@elitedcs/ghl-mcp 3.53.1 → 3.54.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/CHANGELOG.md +44 -17
- package/README.md +4 -4
- package/dist/index.js +1644 -550
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -886,26 +886,26 @@ async function pollCaptureState(budgetMs, intervalMs = 2e3) {
|
|
|
886
886
|
await sleep2(Math.min(intervalMs, Math.max(1, deadline - Date.now())));
|
|
887
887
|
}
|
|
888
888
|
}
|
|
889
|
-
var fs4, path4, import_child_process,
|
|
889
|
+
var fs4, path4, import_child_process, import_zod39, CaptureStateSchema, EXTRACT_FIREBASE_PAGE_FN, HEAL_POISONED_DB_PAGE_FN, EXTRACT_FIREBASE_EXPRESSION, HEAL_POISONED_DB_EXPRESSION, HELPER_LOGIN_TIMEOUT_MS, HEADLESS_PROBE_TIMEOUT_MS, CAPTURED_FRESH_MS, WAITING_FRESH_MS, sleep2;
|
|
890
890
|
var init_interactive_capture = __esm({
|
|
891
891
|
"src/interactive-capture.ts"() {
|
|
892
892
|
"use strict";
|
|
893
893
|
fs4 = __toESM(require("fs"));
|
|
894
894
|
path4 = __toESM(require("path"));
|
|
895
895
|
import_child_process = require("child_process");
|
|
896
|
-
|
|
896
|
+
import_zod39 = require("zod");
|
|
897
897
|
init_credentials_store();
|
|
898
|
-
CaptureStateSchema =
|
|
899
|
-
status:
|
|
900
|
-
startedAt:
|
|
901
|
-
updatedAt:
|
|
898
|
+
CaptureStateSchema = import_zod39.z.object({
|
|
899
|
+
status: import_zod39.z.enum(["waiting_login", "captured", "timeout", "error"]),
|
|
900
|
+
startedAt: import_zod39.z.string(),
|
|
901
|
+
updatedAt: import_zod39.z.string(),
|
|
902
902
|
// Present when status === "captured"
|
|
903
|
-
ghl_firebase_api_key:
|
|
904
|
-
ghl_user_id:
|
|
905
|
-
ghl_firebase_refresh_token:
|
|
906
|
-
account_email:
|
|
903
|
+
ghl_firebase_api_key: import_zod39.z.string().optional(),
|
|
904
|
+
ghl_user_id: import_zod39.z.string().optional(),
|
|
905
|
+
ghl_firebase_refresh_token: import_zod39.z.string().optional(),
|
|
906
|
+
account_email: import_zod39.z.string().optional(),
|
|
907
907
|
// Present when status === "error"
|
|
908
|
-
error:
|
|
908
|
+
error: import_zod39.z.string().optional()
|
|
909
909
|
});
|
|
910
910
|
EXTRACT_FIREBASE_PAGE_FN = `async () => {
|
|
911
911
|
const pick = (rows) => {
|
|
@@ -1010,8 +1010,26 @@ function deviceFingerprint(opts) {
|
|
|
1010
1010
|
return opts.cached;
|
|
1011
1011
|
}
|
|
1012
1012
|
const crypto4 = require("node:crypto");
|
|
1013
|
+
if (!opts) {
|
|
1014
|
+
try {
|
|
1015
|
+
const store = (init_credentials_store(), __toCommonJS(credentials_store_exports));
|
|
1016
|
+
const creds = store.readCredentials();
|
|
1017
|
+
if (creds?.device_id) return creds.device_id;
|
|
1018
|
+
const adopted = creds?.signed_attestation ? parseAttestationPayload(creds.signed_attestation)?.device_fingerprint : void 0;
|
|
1019
|
+
const id = adopted || crypto4.randomBytes(8).toString("hex");
|
|
1020
|
+
if (creds) {
|
|
1021
|
+
try {
|
|
1022
|
+
store.writeCredentials({ ...creds, device_id: id });
|
|
1023
|
+
} catch {
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
return id;
|
|
1027
|
+
} catch {
|
|
1028
|
+
return legacyDeviceFingerprint();
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1013
1031
|
const fresh = crypto4.randomBytes(8).toString("hex");
|
|
1014
|
-
opts
|
|
1032
|
+
opts.persist?.(fresh);
|
|
1015
1033
|
return fresh;
|
|
1016
1034
|
}
|
|
1017
1035
|
function base64urlDecode(s) {
|
|
@@ -1217,21 +1235,21 @@ async function validateFirebase(firebaseKey, refreshToken) {
|
|
|
1217
1235
|
function registerSetupTool(server2) {
|
|
1218
1236
|
server2.tool(
|
|
1219
1237
|
"setup_ghl_mcp",
|
|
1220
|
-
"First-run setup for GHL Command MCP. Validates your license and GHL credentials, then writes them to a per-user credentials file. Restart Claude after this completes to load all
|
|
1238
|
+
"First-run setup for GHL Command MCP. Validates your license and GHL credentials, then writes them to a per-user credentials file. Restart Claude after this completes to load all 234 tools (180 if you skip the optional Firebase fields; add Firebase later with enable_workflow_builder).",
|
|
1221
1239
|
{
|
|
1222
|
-
email:
|
|
1223
|
-
license_key:
|
|
1224
|
-
ghl_api_key:
|
|
1225
|
-
ghl_location_id:
|
|
1226
|
-
ghl_company_id:
|
|
1240
|
+
email: import_zod40.z.string().email().describe("Email used at purchase."),
|
|
1241
|
+
license_key: import_zod40.z.string().min(20).describe("License key from your purchase email."),
|
|
1242
|
+
ghl_api_key: import_zod40.z.string().min(10).describe("GHL Private Integration key (starts with 'pit-'). Created INSIDE the sub-account at Settings > Integrations > Private Integrations."),
|
|
1243
|
+
ghl_location_id: import_zod40.z.string().min(10).describe("GHL Location ID (sub-account ID). Found in your GHL URL: /location/THIS_PART/dashboard."),
|
|
1244
|
+
ghl_company_id: import_zod40.z.string().optional().describe("(Agency only) Company ID for multi-location access."),
|
|
1227
1245
|
// v3.25.0: one-paste shortcut. Run `auto_capture_firebase_script` first;
|
|
1228
1246
|
// it returns a console script that fills the clipboard with this exact
|
|
1229
1247
|
// JSON payload. Pasting it here removes the need to fill ghl_user_id,
|
|
1230
1248
|
// ghl_firebase_api_key, and ghl_firebase_refresh_token individually.
|
|
1231
|
-
firebase_paste:
|
|
1232
|
-
ghl_user_id:
|
|
1233
|
-
ghl_firebase_api_key:
|
|
1234
|
-
ghl_firebase_refresh_token:
|
|
1249
|
+
firebase_paste: import_zod40.z.string().optional().describe("(Workflow Builder, one-paste path) Paste the JSON output from auto_capture_firebase_script here. Replaces the three separate Firebase fields below."),
|
|
1250
|
+
ghl_user_id: import_zod40.z.string().optional().describe("(Workflow Builder, manual path) Firebase User ID. Prefer firebase_paste instead."),
|
|
1251
|
+
ghl_firebase_api_key: import_zod40.z.string().optional().describe("(Workflow Builder, manual path) Firebase API Key starting with 'AIza'. Prefer firebase_paste instead."),
|
|
1252
|
+
ghl_firebase_refresh_token: import_zod40.z.string().optional().describe("(Workflow Builder, manual path) Firebase refresh token. Prefer firebase_paste instead.")
|
|
1235
1253
|
},
|
|
1236
1254
|
async (args) => {
|
|
1237
1255
|
const lic = await validateLicense(args.email, args.license_key);
|
|
@@ -1299,7 +1317,7 @@ Note: Firebase credentials rejected (${fb.error}). Saved without Workflow Builde
|
|
|
1299
1317
|
signed_attestation: lic.signedAttestation
|
|
1300
1318
|
});
|
|
1301
1319
|
const isFree = lic.tier === "free";
|
|
1302
|
-
const toolCount = isFree ? workflowBuilderEnabled ? "106" : "88" : workflowBuilderEnabled ? "
|
|
1320
|
+
const toolCount = isFree ? workflowBuilderEnabled ? "106" : "88" : workflowBuilderEnabled ? "234" : "180";
|
|
1303
1321
|
const wfLine = workflowBuilderEnabled ? "Workflow Builder: enabled." : "Workflow Builder: not configured (optional).";
|
|
1304
1322
|
const wfTip = workflowBuilderEnabled ? "" : isFree ? `
|
|
1305
1323
|
Unlock the account auditor next (the free tier's best tool): say "Unlock the Workflow Builder" \u2014 one browser login enables audit_workflows, validate_workflow, and the full-detail reads.` : "\nTo enable Workflow Builder later (52 extra Firebase-gated tools): run enable_workflow_builder with your three Firebase values. No need to re-enter license/API key/location ID.";
|
|
@@ -1329,16 +1347,16 @@ Unlock the account auditor next (the free tier's best tool): say "Unlock the Wor
|
|
|
1329
1347
|
function registerEnableWorkflowBuilderTool(server2) {
|
|
1330
1348
|
server2.tool(
|
|
1331
1349
|
"enable_workflow_builder",
|
|
1332
|
-
"Add Firebase credentials to an existing GHL Command install to unlock
|
|
1350
|
+
"Add Firebase credentials to an existing GHL Command install to unlock 54 additional tools across the internal-API modules: workflow builder (create/edit/clone/delete/publish/validate workflows, build_if_else_branch, build_goal_event, get_trigger_registry), funnel + page builder, form builder, pipeline builder, workflow cloner, smart lists, reputation, email campaigns, email templates, and memberships, plus the pre-deploy validator. On the FREE tier this same login unlocks the read-only auditor suite (audit_workflows, validate_workflow, full-detail workflow/funnel/pipeline reads). Requires you've already run setup_ghl_mcp. EASIEST PATH: run `capture_firebase_interactive` instead \u2014 a Chrome window opens, you log into GHL, zero pasting. Use THIS tool when you have JSON from `auto_capture_firebase_script` (console-paste path) to put in `firebase_paste`, or the three manual DevTools fields. Tool count goes from 180 to 234 after the next Claude restart.",
|
|
1333
1351
|
{
|
|
1334
1352
|
// v3.25.0: one-paste path. Tool runs `auto_capture_firebase_script` to
|
|
1335
1353
|
// get the console script; the script returns a JSON object that pastes
|
|
1336
1354
|
// cleanly into this field. Saves the buyer from picking out three
|
|
1337
1355
|
// separate fields in IndexedDB.
|
|
1338
|
-
firebase_paste:
|
|
1339
|
-
ghl_user_id:
|
|
1340
|
-
ghl_firebase_api_key:
|
|
1341
|
-
ghl_firebase_refresh_token:
|
|
1356
|
+
firebase_paste: import_zod40.z.string().optional().describe("Paste the JSON output from auto_capture_firebase_script here. Replaces the three separate Firebase fields below."),
|
|
1357
|
+
ghl_user_id: import_zod40.z.string().min(10).optional().describe("(Manual path) Firebase User ID (uid). Prefer firebase_paste."),
|
|
1358
|
+
ghl_firebase_api_key: import_zod40.z.string().min(10).optional().describe("(Manual path) Firebase API Key starting with 'AIza'. Prefer firebase_paste."),
|
|
1359
|
+
ghl_firebase_refresh_token: import_zod40.z.string().min(10).optional().describe("(Manual path) Firebase refresh token. Prefer firebase_paste.")
|
|
1342
1360
|
},
|
|
1343
1361
|
async (args) => {
|
|
1344
1362
|
const existing = readCredentials();
|
|
@@ -1410,7 +1428,7 @@ DevTools steps: https://elitedcs.com/ghl-mcp-firebase`
|
|
|
1410
1428
|
"",
|
|
1411
1429
|
"**You MUST restart Claude before using any workflow-builder tool.** Quit Claude completely (Cmd+Q on Mac, full exit on Windows) and reopen. Without a restart, the workflow builder tools will keep using the OLD Firebase auth from before this call and fail with 401 errors \u2014 even though this tool reported success.",
|
|
1412
1430
|
"",
|
|
1413
|
-
'After restart, all
|
|
1431
|
+
'After restart, all 234 tools load. Try: "List my workflows in full detail" or "Validate workflow <id>".',
|
|
1414
1432
|
"",
|
|
1415
1433
|
"Note: Firebase refresh tokens rotate every few weeks. If workflow tools stop working in a few weeks (run `health_check` to confirm Firebase auth: FAIL), run `auto_capture_firebase_script` for fresh values and re-run this tool with the new firebase_paste."
|
|
1416
1434
|
].join("\n")
|
|
@@ -1506,7 +1524,7 @@ The login in the capture window may belong to the wrong GHL account, or the sess
|
|
|
1506
1524
|
"",
|
|
1507
1525
|
"**You MUST restart Claude before using any workflow-builder tool.** Quit Claude completely (Cmd+Q on Mac, full exit on Windows) and reopen.",
|
|
1508
1526
|
"",
|
|
1509
|
-
'After restart, all
|
|
1527
|
+
'After restart, all 234 tools load. Try: "List my workflows in full detail".',
|
|
1510
1528
|
"",
|
|
1511
1529
|
"Future token rotations re-capture silently \u2014 if workflow tools ever 401, just run capture_firebase_interactive again; no window should appear."
|
|
1512
1530
|
].join("\n")
|
|
@@ -1592,8 +1610,8 @@ function registerLeadCaptureTool(server2) {
|
|
|
1592
1610
|
"request_license",
|
|
1593
1611
|
"Get a GHL Command license. Use this if you installed from npm but don't have a license yet (or setup_ghl_mcp says your license is missing/invalid). GHL Command is $97/mo \u2014 every sub-account you manage, 3-machine activation, includes the only programmatic GHL workflow builder. There's also a FREE read-only tier (account audits + all reads on your own account) \u2014 instant key at https://ghlcommand.com/free. Leave your email and we'll send the purchase link + setup help; the tool also returns where to buy right now.",
|
|
1594
1612
|
{
|
|
1595
|
-
email:
|
|
1596
|
-
name:
|
|
1613
|
+
email: import_zod40.z.string().email().describe("Your email \u2014 where to send the purchase link and setup help."),
|
|
1614
|
+
name: import_zod40.z.string().optional().describe("Your name (optional).")
|
|
1597
1615
|
},
|
|
1598
1616
|
async (args) => {
|
|
1599
1617
|
const buyUrl = "https://ghlcommand.com";
|
|
@@ -1630,13 +1648,13 @@ function registerLeadCaptureTool(server2) {
|
|
|
1630
1648
|
}
|
|
1631
1649
|
);
|
|
1632
1650
|
}
|
|
1633
|
-
var os2, crypto2,
|
|
1651
|
+
var os2, crypto2, import_zod40, LICENSE_API, CAPTURE_API, GHL_API, FIREBASE_TOKEN_API;
|
|
1634
1652
|
var init_setup_tool = __esm({
|
|
1635
1653
|
"src/setup-tool.ts"() {
|
|
1636
1654
|
"use strict";
|
|
1637
1655
|
os2 = __toESM(require("os"));
|
|
1638
1656
|
crypto2 = __toESM(require("crypto"));
|
|
1639
|
-
|
|
1657
|
+
import_zod40 = require("zod");
|
|
1640
1658
|
init_credentials_store();
|
|
1641
1659
|
init_firebase_capture_script();
|
|
1642
1660
|
init_firebase_claims();
|
|
@@ -2084,9 +2102,9 @@ var require_package = __commonJS({
|
|
|
2084
2102
|
"package.json"(exports2, module2) {
|
|
2085
2103
|
module2.exports = {
|
|
2086
2104
|
name: "@elitedcs/ghl-mcp",
|
|
2087
|
-
version: "3.
|
|
2105
|
+
version: "3.54.0",
|
|
2088
2106
|
mcpName: "io.github.drjerryrelth/ghl-command",
|
|
2089
|
-
description: "GoHighLevel MCP Server for Claude.
|
|
2107
|
+
description: "GoHighLevel MCP Server for Claude. 234 tools \u2014 full CRM, automation, marketing control, account-wide workflow audit, live funnel-capture verification, and the only programmatic GHL workflow builder, now multi-tenant across client accounts.",
|
|
2090
2108
|
main: "dist/index.js",
|
|
2091
2109
|
bin: {
|
|
2092
2110
|
"ghl-mcp": "dist/index.js"
|
|
@@ -2293,6 +2311,22 @@ var init_launcher = __esm({
|
|
|
2293
2311
|
});
|
|
2294
2312
|
|
|
2295
2313
|
// src/stage-runner.ts
|
|
2314
|
+
function buildPermission(locationId2, opts = {}) {
|
|
2315
|
+
const protectedName = PROTECTED_LOCATIONS[locationId2];
|
|
2316
|
+
if (protectedName) {
|
|
2317
|
+
return { allowed: false, kind: "protected", reason: `${protectedName} is permanently protected \u2014 builds are refused here, and no approval can override that.` };
|
|
2318
|
+
}
|
|
2319
|
+
const sandbox = SANDBOX_ALLOWLIST[locationId2];
|
|
2320
|
+
if (sandbox) return { allowed: true, kind: "sandbox", reason: `${sandbox} is a sandbox.` };
|
|
2321
|
+
if (opts.approvedAt) {
|
|
2322
|
+
return { allowed: true, kind: "approved", reason: `Approved for building on ${new Date(opts.approvedAt).toLocaleDateString()}.` };
|
|
2323
|
+
}
|
|
2324
|
+
return {
|
|
2325
|
+
allowed: false,
|
|
2326
|
+
kind: "not_approved",
|
|
2327
|
+
reason: `${opts.name || locationId2} is not approved for building yet. Approve it on the card first \u2014 that is the deliberate step that lets automation write into a real client account.`
|
|
2328
|
+
};
|
|
2329
|
+
}
|
|
2296
2330
|
function stageBlockedBy(stages, stage) {
|
|
2297
2331
|
if (!stages) return stage === 0 ? null : 0;
|
|
2298
2332
|
for (let i = 0; i < stage; i++) {
|
|
@@ -2356,12 +2390,9 @@ function parseResultLine(text) {
|
|
|
2356
2390
|
}
|
|
2357
2391
|
}
|
|
2358
2392
|
function runStage(locationId2, stage, onEvent, opts = {}) {
|
|
2359
|
-
const
|
|
2360
|
-
if (!
|
|
2361
|
-
|
|
2362
|
-
`Refused: ${locationId2} is not a sandbox account. Powered stages run ONLY on: ${Object.values(SANDBOX_ALLOWLIST).join(", ")}.`
|
|
2363
|
-
));
|
|
2364
|
-
}
|
|
2393
|
+
const permission = buildPermission(locationId2, { name: opts.name, approvedAt: opts.approvedAt });
|
|
2394
|
+
if (!permission.allowed) return Promise.reject(new Error(`Refused: ${permission.reason}`));
|
|
2395
|
+
const locationName = SANDBOX_ALLOWLIST[locationId2] || opts.name || locationId2;
|
|
2365
2396
|
const spec = STAGE_SPECS[stage];
|
|
2366
2397
|
if (!spec) return Promise.reject(new Error(`Stage ${stage} is not powered yet.`));
|
|
2367
2398
|
return new Promise((resolve5) => {
|
|
@@ -2427,7 +2458,7 @@ function runStage(locationId2, stage, onEvent, opts = {}) {
|
|
|
2427
2458
|
});
|
|
2428
2459
|
});
|
|
2429
2460
|
}
|
|
2430
|
-
var import_child_process2, fs8, os4, path8, SANDBOX_ALLOWLIST, STAGE_SPECS, HUMAN_GATE_STAGES;
|
|
2461
|
+
var import_child_process2, fs8, os4, path8, SANDBOX_ALLOWLIST, PROTECTED_LOCATIONS, STAGE_SPECS, HUMAN_GATE_STAGES;
|
|
2431
2462
|
var init_stage_runner = __esm({
|
|
2432
2463
|
"src/stage-runner.ts"() {
|
|
2433
2464
|
"use strict";
|
|
@@ -2439,6 +2470,9 @@ var init_stage_runner = __esm({
|
|
|
2439
2470
|
JrV2p35O3hY2wqhr2c0T: "MCP Testing",
|
|
2440
2471
|
jHP5wkYRineXDlzAOEbW: "Blueprint Demo"
|
|
2441
2472
|
};
|
|
2473
|
+
PROTECTED_LOCATIONS = {
|
|
2474
|
+
HJfJXQdWwPNxYdjqI1ua: "QA Test Clinic - v3 (live CLL snapshot source)"
|
|
2475
|
+
};
|
|
2442
2476
|
STAGE_SPECS = {
|
|
2443
2477
|
0: {
|
|
2444
2478
|
stage: 0,
|
|
@@ -2448,7 +2482,12 @@ var init_stage_runner = __esm({
|
|
|
2448
2482
|
"mcp__ghl__get_current_location",
|
|
2449
2483
|
"mcp__ghl__get_intake_question_set",
|
|
2450
2484
|
"mcp__ghl__install_intake_form",
|
|
2451
|
-
"mcp__ghl__get_forms"
|
|
2485
|
+
"mcp__ghl__get_forms",
|
|
2486
|
+
"mcp__ghl__get_workflows",
|
|
2487
|
+
"mcp__ghl__create_workflow",
|
|
2488
|
+
"mcp__ghl__update_workflow_actions",
|
|
2489
|
+
"mcp__ghl__publish_workflow",
|
|
2490
|
+
"mcp__ghl__get_users"
|
|
2452
2491
|
],
|
|
2453
2492
|
prompt: (locationId2, locationName, ctx) => `You are running ONE unattended step of a GHL Command Blueprint build. Use ONLY the ghl MCP tools.
|
|
2454
2493
|
` + (ctx?.industry ? `This client is a ${ctx.industry} business \u2014 the intake is tailored to that.
|
|
@@ -2458,8 +2497,11 @@ var init_stage_runner = __esm({
|
|
|
2458
2497
|
2. Call get_current_location and STOP with a line "RESULT: {\\"ok\\":false,\\"error\\":\\"wrong location\\"}" if it is not ${locationId2}.
|
|
2459
2498
|
3. Call get_forms FIRST. If a form named "GHL Command Blueprint \u2014 Client Intake" ALREADY EXISTS, do NOT install another one \u2014 reuse it and report it. Only if none exists, install it with install_intake_form (use get_intake_question_set first if the tool needs the question set).
|
|
2460
2499
|
4. Verify with get_forms that the form now exists.
|
|
2500
|
+
5. Make sure nothing falls through the cracks: check get_workflows for a workflow named "Blueprint Intake \u2014 Submitted". If it does NOT exist, create and publish it:
|
|
2501
|
+
trigger = form_submission on that intake form; actions = internal_notification to the account users (title "Blueprint intake received", body naming the contact and that answers are in), then add_contact_tag ["blueprint-intake-received"], then add_notes with a short HTML note that the intake was submitted.
|
|
2502
|
+
Use get_users to pick a real user id for the notification \u2014 an empty recipient fails publish validation. If the workflow already exists, leave it alone.
|
|
2461
2503
|
Finish with EXACTLY one final line in this format (valid JSON after the colon):
|
|
2462
|
-
RESULT: {"ok":true,"formId":"...","formName":"..."}
|
|
2504
|
+
RESULT: {"ok":true,"formId":"...","formName":"...","summary":"<form + whether the submitted-notification workflow existed or was created>"}
|
|
2463
2505
|
If anything fails, finish with: RESULT: {"ok":false,"error":"<short reason>"}`
|
|
2464
2506
|
},
|
|
2465
2507
|
1: {
|
|
@@ -2685,38 +2727,68 @@ var init_customization = __esm({
|
|
|
2685
2727
|
function publicFormUrl(formId) {
|
|
2686
2728
|
return `https://api.leadconnectorhq.com/widget/form/${formId}`;
|
|
2687
2729
|
}
|
|
2730
|
+
function prefilledFormUrl(formUrl, queryKeys, answers, contact = {}) {
|
|
2731
|
+
const p = new URLSearchParams();
|
|
2732
|
+
if (contact.firstName) p.set("first_name", contact.firstName);
|
|
2733
|
+
if (contact.lastName) p.set("last_name", contact.lastName);
|
|
2734
|
+
if (contact.email) p.set("email", contact.email);
|
|
2735
|
+
if (contact.phone) p.set("phone", contact.phone);
|
|
2736
|
+
for (const [label, value] of Object.entries(answers)) {
|
|
2737
|
+
const key = queryKeys[label];
|
|
2738
|
+
if (key && value && String(value).trim()) p.set(key, String(value));
|
|
2739
|
+
}
|
|
2740
|
+
const qs = p.toString();
|
|
2741
|
+
return qs ? `${formUrl}?${qs}` : formUrl;
|
|
2742
|
+
}
|
|
2688
2743
|
async function readIntakeSnapshot(client, locationId2, sentMarker) {
|
|
2689
|
-
const empty = { status: "not_installed", fields: {}, submissions: 0 };
|
|
2744
|
+
const empty = { status: "not_installed", fields: {}, queryKeys: {}, submissions: 0 };
|
|
2690
2745
|
try {
|
|
2691
2746
|
const forms = await client.get("/forms/", { params: { locationId: locationId2, limit: 100 } });
|
|
2692
2747
|
const form = (forms.forms ?? []).find((f) => f.name === INTAKE_FORM_NAME2);
|
|
2693
2748
|
if (!form) return empty;
|
|
2694
2749
|
const cf = await client.get("/locations/" + locationId2 + "/customFields");
|
|
2695
2750
|
const fields = {};
|
|
2751
|
+
const queryKeys = {};
|
|
2696
2752
|
for (const f of cf.customFields ?? []) {
|
|
2697
|
-
if (f.name?.startsWith(INTAKE_FIELD_NAME_PREFIX))
|
|
2753
|
+
if (!f.name?.startsWith(INTAKE_FIELD_NAME_PREFIX)) continue;
|
|
2754
|
+
const label = f.name.slice(INTAKE_FIELD_NAME_PREFIX.length);
|
|
2755
|
+
fields[label] = f.id;
|
|
2756
|
+
if (f.fieldKey) queryKeys[label] = f.fieldKey.replace(/^contact\./, "");
|
|
2698
2757
|
}
|
|
2699
2758
|
let submissions = 0;
|
|
2700
2759
|
let answeredAt;
|
|
2760
|
+
let channel;
|
|
2761
|
+
let contactId;
|
|
2701
2762
|
try {
|
|
2702
2763
|
const subs = await client.get("/forms/submissions", { params: { locationId: locationId2, formId: form.id, limit: 5 } });
|
|
2703
|
-
|
|
2704
|
-
|
|
2764
|
+
if ((subs.submissions ?? []).length) {
|
|
2765
|
+
submissions = subs.submissions.length;
|
|
2766
|
+
answeredAt = subs.submissions[0]?.createdAt;
|
|
2767
|
+
channel = "form";
|
|
2768
|
+
}
|
|
2705
2769
|
} catch {
|
|
2706
2770
|
}
|
|
2707
2771
|
if (!submissions) {
|
|
2708
2772
|
try {
|
|
2709
|
-
const
|
|
2710
|
-
const
|
|
2773
|
+
const seen = /* @__PURE__ */ new Map();
|
|
2774
|
+
for (const q2 of [INTAKE_CONTACT_TAG, INTAKE_FORM_NAME2]) {
|
|
2775
|
+
const found = await client.get("/contacts/", { params: { locationId: locationId2, query: q2, limit: 20 } });
|
|
2776
|
+
for (const c of found.contacts ?? []) seen.set(c.id, c);
|
|
2777
|
+
}
|
|
2778
|
+
const isFormSubmission = (c) => c.source === INTAKE_FORM_NAME2 || (c.attributions ?? []).some((a) => a.mediumId === form.id || a.medium === "form");
|
|
2779
|
+
const all = [...seen.values()];
|
|
2780
|
+
const hit = all.find(isFormSubmission) ?? all.find((c) => (c.tags ?? []).includes(INTAKE_CONTACT_TAG));
|
|
2711
2781
|
if (hit) {
|
|
2712
2782
|
submissions = 1;
|
|
2713
2783
|
answeredAt = hit.dateUpdated;
|
|
2784
|
+
contactId = hit.id;
|
|
2785
|
+
channel = isFormSubmission(hit) ? "form" : "cockpit";
|
|
2714
2786
|
}
|
|
2715
2787
|
} catch {
|
|
2716
2788
|
}
|
|
2717
2789
|
}
|
|
2718
2790
|
const status = submissions > 0 ? "received" : sentMarker ? "sent" : "installed";
|
|
2719
|
-
return { status, formId: form.id, formUrl: publicFormUrl(form.id), fields, submissions, answeredAt };
|
|
2791
|
+
return { status, formId: form.id, formUrl: publicFormUrl(form.id), fields, queryKeys, submissions, answeredAt, channel, contactId };
|
|
2720
2792
|
} catch {
|
|
2721
2793
|
return empty;
|
|
2722
2794
|
}
|
|
@@ -2923,16 +2995,36 @@ function parseReview(text) {
|
|
|
2923
2995
|
return { ok: false, error: "the review came back malformed", raw: m[1].slice(0, 400) };
|
|
2924
2996
|
}
|
|
2925
2997
|
}
|
|
2998
|
+
function strictRetryPrompt(input) {
|
|
2999
|
+
return [
|
|
3000
|
+
reviewPrompt(input),
|
|
3001
|
+
"",
|
|
3002
|
+
"IMPORTANT: your previous answer did not include the RESULT line and was unusable.",
|
|
3003
|
+
"Output NOTHING except one line beginning with RESULT: followed by the JSON object.",
|
|
3004
|
+
"No preamble, no explanation, no markdown fences, no closing remarks."
|
|
3005
|
+
].join("\n");
|
|
3006
|
+
}
|
|
2926
3007
|
async function generateReview(spawnClaude, input) {
|
|
2927
3008
|
const answered = Object.values(input.answers).filter((v) => v && String(v).trim()).length;
|
|
2928
3009
|
if (answered < 5) {
|
|
2929
3010
|
return { ok: false, error: `Only ${answered} intake answers so far \u2014 complete the intake first, or there is nothing to reason from.` };
|
|
2930
3011
|
}
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
3012
|
+
let lastRaw = "";
|
|
3013
|
+
for (const prompt of [reviewPrompt(input), strictRetryPrompt(input)]) {
|
|
3014
|
+
try {
|
|
3015
|
+
const raw = await spawnClaude(prompt);
|
|
3016
|
+
lastRaw = raw;
|
|
3017
|
+
const parsed = parseReview(raw);
|
|
3018
|
+
if (parsed.ok) return parsed;
|
|
3019
|
+
} catch (e) {
|
|
3020
|
+
lastRaw = e instanceof Error ? e.message : String(e);
|
|
3021
|
+
}
|
|
2935
3022
|
}
|
|
3023
|
+
return {
|
|
3024
|
+
ok: false,
|
|
3025
|
+
error: "The review came back unusable twice. Press Generate again, or open the log if it keeps happening.",
|
|
3026
|
+
raw: lastRaw.slice(-600)
|
|
3027
|
+
};
|
|
2936
3028
|
}
|
|
2937
3029
|
function reviewDocumentHtml(review, opts) {
|
|
2938
3030
|
const accent = opts.accent && /^#[0-9a-fA-F]{6}$/.test(opts.accent) ? opts.accent : "#B8934A";
|
|
@@ -3180,7 +3272,7 @@ async function resolvePlan2(creds) {
|
|
|
3180
3272
|
}
|
|
3181
3273
|
return { error: "Could not verify the license (offline and no valid cached attestation)." };
|
|
3182
3274
|
}
|
|
3183
|
-
function startRun(locationId2, stage, onDone) {
|
|
3275
|
+
function startRun(locationId2, stage, onDone, meta = {}) {
|
|
3184
3276
|
activeRun = { locationId: locationId2, stage, running: true, lines: [] };
|
|
3185
3277
|
const run = activeRun;
|
|
3186
3278
|
const state = readCockpitState();
|
|
@@ -3199,7 +3291,7 @@ function startRun(locationId2, stage, onDone) {
|
|
|
3199
3291
|
runStage(locationId2, stage, (e) => {
|
|
3200
3292
|
run.lines.push(e.line);
|
|
3201
3293
|
if (run.lines.length > 200) run.lines.shift();
|
|
3202
|
-
}, { context }).then((outcome) => {
|
|
3294
|
+
}, { context, name: meta.name, approvedAt: meta.approvedAt }).then((outcome) => {
|
|
3203
3295
|
run.running = false;
|
|
3204
3296
|
run.ok = outcome.ok;
|
|
3205
3297
|
if (outcome.summary || outcome.issues?.length) {
|
|
@@ -3330,7 +3422,7 @@ function html(roster) {
|
|
|
3330
3422
|
<script>
|
|
3331
3423
|
const STAGES=${JSON.stringify(STAGES)};const ROSTER=${JSON.stringify(roster)};
|
|
3332
3424
|
const SANDBOX=${JSON.stringify(Object.keys(SANDBOX_ALLOWLIST))};const POWERED=${JSON.stringify(Object.keys(STAGE_SPECS).map(Number))};
|
|
3333
|
-
const GATES=${JSON.stringify(HUMAN_GATE_STAGES)};
|
|
3425
|
+
const GATES=${JSON.stringify(HUMAN_GATE_STAGES)};const PROTECTED=${JSON.stringify(PROTECTED_LOCATIONS)};
|
|
3334
3426
|
const TYPES=["client","sandbox","template","hidden"];
|
|
3335
3427
|
const NEXT={pending:"in_progress",in_progress:"done",done:"pending"};
|
|
3336
3428
|
let polling=false,query="",showParked=false,showNew=false,snapshots=null;
|
|
@@ -3378,7 +3470,18 @@ function intakePanel(){const d=document.createElement("div");d.className="ncform
|
|
|
3378
3470
|
reset.onclick=()=>{if(confirm("Remove all your customizations and go back to the base question set?"))saveOverlay({})};
|
|
3379
3471
|
d.appendChild(reset);
|
|
3380
3472
|
return d}
|
|
3381
|
-
let iOpen={},iData={},iMode={},iAnswers={},iIdx={},iPre={},iSub={};
|
|
3473
|
+
let iOpen={},iData={},iMode={},iAnswers={},iIdx={},iPre={},iSub={},oOpen={};
|
|
3474
|
+
function outcomePanel(id,i,state){const oc=(state.outcomes||{})[id+":"+i];if(!oc)return null;
|
|
3475
|
+
const d=document.createElement("div");d.className="ipanel";d.style.borderColor="#e0a75e";
|
|
3476
|
+
d.innerHTML="<h3>"+STAGES[i]+" \u2014 what came back</h3>";
|
|
3477
|
+
if(oc.summary){const p=document.createElement("p");p.style.cssText="font-size:.88rem;margin:.3rem 0 .5rem";p.textContent=oc.summary;d.appendChild(p)}
|
|
3478
|
+
for(const iss of (oc.issues||[])){const g=document.createElement("div");g.className="pendpanel";g.style.margin=".3rem 0";
|
|
3479
|
+
g.textContent="\u26A0 "+iss;d.appendChild(g)}
|
|
3480
|
+
const when=document.createElement("p");when.style.cssText="font-size:.72rem;color:#8a90a3;margin:.5rem 0 0";
|
|
3481
|
+
when.textContent="Checked "+new Date(oc.at).toLocaleString();d.appendChild(when);
|
|
3482
|
+
const x=document.createElement("button");x.className="intakebtn";x.style.marginTop=".5rem";x.textContent="Close";
|
|
3483
|
+
x.onclick=()=>{oOpen[id+":"+i]=false;render(lastState,lastRun)};d.appendChild(x);
|
|
3484
|
+
return d}
|
|
3382
3485
|
async function iLoad(id){const r=await(await fetch("/api/client-intake?locationId="+id)).json();iData[id]=r;
|
|
3383
3486
|
if(r.ok&&!iAnswers[id]){iAnswers[id]={}}render(lastState,lastRun)}
|
|
3384
3487
|
function iField(id,q,val,prefilled){const w=document.createElement("div");w.className="ifield"+(prefilled?" prefilled":"");
|
|
@@ -3396,7 +3499,7 @@ function intakeWorkspace(id,name){const d=iData[id];const box=document.createEle
|
|
|
3396
3499
|
if(!d.ok){box.innerHTML="<h3>Intake</h3><p style='font-size:.85rem;color:#b45309'>"+d.error+"</p>";return box}
|
|
3397
3500
|
box.innerHTML="<h3>Intake for "+name+"</h3>";
|
|
3398
3501
|
const sub=document.createElement("p");sub.style.cssText="margin:.1rem 0 .2rem;font-size:.8rem;color:#6b7280";
|
|
3399
|
-
sub.textContent=d.status==="received"?("
|
|
3502
|
+
sub.textContent=d.status==="received"?((d.channel==="form"?"Submitted through the GHL form":"Saved from the cockpit")+(d.answeredAt?" \xB7 "+new Date(d.answeredAt).toLocaleString():"")):d.status==="sent"?"Link sent \u2014 waiting on the client":"Ready to complete";
|
|
3400
3503
|
box.appendChild(sub);
|
|
3401
3504
|
const ch=document.createElement("div");ch.className="ichoice";
|
|
3402
3505
|
const modes=[["fill","Fill it here"],["interview","Interview mode"],["transcript","From a call"],["send","Send to client"],["link","Copy link"]];
|
|
@@ -3473,11 +3576,27 @@ function intakeWorkspace(id,name){const d=iData[id];const box=document.createEle
|
|
|
3473
3576
|
for(const q of qs){if(q.sectionLabel!==lastSec){lastSec=q.sectionLabel;const h=document.createElement("p");
|
|
3474
3577
|
h.style.cssText="margin:.8rem 0 .1rem;font-size:.72rem;letter-spacing:.06em;text-transform:uppercase;color:#8a90a3";h.textContent=lastSec;box.appendChild(h)}
|
|
3475
3578
|
box.appendChild(iField(id,q,ans[q.label],pre.includes(q.label)))}
|
|
3476
|
-
const save=document.createElement("button");save.className="runbtn";save.style.marginTop=".8rem";
|
|
3477
|
-
save.
|
|
3579
|
+
const save=document.createElement("button");save.className="runbtn";save.style.marginTop=".8rem";
|
|
3580
|
+
save.textContent="Review & submit the real form \u2192";
|
|
3581
|
+
save.title="Opens this client's actual GHL form with every answer filled in. One click submits it, so it lands as a genuine form submission.";
|
|
3582
|
+
save.onclick=async()=>{save.disabled=true;save.textContent="Preparing the form\u2026";
|
|
3583
|
+
const r=await(await fetch("/api/intake-prefill-url",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({locationId:id,answers:iAnswers[id]||{},contact:{firstName:(iAnswers[id]||{})["Business Name"]||name}})})).json();
|
|
3584
|
+
save.disabled=false;save.textContent="Review & submit the real form \u2192";
|
|
3585
|
+
if(!r.ok){alert(r.error);return}
|
|
3586
|
+
window.open(r.url,"_blank");
|
|
3587
|
+
const hint=document.createElement("p");hint.style.cssText="font-size:.8rem;color:#6b7280;margin:.5rem 0 0";
|
|
3588
|
+
hint.textContent="The form opened in a new tab with your answers filled in. Click Submit there \u2014 then come back and press Refresh.";
|
|
3589
|
+
box.appendChild(hint);
|
|
3590
|
+
const rf=document.createElement("button");rf.className="intakebtn";rf.style.marginTop=".4rem";rf.textContent="Refresh status";
|
|
3591
|
+
rf.onclick=()=>iLoad(id);box.appendChild(rf)};
|
|
3592
|
+
box.appendChild(save);
|
|
3593
|
+
const alt=document.createElement("button");alt.className="intakebtn";alt.style.cssText="margin-top:.8rem;margin-left:.5rem";
|
|
3594
|
+
alt.textContent="Save without submitting";
|
|
3595
|
+
alt.title="Stores the answers on a tagged contact only \u2014 no form submission.";
|
|
3596
|
+
alt.onclick=async()=>{alt.disabled=true;alt.textContent="Saving\u2026";
|
|
3478
3597
|
const r=await(await fetch("/api/intake-submit",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({locationId:id,answers:iAnswers[id]||{},contact:{firstName:(iAnswers[id]||{})["Business Name"]||name}})})).json();
|
|
3479
|
-
if(r.ok){iMode[id]=null;iPre[id]=[];await iLoad(id)}else{alert(r.error);
|
|
3480
|
-
box.appendChild(
|
|
3598
|
+
if(r.ok){iMode[id]=null;iPre[id]=[];await iLoad(id)}else{alert(r.error);alt.disabled=false;alt.textContent="Save without submitting"}};
|
|
3599
|
+
box.appendChild(alt)}}
|
|
3481
3600
|
return box}
|
|
3482
3601
|
let rOpen={},rData={};
|
|
3483
3602
|
async function rLoad(id){const r=await(await fetch("/api/review?locationId="+id)).json();rData[id]=r;render(lastState,lastRun)}
|
|
@@ -3582,17 +3701,37 @@ function card(c,state,run){const st=(state.clients[c.locationId]||{stages:STAGES
|
|
|
3582
3701
|
if(gate)el.title=gate;
|
|
3583
3702
|
const oc=(state.outcomes||{})[c.locationId+":"+i];
|
|
3584
3703
|
if(oc&&(oc.summary||(oc.issues||[]).length)){const note=document.createElement("small");
|
|
3585
|
-
|
|
3586
|
-
note.
|
|
3587
|
-
note.
|
|
3704
|
+
const nIss=(oc.issues||[]).length;
|
|
3705
|
+
note.style.cssText="display:block;margin-top:.25rem;color:"+(nIss?"#b45309":"#16a34a")+";font-size:.66rem;line-height:1.25;text-decoration:"+(nIss?"underline":"none")+";cursor:"+(nIss?"pointer":"default");
|
|
3706
|
+
note.textContent=nIss?("\u26A0 "+nIss+" issue"+(nIss>1?"s":"")+" \u2014 see details"):(oc.summary||"").slice(0,90);
|
|
3707
|
+
if(nIss)note.onclick=(ev)=>{ev.stopPropagation();oOpen[c.locationId+":"+i]=!oOpen[c.locationId+":"+i];render(lastState,lastRun)};
|
|
3708
|
+
el.appendChild(note)}
|
|
3588
3709
|
el.onclick=async()=>{await fetch("/api/stage",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({locationId:c.locationId,stage:i,status:NEXT[st[i]||"pending"]})});load()};
|
|
3589
|
-
|
|
3710
|
+
const canBuild=sandbox||Boolean((state.buildApproved||{})[c.locationId]);
|
|
3711
|
+
if(canBuild&&POWERED.includes(i)){const b=document.createElement("button");b.className="runbtn";
|
|
3590
3712
|
const busy=run&&run.running;b.textContent=busy&&run.locationId===c.locationId&&run.stage===i?"Running\u2026":"Run \u25B6";
|
|
3591
3713
|
b.disabled=Boolean(busy);
|
|
3592
3714
|
b.onclick=async(ev)=>{ev.stopPropagation();const res=await fetch("/api/run",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({locationId:c.locationId,stage:i})});const j=await res.json();if(!j.ok)alert(j.error);load()};
|
|
3593
3715
|
el.appendChild(document.createElement("br"));el.appendChild(b)}
|
|
3594
3716
|
row.appendChild(el)});
|
|
3595
3717
|
div.appendChild(row);
|
|
3718
|
+
for(let i=0;i<STAGES.length;i++){if(oOpen[c.locationId+":"+i]){const op=outcomePanel(c.locationId,i,state);if(op)div.appendChild(op)}}
|
|
3719
|
+
const _prot=PROTECTED[c.locationId];
|
|
3720
|
+
const _appr=(state.buildApproved||{})[c.locationId];
|
|
3721
|
+
if(!sandbox){const ab=document.createElement("div");ab.style.cssText="margin-top:.55rem;font-size:.78rem";
|
|
3722
|
+
if(_prot){ab.innerHTML='<span class="istatus" style="background:#fdecec;color:#b33">PROTECTED</span> <span style="color:#6b7280">'+_prot+' \u2014 builds refused here.</span>'}
|
|
3723
|
+
else if(_appr){const s1=document.createElement("span");s1.className="istatus received";s1.textContent="APPROVED FOR BUILDING";
|
|
3724
|
+
const rv=document.createElement("button");rv.className="qdel";rv.style.marginLeft=".5rem";rv.textContent="revoke";
|
|
3725
|
+
rv.onclick=async()=>{await fetch("/api/build-approval",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({locationId:c.locationId,revoke:true})});load()};
|
|
3726
|
+
ab.appendChild(s1);ab.appendChild(rv)}
|
|
3727
|
+
else{const w=document.createElement("span");w.style.color="#6b7280";w.textContent="Automated building is off for this client. ";
|
|
3728
|
+
const btn=document.createElement("button");btn.className="intakebtn";btn.style.padding=".25rem .55rem";btn.textContent="Approve building\u2026";
|
|
3729
|
+
btn.onclick=async()=>{const typed=prompt('This lets Command OS write into "'+c.name+'" \u2014 a real client account.'+String.fromCharCode(10,10)+'Type the client name exactly to confirm:');
|
|
3730
|
+
if(typed===null)return;
|
|
3731
|
+
const r=await(await fetch("/api/build-approval",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({locationId:c.locationId,confirmName:typed})})).json();
|
|
3732
|
+
if(!r.ok)alert(r.error);load()};
|
|
3733
|
+
ab.appendChild(w);ab.appendChild(btn)}
|
|
3734
|
+
div.appendChild(ab)}
|
|
3596
3735
|
const _intakeIn=(iData[c.locationId]&&iData[c.locationId].status==="received");
|
|
3597
3736
|
if(_intakeIn||st[1]==="done"||st[2]==="done"||(rData[c.locationId]&&rData[c.locationId].ok)){
|
|
3598
3737
|
const rr=document.createElement("div");rr.style.cssText="margin-top:.5rem";
|
|
@@ -3607,7 +3746,8 @@ function card(c,state,run){const st=(state.clients[c.locationId]||{stages:STAGES
|
|
|
3607
3746
|
ir.appendChild(ib2);
|
|
3608
3747
|
const dd=iData[c.locationId];
|
|
3609
3748
|
if(dd&&dd.ok){const chip=document.createElement("span");chip.className="istatus "+dd.status;
|
|
3610
|
-
chip.textContent=dd.status==="received"?"ANSWERS IN":dd.status==="sent"?"SENT":"NOT STARTED";
|
|
3749
|
+
chip.textContent=dd.status==="received"?("ANSWERS IN"+(dd.channel==="form"?" \xB7 FORM":dd.channel==="cockpit"?" \xB7 SAVED HERE":"")):dd.status==="sent"?"SENT":"NOT STARTED";
|
|
3750
|
+
chip.title=dd.channel==="form"?"A real form submission \u2014 visible in GHL's Submissions and re-readable later.":dd.channel==="cockpit"?"Saved from the cockpit onto a tagged contact (no form submission).":"";ir.appendChild(chip)}
|
|
3611
3751
|
div.appendChild(ir);
|
|
3612
3752
|
if(iOpen[c.locationId])div.appendChild(intakeWorkspace(c.locationId,c.name))}
|
|
3613
3753
|
if(run&&run.locationId===c.locationId&&run.lines&&run.lines.length){const log=document.createElement("div");log.className="runlog";
|
|
@@ -3659,12 +3799,12 @@ async function runDashboard(argv) {
|
|
|
3659
3799
|
`);
|
|
3660
3800
|
return 0;
|
|
3661
3801
|
}
|
|
3662
|
-
const
|
|
3663
|
-
if ("error" in
|
|
3664
|
-
notify(
|
|
3802
|
+
const gate2 = await resolvePlan2(readCredentials());
|
|
3803
|
+
if ("error" in gate2) {
|
|
3804
|
+
notify(gate2.error);
|
|
3665
3805
|
return 3;
|
|
3666
3806
|
}
|
|
3667
|
-
if (
|
|
3807
|
+
if (gate2.plan !== "command-os") {
|
|
3668
3808
|
notify(UPGRADE_MSG.trim());
|
|
3669
3809
|
return 3;
|
|
3670
3810
|
}
|
|
@@ -3757,7 +3897,12 @@ async function runDashboard(argv) {
|
|
|
3757
3897
|
try {
|
|
3758
3898
|
const { locationId: locationId2, stage } = JSON.parse(body);
|
|
3759
3899
|
if (activeRun?.running) throw new Error("a run is already in progress");
|
|
3760
|
-
|
|
3900
|
+
const st0 = readCockpitState();
|
|
3901
|
+
const perm = buildPermission(locationId2, {
|
|
3902
|
+
name: currentRoster().find((r) => r.locationId === locationId2)?.name,
|
|
3903
|
+
approvedAt: st0.buildApproved?.[locationId2]
|
|
3904
|
+
});
|
|
3905
|
+
if (!perm.allowed) throw new Error(perm.reason);
|
|
3761
3906
|
if (!STAGE_SPECS[stage]) {
|
|
3762
3907
|
throw new Error(HUMAN_GATE_STAGES[stage] ? `That stage is a human step: ${HUMAN_GATE_STAGES[stage]}. Click it to mark it done when you have.` : "this stage is not powered yet");
|
|
3763
3908
|
}
|
|
@@ -3767,7 +3912,7 @@ async function runDashboard(argv) {
|
|
|
3767
3912
|
startRun(locationId2, stage, (ok) => {
|
|
3768
3913
|
writeCockpitState(setStage(readCockpitState(), locationId2, stage, ok ? "done" : "pending"));
|
|
3769
3914
|
pushShared(locationId2);
|
|
3770
|
-
});
|
|
3915
|
+
}, { name: currentRoster().find((r) => r.locationId === locationId2)?.name, approvedAt: st0.buildApproved?.[locationId2] });
|
|
3771
3916
|
pushShared(locationId2);
|
|
3772
3917
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
3773
3918
|
res.end(JSON.stringify({ ok: true }));
|
|
@@ -3832,6 +3977,28 @@ async function runDashboard(argv) {
|
|
|
3832
3977
|
})();
|
|
3833
3978
|
return;
|
|
3834
3979
|
}
|
|
3980
|
+
if (req.method === "POST" && url === "/api/intake-prefill-url") {
|
|
3981
|
+
let body = "";
|
|
3982
|
+
req.on("data", (c) => {
|
|
3983
|
+
body += c;
|
|
3984
|
+
if (body.length > 2e5) req.destroy();
|
|
3985
|
+
});
|
|
3986
|
+
req.on("end", async () => {
|
|
3987
|
+
try {
|
|
3988
|
+
const args = JSON.parse(body);
|
|
3989
|
+
const c = clientFor(args.locationId);
|
|
3990
|
+
if (!c) throw new Error("this client isn't connected yet");
|
|
3991
|
+
const snap = await readIntakeSnapshot(c, args.locationId, false);
|
|
3992
|
+
if (!snap.formId || !snap.formUrl) throw new Error("run the Intake stage first \u2014 there's no form yet");
|
|
3993
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
3994
|
+
res.end(JSON.stringify({ ok: true, url: prefilledFormUrl(snap.formUrl, snap.queryKeys, args.answers ?? {}, args.contact ?? {}) }));
|
|
3995
|
+
} catch (e) {
|
|
3996
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
3997
|
+
res.end(JSON.stringify({ ok: false, error: e instanceof Error ? e.message : "failed" }));
|
|
3998
|
+
}
|
|
3999
|
+
});
|
|
4000
|
+
return;
|
|
4001
|
+
}
|
|
3835
4002
|
if (req.method === "POST" && (url === "/api/intake-submit" || url === "/api/intake-send" || url === "/api/intake-prefill")) {
|
|
3836
4003
|
let body = "";
|
|
3837
4004
|
req.on("data", (c) => {
|
|
@@ -3932,6 +4099,37 @@ async function runDashboard(argv) {
|
|
|
3932
4099
|
res.end(JSON.stringify(readCockpitState().reviews?.[locationId2] ?? { ok: false, error: "not generated yet" }));
|
|
3933
4100
|
return;
|
|
3934
4101
|
}
|
|
4102
|
+
if (req.method === "POST" && url === "/api/build-approval") {
|
|
4103
|
+
let body = "";
|
|
4104
|
+
req.on("data", (c) => {
|
|
4105
|
+
body += c;
|
|
4106
|
+
if (body.length > 5e3) req.destroy();
|
|
4107
|
+
});
|
|
4108
|
+
req.on("end", () => {
|
|
4109
|
+
try {
|
|
4110
|
+
const { locationId: locationId2, confirmName, revoke } = JSON.parse(body);
|
|
4111
|
+
const entry = currentRoster().find((r) => r.locationId === locationId2);
|
|
4112
|
+
if (!entry) throw new Error("unknown client");
|
|
4113
|
+
if (PROTECTED_LOCATIONS[locationId2]) throw new Error(PROTECTED_LOCATIONS[locationId2] + " can never be approved for building.");
|
|
4114
|
+
const st = readCockpitState();
|
|
4115
|
+
const approved = { ...st.buildApproved ?? {} };
|
|
4116
|
+
if (revoke) delete approved[locationId2];
|
|
4117
|
+
else {
|
|
4118
|
+
if (String(confirmName || "").trim().toLowerCase() !== entry.name.trim().toLowerCase()) {
|
|
4119
|
+
throw new Error(`Type the client's name exactly ("${entry.name}") to approve automated building.`);
|
|
4120
|
+
}
|
|
4121
|
+
approved[locationId2] = (/* @__PURE__ */ new Date()).toISOString();
|
|
4122
|
+
}
|
|
4123
|
+
writeCockpitState({ ...st, buildApproved: approved });
|
|
4124
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
4125
|
+
res.end(JSON.stringify({ ok: true }));
|
|
4126
|
+
} catch (e) {
|
|
4127
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
4128
|
+
res.end(JSON.stringify({ ok: false, error: e instanceof Error ? e.message : "bad request" }));
|
|
4129
|
+
}
|
|
4130
|
+
});
|
|
4131
|
+
return;
|
|
4132
|
+
}
|
|
3935
4133
|
if (req.method === "POST" && url === "/api/branding") {
|
|
3936
4134
|
let body = "";
|
|
3937
4135
|
req.on("data", (c) => {
|
|
@@ -3970,9 +4168,9 @@ async function runDashboard(argv) {
|
|
|
3970
4168
|
const answers = {};
|
|
3971
4169
|
if (hit) {
|
|
3972
4170
|
const full = await c.get(`/contacts/${hit.id}`);
|
|
3973
|
-
const
|
|
4171
|
+
const byId2 = Object.fromEntries(Object.entries(snap.fields).map(([label, id]) => [id, label]));
|
|
3974
4172
|
for (const f of full.contact?.customFields ?? []) {
|
|
3975
|
-
const label =
|
|
4173
|
+
const label = byId2[f.id];
|
|
3976
4174
|
if (label && f.value != null && String(f.value).trim()) answers[label] = String(f.value);
|
|
3977
4175
|
}
|
|
3978
4176
|
}
|
|
@@ -4758,7 +4956,7 @@ function getStringArray(value) {
|
|
|
4758
4956
|
return value;
|
|
4759
4957
|
}
|
|
4760
4958
|
function validateActionChain(actions, existingIds) {
|
|
4761
|
-
const
|
|
4959
|
+
const byId2 = new Map(actions.filter(hasId).map((action) => [action.id, action]));
|
|
4762
4960
|
for (const action of actions) {
|
|
4763
4961
|
const attr = isRecord(action.attributes) ? action.attributes : void 0;
|
|
4764
4962
|
if (!attr) continue;
|
|
@@ -4812,8 +5010,8 @@ function validateActionChain(actions, existingIds) {
|
|
|
4812
5010
|
const next = getStringArray(action.next);
|
|
4813
5011
|
if (!action.id) throw new Error(`If/else condition node "${action.name}" missing id.`);
|
|
4814
5012
|
if (!next || next.length !== 2) throw new Error(`If/else condition node "${action.name}" must have next as exactly [yesBranchId, noBranchId].`);
|
|
4815
|
-
const yes =
|
|
4816
|
-
const no =
|
|
5013
|
+
const yes = byId2.get(next[0]);
|
|
5014
|
+
const no = byId2.get(next[1]);
|
|
4817
5015
|
if (!yes || yes.nodeType !== "branch-yes") throw new Error(`If/else condition node "${action.name}" next[0] must reference a branch-yes node.`);
|
|
4818
5016
|
if (!no || no.nodeType !== "branch-no") throw new Error(`If/else condition node "${action.name}" next[1] must reference a branch-no node.`);
|
|
4819
5017
|
if (yes.parent !== action.id || yes.parentKey !== action.id) throw new Error(`Branch-yes "${yes.name}" must have parent and parentKey set to condition node "${action.id}".`);
|
|
@@ -4838,7 +5036,7 @@ function validateActionChain(actions, existingIds) {
|
|
|
4838
5036
|
throw new Error(`find_opportunity "${action.name}" must have next as exactly [foundTransitionId, notFoundTransitionId].`);
|
|
4839
5037
|
}
|
|
4840
5038
|
for (const tid of next) {
|
|
4841
|
-
const t =
|
|
5039
|
+
const t = byId2.get(tid);
|
|
4842
5040
|
if (!t || t.type !== "transition") {
|
|
4843
5041
|
throw new Error(`find_opportunity "${action.name}" next must reference its two transition nodes.`);
|
|
4844
5042
|
}
|
|
@@ -4847,7 +5045,7 @@ function validateActionChain(actions, existingIds) {
|
|
|
4847
5045
|
}
|
|
4848
5046
|
const firstChildId = typeof t.next === "string" ? t.next : void 0;
|
|
4849
5047
|
if (firstChildId) {
|
|
4850
|
-
const c =
|
|
5048
|
+
const c = byId2.get(firstChildId);
|
|
4851
5049
|
if (!c || c.parent !== tid || c.parentKey !== tid) {
|
|
4852
5050
|
throw new Error(`First child of transition "${t.name}" must have parent and parentKey set to the transition id.`);
|
|
4853
5051
|
}
|
|
@@ -9718,8 +9916,8 @@ ${text2}`);
|
|
|
9718
9916
|
for (const sec of sections) {
|
|
9719
9917
|
const bg = sec.metaData?.extra?.bgImage?.value;
|
|
9720
9918
|
if (bg && bg.mediaType === "video" && bg.videoUrl) videoBackground = true;
|
|
9721
|
-
const
|
|
9722
|
-
for (const el of
|
|
9919
|
+
const elements2 = Array.isArray(sec.elements) ? sec.elements : [];
|
|
9920
|
+
for (const el of elements2) {
|
|
9723
9921
|
if (el.type !== "element") continue;
|
|
9724
9922
|
const meta = typeof el.meta === "string" ? el.meta : null;
|
|
9725
9923
|
if (!meta) continue;
|
|
@@ -9756,7 +9954,7 @@ ${await response.text()}`);
|
|
|
9756
9954
|
}
|
|
9757
9955
|
server2.tool(
|
|
9758
9956
|
"update_page_content",
|
|
9759
|
-
"Update a funnel/website page's builder content \u2014 sections, elements, settings, pageStyles, trackingCode, popups, popupsList, fontsForPreview. Use get_page_content first to see the current structure, modify it, then pass the full envelope here. Writes via GHL's builder autosave
|
|
9957
|
+
"Update a funnel/website page's builder content \u2014 sections, elements, settings, pageStyles, trackingCode, popups, popupsList, fontsForPreview. Use get_page_content first to see the current structure, modify it, then pass the full envelope here. Writes via GHL's builder autosave and returns the new pageDataUrl. \u26A0\uFE0F RELIABLE ONLY AS THE FIRST SAVE ONTO A PAGE: live testing (2026-07-28) shows GHL accepts later saves but may never make them the visible version. For a page that already has content, verify with get_page_full afterward that pageDataUrl actually changed; if it did not, rebuild on a fresh step (create_funnel_page) instead. Saves as a draft unless isPublished is true.",
|
|
9760
9958
|
{
|
|
9761
9959
|
pageId: import_zod34.z.string().describe("The page ID to update."),
|
|
9762
9960
|
content: import_zod34.z.record(import_zod34.z.unknown()).describe("The full page content JSON \u2014 the 8-field envelope: sections, settings, general, pageStyles, trackingCode, fontsForPreview, popups, popupsList. Start from get_page_content and modify it."),
|
|
@@ -9775,7 +9973,9 @@ ${await response.text()}`);
|
|
|
9775
9973
|
if (!resolvedFunnelId) {
|
|
9776
9974
|
throw new Error(`Could not resolve funnelId for page ${pageId}. Pass funnelId explicitly.`);
|
|
9777
9975
|
}
|
|
9778
|
-
const
|
|
9976
|
+
const livePageVersion = typeof meta.pageVersion === "number" ? meta.pageVersion : typeof meta.version === "number" ? meta.version : 1;
|
|
9977
|
+
const hasExistingContent = typeof meta.pageDataDownloadUrl === "string" && meta.pageDataDownloadUrl.length > 0;
|
|
9978
|
+
const pageVersion = hasExistingContent ? livePageVersion + 1 : livePageVersion;
|
|
9779
9979
|
const pageData = {
|
|
9780
9980
|
...content,
|
|
9781
9981
|
pageVersion,
|
|
@@ -9813,8 +10013,901 @@ ${await response.text()}`);
|
|
|
9813
10013
|
);
|
|
9814
10014
|
}
|
|
9815
10015
|
|
|
9816
|
-
// src/tools/
|
|
10016
|
+
// src/tools/page-studio.ts
|
|
9817
10017
|
var import_zod35 = require("zod");
|
|
10018
|
+
|
|
10019
|
+
// src/page-studio/theme.ts
|
|
10020
|
+
var DONOR_COLOR_SLOTS = [
|
|
10021
|
+
{ hex: "#ec606a", slot: "primary" },
|
|
10022
|
+
{ hex: "#f49ca2", slot: "primarySoft" },
|
|
10023
|
+
{ hex: "#e9c7c1", slot: "primarySoft" },
|
|
10024
|
+
{ hex: "#f3f3f3", slot: "surface" },
|
|
10025
|
+
{ hex: "#434445", slot: "textDark" }
|
|
10026
|
+
];
|
|
10027
|
+
var DONOR_HEADING_FONT = "Oswald";
|
|
10028
|
+
var DONOR_BODY_FONT = "Lato";
|
|
10029
|
+
function escapeRegExp(s) {
|
|
10030
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
10031
|
+
}
|
|
10032
|
+
function replaceHex(text, fromHex, toHex) {
|
|
10033
|
+
const re = new RegExp(escapeRegExp(fromHex), "gi");
|
|
10034
|
+
return text.replace(re, toHex);
|
|
10035
|
+
}
|
|
10036
|
+
function replaceFont(text, fromName, toName) {
|
|
10037
|
+
const fromSlug = fromName.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
10038
|
+
const toSlug = toName.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
10039
|
+
let out = text.replace(new RegExp(`--${escapeRegExp(fromSlug)}\\b`, "g"), `--${toSlug}`);
|
|
10040
|
+
out = out.replace(new RegExp(`(?<![A-Za-z0-9])${escapeRegExp(fromName)}(?![A-Za-z0-9])`, "g"), toName);
|
|
10041
|
+
return out;
|
|
10042
|
+
}
|
|
10043
|
+
function applyTheme(envelope, theme) {
|
|
10044
|
+
for (const font of [theme.headingFont, theme.bodyFont]) {
|
|
10045
|
+
if (font !== void 0 && !/^[A-Za-z0-9 ]{2,40}$/.test(font)) {
|
|
10046
|
+
throw new Error(`Invalid font name ${JSON.stringify(font)} \u2014 use a plain Google Fonts name (letters, digits, spaces).`);
|
|
10047
|
+
}
|
|
10048
|
+
}
|
|
10049
|
+
let text = JSON.stringify(envelope);
|
|
10050
|
+
for (const { hex, slot } of DONOR_COLOR_SLOTS) {
|
|
10051
|
+
const to = theme[slot];
|
|
10052
|
+
if (typeof to === "string" && /^#[0-9a-fA-F]{6}$/.test(to)) {
|
|
10053
|
+
text = replaceHex(text, hex, to);
|
|
10054
|
+
}
|
|
10055
|
+
}
|
|
10056
|
+
if (theme.headingFont && theme.headingFont !== DONOR_HEADING_FONT) {
|
|
10057
|
+
text = replaceFont(text, DONOR_HEADING_FONT, theme.headingFont);
|
|
10058
|
+
}
|
|
10059
|
+
if (theme.bodyFont && theme.bodyFont !== DONOR_BODY_FONT) {
|
|
10060
|
+
text = replaceFont(text, DONOR_BODY_FONT, theme.bodyFont);
|
|
10061
|
+
}
|
|
10062
|
+
return JSON.parse(text);
|
|
10063
|
+
}
|
|
10064
|
+
function themedFonts(theme) {
|
|
10065
|
+
return [
|
|
10066
|
+
`'${theme.bodyFont ?? DONOR_BODY_FONT}'`,
|
|
10067
|
+
`'${theme.headingFont ?? DONOR_HEADING_FONT}'`
|
|
10068
|
+
];
|
|
10069
|
+
}
|
|
10070
|
+
function assertFontMatrixComplete(envelope, theme) {
|
|
10071
|
+
const problems = [];
|
|
10072
|
+
const text = JSON.stringify(envelope);
|
|
10073
|
+
if (theme.headingFont && theme.headingFont !== DONOR_HEADING_FONT && /(?<![A-Za-z0-9])Oswald(?![A-Za-z0-9])/.test(text)) {
|
|
10074
|
+
problems.push("donor heading font 'Oswald' still present after theming");
|
|
10075
|
+
}
|
|
10076
|
+
if (theme.bodyFont && theme.bodyFont !== DONOR_BODY_FONT && /(?<![A-Za-z0-9])Lato(?![A-Za-z0-9])/.test(text)) {
|
|
10077
|
+
problems.push("donor body font 'Lato' still present after theming");
|
|
10078
|
+
}
|
|
10079
|
+
return problems;
|
|
10080
|
+
}
|
|
10081
|
+
|
|
10082
|
+
// src/page-studio/donor-sections.json
|
|
10083
|
+
var donor_sections_default = { extractedAt: "2026-07-28", source: "templates/captured/medspa-reference (Med Spa Template Gc2kgDDpABIR8QDyJ6rf, read-only capture)", sections: { topbar: { id: "section-5koSt0KcJ", metaData: { id: "section-5koSt0KcJ", type: "section", child: ["row-Sj_71z4FVM"], class: { width: { value: "fullSection" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingBottom: { unit: "px", value: "10" }, paddingTop: { unit: "px", value: "10" }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { sticky: { value: "noneSticky" }, visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, allowRowMaxWidth: { value: false } }, wrapper: {}, meta: "section", tagName: "c-section", title: "Top Header", _id: "section-5koSt0KcJ", isGlobal: true }, elements: [{ id: "row-Sj_71z4FVM", type: "row", child: ["col-57vCrX5BdC", "col-ontI0QwDAK", "col-fwzCuhI_RQ"], class: { alignRow: { value: "row-align-center" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: "0" }, paddingBottom: { unit: "px", value: "0" }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, rowWidth: { value: 100, unit: "%" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-row", meta: "row", title: "5 Column Row" }, { id: "col-57vCrX5BdC", type: "col", child: ["paragraph-jL-pjux8a"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: "0" }, paddingRight: { value: "0", unit: "px" }, paddingTop: { unit: "px", value: "10" }, paddingBottom: { unit: "px", value: "10" }, backgroundColor: { value: "var(--transparent)" }, width: { value: 24.4, unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "2nd Column" }, { extra: { nodeId: "cparagraph-jL-pjux8a", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p><strong>{{location.phone}}</strong></p>" }, mobileFontSize: { value: 14, unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--my-custom-color-44)" }, boldTextColor: { value: "var(--my-custom-color-44)" }, italicTextColor: { value: "var(--my-custom-color-44)" }, underlineTextColor: { value: "var(--my-custom-color-44)" }, linkTextColor: { value: "var(--my-custom-color-44)" }, iconColor: { value: "var(--my-custom-color-44)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: "60" }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: "1.5", unit: "em" }, textTransform: { value: "none" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-jL-pjux8a", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p", mobileStyles: { textAlign: { value: "center" }, paddingLeft: { unit: "px", value: 0 } } }, { id: "col-ontI0QwDAK", type: "col", child: ["image-YGGYHGoZw"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 5 }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: 55.2, unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "center" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "3rd Column" }, { extra: { nodeId: "cimage-YGGYHGoZw", visibility: { value: { hideDesktop: false, hideMobile: false } }, imageActions: { value: "url" }, visitWebsite: { value: { url: "", newTab: false } }, imageProperties: { value: { width: null, height: "", url: "https://storage.googleapis.com/msgsndr/EVTjG29VnVlvwn3SRGve/media/fee997f8-92c7-4ee2-b0c1-3536b94b71a7.png", altText: "", compression: true, placeholderBase64: "", servingUrl: "", imageMeta: "" } } }, class: { imageRadius: { value: "img-none" }, imageBorder: { value: "img-border-none" }, imageShadow: { value: "img-shadow-none" }, imageEffects: { value: "img-effects-none" } }, styles: { paddingLeft: { unit: "px", value: 10 }, paddingRight: { value: 10, unit: "px" }, paddingTop: { unit: "px", value: "0" }, paddingBottom: { unit: "px", value: "0" }, backgroundColor: { value: "var(--transparent)" }, opacity: { value: "1" }, textAlign: { value: "center" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "image-YGGYHGoZw", type: "element", child: [], meta: "image", tagName: "c-image", title: "Image", tag: "" }, { id: "col-fwzCuhI_RQ", type: "col", child: ["social-icons-cjYa9pkQuv"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: "0" }, paddingRight: { value: "0", unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: 20.4, unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "5th Column" }, { extra: { nodeId: "csocial-icons-cjYa9pkQuv", socials: { value: [{ id: "facebook", label: "Facebook", link: "facebook.com", newWindow: true, nofollow: false, icon: "https://stcdn.leadconnectorhq.com/funnel/icons/brand/facebook-brand.svg" }, { id: "instagram", label: "Instagram", link: "instagram.com", newWindow: true, nofollow: false, icon: "https://stcdn.leadconnectorhq.com/funnel/icons/brand/instagram-brand.svg" }, { id: "youtube", label: "Youtube", link: "youtube.com", newWindow: true, nofollow: false, icon: "https://stcdn.leadconnectorhq.com/funnel/icons/brand/youtube-brand.svg" }] }, displayType: { value: "icon" }, theme: { value: "dark" }, align: { value: "right" }, iconSize: { value: { height: 20, width: 20 } }, customClass: { value: [] }, visibility: { value: { hideDesktop: false, hideMobile: false } } }, class: {}, styles: { fontFamily: { value: "Inter" }, fontSize: { value: 12, unit: "px" }, fontWeight: { value: 500, desktop: "Normal" }, color: { value: "#000000" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, paddingLeft: { unit: "px", value: 10 }, paddingRight: { value: 10, unit: "px" }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 }, marginLeft: { unit: "px", value: 0 } }, wrapper: {}, mobileStyles: {}, mobileWrapper: {}, mobileExtra: { align: { value: "center" } }, customCss: [], id: "social-icons-cjYa9pkQuv", version: 2, type: "element", child: [], meta: "social-icons", tagName: "c-social-icons", title: "Social Icons", tag: "" }], sequence: 0, pageId: "FYBFsBAezEtsY0uXW4IN", funnelId: "pK3yy9CFapchugRrgjgq", locationId: "Gc2kgDDpABIR8QDyJ6rf", isGlobal: true, general: { colors: [{ label: "Black", value: "#000000" }, { label: "Transparent", value: "transparent" }, { label: "my-custom-color-44", name: "My Custom Color 44", value: "#ec606a" }], fontsForPreview: ["'Lato'"], rootVars: { "--'lato'": "'Lato'", "--black": "#000000", "--transparent": "transparent", "--my-custom-color-44": "#ec606a" }, sectionStyles: ":root{--black:#000000;--transparent:transparent;--my-custom-color-44:#ec606a}.hl_page-preview--content .row-Sj_71z4FVM,.hl_page-preview--content .section-5koSt0KcJ{padding:10px 0;margin-top:0;margin-bottom:0;background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .row-Sj_71z4FVM{padding:0;width:100%}.hl_page-preview--content .col-57vCrX5BdC{width:24.4%}.hl_page-preview--content .col-57vCrX5BdC .inner,.hl_page-preview--content .col-fwzCuhI_RQ .inner,.hl_page-preview--content .col-ontI0QwDAK .inner{padding:10px 0;background-color:var(--transparent);width:24.4%;border-color:var(--black);border-width:2px;border-style:solid;margin-top:0;margin-bottom:0}.hl_page-preview--content .paragraph-jL-pjux8a{margin-top:0;margin-bottom:0}.hl_page-preview--content .cparagraph-jL-pjux8a{font-family:var(--contentfont);background-color:var(--transparent);color:var(--my-custom-color-44);icon-color:var(--my-custom-color-44);font-weight:400;padding:0 0 0 60px;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.5em;text-transform:none;letter-spacing:0;text-align:left}@media screen and (min-width:0px) and (max-width:480px){.hl_page-preview--content .cparagraph-jL-pjux8a{text-align:center;padding-left:0}}.hl_page-preview--content .col-ontI0QwDAK{width:55.2%}.hl_page-preview--content .col-fwzCuhI_RQ .inner,.hl_page-preview--content .col-ontI0QwDAK .inner{padding:10px 5px;width:55.2%}.hl_page-preview--content .image-YGGYHGoZw{margin-top:0;margin-bottom:0}.hl_page-preview--content .cimage-YGGYHGoZw{padding:0 10px;background-color:var(--transparent);opacity:1;text-align:center}.hl_page-preview--content .col-fwzCuhI_RQ{width:20.4%}.hl_page-preview--content .col-fwzCuhI_RQ .inner{padding:10px 0;width:20.4%}.hl_page-preview--content .csocial-icons-cjYa9pkQuv{font-family:Inter;font-size:12px;font-weight:500;color:#000;padding:0 10px;margin:0}#section-5koSt0KcJ>.inner{max-width:1170px}#col-57vCrX5BdC>.inner{flex-direction:column;justify-content:center;align-items:inherit;flex-wrap:nowrap}.paragraph-jL-pjux8a{font-weight:undefined}.paragraph-jL-pjux8a em,.paragraph-jL-pjux8a strong,.paragraph-jL-pjux8a u{color:var(--my-custom-color-44)!important}.paragraph-jL-pjux8a a,.paragraph-jL-pjux8a a *{color:var(--my-custom-color-44)!important;text-decoration:none}.paragraph-jL-pjux8a a:hover{text-decoration:underline}@media screen and (min-width:0px) and (max-width:480px){.paragraph-jL-pjux8a h1,.paragraph-jL-pjux8a h2,.paragraph-jL-pjux8a h3,.paragraph-jL-pjux8a h4,.paragraph-jL-pjux8a h5,.paragraph-jL-pjux8a h6,.paragraph-jL-pjux8a ul li,.paragraph-jL-pjux8a.text-output{font-size:14px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-jL-pjux8a h1,.paragraph-jL-pjux8a h2,.paragraph-jL-pjux8a h3,.paragraph-jL-pjux8a h4,.paragraph-jL-pjux8a h5,.paragraph-jL-pjux8a h6,.paragraph-jL-pjux8a ul li,.paragraph-jL-pjux8a.text-output{font-size:16px!important;font-weight:undefined}}.paragraph-jL-pjux8a.text-output h1:first-child:before,.paragraph-jL-pjux8a.text-output h2:first-child:before,.paragraph-jL-pjux8a.text-output h3:first-child:before,.paragraph-jL-pjux8a.text-output h4:first-child:before,.paragraph-jL-pjux8a.text-output h5:first-child:before,.paragraph-jL-pjux8a.text-output h6:first-child:before,.paragraph-jL-pjux8a.text-output p:first-child:before{color:var(--my-custom-color-44);content:'\\';\n font-family: '';margin-right:5px;font-weight:700}#col-fwzCuhI_RQ>.inner,#col-ontI0QwDAK>.inner{flex-direction:column;justify-content:center;align-items:center;flex-wrap:nowrap}#col-fwzCuhI_RQ>.inner{align-items:inherit}#social-icons-cjYa9pkQuv .social-media-icon{height:20px;width:20px}#social-icons-cjYa9pkQuv .social-icons-container{justify-content:right}@media screen and (min-width:0px) and (max-width:480px){#social-icons-cjYa9pkQuv .social-icons-container{justify-content:center}}" } }, nav: { id: "section-O_4cMXt8V", metaData: { id: "section-O_4cMXt8V", type: "section", child: ["row-g-KFgj-Eth"], class: { width: { value: "fullSection" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingBottom: { unit: "px", value: "5" }, paddingTop: { unit: "px", value: "5" }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: "0" }, backgroundColor: { value: "var(--my-custom-color-44)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { sticky: { value: "noneSticky" }, visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, allowRowMaxWidth: { value: false } }, wrapper: {}, meta: "section", tagName: "c-section", title: "Menu", _id: "section-O_4cMXt8V", isGlobal: true }, elements: [{ id: "row-g-KFgj-Eth", type: "row", child: ["col-u_bfKNLdt"], class: { alignRow: { value: "row-align-center" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: "0" }, paddingBottom: { unit: "px", value: "0" }, backgroundColor: { value: "var(--my-custom-color-44)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, rowWidth: { value: 100, unit: "%" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-row", meta: "row", title: "1 Column Row" }, { id: "col-u_bfKNLdt", type: "col", child: ["nav-menu-GPHNpOf5K"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 5 }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: "0" }, paddingBottom: { unit: "px", value: "0" }, backgroundColor: { value: "var(--transparent)" }, width: { value: "100", unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "1st Column" }, { extra: { nodeId: "cnav-menu-GPHNpOf5K", visibility: { value: { hideDesktop: false, hideMobile: false } }, menuItems: { value: [{ id: "1", title: "Home", goTo: "go-to-funnel-step", url: "#home", goToId: "23f58e5f-0c70-43a8-b701-f4cb62e7a18f", openInNewTab: false, childs: [] }, { id: "2", title: "About", goTo: "go-to-funnel-step", url: "#about", goToId: "2b70293b-67cb-4f49-92bf-19d1513f14fc", openInNewTab: false, childs: [] }, { id: "menu-item-ld0VCcost", title: "Team", goTo: "url", url: "https://app.leadconnectorhq.com/v2/preview/WcJKBDYHBY2lXZHxN2EE#section-X3v76b5TI", goToId: "51741192-a852-4f8e-b136-2e1585f3181c", openInNewTab: false, childs: [] }, { id: "menu-item-muKlH7cA3", title: "Services", goTo: "go-to-funnel-step", url: "#new-menu-item", goToId: "b7c6d34d-f3d8-4ed9-8cf7-a66f5cf734e9", openInNewTab: false, childs: [] }, { id: "menu-item-DSPApGpQ5y", title: "FAQs", goTo: "url", url: "https://app.leadconnectorhq.com/v2/preview/WcJKBDYHBY2lXZHxN2EE#section-zJJ17L55C_", goToId: "", openInNewTab: false, childs: [] }, { id: "3", title: "Contacts", goTo: "url", url: "https://app.leadconnectorhq.com/v2/preview/WcJKBDYHBY2lXZHxN2EE#section-k4A5oCSjW", goToId: "18bcb00f-1151-4ae8-9852-45e1a803439b", openInNewTab: false, childs: [] }] }, mobileFontSize: { value: "18", unit: "px" }, desktopFontSize: { value: "18", unit: "px" }, typography: { value: "var(--headlinefont)" }, icon: { value: { name: "bars", unicode: "f0c9", fontFamily: "Font Awesome 5 Free", color: "var(--black)" } }, text: { value: "<p><strong>Business Name</strong></p>" }, imageProperties: { value: { width: "100px", height: "100px", url: "https://via.placeholder.com/100x100.png?text=Put your image", altText: "Brand Logo" } }, includeLogoInMenu: { value: false }, imageActions: { value: "none" }, visitWebsite: { value: { url: "", newTab: false } }, includeHeadlineInMenu: { value: false }, menuLayout: { value: "reverse" } }, class: { borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, marginTop: { unit: "px", value: 0 }, backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--white)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, iconColor: { value: "var(--white)" }, secondaryColor: { value: "var(--white)" }, navMenuItemHoverBackgroundColor: { value: "var(--)" }, lineHeight: { value: "3.8", unit: "em" }, textTransform: { value: "uppercase" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "center" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, navMenuItemSpacingX: { value: "24", unit: "px" }, navMenuItemSpacingY: { value: "0", unit: "px" }, dropdownBackground: { value: "var(--my-custom-color-44)" }, dropdownTextColor: { value: "var(--white)" }, dropdownHoverColor: { value: "var(--white)" }, dropdownItemSpacing: { value: 10, unit: "px" } }, wrapper: {}, customCss: [], id: "nav-menu-GPHNpOf5K", type: "element", child: [], meta: "nav-menu", tagName: "c-nav-menu", title: "Navigation Menu", tag: "" }], sequence: 1, pageId: "FYBFsBAezEtsY0uXW4IN", funnelId: "pK3yy9CFapchugRrgjgq", locationId: "Gc2kgDDpABIR8QDyJ6rf", isGlobal: true, general: { colors: [{ label: "White", value: "#ffffff" }, { label: "Black", value: "#000000" }, { label: "Transparent", value: "transparent" }, { label: "my-custom-color-44", name: "My Custom Color 44", value: "#ec606a" }, { name: "", value: "#fff6", label: "" }], fontsForPreview: ["'Oswald'"], rootVars: { "--'oswald'": "'Oswald'", "--white": "#ffffff", "--black": "#000000", "--transparent": "transparent", "--my-custom-color-44": "#ec606a", "--": "#fff6" }, sectionStyles: ':root{--white:#ffffff;--black:#000000;--transparent:transparent;--my-custom-color-44:#ec606a;--:#fff6}.hl_page-preview--content .row-g-KFgj-Eth,.hl_page-preview--content .section-O_4cMXt8V{padding:5px 0;margin-top:0;margin-bottom:0;background-color:var(--my-custom-color-44);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .row-g-KFgj-Eth{padding:0;width:100%}.hl_page-preview--content .col-u_bfKNLdt{width:100%}.hl_page-preview--content .cnav-menu-GPHNpOf5K,.hl_page-preview--content .col-u_bfKNLdt .inner{margin-top:0;background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .col-u_bfKNLdt .inner{padding:0 5px;width:100%;margin-bottom:0}.hl_page-preview--content .cnav-menu-GPHNpOf5K{font-family:var(--headlinefont);padding:0;color:var(--white);bold-text-color:var(--text-color);italic-text-color:var(--text-color);underline-text-color:var(--text-color);icon-color:var(--white);secondary-color:var(--white);nav-menu-item-hover-background-color:var(--);line-height:3.8em;text-transform:uppercase;letter-spacing:0;text-align:center;nav-menu-item-spacing-x:24px;nav-menu-item-spacing-y:0;dropdown-background:var(--my-custom-color-44);dropdown-text-color:var(--white);dropdown-hover-color:var(--white);dropdown-item-spacing:10px}#section-O_4cMXt8V>.inner{max-width:1170px}#col-u_bfKNLdt>.inner{flex-direction:column;justify-content:center;align-items:inherit;flex-wrap:nowrap}#nav-menu-GPHNpOf5K .nav-menu,.--mobile #nav-menu-GPHNpOf5K .nav-menu{font-size:18px;font-weight:undefined}#nav-menu-popup.nav-menu-GPHNpOf5K .nav-menu-body{background:var(--transparent)}#nav-menu-GPHNpOf5K .nav-menu li.nav-menu-item{display:flex;align-items:center;white-space:nowrap}#nav-menu-GPHNpOf5K .items-cart,#nav-menu-GPHNpOf5K .items-cart-active{color:undefined}#nav-menu-GPHNpOf5K .nav-menu .nav-menu-item a,#nav-menu-popup.nav-menu-GPHNpOf5K .nav-menu .nav-menu-item a{color:var(--white);cursor:pointer;height:inherit;display:flex;align-items:center;padding:0 24px;transition:all .3s ease}#nav-menu-GPHNpOf5K .nav-menu .nav-menu-item:hover a{color:var(--white);background:var(--)}#nav-menu-GPHNpOf5K .nav-menu .dropdown-menu .dropdown-item:hover a,#nav-menu-popup.nav-menu-GPHNpOf5K .nav-menu .nav-menu-item:hover a,#nav-menu-popup.nav-menu-GPHNpOf5K .nav-menu-body .nav-dropdown-menu .nav-menu-item a,#nav-menu-popup.nav-menu-GPHNpOf5K .nav-menu-body .nav-menu .nav-menu-item:hover{color:var(--white)}.--mobile #nav-menu-GPHNpOf5K .nav-menu .dropdown-menu .dropdown-item{font-size:16px;font-weight:undefined}#nav-menu-popup.nav-menu-GPHNpOf5K .nav-menu{font-size:18px;font-family:var(--headlinefont);font-weight:undefined}#nav-menu-popup.nav-menu-GPHNpOf5K .nav-menu-body .close-menu{color:var(--white);font-size:18px;font-weight:600}#nav-menu-popup.nav-menu-GPHNpOf5K .nav-menu-body .nav-menu .nav-menu-item{color:var(--white);text-align:center;transition:all .3s ease;font-size:16px;font-weight:undefined}#nav-menu-GPHNpOf5K .nav-menu .dropdown-menu .dropdown-item{font-size:16px;text-align:center;font-weight:undefined}#nav-menu-GPHNpOf5K .nav-menu .dropdown-menu .dropdown-item a,#nav-menu-popup.nav-menu-GPHNpOf5K .nav-menu .nav-dropdown-menu .nav-menu-item:hover a{color:var(--white);background:var(--my-custom-color-44);padding:10px;transition:all .3s ease}#nav-menu-popup.nav-menu-GPHNpOf5K .nav-menu-body .nav-dropdown-menu .nav-menu-item{background:var(--my-custom-color-44);font-size:16px;font-weight:undefined}#nav-menu-popup.nav-menu-GPHNpOf5K .nav-menu-body .nav-dropdown-menu .nav-menu-item:hover a{color:var(--white)}#nav-menu-GPHNpOf5K .nav-menu-mobile span::before{cursor:pointer;color:var(--white);content:"\uF0C9";font-family:"Font Awesome 5 Free";font-size:18px;font-weight:600}@media screen and (min-width:0px) and (max-width:480px){.nav-menu-GPHNpOf5K .branding .title{font-size:18px;line-height:3.8em;font-weight:undefined}#nav-menu-GPHNpOf5K .hl-autocomplete-results li{font-size:18px}}@media screen and (min-width:481px) and (max-width:10000px){.nav-menu-GPHNpOf5K .branding .title{font-size:18px;line-height:3.8em;font-weight:undefined}#nav-menu-GPHNpOf5K .hl-autocomplete-results li{font-size:18px}}#nav-menu-GPHNpOf5K strong{font-weight:700}#nav-menu-GPHNpOf5K em,#nav-menu-GPHNpOf5K strong,#nav-menu-GPHNpOf5K u{color:var(--text-color)!important}#nav-menu-GPHNpOf5K .hl-autocomplete-input{border:1px solid #cacaca;margin:1px;border-radius:16px}#nav-menu-GPHNpOf5K .hl-autocomplete{font-family:inherit}#nav-menu-GPHNpOf5K .hl-autocomplete-button{background:#fff}#nav-menu-GPHNpOf5K .hl-autocomplete-input-wrapper{color:#000;background-color:#fff}#nav-menu-GPHNpOf5K .hl-autocomplete-results{border:1px solid #cacaca;border-top:none;border-radius:16px;border-top-left-radius:0;border-top-right-radius:0;color:var(--white);background-color:var(--transparent)}#nav-menu-GPHNpOf5K .hl-autocomplete-input:hover{border-width:1.5px;margin:.5px}#nav-menu-GPHNpOf5K .hl-autocomplete-input:focus-within{border-width:2px;margin:0}' } }, hero: { id: "section-i7rCIMA8O", metaData: { id: "section-i7rCIMA8O", type: "section", child: ["row-FSIe9k0QEZ"], class: { width: { value: "fullSection" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingBottom: { unit: "px", value: "100" }, paddingTop: { unit: "px", value: "100" }, marginTop: { unit: "px", value: "0" }, marginBottom: { unit: "px", value: 0 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { sticky: { value: "noneSticky" }, visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "https://firebasestorage.googleapis.com/v0/b/highlevel-backend.appspot.com/o/location%2Fh0gYqQIqOIBs6xxgZjft%2Fimages%2Fa1a2eeaa-7417-4c54-9f3f-655cc9b9b315.jpeg?alt=media", opacity: "1", options: "full-center", servingUrl: "https://lh3.googleusercontent.com/yk8oCaw8FkORxMxnBR6aWhT05h_QBbZR3_VSWb8Fwnpj5XxjLWRcmQeTEpW9wPK5bwMluRZiAfH63P6xT7L5wPivtvDVMsw", placeholderBase64: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAMCAgMCAQEDAwEEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRQBAwQEBQQFCQUFCRQNCw0UFBQUFBQUFBQUFBQUFBQVFBQUFBQUFBQUEhAPDRUNDRQUFBQUFRUNDRUVFBUVDg4NDf/AABEIAAMACgMBEQACEQEDEQH/xAAVAAEBAAAAAAAAAAAAAAAAAAAIBf/EAB0QAAICAgMBAAAAAAAAAAAAAAECBhEDBAAFBzH/xAAVAQEBAAAAAAAAAAAAAAAAAAAEA//EABwRAAEDBQAAAAAAAAAAAAAAAAEAAhIDESFBkf/aAAwDAQACEQMRAD8Ae/qfTaOr4BPHxR7EjFFWwg+FhfAVGiKfQcZqf1mtr5Y3H3eP6zu2JCzNgQkmhZJrkrA6VpOGAT1f/9k=", imageMeta: { height: 639, width: 1920 } } }, allowRowMaxWidth: { value: false } }, wrapper: {}, meta: "section", tagName: "c-section", title: "Section", _id: "section-i7rCIMA8O" }, elements: [{ id: "row-FSIe9k0QEZ", type: "row", child: ["col-6sfxZPMzf", "col-t4hGSsT54i"], class: { alignRow: { value: "row-align-center" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 15 }, paddingBottom: { unit: "px", value: 15 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, rowWidth: { value: 100, unit: "%" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-row", meta: "row", title: "2 Column Row" }, { id: "col-6sfxZPMzf", type: "col", child: ["heading-BcUsx4fVJi", "paragraph-WVEyivzTc", "button-XgW4LOq8Q"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 5 }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: 67.2, unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "1st Column" }, { extra: { nodeId: "cparagraph-WVEyivzTc", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>Experience luxurious, science-backed skincare and wellness services. From rejuvenating facials to body sculpting, our expert team helps you achieve radiant, youthful skin.</p>" }, mobileFontSize: { value: "16", unit: "px" }, desktopFontSize: { value: "22", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: "20" }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: "1.27", unit: "em" }, textTransform: { value: "none" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: "20" } }, customCss: [], id: "paragraph-WVEyivzTc", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { extra: { nodeId: "cbutton-XgW4LOq8Q", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "make an appointment " }, subText: { value: "" }, mobileFontSize: { value: "16", unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, subTextDesktopFontSize: { value: 15, unit: "px" }, subTextMobileFontSize: { value: 15, unit: "px" }, typography: { value: "var(--headlinefont)" }, iconStart: { value: { name: "", unicode: "", fontFamily: "" } }, iconEnd: { value: { name: "", unicode: "", fontFamily: "" } }, action: { value: "go-to-funnel-step" }, visitWebsite: { value: { url: "#", newTab: false } }, hideElements: { value: [] }, scrollToElement: { value: "" }, phoneNumber: { value: "" }, productId: { value: "" }, stepPath: { value: "0b1c9991-d57a-4c54-9c14-6b846e0c16eb" }, saleAction: { value: "go-to-next-funnel-step" } }, class: { buttonEffects: { value: "none" }, buttonBoxShadow: { value: "btnshadow" }, buttonBgStyle: { value: "custom", text: "Custom", targetConfig: { styles: {} } }, buttonVp: { value: "btn-vp" }, buttonHp: { value: "btn-hp" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--my-custom-color-44)" }, color: { value: "var(--white)" }, secondaryColor: { value: "var(--white)" }, textDecoration: { value: "none" }, paddingTop: { unit: "px", value: "12" }, paddingBottom: { unit: "px", value: "12" }, paddingLeft: { unit: "px", value: "30" }, paddingRight: { value: "30", unit: "px" }, fontWeight: { value: "bold" }, borderColor: { value: "var(--secondary)" }, borderWidth: { value: 3, unit: "px" }, borderStyle: { value: "solid" }, letterSpacing: { value: "0", unit: "px" }, textTransform: { value: "uppercase" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, width: { value: "auto", unit: "%" } }, wrapper: { marginTop: { unit: "px", value: "30" }, marginBottom: { unit: "px", value: 0 }, textAlign: { value: "left" } }, customCss: [], id: "button-XgW4LOq8Q", type: "element", child: [], meta: "button", tagName: "c-button", title: "Button", tag: "" }, { extra: { nodeId: "cheading-BcUsx4fVJi", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<h1>Welcome To {{location.name}}</h1>" }, mobileFontSize: { value: 65, unit: "px" }, desktopFontSize: { value: 65, unit: "px" }, typography: { value: "var(--headlinefont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } }, customClass: { value: [] } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal", desktop: "400" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginLeft: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 } }, customCss: [], mobileStyles: {}, mobileWrapper: {}, id: "heading-BcUsx4fVJi", type: "element", child: [], meta: "heading", tagName: "c-heading", title: "Headline", tag: "h1" }, { id: "col-t4hGSsT54i", type: "col", child: [], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 5 }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: 32.8, unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: true } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "2nd Column" }], sequence: 2, pageId: "FYBFsBAezEtsY0uXW4IN", funnelId: "pK3yy9CFapchugRrgjgq", locationId: "Gc2kgDDpABIR8QDyJ6rf", general: { colors: [{ value: "#188bf6", label: "Secondary" }, { label: "White", value: "#ffffff" }, { label: "Black", value: "#000000" }, { label: "Transparent", value: "transparent" }, { label: "my-custom-color-44", name: "My Custom Color 44", value: "#ec606a" }], fontsForPreview: ["'Lato'", "'Oswald'"], rootVars: { "--'lato'": "'Lato'", "--'oswald'": "'Oswald'", "--secondary": "#188bf6", "--white": "#ffffff", "--black": "#000000", "--transparent": "transparent", "--my-custom-color-44": "#ec606a" }, sectionStyles: ":root{--secondary:#188bf6;--white:#ffffff;--black:#000000;--transparent:transparent;--my-custom-color-44:#ec606a}.hl_page-preview--content .row-FSIe9k0QEZ,.hl_page-preview--content .section-i7rCIMA8O{padding:100px 0;margin-top:0;margin-bottom:0;background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .row-FSIe9k0QEZ{padding:15px 0;width:100%}.hl_page-preview--content .col-6sfxZPMzf{width:67.2%}.hl_page-preview--content .col-6sfxZPMzf .inner{padding:10px 5px;width:67.2%;margin-top:0;margin-bottom:0}.hl_page-preview--content .paragraph-WVEyivzTc{margin-top:0;margin-bottom:20px}.hl_page-preview--content .col-6sfxZPMzf .inner,.hl_page-preview--content .cparagraph-WVEyivzTc{background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .cparagraph-WVEyivzTc{font-family:var(--contentfont);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:20px 0 0;opacity:1;text-shadow:0 0 0 transparent;line-height:1.27em;text-transform:none;letter-spacing:0;text-align:left}.hl_page-preview--content .button-XgW4LOq8Q{margin-top:30px;margin-bottom:0;text-align:left}.hl_page-preview--content .cbutton-XgW4LOq8Q{font-family:var(--headlinefont);background-color:var(--my-custom-color-44);color:var(--white);secondary-color:var(--white);text-decoration:none;padding:12px 30px;font-weight:700;border-color:var(--secondary);border-width:3px;border-style:solid;letter-spacing:0;text-transform:uppercase;text-shadow:0 0 0 transparent;width:auto%}.hl_page-preview--content .heading-BcUsx4fVJi{margin:0}.hl_page-preview--content .cheading-BcUsx4fVJi,.hl_page-preview--content .col-t4hGSsT54i .inner{background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .cheading-BcUsx4fVJi{font-family:var(--headlinefont);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;line-height:1.3em;letter-spacing:0;text-align:left}.hl_page-preview--content .col-t4hGSsT54i{width:32.8%}.hl_page-preview--content .col-t4hGSsT54i .inner{padding:10px 5px;width:32.8%;margin-top:0;margin-bottom:0}#section-i7rCIMA8O>.inner{max-width:1170px}#col-6sfxZPMzf>.inner,#col-t4hGSsT54i>.inner{flex-direction:column;justify-content:center;align-items:inherit;flex-wrap:nowrap}.paragraph-WVEyivzTc{font-weight:undefined}.heading-BcUsx4fVJi em,.heading-BcUsx4fVJi strong,.heading-BcUsx4fVJi u,.paragraph-WVEyivzTc em,.paragraph-WVEyivzTc strong,.paragraph-WVEyivzTc u{color:var(--text-color)!important}.heading-BcUsx4fVJi a,.heading-BcUsx4fVJi a *,.paragraph-WVEyivzTc a,.paragraph-WVEyivzTc a *{color:var(--link-color)!important;text-decoration:none}.heading-BcUsx4fVJi a:hover,.paragraph-WVEyivzTc a:hover{text-decoration:underline}@media screen and (min-width:0px) and (max-width:480px){.paragraph-WVEyivzTc h1,.paragraph-WVEyivzTc h2,.paragraph-WVEyivzTc h3,.paragraph-WVEyivzTc h4,.paragraph-WVEyivzTc h5,.paragraph-WVEyivzTc h6,.paragraph-WVEyivzTc ul li,.paragraph-WVEyivzTc.text-output{font-size:16px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-WVEyivzTc h1,.paragraph-WVEyivzTc h2,.paragraph-WVEyivzTc h3,.paragraph-WVEyivzTc h4,.paragraph-WVEyivzTc h5,.paragraph-WVEyivzTc h6,.paragraph-WVEyivzTc ul li,.paragraph-WVEyivzTc.text-output{font-size:22px!important;font-weight:undefined}}.heading-BcUsx4fVJi.text-output h1:first-child:before,.heading-BcUsx4fVJi.text-output h2:first-child:before,.heading-BcUsx4fVJi.text-output h3:first-child:before,.heading-BcUsx4fVJi.text-output h4:first-child:before,.heading-BcUsx4fVJi.text-output h5:first-child:before,.heading-BcUsx4fVJi.text-output h6:first-child:before,.heading-BcUsx4fVJi.text-output p:first-child:before,.paragraph-WVEyivzTc.text-output h1:first-child:before,.paragraph-WVEyivzTc.text-output h2:first-child:before,.paragraph-WVEyivzTc.text-output h3:first-child:before,.paragraph-WVEyivzTc.text-output h4:first-child:before,.paragraph-WVEyivzTc.text-output h5:first-child:before,.paragraph-WVEyivzTc.text-output h6:first-child:before,.paragraph-WVEyivzTc.text-output p:first-child:before{color:var(--text-color);content:'\\';\n font-family: '';margin-right:5px;font-weight:700}@media screen and (min-width:481px) and (max-width:10000px){.button-XgW4LOq8Q .button-icon-end,.button-XgW4LOq8Q .button-icon-start,.button-XgW4LOq8Q .main-heading-button{font-size:16px;font-weight:undefined}.button-XgW4LOq8Q .button-icon-start{margin-right:5px}.button-XgW4LOq8Q .button-icon-end{margin-left:5px}.button-XgW4LOq8Q .sub-heading-button{font-size:15px;color:var(--white);font-weight:undefined}}@media screen and (min-width:0px) and (max-width:480px){.button-XgW4LOq8Q .button-icon-end,.button-XgW4LOq8Q .button-icon-start,.button-XgW4LOq8Q .main-heading-button{font-size:16px;font-weight:undefined}.button-XgW4LOq8Q .button-icon-start{margin-right:5px}.button-XgW4LOq8Q .button-icon-end{margin-left:5px}.button-XgW4LOq8Q .sub-heading-button{font-size:15px;color:var(--white);font-weight:undefined}}.heading-BcUsx4fVJi{font-weight:400}@media screen and (min-width:0px) and (max-width:480px){.heading-BcUsx4fVJi h1,.heading-BcUsx4fVJi h2,.heading-BcUsx4fVJi h3,.heading-BcUsx4fVJi h4,.heading-BcUsx4fVJi h5,.heading-BcUsx4fVJi h6,.heading-BcUsx4fVJi ul li,.heading-BcUsx4fVJi.text-output{font-size:65px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.heading-BcUsx4fVJi h1,.heading-BcUsx4fVJi h2,.heading-BcUsx4fVJi h3,.heading-BcUsx4fVJi h4,.heading-BcUsx4fVJi h5,.heading-BcUsx4fVJi h6,.heading-BcUsx4fVJi ul li,.heading-BcUsx4fVJi.text-output{font-size:65px!important;font-weight:undefined}}" } }, valueCards: { id: "section-_gNK8lmb6", metaData: { id: "section-_gNK8lmb6", type: "section", child: ["row-aVCgRa8ogS"], class: { width: { value: "fullSection" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingBottom: { unit: "px", value: 20 }, paddingTop: { unit: "px", value: "30" }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { sticky: { value: "noneSticky" }, visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, allowRowMaxWidth: { value: false } }, wrapper: {}, meta: "section", tagName: "c-section", title: "Section", _id: "section-_gNK8lmb6" }, elements: [{ id: "row-aVCgRa8ogS", type: "row", child: ["col--YcAMCaa-", "col-O6hNBWA0L", "col-Ce4EQ7ehv"], class: { alignRow: { value: "row-align-center" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 15 }, paddingBottom: { unit: "px", value: 15 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, rowWidth: { value: 100, unit: "%" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-row", meta: "row", title: "4 Column Row" }, { id: "col--YcAMCaa-", type: "col", child: ["heading-ZvINOOFQi", "divider-y7JRL27_X", "paragraph-1XjOnx_r2", "paragraph-iuePsO6Jd", "paragraph-fBuGHkfQd"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: "10" }, paddingRight: { value: "10", unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: "100", unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "flex-start" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: "0" }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "1st Column" }, { extra: { nodeId: "cheading-ZvINOOFQi", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>OPENING HOURS</p>" }, mobileFontSize: { value: "20", unit: "px" }, desktopFontSize: { value: "20", unit: "px" }, typography: { value: "var(--headlinefont)" }, icon: { value: { name: "calendar-week", unicode: "f784", fontFamily: "Font Awesome 5 Free", color: "var(--black)" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--my-custom-color-44)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--my-custom-color-44)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: "40" }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "none" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "heading-ZvINOOFQi", type: "element", child: [], meta: "heading", tagName: "c-heading", title: "Headline", tag: "h1" }, { extra: { nodeId: "cdivider-y7JRL27_X", visibility: { value: { hideDesktop: false, hideMobile: false } }, dividerProperties: { value: { width: "100%", height: "1px", borderStyle: "solid", align: "center", color: "var(--my-custom-color-71)" } } }, class: {}, styles: { paddingTop: { unit: "px", value: "5" }, paddingBottom: { unit: "px", value: 5 } }, wrapper: { marginTop: { unit: "px", value: "5" }, marginBottom: { unit: "px", value: 0 }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 } }, customCss: [], id: "divider-y7JRL27_X", type: "element", child: [], meta: "divider", tagName: "c-divider", title: "Divider", tag: "" }, { extra: { nodeId: "cparagraph-1XjOnx_r2", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>Mon\u2013Fri</p><p>8:00am\u20137:00pm</p>" }, mobileFontSize: { value: "16", unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: "15" }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-1XjOnx_r2", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { extra: { nodeId: "cparagraph-iuePsO6Jd", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>Saturday</p><p>9:00am\u20134:00pm</p>" }, mobileFontSize: { value: "16", unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: "15" }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-iuePsO6Jd", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { extra: { nodeId: "cparagraph-fBuGHkfQd", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>Sunday</p><p>CLOSED</p>" }, mobileFontSize: { value: "16", unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: "15" }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-fBuGHkfQd", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { id: "col-O6hNBWA0L", type: "col", child: ["heading-h2fK7KiZ6", "divider-J9m382ioKb", "paragraph-y_I-jJh6ya"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: "10" }, paddingRight: { value: "10", unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: "10" }, backgroundColor: { value: "var(--transparent)" }, width: { value: "100", unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "flex-start" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "2nd Column" }, { extra: { nodeId: "cdivider-J9m382ioKb", visibility: { value: { hideDesktop: false, hideMobile: false } }, dividerProperties: { value: { width: "100%", height: "1px", borderStyle: "solid", align: "center", color: "var(--my-custom-color-71)" } } }, class: {}, styles: { paddingTop: { unit: "px", value: 5 }, paddingBottom: { unit: "px", value: 5 } }, wrapper: { marginTop: { unit: "px", value: "5" }, marginBottom: { unit: "px", value: 0 }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 } }, customCss: [], id: "divider-J9m382ioKb", type: "element", child: [], meta: "divider", tagName: "c-divider", title: "Divider", tag: "" }, { extra: { nodeId: "cparagraph-y_I-jJh6ya", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>Booking an appointment at {{location.name}} is easy and convenient. Our expert team is here to provide personalized treatments tailored to your unique needs. Click below to schedule your session and start your journey to a more radiant, confident you.</p>" }, mobileFontSize: { value: "16", unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: "1.5", unit: "em" }, textTransform: { value: "none" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-y_I-jJh6ya", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { extra: { nodeId: "cheading-h2fK7KiZ6", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>APPOINTMENTS</p>" }, mobileFontSize: { value: "20", unit: "px" }, desktopFontSize: { value: "20", unit: "px" }, typography: { value: "var(--headlinefont)" }, icon: { value: { name: "phone-square-alt", unicode: "f87b", fontFamily: "Font Awesome 5 Free", color: "var(--black)" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--my-custom-color-44)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--my-custom-color-44)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: "40" }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "heading-h2fK7KiZ6", type: "element", child: [], meta: "heading", tagName: "c-heading", title: "Headline", tag: "h1" }, { id: "col-Ce4EQ7ehv", type: "col", child: ["heading-FBdJHQ1UZ", "divider-G2u9sBW4y8", "paragraph-nuxIv4A8ad", "paragraph-6KxQcCSVR", "paragraph--m28AM_yp9", "paragraph-pvUi7TFc7r"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: "10" }, paddingRight: { value: "10", unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: "10" }, backgroundColor: { value: "var(--transparent)" }, width: { value: "100", unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "flex-start" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "2nd Column" }, { extra: { nodeId: "cheading-FBdJHQ1UZ", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>LOCATION & CONTACT</p>" }, mobileFontSize: { value: "20", unit: "px" }, desktopFontSize: { value: "20", unit: "px" }, typography: { value: "var(--headlinefont)" }, icon: { value: { name: "map-marker-alt", unicode: "f3c5", fontFamily: "Font Awesome 5 Free", color: "var(--black)" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--my-custom-color-44)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--my-custom-color-44)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: "40" }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "heading-FBdJHQ1UZ", type: "element", child: [], meta: "heading", tagName: "c-heading", title: "Headline", tag: "h1" }, { extra: { nodeId: "cdivider-G2u9sBW4y8", visibility: { value: { hideDesktop: false, hideMobile: false } }, dividerProperties: { value: { width: "100%", height: "1px", borderStyle: "solid", align: "center", color: "var(--my-custom-color-71)" } } }, class: {}, styles: { paddingTop: { unit: "px", value: 5 }, paddingBottom: { unit: "px", value: 5 } }, wrapper: { marginTop: { unit: "px", value: "5" }, marginBottom: { unit: "px", value: 0 }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 } }, customCss: [], id: "divider-G2u9sBW4y8", type: "element", child: [], meta: "divider", tagName: "c-divider", title: "Divider", tag: "" }, { extra: { nodeId: "cparagraph--m28AM_yp9", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p><strong>{{location.phone}}</strong></p>" }, mobileFontSize: { value: "20", unit: "px" }, desktopFontSize: { value: 18, unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--my-custom-color-26)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: "0" }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: "1.5", unit: "em" }, textTransform: { value: "none" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: "2" } }, customCss: [], id: "paragraph--m28AM_yp9", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { extra: { nodeId: "cparagraph-6KxQcCSVR", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>Visit us!</p>" }, mobileFontSize: { value: "16", unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: "1.5", unit: "em" }, textTransform: { value: "none" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 10 } }, customCss: [], id: "paragraph-6KxQcCSVR", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { extra: { nodeId: "cparagraph-nuxIv4A8ad", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p><strong>{{location.full_address}}</strong></p>" }, mobileFontSize: { value: "20", unit: "px" }, desktopFontSize: { value: 18, unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--my-custom-color-26)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: "0" }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: "1.5", unit: "em" }, textTransform: { value: "none" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: "2" } }, customCss: [], id: "paragraph-nuxIv4A8ad", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { extra: { nodeId: "cparagraph-pvUi7TFc7r", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>Call us!</p>" }, mobileFontSize: { value: "16", unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: "1.5", unit: "em" }, textTransform: { value: "none" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 10 } }, customCss: [], id: "paragraph-pvUi7TFc7r", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }], sequence: 3, pageId: "FYBFsBAezEtsY0uXW4IN", funnelId: "pK3yy9CFapchugRrgjgq", locationId: "Gc2kgDDpABIR8QDyJ6rf", general: { colors: [{ label: "Black", value: "#000000" }, { label: "Transparent", value: "transparent" }, { label: "my-custom-color-26", value: "#434445", name: "My Custom Color 26" }, { label: "my-custom-color-44", name: "My Custom Color 44", value: "#ec606a" }], fontsForPreview: ["'Oswald'", "'Lato'"], rootVars: { "--'oswald'": "'Oswald'", "--'lato'": "'Lato'", "--black": "#000000", "--transparent": "transparent", "--my-custom-color-26": "#434445", "--my-custom-color-44": "#ec606a" }, sectionStyles: `:root{--black:#000000;--transparent:transparent;--my-custom-color-26:#434445;--my-custom-color-44:#ec606a}.hl_page-preview--content .row-aVCgRa8ogS,.hl_page-preview--content .section-_gNK8lmb6{padding:30px 0 20px;margin-top:0;margin-bottom:0;background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .row-aVCgRa8ogS{padding:15px 0;width:100%}.hl_page-preview--content .col--YcAMCaa-{width:100%}.hl_page-preview--content .col--YcAMCaa- .inner,.hl_page-preview--content .col-Ce4EQ7ehv .inner,.hl_page-preview--content .col-O6hNBWA0L .inner{padding:10px;background-color:var(--transparent);width:100%;border-color:var(--black);border-width:2px;border-style:solid;margin-top:0;margin-bottom:0}.hl_page-preview--content .heading-ZvINOOFQi{margin-top:0;margin-bottom:0}.hl_page-preview--content .cheading-ZvINOOFQi{font-family:var(--headlinefont);background-color:var(--transparent);color:var(--my-custom-color-44);icon-color:var(--my-custom-color-44);font-weight:400;padding:0 0 0 40px;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;text-transform:none;letter-spacing:0;text-align:left}.hl_page-preview--content .divider-y7JRL27_X{margin-top:5px;margin-bottom:0;padding-top:10px;padding-bottom:10px}.hl_page-preview--content .cdivider-y7JRL27_X{padding-top:5px;padding-bottom:5px}.hl_page-preview--content .paragraph-1XjOnx_r2{margin-top:0;margin-bottom:0}.hl_page-preview--content .cparagraph-1XjOnx_r2{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0 0 15px;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}.hl_page-preview--content .paragraph-iuePsO6Jd{margin-top:0;margin-bottom:0}.hl_page-preview--content .cparagraph-iuePsO6Jd{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0 0 15px;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}.hl_page-preview--content .paragraph-fBuGHkfQd{margin-top:0;margin-bottom:0}.hl_page-preview--content .cparagraph-fBuGHkfQd{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0 0 15px;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}.hl_page-preview--content .col-O6hNBWA0L{width:100%}.hl_page-preview--content .divider-J9m382ioKb{margin-top:5px;margin-bottom:0;padding-top:10px;padding-bottom:10px}.hl_page-preview--content .cdivider-J9m382ioKb{padding-top:5px;padding-bottom:5px}.hl_page-preview--content .paragraph-y_I-jJh6ya{margin-top:0;margin-bottom:0}.hl_page-preview--content .cparagraph-y_I-jJh6ya{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.5em;text-transform:none;letter-spacing:0;text-align:left}.hl_page-preview--content .heading-h2fK7KiZ6{margin-top:0;margin-bottom:0}.hl_page-preview--content .cheading-h2fK7KiZ6{font-family:var(--headlinefont);background-color:var(--transparent);color:var(--my-custom-color-44);icon-color:var(--my-custom-color-44);font-weight:400;padding:0 0 0 40px;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}.hl_page-preview--content .col-Ce4EQ7ehv{width:100%}.hl_page-preview--content .heading-FBdJHQ1UZ{margin-top:0;margin-bottom:0}.hl_page-preview--content .cheading-FBdJHQ1UZ{font-family:var(--headlinefont);background-color:var(--transparent);color:var(--my-custom-color-44);icon-color:var(--my-custom-color-44);font-weight:400;padding:0 0 0 40px;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}.hl_page-preview--content .divider-G2u9sBW4y8{margin-top:5px;margin-bottom:0;padding-top:10px;padding-bottom:10px}.hl_page-preview--content .cdivider-G2u9sBW4y8{padding-top:5px;padding-bottom:5px}.hl_page-preview--content .paragraph--m28AM_yp9{margin-top:0;margin-bottom:2px}.hl_page-preview--content .cparagraph--m28AM_yp9{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.5em;text-transform:none;letter-spacing:0;text-align:left}.hl_page-preview--content .paragraph-6KxQcCSVR{margin-top:0;margin-bottom:10px}.hl_page-preview--content .cparagraph-6KxQcCSVR{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.5em;text-transform:none;letter-spacing:0;text-align:left}.hl_page-preview--content .paragraph-nuxIv4A8ad{margin-top:0;margin-bottom:2px}.hl_page-preview--content .cparagraph-nuxIv4A8ad{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.5em;text-transform:none;letter-spacing:0;text-align:left}.hl_page-preview--content .paragraph-pvUi7TFc7r{margin-top:0;margin-bottom:10px}.hl_page-preview--content .cparagraph-pvUi7TFc7r{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.5em;text-transform:none;letter-spacing:0;text-align:left}#section-_gNK8lmb6>.inner{max-width:1170px}#col--YcAMCaa->.inner,#col-Ce4EQ7ehv>.inner,#col-O6hNBWA0L>.inner{flex-direction:column;justify-content:flex-start;align-items:inherit;flex-wrap:nowrap}.heading-FBdJHQ1UZ,.heading-ZvINOOFQi,.heading-h2fK7KiZ6,.paragraph--m28AM_yp9,.paragraph-1XjOnx_r2,.paragraph-6KxQcCSVR,.paragraph-fBuGHkfQd,.paragraph-iuePsO6Jd,.paragraph-nuxIv4A8ad,.paragraph-pvUi7TFc7r,.paragraph-y_I-jJh6ya{font-weight:undefined}.heading-FBdJHQ1UZ em,.heading-FBdJHQ1UZ strong,.heading-FBdJHQ1UZ u,.heading-ZvINOOFQi em,.heading-ZvINOOFQi strong,.heading-ZvINOOFQi u,.heading-h2fK7KiZ6 em,.heading-h2fK7KiZ6 strong,.heading-h2fK7KiZ6 u,.paragraph--m28AM_yp9 em,.paragraph--m28AM_yp9 strong,.paragraph--m28AM_yp9 u,.paragraph-1XjOnx_r2 em,.paragraph-1XjOnx_r2 strong,.paragraph-1XjOnx_r2 u,.paragraph-6KxQcCSVR em,.paragraph-6KxQcCSVR strong,.paragraph-6KxQcCSVR u,.paragraph-fBuGHkfQd em,.paragraph-fBuGHkfQd strong,.paragraph-fBuGHkfQd u,.paragraph-iuePsO6Jd em,.paragraph-iuePsO6Jd strong,.paragraph-iuePsO6Jd u,.paragraph-nuxIv4A8ad em,.paragraph-nuxIv4A8ad strong,.paragraph-nuxIv4A8ad u,.paragraph-pvUi7TFc7r em,.paragraph-pvUi7TFc7r strong,.paragraph-pvUi7TFc7r u,.paragraph-y_I-jJh6ya em,.paragraph-y_I-jJh6ya strong,.paragraph-y_I-jJh6ya u{color:var(--text-color)!important}.heading-FBdJHQ1UZ a,.heading-FBdJHQ1UZ a *,.heading-ZvINOOFQi a,.heading-ZvINOOFQi a *,.heading-h2fK7KiZ6 a,.heading-h2fK7KiZ6 a *,.paragraph-1XjOnx_r2 a,.paragraph-1XjOnx_r2 a *,.paragraph-fBuGHkfQd a,.paragraph-fBuGHkfQd a *,.paragraph-iuePsO6Jd a,.paragraph-iuePsO6Jd a *,.paragraph-y_I-jJh6ya a,.paragraph-y_I-jJh6ya a *{color:var(--link-color)!important;text-decoration:none}.heading-FBdJHQ1UZ a:hover,.heading-ZvINOOFQi a:hover,.heading-h2fK7KiZ6 a:hover,.paragraph--m28AM_yp9 a:hover,.paragraph-1XjOnx_r2 a:hover,.paragraph-6KxQcCSVR a:hover,.paragraph-fBuGHkfQd a:hover,.paragraph-iuePsO6Jd a:hover,.paragraph-nuxIv4A8ad a:hover,.paragraph-pvUi7TFc7r a:hover,.paragraph-y_I-jJh6ya a:hover{text-decoration:underline}@media screen and (min-width:0px) and (max-width:480px){.heading-ZvINOOFQi h1,.heading-ZvINOOFQi h2,.heading-ZvINOOFQi h3,.heading-ZvINOOFQi h4,.heading-ZvINOOFQi h5,.heading-ZvINOOFQi h6,.heading-ZvINOOFQi ul li,.heading-ZvINOOFQi.text-output{font-size:20px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.heading-ZvINOOFQi h1,.heading-ZvINOOFQi h2,.heading-ZvINOOFQi h3,.heading-ZvINOOFQi h4,.heading-ZvINOOFQi h5,.heading-ZvINOOFQi h6,.heading-ZvINOOFQi ul li,.heading-ZvINOOFQi.text-output{font-size:20px!important;font-weight:undefined}}.heading-ZvINOOFQi.text-output h1:first-child:before,.heading-ZvINOOFQi.text-output h2:first-child:before,.heading-ZvINOOFQi.text-output h3:first-child:before,.heading-ZvINOOFQi.text-output h4:first-child:before,.heading-ZvINOOFQi.text-output h5:first-child:before,.heading-ZvINOOFQi.text-output h6:first-child:before,.heading-ZvINOOFQi.text-output p:first-child:before{color:var(--my-custom-color-44);content:"\uF784";font-family:"Font Awesome 5 Free";margin-right:5px;font-weight:700}.divider-y7JRL27_X .divider-element{width:100%;border-top:1px solid var(--my-custom-color-71);margin:0 auto}@media screen and (min-width:0px) and (max-width:480px){.paragraph-1XjOnx_r2 h1,.paragraph-1XjOnx_r2 h2,.paragraph-1XjOnx_r2 h3,.paragraph-1XjOnx_r2 h4,.paragraph-1XjOnx_r2 h5,.paragraph-1XjOnx_r2 h6,.paragraph-1XjOnx_r2 ul li,.paragraph-1XjOnx_r2.text-output{font-size:16px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-1XjOnx_r2 h1,.paragraph-1XjOnx_r2 h2,.paragraph-1XjOnx_r2 h3,.paragraph-1XjOnx_r2 h4,.paragraph-1XjOnx_r2 h5,.paragraph-1XjOnx_r2 h6,.paragraph-1XjOnx_r2 ul li,.paragraph-1XjOnx_r2.text-output{font-size:16px!important;font-weight:undefined}}.paragraph-1XjOnx_r2.text-output h1:first-child:before,.paragraph-1XjOnx_r2.text-output h2:first-child:before,.paragraph-1XjOnx_r2.text-output h3:first-child:before,.paragraph-1XjOnx_r2.text-output h4:first-child:before,.paragraph-1XjOnx_r2.text-output h5:first-child:before,.paragraph-1XjOnx_r2.text-output h6:first-child:before,.paragraph-1XjOnx_r2.text-output p:first-child:before,.paragraph-fBuGHkfQd.text-output h1:first-child:before,.paragraph-fBuGHkfQd.text-output h2:first-child:before,.paragraph-fBuGHkfQd.text-output h3:first-child:before,.paragraph-fBuGHkfQd.text-output h4:first-child:before,.paragraph-fBuGHkfQd.text-output h5:first-child:before,.paragraph-fBuGHkfQd.text-output h6:first-child:before,.paragraph-fBuGHkfQd.text-output p:first-child:before,.paragraph-iuePsO6Jd.text-output h1:first-child:before,.paragraph-iuePsO6Jd.text-output h2:first-child:before,.paragraph-iuePsO6Jd.text-output h3:first-child:before,.paragraph-iuePsO6Jd.text-output h4:first-child:before,.paragraph-iuePsO6Jd.text-output h5:first-child:before,.paragraph-iuePsO6Jd.text-output h6:first-child:before,.paragraph-iuePsO6Jd.text-output p:first-child:before,.paragraph-y_I-jJh6ya.text-output h1:first-child:before,.paragraph-y_I-jJh6ya.text-output h2:first-child:before,.paragraph-y_I-jJh6ya.text-output h3:first-child:before,.paragraph-y_I-jJh6ya.text-output h4:first-child:before,.paragraph-y_I-jJh6ya.text-output h5:first-child:before,.paragraph-y_I-jJh6ya.text-output h6:first-child:before,.paragraph-y_I-jJh6ya.text-output p:first-child:before{color:var(--text-color);content:'\\';
|
|
10084
|
+
font-family: '';margin-right:5px;font-weight:700}@media screen and (min-width:0px) and (max-width:480px){.paragraph-iuePsO6Jd h1,.paragraph-iuePsO6Jd h2,.paragraph-iuePsO6Jd h3,.paragraph-iuePsO6Jd h4,.paragraph-iuePsO6Jd h5,.paragraph-iuePsO6Jd h6,.paragraph-iuePsO6Jd ul li,.paragraph-iuePsO6Jd.text-output{font-size:16px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-iuePsO6Jd h1,.paragraph-iuePsO6Jd h2,.paragraph-iuePsO6Jd h3,.paragraph-iuePsO6Jd h4,.paragraph-iuePsO6Jd h5,.paragraph-iuePsO6Jd h6,.paragraph-iuePsO6Jd ul li,.paragraph-iuePsO6Jd.text-output{font-size:16px!important;font-weight:undefined}}@media screen and (min-width:0px) and (max-width:480px){.paragraph-fBuGHkfQd h1,.paragraph-fBuGHkfQd h2,.paragraph-fBuGHkfQd h3,.paragraph-fBuGHkfQd h4,.paragraph-fBuGHkfQd h5,.paragraph-fBuGHkfQd h6,.paragraph-fBuGHkfQd ul li,.paragraph-fBuGHkfQd.text-output{font-size:16px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-fBuGHkfQd h1,.paragraph-fBuGHkfQd h2,.paragraph-fBuGHkfQd h3,.paragraph-fBuGHkfQd h4,.paragraph-fBuGHkfQd h5,.paragraph-fBuGHkfQd h6,.paragraph-fBuGHkfQd ul li,.paragraph-fBuGHkfQd.text-output{font-size:16px!important;font-weight:undefined}}.divider-J9m382ioKb .divider-element{width:100%;border-top:1px solid var(--my-custom-color-71);margin:0 auto}@media screen and (min-width:0px) and (max-width:480px){.paragraph-y_I-jJh6ya h1,.paragraph-y_I-jJh6ya h2,.paragraph-y_I-jJh6ya h3,.paragraph-y_I-jJh6ya h4,.paragraph-y_I-jJh6ya h5,.paragraph-y_I-jJh6ya h6,.paragraph-y_I-jJh6ya ul li,.paragraph-y_I-jJh6ya.text-output{font-size:16px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-y_I-jJh6ya h1,.paragraph-y_I-jJh6ya h2,.paragraph-y_I-jJh6ya h3,.paragraph-y_I-jJh6ya h4,.paragraph-y_I-jJh6ya h5,.paragraph-y_I-jJh6ya h6,.paragraph-y_I-jJh6ya ul li,.paragraph-y_I-jJh6ya.text-output{font-size:16px!important;font-weight:undefined}}@media screen and (min-width:0px) and (max-width:480px){.heading-h2fK7KiZ6 h1,.heading-h2fK7KiZ6 h2,.heading-h2fK7KiZ6 h3,.heading-h2fK7KiZ6 h4,.heading-h2fK7KiZ6 h5,.heading-h2fK7KiZ6 h6,.heading-h2fK7KiZ6 ul li,.heading-h2fK7KiZ6.text-output{font-size:20px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.heading-h2fK7KiZ6 h1,.heading-h2fK7KiZ6 h2,.heading-h2fK7KiZ6 h3,.heading-h2fK7KiZ6 h4,.heading-h2fK7KiZ6 h5,.heading-h2fK7KiZ6 h6,.heading-h2fK7KiZ6 ul li,.heading-h2fK7KiZ6.text-output{font-size:20px!important;font-weight:undefined}}.heading-h2fK7KiZ6.text-output h1:first-child:before,.heading-h2fK7KiZ6.text-output h2:first-child:before,.heading-h2fK7KiZ6.text-output h3:first-child:before,.heading-h2fK7KiZ6.text-output h4:first-child:before,.heading-h2fK7KiZ6.text-output h5:first-child:before,.heading-h2fK7KiZ6.text-output h6:first-child:before,.heading-h2fK7KiZ6.text-output p:first-child:before{color:var(--my-custom-color-44);content:"\uF87B";font-family:"Font Awesome 5 Free";margin-right:5px;font-weight:700}@media screen and (min-width:0px) and (max-width:480px){.heading-FBdJHQ1UZ h1,.heading-FBdJHQ1UZ h2,.heading-FBdJHQ1UZ h3,.heading-FBdJHQ1UZ h4,.heading-FBdJHQ1UZ h5,.heading-FBdJHQ1UZ h6,.heading-FBdJHQ1UZ ul li,.heading-FBdJHQ1UZ.text-output{font-size:20px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.heading-FBdJHQ1UZ h1,.heading-FBdJHQ1UZ h2,.heading-FBdJHQ1UZ h3,.heading-FBdJHQ1UZ h4,.heading-FBdJHQ1UZ h5,.heading-FBdJHQ1UZ h6,.heading-FBdJHQ1UZ ul li,.heading-FBdJHQ1UZ.text-output{font-size:20px!important;font-weight:undefined}}.heading-FBdJHQ1UZ.text-output h1:first-child:before,.heading-FBdJHQ1UZ.text-output h2:first-child:before,.heading-FBdJHQ1UZ.text-output h3:first-child:before,.heading-FBdJHQ1UZ.text-output h4:first-child:before,.heading-FBdJHQ1UZ.text-output h5:first-child:before,.heading-FBdJHQ1UZ.text-output h6:first-child:before,.heading-FBdJHQ1UZ.text-output p:first-child:before{color:var(--my-custom-color-44);content:"\uF3C5";font-family:"Font Awesome 5 Free";margin-right:5px;font-weight:700}.divider-G2u9sBW4y8 .divider-element{width:100%;border-top:1px solid var(--my-custom-color-71);margin:0 auto}.paragraph--m28AM_yp9 a,.paragraph--m28AM_yp9 a *{color:var(--my-custom-color-26)!important;text-decoration:none}@media screen and (min-width:0px) and (max-width:480px){.paragraph--m28AM_yp9 h1,.paragraph--m28AM_yp9 h2,.paragraph--m28AM_yp9 h3,.paragraph--m28AM_yp9 h4,.paragraph--m28AM_yp9 h5,.paragraph--m28AM_yp9 h6,.paragraph--m28AM_yp9 ul li,.paragraph--m28AM_yp9.text-output{font-size:20px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph--m28AM_yp9 h1,.paragraph--m28AM_yp9 h2,.paragraph--m28AM_yp9 h3,.paragraph--m28AM_yp9 h4,.paragraph--m28AM_yp9 h5,.paragraph--m28AM_yp9 h6,.paragraph--m28AM_yp9 ul li,.paragraph--m28AM_yp9.text-output{font-size:18px!important;font-weight:undefined}}.paragraph--m28AM_yp9.text-output h1:first-child:before,.paragraph--m28AM_yp9.text-output h2:first-child:before,.paragraph--m28AM_yp9.text-output h3:first-child:before,.paragraph--m28AM_yp9.text-output h4:first-child:before,.paragraph--m28AM_yp9.text-output h5:first-child:before,.paragraph--m28AM_yp9.text-output h6:first-child:before,.paragraph--m28AM_yp9.text-output p:first-child:before,.paragraph-6KxQcCSVR.text-output h1:first-child:before,.paragraph-6KxQcCSVR.text-output h2:first-child:before,.paragraph-6KxQcCSVR.text-output h3:first-child:before,.paragraph-6KxQcCSVR.text-output h4:first-child:before,.paragraph-6KxQcCSVR.text-output h5:first-child:before,.paragraph-6KxQcCSVR.text-output h6:first-child:before,.paragraph-6KxQcCSVR.text-output p:first-child:before,.paragraph-nuxIv4A8ad.text-output h1:first-child:before,.paragraph-nuxIv4A8ad.text-output h2:first-child:before,.paragraph-nuxIv4A8ad.text-output h3:first-child:before,.paragraph-nuxIv4A8ad.text-output h4:first-child:before,.paragraph-nuxIv4A8ad.text-output h5:first-child:before,.paragraph-nuxIv4A8ad.text-output h6:first-child:before,.paragraph-nuxIv4A8ad.text-output p:first-child:before,.paragraph-pvUi7TFc7r.text-output h1:first-child:before,.paragraph-pvUi7TFc7r.text-output h2:first-child:before,.paragraph-pvUi7TFc7r.text-output h3:first-child:before,.paragraph-pvUi7TFc7r.text-output h4:first-child:before,.paragraph-pvUi7TFc7r.text-output h5:first-child:before,.paragraph-pvUi7TFc7r.text-output h6:first-child:before,.paragraph-pvUi7TFc7r.text-output p:first-child:before{color:var(--text-color);content:'\\';
|
|
10085
|
+
font-family: '';margin-right:5px;font-weight:700}.paragraph-6KxQcCSVR a,.paragraph-6KxQcCSVR a *{color:var(--link-color)!important;text-decoration:none}@media screen and (min-width:0px) and (max-width:480px){.paragraph-6KxQcCSVR h1,.paragraph-6KxQcCSVR h2,.paragraph-6KxQcCSVR h3,.paragraph-6KxQcCSVR h4,.paragraph-6KxQcCSVR h5,.paragraph-6KxQcCSVR h6,.paragraph-6KxQcCSVR ul li,.paragraph-6KxQcCSVR.text-output{font-size:16px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-6KxQcCSVR h1,.paragraph-6KxQcCSVR h2,.paragraph-6KxQcCSVR h3,.paragraph-6KxQcCSVR h4,.paragraph-6KxQcCSVR h5,.paragraph-6KxQcCSVR h6,.paragraph-6KxQcCSVR ul li,.paragraph-6KxQcCSVR.text-output{font-size:16px!important;font-weight:undefined}}.paragraph-nuxIv4A8ad a,.paragraph-nuxIv4A8ad a *{color:var(--my-custom-color-26)!important;text-decoration:none}@media screen and (min-width:0px) and (max-width:480px){.paragraph-nuxIv4A8ad h1,.paragraph-nuxIv4A8ad h2,.paragraph-nuxIv4A8ad h3,.paragraph-nuxIv4A8ad h4,.paragraph-nuxIv4A8ad h5,.paragraph-nuxIv4A8ad h6,.paragraph-nuxIv4A8ad ul li,.paragraph-nuxIv4A8ad.text-output{font-size:20px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-nuxIv4A8ad h1,.paragraph-nuxIv4A8ad h2,.paragraph-nuxIv4A8ad h3,.paragraph-nuxIv4A8ad h4,.paragraph-nuxIv4A8ad h5,.paragraph-nuxIv4A8ad h6,.paragraph-nuxIv4A8ad ul li,.paragraph-nuxIv4A8ad.text-output{font-size:18px!important;font-weight:undefined}}.paragraph-pvUi7TFc7r a,.paragraph-pvUi7TFc7r a *{color:var(--link-color)!important;text-decoration:none}@media screen and (min-width:0px) and (max-width:480px){.paragraph-pvUi7TFc7r h1,.paragraph-pvUi7TFc7r h2,.paragraph-pvUi7TFc7r h3,.paragraph-pvUi7TFc7r h4,.paragraph-pvUi7TFc7r h5,.paragraph-pvUi7TFc7r h6,.paragraph-pvUi7TFc7r ul li,.paragraph-pvUi7TFc7r.text-output{font-size:16px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-pvUi7TFc7r h1,.paragraph-pvUi7TFc7r h2,.paragraph-pvUi7TFc7r h3,.paragraph-pvUi7TFc7r h4,.paragraph-pvUi7TFc7r h5,.paragraph-pvUi7TFc7r h6,.paragraph-pvUi7TFc7r ul li,.paragraph-pvUi7TFc7r.text-output{font-size:16px!important;font-weight:undefined}}` } }, imageText: { id: "section-MCURKhaM7", metaData: { id: "section-MCURKhaM7", type: "section", child: ["row-BafyFVpahF", "row-DTaBn6Nkpv"], class: { width: { value: "fullSection" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingBottom: { unit: "px", value: "90" }, paddingTop: { unit: "px", value: 20 }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { sticky: { value: "noneSticky" }, visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, allowRowMaxWidth: { value: false } }, wrapper: {}, meta: "section", tagName: "c-section", title: "Section", _id: "section-MCURKhaM7" }, elements: [{ id: "row-BafyFVpahF", type: "row", child: ["col-CAyTxea5q"], class: { alignRow: { value: "row-align-center" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 15 }, paddingBottom: { unit: "px", value: 15 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, rowWidth: { value: 100, unit: "%" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-row", meta: "row", title: "1 Column Row" }, { id: "col-CAyTxea5q", type: "col", child: ["sub-heading-MbvugAQFJf", "image-2hPEEKf7g"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 5 }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: "100", unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "1st Column" }, { extra: { nodeId: "cimage-2hPEEKf7g", visibility: { value: { hideDesktop: false, hideMobile: false } }, imageActions: { value: "none" }, visitWebsite: { value: { url: "", newTab: false } }, imageProperties: { value: { width: "", height: "", url: "https://storage.googleapis.com/msgsndr/locatation/EVTjG29VnVlvwn3SRGve/images/e04c0629-2eca-41d4-a320-ef634015616a.png", altText: "", compression: true, placeholderBase64: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAYAAABhYU3QAAAABHNCSVQICAgIfAhkiAAAAF96VFh0UmF3IHByb2ZpbGUgdHlwZSBBUFAxAAAImeNKT81LLcpMVigoyk/LzEnlUgADYxMuE0sTS6NEAwMDCwMIMDQwMDYEkkZAtjlUKNEABZgamFmaGZsZmgMxiM8FAEi2FMk61EMyAAAAVklEQVQImQXBMQ5AMBiA0a+tFpGIpBKLmRs4kCO5iMl9LMwmaUr93lPHtg7GGBsB9YYra9pZo8r73BdTe++AlNKTUVWjQGEBERcVFMJXuq6ftEguABB+L0UZOFcVeFYAAAAASUVORK5CYII=", servingUrl: "https://lh3.googleusercontent.com/8DcV-wSbJBKHjx-cmwagHA3SspBD4P3ScvvmZZog37NoIdaprLI5vt2nY7nfrqeCFVLFa0YTcL7jR3soFjmRqbNiESGeZ1Nm", imageMeta: { width: "", height: "" } } } }, class: { imageRadius: { value: "img-none" }, imageBorder: { value: "img-border-none" }, imageShadow: { value: "img-shadow-none" }, imageEffects: { value: "img-effects-none" } }, styles: { paddingLeft: { unit: "px", value: 10 }, paddingRight: { value: 10, unit: "px" }, paddingTop: { unit: "px", value: "10" }, paddingBottom: { unit: "px", value: "10" }, backgroundColor: { value: "var(--transparent)" }, opacity: { value: "1" }, textAlign: { value: "center" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "image-2hPEEKf7g", type: "element", child: [], meta: "image", tagName: "c-image", title: "Image", tag: "" }, { extra: { nodeId: "csub-heading-MbvugAQFJf", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<h2>WHAT MAKES US DIFFERENT</h2>" }, mobileFontSize: { value: 46, unit: "px" }, desktopFontSize: { value: 46, unit: "px" }, typography: { value: "var(--headlinefont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } }, customClass: { value: [] } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal", desktop: "400" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "center" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginLeft: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 } }, customCss: [], id: "sub-heading-MbvugAQFJf", type: "element", child: [], mobileStyles: {}, mobileWrapper: {}, meta: "sub-heading", tagName: "c-sub-heading", title: "Sub Headline", tag: "h3" }, { id: "row-DTaBn6Nkpv", type: "row", child: ["col-uYMJwyEml", "col-FIkE81-ke", "col-qanoGGetC"], class: { alignRow: { value: "row-align-center" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 15 }, paddingBottom: { unit: "px", value: 15 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, rowWidth: { value: 100, unit: "%" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-row", meta: "row", title: "3 Column Row" }, { id: "col-uYMJwyEml", type: "col", child: ["paragraph-PwtXX77o4", "paragraph-F9SB3vFfN"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: "70" }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: "100", unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "flex-start" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "1st Column" }, { extra: { nodeId: "cparagraph-F9SB3vFfN", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>State-of-the-art technology ensures the highest quality treatments for optimal results and unparalleled skincare and wellness experiences.</p>" }, mobileFontSize: { value: 14, unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-F9SB3vFfN", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { extra: { nodeId: "cparagraph-PwtXX77o4", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p><strong>Modern Equipment</strong></p>" }, mobileFontSize: { value: "20", unit: "px" }, desktopFontSize: { value: "22", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--red)" }, boldTextColor: { value: "var(--my-custom-color-44)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: "10" }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-PwtXX77o4", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { id: "col-FIkE81-ke", type: "col", child: ["paragraph-Ud7-Hmgyun", "paragraph-ECP1xCEVEa"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: "70" }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: "100", unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "flex-start" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "1st Column" }, { extra: { nodeId: "cparagraph-Ud7-Hmgyun", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p><strong>Qualified Staff</strong></p>" }, mobileFontSize: { value: "20", unit: "px" }, desktopFontSize: { value: "22", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--red)" }, boldTextColor: { value: "var(--my-custom-color-44)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: "10" }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-Ud7-Hmgyun", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { extra: { nodeId: "cparagraph-ECP1xCEVEa", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>Our highly trained and certified professionals provide expert care, ensuring safe and effective treatments for every client.</p>" }, mobileFontSize: { value: 14, unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-ECP1xCEVEa", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { id: "col-qanoGGetC", type: "col", child: ["paragraph-Dt21hDz3On", "paragraph-AU_CDh6MOl"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: "70" }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: "100", unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "flex-start" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "1st Column" }, { extra: { nodeId: "cparagraph-Dt21hDz3On", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p><strong>Effective Results</strong></p>" }, mobileFontSize: { value: "20", unit: "px" }, desktopFontSize: { value: "22", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--red)" }, boldTextColor: { value: "var(--my-custom-color-44)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: "10" }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-Dt21hDz3On", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { extra: { nodeId: "cparagraph-AU_CDh6MOl", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>Experience transformative results with our proven treatments, designed to deliver noticeable improvements and enhance your natural beauty.</p>" }, mobileFontSize: { value: 14, unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-AU_CDh6MOl", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }], sequence: 5, pageId: "FYBFsBAezEtsY0uXW4IN", funnelId: "pK3yy9CFapchugRrgjgq", locationId: "Gc2kgDDpABIR8QDyJ6rf", general: { colors: [{ label: "Black", value: "#000000" }, { label: "Red", value: "#e93d3d" }, { label: "Transparent", value: "transparent" }, { label: "my-custom-color-44", name: "My Custom Color 44", value: "#ec606a" }], fontsForPreview: ["'Oswald'", "'Lato'"], rootVars: { "--'oswald'": "'Oswald'", "--'lato'": "'Lato'", "--black": "#000000", "--red": "#e93d3d", "--transparent": "transparent", "--my-custom-color-44": "#ec606a" }, sectionStyles: ":root{--black:#000000;--red:#e93d3d;--transparent:transparent;--my-custom-color-44:#ec606a}.hl_page-preview--content .col-CAyTxea5q .inner,.hl_page-preview--content .row-BafyFVpahF,.hl_page-preview--content .section-MCURKhaM7{padding:20px 0 90px;margin-top:0;margin-bottom:0;background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .col-CAyTxea5q .inner,.hl_page-preview--content .row-BafyFVpahF{padding:15px 0;width:100%}.hl_page-preview--content .col-CAyTxea5q{width:100%}.hl_page-preview--content .col-CAyTxea5q .inner{padding:10px 5px}.hl_page-preview--content .image-2hPEEKf7g{margin-top:0;margin-bottom:0}.hl_page-preview--content .cimage-2hPEEKf7g{padding:10px;background-color:var(--transparent);opacity:1;text-align:center}.hl_page-preview--content .sub-heading-MbvugAQFJf{margin:0}.hl_page-preview--content .csub-heading-MbvugAQFJf,.hl_page-preview--content .row-DTaBn6Nkpv{background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .csub-heading-MbvugAQFJf{font-family:var(--headlinefont);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;line-height:1.3em;letter-spacing:0;text-align:center}.hl_page-preview--content .row-DTaBn6Nkpv{margin-top:0;margin-bottom:0;padding:15px 0;width:100%}.hl_page-preview--content .col-uYMJwyEml{width:100%}.hl_page-preview--content .col-FIkE81-ke .inner,.hl_page-preview--content .col-qanoGGetC .inner,.hl_page-preview--content .col-uYMJwyEml .inner{padding:10px 5px 10px 70px;background-color:var(--transparent);width:100%;border-color:var(--black);border-width:2px;border-style:solid;margin-top:0;margin-bottom:0}.hl_page-preview--content .paragraph-F9SB3vFfN{margin-top:0;margin-bottom:0}.hl_page-preview--content .cparagraph-F9SB3vFfN{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}.hl_page-preview--content .paragraph-PwtXX77o4{margin-top:0;margin-bottom:0}.hl_page-preview--content .cparagraph-PwtXX77o4{font-family:var(--contentfont);background-color:var(--transparent);color:var(--red);icon-color:var(--text-color);font-weight:400;padding:0 0 10px;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}.hl_page-preview--content .col-FIkE81-ke{width:100%}.hl_page-preview--content .paragraph-Ud7-Hmgyun{margin-top:0;margin-bottom:0}.hl_page-preview--content .cparagraph-Ud7-Hmgyun{font-family:var(--contentfont);background-color:var(--transparent);color:var(--red);icon-color:var(--text-color);font-weight:400;padding:0 0 10px;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}.hl_page-preview--content .paragraph-ECP1xCEVEa{margin-top:0;margin-bottom:0}.hl_page-preview--content .cparagraph-ECP1xCEVEa{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}.hl_page-preview--content .col-qanoGGetC{width:100%}.hl_page-preview--content .paragraph-Dt21hDz3On{margin-top:0;margin-bottom:0}.hl_page-preview--content .cparagraph-Dt21hDz3On{font-family:var(--contentfont);background-color:var(--transparent);color:var(--red);icon-color:var(--text-color);font-weight:400;padding:0 0 10px;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}.hl_page-preview--content .paragraph-AU_CDh6MOl{margin-top:0;margin-bottom:0}.hl_page-preview--content .cparagraph-AU_CDh6MOl{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}#section-MCURKhaM7>.inner{max-width:1170px}#col-CAyTxea5q>.inner{flex-direction:column;justify-content:center;align-items:inherit;flex-wrap:nowrap}.sub-heading-MbvugAQFJf{font-weight:400}.paragraph-F9SB3vFfN em,.paragraph-F9SB3vFfN strong,.paragraph-F9SB3vFfN u,.paragraph-PwtXX77o4 em,.paragraph-PwtXX77o4 u,.paragraph-Ud7-Hmgyun em,.paragraph-Ud7-Hmgyun u,.sub-heading-MbvugAQFJf em,.sub-heading-MbvugAQFJf strong,.sub-heading-MbvugAQFJf u{color:var(--text-color)!important}.paragraph-AU_CDh6MOl a,.paragraph-AU_CDh6MOl a *,.paragraph-Dt21hDz3On a,.paragraph-Dt21hDz3On a *,.paragraph-ECP1xCEVEa a,.paragraph-ECP1xCEVEa a *,.paragraph-F9SB3vFfN a,.paragraph-F9SB3vFfN a *,.paragraph-PwtXX77o4 a,.paragraph-PwtXX77o4 a *,.paragraph-Ud7-Hmgyun a,.paragraph-Ud7-Hmgyun a *,.sub-heading-MbvugAQFJf a,.sub-heading-MbvugAQFJf a *{color:var(--link-color)!important;text-decoration:none}.paragraph-AU_CDh6MOl a:hover,.paragraph-Dt21hDz3On a:hover,.paragraph-ECP1xCEVEa a:hover,.paragraph-F9SB3vFfN a:hover,.paragraph-PwtXX77o4 a:hover,.paragraph-Ud7-Hmgyun a:hover,.sub-heading-MbvugAQFJf a:hover{text-decoration:underline}@media screen and (min-width:0px) and (max-width:480px){.sub-heading-MbvugAQFJf h1,.sub-heading-MbvugAQFJf h2,.sub-heading-MbvugAQFJf h3,.sub-heading-MbvugAQFJf h4,.sub-heading-MbvugAQFJf h5,.sub-heading-MbvugAQFJf h6,.sub-heading-MbvugAQFJf ul li,.sub-heading-MbvugAQFJf.text-output{font-size:46px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.sub-heading-MbvugAQFJf h1,.sub-heading-MbvugAQFJf h2,.sub-heading-MbvugAQFJf h3,.sub-heading-MbvugAQFJf h4,.sub-heading-MbvugAQFJf h5,.sub-heading-MbvugAQFJf h6,.sub-heading-MbvugAQFJf ul li,.sub-heading-MbvugAQFJf.text-output{font-size:46px!important;font-weight:undefined}}.paragraph-AU_CDh6MOl.text-output h1:first-child:before,.paragraph-AU_CDh6MOl.text-output h2:first-child:before,.paragraph-AU_CDh6MOl.text-output h3:first-child:before,.paragraph-AU_CDh6MOl.text-output h4:first-child:before,.paragraph-AU_CDh6MOl.text-output h5:first-child:before,.paragraph-AU_CDh6MOl.text-output h6:first-child:before,.paragraph-AU_CDh6MOl.text-output p:first-child:before,.paragraph-Dt21hDz3On.text-output h1:first-child:before,.paragraph-Dt21hDz3On.text-output h2:first-child:before,.paragraph-Dt21hDz3On.text-output h3:first-child:before,.paragraph-Dt21hDz3On.text-output h4:first-child:before,.paragraph-Dt21hDz3On.text-output h5:first-child:before,.paragraph-Dt21hDz3On.text-output h6:first-child:before,.paragraph-Dt21hDz3On.text-output p:first-child:before,.paragraph-ECP1xCEVEa.text-output h1:first-child:before,.paragraph-ECP1xCEVEa.text-output h2:first-child:before,.paragraph-ECP1xCEVEa.text-output h3:first-child:before,.paragraph-ECP1xCEVEa.text-output h4:first-child:before,.paragraph-ECP1xCEVEa.text-output h5:first-child:before,.paragraph-ECP1xCEVEa.text-output h6:first-child:before,.paragraph-ECP1xCEVEa.text-output p:first-child:before,.paragraph-F9SB3vFfN.text-output h1:first-child:before,.paragraph-F9SB3vFfN.text-output h2:first-child:before,.paragraph-F9SB3vFfN.text-output h3:first-child:before,.paragraph-F9SB3vFfN.text-output h4:first-child:before,.paragraph-F9SB3vFfN.text-output h5:first-child:before,.paragraph-F9SB3vFfN.text-output h6:first-child:before,.paragraph-F9SB3vFfN.text-output p:first-child:before,.paragraph-PwtXX77o4.text-output h1:first-child:before,.paragraph-PwtXX77o4.text-output h2:first-child:before,.paragraph-PwtXX77o4.text-output h3:first-child:before,.paragraph-PwtXX77o4.text-output h4:first-child:before,.paragraph-PwtXX77o4.text-output h5:first-child:before,.paragraph-PwtXX77o4.text-output h6:first-child:before,.paragraph-PwtXX77o4.text-output p:first-child:before,.paragraph-Ud7-Hmgyun.text-output h1:first-child:before,.paragraph-Ud7-Hmgyun.text-output h2:first-child:before,.paragraph-Ud7-Hmgyun.text-output h3:first-child:before,.paragraph-Ud7-Hmgyun.text-output h4:first-child:before,.paragraph-Ud7-Hmgyun.text-output h5:first-child:before,.paragraph-Ud7-Hmgyun.text-output h6:first-child:before,.paragraph-Ud7-Hmgyun.text-output p:first-child:before,.sub-heading-MbvugAQFJf.text-output h1:first-child:before,.sub-heading-MbvugAQFJf.text-output h2:first-child:before,.sub-heading-MbvugAQFJf.text-output h3:first-child:before,.sub-heading-MbvugAQFJf.text-output h4:first-child:before,.sub-heading-MbvugAQFJf.text-output h5:first-child:before,.sub-heading-MbvugAQFJf.text-output h6:first-child:before,.sub-heading-MbvugAQFJf.text-output p:first-child:before{color:var(--text-color);content:'\\';\n font-family: '';margin-right:5px;font-weight:700}#col-FIkE81-ke>.inner,#col-qanoGGetC>.inner,#col-uYMJwyEml>.inner{flex-direction:column;justify-content:flex-start;align-items:inherit;flex-wrap:nowrap}.paragraph-AU_CDh6MOl,.paragraph-Dt21hDz3On,.paragraph-ECP1xCEVEa,.paragraph-F9SB3vFfN,.paragraph-PwtXX77o4,.paragraph-Ud7-Hmgyun{font-weight:undefined}@media screen and (min-width:0px) and (max-width:480px){.paragraph-F9SB3vFfN h1,.paragraph-F9SB3vFfN h2,.paragraph-F9SB3vFfN h3,.paragraph-F9SB3vFfN h4,.paragraph-F9SB3vFfN h5,.paragraph-F9SB3vFfN h6,.paragraph-F9SB3vFfN ul li,.paragraph-F9SB3vFfN.text-output{font-size:14px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-F9SB3vFfN h1,.paragraph-F9SB3vFfN h2,.paragraph-F9SB3vFfN h3,.paragraph-F9SB3vFfN h4,.paragraph-F9SB3vFfN h5,.paragraph-F9SB3vFfN h6,.paragraph-F9SB3vFfN ul li,.paragraph-F9SB3vFfN.text-output{font-size:16px!important;font-weight:undefined}}.paragraph-PwtXX77o4 strong,.paragraph-Ud7-Hmgyun strong{color:var(--my-custom-color-44)!important}@media screen and (min-width:0px) and (max-width:480px){.paragraph-PwtXX77o4 h1,.paragraph-PwtXX77o4 h2,.paragraph-PwtXX77o4 h3,.paragraph-PwtXX77o4 h4,.paragraph-PwtXX77o4 h5,.paragraph-PwtXX77o4 h6,.paragraph-PwtXX77o4 ul li,.paragraph-PwtXX77o4.text-output{font-size:20px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-PwtXX77o4 h1,.paragraph-PwtXX77o4 h2,.paragraph-PwtXX77o4 h3,.paragraph-PwtXX77o4 h4,.paragraph-PwtXX77o4 h5,.paragraph-PwtXX77o4 h6,.paragraph-PwtXX77o4 ul li,.paragraph-PwtXX77o4.text-output{font-size:22px!important;font-weight:undefined}}@media screen and (min-width:0px) and (max-width:480px){.paragraph-Ud7-Hmgyun h1,.paragraph-Ud7-Hmgyun h2,.paragraph-Ud7-Hmgyun h3,.paragraph-Ud7-Hmgyun h4,.paragraph-Ud7-Hmgyun h5,.paragraph-Ud7-Hmgyun h6,.paragraph-Ud7-Hmgyun ul li,.paragraph-Ud7-Hmgyun.text-output{font-size:20px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-Ud7-Hmgyun h1,.paragraph-Ud7-Hmgyun h2,.paragraph-Ud7-Hmgyun h3,.paragraph-Ud7-Hmgyun h4,.paragraph-Ud7-Hmgyun h5,.paragraph-Ud7-Hmgyun h6,.paragraph-Ud7-Hmgyun ul li,.paragraph-Ud7-Hmgyun.text-output{font-size:22px!important;font-weight:undefined}}.paragraph-AU_CDh6MOl em,.paragraph-Dt21hDz3On em,.paragraph-Dt21hDz3On u,.paragraph-ECP1xCEVEa em,.paragraph-ECP1xCEVEa strong,.paragraph-ECP1xCEVEa u{color:var(--text-color)!important}@media screen and (min-width:0px) and (max-width:480px){.paragraph-ECP1xCEVEa h1,.paragraph-ECP1xCEVEa h2,.paragraph-ECP1xCEVEa h3,.paragraph-ECP1xCEVEa h4,.paragraph-ECP1xCEVEa h5,.paragraph-ECP1xCEVEa h6,.paragraph-ECP1xCEVEa ul li,.paragraph-ECP1xCEVEa.text-output{font-size:14px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-ECP1xCEVEa h1,.paragraph-ECP1xCEVEa h2,.paragraph-ECP1xCEVEa h3,.paragraph-ECP1xCEVEa h4,.paragraph-ECP1xCEVEa h5,.paragraph-ECP1xCEVEa h6,.paragraph-ECP1xCEVEa ul li,.paragraph-ECP1xCEVEa.text-output{font-size:16px!important;font-weight:undefined}}.paragraph-Dt21hDz3On strong{color:var(--my-custom-color-44)!important}@media screen and (min-width:0px) and (max-width:480px){.paragraph-Dt21hDz3On h1,.paragraph-Dt21hDz3On h2,.paragraph-Dt21hDz3On h3,.paragraph-Dt21hDz3On h4,.paragraph-Dt21hDz3On h5,.paragraph-Dt21hDz3On h6,.paragraph-Dt21hDz3On ul li,.paragraph-Dt21hDz3On.text-output{font-size:20px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-Dt21hDz3On h1,.paragraph-Dt21hDz3On h2,.paragraph-Dt21hDz3On h3,.paragraph-Dt21hDz3On h4,.paragraph-Dt21hDz3On h5,.paragraph-Dt21hDz3On h6,.paragraph-Dt21hDz3On ul li,.paragraph-Dt21hDz3On.text-output{font-size:22px!important;font-weight:undefined}}.paragraph-AU_CDh6MOl strong,.paragraph-AU_CDh6MOl u{color:var(--text-color)!important}@media screen and (min-width:0px) and (max-width:480px){.paragraph-AU_CDh6MOl h1,.paragraph-AU_CDh6MOl h2,.paragraph-AU_CDh6MOl h3,.paragraph-AU_CDh6MOl h4,.paragraph-AU_CDh6MOl h5,.paragraph-AU_CDh6MOl h6,.paragraph-AU_CDh6MOl ul li,.paragraph-AU_CDh6MOl.text-output{font-size:14px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-AU_CDh6MOl h1,.paragraph-AU_CDh6MOl h2,.paragraph-AU_CDh6MOl h3,.paragraph-AU_CDh6MOl h4,.paragraph-AU_CDh6MOl h5,.paragraph-AU_CDh6MOl h6,.paragraph-AU_CDh6MOl ul li,.paragraph-AU_CDh6MOl.text-output{font-size:16px!important;font-weight:undefined}}" } }, ctaBanner: { id: "section--JU5JdhYV", metaData: { id: "section--JU5JdhYV", type: "section", child: ["row-CazIBfKqbz"], class: { width: { value: "fullSection" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingBottom: { unit: "px", value: "100" }, paddingTop: { unit: "px", value: "100" }, marginTop: { unit: "px", value: "0" }, marginBottom: { unit: "px", value: 0 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { sticky: { value: "noneSticky" }, visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "https://firebasestorage.googleapis.com/v0/b/highlevel-backend.appspot.com/o/location%2Fh0gYqQIqOIBs6xxgZjft%2Fimages%2F9ef53318-6f0a-409c-ada2-11d53ce1a6e5.jpeg?alt=media", opacity: "1", options: "full-center", servingUrl: "https://lh3.googleusercontent.com/sT5WiBSUQqVKzeevrcTjiz6CoqIQlZQZ3VcYusidOhHeM9Mwv5fi5NZSODOUk5mCVR1n2H0OPR8OybU0kG5ANkDME4rqFDY", placeholderBase64: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAMCAgMCAgUDAwMEAwMEBQgFBQoEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUCg4BAwQEBQQFCQUFCRINCw0UFBQSFA4SFRINChQVFBQUDxQNDRUSDgoQFBQUFBQOFBQSCgoVFAoVCg4UDA4QCAgKCP/AABEIAAMACgMBEQACEQEDEQH/xAAVAAEBAAAAAAAAAAAAAAAAAAAIBf/EAB4QAQABAgcAAAAAAAAAAAAAAAERAJECAwQFEyFR/8QAFQEBAQAAAAAAAAAAAAAAAAAABQT/xAAZEQEBAAMBAAAAAAAAAAAAAAABAAMEEgL/2gAMAwEAAhEDEQA/AHrsMGZqQAOdxMESykvr0WofAr1N7IB5atVdDf/Z", imageMeta: { height: 537, width: 1920 } } }, allowRowMaxWidth: { value: false } }, wrapper: {}, meta: "section", tagName: "c-section", title: "Section", _id: "section--JU5JdhYV", mobileStyles: { paddingTop: { unit: "px", value: 60 }, paddingBottom: { unit: "px", value: 60 } } }, elements: [{ id: "row-CazIBfKqbz", type: "row", child: ["col-fbo_QJCXqk", "col-fwNPlL8ta"], class: { alignRow: { value: "row-align-center" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 15 }, paddingBottom: { unit: "px", value: 15 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, rowWidth: { value: 100, unit: "%" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-row", meta: "row", title: "2 Column Row" }, { id: "col-fbo_QJCXqk", type: "col", child: [], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 5 }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: 38.6, unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: true } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "1st Column" }, { id: "col-fwNPlL8ta", type: "col", child: ["sub-heading-JJ_mZmXWcY", "paragraph-NAh24LKg8A", "button-H3ED7jvqBu"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 5 }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: 61.4, unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "1st Column" }, { extra: { nodeId: "cparagraph-NAh24LKg8A", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>At {{location.name}}, we offer a comprehensive range of treatments tailored to meet your unique beauty and wellness needs. Each service is designed to deliver exceptional results, ensuring you leave our spa feeling revitalized, confident, and radiant.</p>" }, mobileFontSize: { value: "16", unit: "px" }, desktopFontSize: { value: "18", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: "1.4", unit: "em" }, textTransform: { value: "none" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-NAh24LKg8A", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { extra: { nodeId: "cbutton-H3ED7jvqBu", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "free consultation" }, subText: { value: "" }, mobileFontSize: { value: "16", unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, subTextDesktopFontSize: { value: 15, unit: "px" }, subTextMobileFontSize: { value: 15, unit: "px" }, typography: { value: "var(--headlinefont)" }, iconStart: { value: { name: "", unicode: "", fontFamily: "" } }, iconEnd: { value: { name: "", unicode: "", fontFamily: "" } }, action: { value: "url" }, visitWebsite: { value: { url: "#", newTab: false } }, hideElements: { value: [] }, scrollToElement: { value: "" }, phoneNumber: { value: "" }, productId: { value: "" }, stepPath: { value: "" }, saleAction: { value: "go-to-next-funnel-step" } }, class: { buttonEffects: { value: "none" }, buttonBoxShadow: { value: "btnshadow" }, buttonBgStyle: { value: "custom", text: "Custom", targetConfig: { styles: {} } }, buttonVp: { value: "btn-vp" }, buttonHp: { value: "btn-hp" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--my-custom-color-44)" }, color: { value: "var(--white)" }, secondaryColor: { value: "var(--white)" }, textDecoration: { value: "none" }, paddingTop: { unit: "px", value: "12" }, paddingBottom: { unit: "px", value: "12" }, paddingLeft: { unit: "px", value: "30" }, paddingRight: { value: "30", unit: "px" }, fontWeight: { value: "bold" }, borderColor: { value: "var(--secondary)" }, borderWidth: { value: 3, unit: "px" }, borderStyle: { value: "solid" }, letterSpacing: { value: "0", unit: "px" }, textTransform: { value: "uppercase" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, width: { value: "auto", unit: "%" } }, wrapper: { marginTop: { unit: "px", value: "30" }, marginBottom: { unit: "px", value: 0 }, textAlign: { value: "left" } }, customCss: [], id: "button-H3ED7jvqBu", type: "element", child: [], meta: "button", tagName: "c-button", title: "Button", tag: "" }, { extra: { nodeId: "csub-heading-JJ_mZmXWcY", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<h2>ALL KINDS OF TREATMENTS</h2>" }, mobileFontSize: { value: 60, unit: "px" }, desktopFontSize: { value: 60, unit: "px" }, typography: { value: "var(--headlinefont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } }, customClass: { value: [] } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal", desktop: "400" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginLeft: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 } }, customCss: [], id: "sub-heading-JJ_mZmXWcY", type: "element", child: [], mobileStyles: {}, mobileWrapper: {}, meta: "sub-heading", tagName: "c-sub-heading", title: "Sub Headline", tag: "h3" }], sequence: 6, pageId: "FYBFsBAezEtsY0uXW4IN", funnelId: "pK3yy9CFapchugRrgjgq", locationId: "Gc2kgDDpABIR8QDyJ6rf", general: { colors: [{ value: "#188bf6", label: "Secondary" }, { label: "White", value: "#ffffff" }, { label: "Black", value: "#000000" }, { label: "Transparent", value: "transparent" }, { label: "my-custom-color-44", name: "My Custom Color 44", value: "#ec606a" }], fontsForPreview: ["'Lato'", "'Oswald'"], rootVars: { "--'lato'": "'Lato'", "--'oswald'": "'Oswald'", "--secondary": "#188bf6", "--white": "#ffffff", "--black": "#000000", "--transparent": "transparent", "--my-custom-color-44": "#ec606a" }, sectionStyles: ":root{--secondary:#188bf6;--white:#ffffff;--black:#000000;--transparent:transparent;--my-custom-color-44:#ec606a}.hl_page-preview--content .section--JU5JdhYV{padding:100px 0;margin-top:0;margin-bottom:0;background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid}@media screen and (min-width:0px) and (max-width:480px){.hl_page-preview--content .section--JU5JdhYV{padding-top:60px;padding-bottom:60px}}.hl_page-preview--content .col-fbo_QJCXqk .inner,.hl_page-preview--content .col-fwNPlL8ta .inner,.hl_page-preview--content .row-CazIBfKqbz{margin-top:0;margin-bottom:0;padding:15px 0;background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid;width:100%}.hl_page-preview--content .col-fbo_QJCXqk{width:38.6%}.hl_page-preview--content .col-fbo_QJCXqk .inner,.hl_page-preview--content .col-fwNPlL8ta .inner{padding:10px 5px;width:38.6%}.hl_page-preview--content .col-fwNPlL8ta{width:61.4%}.hl_page-preview--content .col-fwNPlL8ta .inner{width:61.4%}.hl_page-preview--content .paragraph-NAh24LKg8A{margin-top:0;margin-bottom:0}.hl_page-preview--content .cparagraph-NAh24LKg8A{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.4em;text-transform:none;letter-spacing:0;text-align:left}.hl_page-preview--content .button-H3ED7jvqBu{margin-top:30px;margin-bottom:0;text-align:left}.hl_page-preview--content .cbutton-H3ED7jvqBu{font-family:var(--headlinefont);background-color:var(--my-custom-color-44);color:var(--white);secondary-color:var(--white);text-decoration:none;padding:12px 30px;font-weight:700;border-color:var(--secondary);border-width:3px;border-style:solid;letter-spacing:0;text-transform:uppercase;text-shadow:0 0 0 transparent;width:auto%}.hl_page-preview--content .sub-heading-JJ_mZmXWcY{margin:0}.hl_page-preview--content .csub-heading-JJ_mZmXWcY{font-family:var(--headlinefont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}#section--JU5JdhYV>.inner{max-width:1170px}#col-fbo_QJCXqk>.inner,#col-fwNPlL8ta>.inner{flex-direction:column;justify-content:center;align-items:inherit;flex-wrap:nowrap}.paragraph-NAh24LKg8A{font-weight:undefined}.paragraph-NAh24LKg8A em,.paragraph-NAh24LKg8A strong,.paragraph-NAh24LKg8A u,.sub-heading-JJ_mZmXWcY em,.sub-heading-JJ_mZmXWcY strong,.sub-heading-JJ_mZmXWcY u{color:var(--text-color)!important}.paragraph-NAh24LKg8A a,.paragraph-NAh24LKg8A a *,.sub-heading-JJ_mZmXWcY a,.sub-heading-JJ_mZmXWcY a *{color:var(--link-color)!important;text-decoration:none}.paragraph-NAh24LKg8A a:hover,.sub-heading-JJ_mZmXWcY a:hover{text-decoration:underline}@media screen and (min-width:0px) and (max-width:480px){.paragraph-NAh24LKg8A h1,.paragraph-NAh24LKg8A h2,.paragraph-NAh24LKg8A h3,.paragraph-NAh24LKg8A h4,.paragraph-NAh24LKg8A h5,.paragraph-NAh24LKg8A h6,.paragraph-NAh24LKg8A ul li,.paragraph-NAh24LKg8A.text-output{font-size:16px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-NAh24LKg8A h1,.paragraph-NAh24LKg8A h2,.paragraph-NAh24LKg8A h3,.paragraph-NAh24LKg8A h4,.paragraph-NAh24LKg8A h5,.paragraph-NAh24LKg8A h6,.paragraph-NAh24LKg8A ul li,.paragraph-NAh24LKg8A.text-output{font-size:18px!important;font-weight:undefined}}.paragraph-NAh24LKg8A.text-output h1:first-child:before,.paragraph-NAh24LKg8A.text-output h2:first-child:before,.paragraph-NAh24LKg8A.text-output h3:first-child:before,.paragraph-NAh24LKg8A.text-output h4:first-child:before,.paragraph-NAh24LKg8A.text-output h5:first-child:before,.paragraph-NAh24LKg8A.text-output h6:first-child:before,.paragraph-NAh24LKg8A.text-output p:first-child:before,.sub-heading-JJ_mZmXWcY.text-output h1:first-child:before,.sub-heading-JJ_mZmXWcY.text-output h2:first-child:before,.sub-heading-JJ_mZmXWcY.text-output h3:first-child:before,.sub-heading-JJ_mZmXWcY.text-output h4:first-child:before,.sub-heading-JJ_mZmXWcY.text-output h5:first-child:before,.sub-heading-JJ_mZmXWcY.text-output h6:first-child:before,.sub-heading-JJ_mZmXWcY.text-output p:first-child:before{color:var(--text-color);content:'\\';\n font-family: '';margin-right:5px;font-weight:700}@media screen and (min-width:481px) and (max-width:10000px){.button-H3ED7jvqBu .button-icon-end,.button-H3ED7jvqBu .button-icon-start,.button-H3ED7jvqBu .main-heading-button{font-size:16px;font-weight:undefined}.button-H3ED7jvqBu .button-icon-start{margin-right:5px}.button-H3ED7jvqBu .button-icon-end{margin-left:5px}.button-H3ED7jvqBu .sub-heading-button{font-size:15px;color:var(--white);font-weight:undefined}}@media screen and (min-width:0px) and (max-width:480px){.button-H3ED7jvqBu .button-icon-end,.button-H3ED7jvqBu .button-icon-start,.button-H3ED7jvqBu .main-heading-button{font-size:16px;font-weight:undefined}.button-H3ED7jvqBu .button-icon-start{margin-right:5px}.button-H3ED7jvqBu .button-icon-end{margin-left:5px}.button-H3ED7jvqBu .sub-heading-button{font-size:15px;color:var(--white);font-weight:undefined}}.sub-heading-JJ_mZmXWcY{font-weight:400}@media screen and (min-width:0px) and (max-width:480px){.sub-heading-JJ_mZmXWcY h1,.sub-heading-JJ_mZmXWcY h2,.sub-heading-JJ_mZmXWcY h3,.sub-heading-JJ_mZmXWcY h4,.sub-heading-JJ_mZmXWcY h5,.sub-heading-JJ_mZmXWcY h6,.sub-heading-JJ_mZmXWcY ul li,.sub-heading-JJ_mZmXWcY.text-output{font-size:60px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.sub-heading-JJ_mZmXWcY h1,.sub-heading-JJ_mZmXWcY h2,.sub-heading-JJ_mZmXWcY h3,.sub-heading-JJ_mZmXWcY h4,.sub-heading-JJ_mZmXWcY h5,.sub-heading-JJ_mZmXWcY h6,.sub-heading-JJ_mZmXWcY ul li,.sub-heading-JJ_mZmXWcY.text-output{font-size:60px!important;font-weight:undefined}}" } }, faq: { id: "section-zJJ17L55C_", metaData: { id: "section-zJJ17L55C_", type: "section", child: ["row-zwaPMb51Ig", "row-B3nlfUUX-J"], class: { width: { value: "fullSection" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingBottom: { unit: "px", value: 40 }, paddingTop: { unit: "px", value: 40 }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginLeft: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { sticky: { value: "noneSticky" }, visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { mediaType: "image", url: "", opacity: "1", options: "bgCover", svgCode: "", videoUrl: "", videoThumbnail: "", videoLoop: true } }, allowRowMaxWidth: { value: false }, customClass: { value: [] } }, wrapper: {}, meta: "section", tagName: "c-section", title: "FAQs", mobileStyles: {}, mobileWrapper: {}, _id: "section-zJJ17L55C_", isGlobal: true }, elements: [{ id: "row-B3nlfUUX-J", type: "row", child: ["col-TgLmpbuj1O", "col-qmvDyClR0p"], class: { alignRow: { value: "row-align-center" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 15 }, paddingBottom: { unit: "px", value: 15 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { mediaType: "image", url: "", opacity: "1", options: "bgCover", svgCode: "", videoUrl: "", videoThumbnail: "", videoLoop: true } }, rowWidth: { value: 100, unit: "%" }, customClass: { value: [] } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginLeft: { unit: "", value: "auto" }, marginRight: { unit: "", value: "auto" } }, tagName: "c-row", meta: "row", title: "2 Column Row", mobileStyles: {}, mobileWrapper: {} }, { id: "col-TgLmpbuj1O", type: "col", child: ["faq-hC9kdZlk9d"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 5 }, paddingRight: { unit: "px", value: 10 }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, backgroundColor: { value: "var(--transparent)" }, width: { value: "100", unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { mediaType: "image", url: "", opacity: "1", options: "bgCover", svgCode: "", videoUrl: "", videoThumbnail: "", videoLoop: true } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "flex-start" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true }, customClass: { value: [] }, elementVersion: { value: 2 } }, wrapper: { marginLeft: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "1st Column", mobileStyles: {}, mobileWrapper: {} }, { extra: { nodeId: "cfaq-hC9kdZlk9d", faqType: { value: "simple" }, faqList: { value: [{ id: 1, heading: "<h4>What should I expect during my first visit?</h4>", text: "<p>Your first visit begins with a comprehensive consultation where our experts will assess your skin and discuss your aesthetic goals. We will recommend personalized treatment options and answer any questions you may have to ensure you feel comfortable and informed.</p>", showImage: false, image: "https://storage.googleapis.com/msgsndr/knES3eSWYIsc5YSZ3YLl/media/62beef4f9f43b0c53e585a8f.jpeg", active: true, compression: true }, { id: 2, heading: "<h4>Are your treatments safe?</h4>", text: "<p>Yes, all our treatments are performed by highly trained and certified professionals using state-of-the-art equipment and techniques. We prioritize your safety and comfort, adhering to the highest standards of medical care and hygiene.</p>", showImage: false, image: "https://storage.googleapis.com/msgsndr/knES3eSWYIsc5YSZ3YLl/media/62beef4f9f43b0c53e585a8f.jpeg", active: false, compression: true }, { id: 3, heading: "<h4>How do I know which treatment is right for me?</h4>", text: "<p>Our team will guide you through the selection process during your initial consultation. We\u2019ll evaluate your skin type, concerns, and goals to recommend the most suitable treatments to achieve the best results for you.</p>", showImage: false, image: "https://storage.googleapis.com/msgsndr/knES3eSWYIsc5YSZ3YLl/media/62beef4f9f43b0c53e585a8f.jpeg", active: false, compression: true }] }, typography: { value: "var(--contentfont)" }, faqCustomOptions: { value: { openIcon: { color: "var(--black)", fontFamily: "Font Awesome 5 Free", name: "chevron-down", unicode: "f078" }, closeIcon: { color: "var(--black)", fontFamily: "Font Awesome 5 Free", name: "chevron-up", unicode: "f077" }, iconPosition: "left", lineHeight: "1.5", showImagePopup: true, expandAllToggle: false, expandAll: true, firstItemOpen: false } }, featureHeadlineDesktopFontSize: { value: 20, unit: "px" }, featureHeadlineMobileFontSize: { value: 15, unit: "px" }, desktopFontSize: { value: 15, unit: "px" }, mobileFontSize: { value: 12, unit: "px" }, visibility: { value: { hideDesktop: false, hideMobile: false } }, customClass: { value: [] } }, mobileExtra: {}, class: { borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" }, boxShadow: { value: "none" } }, styles: { faqOpenTitleTextColor: { value: "var(--white)" }, faqOpenTitleBackgroundColor: { value: "var(--my-custom-color-44)" }, faqDividerColor: { value: "var(--my-custom-color-16)" }, faqContentTextColor: { value: "var(--my-custom-color-26)" }, faqOpenBackgroundColor: { value: "var(--white)" }, faqClosedTitleTextColor: { value: "var(--my-custom-color-26)" }, faqClosedTitleBackgroundColor: { value: "var(--my-custom-color-60)" }, faqExpandAllButtonTextColor: { value: "var(--my-custom-color-44)" }, faqExpandAllButtonBorderColor: { value: "#D1D5DB" }, faqExpandAllButtonBackgroundColor: { value: "var(--transparent)" }, linkTextColor: { value: "#3B82F6" }, faqHeadingFontFamily: { value: "var(--headlinefont)" }, faqContentFontFamily: { value: "var(--contentfont)" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { unit: "px", value: 0 }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 }, marginLeft: { unit: "px", value: 0 }, borderColor: { value: "var(--black)" }, borderStyle: { value: "solid" }, borderWidth: { value: "2", unit: "px" }, fontWeight: { value: "bold", desktop: "400" }, fontWeightSub: { desktop: "400" } }, wrapper: {}, customCss: [], id: "faq-hC9kdZlk9d", version: 2, type: "element", child: [], meta: "faq", tagName: "c-faq", title: "FAQ", tag: "" }, { id: "col-qmvDyClR0p", type: "col", child: ["faq-xt8Q865Gfb"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 10 }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, backgroundColor: { value: "var(--transparent)" }, width: { value: "100", unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { mediaType: "image", url: "", opacity: "1", options: "bgCover", svgCode: "", videoUrl: "", videoThumbnail: "", videoLoop: true } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "flex-start" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true }, customClass: { value: [] }, elementVersion: { value: 2 } }, wrapper: { marginLeft: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "2nd Column", mobileStyles: {}, mobileWrapper: {} }, { extra: { nodeId: "cfaq-xt8Q865Gfb", faqType: { value: "simple" }, faqList: { value: [{ id: 1, heading: "<h4>Is there any downtime after treatments?</h4>", text: "<p>Most of our treatments are non-invasive or minimally invasive, requiring little to no downtime. However, the recovery time can vary depending on the specific treatment. During your consultation, we will provide detailed post-treatment care instructions and inform you about any necessary recovery time.</p>", showImage: false, image: "https://storage.googleapis.com/msgsndr/knES3eSWYIsc5YSZ3YLl/media/62beef4f9f43b0c53e585a8f.jpeg", active: true, compression: true }, { id: 2, heading: "<h4>How often should I schedule treatments?</h4>", text: "<p>The frequency of treatments depends on the type of service and your individual needs. Some treatments, like facials, may be done monthly, while others, like laser hair removal, may require a series of sessions spaced several weeks apart. We will create a personalized treatment plan to ensure optimal results.</p>", showImage: false, image: "https://storage.googleapis.com/msgsndr/knES3eSWYIsc5YSZ3YLl/media/62beef4f9f43b0c53e585a8f.jpeg", active: false, compression: true }, { id: 3, heading: "<h4>Do you offer packages or memberships?</h4>", text: "<p>Yes, we offer a variety of packages and memberships designed to provide you with ongoing care and savings. Our packages bundle popular treatments for comprehensive care, while our memberships offer exclusive benefits and discounts. Contact us to learn more about our current offerings and find the perfect plan for your needs.</p>", showImage: false, image: "https://storage.googleapis.com/msgsndr/knES3eSWYIsc5YSZ3YLl/media/62beef4f9f43b0c53e585a8f.jpeg", active: false, compression: true }] }, typography: { value: "var(--contentfont)" }, faqCustomOptions: { value: { openIcon: { color: "var(--black)", fontFamily: "Font Awesome 5 Free", name: "chevron-down", unicode: "f078" }, closeIcon: { color: "var(--black)", fontFamily: "Font Awesome 5 Free", name: "chevron-up", unicode: "f077" }, iconPosition: "left", lineHeight: "1.5", showImagePopup: true, expandAllToggle: false, expandAll: true, firstItemOpen: false } }, featureHeadlineDesktopFontSize: { value: 20, unit: "px" }, featureHeadlineMobileFontSize: { value: 15, unit: "px" }, desktopFontSize: { value: 15, unit: "px" }, mobileFontSize: { value: 12, unit: "px" }, visibility: { value: { hideDesktop: false, hideMobile: false } }, customClass: { value: [] } }, mobileExtra: {}, class: { borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" }, boxShadow: { value: "none" } }, styles: { faqOpenTitleTextColor: { value: "var(--white)" }, faqOpenTitleBackgroundColor: { value: "var(--my-custom-color-44)" }, faqDividerColor: { value: "var(--my-custom-color-16)" }, faqContentTextColor: { value: "var(--my-custom-color-26)" }, faqOpenBackgroundColor: { value: "var(--white)" }, faqClosedTitleTextColor: { value: "var(--my-custom-color-26)" }, faqClosedTitleBackgroundColor: { value: "var(--my-custom-color-60)" }, faqExpandAllButtonTextColor: { value: "var(--my-custom-color-44)" }, faqExpandAllButtonBorderColor: { value: "#D1D5DB" }, faqExpandAllButtonBackgroundColor: { value: "var(--my-custom-color-26)" }, linkTextColor: { value: "#3B82F6" }, faqHeadingFontFamily: { value: "var(--headlinefont)" }, faqContentFontFamily: { value: "var(--contentfont)" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { unit: "px", value: 0 }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 }, marginLeft: { unit: "px", value: 0 }, borderColor: { value: "var(--black)" }, borderStyle: { value: "solid" }, borderWidth: { value: "2", unit: "px" }, fontWeight: { value: "bold", desktop: "400" }, fontWeightSub: { desktop: "400" } }, wrapper: {}, customCss: [], id: "faq-xt8Q865Gfb", version: 2, type: "element", child: [], meta: "faq", tagName: "c-faq", title: "FAQ", tag: "" }, { id: "row-zwaPMb51Ig", type: "row", child: ["col-uV9_D99Gtm"], class: { alignRow: { value: "row-align-center" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 15 }, paddingBottom: { unit: "px", value: 15 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { mediaType: "image", url: "", opacity: "1", options: "bgCover", svgCode: "", videoUrl: "", videoThumbnail: "", videoLoop: true } }, rowWidth: { value: 100, unit: "%" }, customClass: { value: [] } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginLeft: { unit: "", value: "auto" }, marginRight: { unit: "", value: "auto" } }, tagName: "c-row", meta: "row", title: "1 Column Row", mobileStyles: {}, mobileWrapper: {} }, { id: "col-uV9_D99Gtm", type: "col", child: ["sub-heading-bQudNu4eBG", "image-VMrslNNuUy"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 5 }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: "100", unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { mediaType: "image", url: "", opacity: "1", options: "bgCover", svgCode: "", videoUrl: "", videoThumbnail: "", videoLoop: true } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true }, customClass: { value: [] }, elementVersion: { value: 2 } }, wrapper: { marginLeft: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "1st Column", mobileStyles: {}, mobileWrapper: {} }, { extra: { nodeId: "cimage-VMrslNNuUy", visibility: { value: { hideDesktop: false, hideMobile: false } }, imageActions: { value: "none" }, visitWebsite: { value: { url: "", newTab: false } }, imageProperties: { value: { width: "", height: "", url: "https://storage.googleapis.com/msgsndr/locatation/EVTjG29VnVlvwn3SRGve/images/e04c0629-2eca-41d4-a320-ef634015616a.png", altText: "", compression: true, placeholderBase64: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAYAAABhYU3QAAAABHNCSVQICAgIfAhkiAAAAF96VFh0UmF3IHByb2ZpbGUgdHlwZSBBUFAxAAAImeNKT81LLcpMVigoyk/LzEnlUgADYxMuE0sTS6NEAwMDCwMIMDQwMDYEkkZAtjlUKNEABZgamFmaGZsZmgMxiM8FAEi2FMk61EMyAAAAVklEQVQImQXBMQ5AMBiA0a+tFpGIpBKLmRs4kCO5iMl9LMwmaUr93lPHtg7GGBsB9YYra9pZo8r73BdTe++AlNKTUVWjQGEBERcVFMJXuq6ftEguABB+L0UZOFcVeFYAAAAASUVORK5CYII=", servingUrl: "https://lh3.googleusercontent.com/8DcV-wSbJBKHjx-cmwagHA3SspBD4P3ScvvmZZog37NoIdaprLI5vt2nY7nfrqeCFVLFa0YTcL7jR3soFjmRqbNiESGeZ1Nm", imageMeta: { width: "", height: "" } } } }, class: { imageRadius: { value: "img-none" }, imageBorder: { value: "img-border-none" }, imageShadow: { value: "img-shadow-none" }, imageEffects: { value: "img-effects-none" } }, styles: { paddingLeft: { unit: "px", value: 10 }, paddingRight: { value: 10, unit: "px" }, paddingTop: { unit: "px", value: "10" }, paddingBottom: { unit: "px", value: "10" }, backgroundColor: { value: "var(--transparent)" }, opacity: { value: "1" }, textAlign: { value: "center" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "image-VMrslNNuUy", type: "element", child: [], meta: "image", tagName: "c-image", title: "Image", tag: "" }, { extra: { nodeId: "csub-heading-bQudNu4eBG", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<h2>FREQUENTLY ASKED QUESTIONS</h2>" }, mobileFontSize: { value: 46, unit: "px" }, desktopFontSize: { value: 46, unit: "px" }, typography: { value: "var(--headlinefont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } }, customClass: { value: [] } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal", desktop: "400" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "center" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginLeft: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 } }, customCss: [], id: "sub-heading-bQudNu4eBG", type: "element", child: [], mobileStyles: {}, mobileWrapper: {}, meta: "sub-heading", tagName: "c-sub-heading", title: "Sub Headline", tag: "h3" }], sequence: 9, pageId: "FYBFsBAezEtsY0uXW4IN", funnelId: "pK3yy9CFapchugRrgjgq", locationId: "Gc2kgDDpABIR8QDyJ6rf", isGlobal: true, general: { colors: [{ label: "Black", value: "#000000" }, { label: "Transparent", value: "transparent" }], fontsForPreview: ["'Lato'", "'Oswald'"], rootVars: { "--'lato'": "'Lato'", "--'oswald'": "'Oswald'", "--black": "#000000", "--transparent": "transparent" }, sectionStyles: `:root{--black:#000000;--transparent:transparent}.hl_page-preview--content .col-TgLmpbuj1O,.hl_page-preview--content .row-B3nlfUUX-J,.hl_page-preview--content .section-zJJ17L55C_{padding:40px 0;margin:0;background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .col-TgLmpbuj1O,.hl_page-preview--content .row-B3nlfUUX-J{margin:0 auto;padding:15px 0;width:100%}.hl_page-preview--content .col-TgLmpbuj1O{padding:0 10px 0 5px;margin:0}.hl_page-preview--content .cfaq-hC9kdZlk9d{font-family:var(--contentfont);faq-open-title-text-color:var(--white);faq-open-title-background-color:var(--my-custom-color-44);faq-divider-color:var(--my-custom-color-16);faq-content-text-color:var(--my-custom-color-26);faq-open-background-color:var(--white);faq-closed-title-text-color:var(--my-custom-color-26);faq-closed-title-background-color:var(--my-custom-color-60);faq-expand-all-button-text-color:var(--my-custom-color-44);faq-expand-all-button-border-color:#d1d5db;faq-expand-all-button-background-color:var(--transparent);link-text-color:#3b82f6;faq-heading-font-family:var(--headlinefont);faq-content-font-family:var(--contentfont);padding:0;margin:0;border-color:var(--black);border-style:solid;border-width:2px;font-weight:700;font-weight-sub:undefined}.hl_page-preview--content .col-qmvDyClR0p{padding:0 5px 0 10px;background-color:var(--transparent);width:100%;border-color:var(--black);border-width:2px;border-style:solid;margin:0}.hl_page-preview--content .cfaq-xt8Q865Gfb{font-family:var(--contentfont);faq-open-title-text-color:var(--white);faq-open-title-background-color:var(--my-custom-color-44);faq-divider-color:var(--my-custom-color-16);faq-content-text-color:var(--my-custom-color-26);faq-open-background-color:var(--white);faq-closed-title-text-color:var(--my-custom-color-26);faq-closed-title-background-color:var(--my-custom-color-60);faq-expand-all-button-text-color:var(--my-custom-color-44);faq-expand-all-button-border-color:#d1d5db;faq-expand-all-button-background-color:var(--my-custom-color-26);link-text-color:#3b82f6;faq-heading-font-family:var(--headlinefont);faq-content-font-family:var(--contentfont);padding:0;margin:0;border-color:var(--black);border-style:solid;border-width:2px;font-weight:700;font-weight-sub:undefined}.hl_page-preview--content .col-uV9_D99Gtm,.hl_page-preview--content .row-zwaPMb51Ig{margin:0 auto;padding:15px 0;background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid;width:100%}.hl_page-preview--content .col-uV9_D99Gtm{padding:10px 5px;margin:0}.hl_page-preview--content .image-VMrslNNuUy{margin-top:0;margin-bottom:0}.hl_page-preview--content .cimage-VMrslNNuUy{padding:10px;background-color:var(--transparent);opacity:1;text-align:center}.hl_page-preview--content .sub-heading-bQudNu4eBG{margin:0}.hl_page-preview--content .csub-heading-bQudNu4eBG{font-family:var(--headlinefont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:center}#section-zJJ17L55C_>.inner{max-width:1170px}#col-TgLmpbuj1O>.inner{flex-direction:column;justify-content:flex-start;align-items:inherit;flex-wrap:nowrap}#faq-hC9kdZlk9d .hl-faq-child-heading-text{font-size:20px}#faq-hC9kdZlk9d .hl-faq-child-heading-text .ProseMirror h4,#faq-hC9kdZlk9d .hl-faq-child-heading-text h4,#faq-hC9kdZlk9d .hl-faq-child-item-text .ProseMirror p,#faq-hC9kdZlk9d .hl-faq-child-item-text p{font-weight:400!important}#faq-hC9kdZlk9d .hl-faq-child-item-text{font-size:15px}#faq-hC9kdZlk9d .faq-separated-child{border-radius:10px}#faq-hC9kdZlk9d .faq-separated-child,#faq-hC9kdZlk9d .faq-separated-child.active{border:1.5px solid var(--my-custom-color-16)}#faq-hC9kdZlk9d .faq-contained-child{border:1px solid var(--my-custom-color-16)}#faq-hC9kdZlk9d .faq-simple-child .hl-faq-child-heading{border-top:1px solid var(--my-custom-color-16)}#faq-hC9kdZlk9d .faq-separated-child .hl-faq-child-heading{border-radius:10px}#faq-hC9kdZlk9d .faq-separated-child .hl-faq-child-heading.active{border-radius:10px 10px 0 0}#faq-hC9kdZlk9d .hl-faq-child-heading{background-color:var(--my-custom-color-60)}#faq-hC9kdZlk9d .hl-faq-child-heading.active{background-color:var(--my-custom-color-44)}#faq-hC9kdZlk9d .hl-faq-child-heading .hl-faq-child-head .hl-faq-child-heading-text,#faq-hC9kdZlk9d .hl-faq-child-heading .hl-faq-child-heading-icon{color:var(--my-custom-color-26)}#faq-hC9kdZlk9d .hl-faq-child-heading.active .hl-faq-child-head .hl-faq-child-heading-text,#faq-hC9kdZlk9d .hl-faq-child-heading.active .hl-faq-child-heading-icon{color:var(--white)}#faq-hC9kdZlk9d .hl-faq-child-heading .hl-faq-child-head .hl-faq-child-heading-text{line-height:1.5;font-family:var(--headlinefont)}#faq-hC9kdZlk9d .hl-faq-child .hl-faq-child-panel{background-color:var(--white)}#faq-hC9kdZlk9d .faq-separated-child .hl-faq-child-panel{border-radius:0}#faq-hC9kdZlk9d .faq-separated-child.active .hl-faq-child-panel{border-radius:0 0 10px 10px}#faq-hC9kdZlk9d .hl-faq-child .hl-faq-child-panel .hl-faq-child-item-text{color:var(--my-custom-color-26);line-height:1.5}#faq-hC9kdZlk9d .hl-faq-child-panel{display:flex;padding:15px;overflow:hidden}#faq-hC9kdZlk9d .hl-faq-child-panel .item-text{min-width:80%;margin:0;font-family:var(--contentfont)}#faq-hC9kdZlk9d .hl-faq-child-panel .item-img{padding:.5em;max-width:20%;height:100%}@media screen and (min-width:0px) and (max-width:480px){#faq-hC9kdZlk9d .hl-faq-child-panel{display:grid;padding:15px}#faq-hC9kdZlk9d .hl-faq-child-panel .item-img{max-width:100%;width:100%;margin:0;padding:0;height:auto}#faq-hC9kdZlk9d .hl-faq-child-panel .item-text{max-width:100%;width:100%;margin:0;height:auto;padding:0 0 5px}#faq-hC9kdZlk9d .hl-faq-child-heading-text{font-size:15px}#faq-hC9kdZlk9d .hl-faq-child-heading-text .ProseMirror h4,#faq-hC9kdZlk9d .hl-faq-child-heading-text h4,#faq-hC9kdZlk9d .hl-faq-child-item-text .ProseMirror p,#faq-hC9kdZlk9d .hl-faq-child-item-text p{font-weight:undefined!important}#faq-hC9kdZlk9d .hl-faq-child-item-text{font-size:12px}}#faq-hC9kdZlk9d .hl-faq-child-heading .hl-faq-child-heading-icon:before,#faq-xt8Q865Gfb .hl-faq-child-heading .hl-faq-child-heading-icon:before{content:"\uF078"!important;font-family:"Font Awesome 5 Free"}#faq-hC9kdZlk9d .hl-faq-child-heading.active .hl-faq-child-heading-icon:before,#faq-xt8Q865Gfb .hl-faq-child-heading.active .hl-faq-child-heading-icon:before{content:"\uF077"!important;font-family:"Font Awesome 5 Free"}#faq-hC9kdZlk9d .expand-collapse-all-button{color:var(--my-custom-color-44);border:1px solid #d1d5db;background-color:var(--transparent)}#faq-hC9kdZlk9d a,#faq-xt8Q865Gfb a{color:#3b82f6!important;text-decoration:none!important}#col-qmvDyClR0p>.inner{flex-direction:column;justify-content:flex-start;align-items:inherit;flex-wrap:nowrap}#faq-xt8Q865Gfb .hl-faq-child-heading-text{font-size:20px}#faq-xt8Q865Gfb .hl-faq-child-heading-text .ProseMirror h4,#faq-xt8Q865Gfb .hl-faq-child-heading-text h4,#faq-xt8Q865Gfb .hl-faq-child-item-text .ProseMirror p,#faq-xt8Q865Gfb .hl-faq-child-item-text p{font-weight:400!important}#faq-xt8Q865Gfb .hl-faq-child-item-text{font-size:15px}#faq-xt8Q865Gfb .faq-separated-child{border-radius:10px}#faq-xt8Q865Gfb .faq-separated-child,#faq-xt8Q865Gfb .faq-separated-child.active{border:1.5px solid var(--my-custom-color-16)}#faq-xt8Q865Gfb .faq-contained-child{border:1px solid var(--my-custom-color-16)}#faq-xt8Q865Gfb .faq-simple-child .hl-faq-child-heading{border-top:1px solid var(--my-custom-color-16)}#faq-xt8Q865Gfb .faq-separated-child .hl-faq-child-heading{border-radius:10px}#faq-xt8Q865Gfb .faq-separated-child .hl-faq-child-heading.active{border-radius:10px 10px 0 0}#faq-xt8Q865Gfb .hl-faq-child-heading{background-color:var(--my-custom-color-60)}#faq-xt8Q865Gfb .hl-faq-child-heading.active{background-color:var(--my-custom-color-44)}#faq-xt8Q865Gfb .hl-faq-child-heading .hl-faq-child-head .hl-faq-child-heading-text,#faq-xt8Q865Gfb .hl-faq-child-heading .hl-faq-child-heading-icon{color:var(--my-custom-color-26)}#faq-xt8Q865Gfb .hl-faq-child-heading.active .hl-faq-child-head .hl-faq-child-heading-text,#faq-xt8Q865Gfb .hl-faq-child-heading.active .hl-faq-child-heading-icon{color:var(--white)}#faq-xt8Q865Gfb .hl-faq-child-heading .hl-faq-child-head .hl-faq-child-heading-text{line-height:1.5;font-family:var(--headlinefont)}#faq-xt8Q865Gfb .hl-faq-child .hl-faq-child-panel{background-color:var(--white)}#faq-xt8Q865Gfb .faq-separated-child .hl-faq-child-panel{border-radius:0}#faq-xt8Q865Gfb .faq-separated-child.active .hl-faq-child-panel{border-radius:0 0 10px 10px}#faq-xt8Q865Gfb .hl-faq-child .hl-faq-child-panel .hl-faq-child-item-text{color:var(--my-custom-color-26);line-height:1.5}#faq-xt8Q865Gfb .hl-faq-child-panel{display:flex;padding:15px;overflow:hidden}#faq-xt8Q865Gfb .hl-faq-child-panel .item-text{min-width:80%;margin:0;font-family:var(--contentfont)}#faq-xt8Q865Gfb .hl-faq-child-panel .item-img{padding:.5em;max-width:20%;height:100%}@media screen and (min-width:0px) and (max-width:480px){#faq-xt8Q865Gfb .hl-faq-child-panel{display:grid;padding:15px}#faq-xt8Q865Gfb .hl-faq-child-panel .item-img{max-width:100%;width:100%;margin:0;padding:0;height:auto}#faq-xt8Q865Gfb .hl-faq-child-panel .item-text{max-width:100%;width:100%;margin:0;height:auto;padding:0 0 5px}#faq-xt8Q865Gfb .hl-faq-child-heading-text{font-size:15px}#faq-xt8Q865Gfb .hl-faq-child-heading-text .ProseMirror h4,#faq-xt8Q865Gfb .hl-faq-child-heading-text h4,#faq-xt8Q865Gfb .hl-faq-child-item-text .ProseMirror p,#faq-xt8Q865Gfb .hl-faq-child-item-text p{font-weight:undefined!important}#faq-xt8Q865Gfb .hl-faq-child-item-text{font-size:12px}}#faq-xt8Q865Gfb .expand-collapse-all-button{color:var(--my-custom-color-44);border:1px solid #d1d5db;background-color:var(--my-custom-color-26)}#col-uV9_D99Gtm>.inner{flex-direction:column;justify-content:center;align-items:inherit;flex-wrap:nowrap}.sub-heading-bQudNu4eBG{font-weight:400}.sub-heading-bQudNu4eBG em,.sub-heading-bQudNu4eBG strong,.sub-heading-bQudNu4eBG u{color:var(--text-color)!important}.sub-heading-bQudNu4eBG a,.sub-heading-bQudNu4eBG a *{color:var(--link-color)!important;text-decoration:none}.sub-heading-bQudNu4eBG a:hover{text-decoration:underline}@media screen and (min-width:0px) and (max-width:480px){.sub-heading-bQudNu4eBG h1,.sub-heading-bQudNu4eBG h2,.sub-heading-bQudNu4eBG h3,.sub-heading-bQudNu4eBG h4,.sub-heading-bQudNu4eBG h5,.sub-heading-bQudNu4eBG h6,.sub-heading-bQudNu4eBG ul li,.sub-heading-bQudNu4eBG.text-output{font-size:46px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.sub-heading-bQudNu4eBG h1,.sub-heading-bQudNu4eBG h2,.sub-heading-bQudNu4eBG h3,.sub-heading-bQudNu4eBG h4,.sub-heading-bQudNu4eBG h5,.sub-heading-bQudNu4eBG h6,.sub-heading-bQudNu4eBG ul li,.sub-heading-bQudNu4eBG.text-output{font-size:46px!important;font-weight:undefined}}.sub-heading-bQudNu4eBG.text-output h1:first-child:before,.sub-heading-bQudNu4eBG.text-output h2:first-child:before,.sub-heading-bQudNu4eBG.text-output h3:first-child:before,.sub-heading-bQudNu4eBG.text-output h4:first-child:before,.sub-heading-bQudNu4eBG.text-output h5:first-child:before,.sub-heading-bQudNu4eBG.text-output h6:first-child:before,.sub-heading-bQudNu4eBG.text-output p:first-child:before{color:var(--text-color);content:'\\';
|
|
10086
|
+
font-family: '';margin-right:5px;font-weight:700}` } }, map: { id: "section-k4A5oCSjW", metaData: { id: "section-k4A5oCSjW", type: "section", child: ["row-pQ0EjtpzhM"], class: { width: { value: "fullSection" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingBottom: { unit: "px", value: 20 }, paddingTop: { unit: "px", value: 20 }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, backgroundColor: { value: "var(--my-custom-color-16)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { sticky: { value: "noneSticky" }, visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, allowRowMaxWidth: { value: true } }, wrapper: {}, meta: "section", tagName: "c-section", title: "Map", _id: "section-k4A5oCSjW", isGlobal: true }, elements: [{ id: "row-pQ0EjtpzhM", type: "row", child: ["col-avDBDXfRP", "col-BumGktCM_n"], class: { alignRow: { value: "row-align-center" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 15 }, paddingBottom: { unit: "px", value: 15 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, rowWidth: { value: 100, unit: "%" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-row", meta: "row", title: "2 Column Row" }, { id: "col-avDBDXfRP", type: "col", child: ["map-tptsa5-Qnk"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 5 }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: "100", unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "1st Column" }, { extra: { nodeId: "cmap-tptsa5-Qnk", visibility: { value: { hideDesktop: false, hideMobile: false } }, mapScale: { value: true }, mapMarkerColor: { value: "var(--red)" }, mapZoom: { value: 13 }, mapLocation: { value: { name: "New York, NY, USA", placeId: "ChIJOwg_06VPwokRYv534QaPC8g", lat: 40.7127753, lng: -74.0059728, url: "https://firebasestorage.googleapis.com/v0/b/highlevel-backend.appspot.com/o/location%2FHdI06zRMberoHhoALSNH%2Fimages%2FWcJKBDYHBY2lXZHxN2EE%2FChIJOwg_06VPwokRYv534QaPC8g%2Fmap-tptsa5-Qnk.jpg?alt=media" } }, mapType: { value: "roadmap" }, mapWidth: { value: "640" }, mapHeight: { value: "500" }, newTab: { value: false }, customClass: { value: [] } }, class: {}, styles: { textAlign: { value: "center" } }, wrapper: {}, customCss: [], id: "map-tptsa5-Qnk", type: "element", child: [], meta: "map", tagName: "c-map", title: "Map", tag: "" }, { id: "col-BumGktCM_n", type: "col", child: ["heading-IUykdV_et", "divider-rwCGPGeRg", "paragraph-5ArwjI1rg", "paragraph-1i2Ja23aQ", "paragraph-pMPMaLeA3"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: "25" }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: "100", unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "2nd Column" }, { extra: { nodeId: "cheading-IUykdV_et", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>CONTACT US</p>" }, mobileFontSize: { value: "22", unit: "px" }, desktopFontSize: { value: "24", unit: "px" }, typography: { value: "var(--headlinefont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "heading-IUykdV_et", type: "element", child: [], meta: "heading", tagName: "c-heading", title: "Headline", tag: "h1" }, { extra: { nodeId: "cdivider-rwCGPGeRg", visibility: { value: { hideDesktop: false, hideMobile: false } }, dividerProperties: { value: { width: "50%", height: "1px", borderStyle: "solid", align: "left", color: "var(--my-custom-color-60)" } } }, class: {}, styles: { paddingTop: { unit: "px", value: 5 }, paddingBottom: { unit: "px", value: 5 } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 } }, customCss: [], id: "divider-rwCGPGeRg", type: "element", child: [], meta: "divider", tagName: "c-divider", title: "Divider", tag: "" }, { extra: { nodeId: "cparagraph-5ArwjI1rg", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>{{location.phone}}</p>" }, mobileFontSize: { value: 14, unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "phone-alt", unicode: "f879", fontFamily: "Font Awesome 5 Free", color: "var(--black)" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--my-custom-color-26)" }, iconColor: { value: "var(--my-custom-color-44)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: "0" }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: "10" }, paddingBottom: { unit: "px", value: "10" }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-5ArwjI1rg", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { extra: { nodeId: "cparagraph-1i2Ja23aQ", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>{{location.full_address}}</p>" }, mobileFontSize: { value: 14, unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "map-marker-alt", unicode: "f3c5", fontFamily: "Font Awesome 5 Free", color: "var(--black)" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--my-custom-color-26)" }, iconColor: { value: "var(--my-custom-color-44)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: "0" }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: "10" }, paddingBottom: { unit: "px", value: "10" }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-1i2Ja23aQ", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { extra: { nodeId: "cparagraph-pMPMaLeA3", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>{{location.email}}</p>" }, mobileFontSize: { value: 14, unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "envelope", unicode: "f0e0", fontFamily: "Font Awesome 5 Free", color: "var(--black)" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--my-custom-color-44)" }, iconColor: { value: "var(--my-custom-color-44)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: "0" }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: "10" }, paddingBottom: { unit: "px", value: "10" }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-pMPMaLeA3", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }], sequence: 10, pageId: "FYBFsBAezEtsY0uXW4IN", funnelId: "pK3yy9CFapchugRrgjgq", locationId: "Gc2kgDDpABIR8QDyJ6rf", isGlobal: true, general: { colors: [{ label: "Black", value: "#000000" }, { label: "Red", value: "#e93d3d" }, { label: "Transparent", value: "transparent" }, { label: "my-custom-color-26", value: "#434445", name: "My Custom Color 26" }, { label: "my-custom-color-44", name: "My Custom Color 44", value: "#ec606a" }, { value: "#f3f3f3", name: "My Custom Color 16", label: "my-custom-color-16" }], fontsForPreview: ["'Oswald'", "'Lato'"], rootVars: { "--'oswald'": "'Oswald'", "--'lato'": "'Lato'", "--black": "#000000", "--red": "#e93d3d", "--transparent": "transparent", "--my-custom-color-26": "#434445", "--my-custom-color-44": "#ec606a", "--my-custom-color-16": "#f3f3f3" }, sectionStyles: `:root{--black:#000000;--red:#e93d3d;--transparent:transparent;--my-custom-color-26:#434445;--my-custom-color-44:#ec606a;--my-custom-color-16:#f3f3f3}.hl_page-preview--content .col-avDBDXfRP .inner,.hl_page-preview--content .row-pQ0EjtpzhM,.hl_page-preview--content .section-k4A5oCSjW{padding:20px 0;margin-top:0;margin-bottom:0;background-color:var(--my-custom-color-16);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .col-avDBDXfRP .inner,.hl_page-preview--content .row-pQ0EjtpzhM{padding:15px 0;background-color:var(--transparent);width:100%}.hl_page-preview--content .col-avDBDXfRP{width:100%}.hl_page-preview--content .col-avDBDXfRP .inner{padding:10px 5px}.hl_page-preview--content .cmap-tptsa5-Qnk{text-align:center}.hl_page-preview--content .col-BumGktCM_n{width:100%}.hl_page-preview--content .col-BumGktCM_n .inner{padding:10px 5px 10px 25px;width:100%;margin-top:0;margin-bottom:0}.hl_page-preview--content .heading-IUykdV_et{margin-top:0;margin-bottom:0}.hl_page-preview--content .cheading-IUykdV_et,.hl_page-preview--content .col-BumGktCM_n .inner{background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .cheading-IUykdV_et{font-family:var(--headlinefont);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;line-height:1.3em;letter-spacing:0;text-align:left}.hl_page-preview--content .divider-rwCGPGeRg{margin-top:0;margin-bottom:0;padding-top:10px;padding-bottom:10px}.hl_page-preview--content .cdivider-rwCGPGeRg{padding-top:5px;padding-bottom:5px}.hl_page-preview--content .paragraph-5ArwjI1rg{margin-top:0;margin-bottom:0}.hl_page-preview--content .cparagraph-5ArwjI1rg{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--my-custom-color-44);font-weight:400;padding:10px 0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}.hl_page-preview--content .paragraph-1i2Ja23aQ{margin-top:0;margin-bottom:0}.hl_page-preview--content .cparagraph-1i2Ja23aQ{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--my-custom-color-44);font-weight:400;padding:10px 0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}.hl_page-preview--content .paragraph-pMPMaLeA3{margin-top:0;margin-bottom:0}.hl_page-preview--content .cparagraph-pMPMaLeA3{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--my-custom-color-44);font-weight:400;padding:10px 0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}#section-k4A5oCSjW>.inner{max-width:100%}#col-BumGktCM_n>.inner,#col-avDBDXfRP>.inner{flex-direction:column;justify-content:center;align-items:inherit;flex-wrap:nowrap}.heading-IUykdV_et,.paragraph-1i2Ja23aQ,.paragraph-5ArwjI1rg,.paragraph-pMPMaLeA3{font-weight:undefined}.heading-IUykdV_et em,.heading-IUykdV_et strong,.heading-IUykdV_et u,.paragraph-1i2Ja23aQ em,.paragraph-1i2Ja23aQ strong,.paragraph-1i2Ja23aQ u,.paragraph-5ArwjI1rg em,.paragraph-5ArwjI1rg strong,.paragraph-5ArwjI1rg u,.paragraph-pMPMaLeA3 em,.paragraph-pMPMaLeA3 strong,.paragraph-pMPMaLeA3 u{color:var(--text-color)!important}.heading-IUykdV_et a,.heading-IUykdV_et a *{color:var(--link-color)!important;text-decoration:none}.heading-IUykdV_et a:hover,.paragraph-1i2Ja23aQ a:hover,.paragraph-5ArwjI1rg a:hover,.paragraph-pMPMaLeA3 a:hover{text-decoration:underline}@media screen and (min-width:0px) and (max-width:480px){.heading-IUykdV_et h1,.heading-IUykdV_et h2,.heading-IUykdV_et h3,.heading-IUykdV_et h4,.heading-IUykdV_et h5,.heading-IUykdV_et h6,.heading-IUykdV_et ul li,.heading-IUykdV_et.text-output{font-size:22px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.heading-IUykdV_et h1,.heading-IUykdV_et h2,.heading-IUykdV_et h3,.heading-IUykdV_et h4,.heading-IUykdV_et h5,.heading-IUykdV_et h6,.heading-IUykdV_et ul li,.heading-IUykdV_et.text-output{font-size:24px!important;font-weight:undefined}}.heading-IUykdV_et.text-output h1:first-child:before,.heading-IUykdV_et.text-output h2:first-child:before,.heading-IUykdV_et.text-output h3:first-child:before,.heading-IUykdV_et.text-output h4:first-child:before,.heading-IUykdV_et.text-output h5:first-child:before,.heading-IUykdV_et.text-output h6:first-child:before,.heading-IUykdV_et.text-output p:first-child:before{color:var(--text-color);content:'\\';
|
|
10087
|
+
font-family: '';margin-right:5px;font-weight:700}.divider-rwCGPGeRg .divider-element{width:50%;border-top:1px solid var(--my-custom-color-60);margin:0 auto 0 0}.paragraph-1i2Ja23aQ a,.paragraph-1i2Ja23aQ a *,.paragraph-5ArwjI1rg a,.paragraph-5ArwjI1rg a *{color:var(--my-custom-color-26)!important;text-decoration:none}@media screen and (min-width:0px) and (max-width:480px){.paragraph-5ArwjI1rg h1,.paragraph-5ArwjI1rg h2,.paragraph-5ArwjI1rg h3,.paragraph-5ArwjI1rg h4,.paragraph-5ArwjI1rg h5,.paragraph-5ArwjI1rg h6,.paragraph-5ArwjI1rg ul li,.paragraph-5ArwjI1rg.text-output{font-size:14px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-5ArwjI1rg h1,.paragraph-5ArwjI1rg h2,.paragraph-5ArwjI1rg h3,.paragraph-5ArwjI1rg h4,.paragraph-5ArwjI1rg h5,.paragraph-5ArwjI1rg h6,.paragraph-5ArwjI1rg ul li,.paragraph-5ArwjI1rg.text-output{font-size:16px!important;font-weight:undefined}}.paragraph-5ArwjI1rg.text-output h1:first-child:before,.paragraph-5ArwjI1rg.text-output h2:first-child:before,.paragraph-5ArwjI1rg.text-output h3:first-child:before,.paragraph-5ArwjI1rg.text-output h4:first-child:before,.paragraph-5ArwjI1rg.text-output h5:first-child:before,.paragraph-5ArwjI1rg.text-output h6:first-child:before,.paragraph-5ArwjI1rg.text-output p:first-child:before{color:var(--my-custom-color-44);content:"\uF879";font-family:"Font Awesome 5 Free";margin-right:5px;font-weight:700}@media screen and (min-width:0px) and (max-width:480px){.paragraph-1i2Ja23aQ h1,.paragraph-1i2Ja23aQ h2,.paragraph-1i2Ja23aQ h3,.paragraph-1i2Ja23aQ h4,.paragraph-1i2Ja23aQ h5,.paragraph-1i2Ja23aQ h6,.paragraph-1i2Ja23aQ ul li,.paragraph-1i2Ja23aQ.text-output{font-size:14px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-1i2Ja23aQ h1,.paragraph-1i2Ja23aQ h2,.paragraph-1i2Ja23aQ h3,.paragraph-1i2Ja23aQ h4,.paragraph-1i2Ja23aQ h5,.paragraph-1i2Ja23aQ h6,.paragraph-1i2Ja23aQ ul li,.paragraph-1i2Ja23aQ.text-output{font-size:16px!important;font-weight:undefined}}.paragraph-1i2Ja23aQ.text-output h1:first-child:before,.paragraph-1i2Ja23aQ.text-output h2:first-child:before,.paragraph-1i2Ja23aQ.text-output h3:first-child:before,.paragraph-1i2Ja23aQ.text-output h4:first-child:before,.paragraph-1i2Ja23aQ.text-output h5:first-child:before,.paragraph-1i2Ja23aQ.text-output h6:first-child:before,.paragraph-1i2Ja23aQ.text-output p:first-child:before{color:var(--my-custom-color-44);content:"\uF3C5";font-family:"Font Awesome 5 Free";margin-right:5px;font-weight:700}.paragraph-pMPMaLeA3 a,.paragraph-pMPMaLeA3 a *{color:var(--my-custom-color-44)!important;text-decoration:none}@media screen and (min-width:0px) and (max-width:480px){.paragraph-pMPMaLeA3 h1,.paragraph-pMPMaLeA3 h2,.paragraph-pMPMaLeA3 h3,.paragraph-pMPMaLeA3 h4,.paragraph-pMPMaLeA3 h5,.paragraph-pMPMaLeA3 h6,.paragraph-pMPMaLeA3 ul li,.paragraph-pMPMaLeA3.text-output{font-size:14px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-pMPMaLeA3 h1,.paragraph-pMPMaLeA3 h2,.paragraph-pMPMaLeA3 h3,.paragraph-pMPMaLeA3 h4,.paragraph-pMPMaLeA3 h5,.paragraph-pMPMaLeA3 h6,.paragraph-pMPMaLeA3 ul li,.paragraph-pMPMaLeA3.text-output{font-size:16px!important;font-weight:undefined}}.paragraph-pMPMaLeA3.text-output h1:first-child:before,.paragraph-pMPMaLeA3.text-output h2:first-child:before,.paragraph-pMPMaLeA3.text-output h3:first-child:before,.paragraph-pMPMaLeA3.text-output h4:first-child:before,.paragraph-pMPMaLeA3.text-output h5:first-child:before,.paragraph-pMPMaLeA3.text-output h6:first-child:before,.paragraph-pMPMaLeA3.text-output p:first-child:before{color:var(--my-custom-color-44);content:"\uF0E0";font-family:"Font Awesome 5 Free";margin-right:5px;font-weight:700}` } }, footer: { id: "section-W2_3qK993", metaData: { id: "section-W2_3qK993", type: "section", child: ["row-wuNraoqgsg"], class: { width: { value: "fullSection" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingBottom: { unit: "px", value: 20 }, paddingTop: { unit: "px", value: 20 }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, backgroundColor: { value: "var(--white)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { sticky: { value: "noneSticky" }, visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, allowRowMaxWidth: { value: false } }, wrapper: {}, meta: "section", tagName: "c-section", title: "Footer", _id: "section-W2_3qK993", isGlobal: true }, elements: [{ id: "row-wuNraoqgsg", type: "row", child: ["col-6LxuCvSGc", "col-kQXDW5avz2", "col-W91BEMl7R9"], class: { alignRow: { value: "row-align-center" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 15 }, paddingBottom: { unit: "px", value: 15 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, rowWidth: { value: 100, unit: "%" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-row", meta: "row", title: "3 Column Row" }, { id: "col-6LxuCvSGc", type: "col", child: ["image-Fuy-QQVmM"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 5 }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: 20.8, unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "1st Column" }, { extra: { nodeId: "cimage-Fuy-QQVmM", visibility: { value: { hideDesktop: false, hideMobile: false } }, imageActions: { value: "none" }, visitWebsite: { value: { url: "", newTab: false } }, imageProperties: { value: { width: "190px", height: "", url: "https://storage.googleapis.com/msgsndr/EVTjG29VnVlvwn3SRGve/media/fee997f8-92c7-4ee2-b0c1-3536b94b71a7.png", altText: "", compression: true, placeholderBase64: "", servingUrl: "", imageMeta: "" } } }, class: { imageRadius: { value: "img-none" }, imageBorder: { value: "img-border-none" }, imageShadow: { value: "img-shadow-none" }, imageEffects: { value: "img-effects-none" } }, styles: { paddingLeft: { unit: "px", value: 10 }, paddingRight: { value: 10, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, opacity: { value: "1" }, textAlign: { value: "center" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "image-Fuy-QQVmM", type: "element", child: [], meta: "image", tagName: "c-image", title: "Image", tag: "" }, { id: "col-kQXDW5avz2", type: "col", child: ["paragraph-R6ogZueLM"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 5 }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: 60.1, unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "2nd Column" }, { extra: { nodeId: "cparagraph-R6ogZueLM", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>\xA9 {{right_now.year}} All Rights Reserved. Terms of Use and Privacy Policy</p>" }, mobileFontSize: { value: 14, unit: "px" }, desktopFontSize: { value: "16", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--overlay)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "center" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "paragraph-R6ogZueLM", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { id: "col-W91BEMl7R9", type: "col", child: ["social-icons-zmn5hzO2aL"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { unit: "px", value: 0 }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, backgroundColor: { value: "var(--transparent)" }, width: { value: 19.1, unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "row" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "center" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "3rd Column" }, { extra: { nodeId: "csocial-icons-zmn5hzO2aL", socials: { value: [{ id: "facebook", label: "Facebook", link: "facebook.com", newWindow: true, nofollow: false, icon: "https://stcdn.leadconnectorhq.com/funnel/icons/brand/facebook-brand.svg" }, { id: "instagram", label: "Instagram", link: "instagram.com", newWindow: true, nofollow: false, icon: "https://stcdn.leadconnectorhq.com/funnel/icons/brand/instagram-brand.svg" }, { id: "youtube", label: "Youtube", link: "youtube.com", newWindow: true, nofollow: false, icon: "https://stcdn.leadconnectorhq.com/funnel/icons/brand/youtube-brand.svg" }] }, displayType: { value: "icon" }, theme: { value: "dark" }, align: { value: "center" }, iconSize: { value: { height: 25, width: 25 } }, customClass: { value: [] }, visibility: { value: { hideDesktop: false, hideMobile: false } } }, class: {}, styles: { fontFamily: { value: "Inter" }, fontSize: { value: 12, unit: "px" }, fontWeight: { value: 500, desktop: "Normal" }, color: { value: "#000000" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { unit: "px", value: 0 }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 }, marginLeft: { unit: "px", value: 0 } }, wrapper: {}, mobileStyles: {}, mobileWrapper: {}, mobileExtra: {}, customCss: [], id: "social-icons-zmn5hzO2aL", version: 2, type: "element", child: [], meta: "social-icons", tagName: "c-social-icons", title: "Social Icons", tag: "" }], sequence: 11, pageId: "FYBFsBAezEtsY0uXW4IN", funnelId: "pK3yy9CFapchugRrgjgq", locationId: "Gc2kgDDpABIR8QDyJ6rf", isGlobal: true, general: { colors: [{ label: "White", value: "#ffffff" }, { label: "Black", value: "#000000" }, { label: "Transparent", value: "transparent" }, { value: "rgba(0, 0, 0, 0.5)", label: "Overlay" }], fontsForPreview: ["'Lato'"], rootVars: { "--'lato'": "'Lato'", "--white": "#ffffff", "--black": "#000000", "--transparent": "transparent", "--overlay": "rgba(0, 0, 0, 0.5)" }, sectionStyles: ":root{--white:#ffffff;--black:#000000;--transparent:transparent;--overlay:rgba(0, 0, 0, 0.5)}.hl_page-preview--content .section-W2_3qK993{padding:20px 0;margin-top:0;margin-bottom:0;background-color:var(--white);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .col-6LxuCvSGc .inner,.hl_page-preview--content .col-kQXDW5avz2 .inner,.hl_page-preview--content .row-wuNraoqgsg{margin-top:0;margin-bottom:0;padding:15px 0;background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid;width:100%}.hl_page-preview--content .col-6LxuCvSGc{width:20.8%}.hl_page-preview--content .col-6LxuCvSGc .inner,.hl_page-preview--content .col-kQXDW5avz2 .inner{padding:10px 5px;width:20.8%}.hl_page-preview--content .image-Fuy-QQVmM{margin-top:0;margin-bottom:0}.hl_page-preview--content .cimage-Fuy-QQVmM{padding:10px;background-color:var(--transparent);opacity:1;text-align:center}.hl_page-preview--content .col-kQXDW5avz2{width:60.1%}.hl_page-preview--content .col-kQXDW5avz2 .inner{width:60.1%}.hl_page-preview--content .paragraph-R6ogZueLM{margin-top:0;margin-bottom:0}.hl_page-preview--content .col-W91BEMl7R9 .inner,.hl_page-preview--content .cparagraph-R6ogZueLM{padding:0;background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .cparagraph-R6ogZueLM{font-family:var(--contentfont);color:var(--overlay);icon-color:var(--text-color);font-weight:400;opacity:1;text-shadow:0 0 0 transparent;line-height:1.3em;letter-spacing:0;text-align:center}.hl_page-preview--content .col-W91BEMl7R9{width:19.1%}.hl_page-preview--content .col-W91BEMl7R9 .inner{width:19.1%;margin-top:0;margin-bottom:0}.hl_page-preview--content .csocial-icons-zmn5hzO2aL{font-family:Inter;font-size:12px;font-weight:500;color:#000;padding:0;margin:0}#section-W2_3qK993>.inner{max-width:1170px}#col-6LxuCvSGc>.inner,#col-kQXDW5avz2>.inner{flex-direction:column;justify-content:center;align-items:inherit;flex-wrap:nowrap}.paragraph-R6ogZueLM{font-weight:undefined}.paragraph-R6ogZueLM em,.paragraph-R6ogZueLM strong,.paragraph-R6ogZueLM u{color:var(--text-color)!important}.paragraph-R6ogZueLM a,.paragraph-R6ogZueLM a *{color:var(--link-color)!important;text-decoration:none}.paragraph-R6ogZueLM a:hover{text-decoration:underline}@media screen and (min-width:0px) and (max-width:480px){.paragraph-R6ogZueLM h1,.paragraph-R6ogZueLM h2,.paragraph-R6ogZueLM h3,.paragraph-R6ogZueLM h4,.paragraph-R6ogZueLM h5,.paragraph-R6ogZueLM h6,.paragraph-R6ogZueLM ul li,.paragraph-R6ogZueLM.text-output{font-size:14px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-R6ogZueLM h1,.paragraph-R6ogZueLM h2,.paragraph-R6ogZueLM h3,.paragraph-R6ogZueLM h4,.paragraph-R6ogZueLM h5,.paragraph-R6ogZueLM h6,.paragraph-R6ogZueLM ul li,.paragraph-R6ogZueLM.text-output{font-size:16px!important;font-weight:undefined}}.paragraph-R6ogZueLM.text-output h1:first-child:before,.paragraph-R6ogZueLM.text-output h2:first-child:before,.paragraph-R6ogZueLM.text-output h3:first-child:before,.paragraph-R6ogZueLM.text-output h4:first-child:before,.paragraph-R6ogZueLM.text-output h5:first-child:before,.paragraph-R6ogZueLM.text-output h6:first-child:before,.paragraph-R6ogZueLM.text-output p:first-child:before{color:var(--text-color);content:'\\';\n font-family: '';margin-right:5px;font-weight:700}#col-W91BEMl7R9>.inner{flex-direction:row;justify-content:center;align-items:center;flex-wrap:wrap}#social-icons-zmn5hzO2aL .social-media-icon{height:25px;width:25px}#social-icons-zmn5hzO2aL .social-icons-container{justify-content:center}" } }, formShell: { id: "section-XMYhZrXmbd", metaData: { id: "section-XMYhZrXmbd", type: "section", child: ["row-cq8LeYxp43"], class: { width: { value: "fullSection" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingBottom: { unit: "px", value: 20 }, paddingTop: { unit: "px", value: 20 }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginLeft: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { sticky: { value: "noneSticky" }, visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { mediaType: "image", url: "", opacity: "1", options: "bgCover", svgCode: "", videoUrl: "", videoThumbnail: "", videoLoop: true } }, allowRowMaxWidth: { value: false }, customClass: { value: [] } }, wrapper: {}, meta: "section", tagName: "c-section", title: "Section", mobileStyles: {}, mobileWrapper: {}, _id: "section-XMYhZrXmbd" }, elements: [{ id: "row-cq8LeYxp43", type: "row", child: ["col-ot-9fcEoch"], class: { alignRow: { value: "row-align-center" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 15 }, paddingBottom: { unit: "px", value: 15 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { mediaType: "image", url: "", opacity: "1", options: "bgCover", svgCode: "", videoUrl: "", videoThumbnail: "", videoLoop: true } }, rowWidth: { value: 100, unit: "%" }, customClass: { value: [] } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginLeft: { unit: "", value: "auto" }, marginRight: { unit: "", value: "auto" } }, tagName: "c-row", meta: "row", title: "1 Column Row", mobileStyles: {}, mobileWrapper: {} }, { id: "col-ot-9fcEoch", type: "col", child: ["heading-gQ8AnRpz8t", "faq-wEED3pufBs"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 5 }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: "100", unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { mediaType: "image", url: "", opacity: "1", options: "bgCover", svgCode: "", videoUrl: "", videoThumbnail: "", videoLoop: true } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true }, customClass: { value: [] }, elementVersion: { value: 2 } }, wrapper: { marginLeft: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "1st Column", mobileStyles: {}, mobileWrapper: {} }, { extra: { nodeId: "cfaq-wEED3pufBs", faqType: { value: "simple" }, faqList: { value: [{ id: 1, heading: "<h4>What should I expect during my first visit?</h4>", text: "<p>Your first visit begins with a comprehensive consultation where our experts will assess your skin and discuss your aesthetic goals. We will recommend personalized treatment options and answer any questions you may have to ensure you feel comfortable and informed.</p>", showImage: false, image: "https://storage.googleapis.com/msgsndr/knES3eSWYIsc5YSZ3YLl/media/62beef4f9f43b0c53e585a8f.jpeg", active: false, compression: true }, { id: 2, heading: "<h4>Are your treatments safe?</h4>", text: "<p>Yes, all our treatments are performed by highly trained and certified professionals using state-of-the-art equipment and techniques. We prioritize your safety and comfort, adhering to the highest standards of medical care and hygiene.</p>", showImage: false, image: "https://storage.googleapis.com/msgsndr/knES3eSWYIsc5YSZ3YLl/media/62beef4f9f43b0c53e585a8f.jpeg", active: false, compression: true }, { id: 3, heading: "<h4>How do I know which treatment is right for me?</h4>", text: "<p>Our team will guide you through the selection process during your initial consultation. We\u2019ll evaluate your skin type, concerns, and goals to recommend the most suitable treatments to achieve the best results for you.</p>", showImage: false, image: "https://storage.googleapis.com/msgsndr/knES3eSWYIsc5YSZ3YLl/media/62beef4f9f43b0c53e585a8f.jpeg", active: false, compression: true }, { heading: "<h4>Is there any downtime after treatments?</h4>", text: "<p>Most of our treatments are non-invasive or minimally invasive, requiring little to no downtime. However, the recovery time can vary depending on the specific treatment. During your consultation, we will provide detailed post-treatment care instructions and inform you about any necessary recovery time.</p>", showImage: false, image: "https://storage.googleapis.com/msgsndr/knES3eSWYIsc5YSZ3YLl/media/62beef4f9f43b0c53e585a8f.jpeg", active: false, compression: true, id: 4 }, { heading: "<h4>How often should I schedule treatments?</h4>", text: "<p>The frequency of treatments depends on the type of service and your individual needs. Some treatments, like facials, may be done monthly, while others, like laser hair removal, may require a series of sessions spaced several weeks apart. We will create a personalized treatment plan to ensure optimal results.</p>", showImage: false, image: "https://storage.googleapis.com/msgsndr/knES3eSWYIsc5YSZ3YLl/media/62beef4f9f43b0c53e585a8f.jpeg", active: false, compression: true, id: 5 }, { heading: "<h4>Do you offer packages or memberships?</h4>", text: "<p>Yes, we offer a variety of packages and memberships designed to provide you with ongoing care and savings. Our packages bundle popular treatments for comprehensive care, while our memberships offer exclusive benefits and discounts. Contact us to learn more about our current offerings and find the perfect plan for your needs.</p>", showImage: false, image: "https://storage.googleapis.com/msgsndr/knES3eSWYIsc5YSZ3YLl/media/62beef4f9f43b0c53e585a8f.jpeg", active: true, compression: true, id: 6 }] }, typography: { value: "var(--contentfont)" }, faqCustomOptions: { value: { openIcon: { color: "var(--black)", fontFamily: "Font Awesome 5 Free", name: "chevron-down", unicode: "f078" }, closeIcon: { color: "var(--black)", fontFamily: "Font Awesome 5 Free", name: "chevron-up", unicode: "f077" }, iconPosition: "right", lineHeight: "1.5", showImagePopup: true, expandAllToggle: true, expandAll: true, firstItemOpen: false } }, featureHeadlineDesktopFontSize: { value: 20, unit: "px" }, featureHeadlineMobileFontSize: { value: 15, unit: "px" }, desktopFontSize: { value: 15, unit: "px" }, mobileFontSize: { value: 12, unit: "px" }, visibility: { value: { hideDesktop: false, hideMobile: false } }, customClass: { value: [] } }, mobileExtra: {}, class: { borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" }, boxShadow: { value: "none" } }, styles: { faqOpenTitleTextColor: { value: "var(--color-lwjrr318)" }, faqOpenTitleBackgroundColor: { value: "var(--white)" }, faqDividerColor: { value: "var(--color-lwktyvyq)" }, faqContentTextColor: { value: "var(--black)" }, faqOpenBackgroundColor: { value: "var(--white)" }, faqClosedTitleTextColor: { value: "#111827" }, faqClosedTitleBackgroundColor: { value: "var(--white)" }, faqExpandAllButtonTextColor: { value: "var(--color-lwjrr318)" }, faqExpandAllButtonBorderColor: { value: "var(--color-lwktyvyq)" }, faqExpandAllButtonBackgroundColor: { value: "var(--transparent)" }, linkTextColor: { value: "#3B82F6" }, faqHeadingFontFamily: { value: "var(--headlinefont)" }, faqContentFontFamily: { value: "var(--contentfont)" }, paddingLeft: { unit: "px", value: 10 }, paddingRight: { value: 10, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 }, marginLeft: { unit: "px", value: 0 }, borderColor: { value: "var(--black)" }, borderStyle: { value: "solid" }, borderWidth: { value: "2", unit: "px" }, fontWeight: { value: "bold", desktop: "400" }, fontWeightSub: { desktop: "400" } }, wrapper: {}, customCss: [], id: "faq-wEED3pufBs", version: 2, type: "element", child: [], meta: "faq", tagName: "c-faq", title: "FAQ", tag: "" }, { child: [], class: { borderRadius: { value: "radius0" }, borders: { value: "noBorder" }, boxShadow: { value: "none" }, radiusEdge: { value: "none" } }, customCss: [], extra: { desktopFontSize: { unit: "px", value: 32 }, icon: { value: { fontFamily: "", name: "", unicode: "" } }, mobileFontSize: { unit: "px", value: 32 }, nodeId: "cheading-gQ8AnRpz8t", text: { value: "<p><strong>FREQUENTLY ASKED QUESTIONS</strong></p>" }, typography: { value: "var(--headlinefont)" }, visibility: { value: { hideDesktop: false, hideMobile: false } } }, id: "heading-gQ8AnRpz8t", meta: "heading", styles: { backgroundColor: { value: "var(--transparent)" }, boldTextColor: { value: "var(--text-color)" }, borderColor: { value: "var(--black)" }, borderStyle: { value: "solid" }, borderWidth: { unit: "px", value: "2" }, color: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, iconColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, letterSpacing: { unit: "px", value: "0" }, lineHeight: { unit: "em", value: 1.3 }, linkTextColor: { value: "var(--link-color)" }, opacity: { value: "1" }, paddingBottom: { unit: "px", value: 0 }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { unit: "px", value: 0 }, paddingTop: { unit: "px", value: 0 }, textAlign: { value: "center" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, textTransform: { value: "none" }, underlineTextColor: { value: "var(--text-color)" } }, tag: "h1", tagName: "c-heading", title: "Headline", type: "element", wrapper: { marginBottom: { unit: "px", value: 0 }, marginTop: { unit: "px", value: 0 } } }], sequence: 3, pageId: "MNXtMkSaaJpvXyKjwRQr", funnelId: "O1vMlBmnKnMTFb7eObof", locationId: "Gc2kgDDpABIR8QDyJ6rf", general: { colors: [{ label: "Black", value: "#000000" }, { label: "Transparent", value: "transparent" }], fontsForPreview: ["'Lato'", "'Oswald'"], rootVars: { "--'lato'": "'Lato'", "--'oswald'": "'Oswald'", "--black": "#000000", "--transparent": "transparent" }, sectionStyles: `:root{--black:#000000;--transparent:transparent}.hl_page-preview--content .col-ot-9fcEoch,.hl_page-preview--content .row-cq8LeYxp43,.hl_page-preview--content .section-XMYhZrXmbd{padding:20px 0;margin:0;background-color:var(--transparent);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .col-ot-9fcEoch,.hl_page-preview--content .row-cq8LeYxp43{margin:0 auto;padding:15px 0;width:100%}.hl_page-preview--content .col-ot-9fcEoch{padding:10px 5px;margin:0}.hl_page-preview--content .cfaq-wEED3pufBs{font-family:var(--contentfont);faq-open-title-text-color:var(--color-lwjrr318);faq-open-title-background-color:var(--white);faq-divider-color:var(--color-lwktyvyq);faq-content-text-color:var(--black);faq-open-background-color:var(--white);faq-closed-title-text-color:#111827;faq-closed-title-background-color:var(--white);faq-expand-all-button-text-color:var(--color-lwjrr318);faq-expand-all-button-border-color:var(--color-lwktyvyq);faq-expand-all-button-background-color:var(--transparent);link-text-color:#3b82f6;faq-heading-font-family:var(--headlinefont);faq-content-font-family:var(--contentfont);padding:10px;margin:0;border-color:var(--black);border-style:solid;border-width:2px;font-weight:700;font-weight-sub:undefined}.hl_page-preview--content .heading-gQ8AnRpz8t{margin-bottom:0;margin-top:0}.hl_page-preview--content .cheading-gQ8AnRpz8t{font-family:var(--headlinefont);background-color:var(--transparent);border-color:var(--black);border-style:solid;border-width:2px;color:var(--text-color);font-weight:400;icon-color:var(--text-color);letter-spacing:0;line-height:1.3em;opacity:1;padding:0;text-align:center;text-shadow:0 0 0 transparent;text-transform:none}#section-XMYhZrXmbd>.inner{max-width:1170px}#col-ot-9fcEoch>.inner{flex-direction:column;justify-content:center;align-items:inherit;flex-wrap:nowrap}#faq-wEED3pufBs .hl-faq-child-heading-text{font-size:20px}#faq-wEED3pufBs .hl-faq-child-heading-text .ProseMirror h4,#faq-wEED3pufBs .hl-faq-child-heading-text h4,#faq-wEED3pufBs .hl-faq-child-item-text .ProseMirror p,#faq-wEED3pufBs .hl-faq-child-item-text p{font-weight:400!important}#faq-wEED3pufBs .hl-faq-child-item-text{font-size:15px}#faq-wEED3pufBs .faq-separated-child{border-radius:10px}#faq-wEED3pufBs .faq-separated-child,#faq-wEED3pufBs .faq-separated-child.active{border:1.5px solid var(--color-lwktyvyq)}#faq-wEED3pufBs .faq-contained-child{border:1px solid var(--color-lwktyvyq)}#faq-wEED3pufBs .faq-simple-child .hl-faq-child-heading{border-top:1px solid var(--color-lwktyvyq)}#faq-wEED3pufBs .faq-separated-child .hl-faq-child-heading{border-radius:10px}#faq-wEED3pufBs .faq-separated-child .hl-faq-child-heading.active{border-radius:10px 10px 0 0}#faq-wEED3pufBs .hl-faq-child-heading,#faq-wEED3pufBs .hl-faq-child-heading.active{background-color:var(--white)}#faq-wEED3pufBs .hl-faq-child-heading .hl-faq-child-head .hl-faq-child-heading-text,#faq-wEED3pufBs .hl-faq-child-heading .hl-faq-child-heading-icon{color:#111827}#faq-wEED3pufBs .hl-faq-child-heading.active .hl-faq-child-head .hl-faq-child-heading-text,#faq-wEED3pufBs .hl-faq-child-heading.active .hl-faq-child-heading-icon{color:var(--color-lwjrr318)}#faq-wEED3pufBs .hl-faq-child-heading .hl-faq-child-head .hl-faq-child-heading-text{line-height:1.5;font-family:var(--headlinefont)}#faq-wEED3pufBs .hl-faq-child .hl-faq-child-panel{background-color:var(--white)}#faq-wEED3pufBs .faq-separated-child .hl-faq-child-panel{border-radius:0}#faq-wEED3pufBs .faq-separated-child.active .hl-faq-child-panel{border-radius:0 0 10px 10px}#faq-wEED3pufBs .hl-faq-child .hl-faq-child-panel .hl-faq-child-item-text{color:var(--black);line-height:1.5}#faq-wEED3pufBs .hl-faq-child-panel{display:flex;padding:15px;overflow:hidden}#faq-wEED3pufBs .hl-faq-child-panel .item-text{min-width:80%;margin:0;font-family:var(--contentfont)}#faq-wEED3pufBs .hl-faq-child-panel .item-img{padding:.5em;max-width:20%;height:100%}@media screen and (min-width:0px) and (max-width:480px){#faq-wEED3pufBs .hl-faq-child-panel{display:grid;padding:15px}#faq-wEED3pufBs .hl-faq-child-panel .item-img{max-width:100%;width:100%;margin:0;padding:0;height:auto}#faq-wEED3pufBs .hl-faq-child-panel .item-text{max-width:100%;width:100%;margin:0;height:auto;padding:0 0 5px}#faq-wEED3pufBs .hl-faq-child-heading-text{font-size:15px}#faq-wEED3pufBs .hl-faq-child-heading-text .ProseMirror h4,#faq-wEED3pufBs .hl-faq-child-heading-text h4,#faq-wEED3pufBs .hl-faq-child-item-text .ProseMirror p,#faq-wEED3pufBs .hl-faq-child-item-text p{font-weight:undefined!important}#faq-wEED3pufBs .hl-faq-child-item-text{font-size:12px}}#faq-wEED3pufBs .hl-faq-child-heading .hl-faq-child-heading-icon:before{content:"\uF078"!important;font-family:"Font Awesome 5 Free"}#faq-wEED3pufBs .hl-faq-child-heading.active .hl-faq-child-heading-icon:before{content:"\uF077"!important;font-family:"Font Awesome 5 Free"}#faq-wEED3pufBs .expand-collapse-all-button{color:var(--color-lwjrr318);border:1px solid var(--color-lwktyvyq);background-color:var(--transparent)}#faq-wEED3pufBs a{color:#3b82f6!important;text-decoration:none!important}.heading-gQ8AnRpz8t{font-weight:undefined}.heading-gQ8AnRpz8t em,.heading-gQ8AnRpz8t strong,.heading-gQ8AnRpz8t u{color:var(--text-color)!important}.heading-gQ8AnRpz8t a,.heading-gQ8AnRpz8t a *{color:var(--link-color)!important;text-decoration:none}.heading-gQ8AnRpz8t a:hover{text-decoration:underline}@media screen and (min-width:0px) and (max-width:480px){.heading-gQ8AnRpz8t h1,.heading-gQ8AnRpz8t h2,.heading-gQ8AnRpz8t h3,.heading-gQ8AnRpz8t h4,.heading-gQ8AnRpz8t h5,.heading-gQ8AnRpz8t h6,.heading-gQ8AnRpz8t ul li,.heading-gQ8AnRpz8t.text-output{font-size:32px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.heading-gQ8AnRpz8t h1,.heading-gQ8AnRpz8t h2,.heading-gQ8AnRpz8t h3,.heading-gQ8AnRpz8t h4,.heading-gQ8AnRpz8t h5,.heading-gQ8AnRpz8t h6,.heading-gQ8AnRpz8t ul li,.heading-gQ8AnRpz8t.text-output{font-size:32px!important;font-weight:undefined}}.heading-gQ8AnRpz8t.text-output h1:first-child:before,.heading-gQ8AnRpz8t.text-output h2:first-child:before,.heading-gQ8AnRpz8t.text-output h3:first-child:before,.heading-gQ8AnRpz8t.text-output h4:first-child:before,.heading-gQ8AnRpz8t.text-output h5:first-child:before,.heading-gQ8AnRpz8t.text-output h6:first-child:before,.heading-gQ8AnRpz8t.text-output p:first-child:before{color:var(--text-color);content:'\\';
|
|
10088
|
+
font-family: '';margin-right:5px;font-weight:700}` } }, booking: { id: "section-MCURKhaM7", metaData: { id: "section-MCURKhaM7", type: "section", child: ["row-BafyFVpahF"], class: { width: { value: "fullSection" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingBottom: { unit: "px", value: "60" }, paddingTop: { unit: "px", value: 20 }, marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, backgroundColor: { value: "var(--white)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { sticky: { value: "noneSticky" }, visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, allowRowMaxWidth: { value: false } }, wrapper: {}, meta: "section", tagName: "c-section", title: "Section", _id: "section-MCURKhaM7" }, elements: [{ id: "row-BafyFVpahF", type: "row", child: ["col-CAyTxea5q"], class: { alignRow: { value: "row-align-center" }, boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: "0" }, paddingBottom: { unit: "px", value: 15 }, backgroundColor: { value: "var(--transparent)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, rowWidth: { value: 100, unit: "%" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-row", meta: "row", title: "1 Column Row" }, { id: "col-CAyTxea5q", type: "col", child: ["heading-SlwxJ2A0nn", "image-2hPEEKf7g", "paragraph-dIjQJIFPn", "calendar-0Yj8r8Npwf", "button-kQavoEkvPP"], class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { paddingLeft: { unit: "px", value: 5 }, paddingRight: { value: 5, unit: "px" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, backgroundColor: { value: "var(--transparent)" }, width: { value: "100", unit: "%" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" } }, extra: { visibility: { value: { hideDesktop: false, hideMobile: false } }, bgImage: { value: { url: "", opacity: "1", options: "bgCover" } }, columnLayout: { value: "column" }, justifyContentColumnLayout: { value: "center" }, alignContentColumnLayout: { value: "inherit" }, forceColumnLayoutForMobile: { value: true } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, tagName: "c-column", meta: "col", title: "1st Column" }, { extra: { nodeId: "cimage-2hPEEKf7g", visibility: { value: { hideDesktop: false, hideMobile: false } }, imageActions: { value: "none" }, visitWebsite: { value: { url: "", newTab: false } }, imageProperties: { value: { width: "", height: "", url: "https://storage.googleapis.com/msgsndr/locatation/EVTjG29VnVlvwn3SRGve/images/e04c0629-2eca-41d4-a320-ef634015616a.png", altText: "", compression: true, placeholderBase64: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAYAAABhYU3QAAAABHNCSVQICAgIfAhkiAAAAF96VFh0UmF3IHByb2ZpbGUgdHlwZSBBUFAxAAAImeNKT81LLcpMVigoyk/LzEnlUgADYxMuE0sTS6NEAwMDCwMIMDQwMDYEkkZAtjlUKNEABZgamFmaGZsZmgMxiM8FAEi2FMk61EMyAAAAVklEQVQImQXBMQ5AMBiA0a+tFpGIpBKLmRs4kCO5iMl9LMwmaUr93lPHtg7GGBsB9YYra9pZo8r73BdTe++AlNKTUVWjQGEBERcVFMJXuq6ftEguABB+L0UZOFcVeFYAAAAASUVORK5CYII=", servingUrl: "https://lh3.googleusercontent.com/8DcV-wSbJBKHjx-cmwagHA3SspBD4P3ScvvmZZog37NoIdaprLI5vt2nY7nfrqeCFVLFa0YTcL7jR3soFjmRqbNiESGeZ1Nm", imageMeta: { width: "", height: "" } } } }, class: { imageRadius: { value: "img-none" }, imageBorder: { value: "img-border-none" }, imageShadow: { value: "img-shadow-none" }, imageEffects: { value: "img-effects-none" } }, styles: { paddingLeft: { unit: "px", value: 10 }, paddingRight: { value: 10, unit: "px" }, paddingTop: { unit: "px", value: "10" }, paddingBottom: { unit: "px", value: "10" }, backgroundColor: { value: "var(--transparent)" }, opacity: { value: "1" }, textAlign: { value: "center" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "image-2hPEEKf7g", type: "element", child: [], meta: "image", tagName: "c-image", title: "Image", tag: "" }, { extra: { nodeId: "cparagraph-dIjQJIFPn", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<p>Ready to embark on your journey to radiant skin and total wellness? Booking an appointment at {{location.name}} is simple and convenient. Our team of experts is here to provide personalized treatments tailored to your unique needs and goals. We offer flexible scheduling to accommodate your busy lifestyle. Whether you prefer a quick lunchtime session or a relaxing afternoon retreat, we have appointment times to fit your needs.</p><p></p><p>Use our booking calendar below to schedule your appointment at any time. Select your preferred service, choose a convenient date and time, and confirm your appointment with just a few clicks.</p><p></p><p>Not sure which treatment is right for you? Schedule a consultation with one of our experienced professionals. We\u2019ll assess your skin and discuss your goals to create a customized treatment plan just for you.</p><p></p><p>If you have any questions or need assistance with booking, please don\u2019t hesitate to contact us at {{location.phone}}. Our friendly team is here to help!</p>" }, mobileFontSize: { value: "16", unit: "px" }, desktopFontSize: { value: "18", unit: "px" }, typography: { value: "var(--contentfont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "left" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 20 } }, customCss: [], id: "paragraph-dIjQJIFPn", type: "element", child: [], meta: "paragraph", tagName: "c-paragraph", title: "Paragraph", tag: "p" }, { extra: { nodeId: "ccalendar-0Yj8r8Npwf", visibility: { value: { hideDesktop: false, hideMobile: false } }, calendarId: { value: "none", text: "You do not have any calendar yet" }, action: { value: "none" }, visitWebsite: { value: { url: "", newTab: false } }, customClass: { value: [] } }, class: {}, styles: { paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginLeft: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 } }, customCss: [], id: "calendar-0Yj8r8Npwf", type: "element", child: [], meta: "calendar", tagName: "c-calendar", title: "Calendar", tag: "" }, { extra: { nodeId: "cheading-SlwxJ2A0nn", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "<h1>BOOK YOUR APPOINTMENT</h1>" }, mobileFontSize: { value: 46, unit: "px" }, desktopFontSize: { value: 46, unit: "px" }, typography: { value: "var(--headlinefont)" }, icon: { value: { name: "", unicode: "", fontFamily: "" } }, customClass: { value: [] } }, class: { boxShadow: { value: "none" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--transparent)" }, color: { value: "var(--text-color)" }, boldTextColor: { value: "var(--text-color)" }, italicTextColor: { value: "var(--text-color)" }, underlineTextColor: { value: "var(--text-color)" }, linkTextColor: { value: "var(--link-color)" }, iconColor: { value: "var(--text-color)" }, fontFamily: { value: "" }, fontWeight: { value: "normal", desktop: "400" }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" }, paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, opacity: { value: "1" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, borderColor: { value: "var(--black)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, lineHeight: { value: 1.3, unit: "em" }, textTransform: { value: "" }, letterSpacing: { value: "0", unit: "px" }, textAlign: { value: "center" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginLeft: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 } }, customCss: [], mobileStyles: {}, mobileWrapper: {}, id: "heading-SlwxJ2A0nn", type: "element", child: [], meta: "heading", tagName: "c-heading", title: "Headline", tag: "h1" }, { extra: { nodeId: "cbutton-kQavoEkvPP", visibility: { value: { hideDesktop: false, hideMobile: false } }, text: { value: "SUBMIT" }, subText: { value: "" }, mobileFontSize: { value: 20, unit: "px" }, desktopFontSize: { value: 20, unit: "px" }, subTextDesktopFontSize: { value: 15, unit: "px" }, subTextMobileFontSize: { value: 15, unit: "px" }, typography: { value: "var(--headlinefont)" }, iconStart: { value: { name: "", unicode: "", fontFamily: "" } }, iconEnd: { value: { name: "", unicode: "", fontFamily: "" } }, action: { value: "go-to-funnel-step" }, visitWebsite: { value: { url: "", newTab: false } }, hideElements: { value: [] }, showElements: { value: [] }, scrollToElement: { value: "" }, phoneNumber: { value: "" }, emailAddress: { value: "" }, productId: { value: "" }, stepPath: { value: "63b348ae-75d9-4ba0-a32b-f8163075c1b1" }, saleAction: { value: "go-to-next-funnel-step" }, theme: { value: "brand" }, customClass: { value: [] } }, class: { buttonEffects: { value: "none" }, buttonBoxShadow: { value: "btnshadow" }, buttonBgStyle: { value: "custom" }, buttonVp: { value: "btn-vp" }, buttonHp: { value: "btn-hp" }, borders: { value: "noBorder" }, borderRadius: { value: "radius0" }, radiusEdge: { value: "none" } }, styles: { backgroundColor: { value: "var(--my-custom-color-44)" }, color: { value: "var(--white)" }, secondaryColor: { value: "var(--white)" }, textDecoration: { value: "none" }, paddingTop: { unit: "px", value: 10 }, paddingBottom: { unit: "px", value: 10 }, paddingLeft: { unit: "px", value: 30 }, paddingRight: { unit: "px", value: 30 }, fontWeight: { value: "", desktop: "400" }, fontWeightSub: { desktop: "400", value: "" }, borderColor: { value: "var(--green)" }, borderWidth: { value: "2", unit: "px" }, borderStyle: { value: "solid" }, letterSpacing: { value: "0", unit: "px" }, textTransform: { value: "" }, textShadow: { value: "0px 0px 0px rgba(0,0,0,0)" }, width: { value: "auto", unit: "%" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 }, marginLeft: { unit: "px", value: 0 }, marginRight: { unit: "px", value: 0 }, textAlign: { value: "center" } }, mobileWrapper: {}, customCss: [], id: "button-kQavoEkvPP", mobileStyles: {}, type: "element", child: [], meta: "button", tagName: "c-button", title: "Button", tag: "" }], sequence: 2, pageId: "n3Asu9D8CUHL3vM5aiJi", funnelId: "pK3yy9CFapchugRrgjgq", locationId: "Gc2kgDDpABIR8QDyJ6rf", general: { colors: [{ label: "White", value: "#ffffff" }, { label: "Black", value: "#000000" }, { label: "Green", value: "#9ae6b4" }, { label: "Transparent", value: "transparent" }, { name: "My Custom Color 44", value: "#ec606a", label: "my-custom-color-44" }], fontsForPreview: ["'Lato'", "'Oswald'"], rootVars: { "--'lato'": "'Lato'", "--'oswald'": "'Oswald'", "--white": "#ffffff", "--black": "#000000", "--green": "#9ae6b4", "--transparent": "transparent", "--my-custom-color-44": "#ec606a" }, sectionStyles: ":root{--white:#ffffff;--black:#000000;--green:#9ae6b4;--transparent:transparent;--my-custom-color-44:#ec606a}.hl_page-preview--content .col-CAyTxea5q .inner,.hl_page-preview--content .row-BafyFVpahF,.hl_page-preview--content .section-MCURKhaM7{padding:20px 0 60px;margin-top:0;margin-bottom:0;background-color:var(--white);border-color:var(--black);border-width:2px;border-style:solid}.hl_page-preview--content .col-CAyTxea5q .inner,.hl_page-preview--content .row-BafyFVpahF{padding:0 0 15px;background-color:var(--transparent);width:100%}.hl_page-preview--content .col-CAyTxea5q{width:100%}.hl_page-preview--content .col-CAyTxea5q .inner{padding:10px 5px}.hl_page-preview--content .image-2hPEEKf7g{margin-top:0;margin-bottom:0}.hl_page-preview--content .cimage-2hPEEKf7g{padding:10px;background-color:var(--transparent);opacity:1;text-align:center}.hl_page-preview--content .paragraph-dIjQJIFPn{margin-top:0;margin-bottom:20px}.hl_page-preview--content .cparagraph-dIjQJIFPn{font-family:var(--contentfont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:left}.hl_page-preview--content .calendar-0Yj8r8Npwf{margin:0}.hl_page-preview--content .ccalendar-0Yj8r8Npwf{padding:0}.hl_page-preview--content .heading-SlwxJ2A0nn{margin:0}.hl_page-preview--content .cheading-SlwxJ2A0nn{font-family:var(--headlinefont);background-color:var(--transparent);color:var(--text-color);icon-color:var(--text-color);font-weight:400;padding:0;opacity:1;text-shadow:0 0 0 transparent;border-color:var(--black);border-width:2px;border-style:solid;line-height:1.3em;letter-spacing:0;text-align:center}.hl_page-preview--content .button-kQavoEkvPP{margin:0;text-align:center}.hl_page-preview--content .cbutton-kQavoEkvPP{font-family:var(--headlinefont);background-color:var(--my-custom-color-44);color:var(--white);secondary-color:var(--white);text-decoration:none;padding:10px 30px;border-color:var(--green);border-width:2px;border-style:solid;letter-spacing:0;text-shadow:0 0 0 transparent;width:auto%}#section-MCURKhaM7>.inner{max-width:1170px}#col-CAyTxea5q>.inner{flex-direction:column;justify-content:center;align-items:inherit;flex-wrap:nowrap}.paragraph-dIjQJIFPn{font-weight:undefined}.heading-SlwxJ2A0nn em,.heading-SlwxJ2A0nn strong,.heading-SlwxJ2A0nn u,.paragraph-dIjQJIFPn em,.paragraph-dIjQJIFPn strong,.paragraph-dIjQJIFPn u{color:var(--text-color)!important}.heading-SlwxJ2A0nn a,.heading-SlwxJ2A0nn a *,.paragraph-dIjQJIFPn a,.paragraph-dIjQJIFPn a *{color:var(--link-color)!important;text-decoration:none}.heading-SlwxJ2A0nn a:hover,.paragraph-dIjQJIFPn a:hover{text-decoration:underline}@media screen and (min-width:0px) and (max-width:480px){.paragraph-dIjQJIFPn h1,.paragraph-dIjQJIFPn h2,.paragraph-dIjQJIFPn h3,.paragraph-dIjQJIFPn h4,.paragraph-dIjQJIFPn h5,.paragraph-dIjQJIFPn h6,.paragraph-dIjQJIFPn ul li,.paragraph-dIjQJIFPn.text-output{font-size:16px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.paragraph-dIjQJIFPn h1,.paragraph-dIjQJIFPn h2,.paragraph-dIjQJIFPn h3,.paragraph-dIjQJIFPn h4,.paragraph-dIjQJIFPn h5,.paragraph-dIjQJIFPn h6,.paragraph-dIjQJIFPn ul li,.paragraph-dIjQJIFPn.text-output{font-size:18px!important;font-weight:undefined}}.heading-SlwxJ2A0nn.text-output h1:first-child:before,.heading-SlwxJ2A0nn.text-output h2:first-child:before,.heading-SlwxJ2A0nn.text-output h3:first-child:before,.heading-SlwxJ2A0nn.text-output h4:first-child:before,.heading-SlwxJ2A0nn.text-output h5:first-child:before,.heading-SlwxJ2A0nn.text-output h6:first-child:before,.heading-SlwxJ2A0nn.text-output p:first-child:before,.paragraph-dIjQJIFPn.text-output h1:first-child:before,.paragraph-dIjQJIFPn.text-output h2:first-child:before,.paragraph-dIjQJIFPn.text-output h3:first-child:before,.paragraph-dIjQJIFPn.text-output h4:first-child:before,.paragraph-dIjQJIFPn.text-output h5:first-child:before,.paragraph-dIjQJIFPn.text-output h6:first-child:before,.paragraph-dIjQJIFPn.text-output p:first-child:before{color:var(--text-color);content:'\\';\n font-family: '';margin-right:5px;font-weight:700}.heading-SlwxJ2A0nn{font-weight:400}@media screen and (min-width:0px) and (max-width:480px){.heading-SlwxJ2A0nn h1,.heading-SlwxJ2A0nn h2,.heading-SlwxJ2A0nn h3,.heading-SlwxJ2A0nn h4,.heading-SlwxJ2A0nn h5,.heading-SlwxJ2A0nn h6,.heading-SlwxJ2A0nn ul li,.heading-SlwxJ2A0nn.text-output{font-size:46px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.heading-SlwxJ2A0nn h1,.heading-SlwxJ2A0nn h2,.heading-SlwxJ2A0nn h3,.heading-SlwxJ2A0nn h4,.heading-SlwxJ2A0nn h5,.heading-SlwxJ2A0nn h6,.heading-SlwxJ2A0nn ul li,.heading-SlwxJ2A0nn.text-output{font-size:46px!important;font-weight:undefined}}@media screen and (min-width:481px) and (max-width:10000px){.button-kQavoEkvPP .button-icon-end,.button-kQavoEkvPP .button-icon-start,.button-kQavoEkvPP .main-heading-button{font-size:20px;font-weight:400}.button-kQavoEkvPP .button-icon-start{margin-right:5px}.button-kQavoEkvPP .button-icon-end{margin-left:5px}.button-kQavoEkvPP .sub-heading-button{font-size:15px;color:var(--white);font-weight:400}}@media screen and (min-width:0px) and (max-width:480px){.button-kQavoEkvPP .button-icon-end,.button-kQavoEkvPP .button-icon-start,.button-kQavoEkvPP .main-heading-button{font-size:20px;font-weight:undefined}.button-kQavoEkvPP .button-icon-start{margin-right:5px}.button-kQavoEkvPP .button-icon-end{margin-left:5px}.button-kQavoEkvPP .sub-heading-button{font-size:15px;color:var(--white);font-weight:undefined}}" } } }, formElement: { extra: { nodeId: "cform-YTQVxc2ryY", visibility: { value: { hideDesktop: false, hideMobile: false } }, formId: { value: "nM86ifoBmhUmyDyaUedm", text: "Marketing Form - Claim Offer" }, action: { value: "none" }, visitWebsite: { value: { url: "", newTab: false } }, customClass: { value: [] } }, class: {}, styles: { paddingTop: { unit: "px", value: 0 }, paddingBottom: { unit: "px", value: 0 }, paddingLeft: { unit: "px", value: 0 }, paddingRight: { value: 0, unit: "px" } }, wrapper: { marginTop: { unit: "px", value: 0 }, marginBottom: { unit: "px", value: 0 } }, customCss: [], id: "form-YTQVxc2ryY", type: "element", child: [], meta: "form", tagName: "c-form", title: "Form", tag: "" }, base: { settings: { settings: { typography: { fonts: { headlineFont: { id: "headlinefont", value: { value: "var(--oswald)", text: "Oswald" }, text: "Headline Font" }, contentFont: { value: { text: "Lato", value: "var(--lato)" }, id: "contentfont", text: "Content Font" } }, colors: { linkColor: { value: { value: "var(--my-custom-color-44)", label: "var(--blue)" } }, textColor: { value: { value: "var(--my-custom-color-26)", label: "var(--black)" } } } }, background: { bgImage: { value: { url: "", options: "bgCover" } }, backgroundColor: { value: "var(--white)" } } } }, general: { general: { colors: [{ label: "Primary", value: "#37ca37" }, { value: "#188bf6", label: "Secondary" }, { label: "White", value: "#ffffff" }, { label: "Gray", value: "#cbd5e0" }, { label: "Black", value: "#000000" }, { label: "Red", value: "#e93d3d" }, { label: "Orange", value: "#f6ad55" }, { label: "Yellow", value: "#faf089" }, { value: "#9ae6b4", label: "Green" }, { value: "#81e6d9", label: "Teal" }, { value: "#63b3ed", label: "Malibu" }, { value: "#757BBD", label: "Indigo" }, { value: "#d6bcfa", label: "Purple" }, { label: "Pink", value: "#fbb6ce" }, { label: "Transparent", value: "transparent" }, { value: "rgba(0, 0, 0, 0.5)", label: "Overlay" }, { label: "my-custom-color-26", value: "#434445", name: "My Custom Color 26" }, { label: "my-custom-color-44", name: "My Custom Color 44", value: "#ec606a" }, { name: "", value: "#fff6", label: "" }, { name: "My Custom Color 71", label: "my-custom-color-71", value: "#d7d7d9" }, { label: "my-custom-color-60", value: "#e9c7c1", name: "My Custom Color 60" }, { name: "My Custom Color 94", value: "#f49ca2 ", label: "my-custom-color-94" }, { value: "#f3f3f3", name: "My Custom Color 16", label: "my-custom-color-16" }], fontsToLoad: ["Arial", "Lato", "Open Sans", "Montserrat", "Oswald", "Roboto", "'Lato'", "'Oswald'"], fontsToLoadForPreview: ["'Lato'", "'Oswald'"], pageStyles: "" } }, pageStyles: ":root{ --primary: #37ca37;\n--secondary: #188bf6;\n--white: #ffffff;\n--gray: #cbd5e0;\n--black: #000000;\n--red: #e93d3d;\n--orange: #f6ad55;\n--yellow: #faf089;\n--green: #9ae6b4;\n--teal: #81e6d9;\n--malibu: #63b3ed;\n--indigo: #757BBD;\n--purple: #d6bcfa;\n--pink: #fbb6ce;\n--transparent: transparent;\n--overlay: rgba(0, 0, 0, 0.5);\n--my-custom-color-26: #434445;\n--my-custom-color-44: #ec606a;\n--: #fff6;\n--my-custom-color-71: #d7d7d9;\n--my-custom-color-60: #e9c7c1;\n--my-custom-color-94: #f49ca2 ;\n--my-custom-color-16: #f3f3f3;\n--arial: 'Arial';\n--lato: 'Lato';\n--open-sans: 'Open Sans';\n--montserrat: 'Montserrat';\n--roboto: 'Roboto';\n--oswald: 'Oswald';\n--'lato': ''Lato'';\n--'oswald': ''Oswald'';\n--headlinefont: 'Oswald';\n--contentfont: 'Lato';\n--link-color: var(--my-custom-color-44);\n--text-color: var(--my-custom-color-26); } .bg-fixed{bottom:0;top:0;left:0;right:0;position:fixed;overflow:auto;background-color:var(--white)} \n \n .drop-zone-draggable .hl_main_popup{background-color:var(--white);border-style:solid;border-width:10px;margin-top:0;border-color:var(--gray);padding:20px}\n \n \n#hl_main_popup{background-color:var(--white);border-style:solid;border-width:10px;margin-top:0;border-color:var(--gray);padding:20px;width:720px} ", trackingCode: {}, fontsForPreview: [] } };
|
|
10089
|
+
|
|
10090
|
+
// src/page-studio/remint.ts
|
|
10091
|
+
var ID_FIELDS = ["id"];
|
|
10092
|
+
function isNodeId(v) {
|
|
10093
|
+
if (v.length < 8 || /^\d/.test(v)) return false;
|
|
10094
|
+
const dash = v.indexOf("-");
|
|
10095
|
+
return dash > 0 && v.length - dash - 1 >= 4;
|
|
10096
|
+
}
|
|
10097
|
+
function collectIds(node, acc) {
|
|
10098
|
+
if (Array.isArray(node)) {
|
|
10099
|
+
for (const item of node) collectIds(item, acc);
|
|
10100
|
+
return;
|
|
10101
|
+
}
|
|
10102
|
+
if (!node || typeof node !== "object") return;
|
|
10103
|
+
const rec = node;
|
|
10104
|
+
for (const f of ID_FIELDS) {
|
|
10105
|
+
const v = rec[f];
|
|
10106
|
+
if (typeof v === "string" && isNodeId(v)) acc.add(v);
|
|
10107
|
+
}
|
|
10108
|
+
const nodeId = rec.extra?.nodeId;
|
|
10109
|
+
if (typeof nodeId === "string" && isNodeId(nodeId)) acc.add(nodeId);
|
|
10110
|
+
for (const [k, v] of Object.entries(rec)) {
|
|
10111
|
+
if (k === "extra") {
|
|
10112
|
+
collectIds(v, acc);
|
|
10113
|
+
continue;
|
|
10114
|
+
}
|
|
10115
|
+
if (typeof v === "object" && v !== null) collectIds(v, acc);
|
|
10116
|
+
}
|
|
10117
|
+
}
|
|
10118
|
+
var mintCounter = 0;
|
|
10119
|
+
function defaultMint(oldId) {
|
|
10120
|
+
const dash = oldId.indexOf("-");
|
|
10121
|
+
const prefix = dash > 0 ? oldId.slice(0, dash) : oldId;
|
|
10122
|
+
mintCounter += 1;
|
|
10123
|
+
const rand = Math.random().toString(36).slice(2, 8);
|
|
10124
|
+
return `${prefix}-ps${rand}${mintCounter.toString(36)}`;
|
|
10125
|
+
}
|
|
10126
|
+
function escapeRegExp2(s) {
|
|
10127
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
10128
|
+
}
|
|
10129
|
+
function remintClone(node, mint = defaultMint) {
|
|
10130
|
+
const ids = /* @__PURE__ */ new Set();
|
|
10131
|
+
collectIds(node, ids);
|
|
10132
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
10133
|
+
for (const oldId of ids) {
|
|
10134
|
+
if (!idMap.has(oldId)) idMap.set(oldId, mint(oldId));
|
|
10135
|
+
}
|
|
10136
|
+
for (const [oldId, newId] of idMap) {
|
|
10137
|
+
const cOld = "c" + oldId;
|
|
10138
|
+
if (idMap.has(cOld)) idMap.set(cOld, "c" + newId);
|
|
10139
|
+
}
|
|
10140
|
+
let text = JSON.stringify(node);
|
|
10141
|
+
const ordered = [...idMap.keys()].sort((a, b) => b.length - a.length);
|
|
10142
|
+
for (const oldId of ordered) {
|
|
10143
|
+
const newId = idMap.get(oldId);
|
|
10144
|
+
if (newId === void 0) continue;
|
|
10145
|
+
const re = new RegExp(`(?:(?<=%2F)|(?<![A-Za-z0-9_-]))${escapeRegExp2(oldId)}(?![A-Za-z0-9_-])`, "g");
|
|
10146
|
+
text = text.replace(re, newId);
|
|
10147
|
+
}
|
|
10148
|
+
return { cloned: JSON.parse(text), idMap };
|
|
10149
|
+
}
|
|
10150
|
+
|
|
10151
|
+
// src/page-studio/sections.ts
|
|
10152
|
+
var donors = donor_sections_default;
|
|
10153
|
+
function deepClone(v) {
|
|
10154
|
+
return JSON.parse(JSON.stringify(v));
|
|
10155
|
+
}
|
|
10156
|
+
function escapeHtml(s) {
|
|
10157
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
10158
|
+
}
|
|
10159
|
+
function elements(section2) {
|
|
10160
|
+
return section2.elements ?? [];
|
|
10161
|
+
}
|
|
10162
|
+
function byId(section2, donorId) {
|
|
10163
|
+
const el = elements(section2).find((e) => e.id === donorId);
|
|
10164
|
+
if (!el) throw new Error(`Page Studio internal: donor element ${donorId} missing \u2014 did the capture change without re-running extract-donors?`);
|
|
10165
|
+
return el;
|
|
10166
|
+
}
|
|
10167
|
+
function setText(el, html2) {
|
|
10168
|
+
const extra = el.extra ?? {};
|
|
10169
|
+
extra.text = { ...extra.text, value: html2 };
|
|
10170
|
+
el.extra = extra;
|
|
10171
|
+
}
|
|
10172
|
+
function setIcon(el, iconName) {
|
|
10173
|
+
const extra = el.extra ?? {};
|
|
10174
|
+
const icon = extra.icon ?? { value: {} };
|
|
10175
|
+
icon.value = { ...icon.value, name: iconName };
|
|
10176
|
+
extra.icon = icon;
|
|
10177
|
+
}
|
|
10178
|
+
function setImageUrl(el, url) {
|
|
10179
|
+
const extra = el.extra ?? {};
|
|
10180
|
+
const props = extra.imageProperties ?? { value: {} };
|
|
10181
|
+
const value = { ...props.value, url };
|
|
10182
|
+
delete value.servingUrl;
|
|
10183
|
+
delete value.placeholderBase64;
|
|
10184
|
+
props.value = value;
|
|
10185
|
+
extra.imageProperties = props;
|
|
10186
|
+
}
|
|
10187
|
+
function setSectionBgImage(section2, url) {
|
|
10188
|
+
const md = section2.metaData ?? {};
|
|
10189
|
+
const extra = md.extra ?? {};
|
|
10190
|
+
const bg = extra.bgImage ?? { value: {} };
|
|
10191
|
+
const value = { ...bg.value, url };
|
|
10192
|
+
delete value.servingUrl;
|
|
10193
|
+
delete value.placeholderBase64;
|
|
10194
|
+
bg.value = value;
|
|
10195
|
+
extra.bgImage = bg;
|
|
10196
|
+
md.extra = extra;
|
|
10197
|
+
section2.metaData = md;
|
|
10198
|
+
}
|
|
10199
|
+
function finish(section2) {
|
|
10200
|
+
const { cloned } = remintClone(section2);
|
|
10201
|
+
const rec = cloned;
|
|
10202
|
+
delete rec.isGlobal;
|
|
10203
|
+
return { section: rec, sectionId: rec.id };
|
|
10204
|
+
}
|
|
10205
|
+
function buildTopbar(params) {
|
|
10206
|
+
const s = deepClone(donors.sections.topbar);
|
|
10207
|
+
if (params.phoneHtml) setText(byId(s, "paragraph-jL-pjux8a"), params.phoneHtml);
|
|
10208
|
+
if (params.logoUrl) setImageUrl(byId(s, "image-YGGYHGoZw"), params.logoUrl);
|
|
10209
|
+
return finish(s);
|
|
10210
|
+
}
|
|
10211
|
+
function buildHero(params) {
|
|
10212
|
+
const s = deepClone(donors.sections.hero);
|
|
10213
|
+
setText(byId(s, "heading-BcUsx4fVJi"), `<h1>${escapeHtml(params.headline)}</h1>`);
|
|
10214
|
+
setText(byId(s, "paragraph-WVEyivzTc"), `<p>${escapeHtml(params.subhead)}</p>`);
|
|
10215
|
+
const btn = byId(s, "button-XgW4LOq8Q");
|
|
10216
|
+
setText(btn, escapeHtml(params.ctaLabel));
|
|
10217
|
+
const ctaUrl = params.ctaHref ?? (params.ctaAnchorId ? `#${params.ctaAnchorId}` : void 0);
|
|
10218
|
+
if (ctaUrl) {
|
|
10219
|
+
const extra = btn.extra ?? {};
|
|
10220
|
+
extra.action = { value: "url" };
|
|
10221
|
+
extra.visitWebsite = { value: { url: ctaUrl, newTab: false } };
|
|
10222
|
+
btn.extra = extra;
|
|
10223
|
+
}
|
|
10224
|
+
if (params.bgImageUrl) setSectionBgImage(s, params.bgImageUrl);
|
|
10225
|
+
return finish(s);
|
|
10226
|
+
}
|
|
10227
|
+
var CARD_SLOTS = [
|
|
10228
|
+
{ title: "heading-ZvINOOFQi", body: "paragraph-1XjOnx_r2", blank: ["paragraph-iuePsO6Jd", "paragraph-fBuGHkfQd"] },
|
|
10229
|
+
{ title: "heading-h2fK7KiZ6", body: "paragraph-y_I-jJh6ya", blank: [] },
|
|
10230
|
+
{ title: "heading-FBdJHQ1UZ", body: "paragraph--m28AM_yp9", blank: ["paragraph-6KxQcCSVR", "paragraph-nuxIv4A8ad", "paragraph-pvUi7TFc7r"] }
|
|
10231
|
+
];
|
|
10232
|
+
function buildValueCards(params) {
|
|
10233
|
+
const s = deepClone(donors.sections.valueCards);
|
|
10234
|
+
const removeIds = /* @__PURE__ */ new Set();
|
|
10235
|
+
params.cards.forEach((card, i) => {
|
|
10236
|
+
const slot = CARD_SLOTS[i];
|
|
10237
|
+
const title = byId(s, slot.title);
|
|
10238
|
+
setText(title, `<p>${escapeHtml(card.title)}</p>`);
|
|
10239
|
+
if (card.iconName) setIcon(title, card.iconName);
|
|
10240
|
+
setText(byId(s, slot.body), card.bodyHtml);
|
|
10241
|
+
for (const blankId of slot.blank) removeIds.add(blankId);
|
|
10242
|
+
});
|
|
10243
|
+
s.elements = elements(s).filter((e) => !removeIds.has(e.id));
|
|
10244
|
+
for (const col of elements(s).filter((e) => e.type === "col")) {
|
|
10245
|
+
col.child = (col.child ?? []).filter((c) => !removeIds.has(c));
|
|
10246
|
+
}
|
|
10247
|
+
return finish(s);
|
|
10248
|
+
}
|
|
10249
|
+
function buildFaq(params) {
|
|
10250
|
+
const s = deepClone(donors.sections.faq);
|
|
10251
|
+
if (params.title) setText(byId(s, "sub-heading-bQudNu4eBG"), `<h2>${escapeHtml(params.title)}</h2>`);
|
|
10252
|
+
if (params.imageUrl) setImageUrl(byId(s, "image-VMrslNNuUy"), params.imageUrl);
|
|
10253
|
+
const toFaqList = (items) => items.map((it, i) => ({ id: i + 1, heading: `<h4>${escapeHtml(it.q)}</h4>`, text: `<p>${escapeHtml(it.a)}</p>` }));
|
|
10254
|
+
const half = Math.ceil(params.items.length / 2);
|
|
10255
|
+
const widgets = ["faq-hC9kdZlk9d", "faq-xt8Q865Gfb"];
|
|
10256
|
+
const parts = [params.items.slice(0, half), params.items.slice(half)];
|
|
10257
|
+
widgets.forEach((wid, i) => {
|
|
10258
|
+
const el = byId(s, wid);
|
|
10259
|
+
const extra = el.extra ?? {};
|
|
10260
|
+
const faqList = extra.faqList ?? {};
|
|
10261
|
+
faqList.value = toFaqList(parts[i]);
|
|
10262
|
+
extra.faqList = faqList;
|
|
10263
|
+
el.extra = extra;
|
|
10264
|
+
});
|
|
10265
|
+
return finish(s);
|
|
10266
|
+
}
|
|
10267
|
+
function buildFooter(params) {
|
|
10268
|
+
const s = deepClone(donors.sections.footer);
|
|
10269
|
+
if (params.logoUrl) setImageUrl(byId(s, "image-Fuy-QQVmM"), params.logoUrl);
|
|
10270
|
+
const legal = byId(s, "paragraph-R6ogZueLM");
|
|
10271
|
+
setText(
|
|
10272
|
+
legal,
|
|
10273
|
+
`<p>${escapeHtml(params.businessLegalName)} \xB7 ${escapeHtml(params.mailingAddress)}</p><p>\xA9 {{right_now.year}} ${escapeHtml(params.businessLegalName)}. All Rights Reserved. <a href="${escapeHtml(params.privacyUrl)}" target="_blank">Privacy Policy</a> \xB7 <a href="${escapeHtml(params.termsUrl)}" target="_blank">Terms of Service</a></p>`
|
|
10274
|
+
);
|
|
10275
|
+
return finish(s);
|
|
10276
|
+
}
|
|
10277
|
+
function buildFormSection(params) {
|
|
10278
|
+
const title = deepClone(byId(donors.sections.faq, "sub-heading-bQudNu4eBG"));
|
|
10279
|
+
title.id = "sub-heading-FRMTITLE";
|
|
10280
|
+
(title.extra ?? {}).nodeId = "csub-heading-FRMTITLE";
|
|
10281
|
+
setText(title, `<h2>${escapeHtml(params.headline)}</h2>`);
|
|
10282
|
+
const disclosure = deepClone(byId(donors.sections.footer, "paragraph-R6ogZueLM"));
|
|
10283
|
+
disclosure.id = "paragraph-FRMDISC";
|
|
10284
|
+
(disclosure.extra ?? {}).nodeId = "cparagraph-FRMDISC";
|
|
10285
|
+
setText(disclosure, params.disclosureHtml);
|
|
10286
|
+
const form = deepClone(donors.formElement);
|
|
10287
|
+
form.id = "form-FRMEMBED";
|
|
10288
|
+
{
|
|
10289
|
+
const extra = form.extra ?? {};
|
|
10290
|
+
extra.nodeId = "cform-FRMEMBED";
|
|
10291
|
+
extra.formId = { value: params.formId, text: params.formName };
|
|
10292
|
+
form.extra = extra;
|
|
10293
|
+
}
|
|
10294
|
+
const legal = deepClone(byId(donors.sections.footer, "paragraph-R6ogZueLM"));
|
|
10295
|
+
legal.id = "paragraph-FRMLEGAL";
|
|
10296
|
+
(legal.extra ?? {}).nodeId = "cparagraph-FRMLEGAL";
|
|
10297
|
+
setText(
|
|
10298
|
+
legal,
|
|
10299
|
+
`<p><a href="${escapeHtml(params.privacyUrl)}" target="_blank">Privacy Policy</a> \xB7 <a href="${escapeHtml(params.termsUrl)}" target="_blank">Terms of Service</a></p>`
|
|
10300
|
+
);
|
|
10301
|
+
const section2 = deepClone(donors.sections.formShell);
|
|
10302
|
+
const els = elements(section2);
|
|
10303
|
+
const row = els.find((e) => e.type === "row");
|
|
10304
|
+
const col = els.find((e) => e.type === "col");
|
|
10305
|
+
if (!row || !col) throw new Error("Page Studio internal: formShell donor lost its row/col \u2014 re-run extract-donors.");
|
|
10306
|
+
const children = [title, disclosure, form, legal];
|
|
10307
|
+
col.child = children.map((c) => c.id);
|
|
10308
|
+
section2.elements = [row, col, ...children];
|
|
10309
|
+
return finish(section2);
|
|
10310
|
+
}
|
|
10311
|
+
function buildNav(params) {
|
|
10312
|
+
const s = deepClone(donors.sections.nav);
|
|
10313
|
+
const el = elements(s).find((e) => e.meta === "nav-menu");
|
|
10314
|
+
if (!el) throw new Error("Page Studio internal: nav donor lost its nav-menu element \u2014 re-run extract-donors.");
|
|
10315
|
+
const extra = el.extra ?? {};
|
|
10316
|
+
extra.menuItems = {
|
|
10317
|
+
value: params.items.map((it, i) => ({
|
|
10318
|
+
id: String(i + 1),
|
|
10319
|
+
title: escapeHtml(it.title),
|
|
10320
|
+
goTo: "go-to-funnel-step",
|
|
10321
|
+
url: `#${escapeHtml(it.slug)}`,
|
|
10322
|
+
goToId: it.stepId,
|
|
10323
|
+
openInNewTab: false,
|
|
10324
|
+
childs: []
|
|
10325
|
+
}))
|
|
10326
|
+
};
|
|
10327
|
+
if (params.brandHtml) extra.text = { ...extra.text, value: params.brandHtml };
|
|
10328
|
+
el.extra = extra;
|
|
10329
|
+
if (params.logoUrl) setImageUrl(el, params.logoUrl);
|
|
10330
|
+
return finish(s);
|
|
10331
|
+
}
|
|
10332
|
+
var IMAGETEXT_SLOTS = [
|
|
10333
|
+
{ title: "paragraph-PwtXX77o4", body: "paragraph-F9SB3vFfN" },
|
|
10334
|
+
{ title: "paragraph-Ud7-Hmgyun", body: "paragraph-ECP1xCEVEa" },
|
|
10335
|
+
{ title: "paragraph-Dt21hDz3On", body: "paragraph-AU_CDh6MOl" }
|
|
10336
|
+
];
|
|
10337
|
+
function buildImageText(params) {
|
|
10338
|
+
const s = deepClone(donors.sections.imageText);
|
|
10339
|
+
setText(byId(s, "sub-heading-MbvugAQFJf"), `<h2>${escapeHtml(params.title)}</h2>`);
|
|
10340
|
+
params.features.forEach((f, i) => {
|
|
10341
|
+
const slot = IMAGETEXT_SLOTS[i];
|
|
10342
|
+
setText(byId(s, slot.title), `<p><strong>${escapeHtml(f.title)}</strong></p>`);
|
|
10343
|
+
setText(byId(s, slot.body), f.bodyHtml);
|
|
10344
|
+
});
|
|
10345
|
+
if (params.imageUrl) setImageUrl(byId(s, "image-2hPEEKf7g"), params.imageUrl);
|
|
10346
|
+
return finish(s);
|
|
10347
|
+
}
|
|
10348
|
+
function buildCtaBanner(params) {
|
|
10349
|
+
const s = deepClone(donors.sections.ctaBanner);
|
|
10350
|
+
setText(byId(s, "sub-heading-JJ_mZmXWcY"), `<h2>${escapeHtml(params.title)}</h2>`);
|
|
10351
|
+
setText(byId(s, "paragraph-NAh24LKg8A"), params.bodyHtml);
|
|
10352
|
+
const btn = byId(s, "button-H3ED7jvqBu");
|
|
10353
|
+
setText(btn, escapeHtml(params.buttonLabel));
|
|
10354
|
+
const extra = btn.extra ?? {};
|
|
10355
|
+
extra.action = { value: "url" };
|
|
10356
|
+
extra.visitWebsite = { value: { url: params.buttonHref, newTab: false } };
|
|
10357
|
+
btn.extra = extra;
|
|
10358
|
+
return finish(s);
|
|
10359
|
+
}
|
|
10360
|
+
function buildMapSection(params) {
|
|
10361
|
+
const s = deepClone(donors.sections.map);
|
|
10362
|
+
if (params.title) setText(byId(s, "heading-IUykdV_et"), `<p>${escapeHtml(params.title)}</p>`);
|
|
10363
|
+
if (params.mapLocation) {
|
|
10364
|
+
const mapEl = byId(s, "map-tptsa5-Qnk");
|
|
10365
|
+
const extra = mapEl.extra ?? {};
|
|
10366
|
+
const loc = extra.mapLocation ?? {};
|
|
10367
|
+
const value = { ...loc.value ?? loc };
|
|
10368
|
+
value.name = params.mapLocation.name;
|
|
10369
|
+
value.lat = params.mapLocation.lat;
|
|
10370
|
+
value.lng = params.mapLocation.lng;
|
|
10371
|
+
if (params.mapLocation.placeId) value.placeId = params.mapLocation.placeId;
|
|
10372
|
+
delete value.url;
|
|
10373
|
+
if (loc.value !== void 0) loc.value = value;
|
|
10374
|
+
else Object.assign(loc, value);
|
|
10375
|
+
extra.mapLocation = loc.value !== void 0 ? loc : { ...loc };
|
|
10376
|
+
mapEl.extra = extra;
|
|
10377
|
+
}
|
|
10378
|
+
return finish(s);
|
|
10379
|
+
}
|
|
10380
|
+
function buildBooking(params) {
|
|
10381
|
+
const s = deepClone(donors.sections.booking);
|
|
10382
|
+
const cal = byId(s, "calendar-0Yj8r8Npwf");
|
|
10383
|
+
const extra = cal.extra ?? {};
|
|
10384
|
+
extra.calendarId = { value: params.calendarId, text: params.calendarName };
|
|
10385
|
+
cal.extra = extra;
|
|
10386
|
+
if (params.title) setText(byId(s, "heading-SlwxJ2A0nn"), `<h1>${escapeHtml(params.title)}</h1>`);
|
|
10387
|
+
if (params.bodyHtml) setText(byId(s, "paragraph-dIjQJIFPn"), params.bodyHtml);
|
|
10388
|
+
if (params.imageUrl) setImageUrl(byId(s, "image-2hPEEKf7g"), params.imageUrl);
|
|
10389
|
+
return finish(s);
|
|
10390
|
+
}
|
|
10391
|
+
function baseEnvelopeParts() {
|
|
10392
|
+
return deepClone(donors.base);
|
|
10393
|
+
}
|
|
10394
|
+
|
|
10395
|
+
// src/page-studio/compose.ts
|
|
10396
|
+
function requireField(value, name, problems) {
|
|
10397
|
+
if (typeof value !== "string" || value.trim().length === 0) problems.push(`missing required field: ${name}`);
|
|
10398
|
+
}
|
|
10399
|
+
function complianceGate(params) {
|
|
10400
|
+
const problems = [];
|
|
10401
|
+
const warnings = [];
|
|
10402
|
+
requireField(params.business?.legalName, "business.legalName", problems);
|
|
10403
|
+
requireField(params.business?.mailingAddress, "business.mailingAddress", problems);
|
|
10404
|
+
requireField(params.business?.privacyUrl, "business.privacyUrl", problems);
|
|
10405
|
+
requireField(params.business?.termsUrl, "business.termsUrl", problems);
|
|
10406
|
+
requireField(params.form?.formId, "form.formId", problems);
|
|
10407
|
+
requireField(params.form?.formName, "form.formName", problems);
|
|
10408
|
+
requireField(params.content?.headline, "content.headline", problems);
|
|
10409
|
+
requireField(params.content?.subhead, "content.subhead", problems);
|
|
10410
|
+
requireField(params.content?.ctaLabel, "content.ctaLabel", problems);
|
|
10411
|
+
for (const url of [params.business?.privacyUrl, params.business?.termsUrl]) {
|
|
10412
|
+
if (typeof url === "string" && url.length > 0 && !/^https?:\/\//.test(url)) {
|
|
10413
|
+
problems.push(`URL must be absolute (https://\u2026): ${url}`);
|
|
10414
|
+
}
|
|
10415
|
+
}
|
|
10416
|
+
if ((params.content?.cards?.length ?? 0) !== 3) problems.push("content.cards must have exactly 3 cards");
|
|
10417
|
+
if ((params.content?.faqs?.length ?? 0) < 2) problems.push("content.faqs needs at least 2 items");
|
|
10418
|
+
if ((params.content?.faqs?.length ?? 0) > 0 && (params.content?.faqs?.length ?? 0) < 4) {
|
|
10419
|
+
warnings.push("content contract recommends 4-8 FAQ items");
|
|
10420
|
+
}
|
|
10421
|
+
if (!params.images?.heroUrl) warnings.push("hero uses the donor template's stock image \u2014 replace with a client-owned image before customer use");
|
|
10422
|
+
if (!params.images?.logoUrl) warnings.push("topbar/footer use the donor template's placeholder logo \u2014 provide images.logoUrl before customer use");
|
|
10423
|
+
if (problems.length > 0) {
|
|
10424
|
+
throw new Error("Compliance gate failed (A2P/content contract):\n- " + problems.join("\n- "));
|
|
10425
|
+
}
|
|
10426
|
+
return warnings;
|
|
10427
|
+
}
|
|
10428
|
+
function composeOptinPage(params) {
|
|
10429
|
+
const warnings = complianceGate(params);
|
|
10430
|
+
const disclosure = params.content.disclosureHtml ?? `<p>Complete the form to claim this offer from ${params.business.legalName}. By submitting you agree to receive recurring informational and marketing messages (reply STOP to opt out, HELP for help; message frequency varies, msg & data rates may apply).</p>`;
|
|
10431
|
+
const formSection = buildFormSection({
|
|
10432
|
+
formId: params.form.formId,
|
|
10433
|
+
formName: params.form.formName,
|
|
10434
|
+
headline: params.content.headline,
|
|
10435
|
+
disclosureHtml: disclosure,
|
|
10436
|
+
privacyUrl: params.business.privacyUrl,
|
|
10437
|
+
termsUrl: params.business.termsUrl
|
|
10438
|
+
});
|
|
10439
|
+
const topbar = buildTopbar({ phoneHtml: params.business.phoneHtml, logoUrl: params.images?.logoUrl });
|
|
10440
|
+
const hero = buildHero({
|
|
10441
|
+
headline: params.content.headline,
|
|
10442
|
+
subhead: params.content.subhead,
|
|
10443
|
+
ctaLabel: params.content.ctaLabel,
|
|
10444
|
+
ctaAnchorId: formSection.sectionId,
|
|
10445
|
+
bgImageUrl: params.images?.heroUrl
|
|
10446
|
+
});
|
|
10447
|
+
const valueCards = buildValueCards({ cards: params.content.cards });
|
|
10448
|
+
const faq = buildFaq({ title: params.content.faqTitle, items: params.content.faqs, imageUrl: params.images?.faqImageUrl });
|
|
10449
|
+
const footer = buildFooter({
|
|
10450
|
+
businessLegalName: params.business.legalName,
|
|
10451
|
+
mailingAddress: params.business.mailingAddress,
|
|
10452
|
+
privacyUrl: params.business.privacyUrl,
|
|
10453
|
+
termsUrl: params.business.termsUrl,
|
|
10454
|
+
logoUrl: params.images?.logoUrl
|
|
10455
|
+
});
|
|
10456
|
+
const ordered = [topbar, hero, valueCards, formSection, faq, footer];
|
|
10457
|
+
const base = baseEnvelopeParts();
|
|
10458
|
+
let envelope = {
|
|
10459
|
+
// sequence must reflect THIS page's order, not the donors' source pages
|
|
10460
|
+
sections: ordered.map((s, i) => ({ ...s.section, sequence: i })),
|
|
10461
|
+
settings: base.settings,
|
|
10462
|
+
general: base.general,
|
|
10463
|
+
pageStyles: base.pageStyles,
|
|
10464
|
+
trackingCode: base.trackingCode,
|
|
10465
|
+
fontsForPreview: themedFonts(params.theme ?? {}),
|
|
10466
|
+
popups: [],
|
|
10467
|
+
popupsList: []
|
|
10468
|
+
};
|
|
10469
|
+
if (params.theme) {
|
|
10470
|
+
envelope = applyTheme(envelope, params.theme);
|
|
10471
|
+
const fontProblems = assertFontMatrixComplete(envelope, params.theme);
|
|
10472
|
+
if (fontProblems.length > 0) {
|
|
10473
|
+
throw new Error("Font matrix incomplete after theming:\n- " + fontProblems.join("\n- "));
|
|
10474
|
+
}
|
|
10475
|
+
}
|
|
10476
|
+
return {
|
|
10477
|
+
envelope,
|
|
10478
|
+
report: {
|
|
10479
|
+
sections: ["topbar", "hero", "valueCards", "formSection", "faq", "footer"],
|
|
10480
|
+
formAnchorId: formSection.sectionId,
|
|
10481
|
+
warnings
|
|
10482
|
+
}
|
|
10483
|
+
};
|
|
10484
|
+
}
|
|
10485
|
+
|
|
10486
|
+
// src/page-studio/website.ts
|
|
10487
|
+
function gate(params) {
|
|
10488
|
+
const problems = [];
|
|
10489
|
+
const warnings = [];
|
|
10490
|
+
const req = (v, name) => {
|
|
10491
|
+
if (typeof v !== "string" || v.trim().length === 0) problems.push(`missing required field: ${name}`);
|
|
10492
|
+
};
|
|
10493
|
+
req(params.business?.legalName, "business.legalName");
|
|
10494
|
+
req(params.business?.mailingAddress, "business.mailingAddress");
|
|
10495
|
+
req(params.business?.privacyUrl, "business.privacyUrl");
|
|
10496
|
+
req(params.business?.termsUrl, "business.termsUrl");
|
|
10497
|
+
if (!params.pages?.length) problems.push("pages must not be empty");
|
|
10498
|
+
if (!params.pages?.some((p) => p.role === "home")) problems.push("a 'home' page is required");
|
|
10499
|
+
const roles = /* @__PURE__ */ new Set();
|
|
10500
|
+
for (const p of params.pages ?? []) {
|
|
10501
|
+
if (roles.has(p.role)) problems.push(`duplicate role: ${p.role} (one page per role)`);
|
|
10502
|
+
roles.add(p.role);
|
|
10503
|
+
req(p.pageId, `pages[${p.slug}].pageId`);
|
|
10504
|
+
req(p.stepId, `pages[${p.slug}].stepId`);
|
|
10505
|
+
req(p.slug, `pages[${p.slug}].slug`);
|
|
10506
|
+
if (p.role !== "home" && !params.content?.[p.role]) problems.push(`content.${p.role} is required for the ${p.role} page`);
|
|
10507
|
+
}
|
|
10508
|
+
if (roles.has("booking")) {
|
|
10509
|
+
const b = params.content?.booking;
|
|
10510
|
+
if (!b?.calendarId || !b?.calendarName) problems.push("content.booking.calendarId + calendarName are required (use get_calendars)");
|
|
10511
|
+
}
|
|
10512
|
+
if (!params.images?.logoUrl) warnings.push("topbar/nav/footer use the donor template's placeholder logo \u2014 provide images.logoUrl before customer use");
|
|
10513
|
+
if (!params.images?.heroUrl) warnings.push("home hero uses the donor template's stock image \u2014 replace before customer use");
|
|
10514
|
+
if (roles.has("contact") && !params.content?.contact?.mapLocation) warnings.push("contact map keeps the donor's placeholder location \u2014 pass content.contact.mapLocation");
|
|
10515
|
+
if (problems.length > 0) throw new Error("Website compliance gate failed:\n- " + problems.join("\n- "));
|
|
10516
|
+
return warnings;
|
|
10517
|
+
}
|
|
10518
|
+
function composeWebsitePage(spec, params) {
|
|
10519
|
+
const warnings = gate(params);
|
|
10520
|
+
const navItems = params.pages.map((p) => ({ title: p.navTitle, slug: p.slug, stepId: p.stepId }));
|
|
10521
|
+
const bookingPage = params.pages.find((p) => p.role === "booking");
|
|
10522
|
+
const bookingHref = bookingPage ? `/${bookingPage.slug}` : `/${params.pages[0].slug}`;
|
|
10523
|
+
const chrome = {
|
|
10524
|
+
topbar: () => buildTopbar({ phoneHtml: params.business.phoneHtml, logoUrl: params.images?.logoUrl }),
|
|
10525
|
+
nav: () => buildNav({ items: navItems, logoUrl: params.images?.logoUrl }),
|
|
10526
|
+
footer: () => buildFooter({
|
|
10527
|
+
businessLegalName: params.business.legalName,
|
|
10528
|
+
mailingAddress: params.business.mailingAddress,
|
|
10529
|
+
privacyUrl: params.business.privacyUrl,
|
|
10530
|
+
termsUrl: params.business.termsUrl,
|
|
10531
|
+
logoUrl: params.images?.logoUrl
|
|
10532
|
+
})
|
|
10533
|
+
};
|
|
10534
|
+
const body = [];
|
|
10535
|
+
const names = ["topbar", "nav"];
|
|
10536
|
+
const c = params.content;
|
|
10537
|
+
switch (spec.role) {
|
|
10538
|
+
case "home": {
|
|
10539
|
+
body.push(
|
|
10540
|
+
buildHero({ headline: c.home.headline, subhead: c.home.subhead, ctaLabel: c.home.ctaLabel, ctaHref: bookingHref, bgImageUrl: params.images?.heroUrl }),
|
|
10541
|
+
buildValueCards({ cards: c.home.cards }),
|
|
10542
|
+
buildImageText(c.home.imageText),
|
|
10543
|
+
buildCtaBanner({ title: "READY WHEN YOU ARE", bodyHtml: `<p>Book a time that suits you \u2014 we handle the rest.</p>`, buttonLabel: c.home.ctaLabel, buttonHref: bookingHref }),
|
|
10544
|
+
buildFaq({ title: c.home.faqTitle, items: c.home.faqs })
|
|
10545
|
+
);
|
|
10546
|
+
names.push("hero", "valueCards", "imageText", "ctaBanner", "faq");
|
|
10547
|
+
break;
|
|
10548
|
+
}
|
|
10549
|
+
case "about": {
|
|
10550
|
+
const a = c.about;
|
|
10551
|
+
if (!a) throw new Error("content.about missing");
|
|
10552
|
+
body.push(buildImageText(a.imageText));
|
|
10553
|
+
names.push("imageText");
|
|
10554
|
+
if (a.cta) {
|
|
10555
|
+
body.push(buildCtaBanner({ ...a.cta, buttonHref: bookingHref }));
|
|
10556
|
+
names.push("ctaBanner");
|
|
10557
|
+
}
|
|
10558
|
+
break;
|
|
10559
|
+
}
|
|
10560
|
+
case "services": {
|
|
10561
|
+
const sv = c.services;
|
|
10562
|
+
if (!sv) throw new Error("content.services missing");
|
|
10563
|
+
body.push(buildValueCards({ cards: sv.cards }));
|
|
10564
|
+
names.push("valueCards");
|
|
10565
|
+
if (sv.cta) {
|
|
10566
|
+
body.push(buildCtaBanner({ ...sv.cta, buttonHref: bookingHref }));
|
|
10567
|
+
names.push("ctaBanner");
|
|
10568
|
+
}
|
|
10569
|
+
break;
|
|
10570
|
+
}
|
|
10571
|
+
case "booking": {
|
|
10572
|
+
const b = c.booking;
|
|
10573
|
+
if (!b) throw new Error("content.booking missing");
|
|
10574
|
+
body.push(buildBooking(b));
|
|
10575
|
+
names.push("booking");
|
|
10576
|
+
break;
|
|
10577
|
+
}
|
|
10578
|
+
case "contact": {
|
|
10579
|
+
body.push(buildMapSection({ title: c.contact?.title, mapLocation: c.contact?.mapLocation }));
|
|
10580
|
+
names.push("map");
|
|
10581
|
+
break;
|
|
10582
|
+
}
|
|
10583
|
+
}
|
|
10584
|
+
names.push("footer");
|
|
10585
|
+
const ordered = [chrome.topbar(), chrome.nav(), ...body, chrome.footer()];
|
|
10586
|
+
const base = baseEnvelopeParts();
|
|
10587
|
+
let envelope = {
|
|
10588
|
+
sections: ordered.map((s, i) => ({ ...s.section, sequence: i })),
|
|
10589
|
+
settings: base.settings,
|
|
10590
|
+
general: base.general,
|
|
10591
|
+
pageStyles: base.pageStyles,
|
|
10592
|
+
trackingCode: base.trackingCode,
|
|
10593
|
+
fontsForPreview: themedFonts(params.theme ?? {}),
|
|
10594
|
+
popups: [],
|
|
10595
|
+
popupsList: []
|
|
10596
|
+
};
|
|
10597
|
+
if (params.theme) {
|
|
10598
|
+
envelope = applyTheme(envelope, params.theme);
|
|
10599
|
+
const fontProblems = assertFontMatrixComplete(envelope, params.theme);
|
|
10600
|
+
if (fontProblems.length > 0) throw new Error("Font matrix incomplete after theming:\n- " + fontProblems.join("\n- "));
|
|
10601
|
+
}
|
|
10602
|
+
return { spec, envelope, sections: names, warnings };
|
|
10603
|
+
}
|
|
10604
|
+
|
|
10605
|
+
// src/tools/page-studio.ts
|
|
10606
|
+
var valueCardSchema = import_zod35.z.object({
|
|
10607
|
+
title: import_zod35.z.string().describe("Card title (short, uppercase reads best)."),
|
|
10608
|
+
bodyHtml: import_zod35.z.string().describe("Card body as HTML (<p>\u2026</p>). May use {{location.*}} merge fields."),
|
|
10609
|
+
iconName: import_zod35.z.string().optional().describe("Font Awesome icon name (e.g. 'calendar-week', 'phone-square-alt', 'map-marker-alt').")
|
|
10610
|
+
});
|
|
10611
|
+
function registerPageStudioTools(server2, builderClient) {
|
|
10612
|
+
const client = builderClient;
|
|
10613
|
+
if (!client) return;
|
|
10614
|
+
async function funnelRequest(method, path11) {
|
|
10615
|
+
const headers = await client.buildHeaders();
|
|
10616
|
+
headers.Origin = "https://app.gohighlevel.com";
|
|
10617
|
+
headers.Referer = "https://app.gohighlevel.com/";
|
|
10618
|
+
const response = await fetch(`https://backend.leadconnectorhq.com/funnels${path11}`, { method, headers });
|
|
10619
|
+
if (!response.ok) throw new Error(`Funnel API Error ${response.status}: ${method} ${path11}
|
|
10620
|
+
${await response.text()}`);
|
|
10621
|
+
const text = await response.text();
|
|
10622
|
+
return text ? JSON.parse(text) : {};
|
|
10623
|
+
}
|
|
10624
|
+
async function autosaveRequest(pageId, body) {
|
|
10625
|
+
const headers = await client.buildHeaders();
|
|
10626
|
+
headers.Origin = "https://page-builder.leadconnectorhq.com";
|
|
10627
|
+
headers.Referer = "https://page-builder.leadconnectorhq.com/";
|
|
10628
|
+
const response = await fetch(`https://backend.leadconnectorhq.com/funnels/builder/autosave/${pageId}`, {
|
|
10629
|
+
method: "POST",
|
|
10630
|
+
headers,
|
|
10631
|
+
body: JSON.stringify(body)
|
|
10632
|
+
});
|
|
10633
|
+
if (!response.ok) throw new Error(`Funnel API Error ${response.status}: POST /builder/autosave/${pageId}
|
|
10634
|
+
${await response.text()}`);
|
|
10635
|
+
const text = await response.text();
|
|
10636
|
+
return text ? JSON.parse(text) : {};
|
|
10637
|
+
}
|
|
10638
|
+
function computeIntegrations(pageData) {
|
|
10639
|
+
const counts = {};
|
|
10640
|
+
const sections = Array.isArray(pageData.sections) ? pageData.sections : [];
|
|
10641
|
+
for (const sec of sections) {
|
|
10642
|
+
for (const el of sec.elements ?? []) {
|
|
10643
|
+
if (el.type !== "element" || typeof el.meta !== "string") continue;
|
|
10644
|
+
const key = el.meta.replace(/-([a-z])/g, (_m, c) => c.toUpperCase());
|
|
10645
|
+
counts[key] = (counts[key] ?? 0) + 1;
|
|
10646
|
+
}
|
|
10647
|
+
}
|
|
10648
|
+
return { videoBackground: false, blogMeta: { selectedBlogCategories: [], categoryNavigationList: [] }, ...counts, popup: false };
|
|
10649
|
+
}
|
|
10650
|
+
server2.tool(
|
|
10651
|
+
"compose_page",
|
|
10652
|
+
"Compose a COMPLETE designer-grade page from the built-in professional section library (cloned from a real GHL template: topbar, image hero, value cards, inline form with A2P disclosures, FAQ, compliant footer) and save it as a DRAFT onto an existing funnel/website page. Brand-themeable (colors + Google fonts). Copy may use {{location.*}} merge fields \u2014 GHL localizes them per account. Modes: dry_run returns the build report without writing; create writes only onto a page with no saved content. There is NO replace/overwrite mode \u2014 GHL only honors the FIRST save onto a page (later saves never become the visible version), so to redo a page delete its step and compose onto a fresh one. Existing pages can never be damaged: the tool refuses any page that has content, any page it cannot read, and any page belonging to a different funnel. The bound form must itself contain the SMS consent checkbox \u2014 this page provides the surrounding A2P disclosures (legal name, address, privacy/terms at point of capture, message description).",
|
|
10653
|
+
{
|
|
10654
|
+
pageId: import_zod35.z.string().describe("The page to write (from create_funnel_page or get_funnel_pages)."),
|
|
10655
|
+
funnelId: import_zod35.z.string().describe("The funnel/website that owns the page."),
|
|
10656
|
+
mode: import_zod35.z.enum(["dry_run", "create"]).describe("dry_run = build + report only. create = write only onto a page with no saved content. (There is no replace mode: GHL only honors the FIRST save onto a page \u2014 repeat saves are accepted but never become the visible version. To redo a page: delete the step, create a fresh one, compose again.)"),
|
|
10657
|
+
business: import_zod35.z.object({
|
|
10658
|
+
legalName: import_zod35.z.string().describe("Legal entity name (A2P: must be visible on the page)."),
|
|
10659
|
+
mailingAddress: import_zod35.z.string().describe("Full physical mailing address (A2P requirement)."),
|
|
10660
|
+
privacyUrl: import_zod35.z.string().describe("Live Privacy Policy URL (absolute)."),
|
|
10661
|
+
termsUrl: import_zod35.z.string().describe("Live Terms of Service URL (absolute)."),
|
|
10662
|
+
phoneHtml: import_zod35.z.string().optional().describe("Topbar phone HTML. Defaults to {{location.phone}}.")
|
|
10663
|
+
}),
|
|
10664
|
+
content: import_zod35.z.object({
|
|
10665
|
+
headline: import_zod35.z.string().describe("H1 + form section title."),
|
|
10666
|
+
subhead: import_zod35.z.string().describe("One-sentence supporting promise under the H1."),
|
|
10667
|
+
ctaLabel: import_zod35.z.string().describe("Hero button label; the button scrolls to the form."),
|
|
10668
|
+
cards: import_zod35.z.array(valueCardSchema).length(3).describe("Exactly 3 value cards."),
|
|
10669
|
+
faqTitle: import_zod35.z.string().optional().describe("FAQ section title. Default: donor's 'FREQUENTLY ASKED QUESTIONS'."),
|
|
10670
|
+
faqs: import_zod35.z.array(import_zod35.z.object({ q: import_zod35.z.string(), a: import_zod35.z.string() })).min(2).describe("FAQ items (4-8 recommended)."),
|
|
10671
|
+
disclosureHtml: import_zod35.z.string().optional().describe("A2P message description above the form. A compliant default is generated.")
|
|
10672
|
+
}),
|
|
10673
|
+
form: import_zod35.z.object({
|
|
10674
|
+
formId: import_zod35.z.string().describe("The GHL form to embed (must contain the SMS consent checkbox)."),
|
|
10675
|
+
formName: import_zod35.z.string().describe("The form's display name.")
|
|
10676
|
+
}),
|
|
10677
|
+
images: import_zod35.z.object({
|
|
10678
|
+
logoUrl: import_zod35.z.string().optional().describe("Brand logo URL (topbar + footer)."),
|
|
10679
|
+
heroUrl: import_zod35.z.string().optional().describe("Hero background image URL (client-owned)."),
|
|
10680
|
+
faqImageUrl: import_zod35.z.string().optional().describe("FAQ side image URL.")
|
|
10681
|
+
}).optional(),
|
|
10682
|
+
theme: import_zod35.z.object({
|
|
10683
|
+
primary: import_zod35.z.string().optional().describe("Brand primary hex (#rrggbb)."),
|
|
10684
|
+
primarySoft: import_zod35.z.string().optional().describe("Soft tint of the primary."),
|
|
10685
|
+
surface: import_zod35.z.string().optional().describe("Light surface background hex."),
|
|
10686
|
+
textDark: import_zod35.z.string().optional().describe("Dark text hex."),
|
|
10687
|
+
headingFont: import_zod35.z.string().optional().describe("Google Fonts name for headings."),
|
|
10688
|
+
bodyFont: import_zod35.z.string().optional().describe("Google Fonts name for body text.")
|
|
10689
|
+
}).optional().describe("Brand theme. Omit to keep the donor template's look.")
|
|
10690
|
+
},
|
|
10691
|
+
async (args) => {
|
|
10692
|
+
try {
|
|
10693
|
+
const params = {
|
|
10694
|
+
business: args.business,
|
|
10695
|
+
content: { ...args.content, cards: args.content.cards },
|
|
10696
|
+
form: args.form,
|
|
10697
|
+
images: args.images,
|
|
10698
|
+
theme: args.theme
|
|
10699
|
+
};
|
|
10700
|
+
const { envelope, report } = composeOptinPage(params);
|
|
10701
|
+
if (args.mode === "dry_run") {
|
|
10702
|
+
return jsonResponse({ mode: "dry_run", wrote: false, report, sectionCount: envelope.sections.length, envelopeBytes: JSON.stringify(envelope).length });
|
|
10703
|
+
}
|
|
10704
|
+
const result = await savePageGuarded({ pageId: args.pageId, funnelId: args.funnelId, envelope });
|
|
10705
|
+
return jsonResponse({ mode: args.mode, wrote: true, pageId: args.pageId, report, ...result, next: NEXT_NOTE });
|
|
10706
|
+
} catch (error) {
|
|
10707
|
+
return errorResponse(error);
|
|
10708
|
+
}
|
|
10709
|
+
}
|
|
10710
|
+
);
|
|
10711
|
+
const NEXT_NOTE = "The save is a DRAFT. Read get_page_full for the regenerated previewSnapshot (allow a few seconds), review desktop AND mobile, then publish in the GHL UI when it looks right.";
|
|
10712
|
+
async function preflightPage(input) {
|
|
10713
|
+
const { pageId, funnelId } = input;
|
|
10714
|
+
let meta = null;
|
|
10715
|
+
for (let attempt = 1; attempt <= 10; attempt++) {
|
|
10716
|
+
try {
|
|
10717
|
+
meta = await funnelRequest("GET", `/page/${pageId}?locationId=${client.locationId}`);
|
|
10718
|
+
break;
|
|
10719
|
+
} catch (e) {
|
|
10720
|
+
const freshRace = /does not exist or is deleted/i.test(String(e));
|
|
10721
|
+
if (attempt === 10) {
|
|
10722
|
+
throw new Error(
|
|
10723
|
+
`Refusing to write: page ${pageId} could not be read after ${attempt} attempts ` + (freshRace ? "(still propagating after creation \u2014 wait ~30s and retry)." : `(last error: ${String(e).slice(0, 200)}). Writing without reading the page risks overwriting existing content.`)
|
|
10724
|
+
);
|
|
10725
|
+
}
|
|
10726
|
+
await new Promise((r) => setTimeout(r, 700 * attempt));
|
|
10727
|
+
}
|
|
10728
|
+
}
|
|
10729
|
+
const m = meta;
|
|
10730
|
+
const metaFunnelId = typeof m.funnelId === "string" ? m.funnelId : null;
|
|
10731
|
+
if (metaFunnelId && metaFunnelId !== funnelId) {
|
|
10732
|
+
throw new Error(`Page ${pageId} belongs to funnel ${metaFunnelId}, not ${funnelId}. Refusing to write to a page outside the target funnel/website.`);
|
|
10733
|
+
}
|
|
10734
|
+
const livePageVersion = typeof m.pageVersion === "number" ? m.pageVersion : typeof m.version === "number" ? m.version : 1;
|
|
10735
|
+
const priorDataUrl = typeof m.pageDataDownloadUrl === "string" ? m.pageDataDownloadUrl : null;
|
|
10736
|
+
const refuseCreate = (version) => {
|
|
10737
|
+
throw new Error(
|
|
10738
|
+
`Page ${pageId} already has saved content (pageVersion ${version}). GHL only honors the FIRST save onto a page, so this page cannot be re-composed. Delete its step (delete_funnel_page), create a fresh one (create_funnel_page), and compose again.`
|
|
10739
|
+
);
|
|
10740
|
+
};
|
|
10741
|
+
if (priorDataUrl) refuseCreate(livePageVersion);
|
|
10742
|
+
for (let confirm = 0; confirm < 3; confirm++) {
|
|
10743
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
10744
|
+
let again = null;
|
|
10745
|
+
try {
|
|
10746
|
+
again = await funnelRequest("GET", `/page/${pageId}?locationId=${client.locationId}`);
|
|
10747
|
+
} catch {
|
|
10748
|
+
again = null;
|
|
10749
|
+
}
|
|
10750
|
+
if (again && typeof again.pageDataDownloadUrl === "string" && again.pageDataDownloadUrl.length > 0) {
|
|
10751
|
+
refuseCreate(typeof again.pageVersion === "number" ? again.pageVersion : livePageVersion);
|
|
10752
|
+
}
|
|
10753
|
+
}
|
|
10754
|
+
return { pageId, livePageVersion, priorDataUrl };
|
|
10755
|
+
}
|
|
10756
|
+
async function performSave(input) {
|
|
10757
|
+
const { funnelId, envelope, pre } = input;
|
|
10758
|
+
const savePageVersion = pre.livePageVersion;
|
|
10759
|
+
const sections = envelope.sections.map((s) => ({ ...s, pageId: pre.pageId, funnelId, locationId: client.locationId }));
|
|
10760
|
+
const pageData = {
|
|
10761
|
+
...envelope,
|
|
10762
|
+
sections,
|
|
10763
|
+
pageVersion: savePageVersion,
|
|
10764
|
+
pageType: "draft",
|
|
10765
|
+
manualSave: true,
|
|
10766
|
+
integrations: computeIntegrations({ sections })
|
|
10767
|
+
};
|
|
10768
|
+
const saved = await autosaveRequest(pre.pageId, { funnelId, pageVersion: savePageVersion, pageData });
|
|
10769
|
+
const savedDataUrl = typeof saved.pageDataUrl === "string" ? saved.pageDataUrl : null;
|
|
10770
|
+
let verified = false;
|
|
10771
|
+
for (let attempt = 1; attempt <= 8 && !verified; attempt++) {
|
|
10772
|
+
await new Promise((r) => setTimeout(r, 4e3));
|
|
10773
|
+
try {
|
|
10774
|
+
const now = await funnelRequest("GET", `/page/${pre.pageId}?locationId=${client.locationId}`);
|
|
10775
|
+
const nowUrl = typeof now.pageDataUrl === "string" ? now.pageDataUrl : "";
|
|
10776
|
+
if (savedDataUrl !== null && nowUrl === savedDataUrl) verified = true;
|
|
10777
|
+
} catch {
|
|
10778
|
+
}
|
|
10779
|
+
}
|
|
10780
|
+
return {
|
|
10781
|
+
saved,
|
|
10782
|
+
verified,
|
|
10783
|
+
...verified ? {} : { verifyNote: "The save was accepted but the page has not yet reported the new content (eventual consistency). Re-check get_page_full in a minute before publishing; if it never advances, the save did not take." }
|
|
10784
|
+
};
|
|
10785
|
+
}
|
|
10786
|
+
async function savePageGuarded(input) {
|
|
10787
|
+
const pre = await preflightPage({ pageId: input.pageId, funnelId: input.funnelId });
|
|
10788
|
+
return performSave({ funnelId: input.funnelId, envelope: input.envelope, pre });
|
|
10789
|
+
}
|
|
10790
|
+
const websitePageSpecSchema = import_zod35.z.object({
|
|
10791
|
+
pageId: import_zod35.z.string().describe("The page id (from create_funnel_page / get_funnel_pages)."),
|
|
10792
|
+
stepId: import_zod35.z.string().describe("The step id that owns the page (nav items wire to this)."),
|
|
10793
|
+
slug: import_zod35.z.string().describe("Step slug without the leading slash (e.g. 'home', 'booking')."),
|
|
10794
|
+
role: import_zod35.z.enum(["home", "about", "services", "booking", "contact"]).describe("Page archetype."),
|
|
10795
|
+
navTitle: import_zod35.z.string().describe("Menu label for this page.")
|
|
10796
|
+
});
|
|
10797
|
+
const imageTextSchema = import_zod35.z.object({
|
|
10798
|
+
title: import_zod35.z.string(),
|
|
10799
|
+
features: import_zod35.z.array(import_zod35.z.object({ title: import_zod35.z.string(), bodyHtml: import_zod35.z.string() })).length(3).describe("Exactly 3 feature blocks (title + HTML body)."),
|
|
10800
|
+
imageUrl: import_zod35.z.string().optional()
|
|
10801
|
+
});
|
|
10802
|
+
server2.tool(
|
|
10803
|
+
"compose_website",
|
|
10804
|
+
"Compose a COMPLETE multi-page WEBSITE (created via create_funnel type:'website') from the professional section library: every page gets topbar + nav (menu items wired to the real steps) + role-specific sections + A2P-compliant footer, brand-themed. Roles: home (hero, value cards, feature block, CTA banner, FAQ), about, services, booking (embeds a real calendar \u2014 verify the id with get_calendars first), contact (map + merge-field contact lines). Nav/header/footer are per-page copies (visually identical to shared sections). Create the website + one step per page first (create_funnel, create_funnel_page), then call this with each page's ids. Modes: dry_run builds + reports without writing; create writes only onto pages with no saved content (no overwrite mode exists \u2014 GHL honors only the FIRST save onto a page; redo = delete the step, create a fresh one). All pages are preflighted (readable, empty, owned by this funnel) BEFORE the first save; saves are DRAFTS and run sequentially with halt-and-report.",
|
|
10805
|
+
{
|
|
10806
|
+
funnelId: import_zod35.z.string().describe("The website's funnel id (create_funnel type:'website')."),
|
|
10807
|
+
mode: import_zod35.z.enum(["dry_run", "create"]).describe("dry_run = build + report only. create = write only onto pages with no saved content. (No replace mode: GHL only honors the FIRST save onto a page. To redo a page: delete its step, create a fresh one, re-run for that page.)"),
|
|
10808
|
+
pages: import_zod35.z.array(websitePageSpecSchema).min(1).describe("The pages to compose. Exactly one 'home' required; one page per role."),
|
|
10809
|
+
business: import_zod35.z.object({
|
|
10810
|
+
legalName: import_zod35.z.string(),
|
|
10811
|
+
mailingAddress: import_zod35.z.string(),
|
|
10812
|
+
privacyUrl: import_zod35.z.string(),
|
|
10813
|
+
termsUrl: import_zod35.z.string(),
|
|
10814
|
+
phoneHtml: import_zod35.z.string().optional()
|
|
10815
|
+
}).describe("Footer legal block on every page (A2P)."),
|
|
10816
|
+
images: import_zod35.z.object({ logoUrl: import_zod35.z.string().optional(), heroUrl: import_zod35.z.string().optional() }).optional(),
|
|
10817
|
+
theme: import_zod35.z.object({
|
|
10818
|
+
primary: import_zod35.z.string().optional(),
|
|
10819
|
+
primarySoft: import_zod35.z.string().optional(),
|
|
10820
|
+
surface: import_zod35.z.string().optional(),
|
|
10821
|
+
textDark: import_zod35.z.string().optional(),
|
|
10822
|
+
headingFont: import_zod35.z.string().optional(),
|
|
10823
|
+
bodyFont: import_zod35.z.string().optional()
|
|
10824
|
+
}).optional(),
|
|
10825
|
+
content: import_zod35.z.object({
|
|
10826
|
+
home: import_zod35.z.object({
|
|
10827
|
+
headline: import_zod35.z.string(),
|
|
10828
|
+
subhead: import_zod35.z.string(),
|
|
10829
|
+
ctaLabel: import_zod35.z.string(),
|
|
10830
|
+
cards: import_zod35.z.array(valueCardSchema).length(3),
|
|
10831
|
+
imageText: imageTextSchema,
|
|
10832
|
+
faqTitle: import_zod35.z.string().optional(),
|
|
10833
|
+
faqs: import_zod35.z.array(import_zod35.z.object({ q: import_zod35.z.string(), a: import_zod35.z.string() })).min(2)
|
|
10834
|
+
}),
|
|
10835
|
+
about: import_zod35.z.object({
|
|
10836
|
+
imageText: imageTextSchema,
|
|
10837
|
+
cta: import_zod35.z.object({ title: import_zod35.z.string(), bodyHtml: import_zod35.z.string(), buttonLabel: import_zod35.z.string() }).optional()
|
|
10838
|
+
}).optional(),
|
|
10839
|
+
services: import_zod35.z.object({
|
|
10840
|
+
cards: import_zod35.z.array(valueCardSchema).length(3),
|
|
10841
|
+
cta: import_zod35.z.object({ title: import_zod35.z.string(), bodyHtml: import_zod35.z.string(), buttonLabel: import_zod35.z.string() }).optional()
|
|
10842
|
+
}).optional(),
|
|
10843
|
+
booking: import_zod35.z.object({
|
|
10844
|
+
calendarId: import_zod35.z.string().describe("Real calendar id \u2014 verify with get_calendars; a bad id shows an empty booking widget."),
|
|
10845
|
+
calendarName: import_zod35.z.string(),
|
|
10846
|
+
title: import_zod35.z.string().optional(),
|
|
10847
|
+
bodyHtml: import_zod35.z.string().optional()
|
|
10848
|
+
}).optional(),
|
|
10849
|
+
contact: import_zod35.z.object({
|
|
10850
|
+
title: import_zod35.z.string().optional(),
|
|
10851
|
+
mapLocation: import_zod35.z.object({ name: import_zod35.z.string(), lat: import_zod35.z.number(), lng: import_zod35.z.number(), placeId: import_zod35.z.string().optional() }).optional()
|
|
10852
|
+
}).optional()
|
|
10853
|
+
})
|
|
10854
|
+
},
|
|
10855
|
+
async (args) => {
|
|
10856
|
+
try {
|
|
10857
|
+
const params = {
|
|
10858
|
+
business: args.business,
|
|
10859
|
+
images: args.images,
|
|
10860
|
+
theme: args.theme,
|
|
10861
|
+
pages: args.pages,
|
|
10862
|
+
content: args.content
|
|
10863
|
+
};
|
|
10864
|
+
const results = args.pages.map((spec) => composeWebsitePage(spec, params));
|
|
10865
|
+
if (args.mode === "dry_run") {
|
|
10866
|
+
return jsonResponse({
|
|
10867
|
+
mode: "dry_run",
|
|
10868
|
+
wrote: false,
|
|
10869
|
+
pages: results.map((r) => ({ slug: r.spec.slug, role: r.spec.role, sections: r.sections, envelopeBytes: JSON.stringify(r.envelope).length })),
|
|
10870
|
+
warnings: results[0]?.warnings ?? []
|
|
10871
|
+
});
|
|
10872
|
+
}
|
|
10873
|
+
const preflights = [];
|
|
10874
|
+
for (const r of results) {
|
|
10875
|
+
try {
|
|
10876
|
+
preflights.push({ r, pre: await preflightPage({ pageId: r.spec.pageId, funnelId: args.funnelId }) });
|
|
10877
|
+
} catch (e) {
|
|
10878
|
+
return jsonResponse({
|
|
10879
|
+
mode: args.mode,
|
|
10880
|
+
wrote: false,
|
|
10881
|
+
failedPreflight: { slug: r.spec.slug, pageId: r.spec.pageId, error: String(e) },
|
|
10882
|
+
note: "Nothing was written \u2014 the preflight failed before the first save. Fix the reported page and re-run."
|
|
10883
|
+
});
|
|
10884
|
+
}
|
|
10885
|
+
}
|
|
10886
|
+
const written = [];
|
|
10887
|
+
for (const { r, pre } of preflights) {
|
|
10888
|
+
try {
|
|
10889
|
+
const saved = await performSave({ funnelId: args.funnelId, envelope: r.envelope, pre });
|
|
10890
|
+
written.push({ slug: r.spec.slug, role: r.spec.role, pageId: r.spec.pageId, wrote: true, ...saved });
|
|
10891
|
+
} catch (e) {
|
|
10892
|
+
return jsonResponse({
|
|
10893
|
+
mode: args.mode,
|
|
10894
|
+
wrote: written.length > 0,
|
|
10895
|
+
pages: written,
|
|
10896
|
+
failedAt: { slug: r.spec.slug, pageId: r.spec.pageId, error: String(e) },
|
|
10897
|
+
note: "Run halted at the first failing save. Already-written pages are drafts and stay as saved. Fix the failure, delete + recreate any unfinished steps, and re-run for the remaining pages."
|
|
10898
|
+
});
|
|
10899
|
+
}
|
|
10900
|
+
}
|
|
10901
|
+
return jsonResponse({ mode: args.mode, wrote: true, pages: written, warnings: results[0]?.warnings ?? [], next: NEXT_NOTE });
|
|
10902
|
+
} catch (error) {
|
|
10903
|
+
return errorResponse(error);
|
|
10904
|
+
}
|
|
10905
|
+
}
|
|
10906
|
+
);
|
|
10907
|
+
}
|
|
10908
|
+
|
|
10909
|
+
// src/tools/form-builder.ts
|
|
10910
|
+
var import_zod36 = require("zod");
|
|
9818
10911
|
function pickFormName(builderForm) {
|
|
9819
10912
|
if (builderForm && typeof builderForm === "object" && "form" in builderForm) {
|
|
9820
10913
|
const name = builderForm.form?.name;
|
|
@@ -9871,7 +10964,7 @@ function registerFormBuilderTools(server2, builderClient, publicClient) {
|
|
|
9871
10964
|
"get_form_full",
|
|
9872
10965
|
"Get a form with full builder data: all fields (labels, types, IDs, validation), conditional logic, auto-responder config, email notification settings, styling, and version history. This is the internal API \u2014 it returns everything the form builder UI shows.",
|
|
9873
10966
|
{
|
|
9874
|
-
formId:
|
|
10967
|
+
formId: import_zod36.z.string().describe("The form ID to retrieve.")
|
|
9875
10968
|
},
|
|
9876
10969
|
async ({ formId }) => {
|
|
9877
10970
|
try {
|
|
@@ -9888,9 +10981,9 @@ function registerFormBuilderTools(server2, builderClient, publicClient) {
|
|
|
9888
10981
|
"update_form",
|
|
9889
10982
|
"Update a form's structure \u2014 fields, labels, conditional logic, auto-responder, email notifications, styling. Use get_form_full first to read the current form, modify the formData object, then pass it here. If name is omitted, the current name is preserved (one extra GET).",
|
|
9890
10983
|
{
|
|
9891
|
-
formId:
|
|
9892
|
-
formData:
|
|
9893
|
-
name:
|
|
10984
|
+
formId: import_zod36.z.string().describe("The form ID to update."),
|
|
10985
|
+
formData: import_zod36.z.record(import_zod36.z.unknown()).describe("The updated formData object containing form fields, settings, autoResponder config, etc."),
|
|
10986
|
+
name: import_zod36.z.string().optional().describe("Updated form name. If omitted, the current name is preserved.")
|
|
9894
10987
|
},
|
|
9895
10988
|
async ({ formId, formData, name }) => {
|
|
9896
10989
|
try {
|
|
@@ -9937,7 +11030,7 @@ function registerFormBuilderTools(server2, builderClient, publicClient) {
|
|
|
9937
11030
|
"create_form",
|
|
9938
11031
|
"Create a new form. Starts with a basic structure \u2014 use update_form to add fields and configure settings.",
|
|
9939
11032
|
{
|
|
9940
|
-
name:
|
|
11033
|
+
name: import_zod36.z.string().describe("Name for the new form.")
|
|
9941
11034
|
},
|
|
9942
11035
|
async ({ name }) => {
|
|
9943
11036
|
try {
|
|
@@ -9963,8 +11056,8 @@ function registerFormBuilderTools(server2, builderClient, publicClient) {
|
|
|
9963
11056
|
"delete_form",
|
|
9964
11057
|
"Permanently delete a form. IRREVERSIBLE.",
|
|
9965
11058
|
{
|
|
9966
|
-
formId:
|
|
9967
|
-
confirm:
|
|
11059
|
+
formId: import_zod36.z.string().describe("The form ID to delete."),
|
|
11060
|
+
confirm: import_zod36.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
9968
11061
|
},
|
|
9969
11062
|
async ({ formId }) => {
|
|
9970
11063
|
try {
|
|
@@ -9981,9 +11074,9 @@ function registerFormBuilderTools(server2, builderClient, publicClient) {
|
|
|
9981
11074
|
"get_form_submissions_full",
|
|
9982
11075
|
"Get form submissions with full field data, contact info, and submission timestamps via the internal API. Offset-based pagination via skip/limit.",
|
|
9983
11076
|
{
|
|
9984
|
-
formId:
|
|
9985
|
-
limit:
|
|
9986
|
-
skip:
|
|
11077
|
+
formId: import_zod36.z.string().optional().describe("Filter by form ID. If omitted, returns all submissions."),
|
|
11078
|
+
limit: import_zod36.z.number().optional().describe("Max submissions to return. Defaults to 20."),
|
|
11079
|
+
skip: import_zod36.z.number().optional().describe("Number to skip for pagination.")
|
|
9987
11080
|
},
|
|
9988
11081
|
async ({ formId, limit, skip }) => {
|
|
9989
11082
|
try {
|
|
@@ -10002,7 +11095,7 @@ function registerFormBuilderTools(server2, builderClient, publicClient) {
|
|
|
10002
11095
|
}
|
|
10003
11096
|
|
|
10004
11097
|
// src/tools/funnel-qa.ts
|
|
10005
|
-
var
|
|
11098
|
+
var import_zod37 = require("zod");
|
|
10006
11099
|
var asObj = (v) => v && typeof v === "object" ? v : {};
|
|
10007
11100
|
var asArr = (v) => Array.isArray(v) ? v : [];
|
|
10008
11101
|
var str = (v) => typeof v === "string" ? v : void 0;
|
|
@@ -10126,34 +11219,34 @@ async function submit(url, body) {
|
|
|
10126
11219
|
const text = (await res.text().catch(() => "")).slice(0, 300);
|
|
10127
11220
|
return { httpStatus: res.status, blockedByCaptcha: res.status === 403 && /captcha|turnstile/i.test(text), text };
|
|
10128
11221
|
}
|
|
10129
|
-
var customFieldInput =
|
|
10130
|
-
fieldId:
|
|
10131
|
-
value:
|
|
10132
|
-
label:
|
|
11222
|
+
var customFieldInput = import_zod37.z.object({
|
|
11223
|
+
fieldId: import_zod37.z.string().describe("The VERIFIED GHL custom-field id the form sends (from apply_build_plan's wiring bundle)."),
|
|
11224
|
+
value: import_zod37.z.string().describe("The value the form sends for this field \u2014 asserted to PERSIST on the contact."),
|
|
11225
|
+
label: import_zod37.z.string().optional().describe("Human label (informational).")
|
|
10133
11226
|
});
|
|
10134
11227
|
function registerFunnelQaTools(server2, client, builderClient) {
|
|
10135
11228
|
server2.tool(
|
|
10136
11229
|
"verify_funnel",
|
|
10137
11230
|
"Prove a live public funnel actually captures a lead AND the automation acts on it \u2014 the runtime companion to audit_workflows. Submits a sentinel lead to funnelUrl, then reads GHL back to verify what REALLY happened (the UI/thank-you page is never proof): (1) backend contact truth \u2014 the contact is actually created (search_contacts), with submit\u2192appear latency; (2) field-value fidelity \u2014 each expectCustom value actually PERSISTED on the contact (a wrong field id makes upsert succeed while silently dropping the value); (3) the triggerTag landed (else the workflow can't fire); (4) SMS/A2P pre-check \u2014 flags if the account has no SMS-capable number so any SMS step would silently fail; (5) workflow status \u2014 flags a DRAFT workflow (never fires on real leads); (6) outreach fired \u2014 an OUTBOUND message was actually logged for the contact (proves enrollment + send, not just a green log), with latency; (7) consent recorded when messaging fires (TCPA/CAN-SPAM); (8) duplicate-contact retest \u2014 a second identical submit dedups to ONE contact, not a duplicate/false-failure; (9) opportunity/routing (expectOpportunity/expectAssigned/expectSource); (10) multi-surface (extraUrls) + concurrent double-submit race. Booking can't be faked server-side, so a real burner appointment is surfaced as a manual step. WARNING: this creates a real (clearly-marked 'blueprint-qa') contact and MAY fire real automation + internal notifications; it deletes the sentinel afterward by default (cleanup). Run it on the REAL production URL.",
|
|
10138
11231
|
{
|
|
10139
|
-
funnelUrl:
|
|
10140
|
-
sentinelEmail:
|
|
10141
|
-
testPhone:
|
|
10142
|
-
submitBody:
|
|
10143
|
-
expectCustom:
|
|
10144
|
-
expectStandard:
|
|
10145
|
-
triggerTag:
|
|
10146
|
-
workflowId:
|
|
10147
|
-
consentFieldId:
|
|
10148
|
-
expectOutreach:
|
|
10149
|
-
outreachWaitSec:
|
|
10150
|
-
expectOpportunity:
|
|
10151
|
-
expectAssigned:
|
|
10152
|
-
expectSource:
|
|
10153
|
-
extraUrls:
|
|
10154
|
-
testConcurrentDuplicate:
|
|
10155
|
-
cleanup:
|
|
10156
|
-
locationId:
|
|
11232
|
+
funnelUrl: import_zod37.z.string().describe("The live URL the test submission POSTs to (your external lead-bridge Worker URL, or any endpoint that creates the GHL contact). POSTed as JSON."),
|
|
11233
|
+
sentinelEmail: import_zod37.z.string().optional().describe("Override the minted sentinel email. Default: a unique blueprint-qa.<id>@example.com (won't deliver; used only to find the contact)."),
|
|
11234
|
+
testPhone: import_zod37.z.string().optional().describe("Include a phone on the submission (enables SMS-path checks). Must be a test-safe number you control \u2014 real SMS may send + bill."),
|
|
11235
|
+
submitBody: import_zod37.z.record(import_zod37.z.unknown()).optional().describe("Full JSON body to POST (advanced; for non-bridge endpoints). The sentinel email is injected if absent. Default body is the lead-bridge contract {first_name,last_name,email,phone,custom,_hp}."),
|
|
11236
|
+
expectCustom: import_zod37.z.array(customFieldInput).optional().describe("Custom fields the form sends \u2014 each is asserted to PERSIST with the sent value (field-value fidelity, Carlos #3)."),
|
|
11237
|
+
expectStandard: import_zod37.z.array(import_zod37.z.string()).optional().describe("Standard contact keys to assert saved (e.g. ['phone','first_name']). email is always asserted."),
|
|
11238
|
+
triggerTag: import_zod37.z.string().optional().describe("The tag the form/bridge should add (the speed-to-lead trigger). Asserted to land on the contact."),
|
|
11239
|
+
workflowId: import_zod37.z.string().optional().describe("The speed-to-lead workflow to inspect \u2014 flags DRAFT status and cross-checks SMS capability."),
|
|
11240
|
+
consentFieldId: import_zod37.z.string().optional().describe("Custom field id that records consent \u2014 asserted populated when messaging fires (legal)."),
|
|
11241
|
+
expectOutreach: import_zod37.z.boolean().optional().describe("Poll the message log for an OUTBOUND message to the contact (proves the automation fired + sent). Defaults true when triggerTag or workflowId is given."),
|
|
11242
|
+
outreachWaitSec: import_zod37.z.number().optional().describe("How long to poll for the outbound message (default 90s)."),
|
|
11243
|
+
expectOpportunity: import_zod37.z.object({ pipelineId: import_zod37.z.string().optional(), stageId: import_zod37.z.string().optional() }).optional().describe("Assert an opportunity was created for the contact (optionally in this pipeline/stage)."),
|
|
11244
|
+
expectAssigned: import_zod37.z.boolean().optional().describe("Assert the contact was assigned to a user (someone follows up)."),
|
|
11245
|
+
expectSource: import_zod37.z.boolean().optional().describe("Assert a lead source/attribution was captured (reporting works)."),
|
|
11246
|
+
extraUrls: import_zod37.z.array(import_zod37.z.string()).optional().describe("Additional capture surfaces to test the same way (each gets its own sentinel) \u2014 popup/inline/exit-intent forms."),
|
|
11247
|
+
testConcurrentDuplicate: import_zod37.z.boolean().optional().describe("Fire two simultaneous submits with a fresh email \u2192 assert exactly ONE contact (concurrent dedup race)."),
|
|
11248
|
+
cleanup: import_zod37.z.boolean().optional().describe("Delete the sentinel contact(s) after verifying. Default true."),
|
|
11249
|
+
locationId: import_zod37.z.string().optional().describe("Target sub-account. Must match the active location.")
|
|
10157
11250
|
},
|
|
10158
11251
|
async (args) => {
|
|
10159
11252
|
try {
|
|
@@ -10365,21 +11458,21 @@ function registerFunnelQaTools(server2, client, builderClient) {
|
|
|
10365
11458
|
checks.push({ id: "cleanup", label: "Sentinel cleanup", status: cleanedUp ? "pass" : "warn", detail: cleanedUp ? `Deleted ${deleted} sentinel contact(s).` : `Deleted ${deleted}/${uniq.length} sentinel contact(s) \u2014 remove any leftover "blueprint-qa" contacts manually.` });
|
|
10366
11459
|
}
|
|
10367
11460
|
}
|
|
10368
|
-
return
|
|
11461
|
+
return finish2(checks, { contactId, sentinelEmail: searchEmail, cleanedUp });
|
|
10369
11462
|
} catch (error) {
|
|
10370
11463
|
return errorResponse(error);
|
|
10371
11464
|
}
|
|
10372
11465
|
}
|
|
10373
11466
|
);
|
|
10374
11467
|
}
|
|
10375
|
-
function
|
|
11468
|
+
function finish2(checks, extra) {
|
|
10376
11469
|
const { ok, verdict, summary } = rollupVerdict(checks);
|
|
10377
11470
|
const note = "WARNING: verify_funnel created a real (clearly-marked 'blueprint-qa') contact and may have fired real automation + internal notifications. Run on the real production URL; the form/thank-you page is never proof \u2014 only the backend is.";
|
|
10378
11471
|
return jsonResponse({ ok, verdict, summary, checks, note, ...extra });
|
|
10379
11472
|
}
|
|
10380
11473
|
|
|
10381
11474
|
// src/tools/pipeline-builder.ts
|
|
10382
|
-
var
|
|
11475
|
+
var import_zod38 = require("zod");
|
|
10383
11476
|
function registerPipelineBuilderTools(server2, builderClient) {
|
|
10384
11477
|
const client = builderClient;
|
|
10385
11478
|
if (!client) return;
|
|
@@ -10424,7 +11517,7 @@ ${text2}`);
|
|
|
10424
11517
|
"get_pipeline_full",
|
|
10425
11518
|
"Get a single pipeline with complete stage configuration: IDs, names, positions, display settings.",
|
|
10426
11519
|
{
|
|
10427
|
-
pipelineId:
|
|
11520
|
+
pipelineId: import_zod38.z.string().describe("The pipeline ID to retrieve.")
|
|
10428
11521
|
},
|
|
10429
11522
|
async ({ pipelineId }) => {
|
|
10430
11523
|
try {
|
|
@@ -10442,17 +11535,17 @@ ${text2}`);
|
|
|
10442
11535
|
"create_pipeline",
|
|
10443
11536
|
"Create a new pipeline with stages. Each stage needs a name and position (0-based).",
|
|
10444
11537
|
{
|
|
10445
|
-
name:
|
|
10446
|
-
stages:
|
|
10447
|
-
|
|
10448
|
-
name:
|
|
10449
|
-
position:
|
|
10450
|
-
showInFunnel:
|
|
10451
|
-
showInPieChart:
|
|
11538
|
+
name: import_zod38.z.string().describe("Pipeline name."),
|
|
11539
|
+
stages: import_zod38.z.array(
|
|
11540
|
+
import_zod38.z.object({
|
|
11541
|
+
name: import_zod38.z.string().describe("Stage name."),
|
|
11542
|
+
position: import_zod38.z.number().describe("Stage position (0-based)."),
|
|
11543
|
+
showInFunnel: import_zod38.z.boolean().optional().describe("Show in funnel view. Defaults to true."),
|
|
11544
|
+
showInPieChart: import_zod38.z.boolean().optional().describe("Show in pie chart. Defaults to true.")
|
|
10452
11545
|
})
|
|
10453
11546
|
).describe("Array of stages in order."),
|
|
10454
|
-
showInFunnel:
|
|
10455
|
-
showInPieChart:
|
|
11547
|
+
showInFunnel: import_zod38.z.boolean().optional().describe("Show pipeline in funnel view. Defaults to true."),
|
|
11548
|
+
showInPieChart: import_zod38.z.boolean().optional().describe("Show pipeline in pie chart. Defaults to true.")
|
|
10456
11549
|
},
|
|
10457
11550
|
async ({ name, stages, showInFunnel, showInPieChart }) => {
|
|
10458
11551
|
try {
|
|
@@ -10482,19 +11575,19 @@ ${text2}`);
|
|
|
10482
11575
|
"update_pipeline",
|
|
10483
11576
|
"Update a pipeline's name, stages, or display settings. You can add, remove, rename, or reorder stages. Pass the complete stages array \u2014 stages not included will be removed.",
|
|
10484
11577
|
{
|
|
10485
|
-
pipelineId:
|
|
10486
|
-
name:
|
|
10487
|
-
stages:
|
|
10488
|
-
|
|
10489
|
-
id:
|
|
10490
|
-
name:
|
|
10491
|
-
position:
|
|
10492
|
-
showInFunnel:
|
|
10493
|
-
showInPieChart:
|
|
11578
|
+
pipelineId: import_zod38.z.string().describe("The pipeline ID to update."),
|
|
11579
|
+
name: import_zod38.z.string().optional().describe("New pipeline name."),
|
|
11580
|
+
stages: import_zod38.z.array(
|
|
11581
|
+
import_zod38.z.object({
|
|
11582
|
+
id: import_zod38.z.string().optional().describe("Existing stage ID (omit for new stages)."),
|
|
11583
|
+
name: import_zod38.z.string().describe("Stage name."),
|
|
11584
|
+
position: import_zod38.z.number().describe("Stage position (0-based)."),
|
|
11585
|
+
showInFunnel: import_zod38.z.boolean().optional().describe("Show in funnel view."),
|
|
11586
|
+
showInPieChart: import_zod38.z.boolean().optional().describe("Show in pie chart.")
|
|
10494
11587
|
})
|
|
10495
11588
|
).optional().describe("Complete stages array. Stages not included will be removed."),
|
|
10496
|
-
showInFunnel:
|
|
10497
|
-
showInPieChart:
|
|
11589
|
+
showInFunnel: import_zod38.z.boolean().optional().describe("Show pipeline in funnel view."),
|
|
11590
|
+
showInPieChart: import_zod38.z.boolean().optional().describe("Show pipeline in pie chart.")
|
|
10498
11591
|
},
|
|
10499
11592
|
async ({ pipelineId, name, stages, showInFunnel, showInPieChart }) => {
|
|
10500
11593
|
try {
|
|
@@ -10517,8 +11610,8 @@ ${text2}`);
|
|
|
10517
11610
|
"delete_pipeline",
|
|
10518
11611
|
"Permanently delete a pipeline and all its stages. Opportunities become unassigned. IRREVERSIBLE.",
|
|
10519
11612
|
{
|
|
10520
|
-
pipelineId:
|
|
10521
|
-
confirm:
|
|
11613
|
+
pipelineId: import_zod38.z.string().describe("The pipeline ID to delete."),
|
|
11614
|
+
confirm: import_zod38.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action.")
|
|
10522
11615
|
},
|
|
10523
11616
|
async ({ pipelineId }) => {
|
|
10524
11617
|
try {
|
|
@@ -10535,7 +11628,7 @@ ${text2}`);
|
|
|
10535
11628
|
}
|
|
10536
11629
|
|
|
10537
11630
|
// src/tools/location-switcher.ts
|
|
10538
|
-
var
|
|
11631
|
+
var import_zod41 = require("zod");
|
|
10539
11632
|
init_ghl_client();
|
|
10540
11633
|
init_provisioning();
|
|
10541
11634
|
init_setup_tool();
|
|
@@ -10620,7 +11713,7 @@ Token registry: ${registeredCount} location(s) registered${versionLine}`
|
|
|
10620
11713
|
"switch_location",
|
|
10621
11714
|
"Switch the active GHL sub-account. Automatically swaps the API key from the token registry if available. After switching, all tools default to the new location.",
|
|
10622
11715
|
{
|
|
10623
|
-
locationId:
|
|
11716
|
+
locationId: import_zod41.z.string().describe("The Location ID to switch to.")
|
|
10624
11717
|
},
|
|
10625
11718
|
async ({ locationId: locationId2 }) => withSwitchLock(async () => {
|
|
10626
11719
|
const previousId = client.defaultLocationId;
|
|
@@ -10693,9 +11786,9 @@ Still on: ${previousId || "none"}${hint}` }],
|
|
|
10693
11786
|
"register_location",
|
|
10694
11787
|
"Add a GHL sub-account to the token registry so switch_location can automatically use its API key. Each sub-account needs its own Private Integration key created in GHL Settings > Integrations.",
|
|
10695
11788
|
{
|
|
10696
|
-
locationId:
|
|
10697
|
-
name:
|
|
10698
|
-
apiKey:
|
|
11789
|
+
locationId: import_zod41.z.string().describe("The GHL Location ID (from Settings > Business Profile)."),
|
|
11790
|
+
name: import_zod41.z.string().describe("A friendly name for this sub-account (e.g. 'PNTracker', 'Med Spa Template')."),
|
|
11791
|
+
apiKey: import_zod41.z.string().describe("The Private Integration API key for this sub-account (starts with 'pit-').")
|
|
10699
11792
|
},
|
|
10700
11793
|
async ({ locationId: locationId2, name, apiKey: apiKey2 }) => {
|
|
10701
11794
|
if (!registry2) {
|
|
@@ -10752,7 +11845,7 @@ The API key could not access location ${locationId2}. Make sure:
|
|
|
10752
11845
|
"register_agency_key",
|
|
10753
11846
|
"Store the AGENCY-level (company-scoped) API key in the token registry. This key powers agency-wide tools: list_snapshots, create_snapshot_share_link, and list_available_locations across all sub-accounts. Create it at the AGENCY level in GHL (Agency Settings > Private Integrations) \u2014 it is different from a sub-account's key. The key is validated before saving.",
|
|
10754
11847
|
{
|
|
10755
|
-
apiKey:
|
|
11848
|
+
apiKey: import_zod41.z.string().describe("The agency-level Private Integration API key (starts with 'pit-'). Must be created in AGENCY settings, not inside a sub-account.")
|
|
10756
11849
|
},
|
|
10757
11850
|
async ({ apiKey: apiKey2 }) => {
|
|
10758
11851
|
if (!registry2) {
|
|
@@ -10806,7 +11899,7 @@ Agency-wide tools now available: list_snapshots, create_snapshot_share_link, and
|
|
|
10806
11899
|
"unregister_location",
|
|
10807
11900
|
"Remove a GHL sub-account from the token registry.",
|
|
10808
11901
|
{
|
|
10809
|
-
locationId:
|
|
11902
|
+
locationId: import_zod41.z.string().describe("The Location ID to remove.")
|
|
10810
11903
|
},
|
|
10811
11904
|
async ({ locationId: locationId2 }) => {
|
|
10812
11905
|
if (!registry2) {
|
|
@@ -10832,12 +11925,12 @@ Agency-wide tools now available: list_snapshots, create_snapshot_share_link, and
|
|
|
10832
11925
|
"register_company_firebase",
|
|
10833
11926
|
"Register a GHL company's Firebase credentials so the workflow builder and all Firebase-gated tools work when you switch into THAT company's sub-accounts. Firebase refresh tokens are company-scoped, so managing a client's GHL (e.g. an account where you're an admin user) requires that company's own token. Capture the values from a browser session logged into the client's account. The tool stores them under the company ID the Firebase token itself authenticates as (decoded from the token), so you do NOT need to hunt down the exact internal company ID \u2014 pass whatever ID you have and it self-corrects. After this, switch_location to any of that company's locations authenticates the workflow builder correctly. DevTools capture steps: elitedcs.com/ghl-mcp-firebase.",
|
|
10834
11927
|
{
|
|
10835
|
-
companyId:
|
|
10836
|
-
name:
|
|
10837
|
-
ghl_firebase_refresh_token:
|
|
10838
|
-
ghl_user_id:
|
|
10839
|
-
ghl_firebase_api_key:
|
|
10840
|
-
test_location_id:
|
|
11928
|
+
companyId: import_zod41.z.string().describe("A GHL company/agency ID for this client (from switch_location/register_location output, or the GHL agency URL). Best-effort only: the tool re-keys the entry to the company ID the Firebase token actually authenticates as, which can differ from the ID shown in the agency URL. Just pass what you have."),
|
|
11929
|
+
name: import_zod41.z.string().describe("Friendly name for this client/company (e.g. 'Nathan \u2014 Acme Health')."),
|
|
11930
|
+
ghl_firebase_refresh_token: import_zod41.z.string().min(10).describe("Firebase refresh token captured from a browser session logged into THIS company's GHL. value.stsTokenManager.refreshToken in the firebase:authUser IndexedDB row."),
|
|
11931
|
+
ghl_user_id: import_zod41.z.string().min(5).describe("Firebase User ID (uid) from the same session. value.uid in the firebase:authUser row."),
|
|
11932
|
+
ghl_firebase_api_key: import_zod41.z.string().optional().describe("Firebase API key (starts with 'AIza'). Optional \u2014 defaults to your home Firebase API key, which is identical across GHL accounts."),
|
|
11933
|
+
test_location_id: import_zod41.z.string().optional().describe("Optional but recommended: a registered location ID belonging to this company. The tool then makes a real workflow-builder call to confirm these credentials actually work for this company before you rely on them.")
|
|
10841
11934
|
},
|
|
10842
11935
|
async (args) => {
|
|
10843
11936
|
if (!registry2) {
|
|
@@ -10941,7 +12034,7 @@ Now run switch_location to any of this company's sub-accounts \u2014 the workflo
|
|
|
10941
12034
|
"unregister_company_firebase",
|
|
10942
12035
|
"Remove a company's Firebase credentials from the registry. Workflow-builder tools will stop working for that company's sub-accounts until re-registered.",
|
|
10943
12036
|
{
|
|
10944
|
-
companyId:
|
|
12037
|
+
companyId: import_zod41.z.string().describe("The company ID to remove Firebase credentials for.")
|
|
10945
12038
|
},
|
|
10946
12039
|
async ({ companyId }) => {
|
|
10947
12040
|
if (!registry2) {
|
|
@@ -11009,8 +12102,8 @@ ${lines.join("\n")}
|
|
|
11009
12102
|
"list_available_locations",
|
|
11010
12103
|
"List all GHL sub-accounts (locations) accessible with the current or agency API key. Shows locations that exist in the GHL account \u2014 use register_location to add their tokens. Offset-based pagination via skip/limit.",
|
|
11011
12104
|
{
|
|
11012
|
-
limit:
|
|
11013
|
-
skip:
|
|
12105
|
+
limit: import_zod41.z.number().optional().describe("Max locations to return. Defaults to 20."),
|
|
12106
|
+
skip: import_zod41.z.number().optional().describe("Number to skip for pagination.")
|
|
11014
12107
|
},
|
|
11015
12108
|
async ({ limit, skip }) => {
|
|
11016
12109
|
try {
|
|
@@ -11054,21 +12147,21 @@ ${lines.join("\n")}
|
|
|
11054
12147
|
"create_sub_account",
|
|
11055
12148
|
"Create a NEW GHL sub-account (location) under the agency, optionally loading a snapshot at creation \u2014 the first step of fully programmatic client provisioning (create \u2192 Blueprint build \u2192 verify_funnel). Requires an agency-level API key with the locations.write scope (add via register_agency_key). After creating, this probes whether the agency key can operate the new location and auto-registers it in the token registry when it can (switch_location then works immediately); if the probe fails, create a Private Integration Token inside the new sub-account and run register_location. Company Firebase (register_company_firebase) covers the internal-API builder tools in the new location either way.",
|
|
11056
12149
|
{
|
|
11057
|
-
name:
|
|
11058
|
-
snapshot_id:
|
|
11059
|
-
company_id:
|
|
11060
|
-
first_name:
|
|
11061
|
-
last_name:
|
|
11062
|
-
email:
|
|
11063
|
-
phone:
|
|
11064
|
-
address:
|
|
11065
|
-
city:
|
|
11066
|
-
state:
|
|
11067
|
-
postal_code:
|
|
11068
|
-
country:
|
|
11069
|
-
website:
|
|
11070
|
-
timezone:
|
|
11071
|
-
auto_register:
|
|
12150
|
+
name: import_zod41.z.string().min(1).describe("Business / sub-account name."),
|
|
12151
|
+
snapshot_id: import_zod41.z.string().optional().describe("Snapshot ID to load at creation (see list_snapshots)."),
|
|
12152
|
+
company_id: import_zod41.z.string().optional().describe("Agency company ID. Defaults to the active location's registered companyId."),
|
|
12153
|
+
first_name: import_zod41.z.string().optional().describe("Prospect/owner first name."),
|
|
12154
|
+
last_name: import_zod41.z.string().optional().describe("Prospect/owner last name."),
|
|
12155
|
+
email: import_zod41.z.string().email().optional().describe("Prospect/owner email."),
|
|
12156
|
+
phone: import_zod41.z.string().optional().describe("Business phone (E.164, e.g. +15551234567)."),
|
|
12157
|
+
address: import_zod41.z.string().optional().describe("Street address."),
|
|
12158
|
+
city: import_zod41.z.string().optional(),
|
|
12159
|
+
state: import_zod41.z.string().optional(),
|
|
12160
|
+
postal_code: import_zod41.z.string().optional(),
|
|
12161
|
+
country: import_zod41.z.string().optional().describe("Two-letter country code. Defaults to US."),
|
|
12162
|
+
website: import_zod41.z.string().optional(),
|
|
12163
|
+
timezone: import_zod41.z.string().optional().describe("IANA timezone, e.g. America/Los_Angeles."),
|
|
12164
|
+
auto_register: import_zod41.z.boolean().optional().describe("Probe the new location with the agency key and add it to the token registry on success. Default true.")
|
|
11072
12165
|
},
|
|
11073
12166
|
async (args) => {
|
|
11074
12167
|
const outcome = await provisionSubAccount(client, registry2, args);
|
|
@@ -11096,9 +12189,9 @@ ${lines.join("\n")}
|
|
|
11096
12189
|
"delete_sub_account",
|
|
11097
12190
|
"Permanently delete a GHL sub-account (location) via the agency API. IRREVERSIBLE \u2014 every contact, workflow, funnel, and setting inside the sub-account is destroyed. Refuses to delete the currently active location. Also removes the location from the token registry. Requires an agency-level key with locations.write.",
|
|
11098
12191
|
{
|
|
11099
|
-
location_id:
|
|
11100
|
-
confirm:
|
|
11101
|
-
delete_twilio:
|
|
12192
|
+
location_id: import_zod41.z.string().min(1).describe("The location ID to delete."),
|
|
12193
|
+
confirm: import_zod41.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action."),
|
|
12194
|
+
delete_twilio: import_zod41.z.boolean().optional().describe("Also delete the location's Twilio sub-account. Default false.")
|
|
11102
12195
|
},
|
|
11103
12196
|
async ({ location_id, delete_twilio }) => {
|
|
11104
12197
|
const agencyKey = registry2?.getAgencyKey();
|
|
@@ -11136,7 +12229,7 @@ ${lines.join("\n")}
|
|
|
11136
12229
|
}
|
|
11137
12230
|
|
|
11138
12231
|
// src/tools/bulk-operations.ts
|
|
11139
|
-
var
|
|
12232
|
+
var import_zod42 = require("zod");
|
|
11140
12233
|
function delay(ms) {
|
|
11141
12234
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
11142
12235
|
}
|
|
@@ -11148,8 +12241,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
11148
12241
|
"bulk_add_tags",
|
|
11149
12242
|
"Add tags to multiple contacts at once. Rate-limited to avoid API throttling. Returns a summary of successes and failures.",
|
|
11150
12243
|
{
|
|
11151
|
-
contactIds:
|
|
11152
|
-
tags:
|
|
12244
|
+
contactIds: import_zod42.z.array(import_zod42.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to tag."),
|
|
12245
|
+
tags: import_zod42.z.array(import_zod42.z.string()).min(1, "At least one tag required.").describe("Tags to add to each contact.")
|
|
11153
12246
|
},
|
|
11154
12247
|
async ({ contactIds, tags }) => {
|
|
11155
12248
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -11171,8 +12264,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
11171
12264
|
"bulk_remove_tags",
|
|
11172
12265
|
"Remove tags from multiple contacts at once. Rate-limited.",
|
|
11173
12266
|
{
|
|
11174
|
-
contactIds:
|
|
11175
|
-
tags:
|
|
12267
|
+
contactIds: import_zod42.z.array(import_zod42.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs."),
|
|
12268
|
+
tags: import_zod42.z.array(import_zod42.z.string()).min(1, "At least one tag required.").describe("Tags to remove from each contact.")
|
|
11176
12269
|
},
|
|
11177
12270
|
async ({ contactIds, tags }) => {
|
|
11178
12271
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -11193,8 +12286,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
11193
12286
|
"bulk_update_contacts",
|
|
11194
12287
|
"Update the same field(s) on multiple contacts at once. Rate-limited. Example: set a custom field value, change source, update address for a batch of contacts.",
|
|
11195
12288
|
{
|
|
11196
|
-
contactIds:
|
|
11197
|
-
fields:
|
|
12289
|
+
contactIds: import_zod42.z.array(import_zod42.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to update."),
|
|
12290
|
+
fields: import_zod42.z.record(import_zod42.z.unknown()).describe("Fields to set on each contact (e.g. {customField: {id: 'xxx', value: 'yyy'}}, {source: 'Import'}).")
|
|
11198
12291
|
},
|
|
11199
12292
|
async ({ contactIds, fields }) => {
|
|
11200
12293
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -11215,8 +12308,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
11215
12308
|
"bulk_add_to_workflow",
|
|
11216
12309
|
"Enroll multiple contacts into a workflow at once. Rate-limited.",
|
|
11217
12310
|
{
|
|
11218
|
-
contactIds:
|
|
11219
|
-
workflowId:
|
|
12311
|
+
contactIds: import_zod42.z.array(import_zod42.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to enroll."),
|
|
12312
|
+
workflowId: import_zod42.z.string().describe("The workflow ID to enroll contacts into.")
|
|
11220
12313
|
},
|
|
11221
12314
|
async ({ contactIds, workflowId }) => {
|
|
11222
12315
|
const results = { success: 0, failed: 0, errors: [] };
|
|
@@ -11237,8 +12330,8 @@ function registerBulkOperationTools(server2, client) {
|
|
|
11237
12330
|
"bulk_delete_contacts",
|
|
11238
12331
|
"Delete multiple contacts at once. IRREVERSIBLE. Rate-limited. Use with extreme caution.",
|
|
11239
12332
|
{
|
|
11240
|
-
contactIds:
|
|
11241
|
-
confirm:
|
|
12333
|
+
contactIds: import_zod42.z.array(import_zod42.z.string()).min(1, "At least one contact ID required.").describe("Array of contact IDs to permanently delete."),
|
|
12334
|
+
confirm: import_zod42.z.literal("DELETE").describe("Must pass the string 'DELETE' to confirm. This is a safety check.")
|
|
11242
12335
|
},
|
|
11243
12336
|
async ({ contactIds, confirm }) => {
|
|
11244
12337
|
if (confirm !== "DELETE") {
|
|
@@ -11261,7 +12354,7 @@ function registerBulkOperationTools(server2, client) {
|
|
|
11261
12354
|
}
|
|
11262
12355
|
|
|
11263
12356
|
// src/tools/account-export.ts
|
|
11264
|
-
var
|
|
12357
|
+
var import_zod43 = require("zod");
|
|
11265
12358
|
function delay2(ms) {
|
|
11266
12359
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
11267
12360
|
}
|
|
@@ -11271,8 +12364,8 @@ function registerAccountExportTools(server2, client) {
|
|
|
11271
12364
|
"export_account",
|
|
11272
12365
|
"Export a complete inventory of the GHL sub-account: location info, contacts (count + sample), pipelines with stages, workflows (with full actions if builder auth is configured), funnels with pages, forms, custom fields, custom values, tags, calendars, and users. Returns a comprehensive JSON report for auditing or backup.",
|
|
11273
12366
|
{
|
|
11274
|
-
locationId:
|
|
11275
|
-
includeContacts:
|
|
12367
|
+
locationId: import_zod43.z.string().optional().describe("Location ID to export. Uses default if not specified."),
|
|
12368
|
+
includeContacts: import_zod43.z.boolean().optional().describe("Include contact list (first 100). Defaults to false for speed.")
|
|
11276
12369
|
},
|
|
11277
12370
|
async ({ locationId: locationId2, includeContacts }) => {
|
|
11278
12371
|
try {
|
|
@@ -11400,8 +12493,8 @@ function registerAccountExportTools(server2, client) {
|
|
|
11400
12493
|
"compare_locations",
|
|
11401
12494
|
"Compare two GHL sub-accounts side by side \u2014 shows differences in pipelines, workflows, custom fields, tags, forms, and funnels. Useful for ensuring consistency across locations or auditing before/after changes.",
|
|
11402
12495
|
{
|
|
11403
|
-
locationA:
|
|
11404
|
-
locationB:
|
|
12496
|
+
locationA: import_zod43.z.string().describe("First Location ID."),
|
|
12497
|
+
locationB: import_zod43.z.string().describe("Second Location ID.")
|
|
11405
12498
|
},
|
|
11406
12499
|
async ({ locationA, locationB }) => {
|
|
11407
12500
|
try {
|
|
@@ -11479,7 +12572,7 @@ function registerAccountExportTools(server2, client) {
|
|
|
11479
12572
|
}
|
|
11480
12573
|
|
|
11481
12574
|
// src/tools/workflow-cloner.ts
|
|
11482
|
-
var
|
|
12575
|
+
var import_zod44 = require("zod");
|
|
11483
12576
|
var crypto3 = __toESM(require("crypto"));
|
|
11484
12577
|
function registerWorkflowClonerTools(server2, builderClient) {
|
|
11485
12578
|
const client = builderClient;
|
|
@@ -11488,8 +12581,8 @@ function registerWorkflowClonerTools(server2, builderClient) {
|
|
|
11488
12581
|
"clone_workflow",
|
|
11489
12582
|
"Deep clone a workflow \u2014 creates an exact copy with new IDs for all actions, triggers, and references. The clone starts as a draft. Useful for creating templates or duplicating workflows across projects.",
|
|
11490
12583
|
{
|
|
11491
|
-
sourceWorkflowId:
|
|
11492
|
-
newName:
|
|
12584
|
+
sourceWorkflowId: import_zod44.z.string().describe("The workflow ID to clone."),
|
|
12585
|
+
newName: import_zod44.z.string().describe("Name for the cloned workflow.")
|
|
11493
12586
|
},
|
|
11494
12587
|
async ({ sourceWorkflowId, newName }) => {
|
|
11495
12588
|
try {
|
|
@@ -11578,7 +12671,7 @@ function registerWorkflowClonerTools(server2, builderClient) {
|
|
|
11578
12671
|
}
|
|
11579
12672
|
|
|
11580
12673
|
// src/tools/smart-lists.ts
|
|
11581
|
-
var
|
|
12674
|
+
var import_zod45 = require("zod");
|
|
11582
12675
|
var SMARTLIST_BASE = "https://backend.leadconnectorhq.com/lists/dynamic";
|
|
11583
12676
|
var OBJECT_KEYS = ["contacts", "opportunity"];
|
|
11584
12677
|
function registerSmartListTools(server2, builderClient) {
|
|
@@ -11605,11 +12698,11 @@ ${text2}`);
|
|
|
11605
12698
|
"list_smart_lists",
|
|
11606
12699
|
"List smart lists (dynamic / saved-filter lists) in a location. Smart Lists are saved searches over contacts or opportunities \u2014 agencies use them to segment by complex criteria. Filters and columns aren't returned in the list view; use get_smart_list for the full filter spec.",
|
|
11607
12700
|
{
|
|
11608
|
-
objectKey:
|
|
11609
|
-
query:
|
|
11610
|
-
limit:
|
|
11611
|
-
startAfter:
|
|
11612
|
-
locationId:
|
|
12701
|
+
objectKey: import_zod45.z.enum(OBJECT_KEYS).describe("The object type the lists segment over. 'contacts' for contact-segments, 'opportunity' for opportunity-segments. Required \u2014 GHL rejects requests without it."),
|
|
12702
|
+
query: import_zod45.z.string().optional().describe("Free-text search across smart list names."),
|
|
12703
|
+
limit: import_zod45.z.number().optional().describe("Max smart lists per page. Defaults to 20 on GHL's side."),
|
|
12704
|
+
startAfter: import_zod45.z.string().optional().describe("Cursor for pagination \u2014 pass the last list's id from the previous page."),
|
|
12705
|
+
locationId: import_zod45.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
|
|
11613
12706
|
},
|
|
11614
12707
|
async ({ objectKey, query, limit, startAfter, locationId: locationId2 }) => {
|
|
11615
12708
|
try {
|
|
@@ -11629,8 +12722,8 @@ ${text2}`);
|
|
|
11629
12722
|
"get_smart_list",
|
|
11630
12723
|
"Get a single smart list by ID with its full configuration: filters, columns, permissions, and metadata. The filters array is what defines who/what is in the list.",
|
|
11631
12724
|
{
|
|
11632
|
-
listId:
|
|
11633
|
-
locationId:
|
|
12725
|
+
listId: import_zod45.z.string().describe("The smart list ID (from list_smart_lists or a previous create_smart_list response)."),
|
|
12726
|
+
locationId: import_zod45.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
|
|
11634
12727
|
},
|
|
11635
12728
|
async ({ listId, locationId: locationId2 }) => {
|
|
11636
12729
|
try {
|
|
@@ -11646,13 +12739,13 @@ ${text2}`);
|
|
|
11646
12739
|
"create_smart_list",
|
|
11647
12740
|
"Create a new smart list (dynamic filter list). Required: name + objectKey. Filters define the saved-search criteria \u2014 pass an empty array to create an empty list and add filters later via update_smart_list. The shape of filters/columns is opaque here; query an existing smart list with get_smart_list to see the format GHL expects.",
|
|
11648
12741
|
{
|
|
11649
|
-
name:
|
|
11650
|
-
objectKey:
|
|
11651
|
-
filters:
|
|
11652
|
-
columns:
|
|
11653
|
-
pipelineIds:
|
|
11654
|
-
defaultInPipelines:
|
|
11655
|
-
locationId:
|
|
12742
|
+
name: import_zod45.z.string().describe("Display name for the smart list."),
|
|
12743
|
+
objectKey: import_zod45.z.enum(OBJECT_KEYS).describe("Object type the list segments over. 'contacts' or 'opportunity'."),
|
|
12744
|
+
filters: import_zod45.z.array(import_zod45.z.record(import_zod45.z.unknown())).optional().describe("Array of filter objects. Each object has fields like {field, operator, value} \u2014 exact shape varies by filter type. See get_smart_list on an existing list to learn the format."),
|
|
12745
|
+
columns: import_zod45.z.array(import_zod45.z.record(import_zod45.z.unknown())).optional().describe("Array of column definitions for the smart list view in GHL UI. Each defines which contact/opportunity field shows as a column. Defaults to GHL's standard columns if omitted."),
|
|
12746
|
+
pipelineIds: import_zod45.z.array(import_zod45.z.string()).optional().describe("(opportunity objectKey only) Pipeline IDs to restrict this smart list to. Empty array = all pipelines."),
|
|
12747
|
+
defaultInPipelines: import_zod45.z.array(import_zod45.z.string()).optional().describe("(opportunity objectKey only) Pipeline IDs where this list is the default view."),
|
|
12748
|
+
locationId: import_zod45.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
|
|
11656
12749
|
},
|
|
11657
12750
|
async ({ name, objectKey, filters, columns, pipelineIds, defaultInPipelines, locationId: locationId2 }) => {
|
|
11658
12751
|
try {
|
|
@@ -11673,13 +12766,13 @@ ${text2}`);
|
|
|
11673
12766
|
"update_smart_list",
|
|
11674
12767
|
"Update an existing smart list's name, filters, or columns. The objectKey CANNOT be changed after creation (GHL rejects with 422 if you try). Use get_smart_list first to inspect the current filters; partial updates work \u2014 pass only the fields you want to change.",
|
|
11675
12768
|
{
|
|
11676
|
-
listId:
|
|
11677
|
-
name:
|
|
11678
|
-
filters:
|
|
11679
|
-
columns:
|
|
11680
|
-
pipelineIds:
|
|
11681
|
-
defaultInPipelines:
|
|
11682
|
-
locationId:
|
|
12769
|
+
listId: import_zod45.z.string().describe("The smart list ID to update."),
|
|
12770
|
+
name: import_zod45.z.string().optional().describe("New display name."),
|
|
12771
|
+
filters: import_zod45.z.array(import_zod45.z.record(import_zod45.z.unknown())).optional().describe("Replace the filter array entirely. To add a filter, fetch the current list, append, and pass the new array."),
|
|
12772
|
+
columns: import_zod45.z.array(import_zod45.z.record(import_zod45.z.unknown())).optional().describe("Replace the column array entirely."),
|
|
12773
|
+
pipelineIds: import_zod45.z.array(import_zod45.z.string()).optional().describe("(opportunity only) Update the pipeline scope."),
|
|
12774
|
+
defaultInPipelines: import_zod45.z.array(import_zod45.z.string()).optional().describe("(opportunity only) Update the default-in-pipelines list."),
|
|
12775
|
+
locationId: import_zod45.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
|
|
11683
12776
|
},
|
|
11684
12777
|
async ({ listId, name, filters, columns, pipelineIds, defaultInPipelines, locationId: locationId2 }) => {
|
|
11685
12778
|
try {
|
|
@@ -11704,9 +12797,9 @@ ${text2}`);
|
|
|
11704
12797
|
"delete_smart_list",
|
|
11705
12798
|
"Permanently delete a smart list. IRREVERSIBLE. The list configuration is removed but the contacts/opportunities themselves are NOT touched \u2014 smart lists are just saved filters. Any workflow trigger / dashboard / report that referenced this list by ID will stop working.",
|
|
11706
12799
|
{
|
|
11707
|
-
listId:
|
|
11708
|
-
confirm:
|
|
11709
|
-
locationId:
|
|
12800
|
+
listId: import_zod45.z.string().describe("The smart list ID to delete."),
|
|
12801
|
+
confirm: import_zod45.z.literal("DELETE").describe("Must pass 'DELETE' to confirm this destructive action."),
|
|
12802
|
+
locationId: import_zod45.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
|
|
11710
12803
|
},
|
|
11711
12804
|
async ({ listId, locationId: locationId2 }) => {
|
|
11712
12805
|
try {
|
|
@@ -11721,7 +12814,7 @@ ${text2}`);
|
|
|
11721
12814
|
}
|
|
11722
12815
|
|
|
11723
12816
|
// src/tools/reputation.ts
|
|
11724
|
-
var
|
|
12817
|
+
var import_zod46 = require("zod");
|
|
11725
12818
|
var REPUTATION_BASE = "https://backend.leadconnectorhq.com/reputation";
|
|
11726
12819
|
function registerReputationTools(server2, builderClient) {
|
|
11727
12820
|
const client = builderClient;
|
|
@@ -11743,7 +12836,7 @@ ${text2}`);
|
|
|
11743
12836
|
"get_review_link_list",
|
|
11744
12837
|
"List the review-link destinations configured for a location \u2014 the platforms (Google, Facebook, etc.) where review requests send contacts. Each entry has a label and the public review URL. Useful for: building review-request workflows (the workflow goal condition `review_request_clicked` references these review-link ids), and auditing which review platforms a sub-account has connected.",
|
|
11745
12838
|
{
|
|
11746
|
-
locationId:
|
|
12839
|
+
locationId: import_zod46.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
|
|
11747
12840
|
},
|
|
11748
12841
|
async ({ locationId: locationId2 }) => {
|
|
11749
12842
|
const loc = locationId2 ?? client.locationId;
|
|
@@ -11755,11 +12848,11 @@ ${text2}`);
|
|
|
11755
12848
|
"list_reviews",
|
|
11756
12849
|
"List the reviews a location has received (Google, Facebook, etc.) with rating, author, text, reply status, and source. Supports paging and an optional rating filter. NOTE: location is resolved through nested filter params internally \u2014 a flat locationId is what caused the long-standing 'No Location Found' error, now fixed. Responding to a review is not yet available via API. Requires Firebase auth.",
|
|
11757
12850
|
{
|
|
11758
|
-
locationId:
|
|
11759
|
-
pageNumber:
|
|
11760
|
-
pageSize:
|
|
11761
|
-
rating:
|
|
11762
|
-
includeDeleted:
|
|
12851
|
+
locationId: import_zod46.z.string().optional().describe("Location ID. Falls back to the active builder client's location."),
|
|
12852
|
+
pageNumber: import_zod46.z.number().optional().describe("1-based page number. Defaults to 1."),
|
|
12853
|
+
pageSize: import_zod46.z.number().optional().describe("Results per page. Defaults to 10."),
|
|
12854
|
+
rating: import_zod46.z.number().optional().describe("Optional: only return reviews with this star rating (1-5)."),
|
|
12855
|
+
includeDeleted: import_zod46.z.boolean().optional().describe("Include deleted reviews. Defaults to false.")
|
|
11763
12856
|
},
|
|
11764
12857
|
async ({ locationId: locationId2, pageNumber, pageSize, rating, includeDeleted }) => {
|
|
11765
12858
|
const loc = locationId2 ?? client.locationId;
|
|
@@ -11789,7 +12882,7 @@ function buildReviewsQuery(locationId2, opts = {}) {
|
|
|
11789
12882
|
}
|
|
11790
12883
|
|
|
11791
12884
|
// src/tools/email-campaigns.ts
|
|
11792
|
-
var
|
|
12885
|
+
var import_zod47 = require("zod");
|
|
11793
12886
|
var SVC_BASE = "https://services.leadconnectorhq.com";
|
|
11794
12887
|
function registerEmailCampaignTools(server2, builderClient) {
|
|
11795
12888
|
const client = builderClient;
|
|
@@ -11799,15 +12892,15 @@ function registerEmailCampaignTools(server2, builderClient) {
|
|
|
11799
12892
|
"create_email_campaign",
|
|
11800
12893
|
"Create an email campaign / broadcast DRAFT from an existing email template. Requires a templateId (create one first with create_email_template). The campaign is created as a draft \u2014 to actually SEND or schedule it, finish in the GHL UI: the send/schedule endpoint isn't available through the API yet. There's also no API delete for campaigns, so drafts created here are removed via the GHL UI. Despite those limits, this gets the campaign 90% built \u2014 template, subject, sender, name all set programmatically.",
|
|
11801
12894
|
{
|
|
11802
|
-
templateId:
|
|
11803
|
-
name:
|
|
11804
|
-
subject:
|
|
11805
|
-
fromName:
|
|
11806
|
-
fromEmail:
|
|
11807
|
-
isPlainText:
|
|
11808
|
-
enableResendToUnopened:
|
|
11809
|
-
hasUtmTracking:
|
|
11810
|
-
locationId:
|
|
12895
|
+
templateId: import_zod47.z.string().describe("ID of an email template (from create_email_template or list_email_templates) to use as the campaign body."),
|
|
12896
|
+
name: import_zod47.z.string().optional().describe("Internal campaign name (shown in the campaigns list, not to recipients). Defaults to a GHL-generated name."),
|
|
12897
|
+
subject: import_zod47.z.string().optional().describe("Email subject line recipients see."),
|
|
12898
|
+
fromName: import_zod47.z.string().optional().describe("Sender display name."),
|
|
12899
|
+
fromEmail: import_zod47.z.string().optional().describe("Sender email address. Must be a verified sending address in the location."),
|
|
12900
|
+
isPlainText: import_zod47.z.boolean().optional().describe("Send as plain text instead of HTML. Defaults to false."),
|
|
12901
|
+
enableResendToUnopened: import_zod47.z.boolean().optional().describe("Auto-resend to contacts who didn't open. Defaults to false."),
|
|
12902
|
+
hasUtmTracking: import_zod47.z.boolean().optional().describe("Append UTM tracking params to links. Defaults to false."),
|
|
12903
|
+
locationId: import_zod47.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
|
|
11811
12904
|
},
|
|
11812
12905
|
async ({ templateId, name, subject, fromName, fromEmail, isPlainText, enableResendToUnopened, hasUtmTracking, locationId: locationId2 }) => {
|
|
11813
12906
|
const loc = locationId2 ?? client.locationId;
|
|
@@ -11841,7 +12934,7 @@ ${text2}`);
|
|
|
11841
12934
|
}
|
|
11842
12935
|
|
|
11843
12936
|
// src/tools/memberships.ts
|
|
11844
|
-
var
|
|
12937
|
+
var import_zod48 = require("zod");
|
|
11845
12938
|
var MEMBERSHIP_BASE = "https://backend.leadconnectorhq.com/membership";
|
|
11846
12939
|
function registerMembershipTools(server2, builderClient) {
|
|
11847
12940
|
const client = builderClient;
|
|
@@ -11867,7 +12960,7 @@ ${text2}`);
|
|
|
11867
12960
|
"list_membership_offers",
|
|
11868
12961
|
"List a location's membership offers and products in one call. Returns { products: [...], offers: [...] }. Products are courses/communities; offers are the access grants (what a contact gets enrolled in). Use the returned ids with membership trigger conditions like offer_access_granted / product_completed.",
|
|
11869
12962
|
{
|
|
11870
|
-
locationId:
|
|
12963
|
+
locationId: import_zod48.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
|
|
11871
12964
|
},
|
|
11872
12965
|
async ({ locationId: locationId2 }) => {
|
|
11873
12966
|
const loc = locationId2 ?? client.locationId;
|
|
@@ -11879,8 +12972,8 @@ ${text2}`);
|
|
|
11879
12972
|
"list_membership_categories",
|
|
11880
12973
|
"List all membership/course categories in a location. Categories group lessons inside a course/product. Use the returned ids with the category_completed / category_started trigger conditions. READ-ONLY.",
|
|
11881
12974
|
{
|
|
11882
|
-
limit:
|
|
11883
|
-
locationId:
|
|
12975
|
+
limit: import_zod48.z.number().optional().describe("Max categories to return. Defaults to a large value (effectively all)."),
|
|
12976
|
+
locationId: import_zod48.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
|
|
11884
12977
|
},
|
|
11885
12978
|
async ({ limit, locationId: locationId2 }) => {
|
|
11886
12979
|
const loc = locationId2 ?? client.locationId;
|
|
@@ -11892,8 +12985,8 @@ ${text2}`);
|
|
|
11892
12985
|
"list_membership_lessons",
|
|
11893
12986
|
"List all membership/course lessons in a location. Use the returned ids with the lesson_completed / lesson_started trigger conditions. READ-ONLY.",
|
|
11894
12987
|
{
|
|
11895
|
-
limit:
|
|
11896
|
-
locationId:
|
|
12988
|
+
limit: import_zod48.z.number().optional().describe("Max lessons to return. Defaults to a large value (effectively all)."),
|
|
12989
|
+
locationId: import_zod48.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
|
|
11897
12990
|
},
|
|
11898
12991
|
async ({ limit, locationId: locationId2 }) => {
|
|
11899
12992
|
const loc = locationId2 ?? client.locationId;
|
|
@@ -11905,9 +12998,9 @@ ${text2}`);
|
|
|
11905
12998
|
"create_course",
|
|
11906
12999
|
"Create a membership course (a 'product') in a location. Creates the course shell with a title and description; add categories (create_membership_category) and lessons (create_membership_lesson) into it, and an offer (create_membership_offer) to grant access. Returns the new product, including its id. Requires Firebase auth.",
|
|
11907
13000
|
{
|
|
11908
|
-
title:
|
|
11909
|
-
description:
|
|
11910
|
-
locationId:
|
|
13001
|
+
title: import_zod48.z.string().describe("Course title."),
|
|
13002
|
+
description: import_zod48.z.string().optional().describe("Course description. Defaults to empty."),
|
|
13003
|
+
locationId: import_zod48.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
|
|
11911
13004
|
},
|
|
11912
13005
|
async ({ title, description, locationId: locationId2 }) => {
|
|
11913
13006
|
const loc = locationId2 ?? client.locationId;
|
|
@@ -11919,13 +13012,13 @@ ${text2}`);
|
|
|
11919
13012
|
"create_membership_category",
|
|
11920
13013
|
"Create a category (module/section) inside a membership course. Categories group lessons. Needs the productId of the course (from create_course or list_membership_offers). Returns the new category, including its id (use it as categoryId when creating lessons). Requires Firebase auth.",
|
|
11921
13014
|
{
|
|
11922
|
-
title:
|
|
11923
|
-
productId:
|
|
11924
|
-
description:
|
|
11925
|
-
visibility:
|
|
11926
|
-
sequenceNo:
|
|
11927
|
-
dripDays:
|
|
11928
|
-
locationId:
|
|
13015
|
+
title: import_zod48.z.string().describe("Category title (e.g. 'Module 1')."),
|
|
13016
|
+
productId: import_zod48.z.string().describe("The course/product id this category belongs to."),
|
|
13017
|
+
description: import_zod48.z.string().optional().describe("Category description. Defaults to empty."),
|
|
13018
|
+
visibility: import_zod48.z.enum(["published", "draft"]).optional().describe("'published' (default) or 'draft'."),
|
|
13019
|
+
sequenceNo: import_zod48.z.number().optional().describe("Display order within the course. Defaults to 0."),
|
|
13020
|
+
dripDays: import_zod48.z.number().optional().describe("Days after enrollment before this category unlocks. Defaults to 0 (no drip)."),
|
|
13021
|
+
locationId: import_zod48.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
|
|
11929
13022
|
},
|
|
11930
13023
|
async ({ title, productId, description, visibility, sequenceNo, dripDays, locationId: locationId2 }) => {
|
|
11931
13024
|
const loc = locationId2 ?? client.locationId;
|
|
@@ -11937,14 +13030,14 @@ ${text2}`);
|
|
|
11937
13030
|
"create_membership_lesson",
|
|
11938
13031
|
"Create a lesson (a 'post') inside a membership course category. Needs both the categoryId (from create_membership_category) and the productId of the course. Description is the lesson body as HTML. Returns the new lesson, including its id. Requires Firebase auth.",
|
|
11939
13032
|
{
|
|
11940
|
-
title:
|
|
11941
|
-
categoryId:
|
|
11942
|
-
productId:
|
|
11943
|
-
description:
|
|
11944
|
-
contentType:
|
|
11945
|
-
visibility:
|
|
11946
|
-
sequenceNo:
|
|
11947
|
-
locationId:
|
|
13033
|
+
title: import_zod48.z.string().describe("Lesson title."),
|
|
13034
|
+
categoryId: import_zod48.z.string().describe("The category id this lesson belongs to (from create_membership_category)."),
|
|
13035
|
+
productId: import_zod48.z.string().describe("The course/product id this lesson belongs to."),
|
|
13036
|
+
description: import_zod48.z.string().optional().describe("Lesson body as HTML. Defaults to empty."),
|
|
13037
|
+
contentType: import_zod48.z.enum(["video", "audio", "text", "pdf", "assignment"]).optional().describe("Lesson content type. Defaults to 'video'."),
|
|
13038
|
+
visibility: import_zod48.z.enum(["published", "draft"]).optional().describe("'published' (default) or 'draft'."),
|
|
13039
|
+
sequenceNo: import_zod48.z.number().optional().describe("Display order within the category. Defaults to 0."),
|
|
13040
|
+
locationId: import_zod48.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
|
|
11948
13041
|
},
|
|
11949
13042
|
async ({ title, categoryId, productId, description, contentType, visibility, sequenceNo, locationId: locationId2 }) => {
|
|
11950
13043
|
const loc = locationId2 ?? client.locationId;
|
|
@@ -11956,12 +13049,12 @@ ${text2}`);
|
|
|
11956
13049
|
"create_membership_offer",
|
|
11957
13050
|
"Create a membership offer \u2014 the access grant that enrolls contacts into one or more courses/products. Link it to course product ids. Defaults to a free offer; for paid, set type to 'recurring' or 'one_time' with an amount. Returns the new offer, including its id (referenced by the offer_access_granted trigger). Requires Firebase auth.",
|
|
11958
13051
|
{
|
|
11959
|
-
title:
|
|
11960
|
-
productIds:
|
|
11961
|
-
type:
|
|
11962
|
-
amount:
|
|
11963
|
-
currency:
|
|
11964
|
-
locationId:
|
|
13052
|
+
title: import_zod48.z.string().describe("Offer title (shown at checkout / in the offer list)."),
|
|
13053
|
+
productIds: import_zod48.z.array(import_zod48.z.string()).describe("Course/product ids this offer grants access to (from create_course or list_membership_offers)."),
|
|
13054
|
+
type: import_zod48.z.enum(["free", "recurring", "one_time"]).optional().describe("Offer type. Defaults to 'free'."),
|
|
13055
|
+
amount: import_zod48.z.number().optional().describe("Price for paid offers. Defaults to 0 (free)."),
|
|
13056
|
+
currency: import_zod48.z.string().optional().describe("Currency code for paid offers. Defaults to 'USD'."),
|
|
13057
|
+
locationId: import_zod48.z.string().optional().describe("Location ID. Falls back to the active builder client's location.")
|
|
11965
13058
|
},
|
|
11966
13059
|
async ({ title, productIds, type, amount, currency, locationId: locationId2 }) => {
|
|
11967
13060
|
const loc = locationId2 ?? client.locationId;
|
|
@@ -12020,41 +13113,41 @@ function buildOfferPayload(o) {
|
|
|
12020
13113
|
}
|
|
12021
13114
|
|
|
12022
13115
|
// src/tools/template-deployer.ts
|
|
12023
|
-
var
|
|
13116
|
+
var import_zod49 = require("zod");
|
|
12024
13117
|
var fs5 = __toESM(require("fs"));
|
|
12025
13118
|
var path5 = __toESM(require("path"));
|
|
12026
13119
|
function delay3(ms) {
|
|
12027
13120
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
12028
13121
|
}
|
|
12029
|
-
var TemplateSchema =
|
|
12030
|
-
templateName:
|
|
12031
|
-
templateVersion:
|
|
12032
|
-
description:
|
|
12033
|
-
questionnaire:
|
|
12034
|
-
id:
|
|
12035
|
-
question:
|
|
12036
|
-
type:
|
|
12037
|
-
required:
|
|
12038
|
-
placeholder:
|
|
13122
|
+
var TemplateSchema = import_zod49.z.object({
|
|
13123
|
+
templateName: import_zod49.z.string(),
|
|
13124
|
+
templateVersion: import_zod49.z.string().optional(),
|
|
13125
|
+
description: import_zod49.z.string().optional().default(""),
|
|
13126
|
+
questionnaire: import_zod49.z.array(import_zod49.z.object({
|
|
13127
|
+
id: import_zod49.z.string(),
|
|
13128
|
+
question: import_zod49.z.string(),
|
|
13129
|
+
type: import_zod49.z.string(),
|
|
13130
|
+
required: import_zod49.z.boolean().optional(),
|
|
13131
|
+
placeholder: import_zod49.z.string().optional()
|
|
12039
13132
|
})).optional().default([]),
|
|
12040
|
-
location:
|
|
12041
|
-
tags:
|
|
12042
|
-
customFields:
|
|
12043
|
-
name:
|
|
12044
|
-
dataType:
|
|
13133
|
+
location: import_zod49.z.record(import_zod49.z.unknown()).optional(),
|
|
13134
|
+
tags: import_zod49.z.array(import_zod49.z.string()).optional(),
|
|
13135
|
+
customFields: import_zod49.z.array(import_zod49.z.object({
|
|
13136
|
+
name: import_zod49.z.string(),
|
|
13137
|
+
dataType: import_zod49.z.string()
|
|
12045
13138
|
})).optional(),
|
|
12046
|
-
pipelines:
|
|
12047
|
-
name:
|
|
12048
|
-
stages:
|
|
13139
|
+
pipelines: import_zod49.z.array(import_zod49.z.object({
|
|
13140
|
+
name: import_zod49.z.string(),
|
|
13141
|
+
stages: import_zod49.z.array(import_zod49.z.object({ position: import_zod49.z.number(), name: import_zod49.z.string() }))
|
|
12049
13142
|
})).optional(),
|
|
12050
|
-
workflows:
|
|
12051
|
-
name:
|
|
12052
|
-
condition:
|
|
12053
|
-
actions:
|
|
13143
|
+
workflows: import_zod49.z.array(import_zod49.z.object({
|
|
13144
|
+
name: import_zod49.z.string(),
|
|
13145
|
+
condition: import_zod49.z.string().optional(),
|
|
13146
|
+
actions: import_zod49.z.array(import_zod49.z.record(import_zod49.z.unknown())).optional().default([])
|
|
12054
13147
|
})).optional(),
|
|
12055
|
-
calendars:
|
|
12056
|
-
name:
|
|
12057
|
-
description:
|
|
13148
|
+
calendars: import_zod49.z.array(import_zod49.z.object({
|
|
13149
|
+
name: import_zod49.z.string(),
|
|
13150
|
+
description: import_zod49.z.string().optional()
|
|
12058
13151
|
})).optional()
|
|
12059
13152
|
});
|
|
12060
13153
|
function registerTemplateDeployerTools(server2, client) {
|
|
@@ -12125,7 +13218,7 @@ function registerTemplateDeployerTools(server2, client) {
|
|
|
12125
13218
|
"get_template_questionnaire",
|
|
12126
13219
|
"Get the questionnaire for a specific template. Returns all the questions that need to be answered before deploying. Present these to the user one at a time in a conversational style.",
|
|
12127
13220
|
{
|
|
12128
|
-
templateFile:
|
|
13221
|
+
templateFile: import_zod49.z.string().describe("Path to the template JSON file (from list_templates).")
|
|
12129
13222
|
},
|
|
12130
13223
|
async ({ templateFile }) => {
|
|
12131
13224
|
try {
|
|
@@ -12158,10 +13251,10 @@ function registerTemplateDeployerTools(server2, client) {
|
|
|
12158
13251
|
"deploy_template",
|
|
12159
13252
|
"Deploy a template to set up a GHL sub-account. Creates tags, custom fields, pipelines with stages, calendars, workflows, and forms based on the template and the user's questionnaire answers. This is the main setup automation tool.",
|
|
12160
13253
|
{
|
|
12161
|
-
templateFile:
|
|
12162
|
-
answers:
|
|
12163
|
-
locationId:
|
|
12164
|
-
dryRun:
|
|
13254
|
+
templateFile: import_zod49.z.string().describe("Path to the template JSON file."),
|
|
13255
|
+
answers: import_zod49.z.record(import_zod49.z.unknown()).describe("Questionnaire answers keyed by question ID (e.g. {business_name: 'My Clinic', business_phone: '+15551234567', ...})."),
|
|
13256
|
+
locationId: import_zod49.z.string().optional().describe("Location ID to deploy to. Uses default if not specified."),
|
|
13257
|
+
dryRun: import_zod49.z.boolean().optional().describe("If true, shows what would be created without actually creating anything. Defaults to false.")
|
|
12165
13258
|
},
|
|
12166
13259
|
async ({ templateFile, answers, locationId: locationId2, dryRun }) => {
|
|
12167
13260
|
try {
|
|
@@ -12407,7 +13500,7 @@ ${errors.join("\n")}` : "\nNo errors!",
|
|
|
12407
13500
|
}
|
|
12408
13501
|
|
|
12409
13502
|
// src/tools/validators.ts
|
|
12410
|
-
var
|
|
13503
|
+
var import_zod50 = require("zod");
|
|
12411
13504
|
var ALL_CATEGORIES = ["pipeline", "stage", "custom_field", "user", "workflow", "form", "calendar", "survey"];
|
|
12412
13505
|
var STANDARD_CONTACT_FIELDS = /* @__PURE__ */ new Set([
|
|
12413
13506
|
"first_name",
|
|
@@ -12676,7 +13769,7 @@ function collectCustomFieldKeys(envelope) {
|
|
|
12676
13769
|
}
|
|
12677
13770
|
return keys;
|
|
12678
13771
|
}
|
|
12679
|
-
function
|
|
13772
|
+
function collectIds2(envelope, listKeys) {
|
|
12680
13773
|
const ids = /* @__PURE__ */ new Set();
|
|
12681
13774
|
let arr = null;
|
|
12682
13775
|
if (Array.isArray(envelope)) arr = envelope;
|
|
@@ -12748,7 +13841,7 @@ async function fetchAndBuildLookups(client, builderClient, locationId2, workflow
|
|
|
12748
13841
|
status[cat] = "failed";
|
|
12749
13842
|
return /* @__PURE__ */ new Set();
|
|
12750
13843
|
}
|
|
12751
|
-
const { ids, found } =
|
|
13844
|
+
const { ids, found } = collectIds2(data[key], listKeys);
|
|
12752
13845
|
if (!found) status[cat] = "unparseable";
|
|
12753
13846
|
return ids;
|
|
12754
13847
|
}
|
|
@@ -12865,7 +13958,7 @@ function registerValidatorTools(server2, client, builderClient) {
|
|
|
12865
13958
|
server2.tool(
|
|
12866
13959
|
"validate_workflow",
|
|
12867
13960
|
"Pre-flight ID validation for ONE deployed GHL workflow. Scans every trigger and action for references to pipelines, pipeline stages, custom fields, users, workflows, forms, calendars, and surveys; verifies each ID exists in the current location. Use BEFORE publish_workflow when a workflow was edited, or when a published workflow stops behaving. Catches the silent-failure bug where invalid IDs make GHL skip all subsequent actions. Never reports a false break \u2014 anything it cannot fully verify is marked 'unverified', not 'error'.",
|
|
12868
|
-
{ workflowId:
|
|
13961
|
+
{ workflowId: import_zod50.z.string().describe("The workflow ID to validate.") },
|
|
12869
13962
|
async ({ workflowId }) => {
|
|
12870
13963
|
try {
|
|
12871
13964
|
const workflow = await builderClient.getWorkflow(workflowId);
|
|
@@ -13117,11 +14210,11 @@ function registerDiagnosticTools(server2, installedVersion, client, builderClien
|
|
|
13117
14210
|
}
|
|
13118
14211
|
|
|
13119
14212
|
// src/tools/snapshots.ts
|
|
13120
|
-
var
|
|
14213
|
+
var import_zod51 = require("zod");
|
|
13121
14214
|
init_ghl_client();
|
|
13122
|
-
var SnapshotSchema =
|
|
13123
|
-
var SnapshotsResponseSchema =
|
|
13124
|
-
var ShareLinkResponseSchema =
|
|
14215
|
+
var SnapshotSchema = import_zod51.z.object({ id: import_zod51.z.string(), name: import_zod51.z.string(), type: import_zod51.z.string() }).passthrough();
|
|
14216
|
+
var SnapshotsResponseSchema = import_zod51.z.object({ snapshots: import_zod51.z.array(SnapshotSchema) }).passthrough();
|
|
14217
|
+
var ShareLinkResponseSchema = import_zod51.z.object({ id: import_zod51.z.string(), shareLink: import_zod51.z.string() }).passthrough();
|
|
13125
14218
|
var SHARE_TYPES = [
|
|
13126
14219
|
"link",
|
|
13127
14220
|
"permanent_link",
|
|
@@ -13168,7 +14261,7 @@ function registerSnapshotTools(server2, client, registry2) {
|
|
|
13168
14261
|
"list_snapshots",
|
|
13169
14262
|
"List the agency's GHL snapshots (id, name, type) so you can pick the right one by name before applying it to a sub-account. Reads the agency/company-scoped key (not a sub-account PIT). companyId defaults to the active location's company; pass it explicitly to target a different company you have the agency key for. Read-only.",
|
|
13170
14263
|
{
|
|
13171
|
-
companyId:
|
|
14264
|
+
companyId: import_zod51.z.string().optional().describe(
|
|
13172
14265
|
"Agency/company ID whose snapshots to list. Defaults to the active location's company. Must match the company your agency key is scoped to."
|
|
13173
14266
|
)
|
|
13174
14267
|
},
|
|
@@ -13193,11 +14286,11 @@ function registerSnapshotTools(server2, client, registry2) {
|
|
|
13193
14286
|
"create_snapshot_share_link",
|
|
13194
14287
|
"Create a shareable load link for one of the agency's snapshots (returns a gohighlevel.com/?share=... URL to import the snapshot into a sub-account). Uses the agency/company-scoped key. WARNING: this is NOT idempotent \u2014 each call mints a NEW link, and there is no API to list or revoke links (revoke in the GHL UI under the snapshot's share settings). Pick share_type deliberately. Use list_snapshots first to get the snapshot id.",
|
|
13195
14288
|
{
|
|
13196
|
-
snapshot_id:
|
|
13197
|
-
share_type:
|
|
14289
|
+
snapshot_id: import_zod51.z.string().describe("The snapshot id to share (from list_snapshots)."),
|
|
14290
|
+
share_type: import_zod51.z.enum(SHARE_TYPES).describe(
|
|
13198
14291
|
"Share link type. 'link' = standard share link; 'permanent_link' = non-expiring; 'agency_link' = share to agencies; 'location_link' = load into a sub-account/location; 'marketplace_link' = marketplace listing. No default \u2014 choose intentionally."
|
|
13199
14292
|
),
|
|
13200
|
-
companyId:
|
|
14293
|
+
companyId: import_zod51.z.string().optional().describe(
|
|
13201
14294
|
"Agency/company ID that owns the snapshot. Defaults to the active location's company. Must match the company your agency key is scoped to."
|
|
13202
14295
|
)
|
|
13203
14296
|
},
|
|
@@ -13227,17 +14320,17 @@ function registerSnapshotTools(server2, client, registry2) {
|
|
|
13227
14320
|
}
|
|
13228
14321
|
|
|
13229
14322
|
// src/tools/phone.ts
|
|
13230
|
-
var
|
|
13231
|
-
var PhoneNumberSchema =
|
|
13232
|
-
var NumbersResponseSchema =
|
|
13233
|
-
var PoolsResponseSchema =
|
|
14323
|
+
var import_zod52 = require("zod");
|
|
14324
|
+
var PhoneNumberSchema = import_zod52.z.object({ sid: import_zod52.z.string(), value: import_zod52.z.string(), title: import_zod52.z.string().optional() }).passthrough();
|
|
14325
|
+
var NumbersResponseSchema = import_zod52.z.object({ phoneNumbers: import_zod52.z.array(PhoneNumberSchema) }).passthrough();
|
|
14326
|
+
var PoolsResponseSchema = import_zod52.z.object({ pools: import_zod52.z.array(import_zod52.z.object({}).passthrough()) }).passthrough();
|
|
13234
14327
|
function registerPhoneTools(server2, client) {
|
|
13235
14328
|
safeTool(
|
|
13236
14329
|
server2,
|
|
13237
14330
|
"list_phone_numbers",
|
|
13238
14331
|
"List the LC Phone numbers provisioned for a location (sid, number, label). Read-only. Use to verify or count purchased numbers (e.g. provisioning step 11). Number purchase is not exposed (billable write).",
|
|
13239
14332
|
{
|
|
13240
|
-
locationId:
|
|
14333
|
+
locationId: import_zod52.z.string().optional().describe("Defaults to the active location.")
|
|
13241
14334
|
},
|
|
13242
14335
|
async ({ locationId: locationId2 }) => {
|
|
13243
14336
|
const loc = client.resolveLocationId(locationId2);
|
|
@@ -13255,7 +14348,7 @@ function registerPhoneTools(server2, client) {
|
|
|
13255
14348
|
"list_number_pools",
|
|
13256
14349
|
"List LC Phone number pools configured for a location. Read-only.",
|
|
13257
14350
|
{
|
|
13258
|
-
locationId:
|
|
14351
|
+
locationId: import_zod52.z.string().optional().describe("Defaults to the active location.")
|
|
13259
14352
|
},
|
|
13260
14353
|
async ({ locationId: locationId2 }) => {
|
|
13261
14354
|
const loc = client.resolveLocationId(locationId2);
|
|
@@ -13267,10 +14360,10 @@ function registerPhoneTools(server2, client) {
|
|
|
13267
14360
|
}
|
|
13268
14361
|
|
|
13269
14362
|
// src/tools/account-health.ts
|
|
13270
|
-
var
|
|
13271
|
-
var MetaTotalSchema =
|
|
13272
|
-
var TotalSchema =
|
|
13273
|
-
var NumbersSchema =
|
|
14363
|
+
var import_zod53 = require("zod");
|
|
14364
|
+
var MetaTotalSchema = import_zod53.z.object({ meta: import_zod53.z.object({ total: import_zod53.z.number() }).passthrough() }).passthrough();
|
|
14365
|
+
var TotalSchema = import_zod53.z.object({ total: import_zod53.z.number() }).passthrough();
|
|
14366
|
+
var NumbersSchema = import_zod53.z.object({ phoneNumbers: import_zod53.z.array(import_zod53.z.unknown()) }).passthrough();
|
|
13274
14367
|
var OPP_STATUSES = ["open", "won", "lost", "abandoned"];
|
|
13275
14368
|
async function section(scope, fn) {
|
|
13276
14369
|
try {
|
|
@@ -13285,8 +14378,8 @@ function registerAccountHealthTools(server2, client) {
|
|
|
13285
14378
|
"get_account_health_summary",
|
|
13286
14379
|
"Account-health summary for a location, composed from existing reads (GHL has no reporting API). Returns: total contacts + NEW contacts in the window; total opportunities + counts by status (open/won/lost/abandoned); total conversations; phone-number count. Every metric is explicitly labeled all_time vs window (with start/end) \u2014 windowed and all-time numbers are never conflated. Sections that can't be read return status:'unavailable' (never a misleading 0). Revenue and appointments are intentionally excluded (not reachable / too costly via the public API).",
|
|
13287
14380
|
{
|
|
13288
|
-
locationId:
|
|
13289
|
-
windowDays:
|
|
14381
|
+
locationId: import_zod53.z.string().optional().describe("Defaults to the active location."),
|
|
14382
|
+
windowDays: import_zod53.z.number().int().positive().max(365).optional().describe("Lookback window in days for windowed metrics (new contacts). Default 30.")
|
|
13290
14383
|
},
|
|
13291
14384
|
async ({ locationId: locationId2, windowDays }) => {
|
|
13292
14385
|
const loc = client.resolveLocationId(locationId2);
|
|
@@ -13358,7 +14451,7 @@ function registerAccountHealthTools(server2, client) {
|
|
|
13358
14451
|
}
|
|
13359
14452
|
|
|
13360
14453
|
// src/tools/intake-to-build.ts
|
|
13361
|
-
var
|
|
14454
|
+
var import_zod56 = require("zod");
|
|
13362
14455
|
|
|
13363
14456
|
// src/intake-to-build/form-template.ts
|
|
13364
14457
|
init_question_set();
|
|
@@ -13642,7 +14735,7 @@ init_question_set();
|
|
|
13642
14735
|
init_question_set();
|
|
13643
14736
|
|
|
13644
14737
|
// src/intake-to-build/brief.ts
|
|
13645
|
-
var
|
|
14738
|
+
var import_zod54 = require("zod");
|
|
13646
14739
|
var BRIEF_SCHEMA_VERSION = "0.1";
|
|
13647
14740
|
var PRESETS = [
|
|
13648
14741
|
"generic",
|
|
@@ -13652,67 +14745,67 @@ var PRESETS = [
|
|
|
13652
14745
|
"ecom",
|
|
13653
14746
|
"agency"
|
|
13654
14747
|
];
|
|
13655
|
-
var presetSchema =
|
|
14748
|
+
var presetSchema = import_zod54.z.enum(PRESETS);
|
|
13656
14749
|
var BRIEF_SOURCES = ["agency_os", "business_os", "intake_form", "hybrid"];
|
|
13657
|
-
var briefSourceSchema =
|
|
13658
|
-
var pricePointSchema =
|
|
13659
|
-
name:
|
|
13660
|
-
price:
|
|
14750
|
+
var briefSourceSchema = import_zod54.z.enum(BRIEF_SOURCES);
|
|
14751
|
+
var pricePointSchema = import_zod54.z.object({
|
|
14752
|
+
name: import_zod54.z.string(),
|
|
14753
|
+
price: import_zod54.z.string()
|
|
13661
14754
|
});
|
|
13662
|
-
var briefSchema =
|
|
13663
|
-
schemaVersion:
|
|
13664
|
-
briefId:
|
|
14755
|
+
var briefSchema = import_zod54.z.object({
|
|
14756
|
+
schemaVersion: import_zod54.z.string(),
|
|
14757
|
+
briefId: import_zod54.z.string(),
|
|
13665
14758
|
preset: presetSchema,
|
|
13666
14759
|
briefSource: briefSourceSchema,
|
|
13667
14760
|
/** Partner-OS deep structures (ICA / offer / brand-DNA), carried verbatim. */
|
|
13668
|
-
extended:
|
|
13669
|
-
business:
|
|
13670
|
-
name:
|
|
13671
|
-
type:
|
|
13672
|
-
website:
|
|
13673
|
-
location:
|
|
13674
|
-
timezone:
|
|
14761
|
+
extended: import_zod54.z.record(import_zod54.z.unknown()).optional(),
|
|
14762
|
+
business: import_zod54.z.object({
|
|
14763
|
+
name: import_zod54.z.string(),
|
|
14764
|
+
type: import_zod54.z.string().optional(),
|
|
14765
|
+
website: import_zod54.z.string().optional(),
|
|
14766
|
+
location: import_zod54.z.string().optional(),
|
|
14767
|
+
timezone: import_zod54.z.string().optional(),
|
|
13675
14768
|
// Ratified additions (atlas 2026-06-15). Enum-ish but kept as strings for
|
|
13676
14769
|
// the same tolerance reason as business.type (don't reject valid briefs).
|
|
13677
|
-
teamSize:
|
|
13678
|
-
monthlyLeadVolume:
|
|
13679
|
-
hours:
|
|
14770
|
+
teamSize: import_zod54.z.string().optional(),
|
|
14771
|
+
monthlyLeadVolume: import_zod54.z.string().optional(),
|
|
14772
|
+
hours: import_zod54.z.string().optional()
|
|
13680
14773
|
}).passthrough(),
|
|
13681
|
-
offer:
|
|
13682
|
-
summary:
|
|
14774
|
+
offer: import_zod54.z.object({
|
|
14775
|
+
summary: import_zod54.z.string().optional(),
|
|
13683
14776
|
// Parsed best-effort; tolerate a raw string when parsing was not possible.
|
|
13684
|
-
pricePoints:
|
|
13685
|
-
leadMagnet:
|
|
13686
|
-
avgDealValue:
|
|
14777
|
+
pricePoints: import_zod54.z.union([import_zod54.z.array(pricePointSchema), import_zod54.z.string()]).optional(),
|
|
14778
|
+
leadMagnet: import_zod54.z.string().optional(),
|
|
14779
|
+
avgDealValue: import_zod54.z.string().optional()
|
|
13687
14780
|
}).passthrough().optional(),
|
|
13688
|
-
audience:
|
|
13689
|
-
ideal:
|
|
13690
|
-
painPoints:
|
|
13691
|
-
objections:
|
|
14781
|
+
audience: import_zod54.z.object({
|
|
14782
|
+
ideal: import_zod54.z.string().optional(),
|
|
14783
|
+
painPoints: import_zod54.z.array(import_zod54.z.string()).optional(),
|
|
14784
|
+
objections: import_zod54.z.array(import_zod54.z.string()).optional()
|
|
13692
14785
|
}).passthrough().optional(),
|
|
13693
|
-
goal:
|
|
14786
|
+
goal: import_zod54.z.object({
|
|
13694
14787
|
// Kept as string: the form option labels are the canonical values, but
|
|
13695
14788
|
// the contract sample shortens some (e.g. "high-touch"). See §7 note.
|
|
13696
|
-
primary:
|
|
13697
|
-
salesStages:
|
|
13698
|
-
bookingNeeded:
|
|
13699
|
-
followUpStyle:
|
|
14789
|
+
primary: import_zod54.z.string(),
|
|
14790
|
+
salesStages: import_zod54.z.array(import_zod54.z.string()).optional(),
|
|
14791
|
+
bookingNeeded: import_zod54.z.boolean().optional(),
|
|
14792
|
+
followUpStyle: import_zod54.z.string().optional()
|
|
13700
14793
|
}).passthrough(),
|
|
13701
|
-
channels:
|
|
13702
|
-
email:
|
|
13703
|
-
sms:
|
|
13704
|
-
a2pStatus:
|
|
13705
|
-
payment:
|
|
13706
|
-
calendarConnected:
|
|
13707
|
-
social:
|
|
14794
|
+
channels: import_zod54.z.object({
|
|
14795
|
+
email: import_zod54.z.boolean().optional(),
|
|
14796
|
+
sms: import_zod54.z.boolean().optional(),
|
|
14797
|
+
a2pStatus: import_zod54.z.string().optional(),
|
|
14798
|
+
payment: import_zod54.z.string().optional(),
|
|
14799
|
+
calendarConnected: import_zod54.z.boolean().optional(),
|
|
14800
|
+
social: import_zod54.z.array(import_zod54.z.string()).optional()
|
|
13708
14801
|
}).passthrough().optional(),
|
|
13709
|
-
assets:
|
|
13710
|
-
existingPipeline:
|
|
13711
|
-
existingWorkflows:
|
|
13712
|
-
brand:
|
|
13713
|
-
notes:
|
|
14802
|
+
assets: import_zod54.z.object({
|
|
14803
|
+
existingPipeline: import_zod54.z.string().optional(),
|
|
14804
|
+
existingWorkflows: import_zod54.z.string().optional(),
|
|
14805
|
+
brand: import_zod54.z.string().optional(),
|
|
14806
|
+
notes: import_zod54.z.string().optional()
|
|
13714
14807
|
}).passthrough().optional(),
|
|
13715
|
-
flags:
|
|
14808
|
+
flags: import_zod54.z.array(import_zod54.z.string()).optional()
|
|
13716
14809
|
}).strict();
|
|
13717
14810
|
function validateBrief(input) {
|
|
13718
14811
|
const parsed = briefSchema.safeParse(input);
|
|
@@ -13868,7 +14961,7 @@ function normalizeSubmissionToBrief(opts) {
|
|
|
13868
14961
|
}
|
|
13869
14962
|
|
|
13870
14963
|
// src/intake-to-build/plan.ts
|
|
13871
|
-
var
|
|
14964
|
+
var import_zod55 = require("zod");
|
|
13872
14965
|
var REF_NAMESPACES = [
|
|
13873
14966
|
"pipeline",
|
|
13874
14967
|
"stage",
|
|
@@ -13885,22 +14978,22 @@ var REF_NAMESPACES = [
|
|
|
13885
14978
|
"handoff"
|
|
13886
14979
|
];
|
|
13887
14980
|
var REF_RE = new RegExp(`^(${REF_NAMESPACES.join("|")})\\.[a-z0-9]+(_[a-z0-9]+)*$`);
|
|
13888
|
-
var refSchema =
|
|
14981
|
+
var refSchema = import_zod55.z.string().regex(REF_RE, "must be a <namespace>.<snake_case_slug> ref (no real GHL IDs)");
|
|
13889
14982
|
function nsRef(ns) {
|
|
13890
|
-
return
|
|
14983
|
+
return import_zod55.z.string().regex(new RegExp(`^${ns}\\.[a-z0-9]+(_[a-z0-9]+)*$`), `must be a ${ns}.* ref`);
|
|
13891
14984
|
}
|
|
13892
14985
|
function refNamespace(ref) {
|
|
13893
14986
|
return ref.split(".")[0];
|
|
13894
14987
|
}
|
|
13895
|
-
var stageSchema =
|
|
14988
|
+
var stageSchema = import_zod55.z.object({
|
|
13896
14989
|
ref: nsRef("stage"),
|
|
13897
|
-
name:
|
|
13898
|
-
position:
|
|
14990
|
+
name: import_zod55.z.string(),
|
|
14991
|
+
position: import_zod55.z.number().int().nonnegative()
|
|
13899
14992
|
});
|
|
13900
|
-
var pipelineSchema =
|
|
14993
|
+
var pipelineSchema = import_zod55.z.object({
|
|
13901
14994
|
ref: nsRef("pipeline"),
|
|
13902
|
-
name:
|
|
13903
|
-
stages:
|
|
14995
|
+
name: import_zod55.z.string(),
|
|
14996
|
+
stages: import_zod55.z.array(stageSchema).min(1)
|
|
13904
14997
|
});
|
|
13905
14998
|
var GHL_FIELD_DATATYPES = [
|
|
13906
14999
|
"TEXT",
|
|
@@ -13917,21 +15010,21 @@ var GHL_FIELD_DATATYPES = [
|
|
|
13917
15010
|
"FILE_UPLOAD",
|
|
13918
15011
|
"SIGNATURE"
|
|
13919
15012
|
];
|
|
13920
|
-
var customFieldSchema =
|
|
15013
|
+
var customFieldSchema = import_zod55.z.object({
|
|
13921
15014
|
ref: nsRef("field"),
|
|
13922
|
-
name:
|
|
13923
|
-
dataType:
|
|
13924
|
-
model:
|
|
13925
|
-
options:
|
|
15015
|
+
name: import_zod55.z.string(),
|
|
15016
|
+
dataType: import_zod55.z.enum(GHL_FIELD_DATATYPES),
|
|
15017
|
+
model: import_zod55.z.enum(["contact", "opportunity"]).optional(),
|
|
15018
|
+
options: import_zod55.z.array(import_zod55.z.string()).optional()
|
|
13926
15019
|
});
|
|
13927
|
-
var tagSchema =
|
|
15020
|
+
var tagSchema = import_zod55.z.object({
|
|
13928
15021
|
ref: nsRef("tag"),
|
|
13929
|
-
name:
|
|
15022
|
+
name: import_zod55.z.string()
|
|
13930
15023
|
});
|
|
13931
|
-
var customValueSchema =
|
|
15024
|
+
var customValueSchema = import_zod55.z.object({
|
|
13932
15025
|
ref: nsRef("cv"),
|
|
13933
|
-
name:
|
|
13934
|
-
value:
|
|
15026
|
+
name: import_zod55.z.string(),
|
|
15027
|
+
value: import_zod55.z.string().optional(),
|
|
13935
15028
|
filledBy: refSchema.optional()
|
|
13936
15029
|
});
|
|
13937
15030
|
var CALENDAR_TYPES = [
|
|
@@ -13941,89 +15034,89 @@ var CALENDAR_TYPES = [
|
|
|
13941
15034
|
"collective",
|
|
13942
15035
|
"service_booking"
|
|
13943
15036
|
];
|
|
13944
|
-
var openHoursBlockSchema =
|
|
13945
|
-
daysOfTheWeek:
|
|
13946
|
-
hours:
|
|
13947
|
-
|
|
13948
|
-
openHour:
|
|
13949
|
-
openMinute:
|
|
13950
|
-
closeHour:
|
|
13951
|
-
closeMinute:
|
|
15037
|
+
var openHoursBlockSchema = import_zod55.z.object({
|
|
15038
|
+
daysOfTheWeek: import_zod55.z.array(import_zod55.z.number().int().min(0).max(6)),
|
|
15039
|
+
hours: import_zod55.z.array(
|
|
15040
|
+
import_zod55.z.object({
|
|
15041
|
+
openHour: import_zod55.z.number().int().min(0).max(23),
|
|
15042
|
+
openMinute: import_zod55.z.number().int().min(0).max(59),
|
|
15043
|
+
closeHour: import_zod55.z.number().int().min(0).max(23),
|
|
15044
|
+
closeMinute: import_zod55.z.number().int().min(0).max(59)
|
|
13952
15045
|
})
|
|
13953
15046
|
)
|
|
13954
15047
|
});
|
|
13955
|
-
var calendarSchema =
|
|
15048
|
+
var calendarSchema = import_zod55.z.object({
|
|
13956
15049
|
ref: nsRef("calendar"),
|
|
13957
|
-
name:
|
|
13958
|
-
calendarType:
|
|
13959
|
-
openHours:
|
|
13960
|
-
availabilityType:
|
|
13961
|
-
requiresStaff:
|
|
15050
|
+
name: import_zod55.z.string(),
|
|
15051
|
+
calendarType: import_zod55.z.enum(CALENDAR_TYPES),
|
|
15052
|
+
openHours: import_zod55.z.array(openHoursBlockSchema).optional(),
|
|
15053
|
+
availabilityType: import_zod55.z.number().int().optional(),
|
|
15054
|
+
requiresStaff: import_zod55.z.boolean().optional()
|
|
13962
15055
|
});
|
|
13963
|
-
var formFieldSchema =
|
|
13964
|
-
|
|
13965
|
-
type:
|
|
13966
|
-
key:
|
|
13967
|
-
required:
|
|
15056
|
+
var formFieldSchema = import_zod55.z.discriminatedUnion("type", [
|
|
15057
|
+
import_zod55.z.object({
|
|
15058
|
+
type: import_zod55.z.literal("standard"),
|
|
15059
|
+
key: import_zod55.z.string(),
|
|
15060
|
+
required: import_zod55.z.boolean().optional()
|
|
13968
15061
|
}),
|
|
13969
|
-
|
|
13970
|
-
type:
|
|
15062
|
+
import_zod55.z.object({
|
|
15063
|
+
type: import_zod55.z.literal("custom"),
|
|
13971
15064
|
fieldRef: nsRef("field"),
|
|
13972
|
-
required:
|
|
15065
|
+
required: import_zod55.z.boolean().optional()
|
|
13973
15066
|
})
|
|
13974
15067
|
]);
|
|
13975
|
-
var formSchema =
|
|
15068
|
+
var formSchema = import_zod55.z.object({
|
|
13976
15069
|
ref: nsRef("form"),
|
|
13977
|
-
name:
|
|
13978
|
-
fields:
|
|
15070
|
+
name: import_zod55.z.string(),
|
|
15071
|
+
fields: import_zod55.z.array(formFieldSchema)
|
|
13979
15072
|
});
|
|
13980
|
-
var pageSchema =
|
|
15073
|
+
var pageSchema = import_zod55.z.object({
|
|
13981
15074
|
ref: nsRef("page"),
|
|
13982
|
-
name:
|
|
13983
|
-
role:
|
|
13984
|
-
outline:
|
|
15075
|
+
name: import_zod55.z.string(),
|
|
15076
|
+
role: import_zod55.z.string().optional(),
|
|
15077
|
+
outline: import_zod55.z.string().optional(),
|
|
13985
15078
|
formRef: nsRef("form").optional(),
|
|
13986
15079
|
calendarRef: nsRef("calendar").optional()
|
|
13987
15080
|
});
|
|
13988
15081
|
var FUNNEL_TARGETS = ["ghl", "external"];
|
|
13989
15082
|
var FUNNEL_HOSTS = ["cloudflare", "vercel"];
|
|
13990
|
-
var funnelSchema =
|
|
15083
|
+
var funnelSchema = import_zod55.z.object({
|
|
13991
15084
|
ref: nsRef("funnel"),
|
|
13992
|
-
name:
|
|
15085
|
+
name: import_zod55.z.string(),
|
|
13993
15086
|
// Where the funnel is built. "ghl" (default) = funnel + named steps in GHL.
|
|
13994
15087
|
// "external" = the subscriber builds + hosts the site themselves (Cloudflare/
|
|
13995
15088
|
// Vercel) and wires its form back to this GHL sub-account (POWER-USER path —
|
|
13996
15089
|
// see blueprint-funnel-targets-spec.md §9). The executor does NOT build or
|
|
13997
15090
|
// deploy an external funnel; it surfaces the GHL-side wiring info.
|
|
13998
|
-
target:
|
|
13999
|
-
host:
|
|
15091
|
+
target: import_zod55.z.enum(FUNNEL_TARGETS).optional(),
|
|
15092
|
+
host: import_zod55.z.enum(FUNNEL_HOSTS).optional(),
|
|
14000
15093
|
// external only
|
|
14001
|
-
domain:
|
|
15094
|
+
domain: import_zod55.z.string().optional(),
|
|
14002
15095
|
// external only
|
|
14003
|
-
pages:
|
|
15096
|
+
pages: import_zod55.z.array(pageSchema)
|
|
14004
15097
|
});
|
|
14005
|
-
var emailAssetSchema =
|
|
15098
|
+
var emailAssetSchema = import_zod55.z.object({
|
|
14006
15099
|
ref: nsRef("email"),
|
|
14007
|
-
name:
|
|
14008
|
-
subject:
|
|
14009
|
-
bodyOutline:
|
|
14010
|
-
body:
|
|
14011
|
-
mergeTags:
|
|
15100
|
+
name: import_zod55.z.string(),
|
|
15101
|
+
subject: import_zod55.z.string().optional(),
|
|
15102
|
+
bodyOutline: import_zod55.z.string().optional(),
|
|
15103
|
+
body: import_zod55.z.string().optional(),
|
|
15104
|
+
mergeTags: import_zod55.z.array(import_zod55.z.string()).optional()
|
|
14012
15105
|
});
|
|
14013
|
-
var smsAssetSchema =
|
|
15106
|
+
var smsAssetSchema = import_zod55.z.object({
|
|
14014
15107
|
ref: nsRef("sms"),
|
|
14015
|
-
name:
|
|
14016
|
-
bodyOutline:
|
|
14017
|
-
body:
|
|
14018
|
-
mergeTags:
|
|
15108
|
+
name: import_zod55.z.string(),
|
|
15109
|
+
bodyOutline: import_zod55.z.string().optional(),
|
|
15110
|
+
body: import_zod55.z.string().optional(),
|
|
15111
|
+
mergeTags: import_zod55.z.array(import_zod55.z.string()).optional()
|
|
14019
15112
|
});
|
|
14020
|
-
var waitUnit =
|
|
15113
|
+
var waitUnit = import_zod55.z.enum(["minutes", "hours", "days"]);
|
|
14021
15114
|
var branchActionOptions = [
|
|
14022
|
-
|
|
14023
|
-
|
|
14024
|
-
|
|
14025
|
-
|
|
14026
|
-
|
|
15115
|
+
import_zod55.z.object({ type: import_zod55.z.literal("add_contact_tag"), tagRef: nsRef("tag") }),
|
|
15116
|
+
import_zod55.z.object({ type: import_zod55.z.literal("remove_contact_tag"), tagRef: nsRef("tag") }),
|
|
15117
|
+
import_zod55.z.object({ type: import_zod55.z.literal("send_email"), emailRef: nsRef("email") }),
|
|
15118
|
+
import_zod55.z.object({ type: import_zod55.z.literal("send_sms"), smsRef: nsRef("sms") }),
|
|
15119
|
+
import_zod55.z.object({ type: import_zod55.z.literal("wait"), value: import_zod55.z.number().positive(), unit: waitUnit }),
|
|
14027
15120
|
// Appointment-relative wait ("wait until N BEFORE the appointment").
|
|
14028
15121
|
// Only works when the workflow has an appointment in context (i.e. an
|
|
14029
15122
|
// `appointment` trigger) — enforced by validateBuildPlan. Expands to GHL's
|
|
@@ -14032,85 +15125,85 @@ var branchActionOptions = [
|
|
|
14032
15125
|
// (GHL stores whole minutes). Only "before" is emitted today — that's the
|
|
14033
15126
|
// shape we captured + proved; "after" (post-appointment follow-up) is
|
|
14034
15127
|
// deferred until its shape is captured from a real workflow.
|
|
14035
|
-
|
|
14036
|
-
type:
|
|
14037
|
-
value:
|
|
15128
|
+
import_zod55.z.object({
|
|
15129
|
+
type: import_zod55.z.literal("wait_appointment"),
|
|
15130
|
+
value: import_zod55.z.number().int().positive(),
|
|
14038
15131
|
unit: waitUnit
|
|
14039
15132
|
}),
|
|
14040
|
-
|
|
14041
|
-
type:
|
|
14042
|
-
to:
|
|
14043
|
-
title:
|
|
14044
|
-
body:
|
|
15133
|
+
import_zod55.z.object({
|
|
15134
|
+
type: import_zod55.z.literal("internal_notification"),
|
|
15135
|
+
to: import_zod55.z.string(),
|
|
15136
|
+
title: import_zod55.z.string(),
|
|
15137
|
+
body: import_zod55.z.string()
|
|
14045
15138
|
}),
|
|
14046
|
-
|
|
14047
|
-
type:
|
|
15139
|
+
import_zod55.z.object({
|
|
15140
|
+
type: import_zod55.z.literal("update_contact_field"),
|
|
14048
15141
|
fieldRef: nsRef("field"),
|
|
14049
|
-
value:
|
|
15142
|
+
value: import_zod55.z.string()
|
|
14050
15143
|
}),
|
|
14051
|
-
|
|
14052
|
-
|
|
14053
|
-
type:
|
|
14054
|
-
title:
|
|
14055
|
-
body:
|
|
14056
|
-
dueDate:
|
|
14057
|
-
assignedTo:
|
|
15144
|
+
import_zod55.z.object({ type: import_zod55.z.literal("add_notes"), body: import_zod55.z.string() }),
|
|
15145
|
+
import_zod55.z.object({
|
|
15146
|
+
type: import_zod55.z.literal("task_notification"),
|
|
15147
|
+
title: import_zod55.z.string(),
|
|
15148
|
+
body: import_zod55.z.string().optional(),
|
|
15149
|
+
dueDate: import_zod55.z.string().optional(),
|
|
15150
|
+
assignedTo: import_zod55.z.string().optional()
|
|
14058
15151
|
}),
|
|
14059
|
-
|
|
14060
|
-
|
|
14061
|
-
|
|
14062
|
-
type:
|
|
15152
|
+
import_zod55.z.object({ type: import_zod55.z.literal("remove_from_workflow"), workflowRef: nsRef("workflow") }),
|
|
15153
|
+
import_zod55.z.object({ type: import_zod55.z.literal("add_to_workflow"), workflowRef: nsRef("workflow") }),
|
|
15154
|
+
import_zod55.z.object({
|
|
15155
|
+
type: import_zod55.z.literal("create_opportunity"),
|
|
14063
15156
|
pipelineRef: nsRef("pipeline"),
|
|
14064
15157
|
stageRef: nsRef("stage"),
|
|
14065
15158
|
// Opportunity name (merge fields allowed). Defaults to the contact's name.
|
|
14066
15159
|
// Required by GHL's create node; without it the create silently no-ops.
|
|
14067
|
-
name:
|
|
15160
|
+
name: import_zod55.z.string().optional(),
|
|
14068
15161
|
// Opportunity monetary value (the deal/sale dollar amount). A string so it
|
|
14069
15162
|
// can be a literal ("2500") OR a merge field ("{{contact.package_value}}").
|
|
14070
15163
|
// Optional — omitted → GHL leaves the value unset. Shape captured from Lux
|
|
14071
15164
|
// Bio "14. Package Sale". Lux models the lifecycle by pipeline STAGE, not GHL
|
|
14072
15165
|
// won/lost status, so a "won" opp = move to the closing stage WITH this value.
|
|
14073
|
-
value:
|
|
15166
|
+
value: import_zod55.z.string().optional()
|
|
14074
15167
|
}),
|
|
14075
|
-
|
|
14076
|
-
type:
|
|
15168
|
+
import_zod55.z.object({
|
|
15169
|
+
type: import_zod55.z.literal("update_opportunity"),
|
|
14077
15170
|
pipelineRef: nsRef("pipeline"),
|
|
14078
15171
|
stageRef: nsRef("stage"),
|
|
14079
15172
|
// Opportunity monetary value (see create_opportunity.value). Optional.
|
|
14080
|
-
value:
|
|
15173
|
+
value: import_zod55.z.string().optional()
|
|
14081
15174
|
}),
|
|
14082
|
-
|
|
14083
|
-
type:
|
|
14084
|
-
goalCondition:
|
|
15175
|
+
import_zod55.z.object({
|
|
15176
|
+
type: import_zod55.z.literal("goal_event"),
|
|
15177
|
+
goalCondition: import_zod55.z.string(),
|
|
14085
15178
|
// GHL's GoalAction enum (extracted 2026-05-18): continue | wait | exit.
|
|
14086
|
-
action:
|
|
15179
|
+
action: import_zod55.z.enum(["exit", "continue", "wait"]).optional()
|
|
14087
15180
|
})
|
|
14088
15181
|
];
|
|
14089
|
-
var branchActionSchema =
|
|
14090
|
-
var findOpportunitySchema =
|
|
14091
|
-
type:
|
|
15182
|
+
var branchActionSchema = import_zod55.z.discriminatedUnion("type", branchActionOptions);
|
|
15183
|
+
var findOpportunitySchema = import_zod55.z.object({
|
|
15184
|
+
type: import_zod55.z.literal("find_opportunity"),
|
|
14092
15185
|
pipelineRef: nsRef("pipeline"),
|
|
14093
|
-
found:
|
|
14094
|
-
notFound:
|
|
15186
|
+
found: import_zod55.z.array(branchActionSchema).default([]),
|
|
15187
|
+
notFound: import_zod55.z.array(branchActionSchema).default([])
|
|
14095
15188
|
});
|
|
14096
|
-
var actionSchema =
|
|
15189
|
+
var actionSchema = import_zod55.z.discriminatedUnion("type", [...branchActionOptions, findOpportunitySchema]);
|
|
14097
15190
|
var APPOINTMENT_STATUSES = ["new", "confirmed", "showed", "noshow", "cancelled", "invalid"];
|
|
14098
|
-
var triggerSchema =
|
|
14099
|
-
type:
|
|
15191
|
+
var triggerSchema = import_zod55.z.object({
|
|
15192
|
+
type: import_zod55.z.string(),
|
|
14100
15193
|
formRef: nsRef("form").optional(),
|
|
14101
15194
|
tagRef: nsRef("tag").optional(),
|
|
14102
15195
|
calendarRef: nsRef("calendar").optional(),
|
|
14103
15196
|
pipelineRef: nsRef("pipeline").optional(),
|
|
14104
15197
|
stageRef: nsRef("stage").optional(),
|
|
14105
15198
|
// Required for a native `appointment` trigger (the status it fires on).
|
|
14106
|
-
appointmentStatus:
|
|
15199
|
+
appointmentStatus: import_zod55.z.enum(APPOINTMENT_STATUSES).optional()
|
|
14107
15200
|
});
|
|
14108
|
-
var workflowSchema =
|
|
15201
|
+
var workflowSchema = import_zod55.z.object({
|
|
14109
15202
|
ref: nsRef("workflow"),
|
|
14110
|
-
name:
|
|
15203
|
+
name: import_zod55.z.string(),
|
|
14111
15204
|
trigger: triggerSchema.optional(),
|
|
14112
|
-
stopOnResponse:
|
|
14113
|
-
actions:
|
|
15205
|
+
stopOnResponse: import_zod55.z.boolean().optional(),
|
|
15206
|
+
actions: import_zod55.z.array(actionSchema).max(40)
|
|
14114
15207
|
// house rule: <=40 actions/workflow
|
|
14115
15208
|
});
|
|
14116
15209
|
var HANDOFF_OWNER_LEGACY = {
|
|
@@ -14118,35 +15211,35 @@ var HANDOFF_OWNER_LEGACY = {
|
|
|
14118
15211
|
"JERRY-EXT": "OPERATOR-EXT",
|
|
14119
15212
|
"SASHA": "TEAM"
|
|
14120
15213
|
};
|
|
14121
|
-
var handoffSchema =
|
|
15214
|
+
var handoffSchema = import_zod55.z.object({
|
|
14122
15215
|
ref: nsRef("handoff"),
|
|
14123
|
-
owner:
|
|
14124
|
-
title:
|
|
14125
|
-
trigger:
|
|
14126
|
-
instruction:
|
|
15216
|
+
owner: import_zod55.z.enum(["OPERATOR-UI", "OPERATOR-EXT", "TEAM", "JERRY-UI", "JERRY-EXT", "SASHA"]).transform((o) => HANDOFF_OWNER_LEGACY[o] ?? o),
|
|
15217
|
+
title: import_zod55.z.string(),
|
|
15218
|
+
trigger: import_zod55.z.string().optional(),
|
|
15219
|
+
instruction: import_zod55.z.string(),
|
|
14127
15220
|
produces: refSchema.nullable().optional(),
|
|
14128
|
-
successCheck:
|
|
14129
|
-
blocks:
|
|
15221
|
+
successCheck: import_zod55.z.string(),
|
|
15222
|
+
blocks: import_zod55.z.array(import_zod55.z.string()).optional()
|
|
14130
15223
|
});
|
|
14131
|
-
var buildPlanSchema =
|
|
14132
|
-
schemaVersion:
|
|
14133
|
-
planId:
|
|
14134
|
-
briefId:
|
|
14135
|
-
preset:
|
|
14136
|
-
summary:
|
|
14137
|
-
pipelines:
|
|
14138
|
-
customFields:
|
|
14139
|
-
tags:
|
|
14140
|
-
customValues:
|
|
14141
|
-
calendars:
|
|
14142
|
-
forms:
|
|
14143
|
-
funnels:
|
|
14144
|
-
emails:
|
|
14145
|
-
sms:
|
|
14146
|
-
workflows:
|
|
14147
|
-
handoffs:
|
|
14148
|
-
buildOrder:
|
|
14149
|
-
idMap:
|
|
15224
|
+
var buildPlanSchema = import_zod55.z.object({
|
|
15225
|
+
schemaVersion: import_zod55.z.string(),
|
|
15226
|
+
planId: import_zod55.z.string(),
|
|
15227
|
+
briefId: import_zod55.z.string(),
|
|
15228
|
+
preset: import_zod55.z.string(),
|
|
15229
|
+
summary: import_zod55.z.string().optional(),
|
|
15230
|
+
pipelines: import_zod55.z.array(pipelineSchema).optional(),
|
|
15231
|
+
customFields: import_zod55.z.array(customFieldSchema).optional(),
|
|
15232
|
+
tags: import_zod55.z.array(tagSchema).optional(),
|
|
15233
|
+
customValues: import_zod55.z.array(customValueSchema).optional(),
|
|
15234
|
+
calendars: import_zod55.z.array(calendarSchema).optional(),
|
|
15235
|
+
forms: import_zod55.z.array(formSchema).optional(),
|
|
15236
|
+
funnels: import_zod55.z.array(funnelSchema).optional(),
|
|
15237
|
+
emails: import_zod55.z.array(emailAssetSchema).optional(),
|
|
15238
|
+
sms: import_zod55.z.array(smsAssetSchema).optional(),
|
|
15239
|
+
workflows: import_zod55.z.array(workflowSchema).optional(),
|
|
15240
|
+
handoffs: import_zod55.z.array(handoffSchema).optional(),
|
|
15241
|
+
buildOrder: import_zod55.z.array(import_zod55.z.string()).optional(),
|
|
15242
|
+
idMap: import_zod55.z.record(import_zod55.z.string()).optional()
|
|
14150
15243
|
}).strict();
|
|
14151
15244
|
function collectDefinedRefs(plan) {
|
|
14152
15245
|
const refs = /* @__PURE__ */ new Map();
|
|
@@ -15165,9 +16258,9 @@ function renderReport(plan, result, ctx) {
|
|
|
15165
16258
|
}
|
|
15166
16259
|
}
|
|
15167
16260
|
for (const w of result.workflows) {
|
|
15168
|
-
const
|
|
16261
|
+
const gate2 = w.gatedBy.length ? ` \u2014 DRAFT, gated by ${w.gatedBy.join(", ")}` : ctx.publishWorkflows ? " \u2014 publish" : " \u2014 DRAFT";
|
|
15169
16262
|
const split = w.splitInto > 1 ? ` (splits into ${w.splitInto} chained workflows, >${MAX_ACTIONS_PER_WORKFLOW} actions)` : "";
|
|
15170
|
-
L.push(` [workflow] ${w.name}: ${w.nativeActions.length} actions${split}${
|
|
16263
|
+
L.push(` [workflow] ${w.name}: ${w.nativeActions.length} actions${split}${gate2}`);
|
|
15171
16264
|
}
|
|
15172
16265
|
L.push("");
|
|
15173
16266
|
L.push("\u2500\u2500 You must do these by hand (in order) \u2500\u2500");
|
|
@@ -15463,7 +16556,7 @@ async function executeBackbone(plan, deps, opts = {}) {
|
|
|
15463
16556
|
return halt(form.ref, "form", `could not read custom fields to resolve form refs: ${msg(e)}`);
|
|
15464
16557
|
}
|
|
15465
16558
|
}
|
|
15466
|
-
const
|
|
16559
|
+
const byId2 = new Map(cfRecords.map((r) => [r.id, r]));
|
|
15467
16560
|
const resolved = [];
|
|
15468
16561
|
let fieldHalt2;
|
|
15469
16562
|
for (const ff of form.fields) {
|
|
@@ -15476,7 +16569,7 @@ async function executeBackbone(plan, deps, opts = {}) {
|
|
|
15476
16569
|
fieldHalt2 = halt(form.ref, "form", `form "${form.name}" references ${ff.fieldRef} but that custom field was not built/resolved \u2014 cannot build the form`);
|
|
15477
16570
|
break;
|
|
15478
16571
|
}
|
|
15479
|
-
const rec =
|
|
16572
|
+
const rec = byId2.get(realId);
|
|
15480
16573
|
if (!rec) {
|
|
15481
16574
|
fieldHalt2 = halt(form.ref, "form", `custom field ${ff.fieldRef} (id ${realId}) not found in this account when building form "${form.name}"`);
|
|
15482
16575
|
break;
|
|
@@ -15731,16 +16824,16 @@ function msg(e) {
|
|
|
15731
16824
|
}
|
|
15732
16825
|
|
|
15733
16826
|
// src/tools/intake-to-build.ts
|
|
15734
|
-
var customFieldItemSchema =
|
|
15735
|
-
id:
|
|
15736
|
-
name:
|
|
15737
|
-
fieldKey:
|
|
15738
|
-
dataType:
|
|
15739
|
-
model:
|
|
15740
|
-
parentId:
|
|
15741
|
-
position:
|
|
15742
|
-
dateAdded:
|
|
15743
|
-
picklistOptions:
|
|
16827
|
+
var customFieldItemSchema = import_zod56.z.object({
|
|
16828
|
+
id: import_zod56.z.string(),
|
|
16829
|
+
name: import_zod56.z.string(),
|
|
16830
|
+
fieldKey: import_zod56.z.string(),
|
|
16831
|
+
dataType: import_zod56.z.string(),
|
|
16832
|
+
model: import_zod56.z.string().optional(),
|
|
16833
|
+
parentId: import_zod56.z.string().optional(),
|
|
16834
|
+
position: import_zod56.z.number().optional(),
|
|
16835
|
+
dateAdded: import_zod56.z.string().optional(),
|
|
16836
|
+
picklistOptions: import_zod56.z.array(import_zod56.z.string()).optional()
|
|
15744
16837
|
}).passthrough();
|
|
15745
16838
|
function parseCustomFields(raw) {
|
|
15746
16839
|
const obj = raw && typeof raw === "object" ? raw : {};
|
|
@@ -16039,19 +17132,19 @@ ${text2.slice(0, 300)}`);
|
|
|
16039
17132
|
// same-named funnel beyond it → duplicate). Dedup by id and stop when a page
|
|
16040
17133
|
// adds nothing new — robust whether or not the endpoint honors `offset`.
|
|
16041
17134
|
listFunnels: async () => {
|
|
16042
|
-
const
|
|
17135
|
+
const byId2 = /* @__PURE__ */ new Map();
|
|
16043
17136
|
const pageSize = 100;
|
|
16044
17137
|
const maxFunnels = 5e3;
|
|
16045
17138
|
for (let offset = 0; offset < maxFunnels; offset += pageSize) {
|
|
16046
17139
|
const page = pickFunnels(await funnelApi("GET", `/funnel/list?locationId=${locationId2}&limit=${pageSize}&offset=${offset}&getStats=true`));
|
|
16047
17140
|
let added = 0;
|
|
16048
|
-
for (const f of page) if (!
|
|
16049
|
-
|
|
17141
|
+
for (const f of page) if (!byId2.has(f.id)) {
|
|
17142
|
+
byId2.set(f.id, f);
|
|
16050
17143
|
added++;
|
|
16051
17144
|
}
|
|
16052
17145
|
if (page.length < pageSize || added === 0) break;
|
|
16053
17146
|
}
|
|
16054
|
-
return [...
|
|
17147
|
+
return [...byId2.values()];
|
|
16055
17148
|
},
|
|
16056
17149
|
createFunnel: async (name) => {
|
|
16057
17150
|
const result = await funnelApi("POST", `/funnel/create?locationId=${locationId2}`, {
|
|
@@ -16149,7 +17242,7 @@ function registerIntakeToBuildTools(server2, client, builderClient) {
|
|
|
16149
17242
|
"validate_brief",
|
|
16150
17243
|
"Validate an Intake-to-Build Brief object against the \xA74 schema. Returns {valid, errors}. Use to check a normalized brief before handing it to the plan-generation skill.",
|
|
16151
17244
|
{
|
|
16152
|
-
brief:
|
|
17245
|
+
brief: import_zod56.z.record(import_zod56.z.unknown()).describe("The Brief object to validate.")
|
|
16153
17246
|
},
|
|
16154
17247
|
async ({ brief }) => validateBrief(brief)
|
|
16155
17248
|
);
|
|
@@ -16158,7 +17251,7 @@ function registerIntakeToBuildTools(server2, client, builderClient) {
|
|
|
16158
17251
|
"validate_build_plan",
|
|
16159
17252
|
"Validate an Intake-to-Build Build Plan against the \xA75 schema AND check ref-integrity: every symbolic ref (pipeline.*, stage.*, tag.*, ...) must resolve to a defined object of the right type, and refs must be unique. Dead references are reported as errors here, before any build runs \u2014 the structural guard against 'an invalid ID silently kills downstream actions'. Returns {valid, errors, warnings, referencesScanned}.",
|
|
16160
17253
|
{
|
|
16161
|
-
plan:
|
|
17254
|
+
plan: import_zod56.z.record(import_zod56.z.unknown()).describe("The Build Plan object to validate.")
|
|
16162
17255
|
},
|
|
16163
17256
|
async ({ plan }) => validateBuildPlan(plan)
|
|
16164
17257
|
);
|
|
@@ -16166,12 +17259,12 @@ function registerIntakeToBuildTools(server2, client, builderClient) {
|
|
|
16166
17259
|
"apply_build_plan",
|
|
16167
17260
|
`Take an APPROVED Blueprint \xA75 build plan + the CURRENT confirmed sub-account and build it. mode:"dry_run" (default) writes NOTHING \u2014 it resolves refs, expands each workflow's logical actions to native GHL JSON, runs the NEVER-CLOBBER existing-asset scan, and returns a two-part report. Run it FIRST. mode:"execute" performs LIVE writes for the CRM backbone (pipelines+stages, custom fields, tags, custom values), calendars, AND forms: never clobbers (same-named objects are bound to their existing id, never modified), verifies each create by read-back before resolving its ref, halts on the first failure returning the partial idMap, and is idempotent (re-run = no-op). Staff-requiring calendars (round_robin etc.) auto-build only when you are the sole account user (auto-assigns you as the team member); with 0 or 2+ users they're surfaced as a manual step, not auto-staffed to a guess. Forms build with their standard + custom fields (custom fieldRefs resolve to the real fields created earlier in the run). Funnels: a GHL funnel (target:"ghl", default) builds structurally (funnel + named steps; page content/HTML is a manual step \u2014 plans carry outlines); a funnel with target:"external" is NOT built or deployed here \u2014 the user builds + hosts the site themselves (Cloudflare/Vercel) and wires its form back to this GHL sub-account (surfaced as a manual wiring step). Workflows build as DRAFT with all their logical actions expanded to native GHL JSON (incl. opportunity create/move steps, re-enabled v3.41.0) and chained; a contact_tag trigger is built automatically, other trigger types are surfaced as a manual step; the operator reviews + publishes. Always confirms the active location and validates the plan before any write.`,
|
|
16168
17261
|
{
|
|
16169
|
-
plan:
|
|
16170
|
-
mode:
|
|
16171
|
-
locationId:
|
|
16172
|
-
metHandoffs:
|
|
16173
|
-
publishWorkflows:
|
|
16174
|
-
onConflict:
|
|
17262
|
+
plan: import_zod56.z.record(import_zod56.z.unknown()).describe("The approved \xA75 Build Plan object."),
|
|
17263
|
+
mode: import_zod56.z.enum(["dry_run", "execute"]).optional().describe("dry_run (default) = resolve/expand/scan/report, no writes. execute = live writes (not yet enabled)."),
|
|
17264
|
+
locationId: import_zod56.z.string().optional().describe("Target sub-account. MUST match the active location; if it differs the tool refuses (confirm/switch first)."),
|
|
17265
|
+
metHandoffs: import_zod56.z.array(import_zod56.z.string()).optional().describe('Handoff refs the operator has already satisfied (e.g. ["handoff.a2p"]) \u2014 lifts their gate so dependent workflows are not held DRAFT.'),
|
|
17266
|
+
publishWorkflows: import_zod56.z.boolean().optional().describe("If true, ungated workflows would be published instead of left DRAFT. Default false (DRAFT)."),
|
|
17267
|
+
onConflict: import_zod56.z.enum(["skip", "abort"]).optional().describe("skip (default) = bind same-named existing objects and continue. abort = report conflicts as a halt.")
|
|
16175
17268
|
},
|
|
16176
17269
|
async ({ plan, mode, locationId: locationId2, metHandoffs, publishWorkflows, onConflict }) => {
|
|
16177
17270
|
try {
|
|
@@ -16374,9 +17467,9 @@ function registerIntakeToBuildTools(server2, client, builderClient) {
|
|
|
16374
17467
|
"install_intake_form",
|
|
16375
17468
|
"Install the canonical Intake-to-Build client-intake form into the CURRENT GHL location (whatever get_current_location returns). Account-agnostic, zero hardcoded IDs. Creates any missing intake custom fields (idempotent \u2014 reused on re-run), then builds the form with the proven GHL form-builder field shapes and verifies it. Returns {formId, fieldMap} \u2014 keep fieldMap; normalize_submission_to_brief uses it. Pass dryRun:true to preview what would be created without writing. Pass formId to update an existing intake form in place instead of creating a new one.",
|
|
16376
17469
|
{
|
|
16377
|
-
dryRun:
|
|
16378
|
-
formId:
|
|
16379
|
-
formName:
|
|
17470
|
+
dryRun: import_zod56.z.boolean().optional().describe("Preview the fields/form that would be created without writing anything."),
|
|
17471
|
+
formId: import_zod56.z.string().optional().describe("Update this existing form in place instead of creating a new one."),
|
|
17472
|
+
formName: import_zod56.z.string().optional().describe(`Form name. Defaults to "${INTAKE_FORM_NAME}".`)
|
|
16380
17473
|
},
|
|
16381
17474
|
async ({ dryRun, formId, formName }) => {
|
|
16382
17475
|
try {
|
|
@@ -16464,10 +17557,10 @@ function registerIntakeToBuildTools(server2, client, builderClient) {
|
|
|
16464
17557
|
"normalize_submission_to_brief",
|
|
16465
17558
|
'Read an intake form submission and normalize it into a \xA74 Brief (briefSource:"intake_form"). Pass the formId; by default the most recent submission is used (or pass submissionId). The intakeKey->customFieldId map is taken from fieldMap if provided (the install_intake_form output, most robust), otherwise reconstructed from the live form. Returns {brief, validation, submissionId} \u2014 validation flags any missing required fields (e.g. an incomplete submission).',
|
|
16466
17559
|
{
|
|
16467
|
-
formId:
|
|
16468
|
-
submissionId:
|
|
16469
|
-
fieldMap:
|
|
16470
|
-
preset:
|
|
17560
|
+
formId: import_zod56.z.string().describe("The intake form ID (from install_intake_form)."),
|
|
17561
|
+
submissionId: import_zod56.z.string().optional().describe("Specific submission to normalize. Defaults to the most recent."),
|
|
17562
|
+
fieldMap: import_zod56.z.record(import_zod56.z.string()).optional().describe("intakeKey -> customFieldId map from install_intake_form. Reconstructed from the form if omitted."),
|
|
17563
|
+
preset: import_zod56.z.string().optional().describe("Override the preset. Defaults to one derived from business_type.")
|
|
16471
17564
|
},
|
|
16472
17565
|
async ({ formId, submissionId, fieldMap, preset }) => {
|
|
16473
17566
|
try {
|
|
@@ -16496,7 +17589,7 @@ function registerIntakeToBuildTools(server2, client, builderClient) {
|
|
|
16496
17589
|
const formFull = await formApiRequest(bc, "GET", `/${formId}?locationId=${locationId2}`);
|
|
16497
17590
|
resolvedMap = buildFieldMapFromFormFields(extractFormFields(formFull));
|
|
16498
17591
|
}
|
|
16499
|
-
const presetSchema2 =
|
|
17592
|
+
const presetSchema2 = import_zod56.z.enum(["generic", "med_spa", "clinic_launch_a2p", "coach", "ecom", "agency"]).optional();
|
|
16500
17593
|
const presetParsed = presetSchema2.safeParse(preset);
|
|
16501
17594
|
const brief = normalizeSubmissionToBrief({
|
|
16502
17595
|
others,
|
|
@@ -16562,7 +17655,8 @@ var internalApiTools = [
|
|
|
16562
17655
|
[registerReputationTools, "reputation"],
|
|
16563
17656
|
[registerEmailCampaignTools, "email-campaigns"],
|
|
16564
17657
|
[registerEmailBuilderInternalTools, "email-builder"],
|
|
16565
|
-
[registerMembershipTools, "memberships"]
|
|
17658
|
+
[registerMembershipTools, "memberships"],
|
|
17659
|
+
[registerPageStudioTools, "page-studio"]
|
|
16566
17660
|
];
|
|
16567
17661
|
var VALIDATORS_MODULE = "validators";
|
|
16568
17662
|
var DIAGNOSTICS_MODULE = "diagnostics";
|