{"id":103511,"date":"2026-07-13T06:34:14","date_gmt":"2026-07-13T11:34:14","guid":{"rendered":"https:\/\/sirixmonitoring.com\/?page_id=103511"},"modified":"2026-10-15T10:30:07","modified_gmt":"2026-10-15T15:30:07","slug":"calculateur-de-couts-de-securite","status":"publish","type":"page","link":"https:\/\/sirixmonitoring.com\/fr-ca\/security-cost-calculator\/","title":{"rendered":"Calculateur de co\u00fbts de s\u00e9curit\u00e9"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"103511\" class=\"elementor elementor-103511\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e0fcd1e e-flex e-con-boxed e-con e-parent\" data-id=\"e0fcd1e\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-ef65ff7 elementor-widget-mobile__width-auto elementor-widget__width-initial elementor-widget elementor-widget-heading\" data-id=\"ef65ff7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h1 class=\"elementor-heading-title elementor-size-default\">Get your business security cost in minutes<\/h1>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3ee0c9e elementor-widget__width-initial elementor-widget-mobile__width-initial elementor-widget-tablet__width-initial elementor-widget elementor-widget-text-editor\" data-id=\"3ee0c9e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Answer a few quick questions about your property and get an instant, custom estimate for 24\/7 security monitoring. No sales calls, no obligation.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-836ba28 elementor-widget elementor-widget-html\" data-id=\"836ba28\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!-- Sirix Instant Estimate - Elementor HTML Widget Ready -->\r\n<style>\r\n.sirix-estimator-widget{display:block;width:100%;\r\n  --paper:#FFFFFF; --mist:#F5F5F7; --mist-2:#FAFAFB;\r\n  --hairline:rgba(0,0,0,0.09); --hairline-2:rgba(0,0,0,0.06);\r\n  --ink:#1A1A1A; --ink-2:#2E2E30; --gray:#6E6E73; --gray-faint:#A1A1A6;\r\n  --accent:#41C5A0; --accent-deep:#0E8F6F; --accent-soft:rgba(65,197,160,0.10);\r\n  --accent-line:rgba(65,197,160,0.32);\r\n  --ff:\"Montserrat\",-apple-system,BlinkMacSystemFont,system-ui,sans-serif;\r\n  --maxw:900px;\r\n  --r-sm:10px; --r-md:16px; --r-lg:22px; --r-pill:980px;\r\n  --shadow-rest:0 1px 2px rgba(0,0,0,0.04);\r\n  --shadow-card:0 12px 40px rgba(0,0,0,0.09);\r\n  --t-fast:.16s ease; --t-base:.3s cubic-bezier(.4,0,.2,1);\r\n}.sirix-estimator-widget *{margin:0;padding:0;box-sizing:border-box;}.sirix-estimator-widget{font-family:var(--ff);background:var(--mist);color:var(--ink);-webkit-font-smoothing:antialiased;line-height:1.5;}.sirix-estimator-widget button{font-family:inherit;cursor:pointer;}.sirix-estimator-widget svg{display:block;}\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 SHELL \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/.sirix-estimator-widget .estimator{max-width:var(--maxw);margin:0 auto;padding:10px;}.sirix-estimator-widget .est-card{background:var(--paper);border:1px solid var(--hairline);border-radius:var(--r-lg);box-shadow:var(--shadow-card);overflow:hidden;}\/* header + progress *\/.sirix-estimator-widget .est-top{padding:clamp(24px,4vw,34px) clamp(24px,4vw,44px) 0;}.sirix-estimator-widget .est-brand{display:flex;align-items:center;gap:11px;margin-bottom:22px;}.sirix-estimator-widget .est-brand svg{height:19px;color:var(--ink);}.sirix-estimator-widget .est-brand .est-brand-logo{height:19px;width:auto;max-width:72px;display:block;object-fit:contain;}.sirix-estimator-widget .est-brand b{font-size:13px;letter-spacing:0.04em;font-weight:600;color:var(--gray);}.sirix-estimator-widget .prog-meta{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:10px;}.sirix-estimator-widget .prog-step{font-size:12.5px;font-weight:700;letter-spacing:0.03em;color:var(--accent-deep);text-transform:uppercase;white-space:nowrap;}.sirix-estimator-widget .prog-pct{font-size:12.5px;font-weight:600;color:var(--gray-faint);white-space:nowrap;padding-left:12px;}.sirix-estimator-widget .prog-track{height:6px;background:var(--mist);border-radius:6px;overflow:hidden;}.sirix-estimator-widget .prog-fill{height:100%;background:linear-gradient(90deg,var(--accent),var(--accent-deep));border-radius:6px;width:20%;transition:width .45s cubic-bezier(.4,0,.2,1);}\/* body *\/.sirix-estimator-widget .est-body{padding:clamp(24px,4vw,40px) clamp(24px,4vw,44px);}.sirix-estimator-widget .step{display:none;animation:fade .4s ease;}.sirix-estimator-widget .step.active{display:block;}@keyframes fade{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:none;}}.sirix-estimator-widget .step-q{font-size:clamp(23px,3.4vw,32px);font-weight:700;letter-spacing:-0.02em;line-height:1.1;margin-bottom:8px;}.sirix-estimator-widget .step-sub{font-size:15px;color:var(--gray);margin-bottom:26px;line-height:1.55;max-width:60ch;}\/* option grid (cards) *\/.sirix-estimator-widget .opt-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px;}.sirix-estimator-widget .opt{position:relative;display:flex;align-items:center;gap:13px;text-align:left;background:var(--paper);border:1.5px solid var(--hairline);border-radius:var(--r-md);padding:17px 18px;transition:all var(--t-fast);width:100%;}.sirix-estimator-widget .opt:hover{border-color:var(--accent-line);background:var(--mist-2);}.sirix-estimator-widget .opt.sel{border-color:var(--accent);background:var(--accent-soft);}\/* per-card accent colors (step 1) *\/.sirix-estimator-widget .opt[data-tone]{--tone:var(--accent);--tone-soft:var(--accent-soft);}.sirix-estimator-widget .opt[data-tone=\"blue\"]{--tone:#2176AE;--tone-soft:rgba(33,118,174,0.10);}.sirix-estimator-widget .opt[data-tone=\"amber\"]{--tone:#D98A26;--tone-soft:rgba(217,138,38,0.12);}.sirix-estimator-widget .opt[data-tone=\"violet\"]{--tone:#7C5CBF;--tone-soft:rgba(124,92,191,0.10);}.sirix-estimator-widget .opt[data-tone=\"orange\"]{--tone:#E5683C;--tone-soft:rgba(229,104,60,0.10);}.sirix-estimator-widget .opt[data-tone=\"teal\"]{--tone:#2FA98A;--tone-soft:rgba(47,169,138,0.10);}.sirix-estimator-widget .opt[data-tone=\"indigo\"]{--tone:#4B5BC4;--tone-soft:rgba(75,91,196,0.10);}.sirix-estimator-widget .opt[data-tone=\"rose\"]{--tone:#C2477E;--tone-soft:rgba(194,71,126,0.10);}.sirix-estimator-widget .opt[data-tone=\"slate\"]{--tone:#556070;--tone-soft:rgba(85,96,112,0.10);}.sirix-estimator-widget .opt[data-tone] .ic{background:var(--tone-soft);}.sirix-estimator-widget .opt[data-tone] .ic svg{stroke:var(--tone);}.sirix-estimator-widget .opt[data-tone]:hover{border-color:var(--tone);background:var(--tone-soft);}.sirix-estimator-widget .opt[data-tone].sel{border-color:var(--tone);background:var(--tone-soft);}.sirix-estimator-widget .opt[data-tone].sel .ic{background:var(--tone);}.sirix-estimator-widget .opt[data-tone].sel .ic svg{stroke:#fff;}.sirix-estimator-widget .opt[data-tone].sel .chk{background:var(--tone);border-color:var(--tone);}.sirix-estimator-widget .opt .ic{flex:none;width:42px;height:42px;border-radius:11px;background:var(--mist);display:flex;align-items:center;justify-content:center;transition:all var(--t-fast);}.sirix-estimator-widget .opt.sel .ic{background:var(--accent);}.sirix-estimator-widget .opt .ic svg{width:22px;height:22px;stroke:var(--accent-deep);stroke-width:1.7;fill:none;stroke-linecap:round;stroke-linejoin:round;transition:stroke var(--t-fast);}.sirix-estimator-widget .opt.sel .ic svg{stroke:#fff;}.sirix-estimator-widget .opt .lbl{min-width:0;}.sirix-estimator-widget .opt .lbl b{display:block;font-size:15px;font-weight:600;color:var(--ink);line-height:1.25;}.sirix-estimator-widget .opt .lbl span{display:block;font-size:12.5px;color:var(--gray);margin-top:2px;line-height:1.35;}.sirix-estimator-widget .opt .chk{position:absolute;top:12px;right:12px;width:20px;height:20px;border-radius:50%;border:1.5px solid var(--hairline);display:flex;align-items:center;justify-content:center;opacity:0;transition:all var(--t-fast);}.sirix-estimator-widget .opt.sel .chk{opacity:1;background:var(--accent);border-color:var(--accent);}.sirix-estimator-widget .opt .chk svg{width:12px;height:12px;stroke:#fff;stroke-width:2.6;fill:none;stroke-linecap:round;stroke-linejoin:round;}.sirix-estimator-widget .multi-hint{font-size:13px;color:var(--gray-faint);margin-bottom:18px;font-weight:500;}\/* service checkbox (step 2, no icons) *\/.sirix-estimator-widget .opt .chkbox{flex:none;width:20px;height:20px;border-radius:7px;border:1.8px solid var(--hairline);display:flex;align-items:center;justify-content:center;transition:all var(--t-fast);}.sirix-estimator-widget .opt .chkbox svg{width:12.5px;height:12.5px;stroke:#fff;stroke-width:3.2;fill:none;stroke-linecap:round;stroke-linejoin:round;opacity:0;transform:scale(.6);transition:all var(--t-fast);}.sirix-estimator-widget .opt.sel .chkbox{background:var(--accent);border-color:var(--accent);}.sirix-estimator-widget .opt.sel .chkbox svg{opacity:1;transform:scale(1);}\/* per-site cards (setup step) *\/.sirix-estimator-widget .sites-wrap{display:flex;flex-direction:column;gap:14px;margin-bottom:30px;}.sirix-estimator-widget .site-card{display:grid;grid-template-columns:minmax(0,0.85fr) minmax(0,1.15fr);gap:20px;align-items:center;border:1.5px solid var(--hairline);border-radius:var(--r-md);padding:18px 20px;background:var(--mist-2);}@media(max-width:560px){.sirix-estimator-widget .site-card{grid-template-columns:1fr;gap:16px;}}\/* tier options (intercom \/ gate) *\/.sirix-estimator-widget .tier-seg{display:flex;flex-direction:column;gap:10px;}.sirix-estimator-widget .tier-opt{display:flex;align-items:center;justify-content:space-between;gap:16px;text-align:left;background:var(--paper);border:1.5px solid var(--hairline);border-radius:var(--r-md);padding:16px 20px;transition:all var(--t-fast);}.sirix-estimator-widget .tier-opt:hover{border-color:var(--accent-line);}.sirix-estimator-widget .tier-opt.sel{border-color:var(--accent);background:var(--accent-soft);}.sirix-estimator-widget .tier-vol{font-size:15px;font-weight:600;color:var(--ink);}.sirix-estimator-widget .tier-price{font-size:19px;font-weight:800;color:var(--accent-deep);white-space:nowrap;font-variant-numeric:tabular-nums;}.sirix-estimator-widget .tier-price small{font-size:12px;font-weight:600;color:var(--gray);}.sirix-estimator-widget .site-card .inp label{font-size:13px;font-weight:600;color:var(--ink-2);margin-bottom:7px;}.sirix-estimator-widget .site-card .inp input{font-family:inherit;font-size:15px;color:var(--ink);background:var(--paper);border:1.5px solid var(--hairline);border-radius:var(--r-sm);padding:12px 14px;width:100%;transition:border-color var(--t-fast);}.sirix-estimator-widget .site-card .inp input:focus{outline:none;border-color:var(--accent);}\/* specifics controls *\/.sirix-estimator-widget .field{margin-bottom:30px;}.sirix-estimator-widget .field:last-child{margin-bottom:0;}.sirix-estimator-widget .field-label{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:14px;}.sirix-estimator-widget .field-label b{font-size:16px;font-weight:600;color:var(--ink);}.sirix-estimator-widget .field-label .val{font-size:22px;font-weight:800;color:var(--accent-deep);font-variant-numeric:tabular-nums;letter-spacing:-0.01em;}.sirix-estimator-widget .field-label .val small{font-size:13px;font-weight:600;color:var(--gray);}.sirix-estimator-widget input[type=range]{-webkit-appearance:none;appearance:none;width:100%;height:6px;border-radius:6px;background:var(--mist);outline:none;}.sirix-estimator-widget input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:26px;height:26px;border-radius:50%;background:var(--accent);border:3px solid #fff;box-shadow:0 2px 8px rgba(14,143,111,0.35);cursor:pointer;transition:transform var(--t-fast);}.sirix-estimator-widget input[type=range]::-webkit-slider-thumb:hover{transform:scale(1.12);}.sirix-estimator-widget input[type=range]::-moz-range-thumb{width:26px;height:26px;border-radius:50%;background:var(--accent);border:3px solid #fff;box-shadow:0 2px 8px rgba(14,143,111,0.35);cursor:pointer;}.sirix-estimator-widget .range-ends{display:flex;justify-content:space-between;font-size:12px;color:var(--gray-faint);margin-top:8px;}.sirix-estimator-widget .stepper{display:inline-flex;align-items:center;gap:0;border:1.5px solid var(--hairline);border-radius:var(--r-pill);overflow:hidden;}.sirix-estimator-widget .stepper button{width:46px;height:46px;background:var(--paper);border:none;font-size:22px;font-weight:600;color:var(--accent-deep);display:flex;align-items:center;justify-content:center;transition:background var(--t-fast);}.sirix-estimator-widget .stepper button:hover{background:var(--accent-soft);}.sirix-estimator-widget .stepper button:disabled{color:var(--gray-faint);cursor:not-allowed;}.sirix-estimator-widget .stepper .num{min-width:64px;text-align:center;font-size:19px;font-weight:800;font-variant-numeric:tabular-nums;}.sirix-estimator-widget .seg{display:flex;gap:10px;flex-wrap:wrap;}.sirix-estimator-widget .seg button{flex:1;min-width:130px;text-align:left;background:var(--paper);border:1.5px solid var(--hairline);border-radius:var(--r-md);padding:15px 17px;transition:all var(--t-fast);}.sirix-estimator-widget .seg button:hover{border-color:var(--accent-line);}.sirix-estimator-widget .seg button.sel{border-color:var(--accent);background:var(--accent-soft);}.sirix-estimator-widget .seg button b{display:block;font-size:14.5px;font-weight:600;color:var(--ink);}.sirix-estimator-widget .seg button span{display:block;font-size:12.5px;color:var(--gray);margin-top:3px;}.sirix-estimator-widget .selectwrap{position:relative;}.sirix-estimator-widget .selectwrap select{width:100%;font-family:inherit;font-size:15px;font-weight:500;color:var(--ink);background:var(--paper);border:1.5px solid var(--hairline);border-radius:var(--r-md);padding:15px 44px 15px 17px;appearance:none;cursor:pointer;transition:border-color var(--t-fast);}.sirix-estimator-widget .selectwrap select:focus{outline:none;border-color:var(--accent);}.sirix-estimator-widget .selectwrap .caret{position:absolute;right:16px;top:50%;transform:translateY(-50%);pointer-events:none;color:var(--gray-faint);}\/* estimate *\/.sirix-estimator-widget .est-hero{background:linear-gradient(180deg,rgba(65,197,160,0.14),rgba(65,197,160,0.06));border:1px solid var(--accent-line);border-radius:var(--r-lg);padding:clamp(28px,4vw,44px);}.sirix-estimator-widget .est-context{font-size:clamp(17px,2.2vw,21px);font-weight:500;color:var(--ink-2);line-height:1.4;margin-bottom:18px;}.sirix-estimator-widget .est-context b{font-weight:700;color:var(--ink);}.sirix-estimator-widget .est-bigrange{font-size:clamp(40px,7.5vw,64px);font-weight:800;letter-spacing:-0.03em;line-height:0.98;color:var(--accent-deep);}.sirix-estimator-widget .est-savings{font-size:clamp(14px,1.9vw,16px);font-style:italic;color:var(--accent-deep);line-height:1.5;margin-top:20px;}.sirix-estimator-widget .est-savings b{font-weight:700;}.sirix-estimator-widget .incl{margin-top:clamp(28px,4vw,40px);}.sirix-estimator-widget .incl h3{font-size:clamp(18px,2.4vw,22px);font-weight:700;letter-spacing:-0.01em;margin-bottom:20px;color:#1a1a1a;}.sirix-estimator-widget .incl ul{list-style:none;display:flex;flex-direction:column;gap:16px;}.sirix-estimator-widget .incl li{display:flex;align-items:flex-start;gap:14px;font-size:15.5px;color:var(--ink-2);line-height:1.45;}.sirix-estimator-widget .incl li .tick{flex:none;width:26px;height:26px;border-radius:50%;background:var(--accent);display:flex;align-items:center;justify-content:center;margin-top:1px;}.sirix-estimator-widget .incl li .tick svg{width:15px;height:15px;stroke:#fff;stroke-width:2.6;fill:none;stroke-linecap:round;stroke-linejoin:round;}.sirix-estimator-widget .est-disc{font-size:12.5px;color:var(--gray-faint);line-height:1.6;margin-top:26px;max-width:100% !important;}.sirix-estimator-widget .est-price{font-size:clamp(46px,9vw,76px);font-weight:800;letter-spacing:-0.03em;line-height:0.95;color:var(--ink);}.sirix-estimator-widget .est-price .cur{font-size:0.45em;font-weight:700;color:var(--gray);vertical-align:top;}.sirix-estimator-widget .est-price .per{font-size:0.26em;font-weight:600;color:var(--gray);letter-spacing:0;}.sirix-estimator-widget .est-range{font-size:15px;color:var(--gray);margin-top:14px;}.sirix-estimator-widget .est-setup{font-size:14px;color:var(--gray-faint);margin-top:6px;}.sirix-estimator-widget .est-break{margin-top:28px;text-align:left;background:var(--mist-2);border:1px solid var(--hairline);border-radius:var(--r-md);overflow:hidden;}.sirix-estimator-widget .brk-row{display:flex;justify-content:space-between;align-items:center;padding:13px 20px;border-bottom:1px solid var(--hairline-2);font-size:14px;}.sirix-estimator-widget .brk-row:last-child{border-bottom:none;}.sirix-estimator-widget .brk-row .k{color:var(--gray);}.sirix-estimator-widget .brk-row .k b{color:var(--ink);font-weight:600;}.sirix-estimator-widget .brk-row .v{font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums;}.sirix-estimator-widget .est-disc{font-size:12.5px;color:var(--gray-faint);line-height:1.6;margin-top:18px;max-width:64ch;}\/* contact *\/.sirix-estimator-widget .form-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;}.sirix-estimator-widget .form-grid .full{grid-column:1\/-1;}.sirix-estimator-widget .inp{display:flex;flex-direction:column;gap:7px;}.sirix-estimator-widget .inp label{font-size:13px;font-weight:600;color:var(--ink-2);}.sirix-estimator-widget .inp label .req{color:var(--accent-deep);}.sirix-estimator-widget .inp input,.sirix-estimator-widget .inp select{font-family:inherit;font-size:15px;color:var(--ink);background:var(--paper);border:1.5px solid var(--hairline);border-radius:var(--r-sm);padding:13px 15px;transition:border-color var(--t-fast);width:100%;}.sirix-estimator-widget .inp input:focus,.sirix-estimator-widget .inp select:focus{outline:none;border-color:var(--accent);}.sirix-estimator-widget .inp input::placeholder{color:var(--gray-faint);}.sirix-estimator-widget .summary-strip{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:24px;}.sirix-estimator-widget .summary-strip .pill{font-size:12.5px;font-weight:500;color:var(--ink-2);background:var(--mist);border:1px solid var(--hairline);padding:6px 13px;border-radius:var(--r-pill);}.sirix-estimator-widget .summary-strip .pill b{font-weight:700;color:var(--accent-deep);}\/* success *\/.sirix-estimator-widget .success{text-align:center;padding:20px 0;}.sirix-estimator-widget .success .tick{width:72px;height:72px;border-radius:50%;background:var(--accent-soft);display:flex;align-items:center;justify-content:center;margin:0 auto 22px;}.sirix-estimator-widget .success .tick svg{width:38px;height:38px;stroke:var(--accent-deep);stroke-width:2.2;fill:none;stroke-linecap:round;stroke-linejoin:round;}.sirix-estimator-widget .success h2{font-size:clamp(24px,4vw,32px);font-weight:800;letter-spacing:-0.02em;margin-bottom:12px;}.sirix-estimator-widget .success p{font-size:15.5px;color:var(--gray);max-width:52ch;margin:0 auto;line-height:1.6;}.sirix-estimator-widget .est-foot.contact-mode{justify-content:flex-start;}\/* footer nav *\/.sirix-estimator-widget .est-foot{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:clamp(20px,3vw,26px) clamp(24px,4vw,44px);border-top:1px solid var(--hairline);background:var(--mist-2);}.sirix-estimator-widget .btn{display:inline-flex;align-items:center;gap:9px;font-size:15px;font-weight:600;border-radius:var(--r-pill);padding:13px 28px;border:1.5px solid transparent;transition:all var(--t-fast);}.sirix-estimator-widget .btn-primary{background:var(--accent);color:#fff;box-shadow:0 6px 18px rgba(65,197,160,0.30);}.sirix-estimator-widget .btn-primary:hover{background:var(--accent-deep);}.sirix-estimator-widget .btn-primary:disabled{background:var(--mist);color:var(--gray-faint);box-shadow:none;cursor:not-allowed;}.sirix-estimator-widget .btn-ghost{background:transparent;color:var(--gray);border-color:transparent;padding-left:8px;}.sirix-estimator-widget .btn-ghost:hover{color:var(--ink);}.sirix-estimator-widget .btn-ghost svg,.sirix-estimator-widget .btn-primary svg{width:17px;height:17px;stroke:currentColor;stroke-width:2.2;fill:none;stroke-linecap:round;stroke-linejoin:round;}.sirix-estimator-widget .btn.hidden{visibility:hidden;}@media(max-width:560px){.sirix-estimator-widget .form-grid{grid-template-columns:1fr;}.sirix-estimator-widget .est-foot{padding:18px 22px;}.sirix-estimator-widget .btn{padding:12px 20px;font-size:14px;}\r\n}\r\n\r\n\r\n\r\n\/* ===== Global font lock: Montserrat everywhere in estimator ===== *\/\r\n.sirix-estimator-widget,\r\n.sirix-estimator-widget *{\r\n  font-family:\"Montserrat\",-apple-system,BlinkMacSystemFont,system-ui,sans-serif!important;\r\n}\r\n\r\n\r\n\/* ===== Elementor visual fix: keep Sirix original colors + prevent text clipping ===== *\/\r\n.sirix-estimator-widget{\r\n  background:#F5F5F7!important;\r\n  color:#1A1A1A!important;\r\n  overflow:visible!important;\r\n}\r\n.sirix-estimator-widget .estimator{\r\n  max-width:100%;\r\n  width:100%!important;\r\n}\r\n.sirix-estimator-widget .est-card{\r\n  background:#FFFFFF!important;\r\n  border-color:rgba(0,0,0,0.09)!important;\r\n  overflow:hidden!important;\r\n}\r\n.sirix-estimator-widget .opt-grid{\r\n  display:grid!important;\r\n  grid-template-columns:repeat(3,minmax(0,1fr))!important;\r\n  gap:14px!important;\r\n}\r\n.sirix-estimator-widget .opt{\r\n  min-width:0!important;\r\n  align-items:flex-start!important;\r\n  gap:15px!important;\r\n  padding:10px !important;\r\n  overflow:visible!important;\r\n  white-space:normal!important;\r\n  text-align:left!important;\r\n  background:#FFFFFF!important;\r\n  color:#1A1A1A!important;\r\n  border:1.5px solid rgba(0,0,0,0.09)!important;\r\n  border-radius:16px!important;\r\n  box-shadow:none!important;\r\n}\r\n.sirix-estimator-widget .opt:hover{\r\n  border-color:rgba(65,197,160,0.32)!important;\r\n  background:#FAFAFB!important;\r\n}\r\n.sirix-estimator-widget .opt.sel{\r\n  border-color:#41C5A0!important;\r\n  background:rgba(65,197,160,0.10)!important;\r\n}\r\n.sirix-estimator-widget .opt .lbl{\r\n  flex:1 1 auto!important;\r\n  min-width:0!important;\r\n  max-width:none!important;\r\n  overflow:visible!important;\r\n  white-space:normal!important;\r\n}\r\n.sirix-estimator-widget .opt .lbl,\r\n.sirix-estimator-widget .opt .lbl b,\r\n.sirix-estimator-widget .opt .lbl span{\r\n  display:block!important;\r\n  white-space:normal!important;\r\n  overflow:visible!important;\r\n  text-overflow:clip!important;\r\n  word-break:normal!important;\r\n  overflow-wrap:break-word!important;\r\n  max-width:100%!important;\r\n}\r\n.sirix-estimator-widget .opt .lbl b{\r\n  font-size:15px!important;\r\n  font-weight:600!important;\r\n  line-height:1.25!important;\r\n  color:#1A1A1A!important;\r\n  margin:0 0 2px!important;\r\n}\r\n.sirix-estimator-widget .opt .lbl span{\r\n  font-size:12.5px!important;\r\n  line-height:1.35!important;\r\n  color:#6E6E73!important;\r\n  margin-top:2px!important;\r\n}\r\n.sirix-estimator-widget .opt .chkbox{\r\n  flex:0 0 20px!important;\r\n  width:20px!important;\r\n  height:20px!important;\r\n  margin-top:3px!important;\r\n  border-color:rgba(0,0,0,0.09)!important;\r\n  background:#FFFFFF!important;\r\n}\r\n.sirix-estimator-widget .opt.sel .chkbox{\r\n  background:#41C5A0!important;\r\n  border-color:#41C5A0!important;\r\n}\r\n.sirix-estimator-widget .opt.sel .chkbox svg{\r\n  stroke:#FFFFFF!important;\r\n}\r\n.sirix-estimator-widget .btn-primary{\r\n  background:#41C5A0!important;\r\n  color:#FFFFFF!important;\r\n  box-shadow:0 6px 18px rgba(65,197,160,0.30)!important;\r\n}\r\n.sirix-estimator-widget .btn-primary:hover{\r\n  background:#0E8F6F!important;\r\n}\r\n.sirix-estimator-widget .prog-fill{\r\n  background:linear-gradient(90deg,#41C5A0,#0E8F6F)!important;\r\n}\r\n.sirix-estimator-widget .prog-step,\r\n.sirix-estimator-widget .field-label .val,\r\n.sirix-estimator-widget .tier-price,\r\n.sirix-estimator-widget .est-bigrange,\r\n.sirix-estimator-widget .summary-strip .pill b{\r\n  color:#0E8F6F!important;\r\n}\r\n@media(max-width:920px){\r\n  .sirix-estimator-widget .opt-grid{grid-template-columns:repeat(2,minmax(0,1fr))!important;}\r\n}\r\n@media(max-width:640px){\r\n  .sirix-estimator-widget .opt-grid{grid-template-columns:1fr!important;}\r\n  .sirix-estimator-widget .opt{min-height:auto!important;padding:17px 18px!important;}\r\n}\r\n\r\n\r\n\/* ===== Compact setup bar: sites + schedule + location in one section ===== *\/\r\n.sirix-estimator-widget .setup-compact-card{\r\n  display:grid!important;\r\n  grid-template-columns:190px minmax(330px,0.95fr) minmax(260px,1fr)!important;\r\n  gap:14px!important;\r\n  align-items:end!important;\r\n  background:#FAFAFB!important;\r\n  border:1.5px solid rgba(0,0,0,0.09)!important;\r\n  border-radius:16px!important;\r\n  padding:14px 16px!important;\r\n  margin-bottom:18px!important;\r\n}\r\n.sirix-estimator-widget .setup-compact-card .setup-item{\r\n  min-width:0!important;\r\n  margin:0!important;\r\n}\r\n.sirix-estimator-widget .setup-compact-card .field-label{\r\n  margin:0 0 8px!important;\r\n}\r\n.sirix-estimator-widget .setup-compact-card .field-label b{\r\n  font-size:14px!important;\r\n  font-weight:700!important;\r\n  line-height:1.2!important;\r\n  color:#1A1A1A!important;\r\n}\r\n.sirix-estimator-widget .setup-compact-card .stepper{\r\n  height:46px!important;\r\n  background:#FFFFFF!important;\r\n  border-radius:999px!important;\r\n}\r\n.sirix-estimator-widget .setup-compact-card .stepper button{\r\n  width:44px!important;\r\n  height:44px!important;\r\n  font-size:20px!important;\r\n}\r\n.sirix-estimator-widget .setup-compact-card .stepper .num{\r\n  min-width:58px!important;\r\n  font-size:18px!important;\r\n}\r\n.sirix-estimator-widget .setup-compact-card .seg{\r\n  display:grid!important;\r\n  grid-template-columns:repeat(2,minmax(0,1fr))!important;\r\n  gap:8px!important;\r\n}\r\n.sirix-estimator-widget .setup-compact-card .seg button{\r\n  min-width:0!important;\r\n  min-height:46px!important;\r\n  padding:9px 12px!important;\r\n  background:#FFFFFF!important;\r\n  border-radius:14px!important;\r\n}\r\n.sirix-estimator-widget .setup-compact-card .seg button b{\r\n  font-size:13.5px!important;\r\n  line-height:1.15!important;\r\n}\r\n.sirix-estimator-widget .setup-compact-card .seg button span{\r\n  font-size:11.5px!important;\r\n  line-height:1.2!important;\r\n  margin-top:3px!important;\r\n}\r\n.sirix-estimator-widget .setup-compact-card #locInput{\r\n  height:46px!important;\r\n  padding:10px 14px!important;\r\n  background:#FFFFFF!important;\r\n  border-radius:14px!important;\r\n  font-size:14px!important;\r\n}\r\n.sirix-estimator-widget .setup-compact-card .selectwrap{\r\n  height:46px!important;\r\n}\r\n@media(max-width:980px){\r\n  .sirix-estimator-widget .setup-compact-card{\r\n    grid-template-columns:180px 1fr!important;\r\n  }\r\n  .sirix-estimator-widget .setup-compact-card .setup-location{\r\n    grid-column:1\/-1!important;\r\n  }\r\n}\r\n@media(max-width:640px){\r\n  .sirix-estimator-widget .setup-compact-card{\r\n    grid-template-columns:1fr!important;\r\n    gap:12px!important;\r\n    padding:14px!important;\r\n  }\r\n  .sirix-estimator-widget .setup-compact-card .setup-location{\r\n    grid-column:auto!important;\r\n  }\r\n}\r\n@media(max-width:460px){\r\n  .sirix-estimator-widget .setup-compact-card .seg{\r\n    grid-template-columns:1fr!important;\r\n  }\r\n}\r\n\r\n\r\n\/* ===== Final success message after Freshworks submit ===== *\/\r\n.sirix-estimator-widget .success{\r\n  text-align:center!important;\r\n  padding:clamp(42px,7vw,72px) 20px clamp(36px,6vw,60px)!important;\r\n}\r\n.sirix-estimator-widget .success .tick{\r\n  width:90px!important;\r\n  height:90px!important;\r\n  border-radius:50%!important;\r\n  background:rgba(65,197,160,0.12)!important;\r\n  display:flex!important;\r\n  align-items:center!important;\r\n  justify-content:center!important;\r\n  margin:0 auto 34px!important;\r\n}\r\n.sirix-estimator-widget .success .tick svg{\r\n  width:42px!important;\r\n  height:42px!important;\r\n  stroke:#0E8F6F!important;\r\n  stroke-width:2.4!important;\r\n  fill:none!important;\r\n  stroke-linecap:round!important;\r\n  stroke-linejoin:round!important;\r\n}\r\n.sirix-estimator-widget .success h2{\r\n  font-size:clamp(32px,5.2vw,42px)!important;\r\n  line-height:1.08!important;\r\n  font-weight:800!important;\r\n  letter-spacing:-0.035em!important;\r\n  color:#0B0B0D!important;\r\n  margin:0 0 24px!important;\r\n}\r\n.sirix-estimator-widget .success p{\r\n  font-size:clamp(18px,2.3vw,21px)!important;\r\n  line-height:1.45!important;\r\n  color:#69707D!important;\r\n  max-width:760px!important;\r\n  margin:0 auto!important;\r\n}\r\n\r\n\r\n\r\n\/* ===== Freshworks iframe height fix ===== *\/\r\n.sirix-estimator-widget .freshworks-form-wrap{\r\n  min-height:0!important;\r\n  overflow:hidden!important;\r\n}\r\n.sirix-estimator-widget .freshworks-form-wrap iframe{\r\n  min-height:0!important;\r\n  margin:0!important;\r\n}\r\n\/* locked service chip (deep link from a service page) *\/\r\n.sirix-estimator-widget .est-brand .svc-lock{\r\n  display:inline-flex;\r\n  align-items:center;\r\n  gap:7px;\r\n  margin-left:4px;\r\n  font-size:15px;\r\n  font-weight:700;\r\n  letter-spacing:-0.005em;\r\n  color:#0E8F6F;\r\n  line-height:1.2;\r\n  white-space:nowrap;\r\n}\r\n.sirix-estimator-widget .est-brand .svc-lock svg{\r\n  width:19px;\r\n  height:19px;\r\n  flex:none;\r\n  color:#0E8F6F;\r\n}\r\n.sirix-estimator-widget .est-brand .svc-lock[hidden]{display:none;}\r\n@media(max-width:480px){\r\n  .sirix-estimator-widget .est-brand{flex-wrap:wrap;gap:8px;}\r\n  .sirix-estimator-widget .est-brand .svc-lock{font-size:14px;margin-left:0;}\r\n}\r\n\/* VIP safe passage link (?service=vip): 3-step range calculator *\/\r\n.sirix-estimator-widget.vip-mode .prog-step{\r\n  text-transform:none;\r\n  letter-spacing:0;\r\n}\r\n.sirix-estimator-widget .vip-fine{\r\n  margin:-14px 0 0;\r\n  font-size:12.5px;\r\n  line-height:1.55;\r\n  color:var(--gray-faint);\r\n}\r\n.sirix-estimator-widget .est-label{\r\n  margin:0 0 6px;\r\n  font-size:13px;\r\n  font-weight:700;\r\n  color:var(--accent-deep);\r\n}\r\n.sirix-estimator-widget .est-savings.est-plain{\r\n  font-style:normal;\r\n}\r\n.sirix-estimator-widget .unsure-help.vip-disc{\r\n  margin-top:26px;\r\n}\r\n\/* VIP safe passage: per-site escort inputs *\/\r\n.sirix-estimator-widget .site-card .vip-row{\r\n  grid-column:1\/-1;\r\n  display:grid;\r\n  grid-template-columns:auto minmax(0,1fr);\r\n  gap:22px;\r\n  align-items:center;\r\n}\r\n.sirix-estimator-widget .site-card:not(.site-card-vip) .vip-row{\r\n  border-top:1px dashed var(--hairline);\r\n  padding-top:16px;\r\n  margin-top:2px;\r\n}\r\n.sirix-estimator-widget .site-card.site-card-vip{\r\n  grid-template-columns:minmax(0,0.85fr) minmax(0,1.15fr);\r\n}\r\n.sirix-estimator-widget .site-card .vip-row .field-label{\r\n  margin-bottom:10px;\r\n}\r\n.sirix-estimator-widget .site-card .vip-row .field-label b{\r\n  font-size:13.5px;\r\n  font-weight:700;\r\n}\r\n.sirix-estimator-widget .site-card .vip-row .stepper{\r\n  height:44px;\r\n  background:#FFFFFF;\r\n}\r\n.sirix-estimator-widget .site-card .vip-row .stepper button{\r\n  width:42px;\r\n  height:42px;\r\n  font-size:20px;\r\n}\r\n.sirix-estimator-widget .site-card .vip-row .stepper .num{\r\n  min-width:52px;\r\n  font-size:17px;\r\n}\r\n.sirix-estimator-widget .site-card .vip-note{\r\n  grid-column:1\/-1;\r\n  margin:0;\r\n  font-size:12.5px;\r\n  font-weight:700;\r\n  color:var(--accent-deep);\r\n  font-variant-numeric:tabular-nums;\r\n}\r\n@media(max-width:560px){\r\n  .sirix-estimator-widget .site-card .vip-row,\r\n  .sirix-estimator-widget .site-card.site-card-vip{\r\n    grid-template-columns:1fr;\r\n    gap:16px;\r\n  }\r\n}\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 \"Not sure, help me decide\": optional free-text box \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n.sirix-estimator-widget .unsure-note{\r\n  margin-top:2px;\r\n}\r\n.sirix-estimator-widget .unsure-note label{\r\n  display:block;\r\n  font-size:14.5px;\r\n  font-weight:600;\r\n  color:var(--ink-2);\r\n  margin-bottom:9px;\r\n}\r\n.sirix-estimator-widget .unsure-note label .opt-tag{\r\n  font-weight:500;\r\n  color:var(--gray-faint);\r\n}\r\n.sirix-estimator-widget .unsure-note textarea{\r\n  display:block;\r\n  width:100%;\r\n  min-height:134px;\r\n  resize:vertical;\r\n  font-family:inherit;\r\n  font-size:15px;\r\n  line-height:1.55;\r\n  color:var(--ink);\r\n  background:var(--paper);\r\n  border:1.5px solid var(--hairline);\r\n  border-radius:var(--r-md);\r\n  padding:14px 16px;\r\n  transition:border-color var(--t-fast);\r\n}\r\n.sirix-estimator-widget .unsure-note textarea:focus{\r\n  outline:none;\r\n  border-color:var(--accent);\r\n}\r\n.sirix-estimator-widget .unsure-note textarea::placeholder{\r\n  color:var(--gray-faint);\r\n}\r\n.sirix-estimator-widget .unsure-help{\r\n  display:flex;\r\n  align-items:flex-start;\r\n  gap:10px;\r\n  margin:12px 0 0;\r\n  padding:12px 15px;\r\n  background:var(--mist-2);\r\n  border:1px solid var(--hairline);\r\n  border-radius:var(--r-md);\r\n  font-size:13px;\r\n  line-height:1.55;\r\n  color:var(--gray);\r\n}\r\n.sirix-estimator-widget .unsure-help svg{\r\n  flex:none;\r\n  width:17px;\r\n  height:17px;\r\n  margin-top:1px;\r\n  stroke:var(--accent-deep);\r\n  stroke-width:1.8;\r\n  fill:none;\r\n  stroke-linecap:round;\r\n  stroke-linejoin:round;\r\n}\r\n<\/style>\r\n\r\n<div class=\"sirix-estimator-widget\">\r\n<div class=\"estimator\">\r\n  <div class=\"est-card\">\r\n    <div class=\"est-top\">\r\n      <div class=\"est-brand\">\r\n        <img class=\"est-brand-logo\" src=\"https:\/\/sirixmonitoring.com\/wp-content\/uploads\/2026\/01\/Sirix-logo-for-home-page-table.svg\" alt=\"Sirix\" loading=\"eager\" decoding=\"async\">\r\n        <b>Instant estimate<\/b>\r\n        <span class=\"svc-lock\" id=\"svcLock\" hidden><\/span>\r\n      <\/div>\r\n      <div class=\"prog-meta\">\r\n        <span class=\"prog-step\" id=\"progStep\">Step 1 of 5 \u00b7 Property<\/span>\r\n        <span class=\"prog-pct\" id=\"progPct\">20%<\/span>\r\n      <\/div>\r\n      <div class=\"prog-track\"><div class=\"prog-fill\" id=\"progFill\"><\/div><\/div>\r\n    <\/div>\r\n\r\n    <div class=\"est-body\" id=\"estBody\"><!-- steps injected --><\/div>\r\n\r\n    <div class=\"est-foot\">\r\n      <button class=\"btn btn-ghost hidden\" id=\"btnBack\"><svg viewBox=\"0 0 24 24\"><path d=\"M15 18l-6-6 6-6\"><\/path><\/svg>Back<\/button>\r\n      <button class=\"btn btn-primary\" id=\"btnNext\" disabled=\"\">Continue<svg viewBox=\"0 0 24 24\"><path d=\"M9 18l6-6-6-6\"><\/path><\/svg><\/button>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n<\/div>\r\n\r\n<script>\r\n\r\n(function(){\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 CONFIG \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  var ic = {\r\n    retail:'<path d=\"M3 9l1.5-5h15L21 9M4 9v11h16V9M4 9h16M9 20v-6h6v6\"\/>',\r\n    warehouse:'<path d=\"M3 21V9l9-5 9 5v12M3 21h18M8 21v-7h8v7\"\/>',\r\n    auto:'<path d=\"M5 17h14M6 17l-1.5-5.5L6 7h12l1.5 4.5L18 17M7.5 11h9\"\/><circle cx=\"7.5\" cy=\"17.5\" r=\"1.5\"\/><circle cx=\"16.5\" cy=\"17.5\" r=\"1.5\"\/>',\r\n    construction:'<path d=\"M3 21h18M5 21v-8l7-4 7 4v8M9 21v-5h6v5\"\/><path d=\"M12 9V4l4 2\"\/>',\r\n    residential:'<path d=\"M4 11l8-6 8 6v9a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1z\"\/><path d=\"M9 21v-6h6v6\"\/>',\r\n    commercial:'<path d=\"M5 21V4h9v17M14 9h5v12M8 8h3M8 12h3M8 16h3M17 13h1M17 17h1\"\/>',\r\n    campus:'<path d=\"M3 10l9-5 9 5-9 5-9-5z\"\/><path d=\"M7 12v5c0 1 2.2 2 5 2s5-1 5-2v-5\"\/><path d=\"M21 10v5\"\/>',\r\n    other:'<circle cx=\"12\" cy=\"12\" r=\"9\"\/><path d=\"M9.5 9a2.5 2.5 0 1 1 3.5 2.3c-.8.4-1 .8-1 1.7M12 17h.01\"\/>'\r\n  };\r\n  var sic = {\r\n    continuous:'<circle cx=\"12\" cy=\"12\" r=\"3.2\"\/><path d=\"M2.5 12S6 5.5 12 5.5 21.5 12 21.5 12 18 18.5 12 18.5 2.5 12 2.5 12z\"\/>',\r\n    event:'<path d=\"M13 3L5 13h6l-1 8 8-10h-6z\"\/>',\r\n    verify:'<path d=\"M12 3l7 3v5c0 4.5-3 7.5-7 9-4-1.5-7-4.5-7-9V6z\"\/><path d=\"M9 12l2 2 4-4\"\/>',\r\n    tour:'<circle cx=\"11\" cy=\"11\" r=\"6\"\/><path d=\"M20 20l-4.5-4.5\"\/>',\r\n    access:'<rect x=\"4\" y=\"10\" width=\"16\" height=\"11\" rx=\"2\"\/><path d=\"M8 10V7a4 4 0 0 1 8 0v3\"\/><circle cx=\"12\" cy=\"15.5\" r=\"1.4\"\/>',\r\n    gate:'<path d=\"M3 21V6l4-2 4 2v15M13 21V6l4-2 4 2v15M3 21h18M6 9v0M6 13v0M17 9v0M17 13v0\"\/>',\r\n    lone:'<circle cx=\"12\" cy=\"7\" r=\"3.2\"\/><path d=\"M6 21v-1a6 6 0 0 1 12 0v1\"\/><path d=\"M12 10.5v3M19 4l1.5 1.5M4 20l1.5-1.5\"\/>',\r\n    support:'<path d=\"M4 12a8 8 0 0 1 16 0\"\/><rect x=\"3\" y=\"12\" width=\"3.5\" height=\"6\" rx=\"1.5\"\/><rect x=\"17.5\" y=\"12\" width=\"3.5\" height=\"6\" rx=\"1.5\"\/><path d=\"M19 18a4 4 0 0 1-4 3h-2\"\/>',\r\n    vip:'<path d=\"M12 2.5l7 2.8v5.4c0 4.2-2.8 7.4-7 8.8-4.2-1.4-7-4.6-7-8.8V5.3z\"\/><circle cx=\"12\" cy=\"9.6\" r=\"2\"\/><path d=\"M8.6 15.4c.6-1.7 1.9-2.6 3.4-2.6s2.8.9 3.4 2.6\"\/>',\r\n    help:'<circle cx=\"12\" cy=\"12\" r=\"9\"\/><path d=\"M9.5 9a2.5 2.5 0 1 1 3.5 2.3c-.8.4-1 .8-1 1.7M12 17h.01\"\/>',\r\n    ai:'<rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2.5\"\/><path d=\"M9 2v4M15 2v4M9 18v4M15 18v4M2 9h4M2 15h4M18 9h4M18 15h4\"\/><circle cx=\"12\" cy=\"12\" r=\"2.2\"\/>'\r\n  };\r\n\r\n  var CONFIG = {\r\n    properties:[\r\n      {id:'retail', label:'Retail store', desc:'Shops, malls, showrooms', icon:ic.retail, risk:1.0, tone:'blue'},\r\n      {id:'warehouse', label:'Warehouse \/ storage', desc:'Self-storage, distribution', icon:ic.warehouse, risk:1.1, tone:'amber'},\r\n      {id:'auto', label:'Auto & lots', desc:'Dealerships, parking, yards', icon:ic.auto, risk:1.15, tone:'orange'},\r\n      {id:'construction', label:'Construction site', desc:'Active or dormant sites', icon:ic.construction, risk:1.2, tone:'violet'},\r\n      {id:'residential', label:'Residential \/ condo', desc:'Buildings, communities', icon:ic.residential, risk:1.0, tone:'teal'},\r\n      {id:'commercial', label:'Commercial building', desc:'Offices, mixed-use', icon:ic.commercial, risk:1.0, tone:'indigo'},\r\n      {id:'campus', label:'School \/ campus', desc:'Education, institutions', icon:ic.campus, risk:1.05, tone:'rose'},\r\n      {id:'other', label:'Something else', desc:'Tell us more later', icon:ic.other, risk:1.05, tone:'slate'}\r\n    ],\r\n    services:[\r\n      {id:'video', label:'Video monitoring', desc:'Live or event-based camera monitoring', icon:sic.continuous, rate:75, unit:'camera'},\r\n      {id:'intercom', label:'Intercom response', desc:'We answer & handle intercom requests', icon:sic.access, rate:107, unit:'site'},\r\n      {id:'gate', label:'Gate \/ door control', desc:'Remote access control for entries', icon:sic.gate, rate:180, unit:'site'},\r\n      {id:'lone', label:'Lone worker', desc:'Safety for isolated staff', icon:sic.lone, rate:60, unit:'site'},\r\n      {id:'support', label:'Support to user', desc:'End-user help & troubleshooting', icon:sic.support, rate:50, unit:'site'},\r\n      {id:'vip', label:'VIP safe passage', desc:'Escorted camera checks for VIP movement', icon:sic.vip, rate:15, unit:'escort'},\r\n      {id:'unsure', label:'Not sure, help me decide', desc:'A specialist will guide you', icon:sic.help, rate:0, unit:'none'}\r\n    ],\r\n    schedules:[\r\n      {id:'afterhours', label:'After hours', desc:'Nights & weekends', mult:1.0, phrase:'after-hours monitoring'},\r\n      {id:'always', label:'24 \/ 7 coverage', desc:'Around the clock', mult:2.0, phrase:'24\/7 monitoring'}\r\n    ],\r\n    locations:[\r\n      {id:'ca', label:'Canada', cur:'CAD', sym:'$', fx:1.0},\r\n      {id:'us', label:'United States', cur:'USD', sym:'$', fx:0.72},\r\n      {id:'other', label:'Other \/ international', cur:'USD', sym:'$', fx:0.72}\r\n    ],\r\n    setupPerCamera:64,\r\n    tiers:{\r\n      intercom:{ label:'Expected intercom responses per month', options:[\r\n        {id:'t1', vol:'50 responses or less', price:375},\r\n        {id:'t2', vol:'51 to 100 responses', price:665},\r\n        {id:'t3', vol:'101 to 150 responses', price:915}\r\n      ]},\r\n      gate:{ label:'Expected gate \/ door events per month', options:[\r\n        {id:'t1', vol:'50 events or less', price:215},\r\n        {id:'t2', vol:'51 to 100 events', price:375},\r\n        {id:'t3', vol:'101 to 150 events', price:500}\r\n      ]}\r\n    },\r\n    lone:{ perSite:42, perUser:42 },\r\n    vip:{ perEscort:15, camsPerBand:16, maxEscorts:100, rangeLow:15, rangeHigh:30 },\r\n    contactTimes:['Morning (8am to 12pm)','Afternoon (12pm to 5pm)','Evening (5pm to 8pm)','Anytime']\r\n  };\r\n\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 STATE \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  var state = { step:0, property:null, services:[], sites:1, siteData:[{name:'Site 1', cameras:16, escorts:4, escortCams:16}], intercomTier:'t1', gateTier:'t1', loneUsers:5, schedule:'afterhours', location:'ca', locationText:'', unsureNote:'',\r\n                name:'', email:'', phone:'', besttime:'Anytime' };\r\n  function totalCameras(){ return state.siteData.reduce(function(a,s){ return a + s.cameras; }, 0); }\r\n  function syncSites(n){\r\n    n = Math.max(1, Math.min(10, n));\r\n    state.sites = n;\r\n    while(state.siteData.length < n) state.siteData.push({ name:'Site '+(state.siteData.length+1), cameras:16, escorts:4, escortCams:16 });\r\n    state.siteData.forEach(function(sd){\r\n      if(typeof sd.escorts !== 'number') sd.escorts = 4;\r\n      if(typeof sd.escortCams !== 'number') sd.escortCams = 16;\r\n    });\r\n    state.siteData.length = n;\r\n  }\r\n  \/* VIP safe passage: $15 per escort per 16-camera band, no setup fee *\/\r\n  function hasSvc(id){ return state.services.indexOf(id) > -1; }\r\n  function escortBands(cams){ return Math.max(1, Math.ceil((+cams || 1) \/ CONFIG.vip.camsPerBand)); }\r\n  function escortPrice(cams){ return escortBands(cams) * CONFIG.vip.perEscort; }\r\n  function siteVipMonthly(s){ return (s.escorts || 0) * escortPrice(s.escortCams); }\r\n  function vipMonthly(){ return state.siteData.reduce(function(a,s){ return a + siteVipMonthly(s); }, 0); }\r\n  function totalEscorts(){ return state.siteData.reduce(function(a,s){ return a + (s.escorts || 0); }, 0); }\r\n  \/* \"Not sure, help me decide\" picked on its own: there is nothing priced to configure,\r\n     so the Details step becomes one optional free-text box and the Estimate step drops\r\n     out of the flow entirely. Picked alongside a real service, nothing changes. *\/\r\n  function unsureOnly(){\r\n    return hasSvc('unsure') && state.services.length === 1;\r\n  }\r\n  \/\/ VIP is the only priced pick -> the VIP market-range estimate and contact screens\r\n  function vipOnly(){\r\n    if(!hasSvc('vip')) return false;\r\n    return ['video','intercom','gate','lone'].every(function(id){ return !hasSvc(id); });\r\n  }\r\n  \/* VIP link: estimated market range, escorts x camera blocks x $15 (low) \/ $30 (high) *\/\r\n  function siteVipRange(s){\r\n    var blocks = (s.escorts || 0) * escortBands(s.escortCams);\r\n    return [blocks * CONFIG.vip.rangeLow, blocks * CONFIG.vip.rangeHigh];\r\n  }\r\n  function vipRange(){\r\n    return state.siteData.reduce(function(a,s){ var r = siteVipRange(s); return [a[0]+r[0], a[1]+r[1]]; }, [0,0]);\r\n  }\r\n  function rangeStr(r){ return priceStr(r[0]) + '\\u2013' + Math.round(r[1]).toLocaleString('en-US'); }\r\n  function avgEscortCams(){\r\n    return Math.round(state.siteData.reduce(function(a,s){ return a + (s.escortCams || 0); }, 0) \/ state.siteData.length);\r\n  }\r\n  function vipSiteNote(s){\r\n    var e = s.escorts || 0, b = escortBands(s.escortCams);\r\n    return e + ' escort' + (e !== 1 ? 's' : '') + ' \\u00d7 ' + (b > 1 ? b + ' camera blocks \\u00d7 ' : '') +\r\n             '$' + CONFIG.vip.rangeLow + '\\u2013' + CONFIG.vip.rangeHigh + ' = ' + rangeStr(siteVipRange(s)) + ' \/ month (estimated)';\r\n  }\r\n\r\n  var STEP_NAMES = ['Property','Services','Details','Estimate','Contact'];\r\n\r\n  \/* \u2500\u2500 deep link from a service page: ?service=<id> preselects that service and\r\n     takes the \"Which services do you need?\" step out of the flow entirely.\r\n     Works for any service id, so other service pages can link in the same way. \u2500\u2500 *\/\r\n  function readCalcParam(){\r\n    var raw = '';\r\n    try{\r\n      var q = (window.location.search || '').replace(\/^\\?\/, '').split('&');\r\n      for(var i = 0; i < q.length; i++){\r\n        var kv = q[i].split('=');\r\n        var k = decodeURIComponent((kv[0] || '').replace(\/\\+\/g, ' ')).toLowerCase().trim();\r\n        if(k === 'service' || k === 'calc'){\r\n          raw = decodeURIComponent((kv[1] || '').replace(\/\\+\/g, ' ')).toLowerCase().trim();\r\n        }\r\n      }\r\n    }catch(e){ return ''; }\r\n    return raw;\r\n  }\r\n  \/* industry pages: ?calc=<key> answers the property question for the visitor, so the\r\n     industry step is skipped. A preset with a `service` also answers the service question\r\n     (priced exactly as its base service, only the label changes) and jumps straight to\r\n     Details; a preset without one keeps the normal Services step and everything after it. *\/\r\n  var PRESETS = {\r\n    donation:{ property:{id:'donation', label:'Donation center', desc:'Donation bins and drop-off sites', icon:ic.other, risk:1.0, tone:'slate'},\r\n               service:'video', serviceLabel:'Bin monitoring', serviceDesc:'Live camera monitoring of donation bins' },\r\n    worship: { property:{id:'worship', label:'House of worship', desc:'Churches, mosques, synagogues, temples', icon:ic.campus, risk:1.0, tone:'slate'} }\r\n  };\r\n  function readLockedService(){\r\n    var raw = readCalcParam();\r\n    if(!raw || raw === 'unsure') return '';\r\n    var match = null;\r\n    CONFIG.services.forEach(function(svc){\r\n      if(svc.id === raw || svc.id === raw.replace(\/[^a-z]\/g, '')) match = svc;\r\n    });\r\n    return match ? match.id : '';\r\n  }\r\n  var preset = PRESETS[readCalcParam().replace(\/[^a-z]\/g, '')] || null;\r\n  if(preset){\r\n    \/\/ this visit only: the industry is known and the base service carries the industry's name\r\n    CONFIG.properties.push(preset.property);\r\n    if(preset.service){\r\n      CONFIG.services.forEach(function(svc){\r\n        if(svc.id === preset.service){ svc.label = preset.serviceLabel; svc.desc = preset.serviceDesc; }\r\n      });\r\n    }\r\n    state.property = preset.property.id;\r\n  }\r\n  var lockedService = preset ? (preset.service || '') : readLockedService();\r\n  var vipMode = lockedService === 'vip';\r\n  var BASE_FLOW = [0, 1, 2, 3, 4];\r\n  if(lockedService){\r\n    state.services = [lockedService];\r\n    BASE_FLOW = [0, 2, 3, 4];       \/\/ step 2 is already answered by the link\r\n  }\r\n  if(vipMode || preset){\r\n    \/\/ VIP \/ industry link: no industry step. Services -> Details -> Estimate -> Contact when the\r\n    \/\/ preset only names the industry; Details -> Estimate -> Contact when it names the service too.\r\n    BASE_FLOW = (preset && !preset.service) ? [1, 2, 3, 4] : [2, 3, 4];\r\n    state.step = BASE_FLOW[0];\r\n  }\r\n  \/* recomputed on every paint and on every nav click: an \"unsure only\" basket has no\r\n     numbers to estimate, so step 3 is removed and Continue goes note box -> quote form *\/\r\n  function flow(){\r\n    if(unsureOnly()) return BASE_FLOW.filter(function(s){ return s !== 3; });\r\n    return BASE_FLOW;\r\n  }\r\n  function flowPos(){ var f = flow(); var i = f.indexOf(state.step); return i < 0 ? 0 : i; }\r\n\r\n  var root = document.currentScript ? document.currentScript.previousElementSibling : null;\r\n  if(!root || !root.classList || !root.classList.contains('sirix-estimator-widget')) root = document.querySelector('.sirix-estimator-widget');\r\n  if(!root) return;\r\n  if(vipMode) root.classList.add('vip-mode');\r\n  var $ = function(sel){ return root.querySelector(sel); };\r\n  var body = $('#estBody');\r\n  var btnNext = $('#btnNext');\r\n  var btnBack = $('#btnBack');\r\n  var esc = function(s){ return String(s).replace(\/&\/g,'&amp;').replace(\/<\/g,'&lt;').replace(\/>\/g,'&gt;').replace(\/\"\/g,'&quot;'); };\r\n\r\n  if(lockedService){\r\n    var lockChip = $('#svcLock');\r\n    var lockedSvc = CONFIG.services.find(function(x){ return x.id === lockedService; });\r\n    if(lockChip && lockedSvc){\r\n      lockChip.innerHTML = '<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M12 2.4l7.6 3v5.7c0 4.6-3.1 8.2-7.6 10-4.5-1.8-7.6-5.4-7.6-10V5.4z\" fill=\"currentColor\"\/><path d=\"M8.5 12.1l2.4 2.4 4.6-4.7\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg>'+\r\n        '<span>'+esc(lockedSvc.label)+'<\/span>';\r\n      lockChip.removeAttribute('hidden');\r\n    }\r\n  }\r\n\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 RENDER STEPS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  function stepProperty(){\r\n    var opts = CONFIG.properties.map(function(p){\r\n      return '<button class=\"opt'+(state.property===p.id?' sel':'')+'\" data-tone=\"'+p.tone+'\" data-prop=\"'+p.id+'\">'+\r\n        '<span class=\"ic\"><svg viewBox=\"0 0 24 24\">'+p.icon+'<\/svg><\/span>'+\r\n        '<span class=\"lbl\"><b>'+esc(p.label)+'<\/b><span>'+esc(p.desc)+'<\/span><\/span>'+\r\n        '<span class=\"chk\"><svg viewBox=\"0 0 24 24\"><path d=\"M4 12l5 5L20 6\"\/><\/svg><\/span><\/button>';\r\n    }).join('');\r\n    return '<div class=\"step-q\">What type of property do you protect?<\/div>'+\r\n           '<p class=\"step-sub\">This helps us match the right monitoring approach to your site.<\/p>'+\r\n           '<div class=\"opt-grid\">'+opts+'<\/div>';\r\n  }\r\n\r\n  function stepServices(){\r\n    var opts = CONFIG.services.map(function(s){\r\n      var on = state.services.indexOf(s.id)>-1;\r\n      return '<button class=\"opt'+(on?' sel':'')+'\" data-svc=\"'+s.id+'\">'+\r\n        '<span class=\"chkbox\"><svg viewBox=\"0 0 24 24\"><path d=\"M4 12l5 5L20 6\"\/><\/svg><\/span>'+\r\n        '<span class=\"lbl\"><b>'+esc(s.label)+'<\/b><span>'+esc(s.desc)+'<\/span><\/span><\/button>';\r\n    }).join('');\r\n    return '<div class=\"step-q\">Which services do you need?<\/div>'+\r\n           '<p class=\"step-sub\">Pick everything that applies. Not sure? Choose what sounds closest, we\\u2019ll refine it together.<\/p>'+\r\n           '<p class=\"multi-hint\">Select one or more<\/p>'+\r\n           '<div class=\"opt-grid\">'+opts+'<\/div>';\r\n  }\r\n\r\n  function priceStr(n){ return '$' + Math.round(n).toLocaleString('en-US'); }\r\n  function tierPrice(group){ var o = CONFIG.tiers[group].options.find(function(x){return x.id===state[group+'Tier'];}); return o?o.price:0; }\r\n\r\n  function stepUnsure(){\r\n    return '<div class=\"step-q\">Tell us what you\\u2019re trying to protect<\/div>'+\r\n      '<p class=\"step-sub\">Share a few details below and a specialist will use them to point you to the right service.<\/p>'+\r\n      '<div class=\"unsure-note\">'+\r\n        '<label for=\"unsureNote\">What are you looking for? <span class=\"opt-tag\">(optional)<\/span><\/label>'+\r\n        '<textarea id=\"unsureNote\" rows=\"5\" maxlength=\"1200\" placeholder=\"Example: an unfenced storage yard with recurring theft at night, no cameras on site yet.\">'+esc(state.unsureNote)+'<\/textarea>'+\r\n        '<p class=\"unsure-help\">'+\r\n          '<svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"9\"><\/circle><path d=\"M12 11.5v5M12 7.8h.01\"><\/path><\/svg>'+\r\n          '<span>Not sure what to write? Leave it blank. You\\u2019ll still get your estimate, and a specialist will follow up to fill in the gaps.<\/span>'+\r\n        '<\/p>'+\r\n      '<\/div>';\r\n  }\r\n\r\n  function stepDetails(){\r\n    if(unsureOnly()) return stepUnsure();   \/\/ optional note only, nothing to price\r\n    var svc = state.services;\r\n    var hasVideo = svc.indexOf('video')>-1;\r\n    var hasIntercom = svc.indexOf('intercom')>-1;\r\n    var hasGate = svc.indexOf('gate')>-1;\r\n    var hasLone = svc.indexOf('lone')>-1;\r\n    var hasSupport = svc.indexOf('support')>-1;\r\n    var hasVip = svc.indexOf('vip')>-1;\r\n    var needSites = hasVideo || hasIntercom || hasGate || hasLone || hasSupport || hasVip;\r\n\r\n    var out = '<div class=\"step-q\">Tell us about your setup<\/div>'+\r\n      '<p class=\"step-sub\">'+(vipOnly() ? 'A few details let us shape a realistic estimated range.' : 'A few details let us shape a realistic estimate.')+'<\/p>';\r\n\r\n    if(needSites){\r\n      var scheduleBlock = '';\r\n      if(hasVideo){\r\n        var segs = CONFIG.schedules.map(function(s){\r\n          return '<button class=\"'+(state.schedule===s.id?'sel':'')+'\" data-sched=\"'+s.id+'\"><b>'+esc(s.label)+'<\/b><span>'+esc(s.desc)+'<\/span><\/button>';\r\n        }).join('');\r\n        scheduleBlock = '<div class=\"setup-item setup-schedule\">'+\r\n          '<div class=\"field-label\"><b>Monitoring schedule<\/b><\/div>'+\r\n          '<div class=\"seg\">'+segs+'<\/div>'+\r\n        '<\/div>';\r\n      }\r\n\r\n      out += '<div class=\"setup-compact-card\">'+\r\n        '<div class=\"setup-item setup-sites\">'+\r\n          '<div class=\"field-label\"><b>How many sites?<\/b><\/div>'+\r\n          '<div class=\"stepper\"><button id=\"siteMinus\" aria-label=\"fewer\">\\u2013<\/button><span class=\"num\" id=\"siteNum\">'+state.sites+'<\/span><button id=\"sitePlus\" aria-label=\"more\">+<\/button><\/div>'+\r\n        '<\/div>'+\r\n        scheduleBlock+\r\n        '<div class=\"setup-item setup-location\">'+\r\n          '<div class=\"field-label\"><b>Location<\/b><\/div>'+\r\n          '<div class=\"selectwrap\"><input type=\"text\" id=\"locInput\" placeholder=\"City, province \/ state, or country\" value=\"'+esc(state.locationText)+'\" \/><\/div>'+\r\n        '<\/div>'+\r\n      '<\/div>';\r\n    }\r\n\r\n    if(hasVideo || hasVip){\r\n      var siteCards = state.siteData.map(function(s,i){\r\n        var camBlock = hasVideo ? ('<div class=\"field\" style=\"margin-bottom:0;\">'+\r\n            '<div class=\"field-label\"><b>Cameras<\/b><span class=\"val siteCamVal\" data-i=\"'+i+'\">'+s.cameras+(s.cameras>=100?'+':'')+' <small>cams<\/small><\/span><\/div>'+\r\n            '<input type=\"range\" class=\"siteCam\" data-i=\"'+i+'\" min=\"1\" max=\"100\" value=\"'+s.cameras+'\" \/>'+\r\n            '<div class=\"range-ends\"><span>1<\/span><span>100+<\/span><\/div>'+\r\n          '<\/div>') : '';\r\n        var vipBlock = hasVip ? ('<div class=\"vip-row\">'+\r\n            '<div class=\"vip-item\">'+\r\n              '<div class=\"field-label\"><b>VIP escort events \/ month<\/b><\/div>'+\r\n              '<div class=\"stepper\"><button class=\"vipMinus\" data-i=\"'+i+'\" aria-label=\"fewer escorts\">\\u2013<\/button><span class=\"num vipNum\" data-i=\"'+i+'\">'+s.escorts+'<\/span><button class=\"vipPlus\" data-i=\"'+i+'\" aria-label=\"more escorts\">+<\/button><\/div>'+\r\n            '<\/div>'+\r\n            '<div class=\"vip-item\">'+\r\n              '<div class=\"field-label\"><b>Cameras checked per escort<\/b><span class=\"val vipCamVal\" data-i=\"'+i+'\">'+s.escortCams+(s.escortCams>=100?'+':'')+' <small>cams<\/small><\/span><\/div>'+\r\n              '<input type=\"range\" class=\"vipCam\" data-i=\"'+i+'\" min=\"1\" max=\"100\" value=\"'+s.escortCams+'\" \/>'+\r\n              '<div class=\"range-ends\"><span>1<\/span><span>100+<\/span><\/div>'+\r\n            '<\/div>'+\r\n            '<p class=\"vip-note\" data-i=\"'+i+'\">'+esc(vipSiteNote(s))+'<\/p>'+\r\n          '<\/div>') : '';\r\n        return '<div class=\"site-card'+(hasVideo?'':' site-card-vip')+'\">'+\r\n          '<div class=\"inp\"><label>Site name<\/label>'+\r\n            '<input type=\"text\" class=\"siteName\" data-i=\"'+i+'\" value=\"'+esc(s.name)+'\" placeholder=\"Site '+(i+1)+'\" \/><\/div>'+\r\n          camBlock+\r\n          vipBlock+\r\n        '<\/div>';\r\n      }).join('');\r\n      out += '<div class=\"sites-wrap\">'+siteCards+'<\/div>';\r\n      if(hasVip) out += '<p class=\"vip-fine\">Running estimate uses an estimated market range of $'+CONFIG.vip.rangeLow+' to $'+CONFIG.vip.rangeHigh+' per escort, per block of up to '+CONFIG.vip.camsPerBand+' cameras.<\/p>';\r\n    }\r\n\r\n    if(hasIntercom) out += tierBlock('intercom', false);\r\n    if(hasGate) out += tierBlock('gate', true);\r\n\r\n    if(hasLone){\r\n      out += '<div class=\"field\">'+\r\n        '<div class=\"field-label\"><b>How many lone workers?<\/b><\/div>'+\r\n        '<div class=\"stepper\"><button id=\"userMinus\" aria-label=\"fewer\">\\u2013<\/button><span class=\"num\" id=\"userNum\">'+state.loneUsers+'<\/span><button id=\"userPlus\" aria-label=\"more\">+<\/button><\/div>'+\r\n      '<\/div>';\r\n    }\r\n\r\n    return out;\r\n  }\r\n\r\n  function tierBlock(group, showPrice){\r\n    var cfg = CONFIG.tiers[group], cur = state[group+'Tier'];\r\n    var btns = cfg.options.map(function(o){\r\n      var price = showPrice ? '<span class=\"tier-price\">'+priceStr(o.price)+'<small>\/mo<\/small><\/span>' : '';\r\n      return '<button class=\"tier-opt'+(cur===o.id?' sel':'')+'\" data-tiergroup=\"'+group+'\" data-tierid=\"'+o.id+'\">'+\r\n        '<span class=\"tier-vol\">'+esc(o.vol)+'<\/span>'+price+'<\/button>';\r\n    }).join('');\r\n    return '<div class=\"field\"><div class=\"field-label\"><b>'+esc(cfg.label)+'<\/b><\/div><div class=\"tier-seg\">'+btns+'<\/div><\/div>';\r\n  }\r\n\r\n  function calc(){\r\n    var loc = CONFIG.locations[0]; \/\/ default currency CAD; location captured as free text\r\n    var sched = CONFIG.schedules.find(function(s){return s.id===state.schedule;});\r\n    var prop = CONFIG.properties.find(function(p){return p.id===state.property;}) || {risk:1};\r\n    var lines = [];\r\n    var monthly = 0;\r\n    state.services.forEach(function(sid){\r\n      var s = CONFIG.services.find(function(x){return x.id===sid;});\r\n      if(!s) return;\r\n      var amt = 0;\r\n      if(sid==='video'){ amt = s.rate * totalCameras() * sched.mult * prop.risk; }\r\n      else if(sid==='intercom'){ amt = tierPrice('intercom') * state.sites; }\r\n      else if(sid==='gate'){ amt = tierPrice('gate') * state.sites; }\r\n      else if(sid==='lone'){ amt = CONFIG.lone.perSite * state.sites + CONFIG.lone.perUser * state.loneUsers; }\r\n      else if(sid==='vip'){ amt = vipMonthly(); } \/\/ no setup \/ flat fee, billed per escort\r\n      else if(sid==='support'){ return; } \/\/ custom live assistance, priced via Sirix assessment\r\n      else { return; } \/\/ 'none' (not sure) carries no price\r\n      amt = amt * loc.fx;\r\n      monthly += amt;\r\n      lines.push({ label:s.label, amt:amt });\r\n    });\r\n    var setup = CONFIG.setupPerCamera * totalCameras() * loc.fx;\r\n    return { monthly:monthly, setup:setup, loc:loc, lines:lines };\r\n  }\r\n\r\n  function fmt(n, loc){ return loc.sym + Math.round(n).toLocaleString('en-US'); }\r\n  function round50(n){ return Math.round(n\/50)*50; }\r\n\r\n  \/\/ benefit checklist derived from selected services (deduped, order-preserving)\r\n  var FEATURES = {\r\n    video:['24\/7 AI-powered detection with live human verification','Voice intervention \/ talk-down via on-site speakers'],\r\n    intercom:['Live operators answer and handle intercom requests','Access granted or denied to your protocols'],\r\n    gate:['Remote gate and door access control','Entry logged and verified on every request'],\r\n    lone:['Fall detection, GPS tracking and panic alerts','Check-ins for staff working alone'],\r\n    support:['Direct line to a Sirix support specialist','Setup help, troubleshooting and guidance'],\r\n    vip:['Operators sweep the route cameras live for every VIP escort','Escort followed from start point to destination','Instant escalation and dispatch the moment something is flagged'],\r\n    unsure:['A specialist reviews your site and recommends the right mix']\r\n  };\r\n  var FEATURES_LEAD = ['Connects to your existing cameras, no new hardware'];\r\n  var FEATURES_COMMON = ['Police \/ security dispatch on verified threats','Real-time instant reporting on critical events'];\r\n  function buildFeatures(){\r\n    var out = [], seen = {};\r\n    if(state.services.indexOf('video')>-1 || state.services.indexOf('vip')>-1){ FEATURES_LEAD.forEach(function(f){ if(!seen[f]){ seen[f]=1; out.push(f); } }); }\r\n    state.services.forEach(function(id){ (FEATURES[id]||[]).forEach(function(f){ if(!seen[f]){ seen[f]=1; out.push(f); } }); });\r\n    FEATURES_COMMON.forEach(function(f){ if(!seen[f]){ seen[f]=1; out.push(f); } });\r\n    return out;\r\n  }\r\n\r\n  function findById(list, id){\r\n    return (list || []).find(function(x){ return x.id === id; }) || null;\r\n  }\r\n\r\n  function selectedTierLabel(group){\r\n    var cfg = CONFIG.tiers[group];\r\n    if(!cfg) return '';\r\n    var selected = findById(cfg.options, state[group + 'Tier']);\r\n    return selected ? selected.vol : '';\r\n  }\r\n\r\n  \/\/ -15% \/ +20% around the other priced services; VIP adds its own $15 to $30 market range on top\r\n  function rangeLoHi(r){\r\n    var vip = hasSvc('vip');\r\n    var vr = vip ? vipRange() : [0,0];\r\n    var base = r.monthly - (vip ? vipMonthly() * r.loc.fx : 0);\r\n    var lo = round50(base * 0.85) + vr[0];\r\n    var hi = round50(base * 1.2) + vr[1];\r\n    if(lo < 50) lo = 50;\r\n    if(hi <= lo) hi = lo + 100;\r\n    return [lo, hi];\r\n  }\r\n\r\n  function estimateRangeText(){\r\n    if(vipOnly()) return rangeStr(vipRange()) + ' \/ month (estimated market range)';\r\n    var r = calc();\r\n    if(r.monthly <= 0) return 'Tailored plan';\r\n    var lh = rangeLoHi(r);\r\n    return fmt(lh[0], r.loc) + ' - ' + fmt(lh[1], r.loc) + ' \/ month';\r\n  }\r\n\r\n  function buildFreshworksSummary(){\r\n    var r = calc();\r\n    var prop = findById(CONFIG.properties, state.property);\r\n    var sched = findById(CONFIG.schedules, state.schedule);\r\n    var serviceLabels = state.services.map(function(id){\r\n      var svc = findById(CONFIG.services, id);\r\n      return svc ? svc.label : id;\r\n    });\r\n    var lines = [];\r\n\r\n    lines.push('Sirix Instant Estimate Summary');\r\n    lines.push('');\r\n    if(!vipMode) lines.push('Property type: ' + (prop ? prop.label : 'Not selected'));\r\n    lines.push('Selected services: ' + (serviceLabels.length ? serviceLabels.join(', ') : 'Not selected'));\r\n    lines.push('Number of sites: ' + state.sites);\r\n    lines.push('Location: ' + ((state.locationText || '').trim() || 'Not provided'));\r\n\r\n    if(state.services.indexOf('video') > -1){\r\n      lines.push('Monitoring schedule: ' + (sched ? sched.label : 'Not selected'));\r\n      lines.push('Total cameras: ' + totalCameras());\r\n      lines.push('Site camera details:');\r\n      state.siteData.forEach(function(site, i){\r\n        lines.push('  ' + (i + 1) + '. ' + ((site.name || '').trim() || ('Site ' + (i + 1))) + ': ' + site.cameras + (site.cameras >= 100 ? '+' : '') + ' cameras');\r\n      });\r\n    }\r\n\r\n    if(hasSvc('vip')){\r\n      lines.push('VIP safe passage (estimated market range, not a Sirix price list: $' + CONFIG.vip.rangeLow + '-' + CONFIG.vip.rangeHigh + ' per escort per ' + CONFIG.vip.camsPerBand + ' cameras, no setup or flat fee):');\r\n      state.siteData.forEach(function(site, i){\r\n        lines.push('  ' + (i + 1) + '. ' + ((site.name || '').trim() || ('Site ' + (i + 1))) + ': ' +\r\n          site.escorts + ' escort event' + (site.escorts !== 1 ? 's' : '') + ' \/ month, ~' +\r\n          site.escortCams + (site.escortCams >= 100 ? '+' : '') + ' cameras per escort = ' +\r\n          rangeStr(siteVipRange(site)) + ' \/ month (estimated)');\r\n      });\r\n      lines.push('Total VIP escort events \/ month: ' + totalEscorts());\r\n    }\r\n\r\n    if(state.services.indexOf('intercom') > -1){\r\n      lines.push('Intercom response volume: ' + selectedTierLabel('intercom'));\r\n    }\r\n\r\n    if(state.services.indexOf('gate') > -1){\r\n      lines.push('Gate \/ door event volume: ' + selectedTierLabel('gate'));\r\n    }\r\n\r\n    if(state.services.indexOf('lone') > -1){\r\n      lines.push('Lone workers: ' + state.loneUsers);\r\n    }\r\n\r\n    if(state.services.indexOf('support') > -1){\r\n      lines.push('Support note: Custom live assistance selected. Pricing requires a short scoping assessment.');\r\n    }\r\n\r\n    if(state.services.indexOf('unsure') > -1){\r\n      lines.push('Support note: User is not sure and wants help choosing the right service mix.');\r\n      lines.push('What they are looking for: ' + ((state.unsureNote || '').trim().replace(\/\\s*\\r?\\n\\s*\/g, ' ') || 'Not provided'));\r\n    }\r\n\r\n    lines.push('');\r\n    lines.push('Estimated range: ' + estimateRangeText());\r\n\r\n    if(r.monthly > 0 && !hasSvc('vip')){\r\n      lines.push('Estimated monthly subtotal before final review: ' + fmt(r.monthly, r.loc) + ' \/ month');\r\n    }\r\n\r\n    lines.push('');\r\n    if(vipOnly()) lines.push('Note: This range is built from the calculator selections and estimated market ranges for remote escort monitoring. It is for planning only and is not a Sirix price list. The exact quote is set during the site assessment.');\r\n    else lines.push('Note: This is a ballpark estimate from the calculator selections. Final pricing may change after Sirix reviews the exact site setup, layout, service volume, and discounts.');\r\n\r\n    return lines.join('\\n');\r\n  }\r\n\r\n  function autofillFreshworksTextarea(doc){\r\n    try{\r\n      if(!doc) return false;\r\n      var textarea = doc.querySelector('.formserv-textarea-field textarea.fserv-textarea, textarea.fserv-textarea, .formserv-textarea-field textarea');\r\n      if(!textarea) return false;\r\n\r\n      if(textarea.getAttribute('data-sirix-autofilled') === 'true'){\r\n        return true;\r\n      }\r\n\r\n      if(textarea.getAttribute('data-sirix-user-edited') === 'true'){\r\n        return true;\r\n      }\r\n\r\n      if(textarea.getAttribute('data-sirix-listener') !== 'true'){\r\n        textarea.setAttribute('data-sirix-listener', 'true');\r\n        textarea.addEventListener('input', function(){\r\n          if(textarea.getAttribute('data-sirix-autofilling') !== 'true'){\r\n            textarea.setAttribute('data-sirix-user-edited', 'true');\r\n          }\r\n        });\r\n      }\r\n\r\n      var summary = buildFreshworksSummary();\r\n\r\n      textarea.setAttribute('data-sirix-autofilling', 'true');\r\n      textarea.value = summary;\r\n      textarea.setAttribute('data-sirix-autofilled', 'true');\r\n\r\n      ['input','change'].forEach(function(evtName){\r\n        try{\r\n          textarea.dispatchEvent(new Event(evtName, { bubbles:true }));\r\n        }catch(e){}\r\n      });\r\n\r\n      textarea.removeAttribute('data-sirix-autofilling');\r\n      return true;\r\n    }catch(e){\r\n      return false;\r\n    }\r\n  }\r\n\r\n\r\n  function relabelFreshworksVip(doc){\r\n    if(!vipOnly() || !doc) return;\r\n    try{\r\n      doc.querySelectorAll('.fserv-label, label').forEach(function(lb){\r\n        Array.prototype.forEach.call(lb.childNodes, function(n){\r\n          if(n.nodeType === 3 && \/^\\s*full name\\s*$\/i.test(n.nodeValue)) n.nodeValue = n.nodeValue.replace(\/full name\/i, 'Full name');\r\n        });\r\n      });\r\n      doc.querySelectorAll('.fserv-button-submit').forEach(function(btn){\r\n        if(btn.children.length === 0) btn.textContent = 'Get my tailored quote';\r\n        else if(btn.tagName === 'INPUT') btn.value = 'Get my tailored quote';\r\n      });\r\n    }catch(e){}\r\n  }\r\n\r\n  function readFreshworksCustomerName(doc){\r\n    try{\r\n      if(!doc) return '';\r\n      var inputs = Array.prototype.slice.call(doc.querySelectorAll('input'));\r\n      var named = inputs.filter(function(input){\r\n        var type = (input.getAttribute('type') || 'text').toLowerCase();\r\n        if(type === 'hidden' || type === 'email' || type === 'tel' || type === 'submit' || type === 'button') return false;\r\n        var value = (input.value || '').trim();\r\n        if(!value) return false;\r\n        var meta = [\r\n          input.getAttribute('name') || '',\r\n          input.getAttribute('placeholder') || '',\r\n          input.getAttribute('aria-label') || '',\r\n          input.id || '',\r\n          input.className || ''\r\n        ].join(' ').toLowerCase();\r\n        return meta.indexOf('name') > -1 || meta.indexOf('first') > -1 || meta.indexOf('contact') > -1;\r\n      });\r\n      if(named.length) return named[0].value.trim();\r\n      var textInput = inputs.find(function(input){\r\n        var type = (input.getAttribute('type') || 'text').toLowerCase();\r\n        return type !== 'hidden' && type !== 'email' && type !== 'tel' && type !== 'submit' && type !== 'button' && (input.value || '').trim();\r\n      });\r\n      return textInput ? textInput.value.trim() : '';\r\n    }catch(e){\r\n      return '';\r\n    }\r\n  }\r\n\r\n  function hasFreshworksVisibleError(doc){\r\n    try{\r\n      if(!doc) return false;\r\n      var nodes = Array.prototype.slice.call(doc.querySelectorAll('.fs-notifier, .fserv-control, .error, .has-error, [role=\"alert\"]'));\r\n      return nodes.some(function(node){\r\n        var text = (node.textContent || '').trim().toLowerCase();\r\n        if(!text) return false;\r\n        var style = doc.defaultView.getComputedStyle(node);\r\n        if(style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') return false;\r\n        return text.indexOf('required') > -1 || text.indexOf('invalid') > -1 || text.indexOf('error') > -1 || text.indexOf('please') > -1;\r\n      });\r\n    }catch(e){\r\n      return false;\r\n    }\r\n  }\r\n\r\n  function showQuoteSubmittedSuccess(customerName){\r\n    if(done) return;\r\n    customerName = (customerName || '').trim();\r\n    if(customerName) state.name = customerName;\r\n    done = true;\r\n    paint();\r\n    try{\r\n      root.scrollIntoView({ behavior:'smooth', block:'center' });\r\n    }catch(e){}\r\n  }\r\n\r\n  function wireFreshworksSubmitSuccess(doc){\r\n    try{\r\n      if(!doc) return false;\r\n      var form = doc.querySelector('form, .fserv-form');\r\n      var submitBtn = doc.querySelector('.fserv-button-submit, button[type=\"submit\"], input[type=\"submit\"]');\r\n      if(!form && !submitBtn) return false;\r\n      if(doc.documentElement.getAttribute('data-sirix-submit-wired') === 'true') return true;\r\n      doc.documentElement.setAttribute('data-sirix-submit-wired', 'true');\r\n\r\n      var handled = false;\r\n      var completeAfterSubmit = function(){\r\n        if(handled) return;\r\n        handled = true;\r\n        var customerName = readFreshworksCustomerName(doc);\r\n        setTimeout(function(){\r\n          if(hasFreshworksVisibleError(doc)){\r\n            handled = false;\r\n            return;\r\n          }\r\n          showQuoteSubmittedSuccess(customerName);\r\n        }, 1400);\r\n      };\r\n\r\n      if(form){\r\n        form.addEventListener('submit', function(){\r\n          completeAfterSubmit();\r\n        }, true);\r\n      }\r\n\r\n      if(submitBtn){\r\n        submitBtn.addEventListener('click', function(){\r\n          var customerName = readFreshworksCustomerName(doc);\r\n          setTimeout(function(){\r\n            if(handled || hasFreshworksVisibleError(doc)) return;\r\n            var formStillVisible = form && form.offsetParent !== null;\r\n            var successText = (doc.body ? doc.body.textContent : '').toLowerCase();\r\n            var looksSubmitted = successText.indexOf('thank') > -1 || successText.indexOf('success') > -1 || successText.indexOf('submitted') > -1 || !formStillVisible;\r\n            if(looksSubmitted){\r\n              handled = true;\r\n              showQuoteSubmittedSuccess(customerName);\r\n            }\r\n          }, 1800);\r\n        }, true);\r\n      }\r\n\r\n      return true;\r\n    }catch(e){\r\n      return false;\r\n    }\r\n  }\r\n\r\n  var VIP_INCLUDED = [\r\n    'Connects to your existing cameras, no new hardware',\r\n    'Operators sweep the route cameras live for every VIP escort',\r\n    'Escort followed from start point to destination',\r\n    'Instant escalation the moment something is flagged',\r\n    'Police or security dispatch on verified threats',\r\n    'Real-time reporting on critical events'\r\n  ];\r\n  function stepEstimateVip(){\r\n    var te = totalEscorts();\r\n    var ctx = 'Based on <b>'+te+' VIP escort'+(te!==1?'s':'')+' a month<\/b> across <b>'+state.sites+' site'+(state.sites!==1?'s':'')+'<\/b>:';\r\n    var rows = state.siteData.map(function(s,i){\r\n      var nm = (s.name||'').trim() || ('Site '+(i+1));\r\n      return '<div class=\"brk-row\">'+\r\n        '<span class=\"k\"><b>'+esc(nm)+'<\/b> \\u00b7 '+s.escorts+' escort'+(s.escorts!==1?'s':'')+' \\u00d7 '+s.escortCams+(s.escortCams>=100?'+':'')+' cams<\/span>'+\r\n        '<span class=\"v\">'+rangeStr(siteVipRange(s))+' \/ mo<\/span><\/div>';\r\n    }).join('');\r\n    var checks = VIP_INCLUDED.map(function(f){\r\n      return '<li><span class=\"tick\"><svg viewBox=\"0 0 24 24\"><path d=\"M4 12l5 5L20 6\"\/><\/svg><\/span>'+esc(f)+'<\/li>';\r\n    }).join('');\r\n    return '<div class=\"est-hero\">'+\r\n      '<p class=\"est-context\">'+ctx+'<\/p>'+\r\n      '<p class=\"est-label\">Estimated market range<\/p>'+\r\n      '<div class=\"est-bigrange\">'+rangeStr(vipRange())+'<span style=\"font-size:0.30em;font-weight:600;color:var(--gray);letter-spacing:0;\"> \/ month<\/span><\/div>'+\r\n      '<p class=\"est-savings est-plain\">No setup or flat fee. Remote escorts are typically priced per event, based on how many cameras get checked. Market estimates run about $'+CONFIG.vip.rangeLow+' to $'+CONFIG.vip.rangeHigh+' for up to '+CONFIG.vip.camsPerBand+' cameras, with each further block of '+CONFIG.vip.camsPerBand+' priced the same way.<\/p>'+\r\n    '<\/div>'+\r\n    '<div class=\"est-break\">'+rows+'<\/div>'+\r\n    '<div class=\"incl\"><h3>What\\u2019s included in this range<\/h3><ul>'+checks+'<\/ul><\/div>'+\r\n    '<p class=\"unsure-help vip-disc\">'+\r\n      '<svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"9\"><\/circle><path d=\"M12 11.5v5M12 7.8h.01\"><\/path><\/svg>'+\r\n      '<span>This range is built from the numbers you entered and estimated market ranges for remote escort monitoring. It is shown for planning only and is not a Sirix price list. Camera counts are an average per escort, so the monthly total moves with your real escort volume. Your exact quote is set during the site assessment.<\/span>'+\r\n    '<\/p>';\r\n  }\r\n\r\n  function stepEstimate(){\r\n    if(vipOnly()) return stepEstimateVip();\r\n    var r = calc();\r\n    var prop = CONFIG.properties.find(function(p){return p.id===state.property;}) || {label:'site'};\r\n    var sched = CONFIG.schedules.find(function(s){return s.id===state.schedule;});\r\n    var propPhrase = prop.label.toLowerCase();\r\n    var hasVideo = state.services.indexOf('video')>-1;\r\n    var tc = totalCameras();\r\n    var scope = hasVideo ? ('<b>'+tc+(tc>=100?'+':'')+'-camera '+esc(propPhrase)+'<\/b>') : ('<b>'+esc(propPhrase)+'<\/b>');\r\n    var schedTxt = hasVideo ? (' with '+esc(sched.phrase)) : '';\r\n    var context = 'Based on your '+scope+schedTxt+':';\r\n    var checks = buildFeatures().map(function(f){\r\n      return '<li><span class=\"tick\"><svg viewBox=\"0 0 24 24\"><path d=\"M4 12l5 5L20 6\"\/><\/svg><\/span>'+esc(f)+'<\/li>';\r\n    }).join('');\r\n    var inclBlock = '<div class=\"incl\"><h3>What\u2019s included in this range<\/h3><ul>'+checks+'<\/ul><\/div>';\r\n\r\n    \/\/ tailored (no priced services)\r\n    if(r.monthly <= 0){\r\n      var isSupport = state.services.indexOf('support')>-1;\r\n      if(isSupport){\r\n        var supFeat = ['Trained operators answer in your business name, 24\/7','Simple issues resolved on the spot, the rest escalated','Escalation follows a cascade list you control','Priced from a short scoping assessment with our team'];\r\n        var supChecks = supFeat.map(function(f){ return '<li><span class=\"tick\"><svg viewBox=\"0 0 24 24\"><path d=\"M4 12l5 5L20 6\"\/><\/svg><\/span>'+esc(f)+'<\/li>'; }).join('');\r\n        return '<div class=\"est-hero\">'+\r\n          '<p class=\"est-context\">You picked <b>Support to user<\/b>, customized live assistance for almost anything.<\/p>'+\r\n          '<div class=\"est-bigrange\" style=\"font-size:clamp(28px,5vw,44px);\">Built around your needs<\/div>'+\r\n          '<p class=\"est-savings\">From our 24\/7 command center, our operators handle end-user requests on your behalf and escalate what they can\u2019t resolve. Because every program is scoped differently, software, escalation, reporting, languages and SLAs, we build your price from a short assessment with our team.<\/p>'+\r\n        '<\/div>'+\r\n        '<div class=\"incl\"><h3>What this includes<\/h3><ul>'+supChecks+'<\/ul><\/div>';\r\n      }\r\n      return '<div class=\"est-hero\">'+\r\n        '<p class=\"est-context\">'+context+'<\/p>'+\r\n        '<div class=\"est-bigrange\" style=\"font-size:clamp(30px,5.5vw,48px);\">A tailored plan<\/div>'+\r\n        '<p class=\"est-savings\">Every site is different. A Sirix specialist will recommend the right services and give you an exact price, no guesswork.<\/p>'+\r\n      '<\/div>'+inclBlock;\r\n    }\r\n\r\n    var lh = rangeLoHi(r), lo = lh[0], hi = lh[1];\r\n    var savings = '';\r\n    if(state.services.indexOf('video')>-1){\r\n      var hpd = sched.id==='always' ? 24 : 12;            \/\/ 24\/7 = 24h\/day, off-hours = 12h\/day\r\n      var guard = 30 * hpd * 30 * state.sites;             \/\/ $30\/hr on-site guard equivalent, 30-day month\r\n      var pct = guard>0 ? Math.round((guard - r.monthly)\/guard*100) : 0;\r\n      if(pct<0) pct = 0;\r\n      savings = '<p class=\"est-savings\">This typically replaces <b>'+fmt(guard,r.loc)+'\/mo<\/b> in on-site guard costs, a savings of <b>'+pct+'%<\/b>.<\/p>';\r\n    }\r\n    var disc = 'This is a ballpark based on your inputs, not a formal quote. Final pricing depends on your exact setup, site layout and volume discounts. Continue to get a detailed quote built for your site.';\r\n    return '<div class=\"est-hero\">'+\r\n      '<p class=\"est-context\">'+context+'<\/p>'+\r\n      '<div class=\"est-bigrange\">'+fmt(lo,r.loc)+' - '+fmt(hi,r.loc)+' \/ month<\/div>'+\r\n      savings+\r\n    '<\/div>'+\r\n    inclBlock+\r\n    '<p class=\"est-disc\">'+disc+'<\/p>';\r\n  }\r\n\r\n  function stepContact(){\r\n    if(vipOnly()){\r\n      var vte = totalEscorts();\r\n      return '<div class=\"step-q\">Get your tailored quote<\/div>'+\r\n        '<p class=\"step-sub\">Submit the form below and the Sirix team will follow up with a quote tailored to your sites. Your selections are summarized here for context.<\/p>'+\r\n        '<div class=\"summary-strip\">'+\r\n          '<span class=\"pill\"><b>'+state.sites+'<\/b> site'+(state.sites!==1?'s':'')+'<\/span>'+\r\n          '<span class=\"pill\"><b>'+vte+'<\/b> VIP escort'+(vte!==1?'s':'')+'\/mo<\/span>'+\r\n          '<span class=\"pill\">~<b>'+avgEscortCams()+'<\/b> cams per escort<\/span>'+\r\n          '<span class=\"pill\"><b>'+rangeStr(vipRange())+'<\/b>\/mo estimated<\/span>'+\r\n        '<\/div>'+\r\n        '<div id=\"sirixFreshworksMount\" class=\"freshworks-form-wrap\" aria-live=\"polite\">'+\r\n          '<p class=\"freshworks-loading\">Loading secure quote form...<\/p>'+\r\n        '<\/div>';\r\n    }\r\n    var r = calc();\r\n    var propLabel = (CONFIG.properties.find(function(p){return p.id===state.property;})||{}).label||'Property not selected';\r\n    var svcCount = state.services.length;\r\n    var cLh = rangeLoHi(r);\r\n    var estPill = r.monthly<=0 ? '<span class=\"pill\"><b>Tailored<\/b> plan<\/span>'\r\n      : hasSvc('vip') ? '<span class=\"pill\"><b>'+fmt(cLh[0],r.loc)+' - '+fmt(cLh[1],r.loc)+'<\/b>\/mo estimated<\/span>'\r\n      : '<span class=\"pill\">~'+fmt(r.monthly,r.loc)+'\/mo<\/span>';\r\n    return '<div class=\"step-q\">Get your detailed quote<\/div>'+ \r\n      '<p class=\"step-sub\">Submit the form below and the Sirix team will follow up with a tailored quote. Your calculator selections are summarized here for context.<\/p>'+ \r\n      '<div class=\"summary-strip\">'+\r\n        '<span class=\"pill\">'+esc(propLabel)+'<\/span>'+ \r\n        '<span class=\"pill\"><b>'+svcCount+'<\/b> service'+(svcCount!==1?'s':'')+'<\/span>'+ \r\n        (state.services.indexOf('video')>-1 ? '<span class=\"pill\"><b>'+totalCameras()+'<\/b> cameras<\/span>' : '')+\r\n        (state.services.indexOf('vip')>-1 ? '<span class=\"pill\"><b>'+totalEscorts()+'<\/b> VIP escort'+(totalEscorts()!==1?'s':'')+'\/mo<\/span>' : '')+ \r\n        '<span class=\"pill\"><b>'+state.sites+'<\/b> site'+(state.sites!==1?'s':'')+'<\/span>'+ \r\n        estPill+ \r\n      '<\/div>'+ \r\n      '<div id=\"sirixFreshworksMount\" class=\"freshworks-form-wrap\" aria-live=\"polite\">'+\r\n        '<p class=\"freshworks-loading\">Loading secure quote form...<\/p>'+ \r\n      '<\/div>';\r\n  }\r\n\r\n  function loadFreshworksForm(){\r\n    var mount = root.querySelector('#sirixFreshworksMount');\r\n    if(!mount || mount.getAttribute('data-loaded') === 'true') return;\r\n    mount.setAttribute('data-loaded', 'true');\r\n    mount.innerHTML = '';\r\n\r\n    var iframe = document.createElement('iframe');\r\n    iframe.title = 'Sirix quote form';\r\n    iframe.setAttribute('loading', 'eager');\r\n    iframe.setAttribute('referrerpolicy', 'no-referrer-when-downgrade');\r\n    iframe.style.width = '100%';\r\n    iframe.style.maxWidth = '100%';\r\n    iframe.style.height = '420px';\r\n    iframe.style.minHeight = '0';\r\n    iframe.style.border = '0';\r\n    iframe.style.display = 'block';\r\n    iframe.style.background = 'transparent';\r\n    iframe.style.overflow = 'hidden';\r\n\r\n    iframe.srcdoc = `<!DOCTYPE html>\r\n<html lang=\"ur\">\r\n<head>\r\n<meta charset=\"UTF-8\">\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n<title>Contact Form<\/title>\r\n<style>\r\n  @import url(\"https:\/\/fonts.googleapis.com\/css2?family=Montserrat:wght@400;500;600;700;800&display=swap\");\r\n\r\n  :root{\r\n    --border: #dcdde1;\r\n    --border-focus: #14b8a6;\r\n    --text-dark: #1f2937;\r\n    --text-placeholder: #9aa0a6;\r\n    --required: #e11d2a;\r\n    --radius: 10px;\r\n  }\r\n\r\n  * { box-sizing: border-box; }\r\n\r\n  html{\r\n    margin:0;\r\n    padding:0;\r\n    background:transparent;\r\n    overflow:hidden;\r\n  }\r\n\r\n  body{\r\n    font-family: \"Montserrat\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\r\n    background:transparent;\r\n    margin:0;\r\n    padding: 0;\r\n    min-height:0 !important;\r\n  }\r\n\r\n  \/* ===== Freshworks font lock: force Montserrat inside iframe form ===== *\/\r\n  html,\r\n  body,\r\n  body *,\r\n  .fs-webform-container,\r\n  .fs-webform-container *,\r\n  .fserv-container,\r\n  .fserv-container *,\r\n  .fserv-form,\r\n  .fserv-form *,\r\n  input,\r\n  select,\r\n  textarea,\r\n  button{\r\n    font-family: \"Montserrat\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif !important;\r\n  }\r\n\r\n\r\n  .fs-webform-container,\r\n  .fserv-container,\r\n  .fserv-form{\r\n    min-height:0 !important;\r\n  }\r\n\r\n  .fs-webform-container .fserv-container button {line-height:0 !important;}\r\n\r\n  \/* ===== Outer container ===== *\/\r\n  .fserv-container{\r\n    width: 100% !important;\r\n    max-width: 100% !important;\r\n    margin: 0 !important;\r\n    padding: 32px;\r\n    border-radius: 16px !important;\r\n    box-shadow: none !important;\r\n    box-sizing: border-box;\r\n  }\r\n\r\n  .fs-webform-container .fserv-container{\r\n    border-radius: 16px !important;\r\n    box-shadow: none !important;\r\n  }\r\n\r\n  \/* ===== Grid: turn the stacked fields into 2 columns ===== *\/\r\n  .fserv-form{\r\n    display: grid !important;\r\n    grid-template-columns: 1fr 1fr;\r\n    gap: 20px 24px;\r\n    align-items: start;\r\n    width: 100% !important;\r\n  }\r\n\r\n  \/* Freshworks gives each field wrapper its own fixed width + margin\r\n     (that's what was causing the huge gaps and the columns not lining\r\n     up with the grid). Force every field to fill its grid cell instead. *\/\r\n  .fserv-form .fserv-field,\r\n  .fserv-form .formserv-text-field,\r\n  .fserv-form .formserv-email-field,\r\n  .fserv-form .formserv-tel-field,\r\n  .fserv-form .formserv-select-field,\r\n  .fserv-form .formserv-textarea-field,\r\n  .fserv-form > div{\r\n    width: 100% !important;\r\n    max-width: 100% !important;\r\n    margin: 0 !important;\r\n    box-sizing: border-box;\r\n  }\r\n\r\n  \/* Fields that should take the full row *\/\r\n  .fserv-form .formserv-select-field,\r\n  .fserv-form .formserv-textarea-field,\r\n  .fserv-form > div:last-child{\r\n    grid-column: 1 \/ -1;\r\n  }\r\n\r\n  \/* ===== Labels ===== *\/\r\n  .fserv-label{\r\n    display:block;\r\n    font-weight: 600;\r\n    font-size: 14px;\r\n    color: var(--text-dark);\r\n    margin-bottom: 8px;\r\n  }\r\n\r\n  \/* Force Freshworks labels to 600 weight *\/\r\n  .fs-webform-container .fserv-label{\r\n    font-weight: 600 !important;\r\n  }\r\n\r\n\r\n  \/* Freshworks appends the red asterisk automatically for .fserv-required fields.\r\n     This targets that generated marker. *\/\r\n  .fserv-required .fserv-label::after{\r\n    content: \" *\";\r\n    color: var(--required);\r\n  }\r\n\r\n  \/* ===== Text \/ email inputs ===== *\/\r\n  .fserv-input-text{\r\n    width: 100% !important;\r\n    padding: 13px 16px !important;\r\n    border: 1px solid var(--border) !important;\r\n    border-radius: var(--radius) !important;\r\n    font-size: 15px !important;\r\n    color: var(--text-dark) !important;\r\n    background: #fff !important;\r\n    outline: none !important;\r\n    transition: border-color .15s ease, box-shadow .15s ease;\r\n  }\r\n\r\n  .fserv-input-text::placeholder{\r\n    color: var(--text-placeholder) !important;\r\n    font-weight: 400;\r\n  }\r\n\r\n  .fserv-input-text:focus{\r\n    border-color: var(--border-focus) !important;\r\n    box-shadow: 0 0 0 3px rgba(20,184,166,0.15) !important;\r\n  }\r\n\r\n  \/* ===== Auto-filled estimate summary textarea ===== *\/\r\n  .formserv-textarea-field textarea.fserv-textarea,\r\n  .fserv-textarea{\r\n    width: 100% !important;\r\n    min-height: 150px !important;\r\n    padding: 13px 16px !important;\r\n    border: 1px solid var(--border) !important;\r\n    border-radius: var(--radius) !important;\r\n    font-size: 15px !important;\r\n    line-height: 1.5 !important;\r\n    color: var(--text-dark) !important;\r\n    background: #fff !important;\r\n    outline: none !important;\r\n    resize: vertical !important;\r\n    font-family: inherit !important;\r\n    transition: border-color .15s ease, box-shadow .15s ease;\r\n  }\r\n\r\n  .formserv-textarea-field textarea.fserv-textarea:focus,\r\n  .fserv-textarea:focus{\r\n    border-color: var(--border-focus) !important;\r\n    box-shadow: 0 0 0 3px rgba(20,184,166,0.15) !important;\r\n  }\r\n\r\n\r\n  \/* ===== Hide auto-filled Customer information field from users, but keep it active for backend submission ===== *\/\r\n  .fs-webform-container .formserv-textarea-field{\r\n    position: absolute !important;\r\n    left: -99999px !important;\r\n    top: auto !important;\r\n    width: 1px !important;\r\n    height: 1px !important;\r\n    min-height: 1px !important;\r\n    max-height: 1px !important;\r\n    opacity: 0 !important;\r\n    overflow: hidden !important;\r\n    pointer-events: none !important;\r\n    margin: 0 !important;\r\n    padding: 0 !important;\r\n    border: 0 !important;\r\n  }\r\n\r\n  .fs-webform-container .formserv-textarea-field textarea.fserv-textarea{\r\n    width: 1px !important;\r\n    height: 1px !important;\r\n    min-height: 1px !important;\r\n    max-height: 1px !important;\r\n    padding: 0 !important;\r\n    border: 0 !important;\r\n    resize: none !important;\r\n  }\r\n\r\n  \/* ===== Select2 dropdown (\"Best time to reach you\") ===== *\/\r\n  .select2-container{\r\n    width: 100% !important;\r\n    max-width: 100% !important;\r\n  }\r\n\r\n  .select2-selection--single{\r\n    height: auto !important;\r\n    padding: 13px 16px !important;\r\n    border: 1px solid var(--border) !important;\r\n    border-radius: var(--radius) !important;\r\n    display: flex !important;\r\n    align-items: center;\r\n  }\r\n\r\n  .select2-selection__rendered{\r\n    padding: 0 !important;\r\n    font-size: 15px;\r\n    color: var(--text-dark);\r\n    line-height: normal !important;\r\n  }\r\n\r\n  .select2-selection__arrow{\r\n    height: 100% !important;\r\n    right: 14px !important;\r\n  }\r\n\r\n  .select2-container--default.select2-container--focus .select2-selection--single,\r\n  .select2-container--open .select2-selection--single{\r\n    border-color: var(--border-focus) !important;\r\n    box-shadow: 0 0 0 3px rgba(20,184,166,0.15) !important;\r\n  }\r\n\r\n  \/* ===== Phone field wrapper ===== *\/\r\n  \/* NOTE: the flag\/country-code dropdown lives inside a Web Component's\r\n     shadow DOM (<fsa-country-phone>), so outer CSS like border-radius,\r\n     background, and padding CANNOT reach inside it. Only the visible number\r\n     input next to it (.fserv-input-text) can be styled from here. *\/\r\n  fsa-country-phone{\r\n    display: block;\r\n  }\r\n\r\n  \/* ===== Submit button ===== *\/\r\n  .fserv-form > div:last-child{\r\n    display: flex !important;\r\n    justify-content: center !important;\r\n    width: 100% !important;\r\n  }\r\n\r\n  .fserv-button-submit{\r\n    width: auto !important;\r\n    max-width: 100%;\r\n    box-sizing: border-box;\r\n    background: var(--border-focus) !important;\r\n    color: #fff !important;\r\n    border: none !important;\r\n    padding: 16px 40px !important;\r\n    border-radius: var(--radius) !important;\r\n    font-size: 15px !important;\r\n    font-weight: 600 !important;\r\n    cursor: pointer !important;\r\n    white-space: nowrap;\r\n    text-align: center;\r\n    transition: background .15s ease;\r\n  }\r\n  .fserv-button-submit:hover{\r\n    background:#0d9488 !important;\r\n  }\r\n\r\n  @media (max-width: 640px){\r\n    .fserv-button-submit{\r\n      width: 100% !important;\r\n    }\r\n  }\r\n\r\n  \/* ===== Notifier \/ error banner ===== *\/\r\n  .fs-notifier{\r\n    grid-column: 1 \/ -1;\r\n  }\r\n\r\n  \/* ===== \"Powered by Freshworks\" footer ===== *\/\r\n  .powered-by{\r\n    grid-column: 1 \/ -1;\r\n    text-align: center;\r\n    font-size: 12px;\r\n    color: #9aa0a6;\r\n    margin-top: 8px;\r\n  }\r\n  .powered-by a{\r\n    color: #6b7280;\r\n  }\r\n\r\n  \/* ===== Responsive: mobile ===== *\/\r\n  @media (max-width: 640px){\r\n    .fserv-form{\r\n      grid-template-columns: 1fr !important;\r\n    }\r\n    .fserv-container{\r\n      padding: 20px;\r\n    }\r\n  }\r\n<\/style>\r\n<\/head>\r\n<body>\r\n\r\n<script>\r\n(function(){\r\n  var fsScript = document.createElement('script');\r\n  fsScript.src = 'https:\/\/sirixmonitoring.myfreshworks.com\/crm\/sales\/web_forms\/33c55e0a721e7d475fda78a6c4fba5455718a58d2e6b5e25c4eb5b9298a28f36\/form.js?cb=' + Date.now();\r\n  fsScript.setAttribute('crossorigin', 'anonymous');\r\n  fsScript.id = 'fs_33c55e0a721e7d475fda78a6c4fba5455718a58d2e6b5e25c4eb5b9298a28f36';\r\n  document.body.appendChild(fsScript);\r\n})();\r\n<\\\/script>\r\n\r\n<\/body>\r\n<\/html>`;\r\n\r\n    iframe.addEventListener('load', function(){\r\n      try{\r\n        var doc = iframe.contentDocument || iframe.contentWindow.document;\r\n        var resize = function(){\r\n          try{\r\n            var bodyH = doc.body ? doc.body.scrollHeight : 0;\r\n            var docH = doc.documentElement ? doc.documentElement.scrollHeight : 0;\r\n            var form = doc.querySelector('.fs-webform-container, .fserv-container, .fserv-form');\r\n            var formH = form ? form.getBoundingClientRect().bottom : 0;\r\n            var h = Math.ceil(Math.max(bodyH, docH, formH, 260));\r\n            iframe.style.height = (h + 10) + 'px';\r\n          }catch(e){}\r\n        };\r\n\r\n        var attempts = 0;\r\n        var maxAttempts = 12;\r\n        var submitWireAttempts = 0;\r\n        var maxSubmitWireAttempts = 12;\r\n\r\n        var tryAutofill = function(){\r\n          attempts++;\r\n          var filled = autofillFreshworksTextarea(doc);\r\n          relabelFreshworksVip(doc);\r\n          resize();\r\n\r\n          if(!filled && attempts < maxAttempts){\r\n            setTimeout(tryAutofill, 700);\r\n          }\r\n        };\r\n\r\n        var tryWireSubmit = function(){\r\n          submitWireAttempts++;\r\n          var wired = wireFreshworksSubmitSuccess(doc);\r\n          if(!wired && submitWireAttempts < maxSubmitWireAttempts){\r\n            setTimeout(tryWireSubmit, 700);\r\n          }\r\n        };\r\n\r\n        resize();\r\n        setTimeout(tryAutofill, 700);\r\n        setTimeout(tryWireSubmit, 700);\r\n        setTimeout(resize, 1600);\r\n        setTimeout(resize, 3200);\r\n        setTimeout(resize, 5200);\r\n      }catch(e){}\r\n    });\r\n\r\n    mount.appendChild(iframe);\r\n  }\r\n\r\n\r\n  function stepSuccess(){\r\n    var firstName = (state.name || '').trim().split(\/\\s+\/)[0];\r\n    var thanks = firstName ? ('Thanks, '+esc(firstName)+'.') : 'Thanks.';\r\n    return '<div class=\"success\">'+\r\n      '<div class=\"tick\"><svg viewBox=\"0 0 24 24\"><path d=\"M5 12.5l4.5 4.5L19.5 7\"\/><\/svg><\/div>'+\r\n      '<h2>Your quote is on its way<\/h2>'+\r\n      '<p>'+thanks+' A Sirix specialist will prepare your detailed quote and reach out during your preferred time. Most quotes land within one business day.<\/p>'+\r\n      '<\/div>';\r\n  }\r\n\r\n  var RENDER = [stepProperty, stepServices, stepDetails, stepEstimate, stepContact];\r\n\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 VALIDATION \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  function stepValid(){\r\n    if(state.step===0) return !!state.property;\r\n    if(state.step===1) return state.services.length>0;\r\n    if(state.step===2) return true;\r\n    if(state.step===3) return true;\r\n    if(state.step===4) return true;\r\n    return true;\r\n  }\r\n  function validContact(){\r\n    var okEmail = \/^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$\/.test(state.email.trim());\r\n    var okPhone = state.phone.replace(\/\\D\/g,'').length>=7;\r\n    return state.name.trim().length>1 && okEmail && okPhone;\r\n  }\r\n\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 NAV \/ PAINT \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  var done = false;\r\n  \/* split out of paint() so the services step can refresh the step counter the moment\r\n     \"Not sure\" is toggled, without rebuilding the option grid under the cursor *\/\r\n  function paintProgress(){\r\n    var pos = flowPos();\r\n    var total = flow().length;\r\n    var pct = Math.round(((pos+1)\/total)*100);\r\n    $('#progStep').textContent = 'Step '+(pos+1)+' of '+total+' \u00b7 '+STEP_NAMES[state.step];\r\n    $('#progPct').textContent = pct+'%';\r\n    $('#progFill').style.width = pct+'%';\r\n    return pos;\r\n  }\r\n  function paint(){\r\n    if(done){\r\n      body.innerHTML = stepSuccess();\r\n      var estTopDone = $('.est-top');\r\n      if(estTopDone) estTopDone.style.display = 'none';\r\n      $('.est-foot').style.display = 'none';\r\n      return;\r\n    }\r\n    var estTopActive = $('.est-top');\r\n    if(estTopActive) estTopActive.style.display = '';\r\n    $('.est-foot').style.display = '';\r\n    body.innerHTML = RENDER[state.step]();\r\n    var pos = paintProgress();\r\n    btnBack.classList.toggle('hidden', pos===0);\r\n    $('.est-foot').classList.toggle('contact-mode', state.step===4);\r\n    btnNext.style.display = state.step===4 ? 'none' : '';\r\n    btnNext.innerHTML = state.step===3\r\n      ? 'Looks good, continue<svg viewBox=\"0 0 24 24\"><path d=\"M9 18l6-6-6-6\"\/><\/svg>'\r\n      : 'Continue<svg viewBox=\"0 0 24 24\"><path d=\"M9 18l6-6-6-6\"\/><\/svg>';\r\n    btnNext.disabled = !stepValid();\r\n    wire();\r\n    if(state.step===4) loadFreshworksForm();\r\n  }\r\n\r\n  function wire(){\r\n    \/\/ property\r\n    body.querySelectorAll('[data-prop]').forEach(function(el){\r\n      el.addEventListener('click', function(){ state.property = el.getAttribute('data-prop'); paint(); });\r\n    });\r\n    \/\/ services: all options toggle only. No service should auto-advance.\r\n    body.querySelectorAll('[data-svc]').forEach(function(el){\r\n      el.addEventListener('click', function(){\r\n        var id = el.getAttribute('data-svc');\r\n        var i = state.services.indexOf(id);\r\n\r\n        if(i > -1){\r\n          state.services.splice(i, 1);\r\n        }else{\r\n          state.services.push(id);\r\n        }\r\n\r\n        el.classList.toggle('sel', state.services.indexOf(id) > -1);\r\n        btnNext.disabled = !stepValid();\r\n        paintProgress();   \/\/ the \"not sure\" branch has one step fewer\r\n      });\r\n    });\r\n    \/\/ details\r\n    \/\/ setup step: site count stepper + per-site name & camera sliders\r\n    var sMinus = $('#siteMinus'), sPlus = $('#sitePlus');\r\n    if(sMinus){\r\n      sMinus.disabled = state.sites<=1;\r\n      sMinus.addEventListener('click', function(){ if(state.sites>1){ syncSites(state.sites-1); paint(); } });\r\n      sPlus.addEventListener('click', function(){ if(state.sites<10){ syncSites(state.sites+1); paint(); } });\r\n    }\r\n    body.querySelectorAll('.siteName').forEach(function(el){\r\n      el.addEventListener('input', function(){ state.siteData[+el.getAttribute('data-i')].name = el.value; });\r\n    });\r\n    body.querySelectorAll('.siteCam').forEach(function(el){\r\n      el.addEventListener('input', function(){\r\n        var i = +el.getAttribute('data-i'), v = +el.value;\r\n        state.siteData[i].cameras = v;\r\n        var lbl = body.querySelector('.siteCamVal[data-i=\"'+i+'\"]');\r\n        if(lbl) lbl.innerHTML = v + (v>=100?'+':'') + ' <small>cameras<\/small>';\r\n      });\r\n    });\r\n    \/\/ VIP safe passage: escorts per site + cameras per escort\r\n    var updateVipNote = function(i){\r\n      var n = body.querySelector('.vip-note[data-i=\"'+i+'\"]');\r\n      if(n) n.textContent = vipSiteNote(state.siteData[i]);\r\n    };\r\n    body.querySelectorAll('.vipCam').forEach(function(el){\r\n      el.addEventListener('input', function(){\r\n        var i = +el.getAttribute('data-i'), v = +el.value;\r\n        state.siteData[i].escortCams = v;\r\n        var lbl = body.querySelector('.vipCamVal[data-i=\"'+i+'\"]');\r\n        if(lbl) lbl.innerHTML = v + (v>=100?'+':'') + ' <small>cams<\/small>';\r\n        updateVipNote(i);\r\n      });\r\n    });\r\n    body.querySelectorAll('.vipMinus, .vipPlus').forEach(function(el){\r\n      var i = +el.getAttribute('data-i');\r\n      var isPlus = el.classList.contains('vipPlus');\r\n      if(!isPlus) el.disabled = state.siteData[i].escorts <= 1;\r\n      el.addEventListener('click', function(){\r\n        var n = state.siteData[i].escorts + (isPlus ? 1 : -1);\r\n        if(n < 1 || n > CONFIG.vip.maxEscorts) return;\r\n        state.siteData[i].escorts = n;\r\n        var num = body.querySelector('.vipNum[data-i=\"'+i+'\"]');\r\n        if(num) num.textContent = n;\r\n        var minus = body.querySelector('.vipMinus[data-i=\"'+i+'\"]');\r\n        if(minus) minus.disabled = n <= 1;\r\n        updateVipNote(i);\r\n      });\r\n    });\r\n    \/\/ tier options (intercom \/ gate)\r\n    body.querySelectorAll('.tier-opt').forEach(function(el){\r\n      el.addEventListener('click', function(){\r\n        var g = el.getAttribute('data-tiergroup');\r\n        state[g+'Tier'] = el.getAttribute('data-tierid');\r\n        body.querySelectorAll('.tier-opt[data-tiergroup=\"'+g+'\"]').forEach(function(x){ x.classList.toggle('sel', x===el); });\r\n      });\r\n    });\r\n    \/\/ lone worker users stepper\r\n    var uMinus = $('#userMinus'), uPlus = $('#userPlus');\r\n    if(uMinus){\r\n      var uupd = function(){ $('#userNum').textContent = state.loneUsers; uMinus.disabled = state.loneUsers<=1; };\r\n      uMinus.addEventListener('click', function(){ if(state.loneUsers>1){ state.loneUsers--; uupd(); } });\r\n      uPlus.addEventListener('click', function(){ if(state.loneUsers<200){ state.loneUsers++; uupd(); } });\r\n      uupd();\r\n    }\r\n    body.querySelectorAll('[data-sched]').forEach(function(el){\r\n      el.addEventListener('click', function(){\r\n        state.schedule = el.getAttribute('data-sched');\r\n        body.querySelectorAll('[data-sched]').forEach(function(x){ x.classList.toggle('sel', x===el); });\r\n      });\r\n    });\r\n    var loc = $('#locInput');\r\n    if(loc) loc.addEventListener('input', function(){ state.locationText = loc.value; });\r\n    \/\/ optional note (\"not sure\" branch): stored as typed, never gates Continue\r\n    var uNote = $('#unsureNote');\r\n    if(uNote) uNote.addEventListener('input', function(){ state.unsureNote = uNote.value; });\r\n    \/\/ Freshworks owns the contact form on the final step.\r\n  }\r\n\r\n  btnNext.addEventListener('click', function(){\r\n    if(!stepValid()) return;\r\n    var f = flow(), pos = flowPos();\r\n    if(pos >= f.length-1){ return; }\r\n    state.step = f[pos+1]; paint();\r\n  });\r\n  btnBack.addEventListener('click', function(){\r\n    var f = flow(), pos = flowPos();\r\n    if(pos > 0){ state.step = f[pos-1]; paint(); }\r\n  });\r\n\r\n  paint();\r\n})();\r\n\r\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a7f3c21 elementor-widget elementor-widget-html\" data-id=\"a7f3c21\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<script bv-exclude=\"true\" data-cfasync=\"false\" data-no-optimize=\"1\" data-no-defer=\"1\">\n\/**\n * Sirix \u2014 Security Cost Calculator: attribution fields chhupao + bharo\n *\n * Is page ka aakhri step ka Freshsales web form ek `srcdoc` iframe ke andar render\n * hota hai (#sirixFreshworksMount > iframe). Page-level ka jo \"Sirix UTM fill\"\n * snippet baqi forms par chalta hai wo sirf main document scan karta hai, is liye\n * iframe ke andar wale UTM \/ Landing Page \/ First Touch Date fields na chhupte hain\n * aur na bharte hain \u2014 visitor ko khaali fields nazar aate hain.\n *\n * Ye snippet wohi kaam iframe ke andar karta hai:\n *   1. iframe ke document mein <style> daal kar pehle paint par hi fields chhupata hai,\n *   2. `sirix_attr` cookie (jo \"Sirix UTM Capture\" landing par likhti hai) se unki\n *      value bhar deta hai \u2014 cookie wahi origin hai, is liye srcdoc iframe mein bhi parhi jati hai,\n *   3. field ka poora wrapper (label samet) display:none kar deta hai.\n *\n * Fields Freshsales par VISIBLE hi rehni chahiyen (Hidden field bina default value\n * save nahi hoti aur phir har contact par wohi default chala jata hai) \u2014 chhupana\n * sirf browser mein hota hai, value phir bhi submit hoti hai.\n *\n * Kahan rakhna hai: isi page par ek alag Elementor HTML widget (calculator ke baad,\n * page mein kahin bhi chalega). Main document ke maujooda UTM snippet ko chhedne ki\n * zaroorat nahi \u2014 ye sirf iframes ke andar kaam karta hai, is liye dono takraate nahi.\n *\n * Debug (browser console):\n *   sirixCalcFormFill()  \u2014 abhi dobara bharo\/chhupao, bhari hui fields ka count do\n *   sirixCalcFormDebug() \u2014 har field ka name \/ value \/ hidden state table mein\n *\/\n(function () {\n  var MAP = {\n    cf_utm_source:       'source',\n    cf_utm_medium:       'medium',\n    cf_utm_campaign:     'campaign',\n    cf_utm_term:         'term',\n    cf_utm_content:      'content',\n    cf_utm_id:           'id',\n    cf_landing_page:     'lp',\n    cf_first_touch_date: 'ts'\n  };\n\n  \/\/ Pehle paint ka guard: JS wrapper hata deta hai, lekin us se pehle ki ek jhalak\n  \/\/ bhi visitor ko nazar na aaye. `:has()` na chale to input khud chhup jata hai.\n  var GUARD_CSS = [\n    'input[name*=\"cf_utm_\"],',\n    'input[id*=\"cf_utm_\"],',\n    'input[name*=\"cf_landing_page\"],',\n    'input[id*=\"cf_landing_page\"],',\n    'input[name*=\"cf_first_touch_date\"],',\n    'input[id*=\"cf_first_touch_date\"]{display:none !important;}',\n    '.fserv-field:has(input[name*=\"cf_utm_\"]),',\n    '.fserv-field:has(input[name*=\"cf_landing_page\"]),',\n    '.fserv-field:has(input[name*=\"cf_first_touch_date\"]){display:none !important;}'\n  ].join('');\n\n  function readCookie() {\n    var m = \/(?:^|;\\s*)sirix_attr=([^;]*)\/.exec(document.cookie);\n    if (!m) return null;\n    try { return JSON.parse(decodeURIComponent(m[1])); } catch (e) { return null; }\n  }\n\n  \/\/ Sirf same-origin iframes \u2014 srcdoc\/about:blank parent ka origin le lete hain,\n  \/\/ baqi (cross-origin) par access throw karta hai, jise chup-chaap chhor dete hain.\n  function accessibleDocs() {\n    var docs = [];\n    var frames = document.querySelectorAll('iframe');\n    for (var i = 0; i < frames.length; i++) {\n      try {\n        var d = frames[i].contentDocument;\n        if (d && d.body) docs.push(d);\n      } catch (e) { \/* cross-origin \u2014 chhoro *\/ }\n    }\n    return docs;\n  }\n\n  function injectGuard(doc) {\n    if (doc.getElementById('sirix-attr-guard')) return;\n    var head = doc.head || doc.documentElement;\n    if (!head) return;\n    var style = doc.createElement('style');\n    style.id = 'sirix-attr-guard';\n    style.textContent = GUARD_CSS;\n    head.appendChild(style);\n  }\n\n  function nodesFor(doc, key) {\n    var found = [];\n    var all = doc.querySelectorAll('input, textarea, select');\n    for (var i = 0; i < all.length; i++) {\n      var el = all[i];\n      var hay = ((el.getAttribute('name') || '') + ' ' + (el.getAttribute('id') || '')).toLowerCase();\n      if (hay.indexOf(key) !== -1) found.push(el);\n    }\n    return found;\n  }\n\n  \/\/ Native setter + poora event set \u2014 kuch form frameworks apni internal value sirf\n  \/\/ inhi events par sync karte hain, seedhi el.value assignment par nahi.\n  \/\/ `silent` date picker ke liye hai: us par blur\/change bhejne se picker apni\n  \/\/ parse-nakaami ke sabab value khud mita deta hai.\n  function setValue(el, val, silent) {\n    if (el.value === val) return false;\n    var win = el.ownerDocument.defaultView || window;\n    var proto = el.tagName === 'TEXTAREA' ? win.HTMLTextAreaElement.prototype : win.HTMLInputElement.prototype;\n    var desc = Object.getOwnPropertyDescriptor(proto, 'value');\n    if (desc && desc.set) { desc.set.call(el, val); } else { el.value = val; }\n    el.setAttribute('value', val);\n    if (!silent) {\n      ['input', 'change', 'keyup', 'blur'].forEach(function (type) {\n        el.dispatchEvent(new win.Event(type, { bubbles: true }));\n      });\n    }\n    return true;\n  }\n\n  \/\/ Field ka apna wrapper (label samet) chhupate hain: upar chalte jao jab tak\n  \/\/ ancestor mein sirf yehi ek input ho \u2014 us se upar dusre fields shamil ho jayenge.\n  function hideField(el) {\n    var node = el;\n    for (var i = 0; i < 6; i++) {\n      var parent = node.parentElement;\n      if (!parent || parent.tagName === 'FORM' || parent.tagName === 'BODY') break;\n      if (parent.querySelectorAll('input, textarea, select').length > 1) break;\n      node = parent;\n    }\n    if (node.style.display !== 'none') node.style.setProperty('display', 'none', 'important');\n  }\n\n  \/\/ Date field ka format har account par alag hota hai. Agar input HTML date hai to\n  \/\/ ISO hi chahiye; warna placeholder se andaza lagate hain (DD\/MM\/YYYY vs MM\/DD\/YYYY).\n  function formatDate(el, iso) {\n    var m = \/^(\\d{4})-(\\d{2})-(\\d{2})$\/.exec(iso);\n    if (!m) return iso;\n    var y = m[1], mo = m[2], d = m[3];\n    if ((el.getAttribute('type') || '').toLowerCase() === 'date') return iso;\n    var hint = (el.getAttribute('placeholder') || el.getAttribute('data-format') || '').toLowerCase();\n    var di = hint.indexOf('dd'), mi = hint.indexOf('mm'), yi = hint.indexOf('yy');\n    if (di === -1 || mi === -1) return iso;\n    var sep = hint.indexOf('-') !== -1 ? '-' : '\/';\n    if (yi !== -1 && yi < di && yi < mi) return y + sep + mo + sep + d;\n    return di < mi ? d + sep + mo + sep + y : mo + sep + d + sep + y;\n  }\n\n  \/\/ Date field ka picker apni value khud sambhalta hai aur hamari likhi value submit\n  \/\/ par ginta nahi. Is liye us input ko disable kar ke (disabled inputs serialize\n  \/\/ nahi hote) usi `name` se apna saaf hidden input daal dete hain.\n  function setDateField(doc, el, val) {\n    var name = el.getAttribute('name');\n    if (!name) return false;\n    var shadow = doc.querySelector('input[data-sirix-shadow=\"1\"][name=\"' + name.replace(\/\"\/g, '\\\\\"') + '\"]');\n    if (!shadow) {\n      el.disabled = true;\n      shadow = doc.createElement('input');\n      shadow.type = 'hidden';\n      shadow.setAttribute('data-sirix-shadow', '1');\n      shadow.setAttribute('name', name);\n      el.parentNode.insertBefore(shadow, el.nextSibling);\n    }\n    if (shadow.value === val) return false;\n    shadow.value = val;\n    shadow.setAttribute('value', val);\n    return true;\n  }\n\n  function sweepDoc(doc, data) {\n    injectGuard(doc);\n    var filled = 0;\n    Object.keys(MAP).forEach(function (key) {\n      var val = data ? data[MAP[key]] : null;\n      nodesFor(doc, key).forEach(function (el) {\n        hideField(el);\n        if (!val) return;\n        if (key === 'cf_first_touch_date') {\n          if (setDateField(doc, el, formatDate(el, String(val)))) filled++;\n          return;\n        }\n        if (setValue(el, String(val))) filled++;\n      });\n    });\n    watch(doc);\n    return filled;\n  }\n\n  \/\/ Form JS se render hota hai aur baad mein dobara draw bhi ho sakta hai \u2014 is liye\n  \/\/ har iframe document par ek hi dafa observer lagate hain.\n  function watch(doc) {\n    if (doc.__sirixAttrWatched || !window.MutationObserver) return;\n    doc.__sirixAttrWatched = true;\n    var pending = null;\n    new MutationObserver(function () {\n      if (pending) return;\n      pending = setTimeout(function () { pending = null; sweep(); }, 200);\n    }).observe(doc.documentElement, { childList: true, subtree: true });\n\n    ['mousedown', 'click', 'submit'].forEach(function (type) {\n      doc.addEventListener(type, function () { sweep(); }, true);\n    });\n  }\n\n  function sweep() {\n    var data = readCookie();\n    var filled = 0;\n    accessibleDocs().forEach(function (doc) { filled += sweepDoc(doc, data); });\n    return filled;\n  }\n\n  function start() {\n    sweep();\n\n    \/\/ Form aakhri step par banta hai, is liye main document par bhi nazar rakhni\n    \/\/ hai \u2014 naya iframe add hote hi sweep chal jaye.\n    if (window.MutationObserver) {\n      var pending = null;\n      new MutationObserver(function () {\n        if (pending) return;\n        pending = setTimeout(function () { pending = null; sweep(); }, 200);\n      }).observe(document.documentElement, { childList: true, subtree: true });\n    }\n\n    \/\/ iframe ka `load` mutation nahi hota \u2014 halka polling chalta rehta hai.\n    setInterval(sweep, 1000);\n  }\n\n  window.sirixCalcFormFill = sweep;\n\n  window.sirixCalcFormDebug = function () {\n    var data = readCookie();\n    var rows = [];\n    accessibleDocs().forEach(function (doc, idx) {\n      Object.keys(MAP).forEach(function (key) {\n        var want = data ? data[MAP[key]] : undefined;\n        var els = nodesFor(doc, key);\n        if (!els.length) {\n          rows.push({ frame: idx, field: key, wanted: want, found: 'NO INPUT' });\n          return;\n        }\n        els.forEach(function (el) {\n          var box = el.getBoundingClientRect();\n          rows.push({\n            frame:  idx,\n            field:  key,\n            wanted: want,\n            found:  'yes',\n            name:   el.getAttribute('name') || '',\n            type:   el.getAttribute('type') || '',\n            value:  el.value,\n            hidden: (box.width === 0 && box.height === 0) ? 'yes' : 'NO'\n          });\n        });\n      });\n      var shadows = doc.querySelectorAll('input[data-sirix-shadow=\"1\"]');\n      for (var i = 0; i < shadows.length; i++) {\n        rows.push({ frame: idx, field: 'shadow', found: 'yes', name: shadows[i].name, value: shadows[i].value, hidden: 'yes' });\n      }\n    });\n    if (console.table) { console.table(rows); } else { console.log(rows); }\n    return rows.length;\n  };\n\n  if (document.readyState !== 'loading') { start(); }\n  else { document.addEventListener('DOMContentLoaded', start); }\n})();\n<\/script>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Obtenez le devis de s\u00e9curit\u00e9 de votre entreprise en quelques minutes. R\u00e9pondez \u00e0 quelques questions rapides sur votre bien immobilier et obtenez instantan\u00e9ment un devis personnalis\u00e9 pour une surveillance de s\u00e9curit\u00e9 24 h\/24, 7 j\/7. Pas d'appels commerciaux, sans engagement. Devis instantan\u00e9 \u00c9tape 1 sur 5 \u00b7 Bien immobilier 20% Retour Continuer<\/p>","protected":false},"author":29,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-103511","page","type-page","status-publish","hentry"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v28.7 (Yoast SEO v28.7) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Business Security Systems Cost Calculator - Sirix<\/title>\n<meta name=\"description\" content=\"Get an instant quote for your business security system. Try the free Sirix cost calculator today, no obligation.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/sirixmonitoring.com\/fr-ca\/calculateur-de-couts-de-securite\/\" \/>\n<meta property=\"og:locale\" content=\"fr_CA\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Business Security Systems Cost Calculator - Sirix\" \/>\n<meta property=\"og:description\" content=\"Get an instant quote for your business security system. Try the free Sirix cost calculator today, no obligation.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/sirixmonitoring.com\/fr-ca\/calculateur-de-couts-de-securite\/\" \/>\n<meta property=\"og:site_name\" content=\"Sirix Monitoring\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/sirixmonitoring\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-15T15:30:07+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/sirixmonitoring.com\/wp-content\/uploads\/2026\/01\/Sirix-logo-for-home-page-table.svg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Security cost calculator\" \/>\n<meta name=\"twitter:label1\" content=\"Estimation du temps de lecture\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minute\" \/>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Calculateur de co\u00fbt des syst\u00e8mes de s\u00e9curit\u00e9 pour entreprises - Sirix","description":"Obtenez un devis instantan\u00e9 pour le syst\u00e8me de s\u00e9curit\u00e9 de votre entreprise. Essayez d\u00e8s aujourd'hui le calculateur de co\u00fbts gratuit de Sirix, sans engagement.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/sirixmonitoring.com\/fr-ca\/calculateur-de-couts-de-securite\/","og_locale":"fr_CA","og_type":"article","og_title":"Business Security Systems Cost Calculator - Sirix","og_description":"Get an instant quote for your business security system. Try the free Sirix cost calculator today, no obligation.","og_url":"https:\/\/sirixmonitoring.com\/fr-ca\/calculateur-de-couts-de-securite\/","og_site_name":"Sirix Monitoring","article_publisher":"https:\/\/www.facebook.com\/sirixmonitoring","article_modified_time":"2026-10-15T15:30:07+00:00","og_image":[{"url":"https:\/\/sirixmonitoring.com\/wp-content\/uploads\/2026\/01\/Sirix-logo-for-home-page-table.svg","type":"","width":"","height":""}],"twitter_card":"summary_large_image","twitter_title":"Security cost calculator","twitter_misc":{"Estimation du temps de lecture":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/sirixmonitoring.com\/security-cost-calculator\/","url":"https:\/\/sirixmonitoring.com\/security-cost-calculator\/","name":"Calculateur de co\u00fbt des syst\u00e8mes de s\u00e9curit\u00e9 pour entreprises - Sirix","isPartOf":{"@id":"https:\/\/sirixmonitoring.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/sirixmonitoring.com\/security-cost-calculator\/#primaryimage"},"image":{"@id":"https:\/\/sirixmonitoring.com\/security-cost-calculator\/#primaryimage"},"thumbnailUrl":"https:\/\/sirixmonitoring.com\/wp-content\/uploads\/2026\/01\/Sirix-logo-for-home-page-table.svg","datePublished":"2026-07-13T11:34:14+00:00","dateModified":"2026-10-15T15:30:07+00:00","description":"Obtenez un devis instantan\u00e9 pour le syst\u00e8me de s\u00e9curit\u00e9 de votre entreprise. Essayez d\u00e8s aujourd'hui le calculateur de co\u00fbts gratuit de Sirix, sans engagement.","breadcrumb":{"@id":"https:\/\/sirixmonitoring.com\/security-cost-calculator\/#breadcrumb"},"inLanguage":"fr-CA","potentialAction":[{"@type":"ReadAction","target":["https:\/\/sirixmonitoring.com\/security-cost-calculator\/"]}]},{"@type":"ImageObject","inLanguage":"fr-CA","@id":"https:\/\/sirixmonitoring.com\/security-cost-calculator\/#primaryimage","url":"https:\/\/sirixmonitoring.com\/wp-content\/uploads\/2026\/01\/Sirix-logo-for-home-page-table.svg","contentUrl":"https:\/\/sirixmonitoring.com\/wp-content\/uploads\/2026\/01\/Sirix-logo-for-home-page-table.svg"},{"@type":"BreadcrumbList","@id":"https:\/\/sirixmonitoring.com\/security-cost-calculator\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/sirixmonitoring.com\/"},{"@type":"ListItem","position":2,"name":"Security cost calculator"}]},{"@type":"WebSite","@id":"https:\/\/sirixmonitoring.com\/#website","url":"https:\/\/sirixmonitoring.com\/","name":"Sirix","description":"Services et solutions de s\u00e9curit\u00e9 pour les entreprises","publisher":{"@id":"https:\/\/sirixmonitoring.com\/#organization"},"alternateName":"Sirix Monitoring","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/sirixmonitoring.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fr-CA"},{"@type":"Organization","@id":"https:\/\/sirixmonitoring.com\/#organization","name":"Sirix","alternateName":"Sirix Monitoring","url":"https:\/\/sirixmonitoring.com\/","logo":{"@type":"ImageObject","inLanguage":"fr-CA","@id":"https:\/\/sirixmonitoring.com\/#\/schema\/logo\/image\/","url":"https:\/\/sirixmonitoring.com\/wp-content\/uploads\/2023\/05\/sirix-logo-1.png","contentUrl":"https:\/\/sirixmonitoring.com\/wp-content\/uploads\/2023\/05\/sirix-logo-1.png","width":711,"height":277,"caption":"Sirix"},"image":{"@id":"https:\/\/sirixmonitoring.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/sirixmonitoring","https:\/\/mastodon.social\/@sirixmonitoringofficial","https:\/\/www.linkedin.com\/company\/sirix\/","https:\/\/www.youtube.com\/@sirix_monitoring\/videos"],"description":"Sirix Monitoring est le prestataire de r\u00e9f\u00e9rence en Am\u00e9rique du Nord pour les services de vid\u00e9osurveillance \u00e0 distance en direct 24 h\/24 et 7 j\/7, au service des entreprises aux \u00c9tats-Unis et au Canada. Nous combinons une technologie de d\u00e9tection bas\u00e9e sur l\u2019intelligence artificielle avec l\u2019intervention d\u2019op\u00e9rateurs humains professionnels dans notre centre de contr\u00f4le afin d\u2019assurer une surveillance de s\u00e9curit\u00e9 en temps r\u00e9el et une intervention rapide en cas d\u2019incident. Nos services comprennent la surveillance vid\u00e9o \u00e0 distance, l'analyse vid\u00e9o dans le cloud, la v\u00e9rification vid\u00e9o des alarmes, les rondes de surveillance virtuelles, le contr\u00f4le d'acc\u00e8s, les interventions vocales, la surveillance des interphones d'urgence, la surveillance continue, et bien plus encore. Nous accompagnons un large \u00e9ventail de secteurs, notamment les concessionnaires automobiles, les chantiers de construction, les magasins de d\u00e9tail, les parkings, les parcs \u00e0 camions, les entreprises du secteur du cannabis, les entrep\u00f4ts en libre-service, les immeubles r\u00e9sidentiels collectifs et bien d\u2019autres encore. En tant que prestataire de services de s\u00e9curit\u00e9 enti\u00e8rement agr\u00e9\u00e9 (num\u00e9ro de licence BSP : SE 20030247), nous proposons \u00e9galement des solutions de surveillance en marque blanche aux entreprises de s\u00e9curit\u00e9 \u00e0 la recherche d\u2019un soutien technique fiable. Chez Sirix, la fiabilit\u00e9 est notre engagement fondamental.","legalName":"Sirix Monitoring","numberOfEmployees":{"@type":"QuantitativeValue","minValue":"501","maxValue":"1000"}}]}},"_links":{"self":[{"href":"https:\/\/sirixmonitoring.com\/fr-ca\/wp-json\/wp\/v2\/pages\/103511","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sirixmonitoring.com\/fr-ca\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/sirixmonitoring.com\/fr-ca\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/sirixmonitoring.com\/fr-ca\/wp-json\/wp\/v2\/users\/29"}],"replies":[{"embeddable":true,"href":"https:\/\/sirixmonitoring.com\/fr-ca\/wp-json\/wp\/v2\/comments?post=103511"}],"version-history":[{"count":20,"href":"https:\/\/sirixmonitoring.com\/fr-ca\/wp-json\/wp\/v2\/pages\/103511\/revisions"}],"predecessor-version":[{"id":107303,"href":"https:\/\/sirixmonitoring.com\/fr-ca\/wp-json\/wp\/v2\/pages\/103511\/revisions\/107303"}],"wp:attachment":[{"href":"https:\/\/sirixmonitoring.com\/fr-ca\/wp-json\/wp\/v2\/media?parent=103511"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}