1<!doctype html > 2<html xmlns="http://www.w3.org/1999/xhtml" lang="en" 3 class=""> 4<head> 5 <meta charset="utf-8"> 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
43<script type="text/javascript"> 44 window._currentDevice = 'desktop'; 45 window.Parameters = window.Parameters || { 46 HomeUrl: 'https://www.huffstreeservice.com/', 47 48 SystemID: 'US_HIBU_PRODUCTION', 49 SiteAlias: '7720a79493434d7dbf0e283d7c6423e7', 50 SiteType: atob('RFVEQU9ORQ=='), 51 PublicationDate: 'Oct 06, 2026', 52 ExternalUid: '700149502', 53 IsSiteMultilingual: false, 54 InitialPostAlias: '', 55 InitialPostPageUuid: '', 56 InitialDynamicItem: '', 57 DynamicPageInfo: { 58 isDynamicPage: false, 59 base64JsonRowData: 'null', 60 }, 61 InitialPageAlias: 'home', 62 InitialPageUuid: '0f52bef5eae544d4a9b9525345e78a70', 63 InitialPageId: '117866345', 64 InitialEncodedPageAlias: 'aG9tZQ==', 65 InitialHeaderUuid: '87d82438bc104577b873df0e900a08fd', 66 CurrentPageUrl: '', 67 IsCurrentHomePage: true, 68 ThemeVersion: '500000', 69 DefaultPageAlias: '', 70 RemoveDID: true, 71 WidgetStyleID: null, 72 IsHeaderFixed: false, 73 IsHeaderSkinny: false, 74 StorePagesUrls: 'e30=', 75 IsNewStore: 'false', 76 StorePath: '', 77 StoreId: 'null', 78 StoreVersion: 0, 79 StoreBaseUrl: '', 80 StoreCleanUrl: true, 81 StoreDisableScrolling: true, 82 IsStoreSuspended: false, 83 showCookieNotification: false, 84 cookiesNotificationMarkup: 'null', 85 translatedPageUrl: '', 86 sidebarPosition: 'NA', 87 currentLanguage: 'en', 88 currentLocale: 'en', 89 NavItems: '{}', 90 91 mapConsent: { 92 message: 'This content is served by a third party, {0}. If enabled, {0} may collect information about your activity.', 93 enable: 'Enable' 94 }, 95 NavigationAreaParams: { 96 ShowBackToHomeOnInnerPages: true, 97 NavbarSize: -1, 98 NavbarLiveHomePage: 'https://www.huffstreeservice.com/', 99 NavbarSelector: '#dmNav:has(a)', 100 SubNavbarSelector: '#subnav_main' 101 }, 102 planID: '771', 103 disableTracking: false, 104 pageType: 'FROM_SCRATCH', 105 isRuntimeServer: true, 106 isInEditor: false, 107 isInPreview: false, 108 hasNativeStore: false, 109 defaultLang: 'en', 110 hamburgerMigration: null, 111 isFlexSite: true 112 }; 113 114 window.Parameters.LayoutID = {}; 115 window.Parameters.LayoutID[window._currentDevice] = 30; 116 window.Parameters.LayoutVariationID = {}; 117 window.Parameters.LayoutVariationID[window._currentDevice] = 5; 118</script>
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141<!-- Injecting site-wide to the head --> 142 143 144<meta name="google-site-verification" content="gfaMnWy90GfwFl4YJumE8771AHkxPSTNmuW0WqmlRu0" data-swh-uuid="8c94f3f3acb4463c99659c45401502dd"/> 145 146 147 148<!-- End Injecting site-wide to the head --> 149 150 151 152 153 154<meta name="d-service-worker" content="register"> 155 156 157 158<link rel="canonical" href="https://www.huffstreeservice.com/"> 159 160<meta id="view" name="viewport" content="initial-scale=1, minimum-scale=1, maximum-scale=5, viewport-fit=cover"> 161<meta name="dm:lcp-preload" content="dm:lcp-frozen"> 162<meta name="apple-mobile-web-app-capable" content="yes"> 163 164 165 166<link rel="icon" type="image/x-icon" href="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/site_favicon_16_1790099921726.ico"/> 167 168 169<link rel="preconnect" href="https://le-cdn.hibuwebsites.com"/> 170<link rel="preconnect" href="https://cdn.hibuwebsites.com" crossorigin/> 171<link rel="preconnect" href="https://static-res-cdn.websites.hibu.com"/> 172<link rel="preconnect" href="https://cdn.hibuwebsites.com"/> 173 174 175 176
177<script id='d-js-dmapi'> 178 window.SystemID = 'US_HIBU_PRODUCTION'; 179 180 if (!window.dmAPI) { 181 window.dmAPI = { 182 registerExternalRuntimeComponent: function () { 183 }, 184 getCurrentDeviceType: function () { 185 return window._currentDevice; 186 }, 187 runOnReady: (ns, fn) => { 188 const safeFn = dmAPI.toSafeFn(fn); 189 ns = ns || 'global_' + Math.random().toString(36).slice(2, 11); 190 const eventName = 'afterAjax.' + ns; 191 192 if (document.readyState === 'complete') { 193 $.DM.events.off(eventName).on(eventName, safeFn); 194 setTimeout(function () { 195 safeFn({ 196 isAjax: false, 197 }); 198 }, 0); 199 } else { 200 window?.waitForDeferred?.('dmAjax', () => { 201 $.DM.events.off(eventName).on(eventName, safeFn); 202 safeFn({ 203 isAjax: false, 204 }); 205 }); 206 } 207 }, 208 toSafeFn: (fn) => { 209 if (fn?.safe) { 210 return fn; 211 } 212 const safeFn = function (...args) { 213 try { 214 return fn?.apply(null, args); 215 } catch (e) { 216 console.log('function failed ' + e.message); 217 } 218 }; 219 safeFn.safe = true; 220 return safeFn; 221 } 222 }; 223 } 224 225 if (!window.requestIdleCallback) { 226 window.requestIdleCallback = function (fn) { 227 setTimeout(fn, 0); 228 } 229 } 230</script>
230 231 232 233 234 235 236 237 238
239<script id="d-js-load-css"> 240/** 241 * There are a few <link> tags with CSS resource in them that are preloaded in the page 242 * in each of those there is a "onload" handler which invokes the loadCSS callback 243 * defined here. 244 * We are monitoring 3 main CSS files - the runtime, the global and the page. 245 * When each load we check to see if we can append them all in a batch. If threre 246 * is no page css (which may happen on inner pages) then we do not wait for it 247 */ 248(function () { 249 let cssLinks = {}; 250 function loadCssLink(link) { 251 link.onload = null; 252 link.rel = "stylesheet"; 253 link.type = "text/css"; 254 } 255 256 function checkCss() { 257 const pageCssLink = document.querySelector("[id*='CssLink']"); 258 const widgetCssLink = document.querySelector("[id*='widgetCSS']"); 259 260 if (cssLinks && cssLinks.runtime && cssLinks.global && (!pageCssLink || cssLinks.page) && (!widgetCssLink || cssLinks.widget)) { 261 const storedRuntimeCssLink = cssLinks.runtime; 262 const storedPageCssLink = cssLinks.page; 263 const storedGlobalCssLink = cssLinks.global; 264 const storedWidgetCssLink = cssLinks.widget; 265 266 storedGlobalCssLink.disabled = true; 267 loadCssLink(storedGlobalCssLink); 268 269 if (storedPageCssLink) { 270 storedPageCssLink.disabled = true; 271 loadCssLink(storedPageCssLink); 272 } 273 274 if(storedWidgetCssLink) { 275 storedWidgetCssLink.disabled = true; 276 loadCssLink(storedWidgetCssLink); 277 } 278 279 storedRuntimeCssLink.disabled = true; 280 loadCssLink(storedRuntimeCssLink); 281 282 requestAnimationFrame(() => { 283 setTimeout(() => { 284 storedRuntimeCssLink.disabled = false; 285 storedGlobalCssLink.disabled = false; 286 if (storedPageCssLink) { 287 storedPageCssLink.disabled = false; 288 } 289 if (storedWidgetCssLink) { 290 storedWidgetCssLink.disabled = false; 291 } 292 // (SUP-4179) Clear the accumulated cssLinks only when we're 293 // sure that the document has finished loading and the document 294 // has been parsed. 295 if(document.readyState === 'interactive') { 296 cssLinks = null; 297 } 298 }, 0); 299 }); 300 } 301 } 302 303 304 function loadCSS(link) { 305 try { 306 var urlParams = new URLSearchParams(window.location.search); 307 var noCSS = !!urlParams.get("nocss"); 308 var cssTimeout = urlParams.get("cssTimeout") || 0; 309 310 if (noCSS) { 311 return; 312 } 313 if (link.href && link.href.includes("d-css-runtime")) { 314 cssLinks.runtime = link; 315 checkCss(); 316 } else if (link.id === "siteGlobalCss") { 317 cssLinks.global = link; 318 checkCss(); 319 } 320 321 else if (link.id && link.id.includes("CssLink")) { 322 cssLinks.page = link; 323 checkCss(); 324 } else if (link.id && link.id.includes("widgetCSS")) { 325 cssLinks.widget = link; 326 checkCss(); 327 } 328 329 else { 330 requestIdleCallback(function () { 331 window.setTimeout(function () { 332 loadCssLink(link); 333 }, parseInt(cssTimeout, 10)); 334 }); 335 } 336 } catch (e) { 337 throw e 338 } 339 } 340 window.loadCSS = window.loadCSS || loadCSS; 341})(); 342</script>
342 343 344 345
346<script data-role="deferred-init" type="text/javascript"> 347 /* usage: window.getDeferred(<deferred name>).resolve() or window.getDeferred(<deferred name>).promise.then(...)*/ 348 function Def() { 349 this.promise = new Promise((function (a, b) { 350 this.resolve = a, this.reject = b 351 }).bind(this)) 352 } 353 354 const defs = {}; 355 window.getDeferred = function (a) { 356 return null == defs[a] && (defs[a] = new Def), defs[a] 357 } 358 window.waitForDeferred = function (b, a, c) { 359 let d = window?.getDeferred?.(b); 360 d 361 ? d.promise.then(a) 362 : c && ["complete", "interactive"].includes(document.readyState) 363 ? setTimeout(a, 1) 364 : c 365 ? document.addEventListener("DOMContentLoaded", a) 366 : console.error(`Deferred does not exist`); 367 }; 368</script>
368 369<style id="forceCssIncludes"> 370 /* This file is auto-generated from a `scss` file with the same name */ 371 372.videobgwrapper{overflow:hidden;position:absolute;z-index:0;width:100%;height:100%;top:0;left:0;pointer-events:none;border-radius:inherit}.videobgframe{position:absolute;width:101%;height:100%;top:50%;left:50%;transform:translateY(-50%) translateX(-50%);object-fit:fill}#dm video.videobgframe{margin:0}@media (max-width:767px){.dmRoot .dmPhotoGallery.newPhotoGallery:not(.photo-gallery-done){min-height:80vh}}@media (min-width:1025px){.dmRoot .dmPhotoGallery.newPhotoGallery:not(.photo-gallery-done){min-height:45vh}}@media (min-width:768px) and (max-width:1024px){.responsiveTablet .dmPhotoGallery.newPhotoGallery:not(.photo-gallery-done){min-height:45vh}}#dm [data-show-on-page-only]{display:none!important}#dmRoot div.stickyHeaderFix div.site_content{margin-top:0!important}#dmRoot div.stickyHeaderFix div.hamburger-header-container{position:relative}@media (min-width:768px) and (max-width:1024px){.responsiveTablet #dm .dmInner .hide-for-medium,[data-hidden-on-tablet]{display:none!important}} 373 374body #dm #\31 642529323:not(.photo-gallery-done):not([data-widget-initialized]) { height: 45.0px !important; min-height: initial;} 375body #dm #\31 963014488:not(.photo-gallery-done):not([data-widget-initialized]) { height: 46.0px !important; min-height: initial;} 376body #dm #\31 563404019:not(.photo-gallery-done):not([data-widget-initialized]) { height: 106.0px !important; min-height: initial;} 377body #dm #\31 898883001:not(.photo-gallery-done):not([data-widget-initialized]) { height: 36.0px !important; min-height: initial;} 378</style> 379<style id="cssVariables" type="text/css"> 380 :root { 381 --color_1: rgba(0, 0, 0, 1); 382 --color_10: rgba(246,225,7,1); 383 --color_11: rgba(0,0,0,1); 384 --color_12: rgba(22, 83, 41, 1); 385 --color_13: rgba(22, 83, 41, 1); 386 --color_14: rgba(255, 200, 52, 1); 387 --color_15: rgba(246,225,7,1); 388 --color_16: rgba(0,0,0,1); 389 --color_17: rgba(22,83,41,1); 390 --color_18: rgba(22,83,41,1); 391 --color_19: rgba(246,225,7,1); 392 --color_2: rgba(255, 255, 255, 1); 393 --color_20: rgba(22,83,41,1); 394 --color_21: rgba(255, 255, 255, 1); 395 --color_22: rgba(255, 255, 255, 1); 396 --color_3: rgba(22,83,41,1); 397 --color_4: rgba(246,225,7,1); 398 --color_5: rgba(22,83,41,1); 399 --color_6: rgba(44,44,44,1); 400 --color_7: rgba(255,255,255,1); 401 --color_8: rgba(44,44,44,1); 402 --color_9: rgba(255,255,255,1); 403 --max-content-width_1: 1200px; 404} 405</style> 406 407 408<style id="hideAnimFix"> 409 .dmDesktopBody:not(.editGrid) [data-anim-desktop]:not([data-anim-desktop='none']), .dmDesktopBody:not(.editGrid) [data-anim-extended] { 410 visibility: hidden; 411 } 412 413 .dmDesktopBody:not(.editGrid) .dmNewParagraph[data-anim-desktop]:not([data-anim-desktop='none']), .dmDesktopBody:not(.editGrid) .dmNewParagraph[data-anim-extended] { 414 visibility: hidden !important; 415 } 416 417 #dmRoot:not(.editGrid) .flex-element [data-anim-extended] { 418 visibility: hidden; 419 } 420 421</style> 422 423 424 425<style id="criticalCss"> 426 @charset "UTF-8";#flex-header [data-widget-type=image],.text-align-center{text-align:center}#flex-sticky [data-layout-grid]>.flex-element.group>.flex-element.group>.flex-element.inner-grid,.flex-element.inner-grid,[data-layout-grid],[data-widget-type]:has(>.dmWidget.flexButton){-ms-grid-columns:minmax(0,1fr);grid-template-columns:minmax(0,1fr)}@font-face{font-family:Roboto;font-style:normal;font-weight:100;font-stretch:100%;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3yUBA.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:italic;font-weight:100;font-stretch:100%;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkBnka.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:normal;font-weight:300;font-stretch:100%;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3yUBA.woff2) format('woff2');
426unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:italic;font-weight:300;font-stretch:100%;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkBnka.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:FontAwesome;font-display:block;src:url(https://static-cdn.dwhitelabel.com/fonts/fontawesome-webfont.eot?v=6);src:url(https://static-cdn.dwhitelabel.com/fonts/fontawesome-webfont.eot?#iefix&v=6) format("embedded-opentype"),url(https://static-cdn.dwhitelabel.com/fonts/fontawesome-webfont.woff2?v=6) format("woff2"),url(https://static-cdn.dwhitelabel.com/fonts/fontawesome-webfont.woff?v=6) format("woff"),url(https://static-cdn.dwhitelabel.com/fonts/fontawesome-webfont.ttf?v=6) format("truetype"),url(https://static-cdn.dwhitelabel.com/fonts/fontawesome-webfont.svg#fontawesomeregular?v=6) format("svg");font-weight:400;font-style:normal}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-stretch:100%;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3yUBA.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:italic;font-weight:400;font-stretch:100%;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkBnka.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Poppins;font-style:normal;font-weight:400;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/poppins/v24/pxiEyp8kv8JHgFVrJJfecg.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3yUBA.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:italic;font-weight:500;font-stretch:100%;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkBnka.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:'Be Vietnam';font-style:normal;font-weight:700;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/bevietnam/v10/FBVwdDflz-iPfoPuIC2iKh0C_UBFJg.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-stretch:100%;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3yUBA.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:italic;font-weight:700;font-stretch:100%;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkBnka.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Poppins;font-style:normal;font-weight:700;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/poppins/v24/pxiByp8kv8JHgFVrLCz7Z1xlFQ.woff2) format('woff2');
426unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:normal;font-weight:900;font-stretch:100%;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/roboto/v51/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3yUBA.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:italic;font-weight:900;font-stretch:100%;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/roboto/v51/KFO5CnqEu92Fr1Mu53ZEC9_Vu3r1gIhOszmkBnka.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:'Kumbh Sans';font-style:normal;font-weight:100 900;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/kumbhsans/v27/c4mw1n92AsfhuCq6tVsaoIx1LQICk0boNoq0ShNPVo0.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:'Bebas Neue';font-style:normal;font-weight:400;font-display:swap;src:url(https://cdn.hibuwebsites.com/fonts/s/bebasneue/v16/JTUSjIg69CK48gW7PXoo9Wlhyw.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root{--color_1:rgba(0, 0, 0, 1);--color_10:rgba(246,225,7,1);--color_11:rgba(0,0,0,1);--color_12:rgba(22, 83, 41, 1);--color_13:rgba(22, 83, 41, 1);--color_14:rgba(255, 200, 52, 1);--color_15:rgba(246,225,7,1);--color_16:rgba(0,0,0,1);--color_17:rgba(22,83,41,1);--color_18:rgba(22,83,41,1);--color_19:rgba(246,225,7,1);--color_2:rgba(255, 255, 255, 1);--color_20:rgba(22,83,41,1);--color_21:rgba(255, 255, 255, 1);--color_22:rgba(255, 255, 255, 1);--color_3:rgba(22,83,41,1);--color_4:rgba(246,225,7,1);--color_5:rgba(22,83,41,1);--color_6:rgba(44,44,44,1);--color_7:rgba(255,255,255,1);--color_8:rgba(44,44,44,1);--color_9:rgba(255,255,255,1);--max-content-width_1:1200px;--hover-transform-zoomout:scale(1.06);--hover-transform-float:translateY(-8px);--hover-transform-forward:translateX(8px);--hover-transform-shrink:scale(0.9);--hover-transform-move-top:translateY(-10px);--hover-transform-move-bottom:translateY(10px);--hover-transform-move-left:translateX(-10px);--hover-transform-move-right:translateX(10px);--hover-transform-rotate:rotate(7deg);--hover-transform-opacity:0.7;--hover-scroll-transform:translate3d(0, 0, 0);--btn-border-l-color:rgb(255, 255, 255);--btn-border-r-color:rgb(255, 255, 255);--btn-border-b-width:2px;--btn-text-direction:ltr;--btn-border-radius:50px;--btn-border-t-width:2px;--btn-border-tl-radius:10px;--btn-border-br-radius:10px;--btn-border-bl-radius:10px;--btn-bg-color:var(--color_18);--btn-border-r-width:2px;--btn-border-tr-radius:10px;--btn-border-b-color:rgb(255, 255, 255);--btn-border-l-width:2px;--border-style:solid;--btn-border-t-color:rgb(255, 255, 255);--btn-text-align:center;--btn-text-color:var(--color_2);--btn-text-decoration:none;--btn-text-font-weight:bold;--btn-text-font-family:Poppins,"Poppins Fallback";--btn-icon-color:rgba(0, 0, 0, 0);--btn-icon-fill:rgba(0, 0, 0, 0);--btn-icon-wrpr-display:none;--btn-hover-border-b-color:var(--btn-hover-border-color);--btn-hover-bg:var(--color_19);--btn-hover-border-t-color:var(--btn-hover-border-color);--btn-hover-border-r-color:var(--btn-hover-border-color);--btn-hover-border-l-color:var(--btn-hover-border-color);--btn-hover-border-color:var(--color_1);--btn-hover-text-color:var(--color_1);--btn-hover-text-font-weight:var(--btn-text-font-weight);--btn-hover-text-decoration:var(--btn-text-decoration);--btn-hover-text-font-style:var(--btn-text-font-style);--section-padding-top:4%;--section-padding-left:0%;--section-padding-right:0%;--section-padding-bottom:4%;
426--column-padding-top:16px;--column-padding-right:16px;--column-padding-left:16px;--column-padding-bottom:16px;--inner-column-padding-left:16px;--inner-column-padding-right:16px;--inner-column-padding-top:16px;--inner-column-padding-bottom:16px}[data-layout-grid]{display:-ms-grid;display:grid;justify-content:start;align-items:start}[data-layout-grid]>.flex-element.group{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;-ms-grid-column-align:center;justify-self:center;-ms-grid-row-align:start;align-self:start;order:0;max-width:1200px}[data-layout-grid]>.flex-element.group>.flex-element.group{align-items:flex-start;-ms-grid-row-align:stretch;align-self:stretch}.flex-element.group,.flex-element.inner-grid,[data-layout-grid],[data-layout-grid]>.flex-element.group,[data-layout-grid]>.flex-element.group>.flex-element.group{background-size:cover;background-repeat:no-repeat;background-position:50% 50%;position:relative}.flex-element.group,[data-layout-grid]>.flex-element.group>.flex-element.group{max-width:100%;display:flex;flex-direction:column;justify-content:center}.flex-element.inner-grid{display:-ms-grid;display:grid;justify-content:start;align-items:start;column-gap:0;row-gap:0;width:50%}.flex-element.widget-wrapper{position:relative;min-width:10px;min-height:10px}#dm [data-flex-id] .widget-wrapper>[data-element-type]{width:100%;height:100%;margin:0;padding:0}[data-flex-id] .widget-wrapper [data-element-type=image] img,[data-flex-id] .widget-wrapper [data-element-type=image] img[width][height]{object-fit:cover;width:100%;height:100%}[data-flex-id] .flex-element.grid>.flex-element,[data-flex-id] .flex-element.inner-grid>.flex-element{-ms-grid-column:1;grid-column-start:1;-ms-grid-column-span:1;grid-column-end:span 1;-ms-grid-row:1;grid-row-start:1;-ms-grid-row-span:1;grid-row-end:span 1}[data-widget-type]:has(>.dmWidget.flexButton){display:-ms-grid;display:grid;-ms-grid-rows:minmax(0,1fr);grid-template-rows:minmax(0,1fr)}#flex-header[data-sticky]{position:sticky!important;top:0!important;z-index:13!important}#site_content,.dmInner,[data-flex-id]{position:relative}.dmInner{background:#fff;min-width:auto!important}a,button,input{font-family:inherit}strong{font-weight:700}#dmRoot{-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}[data-layout-grid]{-ms-grid-rows:minmax(0,max-content)!important;grid-template-rows:minmax(0,max-content)!important}.flex-widgets-container{display:none}body.fix-mobile-scrolling{overflow:initial}html{font-family:Source Sans Pro;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}@media (min-width:1025px){[dmle_extension^=ssr]{display:block}[data-hidden-on-desktop]{display:none!important}}@media (max-width:767px){[data-hidden-on-mobile]{display:none!important}}*,:after,:before{box-sizing:border-box}@media (min-width:768px) and (max-width:1024px){.hide-for-medium,[data-hidden-on-tablet]{display:none!important}}.dmInner ul:not(.defaultList){padding:1px}#dm h3.dmwidget-title[hide=true]{display:none}.clearfix,a,img,li,ul{vertical-align:top}.dmOuter{word-wrap:break-word}a[dont-color-link]{color:inherit}#dmFlexHeaderContainer{display:inline}[dmle_extension=custom_extension] .dmWidget{width:150px;padding:0 7px}#flex-sticky{position:fixed;inset:0;z-index:20}#flex-sticky [data-layout-grid]>.flex-element.group>.flex-element.group>.flex-element.inner-grid{width:100vw;height:100dvh;-ms-grid-rows:1fr;grid-template-rows:1fr}#flex-sticky [data-layout-grid]>.flex-element.group>.flex-element.group>.flex-element.inner-grid>.flex-element{-ms-grid-row:1;-ms-grid-row-span:1;-ms-grid-column:1;-ms-grid-column-span:1;grid-area:1/1/2/2;max-width:fill-available;max-width:-webkit-fill-available}@media (min-width:1025px){[data-layout-grid]>.flex-element.group{max-width:var(--max-content-full_1,var(--max-content-width_1,1200px))}[data-version] [class*=" font-size-"],[data-version] [class*=" size-"],[data-version] [class^=font-size-]{font-size:calc(var(--font-size) * var(--font-unit,1px))!important}}@supports (-webkit-touch-callout:none){.flex-element.grid,.flex-element.group{background-attachment:scroll!important}}@media (max-width:1024px){[data-layout-grid]>.flex-element.group{max-width:1200px}}body{container-type:inline-size;container-name:body;-webkit-overflow-scrolling:touch}:not(.runtime-module-container) .layout-drawer,:not(.runtime-module-container) .layout-drawer-overlay{visibility:hidden}:not(.runtime-module-container) .layout-drawer{position:fixed;transform:translate(-100%,-100%)}:not(.runtime-module-container) .layout-drawer[data-origin=side-reverse]{transform:translate(100%,0)}:not(.runtime-module-container) .layout-drawer-overlay{opacity:0}
426.runtime-module-container{width:100%}.runtime-module-container .layout-drawer,.runtime-module-container .layout-drawer-overlay{visibility:visible;height:100%;position:fixed;top:0;left:0}.runtime-module-container .layout-drawer{background-color:#fff;width:75vw;transform:translate(-100%,0);overflow:auto;-webkit-overflow-scrolling:auto;z-index:13;display:flex;flex-direction:column}.runtime-module-container .layout-drawer[data-origin=side-reverse]{transform:translate(100%,0);left:auto;right:0}.runtime-module-container .layout-drawer-overlay{width:100vw;background-color:rgba(0,0,0,.4);opacity:0;z-index:6}@media (min-width:1025px){[data-flex-site] .layout-drawer:not([data-origin=top]){width:30vw}}@media (min-width:768px) and (max-width:1024px){[data-version] [class*=" t-font-size-"],[data-version] [class*=" t-size-"]{font-size:calc(var(--font-size) * var(--t-font-unit,1px))!important}[data-flex-site] .layout-drawer:not([data-origin=top]){width:50vw}}@media (max-width:767px){[data-version] [class*=" m-font-size-"],[data-version] [class*=" m-size-"],[data-version] [class^=m-font-size-]{font-size:calc(var(--font-size) * var(--m-font-unit,1px))!important}[data-flex-site] .layout-drawer:not([data-origin=top]){width:80vw}#dm .dmInner .dmWidget{width:100%}}[data-flex-site] .layout-drawer [data-flex-id]{flex:1 0 auto;transform:translateZ(0)}.main-navigation.unifiednav{justify-content:space-around;align-items:stretch;display:flex;overflow:visible}.main-navigation.unifiednav ul{margin:0;padding:0;font-size:1rem;list-style:none}.main-navigation.unifiednav .unifiednav__container{flex-grow:1;list-style:none;display:flex}.main-navigation.unifiednav .unifiednav__container>.unifiednav__item-wrap{justify-content:flex-start;font-weight:400;display:flex;position:relative}.main-navigation.unifiednav .unav-top>.unifiednav__item-wrap:after,.main-navigation.unifiednav .unav-top>.unifiednav__item-wrap:before{content:"";align-self:center;font-weight:700}.main-navigation.unifiednav :where(.unav-item){color:inherit;font-weight:inherit;letter-spacing:.03em;flex-direction:row;justify-content:flex-start;align-items:center;margin:0;padding:12px 15px;text-decoration:none;display:flex;position:relative}.main-navigation.unifiednav button.unifiednav__item{font:inherit;color:inherit;width:100%;text-align:inherit;background:0 0;border:none}#dm .dmInner .dmWidget,#flex-header{background-image:none;border-style:solid}.main-navigation.unifiednav .unav-top-item{padding:0 15px}.main-navigation.unifiednav .unav-top-item .nav-item-text:after,.main-navigation.unifiednav .unav-top-item .nav-item-text:before{content:"";opacity:0;border:0 solid transparent;border-top-color:currentColor;width:100%;height:0;display:block}.main-navigation.unifiednav .unav-top-item:is(.dmNavItemSelected,:hover,.hover) .nav-item-text:after,.main-navigation.unifiednav .unav-top-item:is(.dmNavItemSelected,:hover,.hover) .nav-item-text:before{opacity:1}.main-navigation.unifiednav .unav-item .nav-item-text{white-space:nowrap}.main-navigation.unifiednav:is(.effect-bottom,.effect-bottom2,.effect-top-bottom){padding:calc(10px - .2em) 15px}.main-navigation.unifiednav:is(.effect-top-bottom,.effect-bottom,.effect-bottom2) .unav-top-item .nav-item-text:after{margin-top:.2em}.main-navigation.unifiednav:is(.effect-top-bottom,.effect-bottom,.effect-bottom2) .unav-top-item .nav-item-text:before{margin-bottom:.2em}.main-navigation.unifiednav:is(.effect-bottom,.effect-bottom2) .unav-top-item .nav-item-text:after,.main-navigation.unifiednav:is(.effect-bottom,.effect-bottom2) .unav-top-item .nav-item-text:before{border-top-width:2px;transform:scaleX(0)}.main-navigation.unifiednav:is(.effect-bottom,.effect-bottom2) .unav-top-item .nav-item-text:before{border-top-color:transparent}.main-navigation.unifiednav:is(.effect-bottom,.effect-bottom2) .unav-top-item:is(.dmNavItemSelected,:hover,.hover) .nav-item-text:after,.main-navigation.unifiednav:is(.effect-bottom,.effect-bottom2) .unav-top-item:is(.dmNavItemSelected,:hover,.hover) .nav-item-text:before{transform:scaleX(1)}.main-navigation.unifiednav.effect-bottom2 .unav-top-item .nav-item-text:after,.main-navigation.unifiednav.effect-bottom2 .unav-top-item .nav-item-text:before{transform-origin:0}.main-navigation.unifiednav .icon{display:none}.main-navigation.unifiednav .unifiednav__item_has-sub-nav .icon{display:initial;margin-left:10px}.main-navigation.unifiednav .unav-sub{opacity:0;z-index:100;background-color:#faf9f9;flex-direction:column;position:absolute;top:0;left:0}.main-navigation.unifiednav .unav-sub[data-depth="0"]{top:100%;transform:translateY(-10px)}.main-navigation.unifiednav .unav-sub>.unifiednav__item-wrap .unav-item{margin:0;padding:15px 30px 15px 15px}.main-navigation.unifiednav .unav-sub>.unifiednav__item-wrap:not(:last-child):after{color:#ececec;border:0 solid;align-self:center;width:100%;height:0;content:""!important}
426.main-navigation.unifiednav:not(.unifiednav_vertical) .unav-sub[data-depth="0"]{left:15px}.main-navigation.unifiednav .unifiednav__container>.unifiednav__item-wrap .unifiednav__container>.unifiednav__item-wrap{flex-direction:column}.main-navigation.unifiednav[layout-sub=submenu_horizontal_1] .unav-sub{color:#999}.main-navigation.unifiednav:not(.unifiednav_vertical)>.unifiednav__container{justify-content:inherit}#dm .main-navigation.unifiednav .unav-sub{background-color:rgba(0,0,0,0)}#dm .main-navigation.unifiednav:is([layout-sub=submenu_horizontal_1],[layout-sub=submenu_horizontal_2]) .unav-sub{background-color:#faf9f9}#dm .main-navigation.unifiednav .unav-sub>.unifiednav__item-wrap:not(:last-child):after{color:#d1d1d1}#dm .main-navigation.unifiednav:not([data-nav-structure=VERTICAL])>.unifiednav__container{justify-content:inherit;flex-wrap:wrap}#dm .main-navigation.unifiednav:not([data-nav-structure=VERTICAL])>.unifiednav__container .nav-item-text:before{text-align:left}#dm .main-navigation.unifiednav:not([data-nav-structure=VERTICAL])[data-divider]:not([data-direction=RIGHT]) :is(.left_nav>.unifiednav__item-wrap,.unav-top>.unifiednav__item-wrap:not(:last-child)):after{content:var(--divider)}#dm .dmInner .dmWidget:not(.displayNone){display:inline-block}#dm .dmInner .dmWidget:not(.flexButton):not(.displayNone)[data-display-type=block]{display:block}#dm .dmInner .dmWidget.flexButton:not(.displayNone){display:flex}#dm .dmInner .dmWidget.flexButton{display:flex;align-items:center;justify-content:center;padding:10px 7px}#dm .dmInner .dmWidget.flexButton .text{padding:0!important;flex-grow:1;max-width:max-content}#dm .dmInner .dmWidget.flexButton:after{display:none}#dm .dmInner .dmWidget{text-decoration:none;margin:10px 0;clear:both;position:relative;text-align:center;line-height:22px;box-shadow:none;padding:0;height:auto;white-space:nowrap}#dm .dmInner .dmWidget:after{content:"";display:inline-block;height:100%;vertical-align:middle;width:0;margin-right:-.25em}.dmWidget.R{float:right}#dm .dmInner .dmWidget input{width:98%;margin:auto;font-size:1.125em;padding:10px!important;background-color:transparent}#dm .dmInner .dmWidget .iconBg{position:absolute;left:0;width:50px;top:50%;margin-top:-13px}#dm .dmWidget .text{display:inline-block;vertical-align:middle;font-size:1.125em;line-height:normal;white-space:normal;padding:10px 7px;max-width:98%}p.rteBlock{margin:0}#dm div.dmContent [class*=" icon-"],[class*=" icon-"]{font-family:
426FontAwesome!important;font-weight:400;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased}[class*=" icon-"]:before{text-decoration:none;display:inline-block;speak:none}a [class*=" icon-"]{display:inline}[class*=" icon-"]{display:inline;width:auto;height:auto;line-height:normal;vertical-align:baseline;background-image:none;background-position:0 0;background-repeat:repeat;margin-top:0}.icon-star:before{content:"\f005"}.icon-angle-right:before{content:"\f105"}.icon-angle-down:before,.icon-angle-right:before{mask:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20640%201792'%3E%3Cpath%20transform='translate(0,1536)%20scale(1,-1)'%20d='M595%20576q0%20-13%20-10%20-23l-466%20-466q-10%20-10%20-23%20-10t-23%2010l-50%2050q-10%2010%20-10%2023t10%2023l393%20393l-393%20393q-10%2010%20-10%2023t10%2023l50%2050q10%2010%2023%2010t23%20-10l466%20-466q10%20-10%2010%20-23z'/%3E%3C/svg%3E") no-repeat center/contain}.icon-angle-down:before{content:"\f107";width:.643em;mask:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201152%201792'%3E%3Cpath%20transform='translate(0,1536)%20scale(1,-1)'%20d='M1075%20800q0%20-13%20-10%20-23l-466%20-466q-10%20-10%20-23%20-10t-23%2010l-466%20466q-10%2010%20-10%2023t10%2023l50%2050q10%2010%2023%2010t23%20-10l393%20-393l393%20393q10%2010%2023%2010t23%20-10l50%20-50q10%20-10%2010%20-23z'/%3E%3C/svg%3E") no-repeat center/contain}.graphicWidget{width:200px;height:200px;margin:10px auto;text-align:center}.graphicWidget svg.svg{width:100%;height:100%;color:#000;fill:#000}.graphicWidgetV2{width:60px;height:60px}.graphicWidgetV3{font-size:0}.dmNewParagraph[data-version] .text-align-left{text-align:left!important}.dmNewParagraph[data-version] .text-align-center{text-align:center!important}.dmNewParagraph[data-version] .text-align-right{text-align:right!important}.dmNewParagraph[data-version]{line-height:initial}.dmNewParagraph[data-version] [class*=size-]{width:auto!important;height:auto!important}.dmNewParagraph[data-version] h1,.dmNewParagraph[data-version] h2,.dmNewParagraph[data-version] h3,.dmNewParagraph[data-version] p{margin-top:0;margin-bottom:0}.dmNewParagraph[data-version] a{vertical-align:initial}@media (min-width:768px) and (max-width:1024px){.dmNewParagraph[data-version] .t-text-align-left{text-align:left!important}}@media (max-width:767px){.dmRoot .dmNewParagraph[data-version] .m-text-align-left{text-align:left!important}}#dm [text-box-padding=true] .postArticle .postText{padding:15px}#dm .blogImg{background-size:cover;background-position:center}#dm .blogImg img{visibility:hidden;position:absolute}#dm .postArticle{float:left;padding-right:15px;padding-left:15px}#dm .postArticle .inner{position:relative;max-width:100%}#dm .postArticle .authorBar{font-size:80%;opacity:.8}#dm .postArticle .readMore{opacity:.8}#dm .postArticle .postDescription{overflow:hidden;line-height:1.4em;word-break:break-word}#dm #dm_content [dmle_extension=internal_blog_list] .postArticle.lastArticle{margin-bottom:0!important}#dm [dmle_extension=internal_blog_list]>.inner{display:block}#dm .postArticle .postTitle h3{margin:0 0 15px;padding:0;line-height:normal}#dm .postArticle .postTitle h3:after{content:""}#dm [dmle_extension=internal_blog_list][show-author=false] .authorBar{display:none}#dm .postText *{text-align:left}#dm .postArticle .inner,#dm [blog-posts-feature-flag=true] .inner{width:100%}#dm [blog-posts-feature-flag=true] .blogImg img,#dm [list-layout=layout4] .blogImg img{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0,0,0,0)}#dm [blog-posts-feature-flag=true] .postTitle h3 a{font-weight:700}#dm [blog-posts-feature-flag=true] .blogImgLink{overflow:hidden;display:inline-block}#dm [blog-posts-feature-flag=true] .blogImg{height:100%;width:100%}#dm [blog-posts-feature-flag=true] .postDescription{max-height:5.5em;color:#747474}#dm [blog-posts-feature-flag=true] .postArticle{padding-right:0;padding-left:0;position:relative;overflow:visible}#dm [blog-posts-feature-flag=true] .postArticle .inner{overflow:hidden}#dm [blog-posts-feature-flag=true] .more-posts-text-container{margin:20px 0}@media (min-width:768px){body.dmRoot #dm [blog-posts-feature-flag=true],body.dmRoot #dm [list-layout=layout4]{display:flex!important;flex-direction:column;align-items:center}}#dm [blog-posts-feature-flag=true][dmle_extension=internal_blog_list][show-author=false] .authorBar{display:none}#dm [list-layout=layout4] .postArticle{position:relative;text-align:left;width:100%}#dm [list-layout=layout4] .postArticle .postText{padding:15px 0;display:block;width:100%}#dm [list-layout=layout4][text-box-padding=true] .postArticle .postText{padding:15px}#dm [list-layout=layout4][text-align=left] .postText *{text-align:left}#dm [list-layout=layout4] .postArticle.lastArticle{margin-bottom:0}#dm [list-layout=layout4] .postArticle a{text-decoration:none}#dm [list-layout=layout4] .postArticle .authorBar{margin:0 0 15px;padding:0}#dm [list-layout=layout4] .postTitle h3 a{font-size:18px;font-weight:700;line-height:1.5em;display:inline-block}#dm [list-layout=layout4] .blogImgLink{height:190px;width:100%;display:block}#dm [list-layout=layout4] .postArticle .inner{background-color:#fff;border-radius:4px;box-shadow:rgba(0,0,0,.25) 0 3px 11px 0!important;-moz-box-shadow:rgba(0,0,0,.25) 0 3px 11px 0!important;-webkit-box-shadow:rgba(0,0,0,.25) 0 3px 11px 0!important}#dm [list-layout=layout4] .postArticle .postDescription{font-size:15px}#dm [blog-posts-feature-flag=true]:not([list-layout=recent_posts]) .postArticle .inner{display:flex;flex-direction:column}#dm [blog-posts-feature-flag=true]:not([list-layout=list_slider]) .postArticle .inner{min-height:100%}#dm [blog-posts-feature-flag=true] .postTextContainer{display:flex;flex-direction:column;flex:1 1 auto;height:100%}#dm [blog-posts-feature-flag=true] .postTextContainer .postText{flex:1 1 auto}#dm [blog-posts-feature-flag=true][text-box-padding=true]:not([list-layout=list_slider]) .postTextContainer .readMore{padding:0 15px 15px}#dm [list-layout=layout4]>
426.inner{display:-ms-grid;display:grid;-ms-grid-columns:(1fr) [1];grid-template-columns:repeat(1,1fr)}#dm [list-layout=layout4][posts-padding="10"]>.inner{grid-gap:20px}@media (max-width:767px){.dmRoot #dm [list-layout=layout4] .postTitle h3 a{font-size:18px}.dmRoot #dm [list-layout=layout4] .postDescription{font-size:14px;margin-bottom:15px;padding:0}.dmRoot #dm [blog-posts-feature-flag=true] .more-posts-text-container{float:none;margin-left:auto;margin-right:auto;display:block!important}}#dm .dmformsubmit input[type=submit]{text-align:inherit}#dm div.dmInner .dmform[data-layout=layout-1] .dmforminput{display:block}#dm div.dmInner .dmform[data-layout=layout-1] .dmforminput>:not(label):not(div):not(small):not(.frc-banner):not(.dmform-field-error){background:0;border:2px solid #000;display:inline-block}#dm div.dmInner .dmform .dmforminput label[hide=true]{display:none}.dmform .dmforminput label{display:block;overflow:hidden;text-overflow:ellipsis}#dm .dmform:has(.spacing-container) .dmform-wrapper{overflow:clip}#dm .dmform:has(.spacing-container) .dmform-title.dmwidget-title{padding-inline:0;margin-block-start:0}#dm .dmform:has(.spacing-container) .spacing-container{margin:-7.5px;border:1px solid transparent;overflow:hidden}#dm .dmform:has(.spacing-container) .spacing-container .dmforminput{margin-top:0;padding:7.5px}#dm .dmform:has(.spacing-container) form.dmRespDesignRow{padding:0}#dm .dmform:has(.spacing-container) form.dmRespDesignRow .dmformsubmit{margin:0;margin-block-start:20px}.dmform{clear:both}div.dmInner .dmform input[type=email],div.dmInner .dmform input[type=tel],div.dmInner .dmform input[type=text]{font-size:16px;background-color:rgba(102,102,102,.15);border:2px solid #fff;width:100%;margin:3px 0;height:40px;padding:0 10px}div.dmInner .dmform input[type=submit]{margin:5px auto;width:100%;border-radius:5px;-webkit-border-radius:5px;-moz-border-radius:5px;height:30px!important;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;font-size:16px;border:0;outline:0}#dm .dmform .dmformsubmit{margin:20px 15px}.dmform-title{padding-right:15px;padding-left:15px}div.dmInner .dmformsubmit input[type=submit]{height:auto!important}@media (max-width:767px){.dmRoot #dm .dmform input[type=submit]{width:100%}#dm .dmform-wrapper .dmformsubmit{width:91%;max-width:91%;padding:0 10px;float:left}}#dmRoot #dm .dmWidget.dmformsubmit,img{max-width:100%}.dmforminput{text-align:left;margin-top:10px;padding-left:.9375em;padding-right:.9375em}#dm .dmPhotoGallery.newPhotoGallery .photoGalleryThumbs .caption-container .caption-inner div,#dm .dmPhotoGallery.newPhotoGallery .photoGalleryThumbs .caption-container .caption-inner h3,#dm .dmPhotoGallery.newPhotoGallery.captionAlignment-center_center .photoGalleryThumbs .caption-container .caption-inner:not(:has(>.caption-link)) div,#dm .dmPhotoGallery.newPhotoGallery.captionAlignment-center_center .photoGalleryThumbs .caption-container .caption-inner:not(:has(>.caption-link)) h3,.dmPhotoGallery.newPhotoGallery .photoGalleryThumbs .caption-container .caption-inner,.dmPhotoGalleryHolder,.form-title-widget,.form-title-widget .form-title-output,.hibu-asst-banner,.imageWidget a{text-align:center}img{-ms-interpolation-mode:bicubic;display:inline-block}.dmRespDesignRow{position:relative;width:100%;margin:0 auto;max-width:960px;padding-top:15px;padding-bottom:15px}.dmRespDesignRow:after,.dmRespDesignRow:before{content:" ";display:table}.dmRespDesignRow:after{clear:both}.dmRespDesignRow .dmRespDesignCol{position:relative;width:100%;display:inline-block;vertical-align:top;float:left}@media (max-width:767px){.dmRespDesignRow .dmRespDesignCol{position:relative;padding-left:15px;padding-right:15px;float:left}.dmRespDesignRow .small-12{position:relative;width:100%}}@media (min-width:768px) and (max-width:1024px){.dmRespDesignRow .medium-12{position:relative;width:100%}}@media (min-width:1025px){.rows-1200 .dmRespDesignRow{max-width:1200px}.dmRespDesignRow .large-12{position:relative;width:100%}}.imageWidget{position:relative}.imageWidget a{font-style:italic}.imageWidget img[width][height]{height:auto}[data-flex-site] #flex-header .imageWidget:after{content:none}[data-flex-site] #flex-header .imageWidget:before{font-size:80px;transform:none}.hamburgerButton{display:block;background-color:transparent;border:0;padding:0;margin:0}.hamburgerButton,.hamburgerButton svg{width:100%;height:100%}.dmPhotoGallery{margin:10px 0;width:100%;overflow:hidden;min-height:1px;clear:both}.dmPhotoGallery .image-container{position:relative}@media (min-width:768px){body.dmRoot #dm [list-layout=layout4][posts-per-row="3"]>.inner{-ms-grid-columns:(1fr) [3];grid-template-columns:repeat(3,1fr)}}.dmPhotoGallery.newPhotoGallery .photoGalleryThumbs .caption-container .caption-inner h3{margin:0;line-height:normal;font-size:21px}.dmPhotoGallery.newPhotoGallery .photoGalleryThumbs .caption-container .caption-inner .caption-text,.dmPhotoGallery.newPhotoGallery .photoGalleryThumbs .caption-container .caption-inner .caption-title{max-width:100%}#dm .dmPhotoGallery.newPhotoGallery .photoGalleryThumbs{list-style:none;position:relative}#dm .dmPhotoGallery.newPhotoGallery.captionAlignment-center_center .photoGalleryThumbs .caption-container .caption-inner:not(:has(>.caption-link)){justify-content:center;align-items:center}#dm .dmPhotoGallery.newPhotoGallery.captionAlignment-center_center .photoGalleryThumbs .caption-container .caption-inner .caption-button{margin:10px auto}#dm .dmPhotoGallery.newPhotoGallery .photoGalleryThumbs .caption-container .caption-inner{align-items:center}#dm .dmPhotoGallery.newPhotoGallery .dmPhotoGalleryHolder{width:100%;padding:0;display:none}#dm .dmPhotoGallery.newPhotoGallery .photogallery-row{display:flex}#dm .dmPhotoGallery.newPhotoGallery .layout-container.square{display:flex;width:100%;flex-direction:column}#dm .dmPhotoGallery.newPhotoGallery .layout-container .photogallery-column{display:flex;flex-direction:column;padding:0;width:100%;margin:0}#dm .dmPhotoGallery.newPhotoGallery .layout-container .photogallery-column.column-4{width:25%}#dm .dmPhotoGallery.newPhotoGallery .layout-container .photogallery-column .photoGalleryThumbs{position:relative;overflow:hidden}#dm .dmPhotoGallery.newPhotoGallery .layout-container .photogallery-column .photoGalleryThumbs .image-container{width:100%;overflow:hidden;
426background:url(https://dd-cdn.multiscreensite.com/runtime-img/galleryLoader.gif) center no-repeat}#dm .dmPhotoGallery.newPhotoGallery .layout-container .photogallery-column .photoGalleryThumbs .image-container.revealed{background:0}#dm .dmPhotoGallery.newPhotoGallery .layout-container .photogallery-column .photoGalleryThumbs .image-container a{display:flex;flex-direction:column;background-size:cover;padding-top:100%}#dm .dmPhotoGallery.newPhotoGallery .layout-container .photogallery-column .photoGalleryThumbs .image-container a img{display:none!important}#dm .dmPhotoGallery.newPhotoGallery .photoGalleryThumbs .thumbnailInnerWrapper{overflow:hidden;transform:translateZ(0)}#dm .dmPhotoGallery.newPhotoGallery .photoGalleryThumbs .image-container{overflow:hidden}#dm .dmPhotoGallery.newPhotoGallery .photoGalleryThumbs .image-container a{background-repeat:no-repeat;background-position:center}#dm .dmPhotoGallery.newPhotoGallery .photoGalleryThumbs .caption-container .caption-inner{display:flex;flex-direction:column;justify-content:center;position:relative;overflow:hidden;z-index:1;background-color:rgba(255,255,255,.9);color:#333;padding:15px;height:100%;box-sizing:border-box}#dm .dmPhotoGallery.newPhotoGallery .photoGalleryThumbs .caption-container .caption-inner .caption-button{margin:10px auto;max-width:100%}#dm .dmPhotoGallery.newPhotoGallery .photoGalleryThumbs .caption-container .caption-inner .caption-button .text{padding:10px 20px!important}#dm .dmPhotoGallery.newPhotoGallery.text-layout-over .photoGalleryThumbs .caption-container{height:100%;width:100%;position:absolute;top:0;left:0;padding:inherit}#dm .dmPhotoGallery.newPhotoGallery.text-layout-over .photoGalleryThumbs .caption-inner{display:flex;flex-direction:column;justify-content:center;box-sizing:border-box;min-height:0!important;padding:10px;transform:scale(1.05);opacity:0;filter:alpha(opacity=0)}#dm .dmPhotoGallery.newPhotoGallery[data-image-hover-effect=zoomout] .photoGalleryThumbs .image-container{-webkit-mask-image:-webkit-radial-gradient(#fff,#000)}.dmPhotoGalleryHolder{font-size:medium!important;margin:0;list-style:none}#dm .dmPhotoGallery .dmPhotoGalleryHolder{width:100%;padding:0}.animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.widget-8ff527 .ucw-wrapper{--ucw-text:#000000;--ucw-bg:#ffffff;--ucw-accent:#b83bd2;--ucw-border:#b83bd2;--ucw-button-hover-text:#ffffff;--ucw-headline-color:var(--color_3, var(--ucw-accent, #b83bd2));--ucw-body-color:var(--color_1, var(--ucw-text, #000000));--ucw-cta-color:var(--color_3, var(--ucw-accent, #b83bd2));--ucw-fine-color:#777777;--ucw-headline-size:32pt;--ucw-body-size:16pt;--ucw-cta-size:20pt;--ucw-fine-size:10pt;--ucw-accent-dark:#a030be;--ucw-accent-glow:rgba(184, 59, 210, 0.22);--ucw-accent-glow-faint:rgba(184, 59, 210, 0.08);--ucw-accent-shadow:rgba(184, 59, 210, 0.35);--ucw-accent-shadow-sm:rgba(184, 59, 210, 0.20);--ucw-accent-focus:rgba(184, 59, 210, 0.20);--ucw-card-shadow:none;--ucw-card-shadow-hover:0 8px 32px var(--ucw-accent-glow);--ucw-logo-width:220px;--ucw-logo-max-height:100px;--ucw-logo-spacing:12px;--ucw-button-gap:12px;--ucw-custom-coupon-gap:20px;--ucw-logo-bottom-gap:24px;--ucw-headline-bottom-gap:12px;--ucw-body-bottom-gap:12px;--ucw-cta-bottom-gap:12px;--ucw-terms-bottom-gap:12px;--ucw-button-bottom-gap:0px}.widget-8ff527 .ucw-action-template,.widget-8ff527 .ucw-callout[hidden],.widget-8ff527 .ucw-coupon[hidden]{display:none!important}.widget-8ff527 .ucw-card__actionLink{display:inline-flex;max-width:100%;text-decoration:none;box-sizing:border-box}.widget-8ff527 .ucw-card__action{max-width:100%}.widget-8ff527 .ucw-callout{width:100%;max-width:100%}.widget-8ff527 .ucw-coupon__grid{display:grid;grid-template-columns:repeat(var(--coupon-cols,2),minmax(0,1fr));gap:20px}@media (min-width:768px) and (max-width:1024px){.widget-8ff527 .ucw-card__action{min-height:46px;padding:0 26px}}@media (max-width:767px){.widget-8ff527 .ucw-coupon__grid{grid-template-columns:1fr;gap:16px}.widget-8ff527 .ucw-card__actionLink{width:auto;max-width:100%}.widget-8ff527 .ucw-card__action{max-width:100%;white-space:normal;text-align:center}}.hibu-asst-banner{position:relative;width:100%;background-color:#5D3F6A;padding:16px 10px}.asst-banner-text{font-size:20px;color:#fff;font-weight:700;line-height:24px;margin:0!important;padding:0!important}.asst-banner-text o{font-size:20px;color:#E2B13C;font-weight:700}.asst-banner-subtext{font-size:10px;color:#eee;line-height:12px;margin-top:5px!important;margin-bottom:0!important;padding:0!important}@media (min-width:768px){.asst-sms-button-desktop-hide{display:none}}.nmw-root [hidden],.widget-0c06e7 .cb1-theme-injector,.widget-1c20f5 .dcbh3-theme-injector,.widget-901b1c .hide-column-if-category-field-empty{display:none!important}@media (max-width:767px){.hibu-asst-banner{padding:12px}.asst-banner-subtext{padding:0 30px!important}.form-title-widget .form-title-output{font-size:1.2em}}.widget-0c06e7{position:absolute!important;width:0!important;height:0!important;overflow:hidden!important;margin:0!important;padding:0!important;border:none!important;opacity:0!important}.cross-collection-image{position:relative;width:100%;height:var(--cross-image-height,400px);background-repeat:no-repeat;background-size:var(--cross-image-background-size,cover);background-position:var(--cross-image-background-position,center center);border-radius:var(--cross-image-border-radius,0);overflow:hidden;visibility:hidden;opacity:0;transform:translateY(0)}.cross-collection-image-overlay{position:absolute;inset:0;background-color:var(--cross-image-overlay-color,#000);opacity:var(--cross-image-overlay-opacity,0)}.form-title-widget .form-title-output{margin:0;color:#fff}#dm .dmInner div.u_1258098665,#dm .dmInner div.u_1601347497,#dm .dmInner div.u_1613806224,.MFalignC{text-align:center!important}@media (min-width:768px) and (max-width:1024px){.form-title-widget .form-title-output{font-size:1.3em}}.nmw-root{--nmw-universal-text:#111111;--nmw-top-text:var(--nmw-universal-text);--nmw-sub-text:var(--nmw-universal-text);--nmw-subsub-text:var(--nmw-universal-text);--nmw-mega-parent-text:var(--nmw-universal-text);--nmw-mega-child-text:var(--nmw-universal-text);--nmw-mega-grandchild-text:var(--nmw-universal-text);--nmw-top-bg:transparent;--nmw-universal-bg:#ffffff;--nmw-sub-bg:var(--nmw-universal-bg);--nmw-subsub-bg:var(--nmw-universal-bg);--nmw-mega-bg:var(--nmw-universal-bg);--nmw-mega-family-bg:transparent;--nmw-universal-font:inherit;--nmw-universal-size:16px;--nmw-universal-weight:500;--nmw-top-font:var(--nmw-universal-font);--nmw-top-size:var(--nmw-universal-size);--nmw-top-weight:var(--nmw-universal-weight);--nmw-sub-font:var(--nmw-universal-font);--nmw-sub-size:var(--nmw-universal-size);--nmw-sub-weight:var(--nmw-universal-weight);--nmw-subsub-font:var(--nmw-universal-font);--nmw-subsub-size:var(--nmw-universal-size);--nmw-subsub-weight:var(--nmw-universal-weight);--nmw-mega-parent-font:var(--nmw-universal-font);--nmw-mega-parent-size:var(--nmw-universal-size);--nmw-mega-parent-weight:var(--nmw-universal-weight);--nmw-mega-child-font:var(--nmw-universal-font);--nmw-mega-child-size:var(--nmw-universal-size);--nmw-mega-child-weight:var(--nmw-universal-weight);--nmw-mega-grandchild-font:var(--nmw-universal-font);--nmw-mega-grandchild-size:var(--nmw-universal-size);--nmw-mega-grandchild-weight:var(--nmw-universal-weight);--nmw-top-chevron-color:var(--nmw-top-text);--nmw-mega-chevron-color:var(--nmw-mega-parent-text);--nmw-chevron-size:10px;--nmw-chevron-weight:1.5px;--nmw-top-gap:32px;--nmw-mirror-gap:0px;position:relative;width:100%;overflow:visible;box-sizing:border-box}.nmw-root *,.nmw-root ::after,.nmw-root ::before{box-sizing:border-box}.nmw-skip-link{position:absolute;
426left:0;top:-9999px;z-index:100000;padding:8px 14px;color:#fff;background:#005fcc;text-decoration:none}.nmw-loading{min-height:40px}.nmw-tools{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}.nmw-loading[hidden]{display:none!important}.nmw-tools:empty{display:none}@media (prefers-reduced-motion:reduce){.widget-8ff527 .ucw-card__action,.widget-8ff527 .ucw-card__actionLink{animation:none!important}.nmw-root *,.nmw-root ::after,.nmw-root ::before{scroll-behavior:auto!important;animation-duration:0s!important;animation-iteration-count:1!important}}.nmw-manual-items-source,.nmw-manual-items-source[hidden]{display:none!important}.copy-block-link-widget{width:100%}.copy-block-link-anchor{display:block;width:100%;text-decoration:none}.headerWidget{min-height:10px}#\31 48da2d9,#\33 91d01b6,#\35 042981a,#b7ff358b,#bd7b2692,#cc48b184,#e77f39e9,#f5745250{min-height:50px}.motFactCont{margin-top:8px;margin-bottom:8px}.motFactCont p.rteBlock{display:block;line-height:22px;color:#fff!important;font-size:20px}@media (min-width:768px){p.rteBlock:after{color:#fff}}@media (max-width:767px){.motFactCont p.rteBlock{line-height:20px;font-size:16px}#\32 7581a62{grid-area:1/1/span 1/span 1}}.widget-403a95 .cb2-theme-injector,.widget-8eedf9 .cb0-theme-injector,.widget-ab442a .hide-section-if-category-field-empty{display:none!important}img[width][height]{height:auto}#dm div.dmContent h1{color:#666}#dm .dmform .dmforminput label,#dm div.dmInner,.dmPhotoGallery .caption-text.caption-text{font-family:Roboto,"Roboto Fallback";font-weight:400;color:var(--color_2);line-height:1.5}#dm div.dmNewParagraph p{color:var(--color_1);direction:ltr;font-family:Poppins,"Poppins Fallback";font-weight:400;font-style:normal;text-decoration:none}#dm div.dmContent h1,#dm div.dmContent h2{font-family:"Kumbh Sans","Kumbh Sans Fallback";font-weight:400;font-style:normal;direction:ltr}#dm div.dmContent h1{color:var(--color_2);text-decoration:none;text-shadow:rgba(0,0,0,.4) 0 0 15px}#dm div.dmContent .dmNewParagraph[data-version] h1{text-decoration:inherit}#dm div.dmContent h2{color:var(--color_1);text-decoration:none}#dm div.dmContent h3,#dm div.dmContent h5,#dm div.flex_hfcontainer h3{font-family:"Kumbh Sans","Kumbh Sans Fallback";font-weight:700}#dm div.dmContent .dmNewParagraph[data-version] h2{text-decoration:inherit}#dm div.dmContent .dmNewParagraph[data-version] h2 *{text-decoration:none}#dm div.dmContent h3,#dm div.flex_hfcontainer h3{color:var(--color_1);direction:ltr;font-style:normal;text-decoration:none}#dm div.dmContent .dmNewParagraph[data-version] h3{text-decoration:inherit}#dm div.dmContent .dmNewParagraph[data-version] h3 *,#dm div.dmContent h5{text-decoration:none}#dm div.dmContent h5{color:var(--color_2);direction:ltr;font-style:normal}#dmRoot #dm div.dmContent h1,#dmRoot #dm div.dmContent h2,#dmRoot #dm div.dmContent h3,#dmRoot #dm div.dmContent h5,#dmRoot #dm div.dmNewParagraph p,#dmRoot #dm div.flex_hfcontainer h3{font-weight:400;font-style:normal;letter-spacing:initial}#dm .dmNewParagraph a:visited,#dm div.dmNewParagraph a:visited{color:rgba(246,225,7,1);text-decoration:none solid #59894e}#dm .dmNewParagraph a,#dm div.dmNewParagraph a{color:rgba(246,225,7,1);text-decoration:none}#dmRoot #dm div.dmContent h2{color:#f6e107;direction:ltr;font-family:"Bebas Neue","Bebas Neue Fallback";text-decoration:none;text-transform:uppercase}#dmRoot #dm div.dmContent .dmNewParagraph[data-version] h2{text-decoration:inherit}#dmRoot #dm div.dmContent .dmNewParagraph[data-version] h2 *{text-decoration:none}#dmRoot #dm div.dmContent h1{color:#fff;direction:ltr;font-family:"Bebas Neue","Bebas Neue Fallback";text-decoration:none;text-transform:uppercase}#dmRoot #dm div.dmContent .dmNewParagraph[data-version] h1{text-decoration:inherit}#dmRoot #dm div.dmContent h3,#dmRoot #dm div.flex_hfcontainer h3{color:var(--color_4);direction:ltr;font-family:"Bebas Neue","Bebas Neue Fallback";text-decoration:none;text-transform:uppercase}#dmRoot #dm div.dmContent .dmNewParagraph[data-version] h3{text-decoration:inherit}#dmRoot #dm div.dmContent .dmNewParagraph[data-version] h3 *{text-decoration:none}#dmRoot #dm div.dmContent h5{color:#000;direction:ltr;font-family:"Bebas Neue","Bebas Neue Fallback";text-decoration:none;text-transform:uppercase}#dmRoot #dm div.dmNewParagraph p{color:#fff;direction:ltr;font-family:Roboto,"Roboto Fallback";text-decoration:none;line-height:1.5}@media (min-width:1025px){#dm DIV.dmOuter DIV.dmInner{background-color:rgba(44,44,44,1)}#dm div.dmNewParagraph p{font-size:16px}#dm div.dmContent h1{font-size:48px}#dm div.dmContent h2{font-size:40px}#dm div.dmContent h3,#dm div.dmContent h5,#dm div.flex_hfcontainer h3{font-size:24px}#dmRoot #dm div.dmContent h3,#dmRoot #dm div.flex_hfcontainer h3{font-size:26px}#dmRoot #dm div.dmContent h5{font-size:24px}#dm .dmform .dmforminput label,#dm div.dmInner,#dmRoot #dm div.dmNewParagraph p,.dmPhotoGallery .caption-text.caption-text{font-size:15px}#dmRoot #dm div.dmContent h2{font-size:35px}:root{--btn-text-font-size:18px}}@media (min-width:768px) and (max-width:1024px){#dm div.dmNewParagraph p{font-size:16px}#dm div.dmContent h1{font-size:60px}#dm div.dmContent h3,#dm div.flex_hfcontainer h3{font-size:24px}#dm div.dmContent h2{font-size:35px}#dmRoot #dm div.dmContent h1{font-size:48px}#dmRoot #dm div.dmContent h3,#dmRoot #dm div.flex_hfcontainer h3{font-size:26px}#dmRoot #dm div.dmContent h5{font-size:24px}#dm DIV.dmOuter DIV.dmInner{background-color:rgba(44,44,44,1)}:root{--btn-text-font-size:16px}}@media (min-width:0px) and (max-width:767px){#dm div.dmContent h1{font-size:40px}#dm div.dmNewParagraph p{font-size:16px}#dm div.dmContent h3,#dm div.flex_hfcontainer h3{font-size:22px}#dm div.dmContent h2{font-size:30px}#dm div.dmContent h5{font-size:18px}#dmRoot #dm div.dmContent h5{font-size:24px}#dmRoot #dm div.dmContent h3,#dmRoot #dm div.flex_hfcontainer h3{font-size:26px}#dm DIV.dmOuter DIV.dmInner{background-color:rgba(44,44,44,1)}#dmRoot #dm div.dmContent h2{font-size:25px}:root{--btn-text-font-size:17px;--section-padding-left:4%;--section-padding-right:4%}}#dm .dmWidget:not([data-buttonstyle]){border-radius:50px}#dm .dmWidget:not([data-buttonstyle]) .text,#dm .dmWidget:not([data-buttonstyle]) input,#dm .dmWidget:not([data-buttonstyle]).flexButton{padding:10px 0}#dm .dmWidget.button_2:not([data-buttonstyle]) .iconBg,#dm .dmWidget:not([data-buttonstyle]) .iconBg{display:none}#dm div.dmInner #site_content .dmWidget{background-color:var(--btn-bg-color);border-color:var(--btn-border-color);border-bottom-color:var(--btn-border-b-color);border-left-color:var(--btn-border-l-color);border-right-color:var(--btn-border-r-color);border-top-color:var(--btn-border-t-color);border-radius:var(--btn-border-radius);border-bottom-left-radius:var(--btn-border-bl-radius);border-bottom-right-radius:var(--btn-border-br-radius);border-top-left-radius:var(--btn-border-tl-radius);border-top-right-radius:var(--btn-border-tr-radius);border-width:var(--btn-border-width);border-bottom-width:var(--btn-border-b-width);border-left-width:var(--btn-border-l-width);border-right-width:var(--btn-border-r-width);border-top-width:var(--btn-border-t-width);direction:var(--btn-text-direction);text-align:var(--btn-text-align)}#dm div.dmInner #site_content .dmWidget span.text,#dm div.dmInner #site_content .dmformsubmit input{color:var(--btn-text-color);font-family:var(--btn-text-font-family);font-size:var(--btn-text-font-size);
426font-weight:var(--btn-text-font-weight);text-decoration:var(--btn-text-decoration)}#dm div.dmInner #site_content .dmWidget span.icon{color:var(--btn-icon-color);fill:var(--btn-icon-fill)}#dm div.dmInner #site_content .dmWidget:not([data-buttonstyle]) .iconBg{display:var(--btn-icon-wrpr-display)}.dmBody [data-layout-grid]>.flex-element.group,.dmFooterContainer [data-layout-grid]>.flex-element.group{padding-bottom:var(--section-padding-bottom);padding-left:var(--section-padding-left);padding-right:var(--section-padding-right);padding-top:var(--section-padding-top)}.dmBody [data-layout-grid]>.flex-element.group>.flex-element.group,.dmFooterContainer [data-layout-grid]>.flex-element.group>.flex-element.group{padding-bottom:var(--column-padding-bottom);padding-left:var(--column-padding-left);padding-right:var(--column-padding-right);padding-top:var(--column-padding-top)}.dmBody [data-layout-grid]>.flex-element.group>.flex-element.group .flex-element.group:not([data-layout-type] *):not([data-layout-type]){padding-bottom:var(--inner-column-padding-bottom);padding-left:var(--inner-column-padding-left);padding-right:var(--inner-column-padding-right);padding-top:var(--inner-column-padding-top)}#dm .dmInner nav.u_1398948466.main-navigation.unifiednav:not([data-nav-structure=VERTICAL]) .unifiednav__container[data-depth]{box-shadow:rgba(0,0,0,.25) 3px 3px 11px 0!important}#dm .dmInner nav.u_1398948466.main-navigation.unifiednav .unifiednav__container:not([data-depth])>.unifiednav__item-wrap>.unifiednav__item{color:var(--color_11)!important;direction:ltr!important;font-weight:500!important;text-decoration:none solid #111!important;font-size:16px!important;font-style:normal!important;border-radius:0!important;text-transform:none!important;justify-content:flex-start!important;font-family:Poppins!important;-webkit-border-radius:0!important;text-align:left!important;padding:0 20px!important;margin:0!important}#dm .dmInner a.u_1234177366 span.text{font-size:18px!important}#dm .dmInner div.u_1857856301{border-style:solid!important;border-color:#df7cfb!important;border-width:0!important}#dm .dmInner .u_1389791254 .svg{width:100%!important}#dm .dmInner div.u_1389791254 .svg{fill:var(--color_2)!important}#dm .dmInner div.u_1389791254{padding:12.5%!important;border-radius:50%!important;border-color:var(--color_2)!important;border-width:1px!important;border-style:solid!important;background-color:var(--color_13)!important;background-image:initial!important}#dm .dmInner nav.u_1915042179.main-navigation.unifiednav:not([data-nav-structure=VERTICAL]) .unifiednav__container[data-depth]{box-shadow:rgba(0,0,0,.25) 3px 3px 11px 0!important}#b7dee1fb,#flex-header{box-shadow:rgba(0,0,0,.25) 0 0 11px 0}#dm .dmInner nav.u_1915042179.main-navigation.unifiednav .unifiednav__container:not([data-depth])>.unifiednav__item-wrap>.unifiednav__item{color:var(--color_11)!important;direction:ltr!important;font-weight:500!important;text-decoration:none solid #111!important;font-size:16px!important;font-style:normal!important;border-radius:0!important;text-transform:none!important;justify-content:flex-start!important;font-family:Poppins!important;-webkit-border-radius:0!important;text-align:left!important;padding:0 20px!important;margin:0!important}#dm .dmInner nav.u_1398948466.main-navigation.unifiednav .unifiednav__container[data-depth] .unifiednav__item,#dm .dmInner nav.u_1915042179.main-navigation.unifiednav .unifiednav__container[data-depth] .unifiednav__item{font-weight:500!important;text-decoration:none solid #999!important;padding:4px 30px 4px 15px!important;direction:ltr!important;text-transform:none!important;font-family:Poppins!important;font-style:normal!important;font-size:14px!important}#dm .dmInner nav.u_1915042179.main-navigation.unifiednav .unifiednav__container[data-depth]{background-color:var(--color_11)!important;background-image:initial!important}#dm .dmInner nav.u_1915042179.main-navigation.unifiednav .unifiednav__container[data-depth] .unifiednav__item{color:var(--color_10)!important;justify-content:flex-start!important;text-align:left!important}#dm .dmInner nav.u_1398948466.main-navigation.unifiednav .unifiednav__container[data-depth]{background-color:var(--color_10)!important;background-image:none!important}#dm .dmInner nav.u_1398948466.main-navigation.unifiednav .unifiednav__container[data-depth] .unifiednav__item{
426color:var(--color_11)!important;justify-content:flex-start!important;text-align:left!important}#dm .dmInner nav.u_1869341664{justify-content:center!important;color:#000!important}#dm .dmInner nav.u_1869341664.main-navigation.unifiednav:not([data-nav-structure=VERTICAL]) .unifiednav__container:not([data-depth])>.unifiednav__item-wrap:not(:last-child)::after,#dm .dmInner nav.u_1869341664.main-navigation.unifiednav:not([data-nav-structure=VERTICAL]) .unifiednav__container:not([data-depth])>.unifiednav__item-wrap:not(:last-child)::before{font-size:11px!important}#dm .dmInner nav.u_1869341664.main-navigation.unifiednav .unifiednav__container:not([data-depth])>.unifiednav__item-wrap>.unifiednav__item{font-size:11px!important;color:rgba(102,102,102,1)!important;direction:ltr!important;font-weight:400!important;text-decoration:none solid #fff!important;font-style:normal!important;border-radius:0!important;text-transform:none!important;justify-content:flex-start!important;font-family:Poppins!important;-webkit-border-radius:0!important;text-align:left!important;padding:0 20px 0 0!important;margin:0!important}#dm .dmInner nav.u_1869341664.main-navigation.unifiednav .unifiednav__container:not([data-depth])>.unifiednav__item-wrap>.unifiednav__item.dmNavItemSelected{color:rgba(102,102,102,1)!important}#dm .dmInner nav.u_1869341664.main-navigation.unifiednav .unifiednav__container[data-depth] .unifiednav__item{font-size:11px!important;color:rgba(102,102,102,1)!important}#dm .dmInner nav.u_1398948466,#dm .dmInner nav.u_1915042179{justify-content:center!important}#\33 710bc01,#\39 c18e540{justify-content:flex-start}#dm .dmInner div#hamburger-drawer.layout-drawer{background-color:var(--color_10)!important}#dm .dmInner div.u_1127636214{color:var(--color_7)!important;direction:ltr!important;text-transform:none!important;text-shadow:none!important;font-weight:700!important;text-decoration:none solid #000!important;letter-spacing:normal!important;font-family:Poppins!important;line-height:normal!important;font-style:normal!important;text-align:right!important;font-size:20px!important}#dm .dmInner div.u_1220116170 img{border-radius:33px!important}#dm .dmInner div.u_1301876968 img{border-radius:21px!important}#dm .dmInner div.u_1303640445 img{border-radius:14px!important}@media (min-width:0) and (max-width:767px){#dm .dmInner a.u_1105358164 span.text,#dm .dmInner a.u_1524906790 span.text{font-size:16px!important}}@media (min-width:768px) and (max-width:1024px){:root{--btn-text-font-size:16px;--section-padding-left:2%;--section-padding-right:2%}div[dmtemplateid=FlexHeader] .layout-drawer-overlay{background-color:rgba(0,0,0,.6)!important}#dm .dmInner div#hamburger-drawer.layout-drawer{margin:0!important;padding:0!important}#dm .dmInner a.u_1997567173 span.text{font-size:14px!important}#dm .dmInner div.u_1127636214{font-size:20px!important}}#a8f32aec,#bd946f29{max-height:100%;background-color:var(--color_10);align-self:auto;background-image:initial}@media (min-width:0px) and (max-width:767px){#dm .dmInner #hamburger-drawer.layout-drawer:not([data-origin=top]){width:68vw!important}#dm .dmInner div#hamburger-drawer.layout-drawer{margin:0!important;padding:0!important}#dm .dmInner a.u_1105358164 span.text,#dm .dmInner a.u_1524906790 span.text{font-size:14px!important}}#\31 1d216b4,#\33 aa37ebb{width:33%;min-height:75px}#\34 598469b,#\35 801a4e8,#\38 e45e82b{width:30px;height:30px}#\31 db7e0c7,#\35 9867e38,#\37 46860ee,#\37 fcf5600,#cb51b1aa,#d47c231b,#e154016c,#e76e903e,#widget_7d2{margin-left:0;margin-right:0}#flex-header{background-color:var(--color_6);border-color:var(--color_10) #000 rgba(203,203,203,1);border-width:4px 0 0;padding:0}#\33 710bc01{min-height:8px;column-gap:4%;row-gap:0;width:100%;align-items:center;min-width:4%;flex-wrap:nowrap;background-color:rgba(0,0,0,0);background-image:initial;padding:0;margin:0}#\39 360b347{min-height:144px;column-gap:0;row-gap:0;max-width:none;width:100%;flex-wrap:nowrap;padding:0;margin:0}#\35 1d6dafc{width:100%;height:auto;max-width:100%;align-self:stretch}#bd946f29{align-items:flex-start;width:100%;min-height:60px;justify-self:auto;order:1;padding:0;margin:0;grid-area:auto/auto/auto/auto}#\37 46860ee{width:100%;height:auto;max-width:100%;order:0;align-self:auto;margin-bottom:-9px;grid-area:auto/auto/auto/auto}#\36 a5bfb4c{justify-content:flex-end;align-items:flex-start;width:100%;min-height:80px;max-height:100%;row-gap:4px;column-gap:4%;align-self:auto;order:1;justify-self:auto;padding:0 0 5px;margin:0;grid-area:auto/auto/auto/auto}#d3a805c8{align-items:flex-start;width:100%;min-height:75px;max-height:100%;row-gap:24px;column-gap:4%;align-self:flex-end;order:0;padding:0;margin:0;grid-area:auto/auto/auto/auto}#\33 ad8c19c.flex-element.widget-wrapper>[data-element-type]{padding-top:0;padding-bottom:7px}#\33 ad8c19c{width:99.92%;height:auto;max-width:100%;align-self:auto;order:0;margin:0;grid-area:auto/auto/auto/auto}#e77f39e9{width:250px;height:auto;max-width:100%;justify-self:auto;align-self:flex-end;order:0;margin-top:0;margin-bottom:0;grid-area:auto/auto/auto/auto}#\35 19ddbdc{width:376px;height:auto;max-width:100%;justify-self:auto;align-self:auto;order:0;margin:0;grid-area:auto/auto/auto/auto}#\33 a2d0b90{flex-direction:row;align-items:center;width:100%;min-height:80px;max-height:100%;justify-self:auto;align-self:auto;order:0;flex-wrap:nowrap;background-color:rgba(0,0,0,0);background-image:initial;padding:1% 2%;margin:0;grid-area:auto/auto/auto/auto}#\33 b22d9b0{align-items:flex-start;width:100%;min-height:75px;max-height:100%;row-gap:24px;column-gap:4%;align-self:auto;order:0;padding:0;margin:0;grid-area:auto/auto/auto/auto}#a8c6072d{width:99.7%;height:auto;max-width:100%;order:0;align-self:auto;margin:0;grid-area:auto/auto/auto/auto}#e3dfb55d{flex-direction:row;align-items:center;width:33.37%;min-height:160px;max-height:100%;row-gap:24px;column-gap:4%;justify-self:auto;align-self:auto;order:1;padding:0;margin:0;grid-area:auto/auto/auto/auto}#\34 23fc4a2{justify-content:space-between;align-items:center;width:32.45%;min-height:160px;max-height:100%;row-gap:0;column-gap:4%;flex-wrap:nowrap;order:0;
426justify-self:auto;align-self:auto;padding:0;margin:0;grid-area:auto/auto/auto/auto}#\35 bfb3718.flex-element.widget-wrapper>[data-element-type]{padding-bottom:0;padding-top:0}#\30 ece3d12,#\39 e5ef93d{width:50%;padding:0 0 0 4%;order:0}#\32 fd7b414,#\39 f3f031f,#a7708a16{padding:16px;min-width:4%;column-gap:4%;row-gap:24px}#\35 bfb3718{width:425px;height:auto;max-width:100%;justify-self:auto;order:0;grid-area:auto/auto/auto/auto}#\35 cbebde5{justify-content:space-between;align-items:center;width:32.51%;min-height:160px;max-height:100%;row-gap:0;column-gap:4%;justify-self:auto;align-self:auto;order:2;flex-wrap:nowrap;padding:0;margin:0;grid-area:auto/auto/auto/auto}#\36 881434d{align-items:center;width:479px;min-height:157px;max-height:100%;row-gap:24px;column-gap:4%;background-color:rgba(0,0,0,0);background-image:initial;border-radius:8px;height:auto;align-content:center;padding:8px 4%;margin:0}#\30 ad35782{width:99.99%;height:auto;max-width:100%;align-self:auto;order:1;justify-self:auto;margin-bottom:3px;margin-top:5px;grid-area:auto/auto/auto/auto}#be1b9f91{flex-direction:row;align-items:flex-start;width:99.26%;min-height:160px;max-height:100%;row-gap:24px;column-gap:1%;order:0;justify-self:auto;align-self:auto;padding:0;margin:0;grid-area:auto/auto/auto/auto}#\38 caf0a70{justify-content:flex-end;align-items:flex-start;width:100%;min-height:80px;max-height:100%;row-gap:0;column-gap:4%;padding:0 0 10px;margin:0}#a8f32aec{align-items:flex-start;width:100%;min-height:60px;justify-self:auto;order:2;padding:0;margin:0;grid-area:auto/auto/auto/auto}#\36 18f39ae,#\36 5e14480,#\39 34bad03{width:100%;max-width:100%;justify-self:auto}#\31 48da2d9,#\32 fd7b414,#\34 cb86e4c,#\38 e45e82b .hamburgerButton,#\39 f3f031f,#da0131a7,#group_jjh{background-color:rgba(0,0,0,0)}#\33 92df140,#widget_7d2{width:100%;height:auto;max-width:100%;align-self:stretch}#\36 18f39ae{height:1px;align-self:auto;order:2;min-height:4px;grid-area:auto/auto/auto/auto}#\36 5e14480,#\39 34bad03{height:auto;order:0;align-self:auto;grid-area:auto/auto/auto/auto}#\35 02c2597,#cbc8b291{max-width:100%;justify-self:auto;align-self:auto;grid-area:auto/auto/auto/auto;width:100%}#cbc8b291{height:auto;order:0}#\35 02c2597{height:1px;order:2;min-height:4px}#\31 db7e0c7,#widget_6mu{height:auto;max-width:100%;justify-self:auto}#\31 db7e0c7{width:180px;align-self:auto;order:5;margin-top:10px;grid-area:auto/auto/auto/auto}#widget_6mu{width:50.77%;order:3;align-self:auto;grid-area:auto/auto/auto/auto}#d0a778c9,#f589fd14{width:99.8%;justify-self:auto;grid-area:auto/auto/auto/auto;align-self:auto;height:auto;max-width:100%}#d0a778c9{order:3}#f589fd14{order:4}#\38 5709a0b{width:100%;height:1px;max-width:100%;min-height:4px;justify-self:auto;align-self:auto;order:5;grid-area:auto/auto/auto/auto}#\32 fd7b414,#group_23b,#group_7in{flex-direction:row;width:25%;margin:0;min-height:8px}#\32 fd7b414{justify-content:flex-start;align-items:center;background-image:initial}#\31 d3acdb9,#\33 2767c2f{min-height:80px;column-gap:0;row-gap:0;width:100%;flex-wrap:nowrap;padding:0 2%;margin:0}#group_23b,#group_7in{justify-content:flex-start;align-items:center;padding:0}#group_jjh{flex-direction:row;justify-content:flex-start;align-items:center;width:25%;min-height:8px;background-image:initial;border-radius:10px;padding:0;margin:0}#ec5d46f2,#widget_ie6{width:auto;height:auto;max-width:100%}#widget_5h5{width:80px;height:auto;max-width:100%}#daf81bcc,#widget_vej{width:280px;height:auto;max-width:100%}#\34 598469b svg,#\35 801a4e8 svg{fill:var(--color_7)}#\34 598469b{max-width:100%;justify-self:auto;align-self:auto;order:0;margin:0;grid-area:auto/auto/auto/auto}#group_tbn{flex-direction:row;justify-content:flex-start;align-items:center;padding:0;margin:0}#widget_qp9{width:100%;height:200px;max-width:100%}#\39 f3f031f{min-height:8px;flex-direction:row;width:100%;justify-content:flex-start;align-items:center;background-image:initial;order:0;margin:0}#\31 1d216b4,#a052d7aa{flex-direction:row;max-height:100%;margin:0}#\31 1d216b4{justify-content:flex-start;align-items:center;row-gap:24px;column-gap:4%;order:0;padding:0}#a052d7aa{justify-content:flex-end;align-items:center;width:50%;min-height:60px;align-self:auto;order:1;justify-self:auto;padding:0 4% 0 0;grid-area:auto/auto/auto/auto}#\33 aa37ebb,#\39 e5ef93d{flex-direction:row;max-height:100%;align-self:auto;grid-area:auto/auto/auto/auto}#\30 7327faa{width:100%;height:8px;max-width:100%}#\39 e5ef93d{align-items:center;min-height:40px;justify-self:auto;margin:0}#\35 801a4e8{max-width:100%}#\33 aa37ebb{justify-content:flex-end;align-items:center;row-gap:24px;column-gap:4%;order:2;justify-self:auto;padding:0;margin:0}#\30 ece3d12,#\31 48da2d9{flex-direction:row;margin:0;max-height:100%}#\30 ece3d12{justify-content:flex-start;align-items:center;min-height:60px}#\31 48da2d9{justify-content:space-between;align-items:flex-start;width:100%;order:2;justify-self:auto;align-self:auto;background-image:initial;padding:0;grid-area:auto/auto/auto/auto}#bff1bb66{width:180px;height:auto;max-width:100%;margin:0}#\34 cb86e4c{flex-direction:row;align-items:flex-start;width:100%;min-height:40px;max-height:100%;order:0;
426justify-self:auto;align-self:center;background-image:initial;padding:0;margin:0;grid-area:auto/auto/auto/auto}#df845449{width:250px;height:auto;max-width:100%}#\39 8702d80{align-items:flex-start;width:100%;min-height:230px;max-height:100%;row-gap:0;column-gap:4%;justify-self:auto;align-self:auto;order:0;padding:0;margin:0;grid-area:auto/auto/auto/auto}#da0131a7{align-items:center;width:35.64%;min-height:90px;max-height:100%;align-self:auto;justify-self:auto;order:1;flex-wrap:nowrap;background-image:initial;border-radius:10px;padding:0;margin:0;grid-area:auto/auto/auto/auto}#\32 e9284f4{flex-direction:row;align-items:flex-start;width:100%;min-height:90px;max-height:100%;justify-self:auto;align-self:auto;order:1;flex-wrap:nowrap;padding:0 1%;margin:0;grid-area:auto/auto/auto/auto}#bd7b2692{width:280px;height:auto;max-width:100%;justify-self:auto;align-self:auto;order:2;grid-area:auto/auto/auto/auto}#a7708a16{min-height:8px;width:100%;align-items:flex-end;margin:0}#\37 8db3927{min-height:100px;column-gap:4%;row-gap:24px;width:100%;padding:2% 0;margin:0}#\38 e45e82b svg{fill:var(--color_11)}#\34 f4d3298,#\37 ca01c83{min-height:8px;column-gap:4%;row-gap:24px;width:100%;min-width:4%;padding:0;margin:0}#\32 4eff763{min-height:0;column-gap:4%;row-gap:24px;width:100%;flex-wrap:nowrap;max-width:none;padding:5px 4%;margin:0}#\33 4b9f983{width:100%;height:auto;max-width:100%;justify-self:auto;align-self:flex-start;order:0;grid-area:auto/auto/auto/auto}#\33 989af5b{background-color:var(--color_2);background-image:initial}#dm .dmInner div.u_1019079231 input:not([type=submit]),#dm .dmInner div.u_1673887128 input:not([type=submit]){background-color:rgba(255,255,255,1)!important;background-image:initial!important;border-style:solid!important;border-color:#000!important;border-width:0!important;border-radius:5px!important}#\37 2168835{grid-template-rows:minmax(300px,max-content);width:100%;max-width:100%}#\37 5ba1c41{min-height:240px;column-gap:4%;row-gap:24px;max-width:none;width:100%;flex-wrap:nowrap;padding:0;margin:0}#widget_21v,#widget_fpt{justify-self:end;align-self:end;margin:40px;height:auto;max-width:100%}#widget_21v{width:60px;order:5}#widget_fpt{width:auto}#widget_301{width:auto;height:auto;max-width:100%;justify-self:end;align-self:end;min-height:auto;min-width:auto;margin:40px}#\31 02296bd,#\32 7581a62{flex-wrap:nowrap;max-width:none}#\32 7581a62{min-height:auto;column-gap:3%;row-gap:18px;width:100%;padding:0;margin:0;grid-area:1/1/span 1/span 1}#\30 4df1da2,#\33 9a585e9,#\34 310a1b0,#\35 aa033c8,#\37 b991c9b,#\38 99c2eb2,#b51d88ee,#f09d8243{width:100%;height:auto;max-width:100%;align-self:auto;justify-self:auto;order:0;margin:0;grid-area:auto/auto/auto/auto}#fe7f7167{width:100%;height:auto;max-width:100%;align-self:auto;order:0;margin:0;grid-area:auto/auto/auto/auto}#\37 e326d80{width:100%;height:auto;max-width:100%;order:0;align-self:auto;justify-self:auto;margin:0;grid-area:auto/auto/auto/auto}@media (min-width:768px) and (max-width:1024px){#ac810934,#flex-header{margin-top:0}#\38 e45e82b,#fd81f3e8,#widget_5h5,#widget_ie6,#widget_vej{align-self:auto;margin:0;grid-area:auto/auto/auto/auto}#\31 d3acdb9,#\32 4eff763{padding-left:4%;padding-right:4%}#\37 5ba1c41,#\39 360b347{padding-left:2%;padding-right:2%}#flex-header{padding-top:0}#\39 360b347{flex-direction:row;flex-wrap:nowrap;min-height:100px;padding-bottom:12px}#\33 710bc01{width:100%;min-height:8px}#fd81f3e8{justify-self:auto;width:100%;order:0}#\33 2767c2f{padding-left:1%;padding-right:1%;min-height:92px;flex-direction:row;flex-wrap:nowrap;column-gap:1%}#\32 fd7b414{width:21.2%;min-height:8px;order:1;column-gap:0;justify-content:center;padding-left:0;padding-right:0}#group_7in,#group_jjh{justify-content:center;min-height:8px}#group_7in{width:21.2%;order:3}#group_jjh{width:34.5%;order:2;margin:10px 2%}#widget_5h5{width:238px;height:auto}#widget_vej{width:130px;min-height:40px}#group_23b{width:8.33%;min-height:8px;order:4;justify-content:center}#group_tbn{order:0;width:8.33%;min-height:8px}#widget_qp9{height:6px}#\31 d3acdb9{flex-direction:row;flex-wrap:nowrap;min-height:80px}#\38 e45e82b{justify-self:auto;order:0}}@media (max-width:767px){#\32 fd7b414,#group_23b,#group_7in,#group_jjh{width:25%;min-height:8px}#\30 ece3d12,#a052d7aa{align-self:center;width:50%;padding-left:1%;padding-right:1%}#daf81bcc,#df845449{min-height:40px}#\35 bfb3718,#bff1bb66,#ec5d46f2{height:auto}#widget_21v,#widget_301,#widget_fpt{max-width:100%;margin:20px}#flex-header{padding-top:0;padding-bottom:0}#\33 710bc01{width:100%;align-items:center;min-height:8px}#\31 d3acdb9,#\33 2767c2f,#\39 360b347{flex-direction:row;padding-left:0;padding-right:0;flex-wrap:nowrap;min-height:60px}#a8f32aec,#bd946f29{order:2}#\33 a2d0b90{order:4}#\32 fd7b414{align-items:center;justify-content:center;padding-top:4px;padding-bottom:4px;
426column-gap:2%}#\39 f3f031f{width:100%;align-items:center;min-height:8px;column-gap:0;justify-content:center;flex-direction:column;flex-wrap:nowrap;row-gap:0;padding:0}#\31 1d216b4{width:15%;order:0;justify-self:auto;align-self:auto;margin:0;grid-area:auto/auto/auto/auto}#a052d7aa,#da0131a7{justify-self:auto;grid-area:auto/auto/auto/auto;margin:0}#bff1bb66{width:246px}#a052d7aa{order:0;justify-content:center}#\39 8702d80{min-height:170px}#da0131a7{width:70%;min-height:70px;align-self:auto;order:1}#\39 e5ef93d{justify-self:auto;width:100%;order:0;min-height:32px;align-self:auto;margin:0;grid-area:auto/auto/auto/auto}#\33 aa37ebb{width:15%;justify-content:center;order:2}#\32 e9284f4{align-self:center;margin-left:0;margin-right:0;align-items:center;min-height:80px;--column-gap:6%;column-gap:6%}#\30 ece3d12{justify-self:auto;order:1;justify-content:center;margin:0;grid-area:auto/auto/auto/auto}#daf81bcc.flex-element.widget-wrapper>[data-element-type].flexButton.dmWidget{padding:10px 0}#daf81bcc{width:250px;margin:0}#\34 cb86e4c{align-items:center;min-height:32px}#ec5d46f2{width:340px}#a7708a16{width:100%;min-height:80px}#\37 8db3927{min-height:unset;flex-direction:column}#\30 c6cf26f{margin:0}#\37 ca01c83{width:100%;min-height:0;align-items:flex-start}#\32 4eff763{min-height:0;flex-direction:column;flex-wrap:nowrap;padding:0 4%}#\37 5ba1c41{min-height:0;flex-direction:column;padding-left:4%;padding-right:4%;flex-wrap:nowrap}#\34 f4d3298{width:100%;min-height:80px;align-items:center}#widget_21v{width:55px}}#dm .dmInner div.u_1550316043 .readMore a{font-weight:700!important}#dm .dmInner div.u_1019079231 .dmforminput label:not(.for-checkable):not(.custom-contact-checkable){color:var(--color_6)!important;font-weight:700!important}#dm .dmInner div.u_1019079231 .dmforminput input{color:rgba(0,0,0,1)!important;font-size:14px!important;font-weight:400!important}#dm .dmInner div.u_1563404019 .motFactCont p.rteBlock{font-weight:700!important}#dm .dmInner div.u_1673887128 .dmforminput label:not(.for-checkable):not(.custom-contact-checkable){color:var(--color_6)!important;font-weight:700!important}#dm .dmInner div.u_1673887128 .dmforminput input{color:rgba(0,0,0,1)!important;font-size:14px!important;font-weight:400!important}#dm .dmInner div.u_1019079231 .dmformsubmit,#dm .dmInner div.u_1673887128 .dmformsubmit{font-size:18px!important;width:250px!important;height:50px!important;float:none!important;display:block!important}#dm .dmInner div.u_1673887128 .dmformsubmit{color:rgba(255,255,255,1)!important}#dm .dmInner .u_1013097116,#dm .dmInner .u_1075363601,#dm .dmInner .u_1240178443,#dm .dmInner .u_1309023037,#dm .dmInner .u_1339545085,#dm .dmInner .u_1377724207,#dm .dmInner .u_1609539177,#dm .dmInner .u_1612997669{width:100%!important}#dm .dmInner div.u_1496323151 .motFactCont p.rteBlock{font-weight:700!important}#dm .dmInner div.u_1199098238,#dm .dmInner div.u_1258098665,#dm .dmInner div.u_1531246810,#dm .dmInner div.u_1601347497{direction:ltr!important;text-transform:none!important;font-weight:400!important;text-decoration:none!important;letter-spacing:normal!important;line-height:normal!important;font-style:normal!important}#dm .dmInner div.u_1601347497{text-shadow:none!important;font-size:32px!important;font-family:"Kumbh Sans"!important}#dm .dmInner div.u_1258098665{text-shadow:rgba(0,0,0,.4) 0 0 15px!important;font-size:50px!important;font-family:"Kumbh Sans"!important}#dm .dmInner .u_1783122354 .asst-banner-text o{color:rgba(247,207,207,1)!important}#dm .dmInner div.u_1783122354 .hibu-asst-banner{background-color:rgba(0,0,0,0)!important}#\33 a304ac7,#c7a80d10,#cc0a6f0b{background-color:rgba(0,0,0,0)}#dm .dmInner div.u_1013097116 img{box-shadow:rgba(0,0,0,.25) 3px 0 11px 0!important;border-radius:12px!important}#dm .dmInner div.u_1612997669 img{box-shadow:rgba(0,0,0,.25) 3px 0 11px 0!important;border-radius:12px!important}#dm .dmInner div.u_1309023037 img{box-shadow:rgba(0,0,0,.25) 3px 0 11px 0!important;border-radius:12px!important}#dm .dmInner div.u_1074972305 .svg,#dm .dmInner div.u_1459686468 .svg,#dm .dmInner div.u_1534046080 .svg,#dm .dmInner div.u_1690037632 .svg,#dm .dmInner div.u_1751702735 .svg,#dm .dmInner div.u_1994781342 .svg{fill:var
426(--color_17)!important}#dm .dmInner nav.u_1398948466,#dm .dmInner nav.u_1915042179{color:#000!important}#dm .dmInner div.u_1019079231 .dmformsubmit{color:rgba(255,255,255,1)!important;margin-left:auto!important;margin-right:auto!important}#dm .dmInner div.u_1200929661{text-align:right!important}#dm .dmInner div.u_1011699339,#dm .dmInner div.u_1821793429{text-align:center!important}#dm .dmInner div.u_1658143524 img{border-radius:0!important}#dm .dmInner .u_1336996153 .photoGalleryThumbs .image-container a{background-size:cover!important}#dm .dmInner div.u_1199098238{text-shadow:none!important;font-size:14px!important;font-family:"Kumbh Sans"!important;text-align:center!important}#dm .dmInner div.u_1995568531{text-align:left!important}#dm .dmInner div.u_1531246810{text-shadow:rgba(0,0,0,.4) 0 0 15px!important;font-size:50px!important;font-family:'Bebas Neue'!important;text-align:center!important}@media (min-width:0) and (max-width:767px){#dm .dmInner .u_1496323151 .motFactCont p.rteBlock,#dm .dmInner .u_1563404019 .motFactCont p.rteBlock{line-height:24px!important}#dm .dmInner div.u_1563404019 .motFactCont p.rteBlock{font-size:18px!important}#dm .dmInner div.u_1199098238{font-size:30px!important}#dm .dmInner div.u_1531246810{font-size:40px!important}#dm .dmInner div.u_1496323151 .motFactCont p.rteBlock{font-size:18px!important}#dm .dmInner div.u_1601347497{font-size:30px!important}#dm .dmInner div.u_1258098665{font-size:40px!important}#dm .dmInner .u_1336996153 .layout-container,#dm .dmInner .u_1336996153 .photoGalleryThumbs{padding:2.5px!important}}@media (min-width:1025px){#dm .dmInner .u_1336996153 .caption-inner,#dm .dmInner .u_1597270632 .caption-inner{-webkit-border-top-right-radius:0!important;-webkit-border-bottom-right-radius:0!important;-webkit-border-bottom-left-radius:0!important;-webkit-border-top-left-radius:0!important}#dm .dmInner div.u_1550316043 .readMore a{font-size:14px!important}#dm .dmInner .u_1496323151 .motFactCont p.rteBlock,#dm .dmInner .u_1563404019 .motFactCont p.rteBlock{line-height:30px!important}#dm .dmInner div.u_1073482025 .ucw-card__action,#dm .dmInner div.u_1081741638 .ucw-card__action,#dm .dmInner div.u_1112831207 .copy-block-link-button,#dm .dmInner div.u_1285306804 .copy-block-link-button,#dm .dmInner div.u_1961864555 .ucw-card__action,#dm .dmInner div.u_1989022222 .copy-block-link-button{width:280px!important;height:50px!important}#dm .dmInner .u_1597270632 .caption-inner{border-radius:0!important;-moz-border-radius:0!important;-webkit-border-radius:0!important}#dm .dmInner div.u_1200929661,#dm .dmInner div.u_1613806224,#dm .dmInner div.u_1821793429,#dm .dmInner div.u_1931493629{text-align:center!important}#dm .dmInner .u_1336996153 .caption-inner{border-radius:0!important;-moz-border-radius:0!important;-webkit-border-radius:0!important}#dm .dmInner .u_1336996153 .photoGalleryThumbs .image-container a{padding-top:180px!important}#dm .dmInner .u_1336996153 .layout-container,#dm .dmInner .u_1336996153 .photoGalleryThumbs{padding:2.5px!important}#dm .dmInner div.u_1995568531,#dm .dmInner div.u_1995568531 p{text-align:left!important}[data-version] .font-size-13,[data-version] .size-13{--font-size:13}[data-version] .font-size-20,[data-version] .size-20{--font-size:20}}.collectionherogeo{display:none!important}@media (min-width:768px) and (max-width:1024px){#dm .dmInner .u_1496323151 .motFactCont p.rteBlock,#dm .dmInner .u_1563404019 .motFactCont p.rteBlock{line-height:30px!important}#dm .dmInner div.u_1073482025 .ucw-card__action,#dm .dmInner div.u_1081741638 .ucw-card__action,#dm .dmInner div.u_1112831207 .copy-block-link-button,#dm .dmInner div.u_1961864555 .ucw-card__action,#dm .dmInner div.u_1989022222 .copy-block-link-button{width:280px!important;height:50px!important}#dm .dmInner div.u_1199098238{font-size:31px!important}#dm .dmInner div.u_1531246810{font-size:50px!important}#dm .dmInner div.u_1601347497{font-size:31px!important}#dm .dmInner div.u_1258098665{font-size:50px!important}#dm .dmInner div.u_1658143524 img{object-position:50% 50%!important}#dm .dmInner div.u_1200929661,#dm .dmInner div.u_1931493629,#dm .dmInner div.u_1995568531{text-align:center!important}#dm .dmInner .u_1336996153 .layout-container,#dm .dmInner .u_1336996153 .photoGalleryThumbs{padding:2.5px!important}}#widget_oo7,#widget_r6f{height:auto;max-width:100%}#\38 34a6021::before,#b93fd6a9::before{content:'';display:block;position:absolute;height:100%;top:0;left:0;background-color:rgba(0,0,0,1);opacity:.4;border-radius:inherit}#c1277cd5,#db4fad4c,#group_69j{width:100%;padding:0}#\38 7457d0a,#b63d2dd0{min-height:8px;min-width:4%;padding:16px;column-gap:4%;margin:0;row-gap:24px}#dm .dmInner div.u_1199098238,#dm .dmInner div.u_1258098665,#dm .dmInner div.u_1496323151,#dm .dmInner div.u_1531246810,#dm .dmInner div.u_1563404019,#dm .dmInner div.u_1601347497{color:#fff!important}@media (min-width:0px) and (max-width:767px){#dm .dmInner div.u_1011699339,#dm .dmInner div.u_1931493629{font-size:26px!important}#dm .dmInner div.u_1200929661{text-align:center!important}}#db4fad4c{min-height:8px;column-gap:4%;row-gap:24px;min-width:4%;margin:0}#\31 02296bd{min-height:240px;column-gap:4%;row-gap:24px;width:100%;padding:2% 4%;margin:0}#group_69j{align-items:flex-start;min-height:160px;max-height:100%;row-gap:24px;column-gap:4%;margin:0}#widget_r6f{width:100%}#widget_oo7{width:100%;order:0}#b63d2dd0{width:48%}#\38 7457d0a{width:100%}#c1277cd5{min-height:240px;column-gap:4%;row-gap:24px;flex-wrap:nowrap;margin:0}#\32 47a8c48,#d9479f42{height:auto;max-width:100%;justify-self:auto;width:100%}#\32 47a8c48.flex-element.widget-wrapper>[data-element-type]{padding-left:24px;padding-right:24px;padding-top:12px}#\32 3ae3ea0,#\33 11dd324,#\39 25e7fdf{padding:16px;margin:0;column-gap:4%;min-height:8px;min-width:4%}#\32 47a8c48{order:2;align-self:auto;grid-area:auto/auto/auto/auto}#fc1e2657{align-items:center;width:100%;min-height:160px;max-height:100%;background-color:var(--color_4);background-image:initial;border-radius:8px;box-shadow:rgba(0,0,0,.25) 3px 0 11px 0;align-self:auto;order:0;
426justify-self:auto;padding:24px 0 40px;margin:0;grid-area:auto/auto/auto/auto}#f6abe2be{min-height:676px;column-gap:4%;row-gap:24px;width:100%;flex-wrap:nowrap;padding:80px 4%;margin:0}#d9479f42{order:1;align-self:auto;margin:-20px 0;grid-area:auto/auto/auto/auto}#\31 e175c53,#\33 a5b36e4,#f33d2b9a{justify-self:auto;height:auto;max-width:100%;align-self:auto;grid-area:auto/auto/auto/auto}#e76e903e{width:100%;height:auto;max-width:100%;order:1;align-self:stretch}#\33 11dd324{width:33.93%;row-gap:24px}#\31 e175c53{width:100%;order:0;margin:0}#\33 a5b36e4,#f33d2b9a{width:auto;order:2}#b7ff358b{width:280px;height:auto;max-width:100%;order:5;justify-self:auto;align-self:auto;margin:0;grid-area:auto/auto/auto/auto}#b93fd6a9::before{width:100%}#b93fd6a9{background-image:url(https://le-cdn.hibuwebsites.com/md/dmip/dms3rep/multi/opt/black-jeans-1920w.png);background-position:50% 0}#\32 3ae3ea0,#\39 25e7fdf{row-gap:16px;width:62.07%;align-items:center}#ea683628,#eb06105c{height:auto;max-width:100%;justify-self:auto}#eb06105c.flex-element.widget-wrapper>[data-element-type].flexButton.dmWidget{padding-left:0;padding-right:0}#eb06105c{width:280px;min-height:52px;align-self:auto;order:5;grid-area:auto/auto/auto/auto}#c0c8fb07{min-height:676px;column-gap:4%;row-gap:24px;width:100%;flex-wrap:nowrap;padding:80px 4%;margin:0}#ea683628{width:100%;order:1;align-self:auto;margin:-20px 0;grid-area:auto/auto/auto/auto}#\34 a684f71,#f5745250{justify-self:auto;margin:0;grid-area:auto/auto/auto/auto;max-width:100%;align-self:auto;height:auto}#\30 7850ad3{width:33.93%;min-width:4%;min-height:8px;column-gap:4%;row-gap:24px;padding:16px;margin:0}#e154016c{width:100%;height:auto;max-width:100%;order:1;align-self:stretch}#\34 a684f71{width:100%;order:0}#f5745250{width:280px;order:5}#\38 34a6021::before{width:100%}#\38 34a6021{background-image:url(https://le-cdn.hibuwebsites.com/md/dmip/dms3rep/multi/opt/black-jeans-1920w.png)}#d761791c{align-items:center;width:100%;min-height:160px;max-height:100%;background-color:var(--color_4);background-image:initial;border-radius:8px;box-shadow:rgba(0,0,0,.25) 3px 0 11px 0;align-self:auto;order:0;justify-self:auto;padding:24px 0 40px;margin:0;grid-area:auto/auto/auto/auto}#\37 ebd781d.flex-element.widget-wrapper>[data-element-type]{padding-left:24px;padding-right:24px;padding-top:12px}#eb7ed250,#fd4f79eb{padding:0 16px;width:100%}#\35 fecb840,#c5b2e9f3{padding:0 4%;min-height:160px;row-gap:12px;order:0}#\32 b871182,#\33 7eaf874,#\39 56767f0,#f41605eb{max-width:none;padding:2% 4%}#\37 ebd781d{width:100%;height:auto;max-width:100%;justify-self:auto;order:2;align-self:auto;grid-area:auto/auto/auto/auto}#\37 72b1abe,#bf1af1cf{flex-direction:row;grid-area:auto/auto/auto/auto;margin:0;max-height:100%;column-gap:4%;row-gap:24px}#bf1af1cf{align-items:flex-start;width:100%;min-height:160px;justify-self:auto;align-self:center;order:1;padding:1% 0}#\37 fcf5600{width:100%;height:auto;max-width:100%;order:0;align-self:center}#\37 72b1abe{align-items:center;width:49.38%;min-height:227px;align-self:auto;order:0;height:auto;align-content:center;justify-content:flex-start;padding:0}#f34f2047{flex-direction:row;align-items:flex-start;width:33.54%;min-height:auto;max-height:100%;row-gap:24px;column-gap:4%;padding:0;margin:0}#\38 9822ae5{width:100%;height:auto;max-width:100%;order:0;margin:0;grid-area:auto/auto/auto/auto}#\39 f4eb432{width:557px;height:229px;max-width:100%;align-self:flex-start}#\32 6a403a5{min-height:8px;column-gap:4%;row-gap:12px;width:100%;min-width:4%;padding:0;margin:0}#\39 56767f0{min-height:371px;column-gap:4%;row-gap:24px;width:100%;flex-wrap:nowrap;margin:0}#\36 0801b00{margin:0}#\38 b50854f{margin-top:4px;margin-bottom:4px}#\33 a304ac7{min-height:8px;column-gap:4%;row-gap:0;width:100%;min-width:4%;padding:0;margin:0}#\30 10de6f0{border-width:0;border-color:rgba(0,0,0,1);border-style:solid;background-color:rgba(138,14,14,1);background-image:initial}#c740231e{min-height:70px;column-gap:0;row-gap:0;max-width:none;width:100%;flex-wrap:nowrap;padding:0;margin:0}#\37 d294100{width:100%;height:auto;max-width:100%;align-self:center}#\33 624ae24,#\34 1895274,#\39 5b687ee,#a0600711,#bba80199,#fe06e649{align-items:flex-start;width:100%;min-height:auto;max-height:100%;row-gap:24px;column-gap:24px;min-width:32px;padding:0;margin:0}#\31 3b740b5,#\34 ac657c2,#\35 2a3e795,#\36 95cf79f,#\37 2710297,#\38 87b741a{width:100%;height:auto;max-width:100%}#eb7ed250{flex-direction:row;align-items:flex-start;min-height:auto;max-height:100%;row-gap:24px;column-gap:3%;min-width:32px;order:1;flex-wrap:nowrap;--column-gap:3%;margin:0}#\34 08cb3a4,#\35 0eaa52b,#\37 70edb16{align-items:flex-start;width:31.84%;min-height:auto;max-height:100%;row-gap:36px;column-gap:4%;flex-wrap:nowrap;min-width:32px;justify-self:auto;align-self:auto;order:0;align-content:flex-start;padding:0;margin:0;grid-area:auto/auto/auto/auto}#\34 53841c5,#\35 1c53a36,#\37 39a2bb2,#bb3c20db,#e997ae28,#f2bd066a{align-items:center;width:17.51%;min-height:auto;max-height:100%;row-gap:24px;column-gap:24px;min-width:32px;padding:0;margin:0}#\37 a97158a,#dacd5ea6{width:50px;height:auto;max-width:100%}#\30 77a1c49{min-height:8px;column-gap:4%;row-gap:20px;width:100%;min-width:4%;flex-wrap:nowrap;background-color:var(--color_15);background-image:none;border-radius:50px;align-items:center;padding:2% 16px 5%;margin:3% 0}#\39 044eabf,#\39 088eade{width:45px;height:auto;max-width:100%}#\31 1b15313,#\34 d2c275d,#\35 86fa04f,#\36 34b917c,#\38 46101b8,#a19b1af3{align-items:center;width:100%;min-height:auto;max-height:100%;row-gap:24px;column-gap:4%;min-width:32px;flex-direction:row;justify-content:flex-start;padding:0;margin:0}#e7b41ab5,#f90f9993{width:100%;height:auto;max-width:100%;justify-self:auto;align-self:center;order:0;margin:0;grid-area:auto/auto/auto/auto}#\36 e382563{min-height:287px;column-gap:4%;row-gap:24px;width:100%;flex-wrap:nowrap;max-width:none;padding:0 2%;margin:0}#\33 f00c98a{width:55px;height:auto;max-width:100%}#bfcf289f{width:191px;height:auto;max-width:100%}#\30 a8502bd{width:40px;height:auto;max-width:100%}#\30 69c84b9{align-items:flex-start;width:100%;min-height:auto;max-height:100%;row-gap:24px;column-gap:24px;min-width:32px;order:0;margin:0}#c7a80d10{min-height:8px;column-gap:4%;row-gap:24px;width:48%;min-width:4%;background-image:url(https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/Screen+Shot+2024-10-04+at+4.03.11+PM-1920w.png);padding:0;margin:0}#\32 b871182,#\33 7eaf874{min-height:300px;column-gap:4%;row-gap:24px;width:100%;flex-wrap:nowrap;margin:0}#\33 1491e36,#c968f3db,#d04bb848{width:100%;height:auto;max-width:100%;align-self:auto;justify-self:auto;order:0;margin:0;grid-area:auto/auto/auto/auto}#\34 7ab8901{width:48%;min-width:4%;min-height:8px;column-gap:4%;row-gap:24px;padding:16px;margin:0}#\39 c18e540{width:48%;min-width:4%;min-height:8px;column-gap:4%;row-gap:24px;order:0;padding:0;margin:0}#cc0a6f0b{min-height:8px;column-gap:4%;row-gap:24px;width:48%;min-width:4%;order:1;justify-content:flex-start;padding:0;margin:0}#\33 1eabdad,#\33 91d01b6,#f1a40cb8{justify-self:auto;grid-area:auto/auto/auto/auto;order:1;margin:0;max-width:100%;align-self:center}#\38 c90c0c5{background-color:var(--color_5);background-image:initial}#fd4f79eb{min-height:8px;column-gap:4%;row-gap:0;min-width:4%;margin:0}#\33 91d01b6{width:280px;height:auto}#\31 0c045d3{min-height:auto;column-gap:4%;row-gap:24px;width:100%;flex-wrap:nowrap;padding:0 0 3%;margin:0}#\33 1eabdad,#f1a40cb8{width:497px;height:300px}#\32 f017a1e,#\33 1a4120b,#\35 32702e9,#\36 6ced809,#\37 8686da5,#c41184f1,#d393fda6,#e149f88b{width:280px;height:auto;max-width:100%;order:2;align-self:flex-start;justify-self:auto;margin:0;grid-area:auto/auto/auto/auto}#c5b2e9f3{align-items:flex-start;width:90.09%;max-height:100%;column-gap:4%;margin:0}#\30 5385236,#\30 c817c75,#\31 851ad42,#\31 c1c3a9d,#\33 2ada83b,#\39 1d5b8cf,#\39 4b20f24,#\39 60cc391,#\39 ef4de34,#b42a1ab1,#b9bdc61f,#d2790430,#dc50b6a9,#e0b5accd,#e3df7ab4,#f2b43354,#f8bde178{width:100%;height:auto;max-width:100%;justify-self:auto;align-self:auto;order:1;grid-area:auto/auto/auto/auto}#\39 eb55001{width:280px;height:auto;max-width:100%;order:2;justify-self:auto;margin:0;grid-area:auto/auto/auto/auto}#\35 9867e38,#cb51b1aa{width:100%;height:auto;min-height:auto;max-width:100%;order:1}#\32 c859d2b{min-height:8px;column-gap:4%;row-gap:0;width:100%;align-items:center;min-width:4%;justify-content:space-between;order:0;padding:0;margin:0}#d47c231b{width:280px;height:auto;max-width:100%;order:2}#\35 fecb840{align-items:flex-start;width:89.93%;max-height:100%;column-gap:4%;justify-self:auto;align-self:center;margin:0;grid-area:auto/auto/auto/auto}#\30 90b2b56,#\32 9c654ba,#\33 3274bb5,#\33 65a42d7,#\35 e664023,#\35 f16df0b,#\36 e455d52,#\37 dfcbffb,#\38 64c2572,#a0142848,#f4692065,#f5388d9b,#f743cc5a{justify-self:auto;height:auto;max-width:100%;grid-area:auto/auto/auto/auto;align-self:auto;margin:0;width:100%;order:1}#\30 90b2b56,#\33 65a42d7,#\38 64c2572,#f4692065,#f743cc5a{min-height:auto}#\30 8cb43a3,#\31 97acacc,#\31 a71802f,#\31 a99e305,#\32 025e18d,#\32 3c9f491,#\34 d7cc87c,#\35 95896c0,#\36 6755e5c,#\38 759bcc7,#\39 857361e,#b43ac9aa,#c01dfdd3,#c88e97e7,#e11a54e7,#f4d0fb72{width:99.99%;height:auto;max-width:100%;justify-self:auto;align-self:auto;order:2;grid-area:auto/auto/auto/auto}#\33 3d16e54,#\33 503b1a5,#\34 3b5ab23,#\34 3e52408,#\34 507fbf6,#\36 e8ed22a,#\37 1fc29cf,#\37 8baf59c,#\38 bf60ab1,#\38 ffccd7d,#b8d30172,#d92a1dc1,#e3a396de,#f0c17362,#f33e681e{align-items:flex-start;width:100%;min-height:160px;max-height:100%;row-gap:12px;column-gap:4%;order:0;
426justify-self:auto;align-self:auto;padding:0;margin:0;grid-area:auto/auto/auto/auto}#\32 94378e9{min-height:8px;column-gap:4%;row-gap:24px;width:100%;align-items:center;min-width:4%;justify-content:space-between;order:0;padding:0;margin:0}#d0493b23,#fad57111{justify-self:auto;margin-left:0;margin-right:0;grid-area:auto/auto/auto/auto;height:auto;max-width:100%;align-self:center}#d0493b23{width:100%;order:1}#acc30245{min-height:8px;column-gap:4%;row-gap:0;width:100%;align-items:center;min-width:4%;justify-content:space-between;padding:0;margin:0}#fad57111{width:498px;order:2}#\38 b49f88e{width:499px;height:auto;max-width:100%;justify-self:auto;align-self:center;order:2;margin-left:0;margin-right:0;grid-area:auto/auto/auto/auto}#\37 f166c5e{min-height:635px;column-gap:3%;row-gap:18px;width:100%;flex-wrap:nowrap;max-width:none;padding:40px 4%;margin:0}#\34 aca3327,#bc3e1e75{min-height:389px;column-gap:3%;row-gap:18px;width:100%;flex-wrap:nowrap;max-width:none;padding:20px 4%;margin:0}#ace36cc1,#faf33040{background-color:rgba(255,255,255,1)}#\31 03f9f3c,#\32 f6610a6,#\33 f44cc34,#\34 d625200,#\36 8b2ac2a,#bed4f072,#c4fd38ba,#e25abd91{width:280px;height:50px;max-width:100%;order:1;align-self:flex-start}#\30 d97b47b,#\39 5746a2b,#bd628c30,#cfd2a0a5,#e429ca1a{min-height:8px;column-gap:4%;row-gap:24px;width:31.33%;align-items:center;min-width:4%;justify-content:space-between;order:0;padding:0;margin:0}#\32 531cd2c,#\39 5e5c437,#a428f415{width:100%;height:250px;max-width:100%;justify-self:auto;align-self:auto;order:1;margin:0;grid-area:auto/auto/auto/auto}#\38 1ceb6f7,#be0780ee{min-height:8px;column-gap:4%;row-gap:24px;width:31.33%;align-items:center;min-width:4%;justify-content:space-between;padding:0;margin:0}#\37 3cd90f9,#\37 4e954e5,#\39 7ebc092,#dae1bdaf,#ee744b36{width:100%;height:200px;max-width:100%;justify-self:auto;align-self:auto;order:0;grid-area:auto/auto/auto/auto}#\38 239d73b{min-height:8px;column-gap:4%;row-gap:24px;width:48.5%;align-items:center;min-width:4%;justify-content:space-between;order:0;padding:0;margin:0}#\32 cc5b3d3{width:100%;height:auto;max-width:100%;order:2;justify-self:auto;align-self:auto;margin:0;grid-area:auto/auto/auto/auto}#\31 891fe74,#\34 33db674,#\37 9911bf3,#f9fdd538{justify-self:auto;grid-area:auto/auto/auto/auto;max-width:100%;align-self:auto;height:auto}#\37 9911bf3{width:67.89%;order:1}#\31 891fe74,#\34 33db674,#f9fdd538{width:100%;order:0;margin:0}#be21207b{width:60px;height:auto;max-width:100%;order:1;justify-self:auto;align-self:auto;margin:0;grid-area:auto/auto/auto/auto}#f41605eb{min-height:240px;column-gap:4%;row-gap:24px;width:100%;flex-wrap:nowrap;margin:0}#fa881aa5{min-height:8px;column-gap:4%;row-gap:24px;width:100%;min-width:4%;padding:16px 0;margin:0}#\35 042981a,#cc48b184{width:280px;height:auto;max-width:100%;justify-self:auto;align-self:center;order:0;margin:0;grid-area:auto/auto/auto/auto}#\34 acec404,#\38 9c64c77,#\38 be0f7d6,#cac62dd6{justify-content:flex-start;width:33%;row-gap:8px;column-gap:4%;padding:0;min-height:auto;max-height:100%;margin:0;grid-area:auto/auto/auto/auto}#\34 acec404,#cac62dd6{align-items:center;flex-wrap:nowrap;justify-self:auto;order:2}#\38 9c64c77,#\38 be0f7d6{align-items:center;flex-wrap:nowrap;justify-self:auto;order:1}#\31 2f77a0f,#\38 c85ee6f,#\39 a7d492b,#ae6ec156,#eb7c8fdb,#efb87c9b{width:51px;height:auto;max-width:100%;order:0;align-self:auto;margin:0;grid-area:auto/auto/auto/auto}#\30 8a7d21c{justify-content:flex-start;align-items:center;width:33%;min-height:auto;max-height:100%;row-gap:8px;column-gap:4%;flex-wrap:nowrap;justify-self:auto;order:0;padding:0;margin:0;grid-area:auto/auto/auto/auto}#e81bdbf2{flex-direction:row;align-items:flex-start;width:100%;min-height:139px;max-height:100%;row-gap:24px;column-gap:0;align-self:auto;flex-wrap:nowrap;justify-self:auto;order:2;height:auto;padding:0;margin:0;grid-area:auto/auto/auto/auto}#a6a9fe96{justify-content:flex-start;align-items:center;width:33%;min-height:auto;max-height:100%;row-gap:8px;column-gap:4%;justify-self:auto;order:0;flex-wrap:nowrap;padding:0;margin:0;grid-area:auto/auto/auto/auto}#\38 d04ab49{flex-direction:row;justify-content:flex-start;align-items:flex-start;width:50%;min-height:auto;max-height:100%;row-gap:24px;column-gap:24px;justify-self:auto;align-self:auto;order:0;margin:0;grid-area:auto/auto/auto/auto}#\33 198bf07,#\33 dc47e81,#\38 b18b1f2,#\38 b276c7c{height:auto;max-width:100%;justify-self:auto;align-self:auto;width:100%}#\33 198bf07{order:0;margin:0;grid-area:auto/auto/auto/auto}#\33 dc47e81,#\38 b18b1f2,#\38 b276c7c{order:1;margin:0;grid-area:auto/auto/auto/auto}#\34 c13680b,#bde63803{height:auto;max-width:100%;justify-self:auto;margin:0;grid-area:auto/auto/auto/auto}#bde63803{width:191px;align-self:auto;order:1}#\34 c13680b{width:64.98%;align-self:auto;order:1}#\33 4e2b901,#bbc5dc4e{height:auto;max-width:100%;justify-self:auto;align-self:auto;order:1}#bbc5dc4e{width:99.75%;margin:0;grid-area:auto/auto/auto/auto}#\33 4e2b901{width:546px;margin:0;grid-area:auto/auto/auto/auto}#\30 9044853,#\32 cfff530,#e29987ca{justify-self:auto;height:auto;max-width:100%;margin:0;grid-area:auto/auto/auto/auto}#\30 9044853,#e29987ca{width:280px;order:3;align-self:auto}#\32 cfff530{width:100%;order:1}#\31 b714432{width:527px;height:auto;max-width:100%;justify-self:auto;order:1;margin:0;grid-area:auto/auto/auto/auto}@media (min-width:768px) and (max-width:1024px){#\32 6a403a5,#d761791c,#fc1e2657{padding-left:0;padding-right:0}#\34 53841c5,#\35 1c53a36,#bb3c20db,#f2bd066a{width:60px}#\30 7850ad3,#\33 11dd324,#a19b1af3,#e997ae28{margin-left:0;margin-right:0}#\35 0eaa52b,#a19b1af3,#eb7ed250{align-content:flex-start}#\34 ac657c2,#\35 0eaa52b,#a19b1af3{align-self:flex-start}#\31 0c045d3,#\34 aca3327,#\36 e382563,#\37 f166c5e,#\39 56767f0,#bc3e1e75,#c1277cd5,#f41605eb{padding-left:2%;padding-right:2%}#\31 02296bd{padding:1%}#db4fad4c{flex-direction:row;column-gap:1%;padding:0}#group_69j{width:100%;order:2;row-gap:16px}#widget_r6f{width:100%}#c0c8fb07,#f6abe2be{padding-top:100px;padding-bottom:20px;flex-direction:column;flex-wrap:nowrap;min-height:0}#\30 7850ad3,#\33 11dd324{width:100%;min-height:80px;padding:8px 10%}#\32 3ae3ea0,#\39 25e7fdf,#\39 c18e540,#bd628c30,#cfd2a0a5{width:100%;min-height:80px}#bf1af1cf{flex-direction:column;flex-wrap:nowrap;margin:0}#\37 2710297,#f34f2047{justify-self:auto;align-self:auto;margin:0;grid-area:auto/auto/auto/auto}#\37 fcf5600{margin:0}#\37 72b1abe{width:100%;order:0;margin:0}#f34f2047{width:100%;order:1}#\32 6a403a5{flex-direction:column;flex-wrap:nowrap}#\39 f4eb432{width:680px;height:500px}#\33 624ae24,#\34 1895274,#a0600711,#fe06e649{width:100%;padding:0 16px;margin:0}#\37 2710297{width:124px;order:0}#\35 2a3e795,#\36 95cf79f,#bfcf289f{align-self:auto;width:100.01%;justify-self:auto;order:0;margin:0;grid-area:auto/auto/auto/auto}#eb7ed250{flex-direction:row;flex-wrap:nowrap;row-gap:8px;min-width:32px;
426column-gap:2%;align-self:center;align-items:flex-start;--column-gap:2%;justify-content:center;width:100%;padding:0;margin:0}#\37 70edb16{min-width:32px;width:32%;row-gap:10px;margin:0}#\34 ac657c2{width:83.32%;justify-self:auto;order:0;margin:0;grid-area:auto/auto/auto/auto}#\30 77a1c49{row-gap:10px;flex-direction:column;flex-wrap:nowrap;width:100%;padding:2% 16px 5%;margin:3% 0}#\39 5b687ee{padding:0 16px;margin:0}#\37 39a2bb2{width:55.34px}#\31 3b740b5{align-self:auto;width:178px;justify-self:auto;order:0;margin:0;grid-area:auto/auto/auto/auto}#\31 1b15313,#\35 86fa04f,#\36 34b917c{column-gap:0;min-height:80px;align-items:flex-start}#bba80199{row-gap:0;align-items:center;width:91.48%;align-content:center;padding:0 16px;margin:0}#e997ae28{row-gap:0;width:55.84px}#a19b1af3{width:100%;column-gap:0;min-height:80px;align-items:flex-start;justify-content:flex-start;flex-direction:row;flex-wrap:nowrap;max-width:100%}#\34 08cb3a4{min-width:32px;width:32%;row-gap:10px;column-gap:4%;flex-direction:column;flex-wrap:nowrap;align-items:center;align-content:center;margin:0}#\34 d2c275d,#\38 46101b8{column-gap:0;align-items:flex-start;margin-right:0;margin-left:0;min-height:80px;width:100%}#\30 69c84b9{min-width:32px;margin:0}#\38 46101b8{flex-direction:row;flex-wrap:nowrap}#f2bd066a{margin-right:0;margin-left:0}#\35 0eaa52b{min-width:32px;width:32%;row-gap:10px;align-items:flex-start;margin:0}#\30 a8502bd,#\33 f00c98a,#\37 a97158a,#dacd5ea6{width:45px}#\38 239d73b,#c7a80d10{width:49%;min-height:8px}#\33 7eaf874{flex-direction:row;flex-wrap:nowrap;min-height:300px;column-gap:2%}#\34 7ab8901{width:100%;min-height:8px}#\32 b871182{flex-direction:column;flex-wrap:nowrap;min-height:0;row-gap:0}#cc0a6f0b{flex-direction:column;flex-wrap:nowrap;width:100%;min-height:80px}#\32 c859d2b{width:100%;min-height:523px;height:auto;margin:0}#\32 94378e9{width:100%;min-height:80px;margin:0}#acc30245{width:100%;row-gap:0;min-height:547px;height:auto;margin:0}#\34 aca3327,#\37 f166c5e{column-gap:2%;flex-direction:column;flex-wrap:nowrap;min-height:0}#\38 b49f88e,#fad57111{width:688px}#bc3e1e75{column-gap:2%;flex-direction:row;flex-wrap:nowrap;min-height:389px}#be0780ee{width:32%;row-gap:20px;min-height:8px;margin:0}#\38 1ceb6f7{width:100%;row-gap:20px;min-height:80px;margin:0}#\30 d97b47b,#\39 5746a2b,#e429ca1a{width:32%;min-height:8px}#e81bdbf2{align-items:flex-start;justify-self:auto;align-self:auto;width:100%;order:2;flex-direction:column;flex-wrap:nowrap;margin:0;grid-area:auto/auto/auto/auto}#\36 a488ed3,#\38 031eca6{justify-self:auto;align-self:auto;width:100%;order:0;margin:0;grid-area:auto/auto/auto/auto}[data-version] .t-font-size-13,[data-version] .t-size-13{--font-size:13}[data-version] .t-font-size-17,[data-version] .t-size-17{--font-size:17}}@media (max-width:767px){#\32 b871182,#c1277cd5{padding-left:4%;padding-right:4%}#c740231e,#fa881aa5{padding-left:0;padding-right:0}#\32 47a8c48,#\33 a5b36e4,#\37 72b1abe,#\37 ebd781d,#e81bdbf2,#f33d2b9a{align-self:auto;grid-area:auto/auto/auto/auto}#\32 6a403a5,#\38 7457d0a,#\39 c18e540,#b63d2dd0,#db4fad4c,#fd4f79eb{width:100%;min-height:80px;align-items:center}#\31 02296bd,#\31 0c045d3,#\33 7eaf874,#\36 e382563,#\39 56767f0,#f41605eb{min-height:0;flex-direction:column;padding-left:4%;padding-right:4%;flex-wrap:nowrap}#c1277cd5{min-height:unset;flex-direction:column}#\32 47a8c48,#\37 ebd781d{justify-self:auto;width:100%;order:1;margin:0}#c0c8fb07,#f6abe2be{min-height:0;flex-direction:column;flex-wrap:nowrap;row-gap:0;padding:60px 4% 40px}#\30 7850ad3,#\33 11dd324{width:100%;min-height:80px;align-items:center;padding:8px}#\33 a5b36e4,#f33d2b9a{justify-self:auto;order:4;margin:16px 0}#bf1af1cf,#c740231e{flex-direction:column}#b7ff358b,#f5745250{order:2}#\32 3ae3ea0,#\39 25e7fdf{min-height:80px;width:100%;padding:0}#bf1af1cf{flex-wrap:nowrap}#\37 72b1abe{justify-self:auto;width:100%;order:0;margin:0}#f34f2047{order:1;width:100%;margin:0}#\32 531cd2c,#\37 3cd90f9,#\37 4e954e5,#\39 5e5c437,#\39 7ebc092,#\39 f4eb432,#a428f415,#dae1bdaf,#ee744b36{height:240px}#\33 a304ac7{min-height:100px;align-items:center;width:100%}#c740231e{min-height:0;flex-wrap:nowrap;row-gap:0}#\33 624ae24,#\34 1895274,#\39 5b687ee,#a0600711,#bba80199,#fe06e649{padding:0;margin:0}#\37 2710297{width:59.98%}#eb7ed250{flex-direction:column;flex-wrap:nowrap;row-gap:16px}#\30 77a1c49,#c7a80d10{align-items:center;width:100%}#\34 08cb3a4,#\37 70edb16{min-width:32px;width:100%;row-gap:16px;margin:0}#\34 53841c5,#\35 1c53a36,#\37 39a2bb2,#bb3c20db,#e997ae28,#f2bd066a{width:30%}#\30 77a1c49{min-height:80px;flex-direction:column;flex-wrap:nowrap;row-gap:0;padding:4% 16px 8%;margin:3% 0}#\35 0eaa52b{min-width:32px;width:100%;row-gap:16px;margin:-3px 0 0}#\34 ac657c2{width:86.92%}#bfcf289f{width:159px}#\31 3b740b5{width:88.95%}#c7a80d10{min-height:171px;flex-direction:column;flex-wrap:nowrap;height:auto}#\34 7ab8901{width:100%;min-height:80px;align-items:center;padding:0}#\32 b871182{min-height:0;flex-direction:column;flex-wrap:nowrap;row-gap:0}#cc0a6f0b{min-height:80px;align-items:center;width:100%;flex-direction:column;flex-wrap:nowrap}#\33 91d01b6{margin:0}#\30 d97b47b,#\32 94378e9,#\32 c859d2b,#\38 1ceb6f7,#\38 239d73b,#\39 5746a2b,#acc30245,#bd628c30,#be0780ee,#cfd2a0a5,#e429ca1a{width:100%;min-height:80px;row-gap:10px}#\34 aca3327,#\37 f166c5e,#bc3e1e75{min-height:0;flex-direction:column;row-gap:25px;flex-wrap:nowrap;padding:20px 4%}#fa881aa5{width:100%;min-height:80px;align-items:center}#e81bdbf2{flex-direction:column;flex-wrap:nowrap;row-gap:0;justify-self:auto;width:100%;order:1;margin:0}[data-version] .m-font-size-13,[data-version] .m-size-13{--font-size:13}[data-version] .m-font-size-16,[data-version] .m-size-16{--font-size:16}}#dmRoot:not(.editGrid) .flex-element [data-anim-extended]{visibility:hidden}@font-face{font-family:"Roboto Fallback";src:local('Arial');ascent-override:92.6709%;
426descent-override:24.3871%;size-adjust:100.1106%;line-gap-override:0}@font-face{font-family:"Poppins Fallback";src:local('Arial');ascent-override:92.326%;descent-override:30.7753%;line-gap-override:8.793%;size-adjust:113.7274%}@font-face{font-family:"Kumbh Sans Fallback";src:local('Arial');ascent-override:93.9558%;descent-override:24.1866%;size-adjust:104.9779%;line-gap-override:0}@font-face{font-family:"Bebas Neue Fallback";src:local('Arial');ascent-override:116.5002%;descent-override:38.8334%;size-adjust:77.2531%;line-gap-override:0}@media (min-width:1025px){#\30 190983d,#\30 43a130b,#\30 4e97c1c,#\30 5e0ee19,#\30 69c84b9,#\30 77a1c49,#\30 7850ad3,#\30 8a7d21c,#\30 d97b47b,#\30 fd36ae1,#\31 136789265,#\31 1b15313,#\31 234177366,#\31 343909481,#\31 401180572,#\31 459911792,#\31 550316043,#\31 801032432,#\31 956183133,#\32 3ae3ea0,#\32 6a403a5,#\32 94378e9,#\32 c859d2b,#\32 e3386d5,#\33 11dd324,#\33 3d16e54,#\33 503b1a5,#\33 624ae24,#\33 710bc01,#\33 a2d0b90,#\33 a304ac7,#\33 b22d9b0,#\34 08cb3a4,#\34 1895274,#\34 23fc4a2,#\34 3b5ab23,#\34 3e52408,#\34 507fbf6,#\34 53841c5,#\34 7ab8901,#\34 cb86e4c,#\34 d2c275d,#\34 efeffee,#\34 f4d3298,#\35 0eaa52b,#\35 1c53a36,#\35 86fa04f,#\35 a572945,#\35 d62f936,#\35 fecb840,#\36 0f88d37,#\36 34b917c,#\36 3a049320d35b55b4ef2a374,#\36 3a049320d35b55b4ef2a377,#\36 406026c90e1521f6ecb0ecc,#\36 406026c90e1521f6ecb0ecd,#\36 881434d,#\36 a488ed3,#\36 e8ed22a,#\37 1fc29cf,#\37 39a2bb2,#\37 5ba1c41,#\37 6e4141e,#\37 70edb16,#\37 8baf59c,#\37 8db3927,#\37 ca01c83,#\38 031eca6,#\38 1ceb6f7,#\38 46101b8,#\38 7457d0a,#\38 78b0320,#\38 bf60ab1,#\38 caf0a70,#\38 ffccd7d,#\39 25e7fdf,#\39 5b687ee,#\39 7a630cf,#\39 8702d80,#\39 c18e540,#a019b36e,#a0600711,#a19b1af3,#a6a9fe96,#a7708a16,#acc30245,#ad9cb284,#b70daeaf,#b8d30172,#ba24d823,#bb3c20db,#bba80199,#bc7c6f5d,#bcb9e9b3,#bd628c30,#be0780ee,#bf57f545,#c5b2e9f3,#c7a80d10,#cfd2a0a5,#d0234170,#d200b2f7,#d3a805c8,#d761791c,#d92a1dc1,#da69dd01,#db4fad4c,#de6ec6ce,#e3a396de,#e429ca1a,#e997ae28,#f0c17362,#f2bd066a,#f2debc4b,#f33e681e,#f6abe2be,#fa881aa5,#fc1e2657,#fd4f79eb,#fe06e649,#group_69j,#group_9n6,#hamburger-drawer{order:0}#\31 136789265,#\31 1b15313,#\31 234177366,#\31 343909481,#\31 401180572,#\31 459911792,#\31 801032432,#\31 956183133,#\32 e3386d5,#\33 a2d0b90,#\34 cb86e4c,#\34 d2c275d,#\34 efeffee,#\35 86fa04f,#\36 34b917c,#\36 3a049320d35b55b4ef2a377,#\36 406026c90e1521f6ecb0ecc,#\37 5ba1c41,#\37 8db3927,#\38 46101b8,#a19b1af3,#f6abe2be{flex-direction:row}#\30 0841c9d,#\30 8465346,#\30 ece3d12,#\31 035845042,#\31 105358164,#\31 191767750,#\31 199369758,#\31 201338092,#\31 338154768,#\31 398948466,#\31 412984898,#\31 507374835,#\31 524906790,#\31 610592242,#\31 612329860,#\31 723750523,#\31 869341664,#\31 915042179,#\31 968129260,#\31 986032916,#\31 997567173,#\31 ac20e54,#\32 a7169e0,#\34 0dfebdf,#\34 16ce683,#\35 91f9133,#\36 405d24c,#\36 af78587,#\36 e06962d,#\37 72b1abe,#\38 d04ab49,#\39 360b347,#\39 56767f0,#\39 e5ef93d,#b7a700bf,#be1b9f91,#c0c8fb07,#ca073e0e,#cf93363d,#d027d36f,#f34f2047,#group_23b,#group_7in,#group_jjh,#group_tbn{order:0;flex-direction:row}#\32 e9284f4,#a052d7aa,#bf1af1cf,#e3dfb55d,#eb7ed250{order:1;flex-direction:row}#\30 5385236,#\30 90b2b56,#\30 ad35782,#\30 b55734b,#\30 c817c75,#\31 03f9f3c,#\31 851ad42,#\31 b0d613d,#\31 b714432,#\31 c1c3a9d,#\32 531cd2c,#\32 9c654ba,#\32 cfff530,#\32 f6610a6,#\33 1eabdad,#\33 2ada83b,#\33 3274bb5,#\33 4e2b901,#\33 65a42d7,#\33 91d01b6,#\33 dc47e81,#\33 f44cc34,#\34 c13680b,#\34 d625200,#\35 9867e38,#\35 e664023,#\35 f16df0b,#\36 8b2ac2a,#\36 a5bfb4c,#\36 e455d52,#\36 f8e19aa,#\37 9911bf3,#\37 dfcbffb,#\38 64c2572,#\38 7c43c22,#\38 9c64c77,#\38 b18b1f2,#\38 b276c7c,#\38 be0f7d6,#\39 1d5b8cf,#\39 264746f,#\39 4b20f24,#\39 5e5c437,#\39 60cc391,#\39 817662a,#\39 89e011e,#\39 ef4de34,#a0142848,#a428f415,#b42a1ab1,#b9bdc61f,#bbc5dc4e,#bd946f29,#bde63803,#be21207b,#bed4f072,#c4fd38ba,#c7f3ddf3,#cb51b1aa,#cc0a6f0b,#d0493b23,#d2790430,#d9479f42,#da0131a7,#dc50b6a9,#e0b5accd,#e154016c,#e25abd91,#e3df7ab4,#e76e903e,#ea683628,#f1a40cb8,#f2b43354,#f4692065,#f5388d9b,#f743cc5a,#f8bde178,#fe222c1c{order:1}#\31 48da2d9,#\33 aa37ebb,#e81bdbf2{order:2;flex-direction:row}#\30 8cb43a3,#\31 97acacc,#\31 a71802f,#\31 a99e305,#\32 025e18d,#\32 3c9f491,#\32 47a8c48,#\32 cc5b3d3,#\32 f017a1e,#\33 1a4120b,#\33 a5b36e4,#\34 acec404,#\34 d7cc87c,#\35 02c2597,#\35 32702e9,#\35 95896c0,#\35 cbebde5,#\36 18f39ae,#\36 6755e5c,#\36 6ced809,#\37 8686da5,#\37 ebd781d,#\38 759bcc7,#\38 b49f88e,#\39 857361e,#\39 eb55001,#a8f32aec,#b43ac9aa,#bd7b2692,#c01dfdd3,#c41184f1,#c88e97e7,#cac62dd6,#d393fda6,#d47c231b,#e
42611a54e7,#e149f88b,#f33d2b9a,#f4d0fb72,#fad57111{order:2}#\31 db7e0c7,#\38 5709a0b,#b7ff358b,#eb06105c,#f5745250,#widget_21v,#widget_9dv{order:5}#\30 9044853,#d0a778c9,#e29987ca,#widget_6mu,#widget_k5l{order:3}#f589fd14{order:4}#widget_391{order:6}} #dm .dmPhotoGallery.newPhotoGallery .dmPhotoGalleryHolder:not(.photo-gallery-done) {display: none;} @media (max-width:767px){ [data-hidden-on-mobile] {display:none!important}} 427 .dmDesktopBody [data-anim-desktop]:not([data-anim-desktop='none']) { 428 visibility: hidden; 429 } 430 431 432</style> 433 434 435 436<style id="fontFallbacks"> 437 @font-face { 438 font-family: "Roboto Fallback"; 439 src: local('Arial'); 440 ascent-override: 92.6709%; 441 descent-override: 24.3871%; 442 size-adjust: 100.1106%; 443 line-gap-override: 0%; 444 }@font-face { 445 font-family: "Poppins Fallback"; 446 src: local('Arial'); 447 ascent-override: 92.326%; 448 descent-override: 30.7753%; 449 line-gap-override: 8.793%; 450 size-adjust: 113.7274%; 451}@font-face { 452 font-family: "Kumbh Sans Fallback"; 453 src: local('Arial'); 454 ascent-override: 93.9558%; 455 descent-override: 24.1866%; 456 size-adjust: 104.9779%; 457 line-gap-override: 0%; 458 }@font-face { 459 font-family: "Bebas Neue Fallback"; 460 src: local('Arial'); 461 ascent-override: 116.5002%; 462 descent-override: 38.8334%; 463 size-adjust: 77.2531%; 464 line-gap-override: 0%; 465 }@font-face { 466 font-family: "Red Hat Display Fallback"; 467 src: local('Arial'); 468 ascent-override: 103.0623%; 469 descent-override: 30.8782%; 470 size-adjust: 98.7752%; 471 line-gap-override: 0%; 472 }@font-face { 473 font-family: "Questrial Fallback"; 474 src: local('Arial'); 475 ascent-override: 82.0755%; 476 descent-override: 21.0193%; 477 size-adjust: 99.908%; 478 line-gap-override: 0%; 479 } 480</style> 481 482 483 484 485 486 487 488 489 490 491 492 493 <link type="application/rss+xml" rel="alternate" href="https://www.huffstreeservice.com/feed/rss2"/> 494 <link type="application/atom+xml" rel="alternate" href="https://www.huffstreeservice.com/feed/atom"/> 495 <meta property="og:type" content="website"/> 496 <meta property="og:url" content="https://www.huffstreeservice.com/"/> 497
497<script type="application/ld+json"> 498 499 500 { 501 "@context" : "https://schema.org", 502 "@type" : "WebSite", 503 "name" : "Huff's Tree Service", 504 "url" : "https://www.huffstreeservice.com/" 505 } 506 507 508 </script>
508 509 <title> 510 511 Tree & Turf Care | Sedgwick County, KS | Huff's Tree Service 512 513 </title> 514 <meta name="description" content="We specialize in tree services, turf, and arbor care. Emergency services available. Free same-day estimates. We have certified arborists on staff."/> 515 516 <meta name="twitter:card" content="summary"/> 517 <meta name="twitter:title" content="Tree & Turf Care | Sedgwick County, KS | Huff's Tree Service"/> 518 <meta name="twitter:description" content="We specialize in tree services, turf, and arbor care. Emergency services available. Free same-day estimates. We have certified arborists on staff."/> 519 <meta name="twitter:image" content="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/home-hero-image-huffs-tree-service-1920w.jpg"/> 520 <meta property="og:description" content="We specialize in tree services, turf, and arbor care. Emergency services available. Free same-day estimates. We have certified arborists on staff."/> 521 <meta property="og:title" content="Tree & Turf Care | Sedgwick County, KS | Huff's Tree Service"/> 522 <meta property="og:image" content="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/home-hero-image-huffs-tree-service-1920w.jpg"/>
523<script type="application/ld+json"> 524{ 525 "@context" : { 526 "@vocab" : "http://schema.org/" 527 }, 528 "@type" : "LocalBusiness", 529 "name" : "Huff's Tree Service", 530 "address" : { 531 "@type" : "PostalAddress", 532 "streetAddress" : "2909 W 41st St N", 533 "addressLocality" : "Wichita", 534 "addressRegion" : "KS", 535 "postalCode" : "67204", 536 "addressCountry" : "US" 537 }, 538 "geo" : { 539 "@type" : "GeoCoordinates", 540 "latitude" : "37.7590777", 541 "longitude" : "-97.37633269999" 542 }, 543 "url" : "https://www.huffstreeservice.com", 544 "telephone" : "(316) 871-3841", 545 "email" : "[email protected]", 546 "logo" : "https://a.mktgcdn.com/p/1Gv9aqw4_XHXLj3dOKu4CdMvVrKRr7bTn2X8HJ1v9ak/400x400.jpg", 547 "sameAs" : [ "https://youtube.com/@HuffsTreeService", "https://instagram.com/huffstreeservice", "https://linkedin.com/company/huff's-tree-service-llc", "https://tiktok.com/@@huffstreeservicellc", "https://facebook.com/423029848194509" ], 548 "image" : [ "https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/video-huffs-tree-service-02.jpg", "https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/white-huffs-logo-38c64e96.png", "https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/white-huffs-logo-38c64e96.png", "https://a.mktgcdn.com/p/WL8_IJvMkXSUoxRlOhhpVZDmKf3s3q0jpwr92AQ23eY/500x500.jpg", "https://a.mktgcdn.com/p/WIz-ywTDkf3ShMmtKfjtTY38thx8ysG7w3kswi8Jrm4/284x177.jpg" ], 549 "openingHoursSpecification" : [ { 550 "@type" : "OpeningHoursSpecification", 551 "dayOfWeek" : [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" ], 552 "opens" : "08:00", 553 "closes" : "16:00" 554 } ], 555 "@id" : "https://www.huffstreeservice.com", 556 "foundingDate" : "2012", 557 "description" : "Huff's Tree Service provides residential and commercial tree trimming, tree removal, turf care, and arbor care services throughout the Wichita, KS area.", 558 "makesOffer" : "[{\"@type\":\"Offer\",\"name\":\"Residential and Commercial Tree Services\"},{\"@type\":\"Offer\",\"name\":\"Turf Care\"},{\"@type\":\"Offer\",\"name\":\"Arbor Care\"},{\"@type\":\"Offer\",\"name\":\"Tree Removal\"},{\"@type\":\"Offer\",\"name\":\"Tree Trimming\"},{\"@type\":\"Offer\",\"name\":\"Plant Healthcare\"},{\"@type\":\"Offer\",\"name\":\"Tree Disease Analysis\"}]" 559} 560</script>
560 561 562 563 564<!-- SYS- VVNfSElCVV9QUk9EVUNUSU9O --> 565</head> 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587<body id="dmRoot" data-page-alias="home" class="dmRoot fix-mobile-scrolling flex-site dmResellerSite " 588 style="padding:0;margin:0;" 589 590 data-flex-site > 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607<div id="dm" class='dmwr'> 608 609 <div class="dm_wrapper -var5 null "> 610 <div dmwrapped="true" id="1901957768" class="dm-home-page" themewaschanged="true"> <div dmtemplateid="FlexHeader" data-responsive-name="FlexLayout" class="runtime-module-container dm-bfs dm-layout-home hasAnimations hasStickyHeader inMiniHeaderMode rows-1200 hamburger-reverse dmPageBody d-page-1716942098 inputs-css-clean dmDHeader" id="dm-outer-wrapper" data-page-class="1716942098" data-soch="true" data-background-parallax-selector=".dmHomeSection1, .dmSectionParallex"> <div id="dmStyle_outerContainer" class="dmOuter"> <div id="dmStyle_innerContainer" class="dmInner" data-auto="page-inner"> <div class="dmLayoutWrapper standard-var dmStandardDesktop"> <div id="site_content"> <div id="dmFlexHeaderContainer" class="flex_hfcontainer"> <div id="flex-header" data-variation-id="variation0" data-sticky="true" data-changeable-on-scroll-properties="|text-color|" role="banner"> <div data-layout-section="" data-auto="flex-section" id="1956345911" data-flex-id="405ddf11" class="" data-hidden-on-tablet="true" data-hidden-on-desktop="true"> <div class="flex-widgets-container" id="1211899340"></div> 611 <section id="6c317a78" class="flex-element section" data-auto="flex-element-section"> <div id="11fd5064" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="1d3acdb9" class="flex-element group" data-auto="flex-element-group" data-hidden-on-tablet="" data-hidden-on-desktop=""> <div id="9f3f031f" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop="" data-hidden-on-tablet=""> <div id="98702d80" class="flex-element group" data-auto="flex-element-group"> <div id="4cb86e4c" class="flex-element group" data-auto="flex-element-group"> <div id="9e5ef93d" class="flex-element group" data-auto="flex-element-group"> <div id="ec5d46f2" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1652217484"> <div class="widget-9015bc u_1652217484 dmCustomWidget" data-lazy-load="true" data-title="" id="1652217484" dmle_extension="custom_extension" data-element-type="custom_extension" data-binding="W3siYmluZGluZ05hbWUiOiJtZXJjaGFudElkIiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCJSZXZpZXdzIFdpZGdldHNcIixcImZuXCI6XCJNZXJjaGFudCBJRFwifSJ9XQ==" icon="false" surround="false" data-widget-id="9015bcbf1ace437aa6f0e66d5bb2e7d3" data-widget-version="25" data-widget-config="eyJtZXJjaGFudElkIjoiODAzNzMiLCJtaW4tcmV2aWV3cyI6IjMiLCJtaW4tcmF0aW5nIjoiNCIsInNob3ctd3JpdGUiOnRydWUsImhpZGUtc3VtbWFyeSI6ZmFsc2UsInRoZW1lIjoibGlnaHQifQ=="> <div class="headerWidget" data-merchant="80373" data-theme="light" data-break="" data-count-limit="3" data-rating-limit="4" data-show-write="true" data-hide-summary="false"></div> 612</div> 613</div> 614</div> 615</div> 616 <div id="2e9284f4" class="flex-element group" data-auto="flex-element-group"> <div id="da0131a7" class="flex-element group" data-auto="flex-element-group"> <div id="bff1bb66" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="image" data-keep-proportion="true" data-external-id="1301876968"> <div class="imageWidget align-center u_1301876968" data-element-type="image" data-widget-type="image" id="1301876968" data-binding="W3siYmluZGluZ05hbWUiOiJpbWFnZSIsInZhbHVlIjoic2l0ZV9pbWFnZXMucGVyc2lzdGVkLmRhcmstbG9nbyJ9XQ=="> <a href="/" id="1415691439"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/white-huffs-logo-38c64e96-1920w.png" alt="Huff's Tree Service - logo" id="1635795816" class="" width="0.0" height="0.0" data-dm-image-path="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/white-huffs-logo-38c64e96.png" data-diy-image="" onerror="handleImageLoadError(this)" loading="lazy"/></a> 617</div> 618</div> 619</div> 620 <div id="11d216b4" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop="" data-hidden-on-tablet="" data-hidden-on-mobile=""> <div id="07327faa" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="spacer" data-external-id="1269358429"> <div data-element-type="spacer" class="dmSpacer" id="1269358429"></div> 621</div> 622</div> 623 <div id="3aa37ebb" class="flex-element group" data-auto="flex-element-group"> <div id="5801a4e8" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="hamburgerButton" data-external-id="1460227856"> <button class="hamburgerButton" data-element-type="hamburgerButton" id="1460227856" aria-label="Open menu" aria-controls="hamburger-drawer" aria-expanded="false"> <svg width="100pt" height="100pt" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1111394517"> <path d="m3.6172 10.754h-0.050782c-1.9727 0-3.5703 1.5977-3.5703 3.5703 0 1.9727 1.5977 3.5703 3.5703 3.5703h0.054688 92.758 0.050782c1.9727 0 3.5703-1.5977 3.5703-3.5703 0-1.9727-1.5977-3.5703-3.5703-3.5703h-0.054688zm0 35.676h-0.050782c-1.9727 0-3.5703 1.5977-3.5703 3.5703s1.5977 3.5703 3.5703 3.5703h0.054688 92.758 0.050782c1.9727 0 3.5703-1.5977 3.5703-3.5703s-1.5977-3.5703-3.5703-3.5703h-0.054688zm0 35.68h-0.050782c-1.9727 0-3.5703 1.5977-3.5703 3.5703 0 1.9727 1.5977 3.5703 3.5703 3.5703h0.054688 92.758 0.050782c1.9727 0 3.5703-1.5977 3.5703-3.5703 0-1.9727-1.5977-3.5703-3.5703-3.5703h-0.054688z"></path> 624</svg> 625</button> 626</div> 627</div> 628</div> 629 <div id="148da2d9" class="flex-element group" data-auto="flex-element-group"> <div id="0ece3d12" class="flex-element group" data-auto="flex-element-group"> <div id="daf81bcc" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1105358164"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton u_1105358164" file="false" href="tel:(316) 871-3841" data-element-type="dButtonLinkId" id="1105358164"> <span class="iconBg" aria-hidden="true" id="1528562180"> <span class="icon hasFontIcon icon-star" id="1809587092"></span> 630</span> 631 <span class="text" id="1035871641">(316) 871-3841</span> 632</a> 633</div> 634</div> 635 <div id="a052d7aa" class="flex-element group" data-auto="flex-element-group"> <div id="df845449" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1524906790"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton u_1524906790 align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton u_1524906790" file="false" href="/request-estimate-form" data-element-type="dButtonLinkId" id="1524906790" data-binding="W3siYmluZGluZ05hbWUiOiJidXR0b25fdGV4dCIsInZhbHVlIjoiU1RBVElDX1BBR0VfQ09MTEVDVElPTi57XCJjblwiOlwiYnV0dG9uc1wiLFwiZm5cIjpcIk1vYmlsZSBCdXR0b25cIn0ifSx7ImJpbmRpbmdOYW1lIjoibGluayIsInZhbHVlIjoiU1RBVElDX1BBR0VfQ09MTEVDVElPTi57XCJjblwiOlwiYnV0dG9uc1wiLFwiZm5cIjpcIlJlcXVlc3QgQ1RBIExpbmtcIn0ifV0=" data-diy-link=""> <span class="iconBg" aria-hidden="true" id="1847377451"> <span class="icon hasFontIcon icon-star" id="1804309602"></span> 636</span> 637 <span class="text" id="1149277214" data-diy-text="">REQUEST ESTIMATE</span> 638</a> 639</div> 640</div> 641</div> 642</div> 643</div> 644</div> 645</div> 646</section> 647</div> 648 <div data-layout-section="" data-auto="flex-section" id="1368876750" data-flex-id="157b4fff" class="" data-hidden-on-desktop="true" data-hidden-on-mobile="true"> <div class="flex-widgets-container" id="1825413659"></div> 649 <section id="726ad2b1" class="flex-element section" data-auto="flex-element-section"> <div id="30295aaf" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="32767c2f" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop="" data-hidden-on-mobile=""> <div id="2fd7b414" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop=""> <div id="widget_ie6" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-hidden-on-mobile="" data-external-id="1288312793"> <div class="widget-9015bc u_1288312793 dmCustomWidget" data-lazy-load="true" data-title="" id="1288312793" dmle_extension="custom_extension" data-element-type="custom_extension" data-binding="W3siYmluZGluZ05hbWUiOiJtZXJjaGFudElkIiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCJSZXZpZXdzIFdpZGdldHNcIixcImZuXCI6XCJNZXJjaGFudCBJRFwifSJ9XQ==" icon="false" surround="false" data-widget-id="9015bcbf1ace437aa6f0e66d5bb2e7d3" data-widget-version="25" data-widget-config="eyJtZXJjaGFudElkIjoiODAzNzMiLCJtaW4tcmV2aWV3cyI6IjMiLCJtaW4tcmF0aW5nIjoiNCIsInNob3ctd3JpdGUiOnRydWUsImhpZGUtc3VtbWFyeSI6dHJ1ZSwidGhlbWUiOiJsaWdodCJ9"> <div class="headerWidget" data-merchant="80373" data-theme="light" data-break="" data-count-limit="3" data-rating-limit="4" data-show-write="true" data-hide-summary="true"></div> 650</div> 651</div> 652</div> 653 <div id="group_jjh" class="flex-element group" data-auto="flex-element-group"> <div id="widget_5h5" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="image" data-keep-proportion="true" data-external-id="1303640445"> <div class="imageWidget align-center u_1303640445" data-element-type="image" data-widget-type="image" id="1303640445" data-binding="W3siYmluZGluZ05hbWUiOiJpbWFnZSIsInZhbHVlIjoic2l0ZV9pbWFnZXMucGVyc2lzdGVkLmRhcmstbG9nbyJ9XQ=="> <a href="/" id="1035792501"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/white-huffs-logo-38c64e96-1920w.png" alt="Huff's Tree Service - logo" id="1107341754" class="" width="0.0" height="0.0" data-dm-image-path="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/white-huffs-logo-38c64e96.png" data-diy-image="" onerror="handleImageLoadError(this)" loading="lazy"/></a> 654</div> 655</div> 656</div> 657 <div id="group_7in" class="flex-element group" data-auto="flex-element-group"> <div id="widget_vej" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1997567173"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton u_1997567173 align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton u_1997567173" file="false" href="/contact" data-element-type="dButtonLinkId" id="1997567173" data-binding="W3siYmluZGluZ05hbWUiOiJsaW5rIiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCJidXR0b25zXCIsXCJmblwiOlwiVGFiIC0gQ29udCAtIExpbmtcIn0ifSx7ImJpbmRpbmdOYW1lIjoiYnV0dG9uX3RleHQiLCJ2YWx1ZSI6IlNUQVRJQ19QQUdFX0NPTExFQ1RJT04ue1wiY25cIjpcImJ1dHRvbnNcIixcImZuXCI6XCJUYWIgLSBDb250IEJ1dHRvblwifSJ9XQ==" data-diy-link=""> <span class="iconBg" aria-hidden="true" id="1066072120"> <span class="icon hasFontIcon icon-star" id="1327803529"></span> 658</span> 659 <span class="text" id="1641422126" data-diy-text="">CONTACT US</span> 660</a> 661</div> 662</div> 663 <div id="group_23b" class="flex-element group" data-auto="flex-element-group"> <div id="4598469b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="hamburgerButton" data-external-id="1761070024"> <button class="hamburgerButton" data-element-type="hamburgerButton" id="1761070024" aria-label="Open menu" aria-controls="hamburger-drawer" aria-expanded="false"> <svg width="100pt" height="100pt" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1639062494"> <path d="m3.6172 10.754h-0.050782c-1.9727 0-3.5703 1.5977-3.5703 3.5703 0 1.9727 1.5977 3.5703 3.5703 3.5703h0.054688 92.758 0.050782c1.9727 0 3.5703-1.5977 3.5703-3.5703 0-1.9727-1.5977-3.5703-3.5703-3.5703h-0.054688zm0 35.676h-0.050782c-1.9727 0-3.5703 1.5977-3.5703 3.5703s1.5977 3.5703 3.5703 3.5703h0.054688 92.758 0.050782c1.9727 0 3.5703-1.5977 3.5703-3.5703s-1.5977-3.5703-3.5703-3.5703h-0.054688zm0 35.68h-0.050782c-1.9727 0-3.5703 1.5977-3.5703 3.5703 0 1.9727 1.5977 3.5703 3.5703 3.5703h0.054688 92.758 0.050782c1.9727 0 3.5703-1.5977 3.5703-3.5703 0-1.9727-1.5977-3.5703-3.5703-3.5703h-0.054688z"></path> 664</svg> 665</button> 666</div> 667</div> 668 <div id="group_tbn" class="flex-element group" data-auto="flex-element-group"> <div id="widget_qp9" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="spacer" data-external-id="1685550797"> <div data-element-type="spacer" class="dmSpacer" id="1685550797"></div> 669</div> 670</div> 671</div> 672</div> 673</section> 674</div> 675 <div data-layout-section="" data-auto="flex-section" id="1058362846" data-flex-id="c0ae99ba" class="" data-hidden-on-mobile="true" data-hidden-on-tablet="true"> <div class="flex-widgets-container" id="1227336095"></div> 676 <section id="ac810934" class="flex-element section" data-auto="flex-element-section"> <div id="b7dee1fb" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="9360b347" class="flex-element group" data-auto="flex-element-group" data-hidden-on-mobile="" data-hidden-on-tablet=""> <div id="3710bc01" class="flex-element group" data-auto="flex-element-group" data-hidden-on-tablet=""> <div id="3a2d0b90" class="flex-element group" data-auto="flex-element-group" data-hidden-on-mobile="" data-hidden-on-tablet=""> <div id="be1b9f91" class="flex-element group" data-auto="flex-element-group"> <div id="423fc4a2" class="flex-element group" data-auto="flex-element-group"> <div id="3b22d9b0" class="flex-element group" data-auto="flex-element-group"> <div id="519ddbdc" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1642529323"> <div class="widget-9015bc u_1642529323 dmCustomWidget" data-lazy-load="true" data-title="" id="1642529323" dmle_extension="custom_extension" data-element-type="custom_extension" data-binding="W3siYmluZGluZ05hbWUiOiJtZXJjaGFudElkIiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCJSZXZpZXdzIFdpZGdldHNcIixcImZuXCI6XCJNZXJjaGFudCBJRFwifSJ9XQ==" icon="false" surround="false" data-widget-id="9015bcbf1ace437aa6f0e66d5bb2e7d3" data-widget-version="25" data-widget-config="eyJtZXJjaGFudElkIjoiODAzNzMiLCJtaW4tcmV2aWV3cyI6IjMiLCJtaW4tcmF0aW5nIjoiNCIsInNob3ctd3JpdGUiOnRydWUsImhpZGUtc3VtbWFyeSI6ZmFsc2UsInRoZW1lIjoibGlnaHQifQ=="> <div class="headerWidget" data-merchant="80373" data-theme="light" data-break="" data-count-limit="3" data-rating-limit="4" data-show-write="true" data-hide-summary="false"></div> 677</div> 678</div> 679</div> 680 <div id="8caf0a70" class="flex-element group" data-auto="flex-element-group"> <div id="a8c6072d" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1857856301"> <div class="dmNewParagraph u_1857856301" data-element-type="paragraph" data-version="5" id="1857856301" style=""><p class="text-align-left t-size-13 m-size-13 size-13"><span class="font-size-13 t-font-size-13 m-font-size-13" style="display: unset; font-style: normal;
680 color: var(--color_7);">Serving</span></p></div> 681</div> 682 <div id="3ad8c19c" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1153192226"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1153192226" data-diy-text="" style=""><p class="text-align-left size-20 t-size-17 m-size-16" style="line-height: 1.1;"><strong class="font-size-20 t-font-size-17 m-font-size-16" style="text-transform: uppercase; display: initial; font-weight: bold; color: var(--color_7);">Sedgwick and Butler Counties, KS</strong></p></div> 683</div> 684</div> 685</div> 686 <div id="e3dfb55d" class="flex-element group" data-auto="flex-element-group"> <div id="6881434d" class="flex-element group" data-auto="flex-element-group"> <div id="5bfb3718" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="image" data-keep-proportion="true" data-external-id="1220116170"> <div class="imageWidget align-center u_1220116170" data-element-type="image" data-widget-type="image" id="1220116170" data-binding="W3siYmluZGluZ05hbWUiOiJpbWFnZSIsInZhbHVlIjoic2l0ZV9pbWFnZXMucGVyc2lzdGVkLmRhcmstbG9nbyJ9XQ=="> <a href="/" id="1909084297"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/white-huffs-logo-38c64e96-510w.png" alt="Huff's Tree Service - logo" id="1563401796" class="" width="425.0" height="135.625" data-dm-image-path="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/white-huffs-logo-38c64e96.png" data-diy-image="" onerror="handleImageLoadError(this)"/></a> 687</div> 688</div> 689</div> 690</div> 691 <div id="5cbebde5" class="flex-element group" data-auto="flex-element-group"> <div id="d3a805c8" class="flex-element group" data-auto="flex-element-group"> <div id="e77f39e9" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1234177366"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton u_1234177366 align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton u_1234177366" file="false" href="/request-estimate-form" data-element-type="dButtonLinkId" id="1234177366" data-binding="W3siYmluZGluZ05hbWUiOiJidXR0b25fdGV4dCIsInZhbHVlIjoiU1RBVElDX1BBR0VfQ09MTEVDVElPTi57XCJjblwiOlwiYnV0dG9uc1wiLFwiZm5cIjpcIkRlc2sgLyBUYWIgQnV0dG9uXCJ9In0seyJiaW5kaW5nTmFtZSI6ImxpbmsiLCJ2YWx1ZSI6IlNUQVRJQ19QQUdFX0NPTExFQ1RJT04ue1wiY25cIjpcImJ1dHRvbnNcIixcImZuXCI6XCJSZXF1ZXN0IENUQSBMaW5rXCJ9In1d" data-diy-link=""> <span class="iconBg" aria-hidden="true" id="1281457075"> <span class="icon hasFontIcon icon-star" id="1446615084"></span> 692</span> 693 <span class="text" id="1422705019" data-diy-text="">REQUEST ESTIMATE</span> 694</a> 695</div> 696</div> 697 <div id="6a5bfb4c" class="flex-element group" data-auto="flex-element-group"> <div id="746860ee" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1791170611"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1791170611" style=""><p class="text-align-right m-size-13 t-size-13 size-13"><span class="m-font-size-13 t-font-size-13 font-size-13" style="color: var(--color_7); font-style: normal; display: unset;">Call us</span></p></div> 698</div> 699 <div id="0ad35782" class="flex-element widget-wrapper YXTPH" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1127636214"> <div class="dmNewParagraph u_1127636214" data-element-type="paragraph" data-version="5" id="1127636214" data-diy-text="" style="" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJjb250ZW50X2xpYnJhcnkuZ2xvYmFsLnBob25lLmxvYy0wIC0gbWFpbiJ9XQ==">(316) 871-3841</div> 700</div> 701</div> 702</div> 703</div> 704</div> 705 <div id="bd946f29" class="flex-element group" data-auto="flex-element-group" data-hidden-on-mobile="" data-hidden-on-tablet=""> <div id="51d6dafc" class="flex-element widget-wrapper navmasterdefault" data-auto="flex-element-widget-wrapper" data-widget-type="ONELinksMenu" data-hidden-on-tablet="" data-hidden-on-mobile="" data-hidden-on-desktop="" data-external-id="1398948466"> <nav class="effect-bottom2 u_1398948466 main-navigation unifiednav dmLinksMenu" data-auto="links-menu" role="navigation" layout-main="horizontal_nav_layout_1" layout-sub="submenu_horizontal_1" data-show-vertical-sub-items="HOVER" id="1398948466" dmle_extension="onelinksmenu" data-element-type="onelinksmenu" data-logo-src="" alt="" data-nav-structure="HORIZONTAL" wr="true" icon="true" surround="true" adwords="" navigation-id="unifiedNav"> <ul role="menubar" class="unifiednav__container unav-top " data-auto="navigation-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/" class="unifiednav__item unav-item unav-top-item dmNavItemSelected dmUDNavigationItem_00 " target="" data-target-page-alias="" aria-current="page" data-auto="selected-page"> <span class="nav-item-text " data-link-text=" 706 Home 707 " data-auto="page-text-style">Home<span class="icon icon-angle-down"></span> 708</span> 709</a> 710</li> 711 <li role="menuitem" aria-haspopup="true" aria-expanded="false" data-sub-nav-menu="true" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/about" class="unifiednav__item unav-item unav-top-item dmUDNavigationItem_010101599305 unifiednav__item_has-sub-nav" target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="About" data-auto="page-text-style">About<span class="icon icon-angle-down"></span> 712</span> 713</a> 714 <ul role="menu" class="unifiednav__container unifiednav__container_sub-nav unav-sub" data-depth="0" data-auto="sub-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/careers" class="unifiednav__item unav-item dmUDNavigationItem_010101402669 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Careers" data-auto="page-text-style">Careers<span class="icon icon-angle-right"></span> 715</span> 716</a> 717</li> 718 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/team" class="unifiednav__item unav-item dmUDNavigationItem_010101693489 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Team" data-auto="page-text-style">Team<span class="icon icon-angle-right"></span> 719</span> 720</a> 721</li> 722 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/faqs" class="unifiednav__item unav-item dmUDNavigationItem_010101347615 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="FAQs" data-auto="page-text-style">FAQs<span class="icon icon-angle-right"></span> 723</span> 724</a> 725</li> 726 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/gallery" class="unifiednav__item unav-item dmUDNavigationItem_010101776001 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Gallery" data-auto="page-text-style">Gallery<span class="icon icon-angle-right" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 727</span> 728</a> 729</li> 730 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/reviews" class="unifiednav__item unav-item dmUDNavigationItem_010101840192 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Reviews" data-auto="page-text-style">Reviews<span class="icon icon-angle-right"></span> 731</span> 732</a> 733</li> 734 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/blog" class="unifiednav__item unav-item dmUDNavigationItem_010101105406 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Blog" data-auto="page-text-style">Blog<span class="icon icon-angle-right"></span> 735</span> 736</a> 737</li> 738</ul> 739</li> 740 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/service-area" class="unifiednav__item unav-item unav-top-item dmUDNavigationItem_01010151303 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Serving Area" data-auto="page-text-style">Serving Area<span class="icon icon-angle-down" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 741</span> 742</a> 743</li> 744 <li role="menuitem" aria-haspopup="true" aria-expanded="false" data-sub-nav-menu="true" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/contact" class="unifiednav__item unav-item unav-top-item dmUDNavigationItem_010101152840 unifiednav__item_has-sub-nav" target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Contact" data-auto="page-text-style">Contact<span class="icon icon-angle-down"></span> 745</span> 746</a> 747 <ul role="menu" class="unifiednav__container unifiednav__container_sub-nav unav-sub" data-depth="0" data-auto="sub-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/request-estimate-form" class="unifiednav__item unav-item dmUDNavigationItem_010101150108 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Request Estimate" data-auto="page-text-style">Request Estimate<span class="icon icon-angle-right"></span> 748</span> 749</a> 750</li> 751</ul> 752</li> 753 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/empty" class="unifiednav__item unav-item unav-top-item dmUDNavigationItem_010101434187 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Poly Social Test" data-auto="page-text-style">Poly Social Test<span class="icon icon-angle-down"></span> 754</span> 755</a> 756</li> 757</ul> 758</nav> 759</div> 760 <div id="widget_7d2" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1963014488"> <div class="widget-5b093d u_1963014488 dmCustomWidget" data-lazy-load="true" data-title="" id="1963014488" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="5b093d0fb9474c1dabfa7807be463b12" data-widget-version="52" data-widget-config="eyJjaGlsZFVybFByZWZpeCI6InNlcnZpY2VzIiwidXNlVW5pdmVyc2FsQ29sb3JzIjp0cnVlLCJsb2FkaW5nRGlzcGxheUdyb3VwIjpudWxsLCJ1c2VVbml2ZXJzYWxUeXBvZ3JhcGh5Ijp0cnVlLCJtZWdhQ2hpbGRGb250U2l6ZSI6IjE0IiwicmVzdG9yZUZ1bGxEZWZhdWx0cyI6ZmFsc2UsIm1lZ2EzTGFiZWwiOiJNZWdhIDMiLCJ0b3BMZXZlbEdhcCI6IjE1IiwibWVnYVRyaWdnZXJDaGV2cm9uR2FwIjoiMTIiLCJtZWdhMkFscGhhYmV0aXplIjpmYWxzZSwibWVnYTFHcm91cCI6bnVsbCwiYW5pbWF0ZVN1Yk5hdiI6ZmFsc2UsIm1lZ2EyTGFiZWwiOiJNZWdhIDIiLCJtZWdhNExhYmVsIjoiTWVnYSA0IiwibWVnYTJMYXlvdXQiOiJncmlkIiwibWVnYTFMYWJlbCI6Ijw8U2VydmljZSBHcm91cCBMYWJlbCA+PiIsImFuaW1hdGVIb3ZlckVmZmVjdHMiOmZhbHNlLCJjYXBpdGFsaXplTmF2Ijp0cnVlLCJ1bml2ZXJzYWxGb250V2VpZ2h0IjoiNTAwIiwibWVnYTJNYXhXaWR0aCI6IjE2MDAiLCJ1bml2ZXJzYWxGb250U2l6ZSI6IjE2IiwiYW5pbWF0ZVRvcENoZXZyb25zIjpmYWxzZSwibG9hZGluZ0l0ZW1Db3VudCI6IjQiLCJhbmltYXRlTWlycm9yIjpmYWxzZSwidG9wTmF2QmFja2dyb3VuZENvbG9yIjoiIiwibWFudWFsTmF2aWdhdGlvbkl0ZW1zIjpbXSwibWVnYUZhbWlseUJhY2tncm91bmRDb2xvciI6InZhcigtLWNvbG9yXzEwKSIsImFjdGl2ZVRleHRDb2xvciI6InZhcigtLWNvbG9yXzExKSIsInRvcENoZXZyb25TdHlsZSI6ImZpbGxlZCIsImFuaW1hdGVUb3BOYXYiOmZhbHNlLCJhbmltYXRlTWVnYUZhbWlsaWVzIjpmYWxzZSwidG9wQ2hldnJvbkNvbG9yIjoiIzIyMjIyMiIsIm1lZ2FDaGV2cm9uQ29sb3IiOiIjMjIyMjIyIiwibWVnYUNoaWxkRm9udFdlaWdodCI6IjQwMCIsInN1YlN1YkZvbnRXZWlnaHQiOiI0MDAiLCJuYXRpdmVQYXJlbnRzIjpbeyJzaG93UGFyZW50Ijp0cnVlLCJwdWxsQ2hpbGRyZW4iOnRydWUsImxhYmVsIjoiIiwidXJsIjp7InZhbHVlIjoiYWJvdXQiLCJsYWJlbCI6IiIsInR5cGUiOiJwYWdlIiwiaHJlZiI6Ii9hYm91dCIsInJhd191cmwiOiIvc2l0ZS81MmFkMTkzNWU0NTY0YjI0YTc4MjQwYjM4MmY0MWEzOS9hYm91dD9uZWU9dHJ1ZSZlZD10cnVlJnNob3dPcmlnaW5hbD10cnVlJnByZXZpZXc9dHJ1ZSZkbV90cnlfbW9kZT10cnVlJmRtX2NoZWNrU3luYz0xIn19LHsic2hvd1BhcmVudCI6dHJ1ZSwicHVsbENoaWxkcmVuIjp0cnVlLCJsYWJlbCI6IiIsInVybCI6eyJ2YWx1ZSI6ImNvbnRhY3QiLCJsYWJlbCI6IiIsInR5cGUiOiJwYWdlIiwiaHJlZiI6Ii9jb250YWN0IiwicmF3X3VybCI6Ii9zaXRlLzUyYWQxOTM1ZTQ1NjRiMjRhNzgyNDBiMzgyZjQxYTM5L2NvbnRhY3Q/bmVlPXRydWUmZWQ9dHJ1ZSZzaG93T3JpZ2luYWw9dHJ1ZSZwcmV2aWV3PXRydWUmZG1fdHJ5X21vZGU9dHJ1ZSZkbV9jaGVja1N5bmM9MSJ9fV0sInVzZVVuaXZlcnNhbEJhY2tncm91bmRzIjp0cnVlLCJ1c2VDdXN0b21OYXZPbmx5IjpmYWxzZSwic3ViU3ViVGV4dENvbG9yIjoiIzIyMjIyMiIsIm1lZ2ExTWF4V2lkdGgiOiIxNjAwIiwibWVnYTRHcm91cCI6bnVsbCwidG9wRm9udFNpemUiOiIxNiIsIm1pcnJvckFsaWdubWVudCI6InN0YXJ0IiwibWVnYTRFeHBhbmRBbGwiOmZhbHNlLCJ0ZXh0Q29sb3JzR3JvdXAiOm51bGwsInN1YkZvbnRTaXplIjoiMTQiLCJ0eXBvZ3JhcGh5R3JvdXAiOm51bGwsIm1pcnJvckl0ZW1HYXAiOiIwIiwiYW5pbWF0ZU1lZ2FNZW51IjpmYWxzZSwibWVnYUdyYW5kY2hpbGRUZXh0Q29sb3IiOiIjMjIyMjIyIiwibWVnYVBhcmVudFRleHRDb2xvciI6IiMyMjIyMjIiLCJtaXJyb3JTdHlsZXMiOm51bGwsIm1lZ2ExTGF5b3V0IjoibWFzb25yeSIsIm1lZ2FHcmFuZGNoaWxkRm9udFNpemUiOiIxNCIsImhvdmVyVGV4dENvbG9yIjoidmFyKC0tY29sb3JfMTEpIiwibWVnYTRDb2x1bW5zIjoiMyIsIm1lZ2EyRXhwYW5kQWxsIjpmYWxzZSwibWVnYTNDb2x1bW5zIjoiMyIsImNoZXZyb25zR3JvdXAiOm51bGwsIm1lZ2ExQ29sdW1ucyI6IjMiLCJtZWdhMkNvbHVtbnMiOiIzIiwibGF5b3V0UHJlc2V0IjoiY2xhc3NpYyIsInN1YlN1Yk5hdkJhY2tncm91bmRDb2xvciI6InZhcigtLWNvbG9yXzEwKSIsInJlc3RvcmVNaXJyb3JEZWZhdWx0cyI6ZmFsc2UsInN1YkZvbnRXZWlnaHQiOiI0MDAiLCJ0b3BGb250V2VpZ2h0IjoiNTAwIiwibWVnYTFFeHBhbmRBbGwiOnRydWUsIm5hdkFsaWdubWVudCI6ImNlbnRlciIsImFuaW1hdGVNZWdhQ2hldnJvbnMiOmZhbHNlLCJ3aWRnZXRNb2RlIjoiZnVsbCIsInN1YlRleHRDb2xvciI6IiMyMjIyMjIiLCJzdWJOYXZCYWNrZ3JvdW5k
760Q29sb3IiOiJ2YXIoLS1jb2xvcl8xMCkiLCJtZWdhNE1heFdpZHRoIjoiMTYwMCIsImJhY2tncm91bmRDb2xvcnNHcm91cCI6bnVsbCwidG9wVGV4dENvbG9yIjoiIzIyMjIyMiIsIm1pcnJvck9wZW5NZW51c09uSG92ZXIiOiIiLCJtZWdhUGFyZW50Rm9udFNpemUiOiIxNiIsIm1lbnVJbnRlcmFjdGlvbkdyb3VwIjpudWxsLCJtaXJyb3JTdHlsaW5nR3JvdXAiOm51bGwsImVuYWJsZUN1c3RvbU5hdmlnYXRpb25CdWlsZGVyIjpmYWxzZSwibWVnYTFBbHBoYWJldGl6ZSI6ZmFsc2UsIm1lZ2EzR3JvdXAiOm51bGwsIm1lZ2E0QWxwaGFiZXRpemUiOmZhbHNlLCJhbmltYXRpb25zRW5hYmxlZCI6ZmFsc2UsImNhdGVnb3J5VXJsUHJlZml4Ijoid2hhdC13ZS1kbyIsInVuaXZlcnNhbENoZXZyb25TdHlsZSI6ImZpbGxlZCIsInVuaXZlcnNhbFRleHRDb2xvciI6InZhcigtLWNvbG9yXzExKSIsInVzZVNlcGFyYXRlTWlycm9yU3R5bGluZyI6ZmFsc2UsImxvYWRpbmdBbmltYXRpb25TdHlsZSI6InNoaW1tZXIiLCJtZWdhMkdyb3VwIjpudWxsLCJtZWdhQ2hldnJvblN0eWxlIjoiZmlsbGVkIiwidW5pdmVyc2FsQ2hldnJvbkNvbG9yIjoidmFyKC0tY29sb3JfMTEpIiwiaG92ZXJCYWNrZ3JvdW5kQ29sb3IiOiJ2YXIoLS1jb2xvcl8xMCkiLCJtZWdhTWVudUJhY2tncm91bmRDb2xvciI6InZhcigtLWNvbG9yXzEwKSIsInVuaXZlcnNhbEJhY2tncm91bmRDb2xvciI6InZhcigtLWNvbG9yXzEwKSIsIm1lZ2EzTGF5b3V0IjoiZ3JpZCIsIm5hdmlnYXRpb25Ub29sc0dyb3VwIjpudWxsLCJtZWdhUGFyZW50Rm9udFdlaWdodCI6IjYwMCIsIm1lZ2FDaGlsZFRleHRDb2xvciI6IiMyMjIyMjIiLCJzdWJTdWJGb250U2l6ZSI6IjE0IiwibWVnYTNBbHBoYWJldGl6ZSI6ZmFsc2UsImxheW91dEdyb3VwIjpudWxsLCJ1bml2ZXJzYWxVbmRlcmxpbmUiOnRydWUsImVuYWJsZU5hdmlnYXRpb25UcmVlUHJldmlldyI6ZmFsc2UsIm1lZ2FHcmFuZGNoaWxkRm9udFdlaWdodCI6IjQwMCIsIndpZGdldE1vZGVVcmxzR3JvdXAiOm51bGwsImFuaW1hdGlvbnNHcm91cCI6bnVsbCwib3Blbk1lbnVzT25Ib3ZlciI6dHJ1ZSwidW5pdmVyc2FsQ2hldnJvbldlaWdodCI6IjIiLCJtZWdhM01heFdpZHRoIjoiMTYwMCIsIm1lZ2E0TGF5b3V0IjoiZ3JpZCIsImFuaW1hdGVTdWJTdWJOYXYiOmZhbHNlLCJtZWdhM0V4cGFuZEFsbCI6ZmFsc2UsInVuaXZlcnNhbENoZXZyb25TaXplIjoiMTAiLCJ1c2VVbml2ZXJzYWxDaGV2cm9uU2V0dGluZ3MiOnRydWV9"><!-- NMW Full Feature Stable: Manual Navigation Items live-update fix --><!-- 761 Use this same HTML for both widget instances. 762 763 Content Panel widgetMode: 764 full = loads Collection, Native, CUSTOMNAV, and Manual navigation data 765 mirror = renders the Full widget's shared navigation vertically 766 767 The hidden manual source is required because Duda link inputs must be output 768 through the custom_link helper. JavaScript reads the Duda-generated anchor 769 attributes and moves them into the rendered navigation. 770 771 Manual Folder items do not require a link. An empty manual Folder is shown as 772 a disabled preview inside the Duda editor, then omitted from preview/live pages 773 until a valid child is assigned. 774--> <div class="nmw-root" data-nmw-mode="full"> <a class="nmw-skip-link" href="#nmw-full-main-nav">Skip to navigation</a> 775 <div class="nmw-loading" data-nmw-loading-view="" role="status" aria-live="polite" aria-label="Loading navigation" hidden=""></div> 776 <div class="nmw-mobile-nav-wrapper nmw-render" data-nmw-render=""></div> 777 <div class="nmw-tools" data-nmw-tools="" aria-live="polite"></div> 778 <div class="nmw-manual-items-source" data-nmw-manual-source="" aria-hidden="true" hidden=""></div> 779</div> 780</div> 781</div> 782</div> 783 <div id="a8f32aec" class="flex-element group" data-auto="flex-element-group" data-hidden-on-mobile="" data-hidden-on-tablet="" data-hidden-on-desktop=""> <div id="392df140" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="ONELinksMenu" data-hidden-on-tablet="" data-hidden-on-desktop="" data-external-id="1915042179"> <nav class="effect-bottom2 u_1915042179 main-navigation unifiednav dmLinksMenu" data-auto="links-menu" role="navigation" layout-main="horizontal_nav_layout_1" layout-sub="submenu_horizontal_1" data-show-vertical-sub-items="HOVER" id="1915042179" dmle_extension="onelinksmenu" data-element-type="onelinksmenu" data-logo-src="" alt="" data-nav-structure="HORIZONTAL" wr="true" icon="true" surround="true" adwords="" navigation-id="unifiedNav"> <ul role="menubar" class="unifiednav__container unav-top " data-auto="navigation-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/" class="unifiednav__item unav-item unav-top-item dmNavItemSelected " target="" data-target-page-alias="home" aria-current="page" data-auto="selected-page"> <span class="nav-item-text " data-link-text=" 784 Home 785 " data-auto="page-text-style">Home<span class="icon icon-angle-down" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 786</span> 787</a> 788</li> 789 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <button type="button" class="unifiednav__item unav-item unav-top-item " data-target-page-alias="mega-menu-4dc8a903"> <span class="nav-item-text " data-link-text="Services" data-auto="page-text-style">Services<span class="icon icon-angle-down" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 790</span> 791</button> 792</li> 793 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/reviews" class="unifiednav__item unav-item unav-top-item " target="" data-target-page-alias="reviews"> <span class="nav-item-text " data-link-text="Reviews" data-auto="page-text-style">Reviews<span class="icon icon-angle-down" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 794</span> 795</a> 796</li> 797 <li role="menuitem" aria-haspopup="true" aria-expanded="false" data-sub-nav-menu="true" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/about" class="unifiednav__item unav-item unav-top-item unifiednav__item_has-sub-nav" target="" data-target-page-alias="about"> <span class="nav-item-text " data-link-text="About" data-auto="page-text-style">About<span class="icon icon-angle-down"></span> 798</span> 799</a> 800 <ul role="menu" class="unifiednav__container unifiednav__container_sub-nav unav-sub" data-depth="0" data-auto="sub-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/faqs" class="unifiednav__item unav-item " target="" data-target-page-alias="faqs"> <span class="nav-item-text " data-link-text="FAQs" data-auto="page-text-style">FAQs<span class="icon icon-angle-right" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 801</span> 802</a> 803</li> 804</ul> 805</li> 806 <li role="menuitem" aria-haspopup="true" aria-expanded="false" data-sub-nav-menu="true" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/contact" class="unifiednav__item unav-item unav-top-item unifiednav__item_has-sub-nav" target="" data-target-page-alias="contact"> <span class="nav-item-text " data-link-text="Contact" data-auto="page-text-style">Contact<span class="icon icon-angle-down"></span> 807</span> 808</a> 809 <ul role="menu" class="unifiednav__container unifiednav__container_sub-nav unav-sub" data-depth="0" data-auto="sub-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/request-estimate-form" class="unifiednav__item unav-item " target="" data-target-page-alias="request-form-page"> <span class="nav-item-text " data-link-text="Request Estimate" data-auto="page-text-style">Request Estimate<span class="icon icon-angle-right" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 810</span> 811</a> 812</li> 813 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/service-area" class="unifiednav__item unav-item " target="" data-target-page-alias="service-area"> <span class="nav-item-text " data-link-text="Serving Area" data-auto="page-text-style">Serving Area<span class="icon icon-angle-right" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 814</span> 815</a> 816</li> 817</ul> 818</li> 819 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/locations" class="unifiednav__item unav-item unav-top-item " target="" data-target-page-alias="locations"> <span class="nav-item-text " data-link-text="Locations" data-auto="page-text-style">Locations<span class="icon icon-angle-down" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 820</span> 821</a> 822</li> 823</ul> 824</nav> 825</div> 826</div> 827</div> 828</div> 829</div> 830</section> 831</div> 832</div> 833 <div id="hamburger-drawer" class="hamburger-drawer layout-drawer" layout="5ff40d2f36ae4e5ea1bc96b2e2fcf67e===header" data-origin="side-reverse"> <div data-layout-section="" data-auto="flex-section" id="1825997552" data-flex-id="4a710abd"> <div class="flex-widgets-container" id="1217094164"></div>
834 <section id="bb7ac507" class="flex-element section" data-auto="flex-element-section"> <div id="d3f5447c" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="78db3927" class="flex-element group" data-auto="flex-element-group"> <div id="a7708a16" class="flex-element group" data-auto="flex-element-group"> <div id="8e45e82b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="hamburgerButton" data-external-id="1202219406"> <button class="hamburgerButton" data-element-type="hamburgerButton" id="1202219406" aria-label="Close menu" aria-controls="hamburger-drawer" aria-expanded="false"> <svg width="100pt" height="100pt" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1928507629"> <path d="m82 87.883c1.625 1.625 4.2656 1.625 5.8906 0 1.6289-1.6289 1.6289-4.2656 0-5.8945l-32.414-32.41 32.406-32.406c1.6289-1.625 1.6289-4.2656 835 0-5.8906-1.6289-1.6289-4.2656-1.6289-5.8906 0l-32.406 32.402-32.406-32.406c-1.625-1.625-4.2656-1.625-5.8906 0-1.6289 1.6289-1.6289 4.2656 0 836 5.8945l32.402 32.406-32.41 32.414c-1.6289 1.625-1.6289 4.2617 0 5.8906 1.625 1.6289 4.2656 1.6289 5.8906 0l32.414-32.414z" fill-rule="evenodd"></path> 837</svg> 838</button> 839</div> 840</div> 841</div> 842</div> 843</section> 844</div> 845 <div data-auto="flex-section" id="1099442592" data-flex-id="63a049320d35b55b4ef2a372" data-layout-section=""> <div class="flex-widgets-container" id="1247649854"></div> 846 <section id="63a049320d35b55b4ef2a373" class="flex-element section" data-auto="flex-element-section"> <div id="63a049320d35b55b4ef2a376" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="63a049320d35b55b4ef2a377" class="flex-element group" data-auto="flex-element-group"> <div id="63a049320d35b55b4ef2a374" class="flex-element group" data-auto="flex-element-group"> <div id="widget_la2" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="4003453145"> <div class="widget-5b093d dmCustomWidget" data-lazy-load="true" data-title="" id="4003453145" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="5b093d0fb9474c1dabfa7807be463b12" data-widget-version="52" data-widget-config="eyJjaGlsZFVybFByZWZpeCI6InNlcnZpY2VzIiwidXNlVW5pdmVyc2FsQ29sb3JzIjp0cnVlLCJsb2FkaW5nRGlzcGxheUdyb3VwIjpudWxsLCJ1c2VVbml2ZXJzYWxUeXBvZ3JhcGh5Ijp0cnVlLCJtZWdhQ2hpbGRGb250U2l6ZSI6IjE0IiwicmVzdG9yZUZ1bGxEZWZhdWx0cyI6ZmFsc2UsIm1lZ2EzTGFiZWwiOiJNZWdhIDMiLCJ0b3BMZXZlbEdhcCI6IjMyIiwibWVnYVRyaWdnZXJDaGV2cm9uR2FwIjoiMTIiLCJtZWdhMkFscGhhYmV0aXplIjpmYWxzZSwibWVnYTFHcm91cCI6bnVsbCwiYW5pbWF0ZVN1Yk5hdiI6dHJ1ZSwibWVnYTJMYWJlbCI6Ik1lZ2EgMiIsIm1lZ2E0TGFiZWwiOiJNZWdhIDQiLCJtZWdhMkxheW91dCI6ImdyaWQiLCJtZWdhMUxhYmVsIjoiTWVnYSAxIiwiYW5pbWF0ZUhvdmVyRWZmZWN0cyI6dHJ1ZSwiY2FwaXRhbGl6ZU5hdiI6ZmFsc2UsInVuaXZlcnNhbEZvbnRXZWlnaHQiOiI1MDAiLCJtZWdhMk1heFdpZHRoIjoiMTYwMCIsInVuaXZlcnNhbEZvbnRTaXplIjoiMTYiLCJhbmltYXRlVG9wQ2hldnJvbnMiOnRydWUsImxvYWRpbmdJdGVtQ291bnQiOiI0IiwiYW5pbWF0ZU1pcnJvciI6dHJ1ZSwidG9wTmF2QmFja2dyb3VuZENvbG9yIjoiIiwibWFudWFsTmF2aWdhdGlvbkl0ZW1zIjpbXSwibWVnYUZhbWlseUJhY2tncm91bmRDb2xvciI6IiIsImFjdGl2ZVRleHRDb2xvciI6ImN1cnJlbnRDb2xvciIsInRvcENoZXZyb25TdHlsZSI6ImZpbGxlZCIsImFuaW1hdGVUb3BOYXYiOnRydWUsImFuaW1hdGVNZWdhRmFtaWxpZXMiOnRydWUsInRvcENoZXZyb25Db2xvciI6IiMyMjIyMjIiLCJtZWdhQ2hldnJvbkNvbG9yIjoiIzIyMjIyMiIsIm1lZ2FDaGlsZEZvbnRXZWlnaHQiOiI0MDAiLCJzdWJTdWJGb250V2VpZ2h0IjoiNDAwIiwibmF0aXZlUGFyZW50cyI6W10sInVzZVVuaXZlcnNhbEJhY2tncm91bmRzIjp0cnVlLCJ1c2VDdXN0b21OYXZPbmx5IjpmYWxzZSwic3ViU3ViVGV4dENvbG9yIjoiIzIyMjIyMiIsIm1lZ2ExTWF4V2lkdGgiOiIxNjAwIiwibWVnYTRHcm91cCI6bnVsbCwidG9wRm9udFNpemUiOiIxNiIsIm1pcnJvckFsaWdubWVudCI6InN0YXJ0IiwibWVnYTRFeHBhbmRBbGwiOmZhbHNlLCJ0ZXh0Q29sb3JzR3JvdXAiOm51bGwsInN1YkZvbnRTaXplIjoiMTQiLCJ0eXBvZ3JhcGh5R3JvdXAiOm51bGwsIm1pcnJvckl0ZW1HYXAiOiIwIiwiYW5pbWF0ZU1lZ2FNZW51Ijp0cnVlLCJtZWdhR3JhbmRjaGlsZFRleHRDb2xvciI6IiMyMjIyMjIiLCJtZWdhUGFyZW50VGV4dENvbG9yIjoiIzIyMjIyMiIsIm1pcnJvclN0eWxlcyI6bnVsbCwibWVnYTFMYXlvdXQiOiJncmlkIiwibWVnYUdyYW5kY2hpbGRGb250U2l6ZSI6IjE0IiwiaG92ZXJUZXh0Q29sb3IiOiJjdXJyZW50Q29sb3IiLCJtZWdhNENvbHVtbnMiOiIzIiwibWVnYTJFeHBhbmRBbGwiOmZhbHNlLCJtZWdhM0NvbHVtbnMiOiIzIiwiY2hldnJvbnNHcm91cCI6bnVsbCwibWVnYTFDb2x1bW5zIjoiMyIsIm1lZ2EyQ29sdW1ucyI6IjMiLCJsYXlvdXRQcmVzZXQiOiJjbGFzc2ljIiwic3ViU3ViTmF2QmFja2dyb3VuZENvbG9yIjoiI2ZmZmZmZiIsInJlc3RvcmVNaXJyb3JEZWZhdWx0cyI6ZmFsc2UsInN1YkZvbnRXZWlnaHQiOiI0MDAiLCJ0b3BGb250V2VpZ2h0IjoiNTAwIiwibWVnYTFFeHBhbmRBbGwiOmZhbHNlLCJuYXZBbGlnbm1lbnQiOiJjZW50ZXIiLCJhbmltYXRlTWVnYUNoZXZyb25zIjp0cnVlLCJ3aWRnZXRNb2RlIjoibWlycm9yIiwic3ViVGV4dENvbG9yIjoiIzIyMjIyMiIsInN1Yk5hdkJhY2tncm91bmRDb2xvciI6IiNmZmZmZmYiLCJtZWdhNE1heFdpZHRoIjoiMTYwMCIsImJhY2tncm91bmRDb2xvcnNHcm91cCI6bnVsbCwidG9wVGV4dENvbG9yIjoiIzIyMjIyMiIsIm1pcnJvck9wZW5NZW51c09uSG92ZXIiOiIiLCJtZWdhUGFyZW50Rm9udFNpemUiOiIxNiIsIm1lbnVJbnRlcmFjdGlvbkdyb3VwIjpudWxsLCJtaXJyb3JTdHlsaW5nR3JvdXAiOm51bGwsImVuYWJsZUN1c3RvbU5hdmlnYXRpb25CdWlsZGVyIjpmYWxzZSwibWVnYTFBbHBoYWJldGl6ZSI6ZmFsc2UsIm1lZ2EzR3JvdXAiOm51bGwsIm1lZ2E0QWxwaGFiZXRpemUiOmZ
846hbHNlLCJhbmltYXRpb25zRW5hYmxlZCI6dHJ1ZSwiY2F0ZWdvcnlVcmxQcmVmaXgiOiJ3aGF0LXdlLWRvIiwidW5pdmVyc2FsQ2hldnJvblN0eWxlIjoiZmlsbGVkIiwidW5pdmVyc2FsVGV4dENvbG9yIjoiIzExMTExMSIsInVzZVNlcGFyYXRlTWlycm9yU3R5bGluZyI6ZmFsc2UsImxvYWRpbmdBbmltYXRpb25TdHlsZSI6InNoaW1tZXIiLCJtZWdhMkdyb3VwIjpudWxsLCJtZWdhQ2hldnJvblN0eWxlIjoiZmlsbGVkIiwidW5pdmVyc2FsQ2hldnJvbkNvbG9yIjoiIzIyMjIyMiIsImhvdmVyQmFja2dyb3VuZENvbG9yIjoiIiwibWVnYU1lbnVCYWNrZ3JvdW5kQ29sb3IiOiIjZmZmZmZmIiwidW5pdmVyc2FsQmFja2dyb3VuZENvbG9yIjoiI2ZmZmZmZiIsIm1lZ2EzTGF5b3V0IjoiZ3JpZCIsIm5hdmlnYXRpb25Ub29sc0dyb3VwIjpudWxsLCJtZWdhUGFyZW50Rm9udFdlaWdodCI6IjYwMCIsIm1lZ2FDaGlsZFRleHRDb2xvciI6IiMyMjIyMjIiLCJzdWJTdWJGb250U2l6ZSI6IjE0IiwibWVnYTNBbHBoYWJldGl6ZSI6ZmFsc2UsImxheW91dEdyb3VwIjpudWxsLCJ1bml2ZXJzYWxVbmRlcmxpbmUiOmZhbHNlLCJlbmFibGVOYXZpZ2F0aW9uVHJlZVByZXZpZXciOmZhbHNlLCJtZWdhR3JhbmRjaGlsZEZvbnRXZWlnaHQiOiI0MDAiLCJ3aWRnZXRNb2RlVXJsc0dyb3VwIjpudWxsLCJhbmltYXRpb25zR3JvdXAiOm51bGwsIm9wZW5NZW51c09uSG92ZXIiOmZhbHNlLCJ1bml2ZXJzYWxDaGV2cm9uV2VpZ2h0IjoiMiIsIm1lZ2EzTWF4V2lkdGgiOiIxNjAwIiwibWVnYTRMYXlvdXQiOiJncmlkIiwiYW5pbWF0ZVN1YlN1Yk5hdiI6dHJ1ZSwibWVnYTNFeHBhbmRBbGwiOmZhbHNlLCJ1bml2ZXJzYWxDaGV2cm9uU2l6ZSI6IjE0IiwidXNlVW5pdmVyc2FsQ2hldnJvblNldHRpbmdzIjp0cnVlfQ=="><!-- NMW Full Feature Stable: Manual Navigation Items live-update fix --><!-- 847 Use this same HTML for both widget instances. 848 849 Content Panel widgetMode: 850 full = loads Collection, Native, CUSTOMNAV, and Manual navigation data 851 mirror = renders the Full widget's shared navigation vertically 852 853 The hidden manual source is required because Duda link inputs must be output 854 through the custom_link helper. JavaScript reads the Duda-generated anchor 855 attributes and moves them into the rendered navigation. 856 857 Manual Folder items do not require a link. An empty manual Folder is shown as 858 a disabled preview inside the Duda editor, then omitted from preview/live pages 859 until a valid child is assigned. 860--> <div class="nmw-root" data-nmw-mode="full"> <a class="nmw-skip-link" href="#nmw-full-main-nav">Skip to navigation</a> 861 <div class="nmw-loading" data-nmw-loading-view="" role="status" aria-live="polite" aria-label="Loading navigation" hidden=""></div> 862 <div class="nmw-mobile-nav-wrapper nmw-render" data-nmw-render=""></div> 863 <div class="nmw-tools" data-nmw-tools="" aria-live="polite"></div> 864 <div class="nmw-manual-items-source" data-nmw-manual-source="" aria-hidden="true" hidden=""></div> 865</div> 866</div> 867</div> 868</div> 869</div> 870</div> 871</section> 872</div> 873 <div data-auto="flex-section" id="1029527021" data-flex-id="6406026c90e1521f6ecb0eca" data-layout-section=""> <div class="flex-widgets-container" id="1659590659"></div> 874 <section id="6406026c90e1521f6ecb0ec9" class="flex-element section" data-auto="flex-element-section"> <div id="6406026c90e1521f6ecb0ecb" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="6406026c90e1521f6ecb0ecc" class="flex-element group" data-auto="flex-element-group"> <div id="6406026c90e1521f6ecb0ecd" class="flex-element group" data-auto="flex-element-group"></div> 875</div> 876</div> 877</section> 878</div> 879</div> 880 <div class="layout-drawer-overlay" id="layout-drawer-overlay"></div> 881</div> 882 <div dmwrapped="true" id="dmFirstContainer" class="dmBody u_dmStyle_template_home dm-home-page" themewaschanged="true"> <div id="allWrapper" class="allWrapper" data-auto="all-wrapper"><!-- navigation placeholders --> <div id="dm_content" class="dmContent" role="main"> <div dm:templateorder="170" class="dmHomeRespTmpl mainBorder dmRespRowsWrapper dmFullRowRespTmpl" id="1716942098"> <div data-layout-section="" data-auto="flex-section" id="1352321863" data-flex-id="fa95c160" class="" data-hidden-on-tablet="true" data-hidden-on-desktop="true" data-hidden-on-mobile="true"> <div class="flex-widgets-container" id="1806718005"></div> 883 <section id="b64ec8bb" class="flex-element section" data-auto="flex-element-section"> <div id="c877aa44" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="c1277cd5" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop="" data-hidden-on-tablet="" data-hidden-on-mobile=""> <div id="b63d2dd0" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop=""></div> 884 <div id="87457d0a" class="flex-element group" data-auto="flex-element-group"></div> 885</div> 886</div> 887</section> 888</div> 889 <div data-layout-section="" data-auto="flex-section" id="1883436679" data-flex-id="060524e0" class="" data-hidden-on-tablet="true" data-hidden-on-mobile="true" data-hidden-on-desktop="true"> <div class="flex-widgets-container" id="1224393650"></div> 890 <section id="a214224e" class="flex-element section" data-auto="flex-element-section"> <div id="b9331987" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="102296bd" class="flex-element group" data-auto="flex-element-group" data-hidden-on-tablet="" data-hidden-on-mobile="" data-hidden-on-desktop=""> <div id="db4fad4c" class="flex-element group" data-auto="flex-element-group"> <div id="widget_oo7" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1877817532"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1877817532" style=""> <h2><span style="display: unset;">Recent Blog Posts</span></h2> 891</div> 892</div> 893 <div id="group_69j" class="flex-element group" data-auto="flex-element-group"> <div id="widget_r6f" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="internal_blog_list" data-external-id="1550316043"> <div class="default u_1550316043 mainBlog layout4" id="1550316043" dmle_extension="internal_blog_list" data-element-type="internal_blog_list" show-images="true" wr="true" trim-title="false" show-blog-title="false" show-action-text="true" text-align="left" icon="true" surround="true" adwords="" list-layout="layout4" visible-items="10" visible-post-lines="4" search-tags="" search-term="" more-posts-text="Show More" header-type="H2" posts-p
893adding="10" posts-per-row="3" show-author="false" text-box-padding="true" action-text="Read more â" skip-post-index="-1" blog-posts-feature-flag="true" data-image-hover-effect="zoomout" show-more-posts-text="true" data-paginate-total-elements="12"> <div class="inner "> <div style="-ms-grid-column:1; -ms-grid-row:1" class="postArticle " data-auto="blog-post-article"> <div class="inner clearfix wow" style="animation-delay: 200.0ms;"> <a class="blogImgLink" data-auto="blog-img-link" dont-color-link="true" href="/how-to-take-care-of-storm-damaged-trees" data-blog-post-alias="how-to-take-care-of-storm-damaged-trees" aria-label="Broken tree trunk split in a green wooded area, with fallen branches and debris on the ground"> <div class="blogImg" data-auto="blog-img" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/how-to-take-care-of-storm-damaged-trees-1920w.jpg');"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/how-to-take-care-of-storm-damaged-trees-1920w.jpg" alt="Broken tree trunk split in a green wooded area, with fallen branches and debris on the ground" onerror="handleImageLoadError(this)" loading="lazy"/></div> 894</a> 895 <div class="postTextContainer"> <div class="postText clearfix"> <div class="postTitle" data-auto="blog-post-title"> <h3> <a dont-color-link="true" href="/how-to-take-care-of-storm-damaged-trees" data-blog-post-alias="how-to-take-care-of-storm-damaged-trees">How to Take Care of Storm-Damaged Trees</a> 896</h3> 897</div> 898 <div class="authorBar" data-auto="blog-author-bar"> <span>August 24, 2026</span> 899</div> 900 <div class="postDescription" data-auto="blog-post-description">And Where to Find a Certified Arborist Near You That Performs Professional Tree Service</div> 901</div> 902 <div class="readMore" data-auto="blog-read-more"> <a dont-color-link="true" href="/how-to-take-care-of-storm-damaged-trees"></a> 903</div> 904</div> 905</div> 906</div> 907 <div style="-ms-grid-column:2; -ms-grid-row:1" class="postArticle " data-auto="blog-post-article"> <div class="inner clearfix wow" style="animation-delay: 400.0ms;"> <a class="blogImgLink" data-auto="blog-img-link" dont-color-link="true" href="/what-to-do-when-a-tree-dies-on-your-property" data-blog-post-alias="what-to-do-when-a-tree-dies-on-your-property" aria-label="Lone dead tree in a green field at sunset with pink clouds and a blue sky"> <div class="blogImg" data-auto="blog-img" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/what-to-do-when-a-tree-dies-on-your-property-1920w.jpg');"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/what-to-do-when-a-tree-dies-on-your-property-1920w.jpg" alt="Lone dead tree in a green field at sunset with pink clouds and a blue sky" onerror="handleImageLoadError(this)" loading="lazy"/></div> 908</a> 909 <div class="postTextContainer"> <div class="postText clearfix"> <div class="postTitle" data-auto="blog-post-title"> <h3> <a dont-color-link="true" href="/what-to-do-when-a-tree-dies-on-your-property" data-blog-post-alias="what-to-do-when-a-tree-dies-on-your-property">what-to-do-when-a-tree-dies-on-your-property</a> 910</h3> 911</div> 912 <div class="authorBar" data-auto="blog-author-bar"> <span>August 24, 2026</span> 913</div> 914 <div class="postDescription" data-auto="blog-post-description">And Where to Find a Certified Arborist Near You That Performs Professional Tree Service</div> 915</div> 916 <div class="readMore" data-auto="blog-read-more"> <a dont-color-link="true" href="/what-to-do-when-a-tree-dies-on-your-property"></a> 917</div> 918</div> 919</div> 920</div> 921 <div style="-ms-grid-column:3; -ms-grid-row:1" class="postArticle " data-auto="blog-post-article"> <div class="inner clearfix wow" style="animation-delay: 600.0ms;"> <a class="blogImgLink" data-auto="blog-img-link" dont-color-link="true" href="/i-have-a-tree-emergency-what-do-i-doad2f9c25" data-blog-post-alias="i-have-a-tree-emergency-what-do-i-doad2f9c25" aria-label="Collapsed tree blocks a white-railed walkway in a wooded yard"> <div class="blogImg" data-auto="blog-img" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/i-have-a-tree-emergency-what-do-i-do-1920w.jpg');"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/i-have-a-tree-emergency-what-do-i-do-1920w.jpg" alt="Collapsed tree blocks a white-railed walkway in a wooded yard" onerror="handleImageLoadError(this)" loading="lazy"/></div> 922</a> 923 <div class="postTextContainer"> <div class="postText clearfix"> <div class="postTitle" data-auto="blog-post-title"> <h3> <a dont-color-link="true" href="/i-have-a-tree-emergency-what-do-i-doad2f9c25" data-blog-post-alias="i-have-a-tree-emergency-what-do-i-doad2f9c25">I Have a Tree Emergency! What Do I Do?</a> 924</h3> 925</div> 926 <div class="authorBar" data-auto="blog-author-bar"> <span>January 11, 2023</span> 927</div> 928 <div class="postDescription" data-auto="blog-post-description">Breaking Down the Scenarios When You Need to Call a Wichita Tree Service Picture this: you’re going about your normal morning routine. Maybe you’re having your morning cup of coffee while checking emails or watching the morning news. Suddenly, you hear a distinct splintery cracking sound from outside. It’s immediately followed by a crashing thump […] 929The post I Have a Tree Emergency! What Do I Do? appeared first on Huff's Tree Service.</div> 930</div> 931 <div class="readMore" data-auto="blog-read-more"> <a dont-color-link="true" href="/i-have-a-tree-emergency-what-do-i-doad2f9c25"></a> 932</div> 933</div> 934</div> 935</div> 936 <div style="-ms-grid-column:1; -ms-grid-row:2" class="postArticle " data-auto="blog-post-article"> <div class="inner clearfix wow" style="animation-delay: 800.0ms;"> <a class="blogImgLink" data-auto="blog-img-link" dont-color-link="true" href="/spring-tree-pests-to-watch-out-for" data-blog-post-alias="spring-tree-pests-to-watch-out-for" aria-label="Two workers in green uniforms inspecting a tree trunk outdoors with a clipboard"> <div class="blogImg" data-auto="blog-img" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/spring-tree-pests-to-watch-out-for-1920w.jpg');"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/spring-tree-pests-to-watch-out-for-1920w.jpg" alt="Two workers in green uniforms inspecting a tree trunk outdoors with a clipboard" onerror="handleImageLoadError(this)" loading="lazy"/></div> 937</a> 938 <div class="postTextContainer"> <div class="postText clearfix"> <div class="postTitle" data-auto="blog-post-title"> <h3> <a dont-color-link="true" href="/spring-tree-pests-to-watch-out-for" data-blog-post-alias="spring-tree-pests-to-watch-out-for">Spring Tree Pests to Watch Out For</a> 939</h3> 940</div> 941 <div class="authorBar" data-auto="blog-author-bar"> <span>January 11, 2023</span> 942</div> 943 <div class="postDescription" data-auto="blog-post-description">Three Bugs and Critters That Can Affect Your Tree Care We know it’s January and tree pests are probably the last thing on your mind right now, but spring will be here before you know it. All the bugs and pests will eventually resurge, putting your trees and landscaping back in the heat of battle […] 944The post Spring Tree Pests to Watch Out For appeared first on Huff's Tree Service.</div> 945</div> 946 <div class="readMore" data-auto="blog-read-more"> <a dont-color-link="true" href="/spring-tree-pests-to-watch-out-for"></a> 947</div> 948</div> 949</div> 950</div> 951 <div style="-ms-grid-column:2; -ms-grid-row:2" class="postArticle " data-auto="blog-post-article"> <div class="inner clearfix wow" style="animation-delay: 1000.0ms;"> <a class="blogImgLink" data-auto="blog-img-link" dont-color-link="true" href="/got-winter-tree-goals-a-certified-arborist-near-you-can-help" data-blog-post-alias="got-winter-tree-goals-a-certified-arborist-near-you-can-help" aria-label="Arborist in blue gear and
951yellow helmet trimming a tree branch high on a trunk with safety harness."> <div class="blogImg" data-auto="blog-img" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/got-winter-tree-goals-a-certified-arborist-near-you-can-help-1920w.jpg');"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/got-winter-tree-goals-a-certified-arborist-near-you-can-help-1920w.jpg" alt="Arborist in blue gear and yellow helmet trimming a tree branch high on a trunk with safety harness." onerror="handleImageLoadError(this)" loading="lazy"/></div> 952</a> 953 <div class="postTextContainer"> <div class="postText clearfix"> <div class="postTitle" data-auto="blog-post-title"> <h3> <a dont-color-link="true" href="/got-winter-tree-goals-a-certified-arborist-near-you-can-help" data-blog-post-alias="got-winter-tree-goals-a-certified-arborist-near-you-can-help">Got Winter Tree Goals? A Certified Arborist Near You Can Help!</a> 954</h3> 955</div> 956 <div class="authorBar" data-auto="blog-author-bar"> <span>November 21, 2022</span> 957</div> 958 <div class="postDescription" data-auto="blog-post-description">How to Get Professional Tree Service in Wichita to Kick Off the New Year It’s getting mighty cold out here in Wichita. We’ve already gotten some snow and morning frost on the family vehicle is a regular occurrence now. Most folks are going through their typical winter prep before the new year. That means cleaning […] 959The post Got Winter Tree Goals? A Certified Arborist Near You Can Help! appeared first on Huff's Tree Service.</div> 960</div> 961 <div class="readMore" data-auto="blog-read-more"> <a dont-color-link="true" href="/got-winter-tree-goals-a-certified-arborist-near-you-can-help"></a> 962</div> 963</div> 964</div> 965</div> 966 <div style="-ms-grid-column:3; -ms-grid-row:2" class="postArticle " data-auto="blog-post-article"> <div class="inner clearfix wow" style="animation-delay: 1200.0ms;"> <a class="blogImgLink" data-auto="blog-img-link" dont-color-link="true" href="/winter-tree-removal-best-practices" data-blog-post-alias="winter-tree-removal-best-practices" aria-label="Leaf-covered woodland with bare trees and a rocky hillside in the background"> <div class="blogImg" data-auto="blog-img" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/winter-tree-removal-best-practices-1920w.jpg');"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/winter-tree-removal-best-practices-1920w.jpg" alt="Leaf-covered woodland with bare trees and a rocky hillside in the background" onerror="handleImageLoadError(this)" loading="lazy"/></div> 967</a> 968 <div class="postTextContainer"> <div class="postText clearfix"> <div class="postTitle" data-auto="blog-post-title"> <h3> <a dont-color-link="true" href="/winter-tree-removal-best-practices" data-blog-post-alias="winter-tree-removal-best-practices">Winter Tree Removal Best Practices</a> 969</h3> 970</div> 971 <div class="authorBar" data-auto="blog-author-bar"> <span>November 7, 2022</span> 972</div> 973 <div class="postDescription" data-auto="blog-post-description">How to Get Professional Tree and Stump Removal Services from a Tree Specialist Near You in Wichita We’re in the thick of the holiday season, which means that we have to shift our landscaping mentality over to cold weather mode. As a certified arborist near you, we can tell you firsthand that this time of […] 974The post Winter Tree Removal Best Practices appeared first on Huff's Tree Service.</div> 975</div> 976 <div class="readMore" data-auto="blog-read-more"> <a dont-color-link="true" href="/winter-tree-removal-best-practices"></a> 977</div> 978</div> 979</div> 980</div> 981 <div style="-ms-grid-column:1; -ms-grid-row:3" class="postArticle " data-auto="blog-post-article"> <div class="inner clearfix wow" style="animation-delay: 1400.0ms;"> <a class="blogImgLink" data-auto="blog-img-link" dont-color-link="true" href="/winter-tree-care-tips-for-wichita-property-owners" data-blog-post-alias="winter-tree-care-tips-for-wichita-property-owners" aria-label="Person in a gray hat and dark coat hugging a tree in a snowy park"> <div class="blogImg" data-auto="blog-img" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/winter-tree-care-tips-for-wichita-property-owners-1920w.jpg');"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/winter-tree-care-tips-for-wichita-property-owners-1920w.jpg" alt="Person in a gray hat and dark coat hugging a tree in a snowy park" onerror="handleImageLoadError(this)" loading="lazy"/></div> 982</a> 983 <div class="postTextContainer"> <div class="postText clearfix"> <div class="postTitle" data-auto="blog-post-title"> <h3> <a dont-color-link="true" href="/winter-tree-care-tips-for-wichita-property-owners" data-blog-post-alias="winter-tree-care-tips-for-wichita-property-owners">Winter Tree Care Tips for Wichita Property Owners</a> 984</h3> 985</div> 986 <div class="authorBar" data-auto="blog-author-bar"> <span>October 24, 2022</span> 987</div> 988 <div class="postDescription" data-auto="blog-post-description">5 Ways to Keep Your Trees in Their Best Condition During the Cold Season To quote a very famous show: “Winter is coming.” As a professional tree service who has been in the business of taking care of trees year-round, we take those words to heart. Winter is hands-down the most challenging time for a […] 989The post Winter Tree Care Tips for Wichita Property Owners appeared first on Huff's Tree Service.</div> 990</div> 991 <div class="readMore" data-auto="blog-read-more"> <a dont-color-link="true" href="/winter-tree-care-tips-for-wichita-property-owners"></a> 992</div> 993</div> 994</div> 995</div> 996 <div style="-ms-grid-column:2; -ms-grid-row:3" class="postArticle " data-auto="blog-post-article"> <div class="inner clearfix wow" style="animation-delay: 1600.0ms;"> <a class="blogImgLink" data-auto="blog-img-link" dont-color-link="true" href="/why-winter-is-ideal-for-trimming-trees" data-blog-post-alias="why-winter-is-ideal-for-trimming-trees" aria-label="Two people trimming bare trees in a snowy backyard, one standing on a ladder"> <div class="blogImg" data-auto="blog-img" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/why-winter-is-ideal-for-trimming-trees-1920w.jpg');"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/why-winter-is-ideal-for-trimming-trees-1920w.jpg" alt="Two people trimming bare trees in a snowy backyard, one standing on a ladder" onerror="handleImageLoadError(this)" loading="lazy"/></div> 997</a> 998 <div class="postTextContainer"> <div class="postText clearfix"> <div class="postTitle" data-auto="blog-post-title"> <h3> <a dont-color-link="true" href="/why-winter-is-ideal-for-trimming-trees" data-blog-post-alias="why-winter-is-ideal-for-trimming-trees">Why Winter is Ideal for Trimming Trees</a> 999</h3> 1000</div> 1001 <div class="authorBar" data-auto="blog-author-bar"> <span>October 10, 2022</span> 1002</div> 1003 <div class="postDescription" data-auto="blog-post-description">Professional Tree Service Advice from a Certified Arborist Near You in Wichita As any professional tree trimming service will tell you, pruning your trees is essential if you want to keep them looking their best and promote healthy, natural growth. When it comes to Wichita tree service, the process of pruning is what removes dead […] 1004The post Why Winter is Ideal for Trimming Trees appeared first on Huff's Tree Service.</div> 1005</div> 1006 <div class="readMore" data-auto="blog-read-more"> <a dont-color-link="true" href="/why-winter-is-ideal-for-trimming-trees"></a> 1007</div> 1008</div> 1009</div> 1010</div> 1011 <div style="-ms-grid-column:3; -ms-grid-row:3" class="postArticle " data-auto="blog-post-article"> <div class="inner clearfix wow" style="animation-delay: 1800.0ms;"> <a class="blogImgLink" data-auto="blog-img-link" dont-color-link="true" href="/first-time-tree-planting-tips-from-your-wichita-tree-specialists" data-blog-post-alias="first-time-tree-planting-tips-from-your-wichita-tree-specialists" aria-label="Two people kneeling in a sunny park, planting a young tree together"> <div class="blogImg" data-auto="blog-img" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/first-time-tree-planting-tips-from-your-wichita-tree-specialists-1920w.jpg');"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/first-time-tree-planting-tips-from-your-wichita-tree-specialists-1920w.jpg" alt="Two people kneeling in a sunny park, planting a young tree together" onerror="handleImageLoadError(this)" loading="lazy"/></div> 1012</a> 1013 <div class="postTextContainer"> <div class="postText clearfix"> <div class="postTitle" data-auto="blog-post-title"> <h3> <a dont-color-link="true" href="/first-time-tree-planting-tips-from-your-wichita-tree-specialists" data-blog-post-alias="first-time-tree-planting-tips-from-your-wichita-tree-specialists">First-Time Tree Planting Tips from your Wichita Tree Specialists</a> 1014</h3> 1015</div> 1016 <div class="authorBar" data-auto="blog-author-bar"> <span>September 19, 2022</span> 1017</div> 1018 <div class="postDescription" data-auto="blog-post-description">How to Ensure Your First Foray into Tree Planting is a Success There’s a first time for everything, but nothing sticks out quite like the first time you plant a tree. The memory of it will quite literally grow right before your very eyes. Your tree will provide shade for picnics and keep your house […] 1019The post First-Time Tree Planting Tips from your Wichita Tree Specialists appeared first on Huff's Tree Service.</div> 1020</div> 1021 <div class="readMore" data-auto="blog-read-more"> <a dont-color-link="true" href="/first-time-tree-planting-tips-from-your-wichita-tree-specialists"></a> 1022</div> 1023</div> 1024</div> 1025</div> 1026 <div style="-ms-grid-column:1; -ms-grid-row:4" class="postArticle lastArticle" data-auto="blog-post-article"> <div class="inner clearfix wow" style="animation-delay: 2000.0ms;"> <a class="blogImgLink" data-auto="blog-img-link" dont-color-link="true" href="/8-reasons-your-local-arborist-recommends-planting-a-tree-native-to-wichita-kansas" data-blog-post-alias="8-reasons-your-local-arborist-recommends-planting-a-tree-native-to-wichita-kansas" aria-label="White-blossomed tree in a green yard with a house and fence in the background"> <div class="blogImg" data-auto="blog-img" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/8-reasons-your-local-arborist-recommends-planting-a-tree-native-to-wichita-kansas-1920w.jpg');"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/8-reasons-your-local-arborist-recommends-planting-a-tree-native-to-wichita-kansas-1920w.jpg" alt="White-blossomed tree in a green yard with a house and fence in the background" onerror="handleImageLoadError(this)" loading="lazy"/></div> 1027</a> 1028 <div class="postTextContainer"> <div class="postText clearfix"> <div class="postTitle" data-auto="blog-post-title"> <h3> <a dont-color-link="true" href="/8-reasons-your-local-arborist-recommends-planting-a-tree-native-to-wichita-kansas" data-blog-post-alias="8-reasons-your-local-arborist-recommends-planting-a-tree-native-to-wichita-kansas">8 Reasons Your Local Arborist Recommends Planting a Tree Native to Wichita, Kansas</a> 1029</h3> 1030</div> 1031 <div class="authorBar" data-auto="blog-author-bar"> <span>September 5, 2022</span> 1032</div> 1033 <div class="postDescription" data-auto="blog-post-description">Give Your Trees the Best Chance to Thrive by Going with a Native Species Native and non-native. These are very important distinctions to make if you plan on planting a tree on your property in Wichita, Kansas. The United States consists of several different planting zones, which is the main guide for arborists regarding what […] 1034The post 8 Reasons Your Local Arborist Recommends Planting a Tree Native to Wichita, Kansas appeared first on Huff's Tree Service.</div> 1035</div> 1036 <div class="readMore" data-auto="blog-read-more"> <a dont-color-link="true" href="/8-reasons-your-local-arborist-recommends-planting-a-tree-native-to-wichita-kansas"></a> 1037</div> 1038</div> 1039</div> 1040</div> 1041</div> 1042 <a dont-color-link="true" class="more-posts-text-container dmWidget"> <span class="morePosts text">Show More</span> 1043</a> 1044</div> 1045</div> 1046</div> 1047</div> 1048</div> 1049</div> 1050</section> 1051</div> 1052 <div data-flex-id="6ccf660f" data-auto="flex-section" id="1836061839" data-layout-section="" data-page-element-type="section" data-page-element-id="1172532458" class="homeherogeo" data-custom-class-name="homeherogeo"> <div class="flex-widgets-container" id="1931119823"></div> 1053 <section id="7ea8d7cf" class="flex-element section" data-auto="flex-element-section"> <div id="b93fd6a9" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid="" data-binding="eyJiaW5kaW5nTmFtZSI6ImJhY2tncm91bmQiLCJ2YWx1ZSI6IlNUQVRJQ19QQUdFX0NPTExFQ1RJT04ue1wiY25cIjpcIjAxIEhPTUVcIixcImZuXCI6XCJIRVJPIElNQUdFXCJ9In0=" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/home-hero-image-huffs-tree-service-1920w.jpg') !important;"> <div id="f6abe2be" class="flex-element group" data-auto="flex-element-group"> <div id="925e7fdf" class="flex-element group" data-auto="flex-element-group"> <div id="1e175c53" class="flex-element widget-wrapper HH1" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1531246810"> <div class="u_1531246810 dmNewParagraph" data-element-type="paragraph" data-version="5" id="1531246810" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCIwMSBIT01FXCIsXCJmblwiOlwiSEVSTyBIRUFETElORVwifSJ9XQ==" data-diy-text="" style="">Tree, Turf & Plant Health Services</div> 1054</div> 1055 <div id="d9479f42" class="flex-element widget-wrapper HH2" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1199098238"> <div class="u_1199098238 dmNewParagraph" data-element-type="paragraph" data-version="5" id="1199098238" data-diy-text="" style="" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCIwMSBIT01FXCIsXCJmblwiOlwiSEVSTyBHRU9cIn0ifV0=">SEDGWICK AND BUTLER COUNTIES, KS</div> 1056</div> 1057 <div id="3a5b36e4" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1563404019"> <div class="u_1563404019 widget-c4b2f9 dmCustomWidget" data-lazy-load="true" data-title="" id="1563404019" dmle_extension="custom_extension" data-element-type="custom_extension" data-binding="W3siYmluZGluZ05hbWUiOiJtb3RGYWN0VGV4dCIsInZhbHVlIjoic2l0ZV90ZXh0Lm1vdGl2YXRpbmcgZmFjdG9ycyJ9XQ==" icon="false" surround="false" data-widget-id="c4b2f903d115403c8c21e9ec6044a4fe" data-widget-version="59" data-widget-config="eyJtb3RGYWN0VGV4dCI6IjxwIGNsYXNzPVwicnRlQmxvY2tcIj5FbWVyZ2VuY3kgU2VydmljZXMgQXZhaWxhYmxlwqA8L3A+PHAgY2xhc3M9XCJydGVCbG9ja1wiPkZyZWUgU2FtZS1EYXkgRXN0aW1hdGVzwqA8L3A+PHAgY2xhc3M9XCJydGVCbG9ja1wiPjUgQ2VydGlmaWVkIEFyYm9yaXN0cyBvbiBTdGFmZjwvcD4iLCJob3JpelRvZ2dsZSI6ZmFsc2UsIm1mQWxpZ24iOiJNRmFsaWduQyIsImRpdlN0eWxlIjoibWYtaG9yaXotYnVsIn0="> <div class="motFactCont MFalignC "> <p class="rteBlock">Emergency Services Available </p><p class="rteBlock">Free Same-Day Estimates </p><p class="rteBlock">5 Certified Arborists on Staff</p> 1058</div> 1059</div> 1060</div> 1061 <div id="b7ff358b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-hidden-on-mobile="" data-external-id="1412984898"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton" file="false" href="tel:(316) 871-3841" data-element-type="dButtonLinkId" id="1412984898" data-binding="W3siYmluZGluZ05hbWUiOiJsaW5rIiwidmFsdWUiOiJjb250ZW50X2xpYnJhcnkuZ2xvYmFsLnBob25lLmxvYy0wIC0gbWFpbiJ
10619LHsiYmluZGluZ05hbWUiOiJidXR0b25fdGV4dCIsInZhbHVlIjoiY29udGVudF9saWJyYXJ5Lmdsb2JhbC5waG9uZS5sb2MtMCAtIG1haW4ifV0=" data-diy-link=""> <span class="iconBg" aria-hidden="true" id="1294230198"> <span class="icon hasFontIcon icon-star" id="1080541107"></span> 1062</span> 1063 <span class="text" id="1397234252" data-diy-text="">(316) 871-3841</span> 1064</a> 1065</div> 1066</div> 1067 <div id="311dd324" class="flex-element group" data-auto="flex-element-group"> <div id="fc1e2657" class="flex-element group" data-auto="flex-element-group" data-anim-extended="eyJkZXNrdG9wIjp7InRyaWdnZXIiOiJlbnRyYW5jZSIsImFuaW1hdGlvbiI6ImZhZGVJbkNvbWJvIiwiZHVyYXRpb24iOjEsImRlbGF5IjowLCJpbnRlbnNpdHkiOjEsImRpciI6ImluLXBsYWNlIn19"> <div id="e76e903e" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1898883001"> <div class="widget-6f306f dmCustomWidget" data-lazy-load="true" data-title="" id="1898883001" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="6f306f3f1793463e9c5243713002bc78" data-widget-version="4" data-widget-config="eyJoZWFkaW5nVGFnIjoiaDUiLCJmYWxsYmFja1RleHQiOiJSZXF1ZXN0IExvcmVtIEVwc29tIn0="> <div class="form-title-widget"> <h5 class="form-title-output">Request Lorem Epsom</h5> 1068</div> 1069</div> 1070</div> 1071 <div id="247a8c48" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="form" lock-element-for-editing="true" data-external-id="1019079231"> <div class="dmform default native-inputs u_1019079231 form-ltr-direction" data-element-type="dContactUsRespId" captcha="true" data-require-captcha="true" data-captcha-position="bottomleft" id="1019079231" data-captcha-message="PHAgY2xhc3M9InJ0ZUJsb2NrIj5UaGlzIHNpdGUgaXMgcHJvdGVjdGVkIGJ5IHJlQ0FQVENIQS48L3A+" data-layout="layout-1" alignment="form-ltr-direction" data-binding="W3siYmluZGluZ05hbWUiOiJlbWFpbCIsInZhbHVlIjoiY29udGVudF9saWJyYXJ5Lmdsb2JhbC5lbWFpbC5lbWFpbCAtIGxvYyAxIn1d"> <h3 class="dmform-title dmwidget-title" id="1955593084" hide="true">Hero Request Form</h3> 1072 <div class="dmform-wrapper" id="1323532418" captcha-lang="en"> <form method="post" class="dmRespDesignRow" locale="ENGLISH" id="1739679758"> <div class="spacing-container" id="1236306917"> <div class="dmforminput required small-12 dmRespDesignCol medium-12 large-12" id="1216328098"> <label for="1554060302" id="1284055220" class="" hide="true" data-dm-for="dmform-0">Name:</label> 1073 <input type="text" class="" name="dmform-0" id="1554060302" placeholder="Full Name*" data-placeholder-original="Full Name*"/> <input type="hidden" name="label-dmform-0" value="Name:" id="1277754605" class=""/> </div> 1074 <div class="dmforminput required small-12 dmRespDesignCol medium-12 large-12" id="1808430815"> <label for="1672879376" id="1188593056" class="" hide="true" data-dm-for="dmform-2">Phone:</label> 1075 <input type="tel" class="" name="dmform-2" id="1672879376" placeholder="Phone*" data-placeholder-original="Phone*"/> <input type="hidden" name="label-dmform-2" value="Phone" id="1508436068"/> </div> 1076 <div class="dmforminput required small-12 dmRespDesignCol medium-12 large-12" id="1473292509"> <label for="1633739979" id="1807579978" class="" hide="true" data-dm-for="dmform-1">Email:</label> 1077 <input type="email" class="" name="dmform-1" id="1633739979" placeholder="Email*" data-placeholder-original="Email*"/> <input type="hidden" name="label-dmform-1" value="Email" id="1824357486"/> </div> 1078 <div class="dmforminput small-12 dmRespDesignCol medium-12 large-12 required" id="1949619954"> <label for="1722294916" id="1896936654" class="" hide="true" data-dm-for="dmform-3">Services</label> 1079<input type="text" name="dmform-3" id="1722294916"/><input type="hidden" name="label-dmform-3" value="Services" id="1215109023" class=""/></div> 1080</div> 1081 <div class="dmformsubmit dmWidget R" id="1488623431"> <input class="" name="submit" type="submit" value="Form Button" id="1370960412"/> </div> 1082 <input name="dmformsendto" type="hidden" id="1306448568" class="" value="O0wrseIfFLvmGWa2hQB1vszHIExBwhgwvYKoLawGbddElvktotfzqf2HGz6vfqBkEKxVMv2u2nS4ty9RumwBQA==" data-dec="true"/> <input class="dmActionInput" type="hidden" name="action" value="/_dm/s/rt/widgets/dmform.submit.jsp" id="1893773884"/>
1082 <input name="dmformsubject" type="hidden" value="Hibu Website Form Submission" id="1603194015" class="" data-email-subject="Hibu Website Form Submission"/> <input name="dmformfrom" type="hidden" value="" id="1718865523"/> <input name="dmformautoreplyenabled" type="hidden" value="false" id="1194455789" class=""/> <input name="dmformautoreplyfrom" type="hidden" value="" id="1845960460"/> <input name="dmformautoreplysubject" type="hidden" value="Thank you for your submission" id="1404245225"/> <input name="dmformautoreplymsg" type="hidden" value="V2UndmUgcmVjZWl2ZWQgeW91ciBtZXNzYWdlIC0gdGhhbmsgeW91LiBPbmUgb2Ygb3VyIHRlYW0gbWVtYmVycyB3aWxsIGdldCBiYWNrIHRvIHlvdSBzb29uLg==" id="1159870522"/> <input name="dmformautoreplyincludeformcopy" type="hidden" value="true" id="1439582503"/> <input name="dmformsubmitparams" type="hidden" value="8mpKnCSiNQXK/d9M7IDrS21iaGO90EYxrd9VAEk3PxJJ+4Wa8LePnTm3DGeS583scrFEbc4I7LKA2XCsfpvaCC/6zdSpNJVLHUvEGM7njP6EtUTrwkZdOrLzYfJqxdPxR6fsakCjFUxhqtDxymk28a4aVNqWFhQX8Zsh2FQbEx8iOql5jykgZgcm7GuPssw6vInYaRuMq41PxKOLShqlJfXMtq4VB3QmnHMp5aUA11lUYWI4wXGljR/1UFf06ztRW651QXDtcMkKjyiGEqi09mJlFBA+tA1PMtm8vElZ9Qq1/ooq3y7TRanE0QR4G6cDqApyj7vetAFBFJc1UrGHbNci2I/9Ga0qPjEt2GCsH/5sMn3UoA53XY2+isJBr5Jox8m6X4beOtdmjmhiZAklv6/qKf9YLGGLEjHJPcGpWMmUk6YsZEA0m35Wj7W+AI2rMtx3E3/gWz36WUT98NB6X3zJYKnfxyqk659FaBGZjtwmDsvtFTL2FRb7G3U9lLR0ufYjTvCX7EH9hxs+r36gZCDh0PefO0tj" data-dec="true"/><input type="hidden" name="page_uuid" value="0f52bef5eae544d4a9b9525345e78a70"/></form> 1083</div> 1084 <div class="dmform-success" style="display:none" id="1125689168"> <br id="1633063501"/> <p class="rteBlock" id="1286287213">Thank you for contacting us.</p> 1085 <p class="rteBlock" id="1219415366">We will get back to you as soon as possible.</p> 1086</div> 1087 <div class="dmform-error" style="display:none" id="1563748711">Oops, there was an error sending your message. <br id="1593479308"/> Please try again later.</div> 1088</div> 1089</div> 1090</div> 1091</div> 1092</div> 1093</div> 1094</section> 1095</div> 1096 <div data-flex-id="0f37c9cb" data-auto="flex-section" id="1526583845" data-layout-section="" data-page-element-type="section" data-page-element-id="1172532458" class="collectionherogeo" data-custom-class-name="collectionherogeo"> <div class="flex-widgets-container" id="1471795551"></div> 1097 <section id="d156a03b" class="flex-element section" data-auto="flex-element-section"> <div id="834a6021" class="flex-element grid lazy" data-auto="flex-element-grid" data-layout-grid="" data-binding="eyJiaW5kaW5nTmFtZSI6ImJhY2tncm91bmQiLCJ2YWx1ZSI6ImR5bmFtaWNfcGFnZV9jb2xsZWN0aW9uLkhFUk8gSU1BR0UifQ==" data-background-image="https://le-cdn.hibuwebsites.com/md/dmip/dms3rep/multi/opt/black-jeans-1920w.png"> <div id="c0c8fb07" class="flex-element group" data-auto="flex-element-group"> <div id="23ae3ea0" class="flex-element group" data-auto="flex-element-group"> <div id="4a684f71" class="flex-element widget-wrapper HH1" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1258098665"> <div class="u_1258098665 dmNewParagraph" data-element-type="paragraph" data-version="5" id="1258098665" data-diy-text="" style="" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJkeW5hbWljX3BhZ2
1097VfY29sbGVjdGlvbi5IRVJPIEhFQURMSU5FIn1d"> <h1 class="text-align-center" id="1260726288">New Title</h1> 1098</div> 1099</div> 1100 <div id="ea683628" class="flex-element widget-wrapper HH2" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1601347497"> <div class="u_1601347497 dmNewParagraph" data-element-type="paragraph" data-version="5" id="1601347497" data-diy-text="" style="" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJkeW5hbWljX3BhZ2VfY29sbGVjdGlvbi5IRVJPIEdFTyJ9XQ=="> <h2 class="text-align-center t-size-31" id="1320301606"><span style="display: initial; color: var(--color_2);" id="1531577057">New Title</span></h2> 1101</div> 1102</div> 1103 <div id="f33d2b9a" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1496323151"> <div class="u_1496323151 widget-c4b2f9 dmCustomWidget" data-lazy-load="true" data-title="" id="1496323151" dmle_extension="custom_extension" data-element-type="custom_extension" data-binding="W3siYmluZGluZ05hbWUiOiJtb3RGYWN0VGV4dCIsInZhbHVlIjoic2l0ZV90ZXh0Lm1vdGl2YXRpbmcgZmFjdG9ycyJ9XQ==" icon="false" surround="false" data-widget-id="c4b2f903d115403c8c21e9ec6044a4fe" data-widget-version="59" data-widget-config="eyJtb3RGYWN0VGV4dCI6IjxwIGNsYXNzPVwicnRlQmxvY2tcIj5FbWVyZ2VuY3kgU2VydmljZXMgQXZhaWxhYmxlwqA8L3A+PHAgY2xhc3M9XCJydGVCbG9ja1wiPkZyZWUgU2FtZS1EYXkgRXN0aW1hdGVzwqA8L3A+PHAgY2xhc3M9XCJydGVCbG9ja1wiPjUgQ2VydGlmaWVkIEFyYm9yaXN0cyBvbiBTdGFmZjwvcD4iLCJob3JpelRvZ2dsZSI6ZmFsc2UsIm1mQWxpZ24iOiJNRmFsaWduQyIsImRpdlN0eWxlIjoibWYtaG9yaXotYnVsIn0="> <div class="motFactCont MFalignC "> <p class="rteBlock">Emergency Services Available </p><p class="rteBlock">Free Same-Day Estimates </p><p class="rteBlock">5 Certified Arborists on Staff</p> 1104</div> 1105</div> 1106</div> 1107 <div id="f5745250" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-hidden-on-mobile="" data-external-id="1986032916"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton" file="false" href="tel:(316) 871-3841" data-element-type="dButtonLinkId" id="1986032916" data-binding="W3siYmluZGluZ05hbWUiOiJsaW5rIiwidmFsdWUiOiJjb250ZW50X2xpYnJhcnkuZ2xvYmFsLnBob25lLmxvYy0wIC0gbWFpbiJ9LHsiYmluZGluZ05hbWUiOiJidXR0b25fdGV4dCIsInZhbHVlIjoiY29udGVudF9saWJyYXJ5Lmdsb2JhbC5waG9uZS5sb2MtMCAtIG1haW4ifV0=" data-diy-link=""> <span class="iconBg" aria-hidden="true" id="1009467264"> <span class="icon hasFontIcon icon-star" id="1962430241"></span> 1108</span> 1109 <span class="text" id="1843241712" data-diy-text="">(316) 871-3841</span> 1110</a> 1111</div> 1112 <div id="eb06105c" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-hidden-on-mobile="" data-external-id="1612329860"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton" file="false" href="/contact" data-element-type="dButtonLinkId" id="1612329860" data-binding="W3siYmluZGluZ05hbWUiOiJsaW5rIiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCJidXR0b25zXCIsXCJmblwiOlwiVmlzaXQgLyBDb250YWN0IExpbmtcIn0ifSx7ImJpbmRpbmdOYW1lIjoiYnV0dG9uX3RleHQiLCJ2YWx1ZSI6IlNUQVRJQ19QQUdFX0NPTExFQ1RJT04ue1wiY25cIjpcImJ1dHRvbnNcIixcImZuXCI6XCJWaXNpdCAvIENvbnRhY3QgQnV0dG9uXCJ9In1d" data-diy-link=""> <span class="iconBg" aria-hidden="true" id="1860033837"> <span class="icon hasFontIcon icon-star" id="1643077392"></span> 1113</span> 1114 <span class="text" id="1506837762" data-diy-text="">CONTACT US</span> 1115</a> 1116</div> 1117</div> 1118 <div id="07850ad3" class="flex-element group" data-auto="flex-element-group"> <div id="d761791c" class="flex-element group" data-auto="flex-element-group" data-anim-extended="eyJkZXNrdG9wIjp7InRyaWdnZXIiOiJlbnRyYW5jZSIsImFuaW1hdGlvbiI6ImZhZGVJbkNvbWJvIiwiZHVyYXRpb24iOjEsImRlbGF5IjowLCJpbnRlbnNpdHkiOjEsImRpciI6ImluLXBsYWNlIn19"> <div id="e154016c" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1373286055"> <div class="widget-6f306f dmCustomWidget" data-lazy-load="true" data-title="" id="1373286055" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="6f306f3f1793463e9c5243713002bc78" data-widget-version="4" data-widget-config="eyJoZWFkaW5nVGFnIjoiaDUiLCJmYWxsYmFja1RleHQiOiJSZXF1ZXN0IExvcmVtIEVwc29tIn0="> <div class="form-title-widget"> <h5 class="form-title-output">Request Lorem Epsom</h5> 1119</div> 1120</div> 1121</div> 1122 <div id="7ebd781d" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="form" lock-element-for-editing="true" data-external-id="1673887128"> <div class="dmform default native-inputs u_1673887128 form-ltr-direction" data-element-type="dContactUsRespId" captcha="true" data-require-captcha="true" data-captcha-position="bottomleft" id="1673887128" data-captcha-message="PHAgY2xhc3M9InJ0ZUJsb2NrIj5UaGlzIHNpdGUgaXMgcHJvdGVjdGVkIGJ5IHJlQ0FQVENIQS48L3A+" data-layout="layout-1" alignment="form-ltr-direction" data-binding="W3siYmluZGluZ05hbWUiOiJlbWFpbCIsInZhbHVlIjoiY29udGVudF9saWJyYXJ5Lmdsb2JhbC5lbWFpbC5lbWFpbCAtIGxvYyAxIn1d"> <h3 class="dmform-title dmwidget-title" id="1389216119" hide="true">Hero Request Form</h3> 1123 <div class="dmform-wrapper" id="1021816190" captcha-lang="en"> <form method="post" class="dmRespDesignRow" locale="ENGLISH" id="1263607347"> <div class="spacing-container" id="1207324606">
1123 <div class="dmforminput required small-12 dmRespDesignCol medium-12 large-12" id="1954449754"> <label for="1743376804" id="1974158264" class="" hide="true" data-dm-for="dmform-0">Name:</label> 1124 <input type="text" class="" name="dmform-0" id="1743376804" placeholder="Full Name*" data-placeholder-original="Full Name*"/> <input type="hidden" name="label-dmform-0" value="Name:" id="1206970123" class=""/> </div> 1125 <div class="dmforminput required small-12 dmRespDesignCol medium-12 large-12" id="1143759103"> <label for="1802876709" id="1632093017" class="" hide="true" data-dm-for="dmform-2">Phone:</label> 1126 <input type="tel" class="" name="dmform-2" id="1802876709" placeholder="Phone*" data-placeholder-original="Phone*"/> <input type="hidden" name="label-dmform-2" value="Phone" id="1421963898"/> </div> 1127 <div class="dmforminput required small-12 dmRespDesignCol medium-12 large-12" id="1429115166"> <label for="1693292987" id="1433975460" class="" hide="true" data-dm-for="dmform-1">Email:</label> 1128 <input type="email" class="" name="dmform-1" id="1693292987" placeholder="Email*" data-placeholder-original="Email*"/> <input type="hidden" name="label-dmform-1" value="Email" id="1686525747"/> </div> 1129 <div class="dmforminput small-12 dmRespDesignCol medium-12 large-12 required" id="1504826107"> <label for="1600142677" id="1340598512" class="" hide="true" data-dm-for="dmform-3">Services</label> 1130<input type="text" name="dmform-3" id="1600142677"/><input type="hidden" name="label-dmform-3" value="Services" id="1854321971" class=""/></div> 1131</div> 1132 <div class="dmformsubmit dmWidget R" id="1327303439"> <input class="" name="submit" type="submit" value="Form Button" id="1554418358"/> </div> 1133 <input name="dmformsendto" type="hidden" id="1642524889" class="" value="O0wrseIfFLvmGWa2hQB1vszHIExBwhgwvYKoLawGbddElvktotfzqf2HGz6vfqBkEKxVMv2u2nS4ty9RumwBQA==" data-dec="true"/> <input class="dmActionInput" type="hidden" name="action" value="/_dm/s/rt/widgets/dmform.submit.jsp" id="1046165661"/> <input name="dmformsubject" type="hidden" value="Hibu Website Form Submission" id="1121031446" class="" data-email-subject="Hibu Website Form Submission"/> <input name="dmformfrom" type="hidden" value="" id="1461608614"/> <input name="dmformautoreplyenabled" type="hidden" value="false" id="1985659778" class=""/> <input name="dmformautoreplyfrom" type="hidden" value="" id="1400297653"/> <input name="dmformautoreplysubject" type="hidden" value="Thank you for your submission" id="1742849496"/> <input name="dmformautoreplymsg" type="hidden" value="V2UndmUgcmVjZWl2ZWQgeW91ciBtZXNzYWdlIC0gdGhhbmsgeW91LiBPbmUgb2Ygb3VyIHRlYW0gbWVtYmVycyB3aWxsIGdldCBiYWNrIHRvIHlvdSBzb29uLg==" id="1458722812"/> <input name="dmformautoreplyincludeformcopy" type="hidden" value="true" id="1197331366"/> <input name="dmformsubmitparams" type="hidden" value="8mpKnCSiNQXK/d9M7IDrS21iaGO90EYxrd9VAEk3PxJJ+4Wa8LePnTm3DGeS583scrFEbc4I7LKA2XCsfpvaCC/6zdSpNJVLHUvEGM7njP6EtUTrwkZdOrLzYfJqxdPxR6fsakCjFUxhqtDxymk28a4aVNqWFhQX8Zsh2FQbEx8iOql5jykgZgcm7GuPssw6vInYaRuMq41PxKOLShqlJfXMtq4VB3QmnHMp5aUA11lUYWI4wXGljR/1UFf06ztRW651QXDtcMkKjyiGEqi09mJlFBA+tA1PMtm8vElZ9Qq1/ooq3y7TRanE0QR4G6cDqApyj7vetAFBFJc1UrGHbNci2I/9Ga0qPjEt2GCsH/5sMn3UoA53XY2+isJBr5Jox8m6X4beOtdmjmhiZAklv6/qKf9YLGGLEjHJPcGpWMmUk6YsZEA0m35Wj7W+AI2rMtx3E3/gWz36WUT98NB6X3zJYKnfxyqk659FaBGZjtwmDsvtFTL2FRb7G3U9lLR0ufYjTvCX7EH9hxs+r36gZCDh0PefO0tj" data-dec="true"/><input type="hidden" name="page_uuid" value="0f52bef5eae544d4a9b9525345e78a70"/></form> 1134</div> 1135 <div class="dmform-success" style="display:none" id="1384636000"> <br id="1607699545"/> <p class="rteBlock" id="1195124846">Thank you for contacting us.</p> 1136 <p class="rteBlock" id="1884572040">We will get back to you as soon as possible.</p> 1137</div> 1138 <div class="dmform-error" style="display:none" id="1681118279">Oops, there was an error sending your message. <br id="1272982348"/> Please try again later.</div> 1139</div> 1140</div> 1141</div> 1142</div> 1143</div> 1144</div> 1145</section> 1146</div> 1147 <div data-layout-section="" data-auto="flex-section" id="1844178153" data-flex-id="f9a24a98" data-page-element-type="section" data-page-element-id="1688378275"> <div class="flex-widgets-container" id="1899023587"></div> 1148 <section id="60801b00" class="flex-element section" data-auto="flex-element-section"> <div id="80c8bd69" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="956767f0" class="flex-element group" data-auto="flex-element-group"> <div id="26a403a5" class="flex-element group" data-auto="flex-element-group"> <div id="7fcf5600" class="flex-element widget-wrapper DCBH2" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1613806224"> <div class="dmNewParagraph u_1613806224" data-element-type="paragraph" data-version="5" id="1613806224" style="" data-inject="introheading1" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCIwMSBIT01FXCIsXCJmblwiOlwiSU5UUk8gSEVBRExJTkVcIn0ifV0=" data-diy-text="">Your Trusted Partner for Complete Tree Care Solutions</div> 1149</div> 1150 <div id="bf1af1cf" class="flex-element group" data-auto="flex-element-group"> <div id="772b1abe" class="flex-element group" data-auto="flex-element-group"> <div id="89822ae5" class="flex-element widget-wrapper DCBP" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1995568531"> <div class="dmNewParagraph u_1995568531" data-element-type="paragraph" data-version="5" id="1995568531" style="" data-inject="introcontent1" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCIwMSBIT01FXCIsXCJmblwiOlwiSU5UUk8gUEFSQUdSQVBIIChDT0xVTU4gMSlcIn0ifV0=" data-diy-text=""><p>When your trees need attention, Huff's Tree Service delivers the skilled care they deserve. Our family-owned business started in 2012, and we've spent over 21 years perfecting our craft and building lasting relationships with property owners throughout Wichita, KS, and surrounding areas. Our team of ISA-certified arborists brings both credentials and hands-on experience to every job, ensuring your trees receive treatments based on proven arboricultural science.</p><p><br/></p><p>
1150Tree trimming keeps your landscape healthy and safe, not just looking good. Overgrown branches can threaten your home, storm-damaged limbs create hazards, and regular maintenance improves your property's appearance. Our knowledgeable staff has the equipment and expertise to handle projects of any size. We offer free same-day estimates so you can make informed decisions quickly, and we're available for after-hours appointments and emergency services when urgent situations arise. Ready to give your trees the care they need? <a href="/contact" runtime_url="/contact" type="page">Contact us</a> 1151today to schedule your consultation.</p></div> 1152</div> 1153</div> 1154 <div id="f34f2047" class="flex-element group" data-auto="flex-element-group"> <div id="9f4eb432" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="image" data-external-id="1658143524"> <div class="imageWidget align-center u_1658143524" data-element-type="image" data-widget-type="image" id="1658143524" data-binding="W3siYmluZGluZ05hbWUiOiJpbWFnZSIsInZhbHVlIjoic2l0ZV9pbWFnZXMucGVyc2lzdGVkLkludHJvIC8gV2h5IENob29zZSBJbWFnZSJ9XQ=="><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/515436627_1219847583493375_5418250398841743604_n-668w.png" alt="Utility truck with extended crane clearing tree branches on a roadside." id="1931757604" class="" width="557.0" height="229.0" data-dm-image-path="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/515436627_1219847583493375_5418250398841743604_n.png" data-diy-image="" onerror="handleImageLoadError(this)"/></div> 1155</div> 1156</div> 1157</div> 1158</div> 1159</div> 1160</div> 1161</section> 1162</div> 1163 <div data-layout-section="" data-auto="flex-section" id="1884391590" data-flex-id="c5ba0c32" data-page-element-type="section" data-page-element-id="1564952396"> <div class="flex-widgets-container" id="1439125907"></div> 1164 <section id="44535651" class="flex-element section" data-auto="flex-element-section"> <div id="b06d12cf" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="ca073e0e" class="flex-element group" data-auto="flex-element-group"> <div id="04e97c1c" class="flex-element group" data-auto="flex-element-group"> <div id="3198bf07" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1931210455"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1931210455" data-diy-text="" data-inject="whychooseheading1" style=""> <h2 class="text-align-center"><span style="display: unset; color: var(--color_16);">Why Choose Us</span></h2> 1165</div> 1166</div> 1167 <div id="e81bdbf2" class="flex-element group" data-auto="flex-element-group"> <div id="8d04ab49" class="flex-element group" data-auto="flex-element-group"> <div id="a6a9fe96" class="flex-element group" data-auto="flex-element-group"> <div id="efb87c9b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="graphic" data-keep-proportion="true" data-external-id="1829673098"> <div class="graphicWidget graphicWidgetV2 graphicWidgetV3 u_1829673098" data-element-type="graphic" data-widget-type="graphic" id="1829673098" data-hover-effect="zoomout"> <svg width="100%" height="100%" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1694488826" class="svg u_1694488826" data-icon-custom="true" data-icon-name="certified_7922799.svg"> <path d="m84.578 43.59c0-19.07-15.508-34.578-34.578-34.578-19.059 0-34.578 15.512-34.578 34.578 0 17.969 13.801 32.801 31.359 34.43 0.058594 0 0.10938 0 0.17188 0.011719 1 0.089844 2.0195 0.12891 3.0508 0.12891s2.0391-0.039062 3.0508-0.12891c0.058593-0.011719 0.10937-0.011719 0.17187-0.011719 17.543-1.6289 31.352-16.461 31.352-34.43zm-33.867 16.16c-1.0312 1.1406-2.5 1.7891-4.0312 1.7891-1.3594 0-2.6719-0.51172-3.6719-1.4297l-16.898-15.391c-2.2188-2.0195-2.3906-5.4805-0.37109-7.6992 2.0312-2.2188 5.4883-2.3906 7.7109-0.37109l12.879 11.73 19.273-21.109c2.0312-2.2188 5.4883-2.3789 7.7109-0.35156 1.0703 0.98047 1.6992 2.3203 1.7617 3.7695 0.070312 1.4609-0.44141 2.8594-1.4219 3.9297z"></path> 1168 <path d="m66.941 28.48-19.891 21.781c-0.32812 0.37109-0.89844 0.39844-1.2695 0.070312l-13.543-12.344c-0.69922-0.62109-1.5703-0.94141-2.4492-0.94141-0.98828 0-1.9688 0.39062-2.6992 1.1797-1.3516 1.4805-1.2383 3.7891 0.25 5.1406l16.898 15.391c0.67188 0.60938 1.5391 0.94922 2.4492 0.94922 1.0195 0 2-0.42188 2.6914-1.1797l22.93-25.129c0.66016-0.73047 0.98828-1.6484 0.94922-2.6211-0.039062-0.98047-0.46094-1.8711-1.1797-2.5312-1.4766-1.3477-3.7891-1.2461-5.1367 0.23438z"></path> 1169 <path d="m22.148 77.898-0.058594 0.14844-6.7383 17.93 13.23-4.89
116906c0.35156-0.12109 0.73047-0.039063 0.96875 0.21875l8.3516 8.6914 7.6289-20.289c-7.8516-0.96875-14.941-4.4492-20.441-9.6211z"></path> 1170 <path d="m20.91 76.059 2.7695-7.3594c-6.2305-6.5391-10.059-15.391-10.059-25.102 0-20.078 16.32-36.398 36.379-36.398s36.379 16.32 36.379 36.391c0 9.7188-3.8398 18.57-10.059 25.102l2.7695 7.3594c9.2383-8.2695 14.5-20.031 14.5-32.469 0-24.031-19.551-43.582-43.59-43.582-24.031 0-43.59 19.551-43.59 43.59 0 12.43 5.2812 24.191 14.5 32.469z"></path> 1171 <path d="m77.801 77.75-2.8906-7.6602c-5.5 5.1484-12.59 8.6484-20.441 9.6211l7.6406 20.289 8.3281-8.6914c0.26172-0.26953 0.64062-0.35156 0.96875-0.21875l13.23 4.8906-6.7812-18.039z"></path> 1172</svg> 1173</div> 1174</div> 1175 <div id="1891fe74" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1347012849"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1347012849" style="" new-inline-bind-applied="true" data-diy-text=""><p class="t-text-align-left text-align-center m-text-align-center" style="line-height: 1.5;"><span style="color: var(--color_16); display: initial;"><span class="inline-data-binding" data-encoded-value="NSBDZXJ0aWZpZWQgQXJib3Jpc3RzIG9uIFN0YWZm" data-inline-binding="" data-inline-binding-encoded="U1RBVElDX1BBR0VfQ09MTEVDVElPTi57ImNuIjoiV2h5IENob29zZSIsImZuIjoiV2h5IENob29zZSAxIn0=">5 Certified Arborists on Staff</span></span></p></div> 1176</div> 1177</div> 1178 <div id="89c64c77" class="flex-element group" data-auto="flex-element-group"> <div id="12f77a0f" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="graphic" data-keep-proportion="true" data-external-id="1809752902"> <div class="graphicWidget graphicWidgetV2 graphicWidgetV3 u_1809752902" data-element-type="graphic" data-widget-type="graphic" id="1809752902" data-hover-effect="zoomout"> <svg width="100%" height="100%" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1123047695" class="svg u_1123047695" data-icon-custom="true" data-icon-name="service_8311899.svg"> <path d="m60.562 7.8125c-0.76953 0-1.4258 0.55859-1.5469 1.3164l-1.3594 8.1172c-0.81641 0.32422-1.6094 0.69531-2.3789 1.1211l-7.1484-3.9805c-0.66797-0.37109-1.5078-0.20703-1.9844 0.39453l-5.8125 7.2852c-0.47656 0.59766-0.45312 1.4531 0.058594 2.0195l5.5156 6.125c-0.25 0.83594-0.44922 1.6875-0.58984 2.5469l-7.5898 3.125c-0.70703 0.28906-1.1016 1.0469-0.93359 1.7891l2.0742 9.0859c0.17187 0.74609 0.85156 1.2578 1.6133 1.2148l8.1914-0.48438c0.50781 0.71875 1.0625 1.4062 1.6602 2.0547l-2.293 7.875v-0.003907c-0.21484 0.73828 0.13672 1.5195 0.82813 1.8477l8.3945 4.0508c0.69141 0.33203 1.5234 0.12109 1.9609-0.50781l4.6797-6.6562c0.4375 0.035156 0.875 0.097656 1.3164 0.10547h0.046875c0.46094-0.007812 0.91406-0.066406 1.375-0.10547l4.6719 6.6328c0.4375 0.62109 1.2617 0.83203 1.9492 0.50391l8.4062-4.0469c0.6875-0.33203 1.0312-1.1133 0.81641-1.8438l-2.293-7.9023c0.59375-0.64844 1.1445-1.3359 1.6523-2.0547l8.1758 0.48438-0.003906 0.003906c0.76172 0.042969 1.4453-0.46875 1.6172-1.2109l2.0781-9.0859v-0.003906c0.17187-0.74609-0.22266-1.5117-0.93359-1.8008l-7.5664-3.1016c-0.14063-0.88281-0.35156-1.75-0.60938-2.6094l5.4648-6.0664-0.003906 0.003906c0.50781-0.57031 0.53516-1.4219 0.058594-2.0195l-5.8125-7.2891c-0.47656-0.59766-1.3164-0.76172-1.9844-0.39063l-7.1484 3.9805c-0.77734-0.4375-1.582-0.83203-2.4102-1.1641l-1.3359-8.0391h-0.003907c-0.12109-0.76172-0.77734-1.3164-1.5469-1.3164zm4.6836 17.184c6.0352 0 10.934 4.9102 10.934 10.945s-4.8984 10.945-10.934 10.945-10.934-4.9102-10.934-10.945 4.8984-10.945 10.934-10.945zm-57.441 39.066c-0.86328 0.003906-1.5586 0.70703-1.5547 1.5703v24.988c-0.003906 0.86328 0.69531 1.5664 1.5547 1.5703h14.07v-28.125zm17.184 0v28.125h7.8203c0.86328-0.003906 1.5586-0.70703 1.5547-1.5703v-24.988c0.003907-0.86328-0.69531-1.5664-1.5547-1.5703zm20.402 2.4023c-2.6484 0.03125-5.2773 0.57812-7.8984 1.207v20.27c1.1289 0.24219 2.2383 0.57812 3.3164 1.0117h0.011718c2.7617 1.1055 5.707 1.6719 8.6797 1.6719h6.7422c4.3164 0 8.6016-0.76953 12.652-2.2617l20.887-7.6914c2.3711-0.875 3.9531-3.1445 3.9531-5.6719 0-2.5703-2.332-4.582-4.8789-4.2188l-16.992 2.4219c-0.019531-0.28125 0.003907 0.14062 0.007813 0.24219 0 3.4336-2.8164 6.2539-6.25 6.2539l-14.059-0.007813c-0.86719 0.003906-1.5742-0.69922-1.5
1178703-1.5703 0.003906-0.86328 0.70703-1.5586 1.5703-1.5547h9.9102c2.293 0 5.875-1.0352 6.6055-3.0898 0.18359-0.51953 0.33594-1.0508 0.44922-1.5469 0.19922-0.875 0.19531-2.5273-0.54297-2.9609-0.23438-0.13672-0.50781-0.21484-0.80469-0.21484l-8.3047-0.003906c-2.9688 0-5.9062-0.55859-8.6641-1.6602l-0.03125-0.011719c-1.6016-0.45703-3.1992-0.63281-4.7891-0.61719zm-15.711 2.2891c0.86328 0 1.5625 0.69922 1.5625 1.5625 0 0.86328-0.69922 1.5625-1.5625 1.5625-0.86328 0-1.5625-0.69922-1.5625-1.5625 0-0.86328 0.69922-1.5625 1.5625-1.5625z"></path> 1179</svg> 1180</div> 1181</div> 1182 <div id="8b18b1f2" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1806043159"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1806043159" style="" new-inline-bind-applied="true" data-diy-text=""><p class="text-align-center m-text-align-center" style="line-height: 1.5;"><span style="color: var(--color_16); display: initial;"><span class="inline-data-binding" data-encoded-value="RW1lcmdlbmN5IFNlcnZpY2VzIEF2YWlsYWJsZQ==" data-inline-binding="" data-inline-binding-encoded="U1RBVElDX1BBR0VfQ09MTEVDVElPTi57ImNuIjoiV2h5IENob29zZSIsImZuIjoiV2h5IENob29zZSAyIn0=">Emergency Services Available</span></span></p></div> 1183</div> 1184</div> 1185 <div id="4acec404" class="flex-element group" data-auto="flex-element-group"> <div id="8c85ee6f" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="graphic" data-keep-proportion="true" data-external-id="1022642321"> <div class="graphicWidget graphicWidgetV2 graphicWidgetV3 u_1022642321" data-element-type="graphic" data-widget-type="graphic" id="1022642321" data-hover-effect="zoomout"> <svg width="100%" height="100%" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1060691097" class="svg u_1060691097" data-icon-custom="true" data-icon-name="experience_7703814.svg"> <path d="m20.703 93.75c0-5.2852 2.1016-10.352 5.832-14.086 3.7383-3.7344 8.8047-5.8359 14.086-5.8359h18.758c5.2812 0 10.348 2.0977 14.086 5.8359 3.7344 3.7305 5.832 8.8008 5.832 14.086 0 0.64844-0.52344 1.1758-1.1719 1.1758l-56.25-0.003906c-0.64453 0-1.1719-0.52734-1.1719-1.1758zm29.297-54.293c8.8398 0 16.016 7.1758 16.016 16.016s-7.1758 16.016-16.016 16.016c-8.8438 0-16.016-7.1758-16.016-16.016s7.1758-16.016 16.016-16.016zm1.043-33.703 3.1172 6.6367 6.9531 1.0586c0.4375 0.0625 0.79688 0.36719 0.9375 0.78516 0.13672 0.41406 0.03125 0.87891-0.27734 1.1914l-5.0625 5.1836 1.2031 7.3281c0.070313 0.44141-0.11719 0.88672-0.48437 1.1445-0.36328 0.25781-0.84766 0.28906-1.2422 0.070313l-6.2031-3.4258-6.1992 3.4258c-0.39453 0.21484-0.87891 0.1875-1.2422-0.070313-0.36719-0.25781-0.55469-0.70312-0.48438-1.1445l1.1992-7.3281-5.0625-5.1836c-0.30859-0.3125-0.41016-0.77734-0.27344-1.1914 0.14062-0.41406 0.5-0.72266 0.9375-0.78516l6.9492-1.0586 3.1172-6.6367c0.19531-0.41016 0.60547-0.67578 1.0625-0.67578s0.86719 0.26172 1.0625 0.67578zm28.125 12.504 3.1211 6.6328 6.9531 1.0586c0.43359 0.066406 0.79297 0.36719 0.93359 0.78906 0.14062 0.41406 0.035157 0.875-0.27344 1.1875l-5.0625 5.1836 1.1953 7.3281c0.070313 0.44531-0.11328 0.89062-0.48047 1.1484-0.36719 0.25781-0.84766 0.28516-1.2422 0.066406l-6.2031-3.4219-6.2031 3.4219c-0.39062 0.21484-0.875 0.19141-1.2422-0.066406-0.36719-0.25781-0.55078-0.70313-0.48047-1.1484l1.1953-7.3281-5.0625-5.1836c-0.30469-0.3125-0.41406-0.77344-0.27344-1.1875 0.14062-0.41797 0.5-0.72266 0.93359-0.78906l6.9531-1.0586 3.1172-6.6328c0.19531-0.41016 0.60938-0.67578 1.0625-0.67578s0.86719 0.26172 1.0625 0.67578zm-56.215 0 3.1211 6.6328 6.9531 1.0586c0.43359 0.066406 0.79297 0.36719 0.93359 0.78906 0.14062 0.41406 0.035156 0.875-0.26953 1.1875l-5.0625 5.1836 1.1953 7.3281c0.070312 0.44531-0.11328 0.89062-0.48047 1.1484-0.36719 0.25781-0.84766 0.28516-1.2422 0.066406l-6.2031-3.4219-6.2031 3.4219c-0.39062 0.21484-0.875 0.19141-1.2422-0.066406-0.36719-0.25781-0.55078-0.70313-0.48047-1.1484l1.1953-7.3281-5.0625-5.1836c-0.30469-0.3125-0.41406-0.77344-0.27344-1.1875 0.14062-0.41797 0.5-0.72266 0.93359-0.78906l6.957-1.0586 3.1172-6.6328c0.19531-0.41016 0.60547-0.67578 1.0586-0.67578 0.45312 0 0.87109 0.26172 1.0625 0.67578z" fill-rule="evenodd"></path> 1186</svg> 1187</div> 1188</div> 1189 <div id="8b276c7c" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1212496927"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1212496927" style="" new-inline-bind-applied="true" data-diy-text=""><p class="text-align-center m-text-align-center" style="line-height: 1.5;"><span style="color: var(--color_16); display: initial;"><span class="inline-data-binding" data-encoded-value="T3ZlciAyMSBZZWFycyBvZiBFeHBlcmllbmNl" data-inline-binding="" data-inline-binding-encoded="U1RBVElDX1BBR0VfQ09MTEVDVElPTi57ImNuIjoiV2h5IENob29zZSIsImZuIjoiV2h5IENob29zZSAzIn0=">Over 21 Years of Experience</span></span></p></div> 1190</div> 1191</div> 1192</div> 1193 <div id="6af78587" class="flex-element group" data-auto="flex-element-group"> <div id="08a7d21c" class="flex-element group" data-auto="flex-element-group"> <div id="ae6ec156" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="graphic" data-keep-proportion="true" data-external-id="1888411886"> <div class="graphicWidget graphicWidgetV2 graphicWidgetV3 u_1888411886" data-element-type="graphic" data-widget-type="graphic" id="1888411886" data-hover-effect="zoomout"> <svg width="100%" height="100%" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1832707936" class="svg u_1832707936" data-icon-custom="true" data-icon-name="conservation_8058274.
1193svg"> <path d="m51.609 56.422c-0.92188-0.82031-2.3008-0.82031-3.2109 0-0.46875 0.42188-0.98047 0.78906-1.5195 1.1016l-1.3906 26.5h9.0312l-1.3906-26.5c-0.53906-0.32031-1.0391-0.67969-1.5195-1.1016z"></path> 1194 <path d="m86.77 40.648c-1.5703-0.17188-3 0.92187-3.25 2.4688l-1.6719 10.199c1.6406 1.3398 1.9883 3.7617 0.75 5.5195l-4.6602 6.6016c-0.32031 0.44922-0.94922 0.55859-1.3984 0.23828-0.44922-0.32031-0.55859-0.94922-0.23828-1.3984l4.6602-6.6016c0.66016-0.94141 0.44141-2.2383-0.5-2.8984-0.94141-0.66016-2.2383-0.44141-2.8984 0.5l-4.6602 6.6016c-0.078125 0.12109-0.19141 0.21875-0.32031 0.28906-0.03125 0.019531-2.8906 1.6719-4.3906 3.8008-0.03125 0.039062-0.058594 0.089844-0.089844 0.12891-1.2617 1.8516-1.7812 4.1211-1.4609 6.3984l0.85938 6.2109h8.1484l-0.078126-1.0312c-0.10156-1.2891 0.25-2.5781 1-3.6406l7.8203-11.078c0.57812-0.82031 0.92969-1.7891 1.0117-2.8008l1.5703-19.301c0-0.12109-0.078125-0.21875-0.19141-0.23047z"></path> 1195 <path d="m73.719 43.711c0-1.9297-0.60938-3.7695-1.75-5.3203-1.1211-1.5195-2.6602-2.6211-4.4492-3.1992-0.32812-0.10938-0.57812-0.37891-0.67188-0.71094-0.078125-0.33984 0.011719-0.69141 0.26172-0.94141 1.2812-1.3086 1.9805-3.0312 1.9883-4.8594 0-1.8711-0.71875-3.6289-2.0391-4.9688-1.3281-1.3281-3.0898-2.0703-4.9609-2.0703-1.2891 0-2.5586 0.35938-3.6484 1.0312-0.28906 0.17969-0.64062 0.19922-0.94922 0.050781-0.30859-0.14062-0.51953-0.42969-0.57031-0.76953-0.23828-1.6484-1.0586-3.1719-2.3203-4.2695-1.2695-1.1094-2.9102-1.7305-4.6016-1.7305-1.6914 0-3.3281 0.60938-4.6016 1.7305-1.2617 1.1016-2.0898 2.6211-2.3203 4.2695-0.050782 0.32812-0.26172 0.62109-0.57031 0.76953-0.30859 0.14062-0.66016 0.12109-0.94922-0.050781-1.1016-0.67188-2.3594-1.0312-3.6484-1.0312-1.8711 0-3.6289 0.73047-4.9609 2.0703-1.3281 1.3281-2.0508 3.1016-2.0391 4.9688 0 1.8281 0.71875 3.5508 1.9883 4.8594 0.23828 0.25 0.33984 0.60156 0.26172 0.94141-0.078125 0.33984-0.33984 0.60938-0.67188 0.71094-1.7891 0.57812-3.3281 1.6797-4.4492 3.1992-1.1484 1.5508-1.75 3.3789-1.75 5.3203 0 4.6992 3.6719 8.6211 8.3594 8.9219 0.32812 0.019532 0.62891 0.19922 0.80078 0.48828 0.67188 1.1094 1.6094 2.0508 2.7305 2.6992 1.1602 0.67188 2.4805 1.0312 3.8203 1.0312 1.8711 0 3.6719-0.67969 5.0703-1.9297 0.83984-0.75 1.8906-1.1211 2.9414-1.1211s2.1016 0.37109 2.9414 1.1211c1.3984 1.2383 3.1992 1.9297 5.0703 1.9297 1.3398 0 2.6719-0.35156 3.8203-1.0312 1.1211-0.64844 2.0703-1.5781 2.7305-2.6992 0.17188-0.28125 0.46875-0.46875 0.80078-0.48828 4.6914-0.30078 8.3594-4.2188 8.3594-8.9219zm-40.039-3.1719c-0.85938 0.39063-1.5195 1.0898-1.8516 1.9688-0.32812 0.87891-0.30859 1.8398 0.078125 2.6992 0.23047 0.5 0 1.1016-0.5 1.3281-0.12891 0.058594-0.26953 0.089844-0.41016 0.089844-0.37891 0-0.75-0.21875-0.91016-0.58984-0.60938-1.3516-0.64844-2.8516-0.12891-4.2383 0.51953-1.3789 1.5586-2.4805 2.9102-3.0898 0.5-0.23047 1.1016 0 1.3281 0.5 0.23047 0.5 0 1.1016-0.5 1.3281z"></path> 1196 <path d="m22.551 80.719h11.262v3.3008h-11.262z"></path> 1197 <path d="m24.449 77.691-0.078125 1.0312h8.1484l0.85938-6.2109c0.32031-2.2695-0.19922-4.5508-1.4609-6.3984-0.03125-0.039062-0.058594-0.089843-0.089844-0.12891-1.5117-2.1289-4.3711-3.7812-4.3906-3.8008-0.12891-0.070313-0.23828-0.17188-0.32031-0.28906l-4.6602-6.6016c-0.66016-0.94141-1.9609-1.1602-2.8984-0.5-0.94141 0.66016-1.1602 1.9609-0.5 2.8984l4.6602 6.6016c0.32031 0.44922 0.21094 1.0781-0.23828 1.3984-0.44922 0.32031-1.0781 0.21094-1.3984-0.23828l-4.6602-6.6016c-1.2383-1.7617-0.89844-4.1719 0.75-5.5195l-1.6719-10.199c-0.26172-1.5586-1.6797-2.6406-3.25-2.4688-0.12109 0.011719-0.19922 0.12109-0.19141 0.23047l1.5703 19.301c0.078125 1.0117 0.42969 1.9688 1.0117 2.8008l7.8203 11.078c0.75 1.0586 1.1016 2.3516 1 3.6406z"></path> 1198 <path d="m66.191 80.719h11.262v3.3008h-11.262z"></path> 1199</svg> 1200</div> 1201</div> 1202 <div id="bde63803" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1829778255"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1829778255" style="" new-inline-bind-applied="true" data-diy-text=""><p class="text-align-center m-text-align-center" style="line-height: 1.5;"><span style="color: var(--color_16); display: initial;"><span class="inline-data-binding" data-encoded-value="V2UgSGF2ZSB0aGUgQmVzdCBUcmVlIENhcmUgU2VydmljZXM=" data-inline-binding="" data-inline-binding-encoded="U1RBVElDX1BBR0VfQ09MTEVDVElPTi57ImNuIjoiV2h5IENob29zZSIsImZuIjoiV2h5IENob29zZSA0In0=">We Have the Best Tree Care Services</span></span></p></div> 1203</div> 1204</div> 1205 <div id="8be0f7d6" class="flex-element group" data-auto="flex-element-group"> <div id="9a7d492b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="graphic" data-keep-proportion="true" data-external-id="1231832823"> <div class="graphicWidget graphicWidgetV2 graphicWidgetV3 u_1231832823" data-element-type="graphic" data-widget-type="graphic" id="1231832823" data-hover-effect="zoomout"> <svg width="100%" height="100%" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1191630688" class="svg u_1191630688" data-icon-custom="true" data-icon-name="family owned_8316614.svg"> <path d="m29.691 24.422c5.1797 0 9.3906-4.2109 9.3906-9.3906s-4.2109-9.3906-9.3906-9.3906c-5.1797 0-9.3906 4.2109-9.3906 9.3906s4.2109 9.3906 9.3906 9.3906z"></path> 1206 <path d="m19.461 36.441-1 17.32 0.76953 1.9688c0.070312 0.019531 0.12891 0.039062 0.19922 0.050781 0.17187-0.19922 0.35156-0.37891 0.55078-0.51953 1.4492-1.0586 3.5-0.67188 5.
12061094 0.94922 0.19141 0.19141 0.39844 0.39844 0.60938 0.60937 3.9219 0.35938 7.8398 0.19141 11.75-0.51172 2.0508-2.4219 4.75-4.3203 8.3086-5.1406-0.23047-2.0195-0.69922-4.7812-1.6484-7.5898-3.3203-1.7695-5.6484-5.1602-5.9414-9.1016-2.1719-1.6914-4.9219-2.7695-8.4609-2.7695-4.5898 0-7.8711 1.8203-10.238 4.4297 0 0.10938 0.011719 0.21094 0 0.32031z"></path> 1207 <path d="m69.648 24.281c5.1797 0 9.3906-4.2109 9.3906-9.3906s-4.2109-9.3906-9.3906-9.3906c-5.1797 0-9.3906 4.2109-9.3906 9.3906s4.2109 9.3906 9.3906 9.3906z"></path> 1208 <path d="m69.648 31.551c-3.8906 0-6.8516 1.3203-9.1016 3.3086-0.37891 3.4883-2.3594 6.4883-5.1914 8.2812-1.0391 2.9609-1.5312 5.8906-1.7695 7.9883 3.5703 0.78906 6.2812 2.6484 8.3398 5.0391 4.1992 0.75 8.4102 0.87891 12.621 0.41016l0.37109-0.37109c1.6094-1.6211 3.6602-2 5.1094-0.94922 0.10938 0.078126 0.21875 0.17188 0.32031 0.26953 0.19141-0.050782 0.37891-0.10156 0.55859-0.14844l0.64062-1.6289-0.98828-17c-2.3984-3.0195-5.8711-5.2109-10.898-5.2109z"></path> 1209 <path d="m49.359 43.891c5.6602 0 10.262-4.6016 10.262-10.262s-4.6016-10.262-10.262-10.262-10.262 4.6016-10.262 10.262 4.6016 10.262 10.262 10.262z"></path> 1210 <path d="m49.75 51.711c-9.2188 0-13.648 6.7305-15.781 13.148 0.83984 0.80859 1.5703 1.5 2.1094 2.0117 0.44922 0 0.89062-0.03125 1.2812-0.070313 3.0586-0.37891 7.6797 0.17969 10.578 3.0195 0.96094 0.92969 1.6406 2.0391 2.0586 3.3008 0.42188-1.2617 1.1094-2.3594 2.0586-3.3008 2.9102-2.8398 7.5195-3.3984 10.578-3.0195 0.39063 0.050781 0.82031 0.070313 1.2812 0.070313 0.44922-0.42969 1.0391-0.98828 1.7109-1.6406-2.0781-6.5312-6.5-13.531-15.891-13.531z"></path> 1211 <path d="m49.441 77.57c0.28906-2.9609-0.44922-5.3281-2.1992-7.0391-2.4805-2.4219-6.6914-3.1211-9.7617-2.7383-0.12891 0.019531-0.26953 0.019531-0.41016 0.03125 0.17969 0.19141 0.17969 0.48828 0 0.67969-0.19141 0.19922-0.51172 0.21094-0.71094 0.019532-0.078125-0.078126-8.1914-7.7695-11.988-11.609-1.25-1.2617-2.7812-1.6016-3.8086-0.83984-1.1914 0.87109-1.6211 3.2188 0.089844 6.5 3.2695 6.2891 6.1211 8.1992 6.1484 8.2188 0.23047 0.14844 0.30078 0.46094 0.14844 0.69141-0.10156 0.14844-0.26172 0.23047-0.42188 0.23047-0.089844 0-0.19141-0.03125-0.26953-0.078125-0.12109-0.078125-3.0781-2.0312-6.4883-8.5898-1.3086-2.5195-1.4609-4.4883-1.0508-5.8789l-1.2305-3.1289c-0.03125-0.070312-0.039062-0.14062-0.03125-0.21094l1.0117-17.43c0.058594-1.0586-0.60156-1.7305-1.2383-2.0117-0.64062-0.26953-1.5781-0.30078-2.3086 0.46875-0.78125 0.82812-1.3594 1.9297-1.7109 3.2812-2.1797 8.2695-3.1016 15.07-3.2109 15.852l2.6016 14.379s2.8711 8.2383 9 12.121c4.4805 2.8398 12.219 4.3398 12.301 4.3594 0.14062 0.03125 0.26172 0.10938 0.32812 0.21875 0.070312 0.12109 0.10156 0.26172 0.058593 0.39062l-2.3789 9.0391h14.539c0.42969-1.7109 2.2109-9.0703 2.9883-16.93z"></path> 1212 <path d="m87.422 68.289 2.5781-14.309c-0.10156-0.78125-1.0312-7.5781-3.2109-15.852-0.35937-1.3516-0.92969-2.4609-1.7109-3.2812-0.73047-0.76953-1.6719-0.75-2.3086-0.46875-0.64062 0.28125-1.3008 0.94922-1.2383 2.0117l1.0117 17.43c0 0.070313 0 0.14063-0.03125 0.21094l-1.2305 3.1289c0.41016 1.3906 0.26172 3.3594-1.0508 5.8789-3.4102 6.5586-6.3711 8.5117-6.4883 8.5898-0.078126 0.050782-0.17969 0.078125-0.26953 0.078125-0.16016 0-0.32031-0.078125-0.42188-0.23047-0.14844-0.23047-0.078125-0.53906 0.14844-0.69141 0.03125-0.019531 2.8789-1.9297 6.1484-8.2188 1.7109-3.2891 1.2812-5.6406 0.089844-6.5-1.0312-0.75-2.5586-0.41016-3.8086 0.83984-3.8008 3.8281-11.91 11.531-11.988 11.609-0.19922 0.19141-0.51953 0.17969-0.71094-0.019531-0.17969-0.19141-0.17969-0.48828 0-0.67969-0.14063-0.011718-0.28125-0.019531-0.41016-0.03125-3.0781-0.37891-7.2812 0.32031-9.7617 2.7383-1.75 1.7109-2.4883 4.0781-2.1992 7.0391 0.78125 7.8516 2.5586 15.211 2.9883 16.93h14.539l-2.3789-9.0391c-0.039062-0.12891-0.011719-0.28125 0.058594-0.39062 0.070313-0.12109 0.19141-0.19922 0.32812-0.21875 0.078125-0.011719 7.8203-1.5195 12.301-4.3594 6.1289-3.8789 8.9883-12.109 9.0195-12.191z"></path> 1213</svg> 1214</div> 1215</div> 1216 <div id="3dc47e81" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1518405849"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1518405849" style="" new-inline-bind-applied="true" data-diy-text=""><p class="text-align-center m-text-align-center" style="line-height: 1.5;"><span style="color: var(--color_16); display: initial;"><span class="inline-data-binding" data-encoded-value="QSBGYW1pbHktT3duZWQgQnVzaW5lc3M=" data-inline-binding="" data-inline-binding-encoded="U1RBVElDX1BBR0VfQ09MTEVDVElPTi57ImNuIjoiV2h5IENob29zZSIsImZuIjoiV2h5IENob29zZSA1In0=">A Family-Owned Business</span></span></p></div> 1217</div> 1218</div> 1219 <div id="cac62dd6" class="flex-element group" data-auto="flex-element-group"> <div id="eb7c8fdb" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="graphic" data-keep-proportion="true" data-external-id="1615097267"> <div class="graphicWidget graphicWidgetV2 graphicWidgetV3 u_1615097267" data-element-type="graphic" data-widget-type="graphic" id="1615097267" data-hover-effect="zoomout"> <svg width="100%" height="100%" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1048979781" class="svg u_1048979781" data-icon-custom="true" data-icon-name="founder_1986347.svg"> <g> <path d="m62.352 53.926c0 6.8242-5.5312 12.352-12.352 12.352s-12.352-5.5273-12.352-12.352c0-6.8203 5.5312-12.352 12.352-12.352s12.352 5.5312 12.352 12.352"></path> 1220 <path d="m45.91 72.938 4.0898 8.1719 4.0898-8.1719-4.0898-5.3516z"></path> 1221 <path d="m62.816 66.184h-3.7773l-4 7.9961-5.043 10.062-5.0352-10.062-4.0078-7.9961h-3.7695c-3.6758 0-6.6523 2.9727-6.6523 6.6484l3.6328 19.008c0.94141 4.9219 4.3906 6.6484 6.3789 6.6484h9.168 0.57812 9.168c1.9883 0 5.4375-1.7305 6.3789-6.6484l3.6328-19.008c0.003906-3.6758-2.9766-6.6484-6.6523-6.6484z"></path> 1222 <path d="m90.406 73.73h-6.0234v-32.152c0-1.2422-1.0117-2.25-2.2539-2.25h-7.4922l-0.003907-14.012c0-1.2422-1.0078-2.25-2.2539-2.25h-9.168v-11.402c0-0.96094-0.65234-2.1914-1.4531-2.7344l-10.316-7.0078c-0.79297-0.54297-2.1016-0.54297-2.8945 0l-10.309 7.0078c-0.79297 0.54297-1.4453 1.7734-1.4453 2.7344v11.402h-9.1719c-1.2422 0-2.2539 1.0078-2.2539 2.25v14.012l-7.5 0.003906c-1.2422 0-2.25 1.0078-2.25 2.25v32.152h-6.0312c-0.95703 0-1.7383 0.77734-1.7383 1.7461v11.266c0 0.96484 0.78125 1.7461 1.7383 1.7461h21.051l-2.75-14.371c-0.03125-0.12891-0.023438-0.25391-0.046875-0.38672l-0.003906 0.003906c-1.0234-5.375 3.0664-9.9375 7.8242-9.9375h2.9492c-2.2969-2.6562-3.7383-6.0781-3.7383-9.8672 0-8.3555 6.7773-15.125 15.133-15.125 8.3594 0 15.129 6.7656 15.129 15.125 0 3.7891-1.4375 7.2109-3.7383 9.8672h2.9531c4.75 0 8.8438 4.5625 7.8164 9.9375-0.023437 0.12891-0.011718 0.25391-0.046874 0.38672l-2.7461 14.371h21.039c0.96484 0 1.7461-0.77734 1.7461-1.7461v-11.266c-0.003906-0.97656-0.78516-1.7539-1.75-1.7539zm-65.738-8.0469c0 0.33594-0.27344 0.60938-0.60938 0.60938l-3.457-0.003907c-0.33594 0-0.60937-0.27344-0.60937-0.60937v-8.3867c0-0.33594 0.27344-0.60938 0.60937-0.60938h3.457c0.33594 0 0.60938 0.27344 0.60938 0.60938zm0-13.039c0 0.33594-0.27344 0.60938-0.60938 0.60938h-3.457c-0.33594 0-0.60937-0.27344-0.60937-0.60938v-8.3867c0-0.33594 0.27344-0.61328 0.60937-0.61328h3.457c0.33594 0 0.60938 0.27344 0.60938 0.61328zm7.0273 0c0 0.33594-0.27344 0.60938-0.60937 0.60938h-3.457c-0.33594 0-0.60938-0.27344-0.60938-0.60938v-8.3867c0-0.33594 0.27344-0.61328 0.60938-0.61328h3.457c0.33594 0 0.60937 0.27344 0.60937 0.61328zm2.3359-16.609c0 0.33594-0.27344 0.60938-0.60938 0.60938l-3.457-0.003906c-0.33594 0-0.60938-0.27344-0.60938-0.60938l0.003906-8.3867c0-0.33594 0.27344-0.60938 0.60938-0.60938h3.457c0.33594 0 0.60938 0.27344 0.60938 0.60938v8.3906zm7.0273 0c0 0.33594-0.27734 0.60938-0.61328 0.60938h-3.457c-0.33203 0-0.60938-0.27344-0.60938-0.60938l-0.003906-8.3906c0-0.33594 0.27734-0.60938 0.60938-0.60938h3.457c0.33594 0 0.61328 0.27344 0.61328 0.60938zm4.2539-15.516c0 0.33594-0.27344 0.61328-0.60938 0.61328h-3.457c-0.33594 0-0.60938-0.27344-0.60938-0.61328v-8.3867c0-0.33594 0.27344-0.60937 0.60938-0.60937h3.457c0.33594 0 0.60938 0.27344 0.60938 0.60937zm7.0234 0c0 0.33594-0.27734 0.61328-0.60938 0.61328h-3.4648c-0.33203 0-0.60938-0.27344-0.60938-0.61328l0.003906-8.3867c0-0.33594 0.27734-0.60937 0.60938-0.60937h3.4648c0.33203 0 0.60938 0.27344 0.60938 0.60937zm2.9531 0.61328
1222c-0.33203 0-0.60937-0.27344-0.60937-0.61328l0.003906-8.3867c0-0.33594 0.27734-0.60937 0.60938-0.60937h3.4648c0.33203 0 0.60938 0.27344 0.60938 0.60937v8.3867c0 0.33594-0.27734 0.61328-0.60938 0.61328zm8.3281 14.902c0 0.33594-0.27344 0.60938-0.60938 0.60938h-3.457c-0.33594 0-0.60938-0.27344-0.60938-0.60938v-8.3906c0-0.33594 0.27344-0.60938 0.60938-0.60938h3.457c0.33594 0 0.60938 0.27344 0.60938 0.60938zm2.3477 0v-8.3906c0-0.33594 0.27734-0.60938 0.60938-0.60938h3.4648c0.33203 0 0.60938 0.27344 0.60938 0.60938v8.3867c0 0.33594-0.27734 0.60938-0.60938 0.60938h-3.4648c-0.33594 0-0.60938-0.27344-0.60938-0.60547zm7.0156 16.609c0 0.33594-0.27734 0.60938-0.60938 0.60938h-3.4609c-0.33203 0-0.60938-0.27344-0.60938-0.60938v-8.3867c0-0.33594 0.27734-0.61328 0.60938-0.61328h3.4648c0.33203 0 0.60938 0.27344 0.60938 0.61328zm7.0195 13.039c0 0.33594-0.27344 0.60938-0.60938 0.60938h-3.457c-0.33594 0-0.60938-0.27344-0.60938-0.60938v-8.3867c0-0.33594 0.27344-0.60938 0.60938-0.60938h3.457c0.33594 0 0.60938 0.27344 0.60938 0.60938zm0-13.039c0 0.33594-0.27344 0.60938-0.60938 0.60938h-3.457c-0.33594 0-0.60938-0.27344-0.60938-0.60938v-8.3867c0-0.33594 0.27344-0.61328 0.60938-0.61328h3.457c0.33594 0 0.60938 0.27344 0.60938 0.61328z"></path> 1223</g> 1224</svg> 1225</div> 1226</div> 1227 <div id="4c13680b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1948610707"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1948610707" style="" new-inline-bind-applied="true" data-diy-text=""><p class="text-align-center m-text-align-center" style="line-height: 1.5;"><span style="color: var(--color_16); display: initial;"><span class="inline-data-binding" data-encoded-value="QnVzaW5lc3MgRXN0YWJsaXNoZWQgaW4gMjAxMg==" data-inline-binding="" data-inline-binding-encoded="U1RBVElDX1BBR0VfQ09MTEVDVElPTi57ImNuIjoiV2h5IENob29zZSIsImZuIjoiV2h5IENob29zZSA2In0=">Business Established in 2012</span></span></p></div> 1228</div> 1229</div> 1230</div> 1231</div> 1232</div> 1233</div> 1234</div> 1235</section> 1236</div> 1237 <div data-layout-section="" data-auto="flex-section" id="1437234140" data-flex-id="34d262ef" data-page-element-type="section" data-page-element-id="1997934803"> <div class="flex-widgets-container" id="1905427577"></div> 1238 <section id="7acd7a75" class="flex-element section" data-auto="flex-element-section"> <div id="d4019f16" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="1ac20e54" class="flex-element group" data-auto="flex-element-group"> <div id="bc7c6f5d" class="flex-element group" data-auto="flex-element-group"> <div id="8031eca6" class="flex-element group" data-auto="flex-element-group"> <div id="bbc5dc4e" class="flex-element widget-wrapper DCBH3" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1172821973"> <div class="dmNewParagraph u_1172821973" data-element-type="paragraph" data-version="5" id="1172821973" style="" data-inject="topicheading1" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCIwMSBIT01FXCIsXCJmblwiOlwiQ09QWSBCTE9DSyAxIEhFQURMSU5FXCJ9In1d" data-diy-text="">Tree Services</div> 1239</div> 1240 <div id="34e2b901" class="flex-element widget-wrapper DCBP" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1461815670"> <div class="dmNewParagraph u_1461815670" data-element-type="paragraph" data-version="5" id="1461815670" style="" data-inject="topiccontent1" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCIwMSBIT01FXCIsXCJmblwiOlwiQ09QWSBCTE9DSyAxIFRFWFRcIn0ifV0=" data-diy-text="">Our tree services cover everything from precision trimming and strategic pruning to complete removal when necessary. With decades of combined experience and ISA certification, our arborists assess each tree's unique needs and deliver customized solutions that promote healthy growth while protecting your property.</div> 1241</div> 1242</div> 1243 <div id="e29987ca" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1423094955"> <div class="widget-f19f9b u_1423094955 dmCustomWidget" data-lazy-load="true" data-title="" id="1423094955" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="f19f9b2806104edb81a7816f71967887" data-widget-version="13" data-widget-config="eyJidXR0b25OYW1lIjoiTEVBUk4gTU9SRSIsInNvdXJjZVBhZ2VUeXBlIjoiaG9tZSIsIm
1243NvcmVQcmVmaXgiOiJzZXJ2aWNlcyIsImNvcHlCbG9ja051bWJlciI6IjEiLCJidXR0b25Sb3V0aW5nT3B0aW9ucyI6bnVsbCwiY2F0ZWdvcnlQcmVmaXgiOiJ3aGF0LXdlLWRvIn0="> <div class="copy-block-link-widget"> <a class="copy-block-link-anchor" aria-label="LEARN MORE" aria-disabled="true" aria-busy="true"> <div class="dmWidget copy-block-link-button"> <span class="text">LEARN MORE</span> 1244 <span class="iconBg"></span> 1245</div> 1246</a> 1247</div> 1248</div> 1249</div> 1250</div> 1251 <div id="9817662a" class="flex-element group lazy" data-auto="flex-element-group" data-background-image=""> <div id="11364c40" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="image" data-external-id="1360296185"> <div class="imageWidget align-center u_1360296185" data-element-type="image" data-widget-type="image" id="1360296185"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/tree-services-hero-huffs-tree-service-cust-996w.png" alt="" id="1651412929" class="" width="1920" height="1080" data-dm-image-path="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/tree-services-hero-huffs-tree-service-cust.png" onerror="handleImageLoadError(this)" loading="lazy"/></div> 1252</div> 1253</div> 1254</div> 1255</div> 1256</section> 1257</div> 1258 <div data-layout-section="" data-auto="flex-section" id="1959065464" data-flex-id="cca82cf8" data-page-element-type="section" data-page-element-id="1997934803"> <div class="flex-widgets-container" id="1960175913"></div> 1259 <section id="8b93ccb2" class="flex-element section" data-auto="flex-element-section"> <div id="cfe045b0" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="40dfebdf" class="flex-element group" data-auto="flex-element-group"> <div id="0fd36ae1" class="flex-element group lazy" data-auto="flex-element-group" data-background-image=""> <div id="f3076520" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="image" data-external-id="1560881400"> <div class="imageWidget align-center u_1560881400" data-element-type="image" data-widget-type="image" id="1560881400"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/turf-and-arbor-care-hero-image-huffs-tree-service-1059w.png" alt="" id="1814010035" class="" width="1898" height="772" data-dm-image-path="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/turf-and-arbor-care-hero-image-huffs-tree-service.png" onerror="handleImageLoadError(this)" loading="lazy"/></div> 1260</div> 1261</div> 1262 <div id="fe222c1c" class="flex-element group" data-auto="flex-element-group"> <div id="6a488ed3" class="flex-element group" data-auto="flex-element-group"> <div id="2cfff530" class="flex-element widget-wrapper DCBH3" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1937554730"> <div class="dmNewParagraph u_1937554730" data-element-type="paragraph" data-version="5" id="1937554730" style="" data-inject="topicheading2" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCIwMSBIT01FXCIsXCJmblwiOlwiQ09QWSBCTE9DSyAyIEhFQURMSU5FXCJ9In1d" data-diy-text="">Turf and Arbor Care</div> 1263</div> 1264 <div id="1b714432" class="flex-element widget-wrapper DCBP" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1458715392"> <div class="dmNewParagraph u_1458715392" data-element-type="paragraph" data-version="5" id="1458715392" style="" data-inject="topiccontent2" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCIwMSBIT01FXCIsXCJmblwiOlwiQ09QWSBCTE9DSyAyIFRFWFRcIn0ifV0=" data-diy-text="">Healthy trees start with healthy soil and proper maintenance practices. Our turf and arbor care programs focus on creating the best growing conditions through targeted treatments, fertilization, and ongoing monitoring that keeps your landscape thriving year-round.</div> 1265</div> 1266</div> 1267 <div id="09044853" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1030952741"> <div class="widget-f19f9b u_1030952741 dmCustomWidget" data-lazy-load="true" data-title="" id="1030952741" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="f19f9b2806104edb81a7816f71967887" data-widget-version="13" data-widget-config="eyJidXR0b25OYW1lIjoiTEVBUk4gTU9SRSIsInNvdXJjZVBhZ2VUeXBlIjoiaG9tZSIsIm
1267NvcmVQcmVmaXgiOiJzZXJ2aWNlcyIsImNvcHlCbG9ja051bWJlciI6IjIiLCJidXR0b25Sb3V0aW5nT3B0aW9ucyI6bnVsbCwiY2F0ZWdvcnlQcmVmaXgiOiJ3aGF0LXdlLWRvIn0="> <div class="copy-block-link-widget"> <a class="copy-block-link-anchor" aria-label="LEARN MORE" aria-disabled="true" aria-busy="true"> <div class="dmWidget copy-block-link-button"> <span class="text">LEARN MORE</span> 1268 <span class="iconBg"></span> 1269</div> 1270</a> 1271</div> 1272</div> 1273</div> 1274</div> 1275</div> 1276</div> 1277</section> 1278</div> 1279 <div data-auto="flex-section" id="1801977510" data-flex-id="6b4e554f" data-layout-section="" data-page-element-type="section" data-page-element-id="1688378275" class="" data-hidden-on-desktop="true"> <div class="flex-widgets-container" id="1469249649"></div> 1280 <section id="8b50854f" class="flex-element section" data-auto="flex-element-section"> <div id="010de6f0" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="c740231e" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop="" data-hidden-on-tablet="" data-hidden-on-mobile=""> <div id="3a304ac7" class="flex-element group" data-auto="flex-element-group"> <div id="7d294100" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1783122354"> <div class="widget-4e2b21 u_1783122354 dmCustomWidget" data-lazy-load="true" data-title="" id="1783122354" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="4e2b21efc370451a8e2c573f02104b04" data-widget-version="22" data-widget-config="eyJvZmZlckRlc2MiOiJvZmZlcnMiLCJDVEF0b2dnbGUiOmZhbHNlfQ=="> <div class="hibu-asst-banner"> <p class="asst-banner-text">Text <o>START</o> 1281to <o></o> 1282to begin receiving offers by text.</p> 1283 <p class="asst-banner-subtext">Msgs may be autodialed. Consent to texts not required to purchase our svcs. Msg. and data rates may apply.</p> 1284 <a href="sms:?&body=START" class="asst-sms-button-desktop-hide"> <div class="dmWidget asst-sms-button"> <span class="text">Text Now!</span> 1285 <span class="iconBg"></span> 1286</div> 1287</a> 1288</div> 1289</div> 1290</div> 1291</div> 1292</div> 1293</div> 1294</section> 1295</div> 1296 <div data-layout-section="" data-auto="flex-section" id="1183392861" data-flex-id="b1d1d7b0" data-page-element-type="section" data-page-element-id="1688378275" class="" data-hidden-on-mobile="true"> <div class="flex-widgets-container" id="1184857346"></div> 1297 <section id="64a291aa" class="flex-element section" data-auto="flex-element-section"> <div id="0716e5d7" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="6e382563" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop="" data-hidden-on-tablet="" data-hidden-on-mobile=""> <div id="077a1c49" class="flex-element group" data-auto="flex-element-group"> <div id="069c84b9" class="flex-element group" data-auto="flex-element-group"> <div id="f90f9993" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1450002470"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1450002470" style=""> <h2 class="text-align-center"><span style="color: var(--color_16); display: unset;">Why Choose Us</span></h2> 1298</div> 1299</div> 1300</div> 1301 <div id="eb7ed250" class="flex-element group" data-auto="flex-element-group"> <div id="50eaa52b" class="flex-element group" data-auto="flex-element-group"> <div id="a19b1af3" class="flex-element group" data-auto="flex-element-group"> <div id="e997ae28" class="flex-element group" data-auto="flex-element-group"> <div id="0a8502bd" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="graphic" data-keep-proportion="true" data-external-id="1751702735"> <div class="graphicWidget graphicWidgetV2 graphicWidgetV3 u_1751702735" data-element-type="graphic" data-widget-type="graphic" id="1751702735"> <svg width="100%" height="100%" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1768914908" class="svg u_1768914908" data-icon-custom="true"> <title id="1484177299">Black award ribbon with a white checkmark inside a circle</title> 1302 <path d="m84.578 43.59c0-19.07-15.508-34.578-34.578-34.578-19.059 0-34.578 15.512-34.578 34.578 0 17.969 13.801 32.801 31.359 34.43 0.058594 0 0.10938 0 0.17188 0.011719 1 0.089844 2.0195 0.12891 3.0508 0.12891s2.0391-0.039062 3.0508-0.12891c0.058593-0.011719 0.10937-0.011719 0.17187-0.011719 17.543-1.6289 31.352-16.461 31.352-34.43zm-33.867 16.16c-1.0312 1.1406-2.5 1.7891-4.0312 1.7891-1.3594 0-2.6719-0.51172-3.6719-1.4297l-16.898-15.391c-2.2188-2.0195-2.3906-5.4805-0.37109-7.6992 2.0312-2.2188 5.4883-2.3906 7.7109-0.37109l12.879 11.73 19.273-21.109c2.0312-2.2188 5.4883-2.3789 7.7109-0.35156 1.0703 0.98047 1.6992 2.3203 1.7617 3.7695 0.070312 1.4609-0.44141 2.8594-1.4219 3.9297z"></path> 1303 <path d="m66.941 28.48-19.891 21.781c-0.32812 0.37109-0.89844 0.39844-1.2695 0.070312l-13.543-12.344c-0.69922-0.62109-1.5703-0.94141-2.4492-0.94141-0.98828 0-1.9688 0.39062-2.6992 1.1797-1.3516 1.4805-1.2383 3.7891 0.25 5.1406l16.898 15.391c0.67188 0.60938 1.5391 0.94922 2.4492 0.94922 1.0195 0 2-0.42188 2.6914-1.1797l22.93-25.129c0.66016-0.73047 0.98828-1.6484 0.94922-2.6211-0.039062-0.98047-0.46094-1.8711-1.1797-2.5312-1.4766-1.3477-3.7891-1.2461-5.1367 0.23438z"></path> 1304 <path d="m22.148 77.898-0.058594 0.14844-6.7383 17.93 13.23-4.89
130406c0.35156-0.12109 0.73047-0.039063 0.96875 0.21875l8.3516 8.6914 7.6289-20.289c-7.8516-0.96875-14.941-4.4492-20.441-9.6211z"></path> 1305 <path d="m20.91 76.059 2.7695-7.3594c-6.2305-6.5391-10.059-15.391-10.059-25.102 0-20.078 16.32-36.398 36.379-36.398s36.379 16.32 36.379 36.391c0 9.7188-3.8398 18.57-10.059 25.102l2.7695 7.3594c9.2383-8.2695 14.5-20.031 14.5-32.469 0-24.031-19.551-43.582-43.59-43.582-24.031 0-43.59 19.551-43.59 43.59 0 12.43 5.2812 24.191 14.5 32.469z"></path> 1306 <path d="m77.801 77.75-2.8906-7.6602c-5.5 5.1484-12.59 8.6484-20.441 9.6211l7.6406 20.289 8.3281-8.6914c0.26172-0.26953 0.64062-0.35156 0.96875-0.21875l13.23 4.8906-6.7812-18.039z"></path> 1307</svg> 1308</div> 1309</div> 1310</div> 1311 <div id="bba80199" class="flex-element group" data-auto="flex-element-group"> <div id="4ac657c2" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1629716378"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1629716378" style="" new-inline-bind-applied="true" data-diy-text=""><p class="m-text-align-left text-align-left t-text-align-left" style="line-height: 1.5;"><span style="color: var(--color_16); display: initial;"><span class="inline-data-binding" data-encoded-value="NSBDZXJ0aWZpZWQgQXJib3Jpc3RzIG9uIFN0YWZm" data-inline-binding="" data-inline-binding-encoded="U1RBVElDX1BBR0VfQ09MTEVDVElPTi57ImNuIjoiV2h5IENob29zZSIsImZuIjoiV2h5IENob29zZSAxIn0=">5 Certified Arborists on Staff</span></span></p></div> 1312</div> 1313</div> 1314</div> 1315 <div id="634b917c" class="flex-element group" data-auto="flex-element-group"> <div id="51c53a36" class="flex-element group" data-auto="flex-element-group"> <div id="dacd5ea6" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-keep-proportion="true" data-widget-type="graphic" data-external-id="1074972305"> <div class="graphicWidget graphicWidgetV2 graphicWidgetV3 u_1074972305" data-element-type="graphic" data-widget-type="graphic" id="10
131574972305"> <svg width="100%" height="100%" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1737914802" class="svg u_1737914802" data-icon-custom="true"> <title id="1721687563">Black hand holding a gear icon, representing support or maintenance</title> 1316 <path d="m60.562 7.8125c-0.76953 0-1.4258 0.55859-1.5469 1.3164l-1.3594 8.1172c-0.81641 0.32422-1.6094 0.69531-2.3789 1.1211l-7.1484-3.9805c-0.66797-0.37109-1.5078-0.20703-1.9844 0.39453l-5.8125 7.2852c-0.47656 0.59766-0.45312 1.4531 0.058594 2.0195l5.5156 6.125c-0.25 0.83594-0.44922 1.6875-0.58984 2.5469l-7.5898 3.125c-0.70703 0.28906-1.1016 1.0469-0.93359 1.7891l2.0742 9.0859c0.17187 0.74609 0.85156 1.2578 1.6133 1.2148l8.1914-0.48438c0.50781 0.71875 1.0625 1.4062 1.6602 2.0547l-2.293 7.875v-0.003907c-0.21484 0.73828 0.13672 1.5195 0.82813 1.8477l8.3945 4.0508c0.69141 0.33203 1.5234 0.12109 1.9609-0.50781l4.6797-6.6562c0.4375 0.035156 0.875 0.097656 1.3164 0.10547h0.046875c0.46094-0.007812 0.91406-0.066406 1.375-0.10547l4.6719 6.6328c0.4375 0.62109 1.2617 0.83203 1.9492 0.50391l8.4062-4.0469c0.6875-0.33203 1.0312-1.1133 0.81641-1.8438l-2.293-7.9023c0.59375-0.64844 1.1445-1.3359 1.6523-2.0547l8.1758 0.48438-0.003906 0.003906c0.76172 0.042969 1.4453-0.46875 1.6172-1.2109l2.0781-9.0859v-0.003906c0.17187-0.74609-0.22266-1.5117-0.93359-1.8008l-7.5664-3.1016c-0.14063-0.88281-0.35156-1.75-0.60938-2.6094l5.4648-6.0664-0.003906 0.003906c0.50781-0.57031 0.53516-1.4219 0.058594-2.0195l-5.8125-7.2891c-0.47656-0.59766-1.3164-0.76172-1.9844-0.39063l-7.1484 3.9805c-0.77734-0.4375-1.582-0.83203-2.4102-1.1641l-1.3359-8.0391h-0.003907c-0.12109-0.76172-0.77734-1.3164-1.5469-1.3164zm4.6836 17.184c6.0352 0 10.934 4.9102 10.934 10.945s-4.8984 10.945-10.934 10.945-10.934-4.9102-10.934-10.945 4.8984-10.945 10.934-10.945zm-57.441 39.066c-0.86328 0.003906-1.5586 0.70703-1.5547 1.5703v24.988c-0.003906 0.86328 0.69531 1.5664 1.5547 1.5703h14.07v-28.125zm17.184 0v28.125h7.8203c0.86328-0.003906 1.5586-0.70703 1.5547-1.5703v-24.988c0.003907-0.86328-0.69531-1.5664-1.5547-1.5703zm20.402 2.4023c-2.6484 0.03125-5.2773 0.57812-7.8984 1.207v20.27c1.1289 0.24219 2.2383 0.57812 3.3164 1.0117h0.011718c2.7617 1.1055 5.707 1.6719 8.6797 1.6719h6.7422c4.3164 0 8.6016-0.76953 12.652-2.2617l20.887-7.6914c2.3711-0.875 3.9531-3.1445 3.9531-5.6719 0-2.5703-2.332-4.582-4.8789-4.2188l-16.992 2.4219c-0.019531-0.28125 0.003907 0.14062 0.007813 0.24219 0 3.4336-2.8164 6.2539-6.25 6.2539l-14.059-0.007813c-0.86719 0.003906-1.5742-0.69922-1.5703-1.5703 0.003906-0.86328 0.70703-1.5586 1.5703-1.5547h9.9102c2.293 0 5.875-1.0352 6.6055-3.0898 0.18359-0.51953 0.33594-1.0508 0.44922-1.5469 0.19922-0.875 0.19531-2.5273-0.54297-2.9609-0.23438-0.13672-0.50781-0.21484-0.80469-0.21484l-8.3047-0.003906c-2.9688 0-5.9062-0.55859-8.6641-1.6602l-0.03125-0.011719c-1.6016-0.45703-3.1992-0.63281-4.7891-0.61719zm-15.711 2.2891c0.86328 0 1.5625 0.69922 1.5625 1.5625 0 0.86328-0.69922 1.5625-1.5625 1.5625-0.86328 0-1.5625-0.69922-1.5625-1.5625 0-0.86328 0.69922-1.5625 1.5625-1.5625z"></path> 1317</svg> 1318</div> 1319</div> 1320</div> 1321 <div id="a0600711" class="flex-element group" data-auto="flex-element-group"> <div id="52a3e795" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1021071781"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1021071781" style="" new-inline-bind-applied="true" data-diy-text=""><p class="text-align-left m-text-align-left" style="line-height: 1.5;"><span style="color: var(--color_16); display: initial;"><span class="inline-data-binding" data-encoded-value="TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=" data-inline-binding="STATIC_PAGE_COLLECTION.{"cn":"Why Choose","fn":"Why Choose 2"}" data-inline-binding-encoded="U1RBVElDX1BBR0VfQ09MTEVDVElPTi57ImNuIjoiV2h5IENob29zZSIsImZuIjoiV2h5IENob29zZSAyIn0=">Emergency Services Available</span></span></p></div> 1322</div> 1323</div> 1324</div> 1325</div> 1326 <div id="770edb16" class="flex-element group" data-auto="flex-element-group"> <div id="11b15313" class="flex-element group" data-auto="flex-element-group"> <div id="453841c5" class="flex-element group" data-auto="flex-element-group"> <div id="7a97158a" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="graphic" data-keep-proportion="true" data-external-id="1534046080"> <div class="graphicWidget graphicWidgetV2 graphicWidgetV3 u_1534046080" data-element-type="graphic" data-widget-type="graphic" id="1534046080"> <svg width="100%" height="100%" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1890372599" class="svg u_1890372599" data-icon-custom="true"> <title id="1041067308">Black user icon with three stars above it</title> 1327 <path d="m20.703 93.75c0-5.2852 2.1016-10.352 5.832-14.086 3.7383-3.7344 8.8047-5.8359 14.086-5.8359h18.758c5.2812 0 10.348 2.0977 14.086 5.8359 3.7344 3.7305 5.832 8.8008 5.832 14.086 0 0.64844-0.52344 1.1758-1.1719 1.1758l-56.25-0.003906c-0.64453 0-1.1719-0.52734-1.1719-1.1758zm29.297-54.293c8.8398 0 16.016 7.1758 16.016 16.016s-7.1758 16.016-16.016 16.016c-8.8438 0-16.016-7.1758-16.016-16.016s7.1758-16.016 16.016-16.016zm1.043-33.703 3.1172 6.6367 6.9531 1.0586c0.4375 0.0625 0.79688 0.36719 0.9375 0.78516 0.13672 0.41406 0.03125 0.87891-0.27734 1.1914l-5.0625 5.1836 1.2031 7.3281c0.070313
13270.44141-0.11719 0.88672-0.48437 1.1445-0.36328 0.25781-0.84766 0.28906-1.2422 0.070313l-6.2031-3.4258-6.1992 3.4258c-0.39453 0.21484-0.87891 0.1875-1.2422-0.070313-0.36719-0.25781-0.55469-0.70312-0.48438-1.1445l1.1992-7.3281-5.0625-5.1836c-0.30859-0.3125-0.41016-0.77734-0.27344-1.1914 0.14062-0.41406 0.5-0.72266 0.9375-0.78516l6.9492-1.0586 3.1172-6.6367c0.19531-0.41016 0.60547-0.67578 1.0625-0.67578s0.86719 0.26172 1.0625 0.67578zm28.125 12.504 3.1211 6.6328 6.9531 1.0586c0.43359 0.066406 0.79297 0.36719 0.93359 0.78906 0.14062 0.41406 0.035157 0.875-0.27344 1.1875l-5.0625 5.1836 1.1953 7.3281c0.070313 0.44531-0.11328 0.89062-0.48047 1.1484-0.36719 0.25781-0.84766 0.28516-1.2422 0.066406l-6.2031-3.4219-6.2031 3.4219c-0.39062 0.21484-0.875 0.19141-1.2422-0.066406-0.36719-0.25781-0.55078-0.70313-0.48047-1.1484l1.1953-7.3281-5.0625-5.1836c-0.30469-0.3125-0.41406-0.77344-0.27344-1.1875 0.14062-0.41797 0.5-0.72266 0.93359-0.78906l6.9531-1.0586 3.1172-6.6328c0.19531-0.41016 0.60938-0.67578 1.0625-0.67578s0.86719 0.26172 1.0625 0.67578zm-56.215 0 3.1211 6.6328 6.9531 1.0586c0.43359 0.066406 0.79297 0.36719 0.93359 0.78906 0.14062 0.41406 0.035156 0.875-0.26953 1.1875l-5.0625 5.1836 1.1953 7.3281c0.070312 0.44531-0.11328 0.89062-0.48047 1.1484-0.36719 0.25781-0.84766 0.28516-1.2422 0.066406l-6.2031-3.4219-6.2031 3.4219c-0.39062 0.21484-0.875 0.19141-1.2422-0.066406-0.36719-0.25781-0.55078-0.70313-0.48047-1.1484l1.1953-7.3281-5.0625-5.1836c-0.30469-0.3125-0.41406-0.77344-0.27344-1.1875 0.14062-0.41797 0.5-0.72266 0.93359-0.78906l6.957-1.0586 3.1172-6.6328c0.19531-0.41016 0.60547-0.67578 1.0586-0.67578 0.45312 0 0.87109 0.26172 1.0625 0.67578z" fill-rule="evenodd"></path> 1328</svg> 1329</div> 1330</div> 1331</div> 1332 <div id="3624ae24" class="flex-element group" data-auto="flex-element-group"> <div id="72710297" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1843573073"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1843573073" style="" new-inline-bind-applied="true" data-diy-text=""><p class="text-align-left m-text-align-left" style="line-height: 1.5;"><span style="color: var(--color_16); display: initial;"><span class="inline-data-binding" data-encoded-value="TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=" data-inline-binding="STATIC_PAGE_COLLECTION.{"cn":"Why Choose","fn":"Why Choose 3"}" data-inline-binding-encoded="U1RBVElDX1BBR0VfQ09MTEVDVElPTi57ImNuIjoiV2h5IENob29zZSIsImZuIjoiV2h5IENob29zZSAzIn0=">Over 21 Years of Experience</span></span></p></div> 1333</div> 1334</div> 1335</div> 1336 <div id="586fa04f" class="flex-element group" data-auto="flex-element-group"> <div id="bb3c20db" class="flex-element group" data-auto="flex-element-group"> <div id="3f00c98a" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-keep-proportion="true" data-widget-type="graphic" data-external-id="1459686468"> <div class="graphicWidget graphicWidgetV2 graphicWidgetV3 u_1459686468" data-element-type="graphic" data-widget-type="graphic" id="1459686468" data-alt="Hands holding a tree silhouette icon"> <svg width="100%" height="100%" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1063383861" class="svg u_1063383861" data-icon-custom="true"> <title id="1370416170">Hands holding a tree silhouette icon</title> 1337 <path d="m51.609 56.422c-0.92188-0.82031-2.3008-0.82031-3.2109 0-0.46875 0.42188-0.98047 0.78906-1.5195 1.1016l-1.3906 26.5h9.0312l-1.3906-26.5c-0.53906-0.32031-1.0391-0.67969-1.5195-1.1016z"></path> 1338 <path d="m86.77 40.648c-1.5703-0.17188-3 0.92187-3.25 2.4688l-1.6719 10.199c1.6406 1.3398 1.9883 3.7617 0.75 5.5195l-4.6602 6.6016c-0.32031 0.44922-0.94922 0.55859-1.3984 0.23828-0.44922-0.32031-0.55859-0.94922-0.23828-1.3984l4.6602-6.6016c0.66016-0.94141 0.44141-2.2383-0.5-2.8984-0.94141-0.66016-2.2383-0.44141-2.8984 0.5l-4.6602 6.6016c-0.078125 0.12109-0.19141 0.21875-0.32031 0.28906-0.03125 0.019531-2.8906 1.6719-4.3906 3.8008-0.03125 0.039062-0.058594 0.089844-0.089844 0.12891-1.2617 1.8516-1.7812 4.1211-1.4609 6.3984l0.85938 6.2109h8.1484l-0.078126-1.0312c-0.10156-1.2891 0.25-2.5781 1-3.6406l7.8203-11.078c0.57812-0.82031 0.92969-1.7891 1.0117-2.8008l1.5703-19.301c0-0.12109-0.078125-0.21875-0.19141-0.23047z"></path> 1339 <path d="m73.719 43.711c0-1.9297-0.60938-3.7695-1.75-5.3203-1.1211-1.5195-2.6602-2.6211-4.4492-3.1992-0.32812-0.10938-0.57812-0.37891-0.67188-0.71094-0.078125-0.33984 0.011719-0.69141 0.26172-0.94141 1.2812-1.3086 1.9805-3.0312 1.9883-4.8594 0-1.8711-0.71875-3.6289-2.0391-4.9688-1.3281-1.3281-3.0898-2.0703-4.9609-2.0703-1.2891 0-2.5586 0.35938-3.6484 1.0312-0.28906 0.17969-0.64062 0.19922-0.94922 0.050781-0.30859-0.14062-0.51953-0.42969-0.57031-0.76953-0.23828-1.6484-1.0586-3.1719-2.3203-4.2695-1.2695-1.1094-2.9102-1.7305-4.6016-1.7305-1.6914 0-3.3281 0.60938-4.6016 1.7305-1.2617 1.1016-2.0898 2.6211-2.3203 4.2695-0.050782 0.32812-0.26172 0.62109-0.57031 0.76953-0.30859 0.14062-0.66016 0.12109-0.94922-0.050781-1.1016-0.67188-2.3594-1.0312-3.6484-1.0312-1.8711 0-3.6289 0.73047-4.9609 2.0703-1.3281 1.3281-2.0508 3.1016-2.0391 4.9688 0 1.8281 0.71875 3.5508 1.9883 4.8594 0.23828 0.25 0.33984 0.60156 0.26172 0.94141-0.078125 0.33984-0.33984 0.60938-0.67188 0.71094-1.7891 0.57812-3.3281 1.6797-4.4492 3.1992-1.1484 1.5508-1.75 3.3789-1.75 5.3203 0 4.6992 3.6719 8.6211 8.3594 8.9219 0.32812 0.019532 0.62891 0.19922 0.80078 0.48828 0.67188 1.1094 1.6094 2.0508 2.7305 2.6992 1.1602 0.67188 2.4805 1.0312 3.8203 1.0312 1.8711 0 3.6719-0.67969 5.0703-1.9297 0.83984-0.75 1.8906-1.1211 2.9414-1.1211s2.1016 0.37109 2.9414 1.1211c1.3984 1.2383 3.1992 1.9297 5.0703 1.9297 1.3398 0 2.6719-0.35156 3.8203-1.0312 1.1211-0.64844 2.0703-1.5781 2.7305-2.6992 0.17188-0.28125 0.46875-0.46875 0.80078-0.48828 4.6914-0.30078 8.3594-4.2188 8.3594-8.9219zm-40.039-3.1719c-0.85938 0.39063-1.5195 1.0898-1.8516 1.9688-0.32812 0.87891-0.30859 1.8398 0.078125 2.6992 0.23047 0.5 0 1.1016-0.5 1.3281-0.12891 0.058594-0.26953 0.089844-0.41016 0.089844-0.37891 0-0.75-0.21875-0.91016-0.58984-0.60938-1.3516-0.64844-2.8516-0.12891-4.2383 0.51953-1.3789 1.5586-2.4805 2.9102-3.0898 0.5-0.23047 1.1016 0 1.3281 0.5 0.23047 0.5 0 1.1016-0.5 1.3281z"></path> 1340 <path d="m22.551 80.719h11.262v3.3008h-11.262z"></path> 1341 <path d="m24.449 77.691-0.078125 1.0312h8.1484l0.85938-6.2109c0.32031-2.2695-0.19922-4.5508-1.4609-6.3984-0.03125-0.039062-0.058594-0.089843-0.089844-0.12891-1.5117-2.1289-4.3711-3.7812-4.3906-3.8008-0.12891-0.070313-0.23828-0.17188-0.32031-0.28906l-4.6602-6.6016c-0.66016-0.94141-1.9609-1.1602-2.8984-0.5-0.94141 0.66016-1.1602 1.9609-0.5 2.8984l4.6602 6.6016c0.32031 0.44922 0.21094 1.0781-0.23828 1.3984-0.44922 0.32031-1.0781 0.21094
1341-1.3984-0.23828l-4.6602-6.6016c-1.2383-1.7617-0.89844-4.1719 0.75-5.5195l-1.6719-10.199c-0.26172-1.5586-1.6797-2.6406-3.25-2.4688-0.12109 0.011719-0.19922 0.12109-0.19141 0.23047l1.5703 19.301c0.078125 1.0117 0.42969 1.9688 1.0117 2.8008l7.8203 11.078c0.75 1.0586 1.1016 2.3516 1 3.6406z"></path> 1342 <path d="m66.191 80.719h11.262v3.3008h-11.262z"></path> 1343</svg> 1344</div> 1345</div> 1346</div> 1347 <div id="95b687ee" class="flex-element group" data-auto="flex-element-group"> <div id="bfcf289f" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1490855689"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1490855689" style="" new-inline-bind-applied="true" data-diy-text=""><p class="text-align-left m-text-align-left" style="line-height: 1.5;"><span style="color: var(--color_16); display: initial;"><span class="inline-data-binding" data-encoded-value="TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ=" data-inline-binding="STATIC_PAGE_COLLECTION.{"cn":"Why Choose","fn":"Why Choose 4"}" data-inline-binding-encoded="U1RBVElDX1BBR0VfQ09MTEVDVElPTi57ImNuIjoiV2h5IENob29zZSIsImZuIjoiV2h5IENob29zZSA0In0=">We Have the Best Tree Care Services</span></span></p></div> 1348</div> 1349</div> 1350</div> 1351</div> 1352 <div id="408cb3a4" class="flex-element group" data-auto="flex-element-group"> <div id="846101b8" class="flex-element group" data-auto="flex-element-group"> <div id="f2bd066a" class="flex-element group" data-auto="flex-element-group"> <div id="9044eabf" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="graphic" data-keep-proportion="true" data-external-id="1690037632"> <div class="graphicWidget graphicWidgetV2 graphicWidgetV3 u_1690037632" data-element-type="graphic" data-widget-type="graphic" id="1690037632" data-alt="Black silhouettes of three people held in cupped hands, symbolizing care and support"> <svg width="100%" height="100%" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1500814182" class="svg u_1500814182" data-icon-custom="true"> <title id="1762699456">Black silhouettes of three people held in cupped hands, symbolizing care and support</title> 1353 <path d="m29.691 24.422c5.1797 0 9.3906-4.2109 9.3906-9.3906s-4.2109-9.3906-9.3906-9.3906c-5.1797 0-9.3906 4.2109-9.3906 9.3906s4.2109 9.3906 9.3906 9.3906z"></path> 1354 <path d="m19.461 36.441-1 17.32 0.76953 1.9688c0.070312 0.019531 0.12891 0.039062 0.19922 0.050781 0.17187-0.19922 0.35156-0.37891 0.55078-0.51953 1.4492-1.0586 3.5-0.67188 5.1094 0.94922 0.19141 0.19141 0.39844 0.39844 0.60938 0.60937 3.9219 0.35938 7.8398 0.19141 11.75-0.51172 2.0508-2.4219 4.75-4.3203 8.3086-5.1406-0.23047-2.0195-0.69922-4.7812-1.6484-7.5898-3.3203-1.7695-5.6484-5.1602-5.9414-9.1016-2.1719-1.6914-4.9219-2.7695-8.4609-2.7695-4.5898 0-7.8711 1.8203-10.238 4.4297 0 0.10938 0.011719 0.21094 0 0.32031z"></path> 1355 <path d="m69.648 24.281c5.1797 0 9.3906-4.2109 9.3906-9.3906s-4.2109-9.3906-9.3906-9.3906c-5.1797 0-9.3906 4.2109-9.3906 9.3906s4.2109 9.3906 9.3906 9.3906z"></path> 1356 <path d="m69.648 31.551c-3.8906 0-6.8516 1.3203-9.1016 3.3086-0.37891 3.4883-2.3594 6.4883-5.1914 8.2812-1.0391 2.9609-1.5312 5.8906-1.7695 7.9883 3.5703 0.78906 6.2812 2.6484 8.3398 5.0391 4.1992 0.75 8.4102 0.87891 12.621 0.41016l0.37109-0.37109c1.6094-1.6211 3.6602-2 5.1094-0.94922 0.10938 0.078126 0.21875 0.17188 0.32031 0.26953 0.19141-0.050782 0.37891-0.10156 0.55859-0.14844l0.64062-1.6289-0.98828-17c-2.3984-3.0195-5.8711-5.2109-10.898-5.2109z"></path> 1357 <path d="m49.359 43.891c5.6602 0 10.262-4.6016 10.262-10.262s-4.6016-10.262-10.262-10.262-10.262 4.6016-10.262 10.262 4.6016 10.262 10.262 10.262z"></path> 1358 <path d="m49.75 51.711c-9.2188 0-13.648 6.7305-15.781 13.148 0.83984 0.80859 1.5703 1.5 2.1094 2.0117 0.44922 0 0.89062-0.03125 1.2812-0.070313 3.0586-0.37891 7.6797 0.17969 10.578 3.0195 0.96094 0.92969 1.6406 2.0391 2.0586 3.3008 0.42188-1.2617 1.1094-2.3594 2.0586-3.3008 2.9102-2.8398 7.5195-3.3984 10.578-3.0195 0.39063 0.050781 0.82031 0.070313 1.2812 0.070313 0.44922-0.42969 1.0391-0.98828 1.7109-1.6406-2.0781-6.5312-6.5-13.531-15.891-13.531z"></path> 1359 <path d="m49.441 77.57c0.28906-2.9609-0.44922-5.3281-2.1992-7.0391-2.4805-2.4219-6.6914-3.1211-9.7617-2.7383-0.12891 0.019531-0.26953 0.019531-0.41016 0.03125 0.17969 0.19141 0.17969 0.48828 0 0.67969-0.19141 0.19922-0.51172 0.21094-0.71094 0.019532-0.078125-0.078126-8.1914-7.7695-11.988-11.609-1.25-1.2617-2.7812-1.6016-3.8086-0.83984-1.1914 0.87109-1.6211 3.2188 0.089844 6.5 3.2695 6.2891 6.1211 8.1992 6.1484 8.2188 0.23047 0.14844 0.30078 0.46094 0.14844 0.69141-0.10156 0.14844-0.26172 0.23047-0.42188 0.23047-0.089844 0-0.19141-0.03125-0.26953-0.078125-0.12109-0.078125-3.0781-2.0312-6.4883-8.5898-1.3086-2.5195-1.4609-4.4883-1.0508-5.8789l-1.2305-3.1289c-0.03125-0.070312-0.039062-0.14062-0.03125-0.21094l1.0117-17.43c0.058594-1.0586-0.60156-1.7305-1.2383-2.0117-0.64062-0.26953-1.5781-0.30078-2.3086 0.46875-0.78125 0.82812-1.3594 1.9297-1.7109 3.2812-2.1797 8.2695-3.1016 15.07-3.2109 15.852l2.6016 14.379s2.8711 8.2383 9 12.121c4.4805 2.8398 12.219 4.3398 12.301 4.3594 0.14062 0.03125 0.26172 0.10938 0.32812 0.21875 0.070312 0.12109 0.10156 0.26172 0.058593 0.39062l-2.3789 9.0391h14.539c0.42969-1.7109 2.2109-9.0703 2.9883-16.93z"></path> 1360 <path d="m87.422 68.289 2.5781-14.309c-0.10156-0.78125-1.0312-7.5781-3.2109-15.852-0.35937-1.3516-0.92969-2.4609-1.7109-3.2812-0.73047-0.76953-1.6719-0.75-2.3086-0.46875-0.64062 0.28125-1.3008 0.94922-1.2383 2.0117l1.0117 17.43c0 0.070313
13600 0.14063-0.03125 0.21094l-1.2305 3.1289c0.41016 1.3906 0.26172 3.3594-1.0508 5.8789-3.4102 6.5586-6.3711 8.5117-6.4883 8.5898-0.078126 0.050782-0.17969 0.078125-0.26953 0.078125-0.16016 0-0.32031-0.078125-0.42188-0.23047-0.14844-0.23047-0.078125-0.53906 0.14844-0.69141 0.03125-0.019531 2.8789-1.9297 6.1484-8.2188 1.7109-3.2891 1.2812-5.6406 0.089844-6.5-1.0312-0.75-2.5586-0.41016-3.8086 0.83984-3.8008 3.8281-11.91 11.531-11.988 11.609-0.19922 0.19141-0.51953 0.17969-0.71094-0.019531-0.17969-0.19141-0.17969-0.48828 0-0.67969-0.14063-0.011718-0.28125-0.019531-0.41016-0.03125-3.0781-0.37891-7.2812 0.32031-9.7617 2.7383-1.75 1.7109-2.4883 4.0781-2.1992 7.0391 0.78125 7.8516 2.5586 15.211 2.9883 16.93h14.539l-2.3789-9.0391c-0.039062-0.12891-0.011719-0.28125 0.058594-0.39062 0.070313-0.12109 0.19141-0.19922 0.32812-0.21875 0.078125-0.011719 7.8203-1.5195 12.301-4.3594 6.1289-3.8789 8.9883-12.109 9.0195-12.191z"></path> 1361</svg> 1362</div> 1363</div> 1364</div> 1365 <div id="41895274" class="flex-element group" data-auto="flex-element-group"> <div id="695cf79f" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1072351865"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1072351865" style="" new-inline-bind-applied="true" data-diy-text=""><p class="text-align-left m-text-align-left" style="line-height: 1.5;"><span style="color: var(--color_16); display: initial;"><span class="inline-data-binding" data-encoded-value="TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=" data-inline-binding="STATIC_PAGE_COLLECTION.{"cn":"Why Choose","fn":"Why Choose 5"}" data-inline-binding-encoded="U1RBVElDX1BBR0VfQ09MTEVDVElPTi57ImNuIjoiV2h5IENob29zZSIsImZuIjoiV2h5IENob29zZSA1In0=">A Family-Owned Business</span></span></p></div> 1366</div> 1367</div> 1368</div> 1369 <div id="4d2c275d" class="flex-element group" data-auto="flex-element-group"> <div id="739a2bb2" class="flex-element group" data-auto="flex-element-group"> <div id="9088eade" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-keep-proportion="true" data-widget-type="graphic" data-external-id="1994781342"> <div class="graphicWidget graphicWidgetV2 graphicWidgetV3 u_1994781342" data-element-type="graphic" data-widget-type="graphic" id="1994781342" data-alt="Black silhouette of a person in front of a building, with a tie-like shape and circular head icon."> <svg width="100%" height="100%" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1349047223" class="svg u_1349047223" data-icon-custom="true"> <title id="1141753182">Black silhouette of a person in front of a building, with a tie-like shape and circular head icon.</title> 1370 <g> <path d="m62.352 53.926c0 6.8242-5.5312 12.352-12.352 12.352s-12.352-5.5273-12.352-12.352c0-6.8203 5.5312-12.352 12.352-12.352s12.352 5.5312 12.352 12.352"></path> 1371 <path d="m45.91 72.938 4.0898 8.1719 4.0898-8.1719-4.0898-5.3516z"></path> 1372 <path d="m62.816 66.184h-3.7773l-4 7.9961-5.043 10.062-5.0352-10.062-4.0078-7.9961h-3.7695c-3.6758 0-6.6523 2.9727-6.6523 6.6484l3.6328 19.008c0.94141 4.9219 4.3906 6.6484 6.3789 6.6484h9.168 0.57812 9.168c1.9883 0 5.4375-1.7305 6.3789-6.6484l3.6328-19.008c0.003906-3.6758-2.9766-6.6484-6.6523-6.6484z"></path> 1373 <path d="m90.406 73.73h-6.0234v-32.152c0-1.2422-1.0117-2.25-2.2539-2.25h-7.4922l-0.003907-14.012c0-1.2422-1.0078-2.25-2.2539-2.25h-9.168v-11.402c0-0.96094-0.65234-2.1914-1.4531-2.7344l-10.316-7.0078c-0.79297-0.54297-2.1016-0.54297-2.8945 0l-10.309 7.0078c-0.79297 0.54297-1.4453 1.7734-1.4453 2.7344v11.402h-9.1719c-1.2422 0-2.2539 1.0078-2.2539 2.25v14.012l-7.5 0.003906c-1.2422 0-2.25 1.0078-2.25 2.25v32.152h-6.0312c-0.95703 0-1.7383 0.77734-1.7383 1.7461v11.266c0 0.96484 0.78125 1.7461 1.7383 1.7461h21.051l-2.75-14.371c-0.03125-0.12891-0.023438-0.25391-0.046875-0.38672l-0.003906 0.003906c-1.0234-5.375 3.0664-9.9375 7.8242-9.9375h2.9492c-2.2969-2.6562-3.7383-6.0781-3.7383-9.8672 0-8.3555 6.7773-15.125 15.133-15.125 8.3594 0 15.129 6.7656 15.129 15.125 0 3.7891-1.4375 7.2109-3.7383 9.8672h2.9531c4.75 0 8.8438 4.5625 7.8164 9.9375-0.023437 0.12891-0.011718 0.25391-0.046874 0.38672l-2.7461 14.371h21.039c0.96484 0 1.7461-0.77734 1.7461-1.7461v-11.266c-0.003906-0.97656-0.78516-1.7539-1.75-1.7539zm-65.738-8.0469c0 0.33594-0.27344 0.60938-0.60938 0.60938l-3.457-0.003907c-0.33594 0-0.60937-0.27344-0.60937-0.60937v-8.3867c0-0.33594 0.27344-0.60938 0.60937-0.60938h3.457c0.33594 0 0.60938 0.27344 0.60938 0.60938zm0-13.039c0 0.33594-0.27344 0.60938-0.60938 0.60938h-3.457c-0.33594 0-0.60937-0.27344-0.60937-0.60938v-8.3867c0-0.33594 0.27344-0.61328 0.60937-0.61328h3.457c0.33594 0 0.60938 0.27344 0.60938 0.61328zm7.0273 0c0 0.33594-0.27344 0.60938-0.60937 0.60938h-3.457c-0.33594 0-0.60938-0.27344-0.60938-0.60938v-8.3867c0-0.33594 0.27344-0.61328 0.60938-0.61328h3.457c0.33594 0 0.60937 0.27344 0.60937 0.61328zm2.3359-16.609c0 0.33594-0.27344 0.60938-0.60938 0.60938l-3.457-0.003906c-0.33594 0-0.60938-0.27344-0.60938-0.60938l0.003906-8.3867c0-0.33594 0.27344-0.60938 0.60938-0.60938h3.457c0.33594 0 0.60938 0.27344 0.60938 0.60938v8.3906zm7.0273 0c0 0.33594-0.27734 0.60938-0.61328 0.60938h-3.457c-0.33203 0-0.60938-0.27344-0.60938-0.60938l-0.003906-8.3906c0-0.33594 0.27734-0.60938 0.60938-0.60938h3.457c0.33594 0 0.61328 0.27344 0.61328 0.60938zm4.2539-15.516c0 0.33594-0.27344 0.61328-0.60938 0.61328h-3.457c-0.33594 0-0.60938-0.27344-0.60938-0.61328v-8.3867c0-0.33594 0.27344-0.60937 0.60938-0.60937h3.457c0.33594 0 0.60938 0.27344 0.60938 0.60937zm7.0234 0c0 0.33594-0.27734 0.61328-0.60938 0.61328h-3.4648c-0.33203 0-0.60938-0.27344-0.60938-0.61328l0.003906-8.3867c0-0.33594 0.27734-0.60937 0.60938-0.60937h3.4648c0.33203 0 0.60938 0.27344 0.60938 0.60937zm2.9531 0.61328
1373c-0.33203 0-0.60937-0.27344-0.60937-0.61328l0.003906-8.3867c0-0.33594 0.27734-0.60937 0.60938-0.60937h3.4648c0.33203 0 0.60938 0.27344 0.60938 0.60937v8.3867c0 0.33594-0.27734 0.61328-0.60938 0.61328zm8.3281 14.902c0 0.33594-0.27344 0.60938-0.60938 0.60938h-3.457c-0.33594 0-0.60938-0.27344-0.60938-0.60938v-8.3906c0-0.33594 0.27344-0.60938 0.60938-0.60938h3.457c0.33594 0 0.60938 0.27344 0.60938 0.60938zm2.3477 0v-8.3906c0-0.33594 0.27734-0.60938 0.60938-0.60938h3.4648c0.33203 0 0.60938 0.27344 0.60938 0.60938v8.3867c0 0.33594-0.27734 0.60938-0.60938 0.60938h-3.4648c-0.33594 0-0.60938-0.27344-0.60938-0.60547zm7.0156 16.609c0 0.33594-0.27734 0.60938-0.60938 0.60938h-3.4609c-0.33203 0-0.60938-0.27344-0.60938-0.60938v-8.3867c0-0.33594 0.27734-0.61328 0.60938-0.61328h3.4648c0.33203 0 0.60938 0.27344 0.60938 0.61328zm7.0195 13.039c0 0.33594-0.27344 0.60938-0.60938 0.60938h-3.457c-0.33594 0-0.60938-0.27344-0.60938-0.60938v-8.3867c0-0.33594 0.27344-0.60938 0.60938-0.60938h3.457c0.33594 0 0.60938 0.27344 0.60938 0.60938zm0-13.039c0 0.33594-0.27344 0.60938-0.60938 0.60938h-3.457c-0.33594 0-0.60938-0.27344-0.60938-0.60938v-8.3867c0-0.33594 0.27344-0.61328 0.60938-0.61328h3.457c0.33594 0 0.60938 0.27344 0.60938 0.61328z"></path> 1374</g> 1375</svg> 1376</div> 1377</div> 1378</div> 1379 <div id="fe06e649" class="flex-element group" data-auto="flex-element-group"> <div id="13b740b5" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1707546761"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1707546761" style="" new-inline-bind-applied="true" data-diy-text=""><p class="text-align-left m-text-align-left" style="line-height: 1.5;"><span style="color: var(--color_16); display: initial;"><span class="inline-data-binding" data-encoded-value="TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4=" data-inline-binding="STATIC_PAGE_COLLECTION.{"cn":"Why Choose","fn":"Why Choose 6"}" data-inline-binding-encoded="U1RBVElDX1BBR0VfQ09MTEVDVElPTi57ImNuIjoiV2h5IENob29zZSIsImZuIjoiV2h5IENob29zZSA2In0=">Business Established in 2012</span></span></p></div> 1380</div> 1381</div> 1382</div> 1383</div> 1384</div> 1385</div> 1386</div> 1387</div> 1388</section> 1389</div> 1390 <div data-auto="flex-section" id="1907830557" data-flex-id="641ec38d" data-layout-section="" data-page-element-type="section" data-page-element-id="1688378275" class="" data-hidden-on-mobile="true"> <div class="flex-widgets-container" id="1797750564"></div> 1391 <section id="3d9f521b" class="flex-element section" data-auto="flex-element-section"> <div id="a2f8eeb9" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="37eaf874" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop="" data-hidden-on-tablet="" data-hidden-on-mobile=""> <div id="c7a80d10" class="flex-element group lazy" data-auto="flex-element-group" data-hidden-on-mobile="" data-hidden-on-tablet="" data-animation-trigger-desktop="entrance" data-anim-extended="eyJkZXNrdG9wIjp7InRyaWdnZXIiOiJlbnRyYW5jZSIsImFuaW1hdGlvbiI6ImZhZGVJbkNvbWJvIiwiZHVyYXRpb24iOjEsImRlbGF5IjowLCJpbnRlbnNpdHkiOjEsImRpciI6ImluLXBsYWNlIn19" data-background-image="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/Screen+Shot+2024-10-04+at+4.03.11+PM-1920w.png"></div> 1392 <div id="47ab8901" class="flex-element group" data-auto="flex-element-group"> <div id="31491e36" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1961864555"> <div class="widget-8ff527 u_1961864555 dmCustomWidget" data-lazy-load="true" data-title="" id="1961864555" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="8ff5270554664bddaecbe7a0b9e45c81" data-widget-version="14" data-widget-config="eyJjYWxsb3V0TWF4V2lkdGgiOiI3MjAiLCJlbmFibGVCdXR0b25SaXBwbGUiOmZhbHNlLCJidXR0b25BbGlnbiI6ImNlbnRlciIsImNhcmRWZXJ0aWNhbEFsaWduIjoidG9wIiwic3BhY2luZ0Rlc2lnbiI6bnVsbCwiY2FyZENvbnRlbnRBbGlnbiI6ImNlbnRlciIsInR5cG9ncmFwaHlIZWFkIjpudWxsLCJjb3Vwb25HYXAiOiIyMCIsInNob3dTdGFuZGFyZEJ1dHRvbiI6ZmFsc2UsImNvdXBvblNldHRpbmdzIjpudWxsLCJlbmFibGVFbnRyYW5jZUFuaW1hdGlvbiI6ZmFsc2UsImhlYWRsaW5lQm90dG9tR2FwIjoiMTIiLCJ3aWRnZXRNb2RlIjoiY291cG9uIiwibG9nb0Rlc2lnbiI6bnVsbCwidHlwb2dyYXBoe
1392UZpbmUiOm51bGwsInVzZURlZmF1bHRMb2dvIjp0cnVlLCJlbmFibGVMb2dvSG92ZXIiOmZhbHNlLCJmaWx0ZXJWYWx1ZSI6IjEiLCJ0eXBvZ3JhcGh5Q3RhIjpudWxsLCJjYXJkRGVzaWduIjpudWxsLCJnZW5lcmFsU2V0dGluZ3MiOm51bGwsImFsbG93ZWRTbHVncyI6IiIsImJvZHlCb3R0b21HYXAiOiIxMiIsImJ1dHRvbkRlc2lnbiI6bnVsbCwiZW5hYmxlQ2FyZEhvdmVyIjpmYWxzZSwiY2FyZFNoYWRvdyI6Im5vbmUiLCJsb2dvQm90dG9tR2FwIjoiMjQiLCJjYWxsb3V0U2V0dGluZ3MiOm51bGwsImxvZ29BbGlnbiI6ImNlbnRlciIsImNvdXBvbkNvbHVtbnMiOiIxIiwiY2FsbG91dEZpbHRlclZhbHVlIjoiIiwiZnVsbFdpZHRoQnV0dG9uc01vYmlsZSI6dHJ1ZSwibG9nb1NwYWNpbmciOiIxMiIsInR5cG9ncmFwaHlCb2R5IjpudWxsLCJhbmltYXRpb25EZXNpZ24iOm51bGwsImxvZ29XaWR0aCI6IjIyMCIsInNob3dBbGwiOmZhbHNlLCJlbmFibGVQaG9uZVB1bHNlIjpmYWxzZSwiYnV0dG9uQm90dG9tR2FwIjoiMCIsImxvZ29NYXhIZWlnaHQiOiIxMDAiLCJmaWx0ZXJCeVNsdWciOmZhbHNlLCJidXR0b25MYXlvdXQiOiJyb3ciLCJjb3Vwb25GaWx0ZXJCeVNsdWciOnRydWUsImNvdXBvbkxheW91dCI6bnVsbCwiY2FsbG91dExheW91dCI6bnVsbCwidGVybXNCb3R0b21HYXAiOiIxMiIsInNob3dQaG9uZUJ1dHRvbiI6dHJ1ZSwidGVybXNEaXNwbGF5TW9kZSI6ImZ1bGwiLCJjdXN0b21pemVTcGFjaW5nIjpmYWxzZSwiYnV0dG9uR2FwIjoiMTIiLCJjdGFCb3R0b21HYXAiOiIxMiIsImVuYWJsZUJ1dHRvbkhvdmVyIjpmYWxzZSwiY2FsbG91dEFsaWduIjoiZnVsbCJ9"> <div class="ucw-wrapper" role="region" aria-label="Promotions" aria-busy="true"> <div class="ucw-callout" hidden=""> <div class="ucw-callout__mount"></div> 1393</div> 1394 <div class="ucw-coupon" hidden=""> <div class="ucw-coupon__grid" role="list"></div> 1395</div> 1396<!-- 1397 Hidden Duda button template. 1398 1399 JavaScript clones this markup for both the collection 1400 button and the phone button. This allows one standard 1401 Duda Button design control to style every generated action. 1402 --> <div class="ucw-action-template" hidden="" aria-hidden="true"> <a class="ucw-card__actionLink" href="#"> <div class="dmWidget ucw-card__action"> <span class="text">Button</span> 1403 <span class="iconBg"></span> 1404</div> 1405</a> 1406</div> 1407</div> 1408</div> 1409</div> 1410</div> 1411</div> 1412</div> 1413</section> 1414</div> 1415 <div data-auto="flex-section" id="1214348819" data-flex-id="9e8c89ad" data-layout-section="" data-page-element-type="section" data-page-element-id="1688378275" class="" data-hidden-on-mobile="true"> <div class="flex-widgets-container" id="1006064923"></div> 1416 <section id="ba986e49" class="flex-element section" data-auto="flex-element-section"> <div id="a3040ec9" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="2b871182" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop="" data-hidden-on-tablet="" data-hidden-on-mobile=""> <div id="9c18e540" class="flex-element group" data-auto="flex-element-group"> <div id="c968f3db" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1073482025"> <div class="widget-8ff527 u_1073482025 dmCustomWidget" data-lazy-load="true" data-title="" id="1073482025" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="8ff5270554664bddaecbe7a0b9e45c81" data-widget-version="14" data-widget-config="eyJjYWxsb3V0TWF4V2lkdGgiOiI3MjAiLCJlbmFibGVCdXR0b25SaXBwbGUiOmZhbHNlLCJidXR0b25BbGlnbiI6ImNlbnRlciIsImNhcmRWZXJ0aWNhbEFsaWduIjoidG9wIiwic3BhY2luZ0Rlc2lnbiI6bnVsbCwiY2FyZENvbnRlbnRBbGlnbiI6ImNlbnRlciIsInR5cG9ncmFwaHlIZWFkIjpudWxsLCJjb3Vwb25HYXAiOiIyMCIsInNob3dTdGFuZGFyZEJ1dHRvbiI6ZmFsc2UsImNvdXBvblNldHRpbmdzIjpudWxsLCJlbmFibGVFbnRyYW5jZUFuaW1hdGlvbiI6ZmFsc2UsImhlYWRsaW5lQm90dG9tR2FwIjoiMTIiLCJ3aWRnZXRNb2RlIjoiY291cG9uIiwibG9nb0Rlc2lnbiI6bnVsbCwidHlwb2dyYXBoeUZpbmUiOm51bGwsInVzZURlZmF1bHRMb2dvIjp0cnVlLCJlbmFibGVMb2dvSG92ZXIiOmZhbHNlLCJmaWx0ZXJWYWx1ZSI6IjIiLCJ0eXBvZ3JhcGh5Q3RhIjpudWxsLCJjYXJkRGVzaWduIjpudWxsLCJnZW5lcmFsU2V0dGluZ3MiOm51bGwsImFsbG93ZWRTbHVncyI6IiIsImJvZHlCb3R0b21HYXAiOiIxMiIsImJ1dHRvbkRlc2lnbiI6bnVsbCwiZW5hYmxlQ2FyZEhvdmVyIjpmYWxzZSwiY2FyZFNoYWRvdyI6Im5vbmUiLCJsb2dvQm90dG9tR2FwIjoiMjQiLCJjYWxsb3V0U2V0dGluZ3MiOm51bGwsImxvZ29BbGlnbiI6ImNlbnRlciIsImNvdXBvbkNvbHVtbnMiOiIxIiwiY2FsbG91dEZpbHRlclZhbHVlIjoiIiwiZnVsbFdpZHRoQnV0dG9uc01vYmlsZSI6dHJ1ZSwibG9nb1NwYWNpbmciOiIxMiIsInR5cG9ncmFwaHlCb2R5IjpudWxsLCJhbmltYXRpb25EZXNpZ24iOm51bGwsImxvZ29XaWR0aCI6IjIyMCIsInNob3dBbGwiOmZhbHNlLCJlbmFibGVQaG9uZVB1bHNlIjpmYWxzZSwiYnV0dG9uQm90dG9tR2FwIjoiMCIsImxvZ29NYXhIZWlnaHQiOiIxMDAiLCJmaWx0ZXJCeVNsdWciOmZhbHNlLCJidXR0b25MYXlvdXQiOiJyb3ciLCJjb3Vwb25GaWx0ZXJCeVNsdWciOnRydWUsImNvdXBvbkxheW91dCI6bnVsbCwiY2FsbG91dExheW91dCI6bnVsbCwidGVybXNCb3R0b21HYXAiOiIxMiIsInNob3dQaG9uZUJ1dHRvbiI6dHJ1ZSwidGVybXNEaXNwbGF5TW9kZSI6ImZ1bGwiLCJjdXN0b21pemVTcGFjaW5nIjpmYWxzZSwiYnV0dG9uR2FwIjoiMTIiLCJjdGFCb3R0b21HYXAiOiIxMiIsImVuYWJsZUJ1dHRvbkhvdmVyIjpmYWxzZSwiY2FsbG91dEFsaWduIjoiZnVsbCJ9"> <div class="ucw-wrapper" role="region" aria-label="Promotions" aria-busy="true"> <div class="ucw-callout" hidden="">
1416 <div class="ucw-callout__mount"></div> 1417</div> 1418 <div class="ucw-coupon" hidden=""> <div class="ucw-coupon__grid" role="list"></div> 1419</div> 1420<!-- 1421 Hidden Duda button template. 1422 1423 JavaScript clones this markup for both the collection 1424 button and the phone button. This allows one standard 1425 Duda Button design control to style every generated action. 1426 --> <div class="ucw-action-template" hidden="" aria-hidden="true"> <a class="ucw-card__actionLink" href="#"> <div class="dmWidget ucw-card__action"> <span class="text">Button</span> 1427 <span class="iconBg"></span> 1428</div> 1429</a> 1430</div> 1431</div> 1432</div> 1433</div> 1434</div> 1435 <div id="cc0a6f0b" class="flex-element group" data-auto="flex-element-group"> <div id="d04bb848" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1081741638"> <div class="widget-8ff527 u_1081741638 dmCustomWidget" data-lazy-load="true" data-title="" id="1081741638" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="8ff5270554664bddaecbe7a0b9e45c81" data-widget-version="14" data-widget-config="eyJjYWxsb3V0TWF4V2lkdGgiOiI3MjAiLCJlbmFibGVCdXR0b25SaXBwbGUiOmZhbHNlLCJidXR0b25BbGlnbiI6ImNlbnRlciIsImNhcmRWZXJ0aWNhbEFsaWduIjoidG9wIiwic3BhY2luZ0Rlc2lnbiI6bnVsbCwiY2FyZENvbnRlbnRBbGlnbiI6ImNlbnRlciIsInR5cG9ncmFwaHlIZWFkIjpudWxsLCJjb3Vwb25HYXAiOiIyMCIsInNob3dTdGFuZGFyZEJ1dHRvbiI6ZmFsc2UsImNvdXBvblNldHRpbmdzIjpudWxsLCJlbmFibGVFbnRyYW5jZUFuaW1hdGlvbiI6ZmFsc2UsImhlYWRsaW5lQm90dG9tR2FwIjoiMTIiLCJ3aWRnZXRNb2RlIjoiY291cG9uIiwibG9nb0Rlc2lnbiI6bnVsbCwidHlwb2dyYXBoeUZpbmUiOm51bGwsInVzZURlZmF1bHRMb2dvIjp0cnVlLCJlbmFibGVMb2dvSG92ZXIiOmZhbHNlLCJmaWx0ZXJWYWx1ZSI6IjMiLCJ0eXBvZ3JhcGh5Q3RhIjpudWxsLCJjYXJkRGVzaWduIjpudWxsLCJnZW5lcmFsU2V0dGluZ3MiOm51bGwsImFsbG93ZWRTbHVncyI6IiIsImJvZHlCb3R0b21HYXAiOiIxMiIsImJ1dHRvbkRlc2lnbiI6bnVsbCwiZW5hYmxlQ2FyZEhvdmVyIjpmYWxzZSwiY2FyZFNoYWRvdyI6Im5vbmUiLCJsb2dvQm90dG9tR2FwIjoiMjQiLCJjYWxsb3V0U2V0dGluZ3MiOm51bGwsImxvZ29BbGlnbiI6ImNlbnRlciIsImNvdXBvbkNvbHVtbnMiOiIxIiwiY2FsbG91dEZpbHRlclZhbHVlIjoiIiwiZnVsbFdpZHRoQnV0dG9uc01vYmlsZSI6dHJ1ZSwibG9nb1NwYWNpbmciOiIxMiIsInR5cG9ncmFwaHlCb2R5IjpudWxsLCJhbmltYXRpb25EZXNpZ24iOm51bGwsImxvZ29XaWR0aCI6IjIyMCIsInNob3dBbGwiOmZhbHNlLCJlbmFibGVQaG9uZVB1bHNlIjpmYWxzZSwiYnV0dG9uQm90dG9tR2FwIjoiMCIsImxvZ29NYXhIZWlnaHQiOiIxMDAiLCJmaWx0ZXJCeVNsdWciOmZhbHNlLCJidXR0b25MYXlvdXQiOiJyb3ciLCJjb3Vwb25GaWx0ZXJCeVNsdWciOnRydWUsImNvdXBvbkxheW91dCI6bnVsbCwiY2FsbG91dExheW91dCI6bnVsbCwidGVybXNCb3R0b21HYXAiOiIxMiIsInNob3dQaG9uZUJ1dHRvbiI6dHJ1ZSwidGVybXNEaXNwbGF5TW9kZSI6ImZ1bGwiLCJjdXN0b21pemVTcGFjaW5nIjpmYWxzZSwiYnV0dG9uR2FwIjoiMTIiLCJjdGFCb3R0b21HYXAiOiIxMiIsImVuYWJsZUJ1dHRvbkhvdmVyIjpmYWxzZSwiY2FsbG91dEFsaWduIjoiZnVsbCJ9"> <div class="ucw-wrapper" role="region" aria-label="Promotions" aria-busy="true"> <div class="ucw-callout" hidden=""> <div class="ucw-callout__mount"></div> 1436</div> 1437 <div class="ucw-coupon" hidden=""> <div class="ucw-coupon__grid" role="list"></div> 1438</div> 1439<!-- 1440 Hidden Duda button template. 1441 1442 JavaScript clones this markup for both the collection 1443 button and the phone button. This allows one standard 1444 Duda Button design control to style every generated action. 1445 --> <div class="ucw-action-template" hidden="" aria-hidden="true"> <a class="ucw-card__actionLink" href="#"> <div class="dmWidget ucw-card__action"> <span class="text">Button</span> 1446 <span class="iconBg"></span> 1447</div> 1448</a> 1449</div> 1450</div> 1451</div> 1452</div> 1453</div> 1454</div> 1455</div> 1456</section> 1457</div> 1458 <div data-layout-section="" data-auto="flex-section" id="1668029879" data-flex-id="bcf46450" data-page-element-type="section" data-page-element-id="1688378275" class="" data-hidden-on-desktop="true"> <div class="flex-widgets-container" id="1578351440"></div> 1459 <section id="b800bf55" class="flex-element section" data-auto="flex-element-section"> <div id="8c90c0c5" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="10c045d3" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop="" data-hidden-on-tablet="" data-hidden-on-mobile=""> <div id="fd4f79eb" class="flex-element group" data-auto="flex-element-group"> <div id="391d01b6" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1191767750"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton" file="false" href="/special-offers" data-element-type="dButtonLinkId" id="1191767750" data-binding="W3siYmluZGluZ05hbWUiOiJsaW5rIiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCJidXR0b25zXCIsXCJmblwiOlwiTW9yZSBPZmZlcnMgTGlua1wifSJ9LHsiYmluZGluZ05hbWUiOiJidXR0b25fdGV4dCIsInZhbHVlIjoiU1RBVElDX1BBR0VfQ09MTEVDVElPTi57XCJjblwiOlwiYnV0dG9uc1wiLFwiZm5cIjpcIk1vcmUgT2ZmZXJzIEJ1dHRvblwifSJ9XQ==" data-diy-link=""> <span class="iconBg" aria-hidden="true" id="1398028174"> <span class="icon hasFontIcon icon-star" id="1531356217"></span> 1460</span> 1461 <span class="text" id="1956394719" data-diy-text="">VIEW MORE OFFERS</span> 1462</a> 1463</div> 1464</div> 1465</div> 1466</div> 1467</section> 1468</div> 1469 <div data-flex-id="3a431b71" data-auto="flex-section" id="1149754944" data-layout-section="" data-page-element-type="section" data-page-element-id="1688378275" class="" data-hidden-on-mobile="true"> <div class="flex-widgets-container" id="1926727959"></div> 1470 <section id="016f36de" class="flex-element section" data-auto="flex-element-section"> <div id="00d81ca6" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="7f166c5e" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop="" data-hidden-on-tablet="" data-hidden-on-mobile=""> <div id="acc30245" class="flex-element group" data-auto="flex-element-group"> <div id="59867e38" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1246049058"> <div class="widget-ab442a dmCustomWidget" data-lazy-load="true" data-title="" id="1246049058" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="ab442ac754384e98a02c4f630b481f5e" data-widget-version="9" data-widget-config="eyJyZXF1aXJlZEZpZWxkTmFtZSI6IkNPUFkgQkxPQ0sgMSBIRUFETElORSIsImNvbGxlY3Rpb25OYW1lIjoiMDEgSE9NRSJ9"> <div class="hide-section-if-category-field-empty" data-collection-name="01 HOME" data-required-field="COPY BLOCK 1 HEADLINE" style="display:none;"></div> 1471</div> 1472</div> 1473 <div id="d47c231b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1112831207"> <div class="widget-f19f9b u_1112831207 dmCustomWidget" data-lazy-load="true" data-title="" id="1112831207" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="f19f9b2806104edb81a7816f71967887" data-widget-version="13" data-widget-config="eyJidXR0b25OYW1lIjoiTGVhcm4gTW9yZSIsInNvdXJjZVBhZ2VUeXBlIjoiaG9tZSIsIm
1473NvcmVQcmVmaXgiOiJzZXJ2aWNlcyIsImNvcHlCbG9ja051bWJlciI6IjEiLCJidXR0b25Sb3V0aW5nT3B0aW9ucyI6bnVsbCwiY2F0ZWdvcnlQcmVmaXgiOiJ3aGF0LXdlLWRvIn0="> <div class="copy-block-link-widget"> <a class="copy-block-link-anchor" aria-label="Learn More" aria-disabled="true" aria-busy="true"> <div class="dmWidget copy-block-link-button"> <span class="text">Learn More</span> 1474 <span class="iconBg"></span> 1475</div> 1476</a> 1477</div> 1478</div> 1479</div> 1480 <div id="c5b2e9f3" class="flex-element group" data-auto="flex-element-group"> <div id="31eabdad" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1676783039"> <div class="widget-31ea1e dmCustomWidget" data-lazy-load="true" data-title="" id="1676783039" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="31ea1ee9b19c4368abcc1dbd5ec6a0d6" data-widget-version="2" data-widget-config="eyJzb3VyY2VQYWdlVHlwZSI6ImhvbWUiLCJjb3B5QmxvY2tOdW1iZXIiOiIxIiwiaW1hZ2VIZWlnaHQiOiIzMDAiLCJiYWNrZ3JvdW5kU2l6ZSI6ImNvdmVyIiwiYmFja2dyb3VuZFBvc2l0aW9uIjoiY2VudGVyIGNlbnRlciIsImJvcmRlclJhZGl1cyI6IjAiLCJvdmVybGF5Q29sb3IiOiIjMDAwMDAwIiwib3ZlcmxheU9wYWNpdHkiOiIwIiwiZW5hYmxlSG92ZXJMaWZ0IjpmYWxzZX0="> <div class="cross-collection-image" role="img" aria-busy="true" aria-hidden="true"> <div class="cross-collection-image-overlay" aria-hidden="true"></div> 1481</div> 1482</div> 1483</div> 1484 <div id="d0493b23" class="flex-element widget-wrapper DCBH3" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1931493629"> <div class="dmNewParagraph u_1931493629" data-element-type="paragraph" data-version="5" id="1931493629" style="" data-inject="topicheading1" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCIwMSBIT01FXCIsXCJmblwiOlwiQ09QWSBCTE9DSyAxIEhFQURMSU5FXCJ9In1d" data-diy-text="">Tree Services</div> 1485</div> 1486 <div id="fad57111" class="flex-element widget-wrapper DCBP" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1200929661"> <div class="dmNewParagraph u_1200929661" data-element-type="paragraph" data-version="5" id="1200929661" style="" data-inject="topiccontent1" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCIwMSBIT01FXCIsXCJmblwiOlwiQ09QWSBCTE9DSyAxIFRFWFRcIn0ifV0=" data-diy-text="">Our tree services cover everything from precision trimming and strategic pruning to complete removal when necessary. With decades of combined experience and ISA certification, our arborists assess each tree's unique needs and deliver customized solutions that promote healthy growth while protecting your property.</div> 1487</div> 1488</div> 1489</div> 1490 <div id="2c859d2b" class="flex-element group" data-auto="flex-element-group"> <div id="5fecb840" class="flex-element group" data-auto="flex-element-group"> <div id="f1a40cb8" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1859507281"> <div class="widget-31ea1e dmCustomWidget" data-lazy-load="true" data-title="" id="1859507281" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="31ea1ee9b19c4368abcc1dbd5ec6a0d6" data-widget-version="2" data-widget-config="eyJzb3VyY2VQYWdlVHlwZSI6ImhvbWUiLCJjb3B5QmxvY2tOdW1iZXIiOiIyIiwiaW1hZ2VIZWlnaHQiOiIzMDAiLCJiYWNrZ3JvdW5kU2l6ZSI6ImNvdmVyIiwiYmFja2dyb3VuZFBvc2l0aW9uIjoiY2VudGVyIGNlbnRlciIsImJvcmRlclJhZGl1cyI6IjAiLCJvdmVybGF5Q29sb3IiOiIjMDAwMDAwIiwib3ZlcmxheU9wYWNpdHkiOiIwIiwiZW5hYmxlSG92ZXJMaWZ0IjpmYWxzZX0="> <div class="cross-collection-image" role="img" aria-busy="true" aria-hidden="true"> <div class="cross-collection-image-overlay" aria-hidden="true"></div> 1491</div> 1492</div> 1493</div> 1494 <div id="05385236" class="flex-element widget-wrapper DCBH3" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1011699339"> <div class="dmNewParagraph u_1011699339" data-element-type="paragraph" data-version="5" id="1011699339" style="" data-inject="topicheading2" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCIwMSBIT01FXCIsXCJmblwiOlwiQ09QWSBCTE9DSyAyIEhFQURMSU5FXCJ9In1d" data-diy-text="">Turf and Arbor Care</div> 1495</div> 1496 <div id="8b49f88e" class="flex-element widget-wrapper DCBP" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1821793429"> <div class="dmNewParagraph u_1821793429" data-element-type="paragraph" data-version="5" id="1821793429" style="" data-inject="topiccontent2" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCIwMSBIT01FXCIsXCJmblwiOlwiQ09QWSBCTE9DSyAyIFRFWFRcIn0ifV0=" data-diy-text="">Healthy trees start with healthy soil and proper maintenance practices. Our turf and arbor care programs focus on creating the best growing conditions through targeted treatments, fertilization, and ongoing monitoring that keeps your landscape thriving year-round.</div> 1497</div> 1498</div> 1499 <div id="cb51b1aa" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1831538458"> <div class="widget-901b1c dmCustomWidget" data-lazy-load="true" data-title="" id="1831538458" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="901b1c7285754fceac707cdcb08aa571" data-widget-version="7" data-widget-config="eyJjb2xsZWN0aW9uTmFtZSI6IjAxIEhPTUUiLCJyZXF1aXJlZEZpZWxkTmFtZSI6IkNPUFkgQkxPQ0sgMiBIRUFETElORSJ9"> <div class="hide-column-if-category-field-empty" data-collection-name="01 HOME" data-required-field="COPY BLOCK 2 HEADLINE" style="display:none;"></div> 1500</div> 1501</div> 1502 <div id="9eb55001" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1989022222"> <div class="widget-f19f9b u_1989022222 dmCustomWidget" data-lazy-load="true" data-title="" id="1989022222" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="f19f9b2806104edb81a7816f71967887" data-widget-version="13" data-widget-config="eyJidXR0b25OYW1lIjoiTGVhcm4gTW9yZSIsInNvdXJjZVBhZ2VUeXBlIjoiaG9tZSIsIm
1502NvcmVQcmVmaXgiOiJzZXJ2aWNlcyIsImNvcHlCbG9ja051bWJlciI6IjIiLCJidXR0b25Sb3V0aW5nT3B0aW9ucyI6bnVsbCwiY2F0ZWdvcnlQcmVmaXgiOiJ3aGF0LXdlLWRvIn0="> <div class="copy-block-link-widget"> <a class="copy-block-link-anchor" aria-label="Learn More" aria-disabled="true" aria-busy="true"> <div class="dmWidget copy-block-link-button"> <span class="text">Learn More</span> 1503 <span class="iconBg"></span> 1504</div> 1505</a> 1506</div> 1507</div> 1508</div> 1509</div> 1510 <div id="294378e9" class="flex-element group" data-auto="flex-element-group"> <div id="6e8ed22a" class="flex-element group" data-auto="flex-element-group"> <div id="a0142848" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1457837878"> <div class="widget-31ea1e dmCustomWidget" data-lazy-load="true" data-title="" id="1457837878" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="31ea1ee9b19c4368abcc1dbd5ec6a0d6" data-widget-version="2" data-widget-config="eyJzb3VyY2VQYWdlVHlwZSI6ImhvbWUiLCJjb3B5QmxvY2tOdW1iZXIiOiIzIiwiaW1hZ2VIZWlnaHQiOiIyMDAiLCJiYWNrZ3JvdW5kU2l6ZSI6ImNvdmVyIiwiYmFja2dyb3VuZFBvc2l0aW9uIjoiY2VudGVyIGNlbnRlciIsImJvcmRlclJhZGl1cyI6IjAiLCJvdmVybGF5Q29sb3IiOiIjMDAwMDAwIiwib3ZlcmxheU9wYWNpdHkiOiIwIiwiZW5hYmxlSG92ZXJMaWZ0IjpmYWxzZX0="> <div class="cross-collection-image" role="img" aria-busy="true" aria-hidden="true"> <div class="cross-collection-image-overlay" aria-hidden="true"></div> 1511</div> 1512</div> 1513</div> 1514</div> 1515 <div id="864c2572" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1290573904"> <div class="widget-901b1c dmCustomWidget" data-lazy-load="true" data-title="" id="1290573904" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="901b1c7285754fceac707cdcb08aa571" data-widget-version="7" data-widget-config="eyJjb2xsZWN0aW9uTmFtZSI6IjAxIEhPTUUiLCJyZXF1aXJlZEZpZWxkTmFtZSI6IkNPUFkgQkxPQ0sgMyBIRUFETElORSJ9"> <div class="hide-column-if-category-field-empty" data-collection-name="01 HOME" data-required-field="COPY BLOCK 3 HEADLINE" style="display:none;"></div> 1516</div> 1517</div> 1518 <div id="d393fda6" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1285306804"> <div class="widget-f19f9b u_1285306804 dmCustomWidget" data-lazy-load="true" data-title="" id="1285306804" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="f19f9b2806104edb81a7816f71967887" data-widget-version="13" data-widget-config="eyJidXR0b25OYW1lIjoiTGVhcm4gTW9yZSIsInNvdXJjZVBhZ2VUeXBlIjoiaG9tZSIsImNvcmVQcmVmaXgiOiJzZXJ2aWNlcyIsImNvcHlCbG9ja051bWJlciI6IjMiLCJidXR0b25Sb3V0aW5nT3B0aW9ucyI6bnVsbCwiY2F0ZWdvcnlQcmVmaXgiOiJ3aGF0LXdlLWRvIn0="> <div class="copy-block-link-widget"> <a class="copy-block-link-anchor" aria-label="Learn More" aria-disabled="true" aria-busy="true"> <div class="dmWidget copy-block-link-button"> <span class="text">Learn More</span> 1519 <span class="iconBg"></span> 1520</div> 1521</a> 1522</div> 1523</div> 1524</div> 1525</div> 1526</div> 1527</div> 1528</section> 1529</div> 1530 <div data-flex-id="c2e55417" data-auto="flex-section" id="1868619496" data-layout-section="" data-page-element-type="section" data-page-element-id="1688378275"> <div class="flex-widgets-container" id="1094315955"></div> 1531 <section id="cda7edee" class="flex-element section" data-auto="flex-element-section"> <div id="b43e6b8f" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="2a7169e0" class="flex-element group" data-auto="flex-element-group"> <div id="76e4141e" class="flex-element group" data-auto="flex-element-group"> <div id="e3a396de" class="flex-element group" data-auto="flex-element-group"> <div id="f5388d9b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1707982437"> <div class="widget-31ea1e dmCustomWidget" data-lazy-load="true" data-title="" id="1707982437" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="31ea1ee9b19c4368abcc1dbd5ec6a0d6" data-widget-version="2" data-widget-config="eyJzb3VyY2VQYWdlVHlwZSI6ImhvbWUiLCJjb3B5QmxvY2tOdW1iZXIiOiI0IiwiaW1hZ2VIZWlnaHQiOiIyMDAiLCJiYWNrZ3JvdW5kU2l6ZSI6ImNvdmVyIiwiYmFja2dyb3VuZFBvc2l0aW9uIjoiY2VudGVyIGNlbnRlciIsImJvcmRlclJhZGl1cyI6IjAiLCJvdmVybGF5Q29sb3IiOiIjMDAwMDAwIiwib3ZlcmxheU9wYWNpdHkiOiIwIiwiZW5hYmxlSG92ZXJMaWZ0IjpmYWxzZX0="> <div class="cross-collection-image" role="img" aria-busy="true" aria-hidden="true"> <div class="cross-collection-image-overlay" aria-hidden="true"></div> 1532</div> 1533</div> 1534</div> 1535</div> 1536 <div id="1b0d613d" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1768644199"> <div class="widget-ab442a dmCustomWidget" data-lazy-load="true" data-title="" id="1768644199" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="ab442ac754384e98a02c4f630b481f5e" data-widget-version="9" data-widget-config="eyJyZXF1aXJlZEZpZWxkTmFtZSI6IkNPUFkgQkxPQ0sgNCBIRUFETElORSIsImNvbGxlY3Rpb25OYW1lIjoiMDEgSE9NRSJ9"> <div class="hide-section-if-category-field-empty" data-collection-name="01 HOME" data-required-field="COPY BLOCK 4 HEADLINE" style="display:none;"></div> 1537</div> 1538</div> 1539 <div id="c41184f1" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1255561142"> <div class="widget-f19f9b u_1255561142 dmCustomWidget" data-lazy-load="true" data-title="" id="1255561142" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="f19f9b2806104edb81a7816f71967887" data-widget-version="13" data-widget-config="eyJidXR0b25OYW1lIjoiTGVhcm4gTW9yZSIsInNvdXJjZVBhZ2VUeXBlIjoiaG9tZSIsIm
1539NvcmVQcmVmaXgiOiJzZXJ2aWNlcyIsImNvcHlCbG9ja051bWJlciI6IjQiLCJidXR0b25Sb3V0aW5nT3B0aW9ucyI6bnVsbCwiY2F0ZWdvcnlQcmVmaXgiOiJ3aGF0LXdlLWRvIn0="> <div class="copy-block-link-widget"> <a class="copy-block-link-anchor" aria-label="Learn More" aria-disabled="true" aria-busy="true"> <div class="dmWidget copy-block-link-button"> <span class="text">Learn More</span> 1540 <span class="iconBg"></span> 1541</div> 1542</a> 1543</div> 1544</div> 1545</div> 1546</div> 1547 <div id="60f88d37" class="flex-element group" data-auto="flex-element-group"> <div id="33d16e54" class="flex-element group" data-auto="flex-element-group"> <div id="6e455d52" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1316770770"> <div class="widget-31ea1e dmCustomWidget" data-lazy-load="true" data-title="" id="1316770770" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="31ea1ee9b19c4368abcc1dbd5ec6a0d6" data-widget-version="2" data-widget-config="eyJzb3VyY2VQYWdlVHlwZSI6ImhvbWUiLCJjb3B5QmxvY2tOdW1iZXIiOiI1IiwiaW1hZ2VIZWlnaHQiOiIyMDAiLCJiYWNrZ3JvdW5kU2l6ZSI6ImNvdmVyIiwiYmFja2dyb3VuZFBvc2l0aW9uIjoiY2VudGVyIGNlbnRlciIsImJvcmRlclJhZGl1cyI6IjAiLCJvdmVybGF5Q29sb3IiOiIjMDAwMDAwIiwib3ZlcmxheU9wYWNpdHkiOiIwIiwiZW5hYmxlSG92ZXJMaWZ0IjpmYWxzZX0="> <div class="cross-collection-image" role="img" aria-busy="true" aria-hidden="true"> <div class="cross-collection-image-overlay" aria-hidden="true"></div> 1548</div> 1549</div> 1550</div> 1551</div> 1552 <div id="365a42d7" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1314388645"> <div class="widget-901b1c dmCustomWidget" data-lazy-load="true" data-title="" id="1314388645" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="901b1c7285754fceac707cdcb08aa571" data-widget-version="7" data-widget-config="eyJjb2xsZWN0aW9uTmFtZSI6IjAxIEhPTUUiLCJyZXF1aXJlZEZpZWxkTmFtZSI6IkNPUFkgQkxPQ0sgNSBIRUFETElORSJ9"> <div class="hide-column-if-category-field-empty" data-collection-name="01 HOME" data-required-field="COPY BLOCK 5 HEADLINE" style="display:none;"></div> 1553</div> 1554</div> 1555 <div id="2f017a1e" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1365707288"> <div class="widget-f19f9b u_1365707288 dmCustomWidget" data-lazy-load="true" data-title="" id="1365707288" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="f19f9b2806104edb81a7816f71967887" data-widget-version="13" data-widget-config="eyJidXR0b25OYW1lIjoiTGVhcm4gTW9yZSIsInNvdXJjZVBhZ2VUeXBlIjoiaG9tZSIsImNvcmVQcmVmaXgiOiJzZXJ2aWNlcyIsImNvcHlCbG9ja051bWJlciI6IjUiLCJidXR0b25Sb3V0aW5nT3B0aW9ucyI6bnVsbCwiY2F0ZWdvcnlQcmVmaXgiOiJ3aGF0LXdlLWRvIn0="> <div class="copy-block-link-widget"> <a class="copy-block-link-anchor" aria-label="Learn More" aria-disabled="true" aria-busy="true"> <div class="dmWidget copy-block-link-button"> <span class="text">Learn More</span> 1556 <span class="iconBg"></span> 1557</div> 1558</a> 1559</div> 1560</div> 1561</div> 1562</div> 1563 <div id="bcb9e9b3" class="flex-element group" data-auto="flex-element-group"> <div id="3503b1a5" class="flex-element group" data-auto="flex-element-group"> <div id="5f16df0b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1604505749"> <div class="widget-31ea1e dmCustomWidget" data-lazy-load="true" data-title="" id="1604505749" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="31ea1ee9b19c4368abcc1dbd5ec6a0d6" data-widget-version="2" data-widget-config="eyJzb3VyY2VQYWdlVHlwZSI6ImhvbWUiLCJjb3B5QmxvY2tOdW1iZXIiOiI2IiwiaW1hZ2VIZWlnaHQiOiIyMDAiLCJiYWNrZ3JvdW5kU2l6ZSI6ImNvdmVyIiwiYmFja2dyb3VuZFBvc2l0aW9uIjoiY2VudGVyIGNlbnRlciIsImJvcmRlclJhZGl1cyI6IjAiLCJvdmVybGF5Q29sb3IiOiIjMDAwMDAwIiwib3ZlcmxheU9wYWNpdHkiOiIwIiwiZW5hYmxlSG92ZXJMaWZ0IjpmYWxzZX0="> <div class="cross-collection-image" role="img" aria-busy="true" aria-hidden="true"> <div class="cross-collection-image-overlay" aria-hidden="true"></div> 1564</div> 1565</div> 1566</div> 1567</div> 1568 <div id="090b2b56" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1908803086"> <div class="widget-901b1c dmCustomWidget" data-lazy-load="true" data-title="" id="1908803086" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="901b1c7285754fceac707cdcb08aa571" data-widget-version="7" data-widget-config="eyJjb2xsZWN0aW9uTmFtZSI6IjAxIEhPTUUiLCJyZXF1aXJlZEZpZWxkTmFtZSI6IkNPUFkgQkxPQ0sgNiBIRUFETElORSJ9"> <div class="hide-column-if-category-field-empty" data-collection-name="01 HOME" data-required-field="COPY BLOCK 6 HEADLINE" style="display:none;"></div> 1569</div> 1570</div> 1571 <div id="532702e9" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1203866538"> <div class="widget-f19f9b u_1203866538 dmCustomWidget" data-lazy-load="true" data-title="" id="1203866538" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="f19f9b2806104edb81a7816f71967887" data-widget-version="13" data-widget-config="eyJidXR0b25OYW1lIjoiTGVhcm4gTW9yZSIsInNvdXJjZVBhZ2VUeXBlIjoiaG9tZSIsIm
1571NvcmVQcmVmaXgiOiJzZXJ2aWNlcyIsImNvcHlCbG9ja051bWJlciI6IjYiLCJidXR0b25Sb3V0aW5nT3B0aW9ucyI6bnVsbCwiY2F0ZWdvcnlQcmVmaXgiOiJ3aGF0LXdlLWRvIn0="> <div class="copy-block-link-widget"> <a class="copy-block-link-anchor" aria-label="Learn More" aria-disabled="true" aria-busy="true"> <div class="dmWidget copy-block-link-button"> <span class="text">Learn More</span> 1572 <span class="iconBg"></span> 1573</div> 1574</a> 1575</div> 1576</div> 1577</div> 1578</div> 1579</div> 1580</div> 1581</section> 1582</div> 1583 <div data-flex-id="62a0797c" data-auto="flex-section" id="1080692909" data-layout-section="" data-page-element-type="section" data-page-element-id="1688378275"> <div class="flex-widgets-container" id="1910227453"></div> 1584 <section id="55307785" class="flex-element section" data-auto="flex-element-section"> <div id="72fbf6d6" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="591f9133" class="flex-element group" data-auto="flex-element-group"> <div id="b70daeaf" class="flex-element group" data-auto="flex-element-group"> <div id="78baf59c" class="flex-element group" data-auto="flex-element-group"> <div id="29c654ba" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1028662752"> <div class="widget-31ea1e dmCustomWidget" data-lazy-load="true" data-title="" id="1028662752" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="31ea1ee9b19c4368abcc1dbd5ec6a0d6" data-widget-version="2" data-widget-config="eyJzb3VyY2VQYWdlVHlwZSI6ImhvbWUiLCJjb3B5QmxvY2tOdW1iZXIiOiI3IiwiaW1hZ2VIZWlnaHQiOiIyMDAiLCJiYWNrZ3JvdW5kU2l6ZSI6ImNvdmVyIiwiYmFja2dyb3VuZFBvc2l0aW9uIjoiY2VudGVyIGNlbnRlciIsImJvcmRlclJhZGl1cyI6IjAiLCJvdmVybGF5Q29sb3IiOiIjMDAwMDAwIiwib3ZlcmxheU9wYWNpdHkiOiIwIiwiZW5hYmxlSG92ZXJMaWZ0IjpmYWxzZX0="> <div class="cross-collection-image" role="img" aria-busy="true" aria-hidden="true"> <div class="cross-collection-image-overlay" aria-hidden="true"></div> 1585</div> 1586</div> 1587</div> 1588</div> 1589 <div id="989e011e" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1815743875"> <div class="widget-ab442a dmCustomWidget" data-lazy-load="true" data-title="" id="1815743875" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="ab442ac754384e98a02c4f630b481f5e" data-widget-version="9" data-widget-config="eyJyZXF1aXJlZEZpZWxkTmFtZSI6IkNPUFkgQkxPQ0sgNyBIRUFETElORSIsImNvbGxlY3Rpb25OYW1lIjoiMDEgSE9NRSJ9"> <div class="hide-section-if-category-field-empty" data-collection-name="01 HOME" data-required-field="COPY BLOCK 7 HEADLINE" style="display:none;"></div> 1590</div> 1591</div> 1592 <div id="78686da5" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1856635284"> <div class="widget-f19f9b u_1856635284 dmCustomWidget" data-lazy-load="true" data-title="" id="1856635284" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="f19f9b2806104edb81a7816f71967887" data-widget-version="13" data-widget-config="eyJidXR0b25OYW1lIjoiTGVhcm4gTW9yZSIsInNvdXJjZVBhZ2VUeXBlIjoiaG9tZSIsImNvcmVQcmVmaXgiOiJzZXJ2aWNlcyIsImNvcHlCbG9ja051bWJlciI6IjciLCJidXR0b25Sb3V0aW5nT3B0aW9ucyI6bnVsbCwiY2F0ZWdvcnlQcmVmaXgiOiJ3aGF0LXdlLWRvIn0="> <div class="copy-block-link-widget"> <a class="copy-block-link-anchor" aria-label="Learn More" aria-disabled="true" aria-busy="true"> <div class="dmWidget copy-block-link-button"> <span class="text">Learn More</span> 1593 <span class="iconBg"></span> 1594</div> 1595</a> 1596</div> 1597</div> 1598</div> 1599</div> 1600 <div id="bf57f545" class="flex-element group" data-auto="flex-element-group"> <div id="97a630cf" class="flex-element group" data-auto="flex-element-group"> <div id="5e664023" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1292951174"> <div class="widget-31ea1e dmCustomWidget" data-lazy-load="true" data-title="" id="1292951174" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="31ea1ee9b19c4368abcc1dbd5ec6a0d6" data-widget-version="2" data-widget-config="eyJzb3VyY2VQYWdlVHlwZSI6ImhvbWUiLCJjb3B5QmxvY2tOdW1iZXIiOiI4IiwiaW1hZ2VIZWlnaHQiOiIyMDAiLCJiYWNrZ3JvdW5kU2l6ZSI6ImNvdmVyIiwiYmFja2dyb3VuZFBvc2l0aW9uIjoiY2VudGVyIGNlbnRlciIsImJvcmRlclJhZGl1cyI6IjAiLCJvdmVybGF5Q29sb3IiOiIjMDAwMDAwIiwib3ZlcmxheU9wYWNpdHkiOiIwIiwiZW5hYmxlSG92ZXJMaWZ0IjpmYWxzZX0="> <div class="cross-collection-image" role="img" aria-busy="true" aria-hidden="true"> <div class="cross-collection-image-overlay" aria-hidden="true"></div> 1601</div> 1602</div> 1603</div> 1604</div> 1605 <div id="f4692065" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1233431865"> <div class="widget-901b1c dmCustomWidget" data-lazy-load="true" data-title="" id="1233431865" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="901b1c7285754fceac707cdcb08aa571" data-widget-version="7" data-widget-config="eyJjb2xsZWN0aW9uTmFtZSI6IjAxIEhPTUUiLCJyZXF1aXJlZEZpZWxkTmFtZSI6IkNPUFkgQkxPQ0sgOCBIRUFETElORSJ9"> <div class="hide-column-if-category-field-empty" data-collection-name="01 HOME" data-required-field="COPY BLOCK 8 HEADLINE" style="display:none;"></div> 1606</div> 1607</div> 1608 <div id="e149f88b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1143937077"> <div class="widget-f19f9b u_1143937077 dmCustomWidget" data-lazy-load="true" data-title="" id="1143937077" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="f19f9b2806104edb81a7816f71967887" data-widget-version="13" data-widget-config="eyJidXR0b25OYW1lIjoiTGVhcm4gTW9yZSIsInNvdXJjZVBhZ2VUeXBlIjoiaG9tZSIsIm
1608NvcmVQcmVmaXgiOiJzZXJ2aWNlcyIsImNvcHlCbG9ja051bWJlciI6IjgiLCJidXR0b25Sb3V0aW5nT3B0aW9ucyI6bnVsbCwiY2F0ZWdvcnlQcmVmaXgiOiJ3aGF0LXdlLWRvIn0="> <div class="copy-block-link-widget"> <a class="copy-block-link-anchor" aria-label="Learn More" aria-disabled="true" aria-busy="true"> <div class="dmWidget copy-block-link-button"> <span class="text">Learn More</span> 1609 <span class="iconBg"></span> 1610</div> 1611</a> 1612</div> 1613</div> 1614</div> 1615</div> 1616 <div id="ba24d823" class="flex-element group" data-auto="flex-element-group"> <div id="43e52408" class="flex-element group" data-auto="flex-element-group"> <div id="7dfcbffb" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1729767403"> <div class="widget-31ea1e dmCustomWidget" data-lazy-load="true" data-title="" id="1729767403" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="31ea1ee9b19c4368abcc1dbd5ec6a0d6" data-widget-version="2" data-widget-config="eyJzb3VyY2VQYWdlVHlwZSI6ImhvbWUiLCJjb3B5QmxvY2tOdW1iZXIiOiI5IiwiaW1hZ2VIZWlnaHQiOiIyMDAiLCJiYWNrZ3JvdW5kU2l6ZSI6ImNvdmVyIiwiYmFja2dyb3VuZFBvc2l0aW9uIjoiY2VudGVyIGNlbnRlciIsImJvcmRlclJhZGl1cyI6IjAiLCJvdmVybGF5Q29sb3IiOiIjMDAwMDAwIiwib3ZlcmxheU9wYWNpdHkiOiIwIiwiZW5hYmxlSG92ZXJMaWZ0IjpmYWxzZX0="> <div class="cross-collection-image" role="img" aria-busy="true" aria-hidden="true"> <div class="cross-collection-image-overlay" aria-hidden="true"></div> 1617</div> 1618</div> 1619</div> 1620</div> 1621 <div id="f743cc5a" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1727984231"> <div class="widget-901b1c dmCustomWidget" data-lazy-load="true" data-title="" id="1727984231" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="901b1c7285754fceac707cdcb08aa571" data-widget-version="7" data-widget-config="eyJjb2xsZWN0aW9uTmFtZSI6IjAxIEhPTUUiLCJyZXF1aXJlZEZpZWxkTmFtZSI6IkNPUFkgQkxPQ0sgOSBIRUFETElORSJ9"> <div class="hide-column-if-category-field-empty" data-collection-name="01 HOME" data-required-field="COPY BLOCK 9 HEADLINE" style="display:none;"></div> 1622</div> 1623</div> 1624 <div id="31a4120b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1088604281"> <div class="widget-f19f9b u_1088604281 dmCustomWidget" data-lazy-load="true" data-title="" id="1088604281" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="f19f9b2806104edb81a7816f71967887" data-widget-version="13" data-widget-config="eyJidXR0b25OYW1lIjoiTGVhcm4gTW9yZSIsInNvdXJjZVBhZ2VUeXBlIjoiaG9tZSIsImNvcmVQcmVmaXgiOiJzZXJ2aWNlcyIsImNvcHlCbG9ja051bWJlciI6IjkiLCJidXR0b25Sb3V0aW5nT3B0aW9ucyI6bnVsbCwiY2F0ZWdvcnlQcmVmaXgiOiJ3aGF0LXdlLWRvIn0="> <div class="copy-block-link-widget"> <a class="copy-block-link-anchor" aria-label="Learn More" aria-disabled="true" aria-busy="true"> <div class="dmWidget copy-block-link-button"> <span class="text">Learn More</span> 1625 <span class="iconBg"></span> 1626</div> 1627</a> 1628</div> 1629</div> 1630</div> 1631</div> 1632</div> 1633</div> 1634</section> 1635</div> 1636 <div data-flex-id="183df2d6" data-auto="flex-section" id="1689152970" data-layout-section="" data-page-element-type="section" data-page-element-id="1688378275" class="" data-hidden-on-mobile="true" data-hidden-on-desktop="true" data-hidden-on-tablet="true"> <div class="flex-widgets-container" id="1769743817"></div> 1637 <section id="8d24a736" class="flex-element section" data-auto="flex-element-section"> <div id="faf33040" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="4aca3327" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop="" data-hidden-on-tablet="" data-hidden-on-mobile=""> <div id="81ceb6f7" class="flex-element group" data-auto="flex-element-group"> <div id="8bf60ab1" class="flex-element group" data-auto="flex-element-group"> <div id="a428f415" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="image" data-external-id="1013097116"> <div class="imageWidget align-center u_1013097116" data-element-type="image" data-widget-type="image" id="1013097116"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/Screen+Shot+2024-10-04+at+4.03.11+PM-1920w.png" alt="Gray placeholder with the words âIMAGE PLACEHOLDERâ centered on a light background" id="1909460419" class="" width="598" height="598" data-dm-image-path="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/Screen+Shot+2024-10-04+at+4.03.11+PM.png" data-hover-effect="zoomout" onerror="handleImageLoadError(this)" loading="lazy"/></div> 1638</div> 1639 <div id="f2b43354" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1631412924"> <div class="dmNewParagraph u_1631412924" data-element-type="paragraph" data-version="5" id="1631412924" style="" data-inject="topicheading13"> <h3><span style="display: unset;">Short title 13</span></h3> 1640</div> 1641</div> 1642 <div id="9857361e" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1973772173"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1973772173" style="" data-inject="topiccontent13"><p><span style="display: unset;">Describe some quality or feature of the company. Write a short paragraph about it and choose an appropriate icon.</span></p></div> 1643</div> 1644</div> 1645 <div id="2f6610a6" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1131203892"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient" file="false" href="/" data-element-type="dButtonLinkId" id="1131203892" data-binding="W3siYmluZGluZ05hbWUiOiJidXR0b25fdGV4dCIsInZhbHVlIjoiU1RBVElDX1BBR0VfQ09MTEVDVElPTi57XCJjblwiOlwiYnV0dG9uc1wiLFwiZm5cIjpcIkxlYXJuIE1vcmVcIn0ifV0=" data-diy-link=""> <span class="iconBg" id="1202924088"> <span class="icon hasFontIcon icon-star" id="1105492306"></span> 1646</span> 1647 <span class="text" id="1157011371" data-diy-text="">LEARN MORE</span> 1648</a> 1649</div> 1650</div> 1651 <div id="cfd2a0a5" class="flex-element group" data-auto="flex-element-group"> <div id="d92a1dc1" class="flex-element group" data-auto="flex-element-group"> <div id="95e5c437" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="image" data-external-id="1612997669"> <div class="imageWidget align-center u_1612997669" data-element-type="image" data-widget-type="image" id="1612997669"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/Screen+Shot+2024-10-04+at+4.03.11+PM-1920w.png" alt="Gray placeholder with the words âIMAGE PLACEHOLDERâ centered on a light background" id="1112877921" class="" width="598" height="598" data-dm-image-path="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/Screen+Shot+2024-10-04+at+4.03.11+PM.png" data-hover-effect="zoomout" onerror="handleImageLoadError(this)" loading="lazy"/></div> 1652</div> 1653 <div id="e3df7ab4" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1921827058"> <div class="dmNewParagraph u_1921827058" data-element-type="paragraph" data-version="5" id="1921827058" style="" data-inject="topicheading14"> <h3><span style="display: unset;">Short title 14</span></h3> 1654</div> 1655</div> 1656 <div id="1a71802f" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1936087525"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1936087525" style="" data-inject="topiccontent14"><p><span style="display: unset;">Describe some quality or feature of the company. Write a short paragraph about it and choose an appropriate icon.</span></p></div> 1657</div> 1658</div> 1659 <div id="4d625200" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1054240479"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient" file="false" href="/" data-element-type="dButtonLinkId" id="1054240479" data-binding="W3siYmluZGluZ05hbWUiOiJidXR0b25fdGV4dCIsInZhbHVlIjoiU1RBVElDX1BBR0VfQ09MTEVDVElPTi57XCJjblwiOlwiYnV0dG9uc1wiLFwiZm5cIjpcIkxlYXJuIE1vcmVcIn0ifV0=" data-diy-link=""> <span class="iconBg" id="1695425282"> <span class="icon hasFontIcon icon-star" id="1046087493"></span> 1660</span> 1661 <span class="text" id="1552831967" data-diy-text="">LEARN MORE</span> 1662</a> 1663</div> 1664</div> 1665 <div id="bd628c30" class="flex-element group" data-auto="flex-element-group"> <div id="b8d30172" class="flex-element group" data-auto="flex-element-group"> <div id="2531cd2c" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="image" data-external-id="1309023037"> <div class="imageWidget align-center u_1309023037" data-element-type="image" data-widget-type="image" id="1309023037"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/Screen+Shot+2024-10-04+at+4.03.11+PM-1920w.png" alt="Gray placeholder with the words âIMAGE PLACEHOLDERâ centered on a light background" id="1197064085" class="" width="598" height="598" data-dm-image-path="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/Screen+Shot+2024-10-04+at+4.03.11+PM.png" data-hover-effect="zoomout" onerror="handleImageLoadError(this)" loading="lazy"/></div> 1666</div> 1667 <div id="94b20f24" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1476244515"> <div class="dmNewParagraph u_1476244515" data-element-type="paragraph" data-version="5" id="1476244515" style="" data-inject="topicheading15"> <h3><span style="display: unset;">Short title 15</span></h3> 1668</div> 1669</div> 1670 <div id="e11a54e7" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1427223207"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1427223207" style="" data-inject="topiccontent15"><p><span style="display: unset;">Describe some quality or feature of the company. Write a short paragraph about it and choose an appropriate icon.</span></p></div> 1671</div> 1672</div> 1673 <div id="bed4f072" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1267350248"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient" file="false" href="/" data-element-type="dButtonLinkId" id="1267350248" data-binding="W3siYmluZGluZ05hbWUiOiJidXR0b25fdGV4dCIsInZhbHVlIjoiU1RBVElDX1BBR0VfQ09MTEVDVElPTi57XCJjblwiOlwiYnV0dG9uc1wiLFwiZm5cIjpcIkxlYXJuIE1vcmVcIn0ifV0=" data-diy-link=""> <span class="iconBg" id="1063045606"> <span class="icon hasFontIcon icon-star" id="1727764501"></span> 1674</span> 1675 <span class="text" id="1750782966" data-diy-text="">LEARN MORE</span> 1676</a> 1677</div> 1678</div> 1679</div> 1680</div> 1681</section> 1682</div> 1683 <div data-flex-id="f31cd5ff" data-auto="flex-section" id="1829356389" data-layout-section="" data-page-element-type="section" data-page-element-id="1688378275"> <div class="flex-widgets-container" id="1748116129"></div> 1684 <section id="5764771c" class="flex-element section" data-auto="flex-element-section"> <div id="ac593d94" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="cf93363d" class="flex-element group" data-auto="flex-element-group"> <div id="da69dd01" class="flex-element group" data-auto="flex-element-group"> <div id="f0c17362" class="flex-element group" data-auto="flex-element-group"> <div id="33274bb5" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1384272310"> <div class="widget-31ea1e dmCustomWidget" data-lazy-load="true" data-title="" id="1384272310" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="31ea1ee9b19c4368abcc1dbd5ec6a0d6" data-widget-version="2" data-widget-config="eyJzb3VyY2VQYWdlVHlwZSI6ImhvbWUiLCJjb3B5QmxvY2tOdW1iZXIiOiIxMCIsImltYWdlSGVpZ2h0IjoiMjAwIiwiYmFja2dyb3VuZFNpemUiOiJjb3ZlciIsImJhY2tncm91bmRQb3NpdGlvbiI6ImNlbnRlciBjZW50ZXIiLCJib3JkZXJSYWR
1684pdXMiOiIwIiwib3ZlcmxheUNvbG9yIjoiIzAwMDAwMCIsIm92ZXJsYXlPcGFjaXR5IjoiMCIsImVuYWJsZUhvdmVyTGlmdCI6ZmFsc2V9"> <div class="cross-collection-image" role="img" aria-busy="true" aria-hidden="true"> <div class="cross-collection-image-overlay" aria-hidden="true"></div> 1685</div> 1686</div> 1687</div> 1688</div> 1689 <div id="87c43c22" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1179537384"> <div class="widget-ab442a dmCustomWidget" data-lazy-load="true" data-title="" id="1179537384" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="ab442ac754384e98a02c4f630b481f5e" data-widget-version="9" data-widget-config="eyJyZXF1aXJlZEZpZWxkTmFtZSI6IkNPUFkgQkxPQ0sgMTAgSEVBRExJTkUiLCJjb2xsZWN0aW9uTmFtZSI6IjAxIEhPTUUifQ=="> <div class="hide-section-if-category-field-empty" data-collection-name="01 HOME" data-required-field="COPY BLOCK 10 HEADLINE" style="display:none;"></div> 1690</div> 1691</div> 1692 <div id="66ced809" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1990949195"> <div class="widget-f19f9b u_1990949195 dmCustomWidget" data-lazy-load="true" data-title="" id="1990949195" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="f19f9b2806104edb81a7816f71967887" data-widget-version="13" data-widget-config="eyJidXR0b25OYW1lIjoiTGVhcm4gTW9yZSIsInNvdXJjZVBhZ2VUeXBlIjoiaG9tZSIsImNvcmVQcmVmaXgiOiJzZXJ2aWNlcyIsImNvcHlCbG9ja051bWJlciI6IjEwIiwiYnV0dG9uUm91dGluZ09wdGlvbnMiOm51bGwsImNhdGVnb3J5UHJlZml4Ijoid2hhdC13ZS1kbyJ9"> <div class="copy-block-link-widget"> <a class="copy-block-link-anchor" aria-label="Learn More" aria-disabled="true" aria-busy="true"> <div class="dmWidget copy-block-link-button"> <span class="text">Learn More</span> 1693 <span class="iconBg"></span> 1694</div> 1695</a> 1696</div> 1697</div> 1698</div> 1699</div> 1700 <div id="95746a2b" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop="" data-hidden-on-tablet="" data-hidden-on-mobile=""> <div id="4507fbf6" class="flex-element group" data-auto="flex-element-group"> <div id="dae1bdaf" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="image" data-external-id="1609539177"> <div class="imageWidget align-center u_1609539177" data-element-type="image" data-widget-type="image" id="1609539177"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/Screen+Shot+2024-10-04+at+4.03.11+PM-1920w.png" alt="Gray placeholder with the words âIMAGE PLACEHOLDERâ centered on a light background" id="1222630083" class="" width="598" height="598" data-dm-image-path="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/Screen+Shot+2024-10-04+at+4.03.11+PM.png" data-hover-effect="zoomout" onerror="handleImageLoadError(this)" loading="lazy"/></div> 1701</div> 1702 <div id="91d5b8cf" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1666308715"> <div class="dmNewParagraph u_1666308715" data-element-type="paragraph" data-version="5" id="1666308715" style="" data-inject="topicheading11"> <h3><span style="display: unset;">Short title 11</span></h3> 1703</div> 1704</div> 1705 <div id="197acacc" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1840006132"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1840006132" style="" data-inject="topiccontent11"><p><span style="display: unset;">Describe some quality or feature of the company. Write a short paragraph about it and choose an appropriate icon.</span></p></div> 1706</div> 1707</div> 1708 <div id="3f44cc34" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1371479025"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient" file="false" href="/" data-element-type="dButtonLinkId" id="1371479025" data-binding="W3siYmluZGluZ05hbWUiOiJidXR0b25fdGV4dCIsInZhbHVlIjoiU1RBVElDX1BBR0VfQ09MTEVDVElPTi57XCJjblwiOlwiYnV0dG9uc1wiLFwiZm5cIjpcIkxlYXJuIE1vcmVcIn0ifV0=" data-diy-link=""> <span class="iconBg" id="1146977392"> <span class="icon hasFontIcon icon-star" id="1691748835"></span> 1709</span> 1710 <span class="text" id="1817295106" data-diy-text="">LEARN MORE</span> 1711</a> 1712</div> 1713</div> 1714 <div id="8239d73b" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop="" data-hidden-on-tablet="" data-hidden-on-mobile=""> <div id="43b5ab23" class="flex-element group" data-auto="flex-element-group"> <div id="97ebc092" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="image" data-external-id="1339545085"> <div class="imageWidget align-center u_1339545085" data-element-type="image" data-widget-type="image" id="1339545085"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/Screen+Shot+2024-10-04+at+4.03.11+PM-1920w.png" alt="Gray placeholder with the words âIMAGE PLACEHOLDERâ centered on a light background" id="1154583417" class="" width="598" height="598" data-dm-image-path="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/Screen+Shot+2024-10-04+at+4.03.11+PM.png" data-hover-effect="zoomout" onerror="handleImageLoadError(this)" loading="lazy"/></div> 1715</div> 1716 <div id="d2790430" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1105759665"> <div class="dmNewParagraph u_1105759665" data-element-type="paragraph" data-version="5" id="1105759665" style="" data-inject="topicheading12"> <h3><span style="display: unset;">Short title 12</span></h3> 1717</div> 1718</div> 1719 <div id="4d7cc87c" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1818143690"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1818143690" style="" data-inject="topiccontent12"><p><span style="display: unset;">Describe some quality or feature of the company. Write a short paragraph about it and choose an appropriate icon.</span></p></div> 1720</div> 1721</div> 1722 <div id="c4fd38ba" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1662232786"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient" file="false" href="/" data-element-type="dButtonLinkId" id="1662232786" data-binding="W3siYmluZGluZ05hbWUiOiJidXR0b25fdGV4dCIsInZhbHVlIjoiU1RBVElDX1BBR0VfQ09MTEVDVElPTi57XCJjblwiOlwiYnV0dG9uc1wiLFwiZm5cIjpcIkxlYXJuIE1vcmVcIn0ifV0=" data-diy-link=""> <span class="iconBg" id="1256060307"> <span class="icon hasFontIcon icon-star" id="1129803738"></span> 1723</span> 1724 <span class="text" id="1881415019" data-diy-text="">LEARN MORE</span> 1725</a> 1726</div> 1727</div> 1728</div> 1729</div> 1730</section> 1731</div> 1732 <div data-auto="flex-section" id="1992317399" data-flex-id="02b965d6" data-layout-section="" data-page-element-type="section" data-page-element-id="1688378275"> <div class="flex-widgets-container" id="1212734502"></div> 1733 <section id="32367343" class="flex-element section" data-auto="flex-element-section"> <div id="5e4e94db" class="flex-element grid lazy" data-auto="flex-element-grid" data-layout-grid="" data-binding="eyJiaW5kaW5nTmFtZSI6ImJhY2tncm91bmQiLCJ2YWx1ZSI6InNpdGVfaW1hZ2VzLnBlcnNpc3RlZC5SZWNlbnQgUmV2aWV3cyBCRyBJbWFnZSJ9" style="background-image: url('data:image/jpeg; base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAHCAYAAAAxrNxjAAAACXBIWXMAAAsTAAALEwEAmpwYAAABDUlEQVQY0wXB20rCcADA4b1PFKkhhR0gnW1G5rJ080AqZcbcH51YaujSUNOCDqQQUnnhXTe9QRfd9Apd+Cy/vk/q3dexRYa6yDLolHgZNelcnzNslZmNH/n9+WY+/0Pq9G2ElaZkJmleFegOBa12nhtH0HNqjJ4emE7fkUxhkDJUjEOZzHGYQjGKVU1yUTvlLJ8mZejE4zEkPSET2fWhBVfRQj50YxurrOM4JpaZQ1V28Lg9SLLiQvEvE1W9ZHWZiohx27W479tUxAmhYIClhUUkJeghrHhJHGxRKhxx1y0y+2gzGTeoV3No+wE21t1Ie/IKEXWNRFSmVs7x+tzg63PA2+QS29bRtE38ARf/JEibYouG9h4AAAAASUVORK5CYII=') !important;" data-background-image="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/recent-reviews-huffs-tree-service-000c5055-1920w.png"> <div id="416ce683" class="flex-element group" data-auto="flex-element-group"> <div id="043a130b" class="flex-element group" data-auto="flex-element-group"> <div id="be21207b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="graphic" data-keep-proportion="true" data-anim-extended="eyJkZXNrdG9wIjp7InRyaWdnZXIiOiJlbnRyYW5jZSIsImFuaW1hdGlvbiI6InJvdGF0ZUluQ29tYm8iLCJkdXJhdGlvbiI6MC41LCJkZWxheSI6MCwiaW50ZW5zaXR5IjowLjQsImRpciI6ImluLXBsYWNlIn19" data-external-id="1769091143"> <div class="graphicWidget graphicWidgetV2 graphicWidgetV3 u_1769091143" data-element-type="graphic" data-widget-type="graphic" id="1769091143"> <svg width="100%" height="100%" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1020566619" class="svg u_1020566619" data-icon-custom="true"> <title id="1139828032">Two overlapping black speech bubbles with horizontal lines, representing a chat or messaging icon</title> 1734 <path d="m31.879 23.465c-1.3789 0-2.5-1.1172-2.5-2.5 0-1.3789 1.1172-2.5 2.5-2.5h17.102c1.3789 0 2.5 1.1172 2.5 2.5 0 1.3789-1.
17341172 2.5-2.5 2.5zm0 7.7617c-1.3789 0-2.5-1.1172-2.5-2.5 0-1.3789 1.1172-2.5 2.5-2.5h34.203c1.3789 0 2.5 1.1172 2.5 2.5 0 1.3789-1.1172 2.5-2.5 2.5zm0 7.7656c-1.3789 0-2.5-1.1172-2.5-2.5 0-1.3789 1.1172-2.5 2.5-2.5h34.203c1.3789 0 2.5 1.1172 2.5 2.5 0 1.3789-1.1172 2.5-2.5 2.5zm-14.008-0.25391h-8.9336c-0.36719 0-0.69141 0.14453-0.92969 0.37891-0.23047 0.23828-0.37891 0.56641-0.37891 0.92578v36.266c0 0.36328 0.14453 0.69141 0.37891 0.92969 0.23828 0.23047 0.57031 0.37891 0.92969 0.37891h3.2383c1.3789 0 2.5 1.1172 2.5 2.5v9.2773c0 0.28516 0.074219 0.54297 0.21094 0.74219 0.13672 0.20703 0.34375 0.37109 0.60156 0.47656 0.26172 0.10547 0.53516 0.12891 0.77734 0.078125 0.23828-0.050781 0.46875-0.17969 0.66016-0.38281l10.348-10.754c0.60156-0.62891 1.2969-1.1055 2.0664-1.4336 0.77734-0.33203 1.6055-0.5 2.4727-0.5h26.723c0.35547 0 0.6875-0.14844 0.92188-0.38281l0.070313-0.070312c0.19531-0.22656 0.3125-0.52734 0.3125-0.85547v-3.0938h-18.383c-1.7383 0-3.3164-0.70703-4.4531-1.8516-1.1406-1.1406-1.8516-2.7188-1.8516-4.4531v-2.043c-0.78125 0.62891-1.6758 1.0508-2.6172 1.25-1.1953 0.25391-2.4609 0.14844-3.6641-0.33203-1.1133-0.44531-2.0391-1.1719-2.7188-2.0859l-0.16797-0.22266c-0.69141-1.0195-1.0703-2.2344-1.0703-3.5352v-6.7773h-0.73437c-1.7383 0-3.3164-0.70703-4.457-1.8516-1.1406-1.1484-1.8516-2.7266-1.8516-4.4531zm-8.9336-5h8.9336v-23.145c0-1.6445 0.64453-3.1523 1.6914-4.2852l0.16016-0.17578c1.1445-1.1445 2.7227-1.8516 4.457-1.8516h49.605c1.7383 0 3.3164 0.70703 4.4531 1.8516 1.1445 1.1445 1.8516 2.7188 1.8516 4.4531v13.742h10.973c1.7383 0 3.3164 0.70703 4.457 1.8516l0.16016 0.17578c1.0508 1.1289 1.6914 2.6367 1.6914 4.2852v36.266c0 1.7305-0.71484 3.3086-1.8594 4.4531-1.1445 1.1406-2.7188 1.8516-4.4492 1.8516h-0.73438v6.7812c0 1.3008-0.38281 2.5117-1.0703 3.5352-0.68359 1.0156-1.6719 1.8203-2.8906 2.3086-1.207 0.48437-2.4766 0.58984-3.668 0.32812-1.1992-0.25391-2.3203-0.87109-3.2227-1.8086l-10.344-10.75c-0.13672-0.14062-0.27734-0.24219-0.42969-0.30469-0.13672-0.058593-0.3125-0.089843-0.51953-0.089843h-3.3477v3.0938c0 1.6484-0.64453 3.1602-1.6953 4.2852l-0.15625 0.17188c-1.1445 1.1445-2.7227 1.8516-4.4531 1.8516h-26.723c-0.21094 0-0.38281 0.03125-0.52344 0.085938-0.14844 0.058593-0.28906 0.16016-0.42969 0.30469l-10.348 10.754c-0.89844 0.9375-2.0195 1.5547-3.2188 1.8086-1.1953 0.25391-2.4648 0.15234-3.668-0.33203-1.2148-0.48828-2.2031-1.3008-2.8906-2.3086-0.69141-1.0195-1.0703-2.2383-1.0703-3.5352v-6.7773h-0.73828c-1.7383 0-3.3164-0.70703-4.457-1.8516-1.1445-1.1523-1.8516-2.7266-1.8516-4.457v-36.266c0-1.7383 0.70703-3.3164 1.8516-4.4531 1.1523-1.1406 2.7266-1.8516 4.457-1.8516zm82.133-4.3984h-10.973v17.523c0 1.7383-0.70703 3.3164-1.8516 4.4531-1.1445 1.1445-2.7227 1.8516-4.4531 1.8516h-26.73c-0.20703 0-0.38281 0.03125-0.51953 0.085937-0.14844 0.0625-0.29297 0.16797-0.42969 0.30469l-5.9492 6.1836v7.168c0 0.35547 0.14844 0.68359 0.38281 0.92188 0.23828 0.23828 0.5625 0.38281 0.92188 0.38281h26.734c0.86719 0 1.6953 0.16797 2.4727 0.5 0.76562 0.32422 1.4609 0.80859 2.0664 1.4414l10.344 10.75c0.19141 0.19922 0.42187 0.32812 0.66406 0.38281 0.24609 0.050782 0.51562 0.03125 0.77734-0.074218 0.25391-0.10156 0.46094-0.26953 0.60156-0.47656 0.13672-0.19922 0.21094-0.45703 0.21094-0.74219v-9.2773c0-1.3789 1.1172-2.5 2.5-2.5h3.2383c0.36719 0 0.69531-0.14844 0.93359-0.38281 0.23047-0.22656 0.375-0.55859 0.375-0.92188v-36.266c0-0.32813-0.11719-0.625-0.30469-0.84766l-0.078125-0.074219c-0.23828-0.23828-0.5625-0.38281-0.92578-0.38281zm-55.344 27.824 6.793-7.0586c0.60938-0.63281 1.3047-1.1172 2.0664-1.4414 0.77734-0.32812 1.6055-0.49609 2.4727-0.49609h26.73c0.35547 0 0.6875-0.14844 0.92188-0.38281 0.23828-0.23828 0.38281-0.5625 0.38281-0.92188v-36.266c0-0.35938-0.14844-0.6875-0.38281-0.92188-0.23828-0.23828-0.5625-0.38281-0.92188-0.38281h-49.605c-0.35938 0-0.69141 0.14844-0.92578 0.38281l-0.078124 0.074219c-0.1875 0.22266-0.30469 0.52344-0.30469 0.84766v36.266c0 0.36719 0.14453 0.69141 0.375 0.92188 0.24609 0.23828 0.57422 0.38281 0.93359 0.38281h3.2383c1.3789 0 2.5 1.1172 2.5 2.5v9.2773c0 0.28516 0.074219 0.53906 0.21094 0.74219l0.058594 0.089844c0.13281 0.16016 0.31641 0.28906 0.54297 0.38281 0.26172 0.10547 0.53125 0.13281 0.77344 0.078125 0.23828-0.050781 0.47266-0.17969 0.66406-0.38281z"></path> 1735</svg> 1736</div> 1737</div> 1738 <div id="79911bf3" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1932763955"> <div class="dmNewParagraph u_1932763955" data-element-type="paragraph" data-version="5" id="1932763955" style="" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJzaXRlX3RleHQucmVjZW50IHJldmlld3MgbGVhZC1pbiB0ZXh0In1d"> <h3 class="m-text-align-left" id="1265283664"><span style="color: var(--color_2); display: unset;" id="1690589552">Here's what our satisfied customers are saying...</span></h3> 1739</div> 1740</div> 1741 <div id="2cc5b3d3" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1619087257"> <div class="u_1619087257 dmNewParagraph" data-element-type="paragraph" data-version="5" id="1619087257" data-diy-text="" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJzaXRlX3RleHQuaG9tZSAvIGNhdCByZWNlbnQgcmV2aWV3cyB0ZXh0In1d" style=""><p class="rteBlock">At Huff's Tree Service, we take pride in providing exceptional tree, turf, and plant health services to our customers. We would be grateful if you could share your thoughts about our family-owned business with others. Your feedback helps us improve and helps others make informed decisions. Please take a moment to <a value="reviews" label="" type="page" href="/reviews" data-runtime-url="/reviews">leave a review</a> 1742of Huff's Tree Service and let others know what you think.</p></div> 1743</div> 1744</div> 1745 <div id="878b0320" class="flex-element group" data-auto="flex-element-group"> <div id="f9fdd538" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1376450106"> <div class="widget-328e6f u_1376450106 dmCustomWidget" data-lazy-load="true" data-title="" id="1376450106" dmle_extension="custom_extension" data-element-type="custom_extension" data-binding="W3siYmluZGluZ05hbWUiOiJtZXJjaGFudElkIiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCJSZXZpZXdzIFdpZGdldHNcIixcImZuXCI6XCJNZXJjaGFudCBJRFwifSJ9XQ==" icon="false" surround="false" data-widget-id="328e6f1fbcec4101ac4f8d9184710a14" data-widget-version="7" data-widget-config="eyJtZXJjaGFudElkIjoiODAzNzMiLCJEYXRhTGluZXMiOiIyIiwiRGF0YU51bSI6IjIiLCJUcnVuY2F0ZURlc3QiOiIvcmV2aWV3cyIsIkRhdGFUaGlyZFBhcnR5IjoidHJ1ZSIsIkRhdGFSYW5kb21pemUiOiJmYWxzZSIsInJldi1kYXJrIjp0cnVlfQ=="> <div id="recentReviewsWidget" class="rev-dark fb-dark" data-lines="2" data-num="2" data-truncate-dest="/reviews" data-randomize="false" data-third-party="true" data-merchant="80373"></div> 1746</div> 1747</div> 1748</div> 1749</div> 1750</div> 1751</section> 1752</div> 1753 <div data-layout-section="" data-auto="flex-section" id="1687617940" data-flex-id="ee379015" data-page-element-type="section" data-page-element-id="1688378275"> <div class="flex-widgets-container" id="1252936045"></div> 1754 <section id="59fff7bf" class="flex-element section" data-auto="flex-element-section"> <div id="40bf71df" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="2e3386d5" class="flex-element group" data-auto="flex-element-group"> <div id="5d62f936" class="flex-element group" data-auto="flex-element-group"> <div id="e7b41ab5" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1739956793"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1739956793" style=""> <h2 class="text-align-center"><span style="display: initial;">Recent Projects</span></h2> 1755</div> 1756</div> 1757 <div id="89eb49e3" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="photoGallery" data-external-id="1597270632"> <div class="dmPhotoGallery newPhotoGallery dmPhotoGalleryResp u_1597270632 photo-gallery-done text-layout-over captionAlignment-center_center photoGallery" galleryoptionsparams="{thumbnailsPerRow: 3, rowsToShow: 3, imageScaleMethod: true}" data-desktop-layout="square" data-desktop-columns="3" data-element-type="dPhotoGalleryId" data-desktop-text-layout="over" id="1597270632" data-placeholder="false" data-image-hover-effect="shine" data-image-animation="none" data-rows-to-show="100"> <div class="dmPhotoGalleryHolder clearfix gallery shadowEffectToChildren gallery4inArow" id="1362986591"></div> 1758 <div class="layout-container square"> <div class="photogallery-row " data-index=""> <div class="photogallery-column column-3" data-index="0"> <div index="0" class="photoGalleryThumbs animated " data-index="0"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Worker cutting a huge fallen tree trunk with a chainsaw and excavator claw nearby" data-dm-force-device="mobile" class="u_1896826704" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-30-huffs-tree-service.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-30-huffs-tree-service-640w.jpg');"><img id="1042696941" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-30-huffs-tree-service-1920w.jpg" alt="Worker cutting a huge fallen tree trunk with a chainsaw and excavator claw nearby" aria-label="Worker cutting a huge fallen tree trunk with a chainsaw and excavator claw nearby" onerror="handleImageLoadError(this)" loading="lazy"/></a> 1759</div> 1760 <div id="1186714277" class="caption-container u_1186714277" style="display:none"> <span class="caption-inner"> <a id="1883581607" class="caption-button dmWidget clearfix u_1883581607" data-auto="c
1760aption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1761</span> 1762 <span class="text" data-auto="button-text">Button</span> 1763</a> 1764</span> 1765</div> 1766</div> 1767</div> 1768</div> 1769 <div class="photogallery-column column-3" data-index="1"> <div index="1" class="photoGalleryThumbs animated " data-index="1"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Yellow tree service sign on a porch, with flowers and a sunny garden in the background." data-dm-force-device="mobile" class="u_1822930435" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-25-huffs-tree-service-939bf898.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-25-huffs-tree-service-939bf898-640w.jpg');"><img id="1272806098" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-25-huffs-tree-service-939bf898-1920w.jpg" alt="Yellow tree service sign on a porch, with flowers and a sunny garden in the background." aria-label="Yellow tree service sign on a porch, with flowers and a sunny garden in the background." onerror="handleImageLoadError(this)" loading="lazy"/></a> 1770</div> 1771 <div id="1275251725" class="caption-container u_1275251725" style="display:none"> <span class="caption-inner"> <a id="1797076964" class="caption-button dmWidget clearfix u_1797076964" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1772</span> 1773 <span class="text" data-auto="button-text">Button</span> 1774</a> 1775</span> 1776</div> 1777</div> 1778</div> 1779</div> 1780 <div class="photogallery-column column-3" data-index="2"> <div index="2" class="photoGalleryThumbs animated " data-index="2"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Tree worker in red harness trims a large tree beside a house on a sunny day." data-dm-force-device="mobile" class="u_1437371866" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-20-huffs-tree-service-414f6d8a.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-20-huffs-tree-service-414f6d8a-640w.jpg');"><img id="1723044074" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-20-huffs-tree-service-414f6d8a-1920w.jpg" alt="Tree worker in red harness trims a large tree beside a house on a sunny day." aria-label="Tree worker in red harness trims a large tree beside a house on a sunny day." onerror="handleImageLoadError(this)" loading="lazy"/></a> 1781</div> 1782 <div id="1587623695" class="caption-container u_1587623695" style="display:none"> <span class="caption-inner"> <a id="1233357252" class="caption-button dmWidget clearfix u_1233357252" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1783</span> 1784 <span class="text" data-auto="button-text">Button</span> 1785</a> 1786</span> 1787</div> 1788</div> 1789</div> 1790</div> 1791</div> 1792 <div class="photogallery-row " data-index=""> <div class="photogallery-column column-3" data-index="3"> <div index="3" class="photoGalleryThumbs animated " data-index="3"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Tree service crew trimming a large tree with a crane truck in a leafy yard" data-dm-force-device="mobile" class="u_1751739895" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-24-huffs-tree-service-0d524ef8.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-24-huffs-tree-service-0d524ef8-64
17920w.jpg');"><img id="1408572759" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-24-huffs-tree-service-0d524ef8-1920w.jpg" alt="Tree service crew trimming a large tree with a crane truck in a leafy yard" aria-label="Tree service crew trimming a large tree with a crane truck in a leafy yard" onerror="handleImageLoadError(this)" loading="lazy"/></a> 1793</div> 1794 <div id="1013434758" class="caption-container u_1013434758" style="display:none"> <span class="caption-inner"> <a id="1985142910" class="caption-button dmWidget clearfix u_1985142910" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1795</span> 1796 <span class="text" data-auto="button-text">Button</span> 1797</a> 1798</span> 1799</div> 1800</div> 1801</div> 1802</div> 1803 <div class="photogallery-column column-3" data-index="4"> <div index="4" class="photoGalleryThumbs animated " data-index="4"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Man in neon shirt on red snowmobile amid storm debris in a damaged residential yard" data-dm-force-device="mobile" class="u_1761807831" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-29-huffs-tree-service.png" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-29-huffs-tree-service-640w.png');"><img id="1924557144" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-29-huffs-tree-service-1920w.png" alt="Man in neon shirt on red snowmobile amid storm debris in a damaged residential yard" aria-label="Man in neon shirt on red snowmobile amid storm debris in a damaged residential yard" onerror="handleImageLoadError(this)" loading="lazy"/></a> 1804</div> 1805 <div id="1902722463" class="caption-container u_1902722463" style="display:none"> <span class="caption-inner"> <a id="1874933706" class="caption-button dmWidget clearfix u_1874933706" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1806</span> 1807 <span class="text" data-auto="button-text">Button</span> 1808</a> 1809</span> 1810</div> 1811</div> 1812</div> 1813</div> 1814 <div class="photogallery-column column-3" data-index="5"> <div index="5" class="photoGalleryThumbs animated " data-index="5"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Worker in neon safety shirt and ear protection walking along a landscaped roadside path." data-dm-force-device="mobile" class="u_1671248154" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-23-huffs-tree-service.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-23-huffs-tree-service-640w.jpg');"><img id="1234747362" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-23-huffs-tree-service-1920w.jpg" alt="Worker in neon safety shirt and ear protection walking along a landscaped roadside path." aria-label="Worker in neon safety shirt and ear protection walking along a landscaped roadside path." onerror="handleImageLoadError(this)" loading="lazy"/></a> 1815</div> 1816 <div id="1337898252" class="caption-container u_1337898252" style="display:none"> <span class="caption-inner"> <a id="1154515060" class="caption-button dmWidget clearfix u_1154515060" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1817</span> 1818 <span class="text" data-auto="button-text">Button</span> 1819</a> 1820</span> 1821</div> 1822</div> 1823</div> 1824</div> 1825</div> 1826 <div class="photogallery-row " data-index=""> <div class="photogallery-column column-3" data-index="6"> <div index="6" class="photoGalleryThumbs animated " data-index="6"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Worker operating a red wood chipper trimming a fallen tree on a leafy roadside" data-dm-force-device="mobile" class="u_1579942053" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-22-huffs-tree-service-69240c23.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-22-huffs-tree-service-69240c23-640w.jpg');"><img id="1160246714" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-22-huffs-tree-service-69240c23-1920w.jpg" alt="Worker operating a red wood chipper trimming a fallen tree on a leafy roadside" aria-label="Worker operating a red wood chipper trimming a fallen tree on a leafy roadside" onerror="handleImageLoadError(this)" loading="lazy"/></a> 1827</div> 1828 <div id="1042099899" class="caption-container u_1042099899" style="display:none"> <span class="caption-inner"> <a id="1703754410" class="caption-button dmWidget clearfix u_1703754410" data-auto="c
1828aption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1829</span> 1830 <span class="text" data-auto="button-text">Button</span> 1831</a> 1832</span> 1833</div> 1834</div> 1835</div> 1836</div> 1837 <div class="photogallery-column column-3" data-index="7"> <div index="7" class="photoGalleryThumbs animated " data-index="7"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Two workers in helmets watching a red drone above dense green trees" data-dm-force-device="mobile" class="u_1984721525" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-31-huffs-tree-service.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-31-huffs-tree-service-640w.jpg');"><img id="1368064380" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-31-huffs-tree-service-1920w.jpg" alt="Two workers in helmets watching a red drone above dense green trees" aria-label="Two workers in helmets watching a red drone above dense green trees" onerror="handleImageLoadError(this)" loading="lazy"/></a> 1838</div> 1839 <div id="1617208877" class="caption-container u_1617208877" style="display:none"> <span class="caption-inner"> <a id="1283982770" class="caption-button dmWidget clearfix u_1283982770" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1840</span> 1841 <span class="text" data-auto="button-text">Button</span> 1842</a> 1843</span> 1844</div> 1845</div> 1846</div> 1847</div> 1848 <div class="photogallery-column column-3" data-index="8"> <div index="8" class="photoGalleryThumbs animated " data-index="8"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Crane trimming a tall tree beside a house under a clear blue sky" data-dm-force-device="mobile" class="u_1862371909" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-32-huffs-tree-service.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-32-huffs-tree-service-640w.jpg');"><img id="1597818908" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-32-huffs-tree-service-1920w.jpg" alt="Crane trimming a tall tree beside a house under a clear blue sky" aria-label="Crane trimming a tall tree beside a house under a clear blue sky" onerror="handleImageLoadError(this)" loading="lazy"/></a> 1849</div> 1850 <div id="1901751267" class="caption-container u_1901751267" style="display:none"> <span class="caption-inner"> <a id="1112240752" class="caption-button dmWidget clearfix u_1112240752" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1851</span> 1852 <span class="text" data-auto="button-text">Button</span> 1853</a> 1854</span> 1855</div> 1856</div> 1857</div> 1858</div> 1859</div> 1860</div> 1861</div> 1862</div> 1863 <div id="5042981a" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1956183133"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton" file="false" href="/gallery" data-element-type="dButtonLinkId" id="1956183133" data-binding="W3siYmluZGluZ05hbWUiOiJsaW5rIiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCJidXR0b25zXCIsXCJmblwiOlwiTW9yZSBQcm9qZWN0cyBMaW5rXCJ9In0seyJiaW5kaW5nTmFtZSI6ImJ1dHRvbl90ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCJidXR0b25zXCIsXCJmblwiOlwiTW9yZSBQcm9qZWN0cyBCdXR0b25cIn0ifV0=" data-diy-link=""> <span class="iconBg" aria-hidden="true" id="1652566852"> <span class="icon hasFontIcon icon-star" id="1805244174"></span> 1864</span> 1865 <span class="text" id="1252513038" data-diy-text="">VIEW MORE PROJECTS</span> 1866</a> 1867</div> 1868</div> 1869</div> 1870</div> 1871</section> 1872</div> 1873 <div data-layout-section="" data-auto="flex-section" id="1943914339" data-flex-id="105b4d22" data-page-element-type="section" data-page-element-id="1688378275" class="" data-hidden-on-tablet="true"> <div class="flex-widgets-container" id="1067715770"></div> 1874 <section id="8afa3dd4" class="flex-element section" data-auto="flex-element-section"> <div id="c7868586" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="f41605eb" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop="" data-hidden-on-tablet="" data-hidden-on-mobile=""> <div id="fa881aa5" class="flex-element group" data-auto="flex-element-group"> <div id="433db674" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1779710744"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1779710744" style=""> <h2 class="text-align-left"><span style="display: initial;">Recent Projects</span></h2> 1875</div> 1876</div> 1877 <div id="887b741a" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="photoGallery" data-external-id="1336996153"> <div class="dmPhotoGallery newPhotoGallery dmPhotoGalleryResp u_1336996153 photo-gallery-done text-layout-over captionAlignment-center_center photoGallery" galleryoptionsparams="{thumbnailsPerRow: 3, rowsToShow: 3, imageScaleMethod: true}" data-desktop-layout="square" data-desktop-columns="4" data-element-type="dPhotoGalleryId" data-desktop-text-layout="over" id="1336996153" data-placeholder="false" data-image-hover-effect="zoomout" data-image-animation="none" data-rows-to-show="100"> <div class="dmPhotoGalleryHolder clearfix gallery shadowEffectToChildren gallery4inArow" id="1362986591"></div> 1878 <div class="layout-container square"> <div class="photogallery-row " data-index=""> <div class="photogallery-column column-4" data-index="0"> <div index="0" class="photoGalleryThumbs animated " data-index="0"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Red boom lift trimming tall trees beside a house under a blue sky." data-dm-force-device="mobile" class="u_1165883154" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-01-huffs-tree-service.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-01-huffs-tree-service-640w.jpg');"><img id="1512376753" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-01-huffs-tree-service-1920w.jpg" alt="Red boom lift trimming tall trees beside a house under a blue sky." aria-label="Red boom lift trimming tall trees beside a house under a blue sky." onerror="handleImageLoadError(this)" loading="lazy"/></a> 1879</div> 1880 <div id="1407306424" class="caption-container u_1407306424" style="display:none"> <span class="caption-inner"> <a id="1724617841" class="caption-button dmWidget clearfix u_1724617841" data-auto="c
1880aption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1881</span> 1882 <span class="text" data-auto="button-text">Button</span> 1883</a> 1884</span> 1885</div> 1886</div> 1887</div> 1888</div> 1889 <div class="photogallery-column column-4" data-index="1"> <div index="1" class="photoGalleryThumbs animated " data-index="1"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Person climbing a tree with safety ropes and gear, viewed from below" data-dm-force-device="mobile" class="u_1939262037" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-02-huffs-tree-service.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-02-huffs-tree-service-640w.jpg');"><img id="1838088320" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-02-huffs-tree-service-1920w.jpg" alt="Person climbing a tree with safety ropes and gear, viewed from below" aria-label="Person climbing a tree with safety ropes and gear, viewed from below" onerror="handleImageLoadError(this)" loading="lazy"/></a> 1890</div> 1891 <div id="1064067814" class="caption-container u_1064067814" style="display:none"> <span class="caption-inner"> <a id="1520987077" class="caption-button dmWidget clearfix u_1520987077" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1892</span> 1893 <span class="text" data-auto="button-text">Button</span> 1894</a> 1895</span> 1896</div> 1897</div> 1898</div> 1899</div> 1900 <div class="photogallery-column column-4" data-index="2"> <div index="2" class="photoGalleryThumbs animated " data-index="2"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Worker in neon vest and red hard hat cutting branches near a wooden shed in a yard" data-dm-force-device="mobile" class="u_1470634859" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-03-huffs-tree-service.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-03-huffs-tree-service-640w.jpg');"><img id="1909171507" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-03-huffs-tree-service-1920w.jpg" alt="Worker in neon vest and red hard hat cutting branches near a wooden shed in a yard" aria-label="Worker in neon vest and red hard hat cutting branches near a wooden shed in a yard" onerror="handleImageLoadError(this)" loading="lazy"/></a> 1901</div> 1902 <div id="1262000244" class="caption-container u_1262000244" style="display:none"> <span class="caption-inner"> <a id="1874579247" class="caption-button dmWidget clearfix u_1874579247" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1903</span> 1904 <span class="text" data-auto="button-text">Button</span> 1905</a> 1906</span> 1907</div> 1908</div> 1909</div> 1910</div> 1911 <div class="photogallery-column column-4" data-index="3"> <div index="3" class="photoGalleryThumbs animated " data-index="3"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Tree worker in a bright green jacket climbing with ropes among pine branches" data-dm-force-device="mobile" class="u_1332205506" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-04-huffs-tree-service.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-04-huffs-tree-service-640w.jpg');"><img id="1415182875" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-04-huffs-tree-service-1920w.jpg" alt="Tree worker in a bright green jacket climb
1911ing with ropes among pine branches" aria-label="Tree worker in a bright green jacket climbing with ropes among pine branches" onerror="handleImageLoadError(this)" loading="lazy"/></a> 1912</div> 1913 <div id="1285382354" class="caption-container u_1285382354" style="display:none"> <span class="caption-inner"> <a id="1788543554" class="caption-button dmWidget clearfix u_1788543554" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1914</span> 1915 <span class="text" data-auto="button-text">Button</span> 1916</a> 1917</span> 1918</div> 1919</div> 1920</div> 1921</div> 1922</div> 1923 <div class="photogallery-row " data-index=""> <div class="photogallery-column column-4" data-index="4"> <div index="4" class="photoGalleryThumbs animated " data-index="4"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Person in climbing gear suspended between tree trunks against a blue sky" data-dm-force-device="mobile" class="u_1578866595" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-05-huffs-tree-service.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-05-huffs-tree-service-640w.jpg');"><img id="1072061042" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-05-huffs-tree-service-1920w.jpg" alt="Person in climbing gear suspended between tree trunks against a blue sky" aria-label="Person in climbing gear suspended between tree trunks against a blue sky" onerror="handleImageLoadError(this)" loading="lazy"/></a> 1924</div> 1925 <div id="1707524086" class="caption-container u_1707524086" style="display:none"> <span class="caption-inner"> <a id="1974175673" class="caption-button dmWidget clearfix u_1974175673" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1926</span> 1927 <span class="text" data-auto="button-text">Button</span> 1928</a> 1929</span> 1930</div> 1931</div> 1932</div> 1933</div> 1934 <div class="photogallery-column column-4" data-index="5"> <div index="5" class="photoGalleryThumbs animated " data-index="5"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Two arborists trimming a large tree beside a house and fence" data-dm-force-device="mobile" class="u_1864941518" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-06-huffs-tree-service.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-06-huffs-tree-service-640w.jpg');"><img id="1449042184" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-06-huffs-tree-service-1920w.jpg" alt="Two arborists trimming a large tree beside a house and fence" aria-label="Two arborists trimming a large tree beside a house and fence" onerror="handleImageLoadError(this)" loading="lazy"/></a> 1935</div> 1936 <div id="1719460308" class="caption-container u_1719460308" style="display:none"> <span class="caption-inner"> <a id="1025893570" class="caption-button dmWidget clearfix u_1025893570" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1937</span> 1938 <span class="text" data-auto="button-text">Button</span> 1939</a> 1940</span> 1941</div> 1942</div> 1943</div> 1944</div> 1945 <div class="photogallery-column column-4" data-index="6"> <div index="6" class="photoGalleryThumbs animated " data-index="6"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Person in a green jacket climbing a tree above a house roof." data-dm-force-device="mobile" class="u_1643004667" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-07-huffs-tree-service.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-07-huffs-tree-service-640w.jpg');"><img id="1453704456" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-07-huffs-tree-service-1920w.jpg" alt="Person in a green jacket climb
1945ing a tree above a house roof." aria-label="Person in a green jacket climbing a tree above a house roof." onerror="handleImageLoadError(this)" loading="lazy"/></a> 1946</div> 1947 <div id="1249036464" class="caption-container u_1249036464" style="display:none"> <span class="caption-inner"> <a id="1223264956" class="caption-button dmWidget clearfix u_1223264956" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1948</span> 1949 <span class="text" data-auto="button-text">Button</span> 1950</a> 1951</span> 1952</div> 1953</div> 1954</div> 1955</div> 1956 <div class="photogallery-column column-4" data-index="7"> <div index="7" class="photoGalleryThumbs animated " data-index="7"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Person using a chainsaw to cut a fallen tree trunk outdoors" data-dm-force-device="mobile" class="u_1479903290" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/gallery-08-huffs-tree-service.jpg" style="background-image: url('https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-08-huffs-tree-service-640w.jpg');"><img id="1991779193" data-src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/gallery-08-huffs-tree-service-1920w.jpg" alt="Person using a chainsaw to cut a fallen tree trunk outdoors" aria-label="Person using a chainsaw to cut a fallen tree trunk outdoors" onerror="handleImageLoadError(this)" loading="lazy"/></a> 1957</div> 1958 <div id="1440773630" class="caption-container u_1440773630" style="display:none"> <span class="caption-inner"> <a id="1364199003" class="caption-button dmWidget clearfix u_1364199003" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 1959</span> 1960 <span class="text" data-auto="button-text">Button</span> 1961</a> 1962</span> 1963</div> 1964</div> 1965</div> 1966</div> 1967</div> 1968</div> 1969</div> 1970</div> 1971 <div id="cc48b184" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1343909481"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton" file="false" href="/gallery" data-element-type="dButtonLinkId" id="1343909481" data-binding="W3siYmluZGluZ05hbWUiOiJsaW5rIiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCJidXR0b25zXCIsXCJmblwiOlwiTW9yZSBQcm9qZWN0cyBMaW5rXCJ9In0seyJiaW5kaW5nTmFtZSI6ImJ1dHRvbl90ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCJidXR0b25zXCIsXCJmblwiOlwiTW9yZSBQcm9qZWN0cyBCdXR0b25cIn0ifV0=" data-diy-link=""> <span class="iconBg" aria-hidden="true" id="1305295675"> <span class="icon hasFontIcon icon-star" id="1842153144"></span> 1972</span> 1973 <span class="text" id="1756495280" data-diy-text="">VIEW MORE PROJECTS</span> 1974</a> 1975</div> 1976</div> 1977</div> 1978</div> 1979</section> 1980</div> 1981 <div data-flex-id="962d1693" data-auto="flex-section" id="1055256788" data-layout-section="" data-page-element-type="section" data-page-element-id="1688378275" class="" data-hidden-on-tablet="true" data-hidden-on-mobile="true" data-hidden-on-desktop="true"> <div class="flex-widgets-container" id="1098463775"></div> 1982 <section id="470ece07" class="flex-element section" data-auto="flex-element-section"> <div id="ace36cc1" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="bc3e1e75" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop="" data-hidden-on-tablet="" data-hidden-on-mobile=""> <div id="be0780ee" class="flex-element group" data-auto="flex-element-group"> <div id="f33e681e" class="flex-element group" data-auto="flex-element-group"> <div id="74e954e5" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="image" data-external-id="1240178443"> <div class="imageWidget align-center u_1240178443" data-element-type="image" data-widget-type="image" id="1240178443"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/Screen+Shot+2024-10-04+at+4.03.11+PM-1920w.png" alt="Gray placeholder with the words âIMAGE PLACEHOLDERâ centered on a light background" id="1120693705" class="" width="598" height="598" data-dm-image-path="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/Screen+Shot+2024-10-04+at+4.03.11+PM.png" data-hover-effect="zoomout" onerror="handleImageLoadError(this)" loading="lazy"/></div> 1983</div> 1984 <div id="b9bdc61f" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1739243320"> <div class="dmNewParagraph u_1739243320" data-element-type="paragraph" data-version="5" id="1739243320" style="" data-inject="topicheading13"> <h3><span style="display: unset;">Short title 13</span></h3> 1985</div> 1986</div> 1987 <div id="f4d0fb72" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1747031047"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1747031047" style="" data-inject="topiccontent13"><p><span style="display: unset;">Describe some quality or feature of the company. Write a short paragraph about it and choose an appropriate icon.</span></p></div> 1988</div> 1989</div> 1990 <div id="e25abd91" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1510779992"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient" file="false" href="/" data-element-type="dButtonLinkId" id="1510779992" data-binding="W3siYmluZGluZ05hbWUiOiJidXR0b25fdGV4dCIsInZhbHVlIjoiU1RBVElDX1BBR0VfQ09MTEVDVElPTi57XCJjblwiOlwiYnV0dG9uc1wiLFwiZm5cIjpcIkxlYXJuIE1vcmVcIn0ifV0=" data-diy-link=""> <span class="iconBg" id="1906282528"> <span class="icon hasFontIcon icon-star" id="1011758277"></span> 1991</span> 1992 <span class="text" id="1300066812" data-diy-text="">LEARN MORE</span> 1993</a> 1994</div> 1995</div> 1996 <div id="e429ca1a" class="flex-element group" data-auto="flex-element-group"> <div id="71fc29cf" class="flex-element group" data-auto="flex-element-group"> <div id="ee744b36" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="image" data-external-id="1075363601"> <div class="imageWidget align-center u_1075363601" data-element-type="image" data-widget-type="image" id="1075363601"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/Screen+Shot+2024-10-04+at+4.03.11+PM-1920w.png" alt="Gray placeholder with the words âIMAGE PLACEHOLDERâ centered on a light background" id="1795974902" class="" width="598" height="598" data-dm-image-path="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/Screen+Shot+2024-10-04+at+4.03.11+PM.png" data-hover-effect="zoomout" onerror="handleImageLoadError(this)" loading="lazy"/></div> 1997</div> 1998 <div id="32ada83b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1016321302"> <div class="dmNewParagraph u_1016321302" data-element-type="paragraph" data-version="5" id="1016321302" style="" data-inject="topicheading14"> <h3><span style="display: unset;">Short title 14</span></h3> 1999</div> 2000</div> 2001 <div id="66755e5c" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1720456551"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1720456551" style="" data-inject="topiccontent14"><p><span style="display: unset;">Describe some quality or feature of the company. Write a short paragraph about it and choose an appropriate icon.</span></p></div> 2002</div> 2003</div> 2004 <div id="68b2ac2a" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1177694567"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient" file="false" href="/" data-element-type="dButtonLinkId" id="1177694567" data-binding="W3siYmluZGluZ05hbWUiOiJidXR0b25fdGV4dCIsInZhbHVlIjoiU1RBVElDX1BBR0VfQ09MTEVDVElPTi57XCJjblwiOlwiYnV0dG9uc1wiLFwiZm5cIjpcIkxlYXJuIE1vcmVcIn0ifV0=" data-diy-link=""> <span class="iconBg" id="1164057418"> <span class="icon hasFontIcon icon-star" id="1106698230"></span> 2005</span> 2006 <span class="text" id="1818615599" data-diy-text="">LEARN MORE</span> 2007</a> 2008</div> 2009</div> 2010 <div id="0d97b47b" class="flex-element group" data-auto="flex-element-group"> <div id="8ffccd7d" class="flex-element group" data-auto="flex-element-group"> <div id="73cd90f9" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="image" data-external-id="1377724207"> <div class="imageWidget align-center u_1377724207" data-element-type="image" data-widget-type="image" id="1377724207"><img src="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/Screen+Shot+2024-10-04+at+4.03.11+PM-1920w.png" alt="Gray placeholder with the words âIMAGE PLACEHOLDERâ centered on a light background" id="1732989163" class="" width="598" height="598" data-dm-image-path="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/Screen+Shot+2024-10-04+at+4.03.11+PM.png" data-hover-effect="zoomout" onerror="handleImageLoadError(this)" loading="lazy"/></div> 2011</div> 2012 <div id="f8bde178" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1924742703"> <div class="dmNewParagraph u_1924742703" data-element-type="paragraph" data-version="5" id="1924742703" style="" data-inject="topicheading15"> <h3><span style="display: unset;">Short title 15</span></h3> 2013</div> 2014</div> 2015 <div id="c01dfdd3" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1215055766"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1215055766" style="" data-inject="topiccontent15"><p><span style="display: unset;">Describe some quality or feature of the company. Write a short paragraph about it and choose an appropriate icon.</span></p></div> 2016</div> 2017</div> 2018 <div id="103f9f3c" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1856693354"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient" file="false" href="/" data-element-type="dButtonLinkId" id="1856693354" data-binding="W3siYmluZGluZ05hbWUiOiJidXR0b25fdGV4dCIsInZhbHVlIjoiU1RBVElDX1BBR0VfQ09MTEVDVElPTi57XCJjblwiOlwiYnV0dG9uc1wiLFwiZm5cIjpcIkxlYXJuIE1vcmVcIn0ifV0=" data-diy-link=""> <span class="iconBg" id="1291360163"> <span class="icon hasFontIcon icon-star" id="1294338093"></span> 2019</span> 2020 <span class="text" id="1621114799" data-diy-text="">LEARN MORE</span> 2021</a> 2022</div> 2023</div> 2024</div> 2025</div> 2026</section> 2027</div> 2028</div> 2029</div> 2030</div> 2031</div> 2032 <div class="dmFooterContainer flex_hfcontainer"> <div id="flex-footer" role="contentinfo"> <div data-layout-section="" data-auto="flex-section" id="1959439239" data-flex-id="2c8e291c" data-page-element-type="section" data-page-element-id="1601394852"> <div class="flex-widgets-container" id="1357377095"></div> 2033 <section id="21379086" class="flex-element section" data-auto="flex-element-section"> <div id="b5a3be9f" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="b7a700bf" class="flex-element group" data-auto="flex-element-group"> <div id="6405d24c" class="flex-element group" data-auto="flex-element-group"> <div id="widget_udf" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="photoGallery" data-external-id="1399295292"> <div class="dmPhotoGallery newPhotoGallery dmPhotoGalleryResp u_1399295292 photo-gallery-done text-layout-over captionAlignment-center_center photoGallery" galleryoptionsparams="{thumbnailsPerRow: 3, rowsToShow: 3, imageScaleMethod: true}" data-desktop-layout="square" data-desktop-columns="3" data-element-type="dPhotoGalleryId" data-desktop-text-layout="over" id="1399295292" data-placeholder="false" data-rows-to-show="100" data-mobile-layout="square" data-mobile-columns="2" data-image-hover-effect="none" data-dm-multisize-skip-opt="true"> <div class="dmPhotoGalleryHolder clearfix gallery shadowEffectToChildren gallery4inArow" id="1362986591"></div> 2034 <div class="layout-container square"> <div class="photogallery-row " data-index=""> <div class="photogallery-column column-3" data-index="0"> <div index="0" class="photoGalleryThumbs animated " data-index="0"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Green and gold ISA Certified Arborist logo with leaf graphic" data-dm-force-device="mobile" class="u_1686570614" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/imgi_5_ISA-Member-logo.png" style="background-image: url('https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/imgi_5_ISA-Member-logo.png');"><img id="1980839445" data-src="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/imgi_5_ISA-Member-logo.png" alt="Green and gold ISA Certified Arborist logo with leaf graphic" aria-label="Green and gold ISA Certified Arborist logo with leaf graphic" onerror="handleImageLoadError(this)" loading="lazy"/></a> 2035</div> 2036 <div id="1196132034" class="caption-container u_1196132034" style="display:none"> <span class="caption-inner"> <a id="1589289585" class="caption-button dmWidget clearfix u_1589289585" data-auto="c
2036aption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 2037</span> 2038 <span class="text" data-auto="button-text">Button</span> 2039</a> 2040</span> 2041</div> 2042</div> 2043</div> 2044</div> 2045 <div class="photogallery-column column-3" data-index="1"> <div index="1" class="photoGalleryThumbs animated " data-index="1"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Green-and-white ISA member badge with a tree emblem and âMEMBERâ text" data-dm-force-device="mobile" class="u_1237769461" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/imgi_4_ISA-Certified-Arborist-logo.png" style="background-image: url('https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/imgi_4_ISA-Certified-Arborist-logo.png');"><img id="1180553454" data-src="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/imgi_4_ISA-Certified-Arborist-logo.png" alt="Green-and-white ISA member badge with a tree emblem and âMEMBERâ text" aria-label="Green-and-white ISA member badge with a tree emblem and âMEMBERâ text" onerror="handleImageLoadError(this)" loading="lazy"/></a> 2046</div> 2047 <div id="1509678721" class="caption-container u_1509678721" style="display:none"> <span class="caption-inner"> <a id="1778813518" class="caption-button dmWidget clearfix u_1778813518" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 2048</span> 2049 <span class="text" data-auto="button-text">Button</span> 2050</a> 2051</span> 2052</div> 2053</div> 2054</div> 2055</div> 2056 <div class="photogallery-column column-3" data-index="2"> <div index="2" class="photoGalleryThumbs animated " data-index="2"> <div class="thumbnailInnerWrapper" style="opacity: 1;"> <div class="image-container revealed"> <a data-dm-multisize-attr="temp" aria-label="Kansas Arborists Association logo with green tree and Kansas silhouette" data-dm-force-device="mobile" class="u_1865072194" data-image-url="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/imgi_6_Kansas-Arborist-Association-logo.png" style="background-image: url('https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/imgi_6_Kansas-Arborist-Association-logo.png');"><img id="1119230340" data-src="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/imgi_6_Kansas-Arborist-Association-logo.png" alt="Kansas Arborists Association logo with green tree and Kansas silhouette" aria-label="Kansas Arborists Association logo with green tree and Kansas silhouette" onerror="handleImageLoadError(this)" loading="lazy"/></a> 2057</div> 2058 <div id="1743371317" class="caption-container u_1743371317" style="display:none"> <span class="caption-inner"> <a id="1190896696" class="caption-button dmWidget clearfix u_1190896696" data-auto="caption-button" href="" style=""> <span class="iconBg" data-auto="button-icon-bg"> <span class="icon hasFontIcon " data-auto="button-icon"></span> 2059</span> 2060 <span class="text" data-auto="button-text">Button</span> 2061</a> 2062</span> 2063</div> 2064</div> 2065</div> 2066</div> 2067</div> 2068</div> 2069</div> 2070</div> 2071 <div id="widget_nk1" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="html" data-external-id="1999539362"> <div data-element-type="html" class="dmCustomHtml u_1999539362" id="1999539362"> <a href="https://www.bbb.org/us/ks/wichita/profile/tree-services/huffs-tree-service-llc-0714-16560/#sealclick" target="_blank" rel="nofollow"><img src="https://seal-nebraska.bbb.org/seals/blue-seal-200-130-bbb-16560.png" style="border: 0;" alt="Huff's Tree Service, LLC BBB Business Review" onerror="handleImageLoadError(this)" loading="lazy"/></a> 2072</div> 2073</div> 2074</div> 2075</div> 2076</div> 2077</section> 2078</div> 2079 <div data-auto="flex-section" id="1518098037" data-flex-id="7b00a5de" data-layout-section="" data-page-element-type="section" data-page-element-id="1761552858"> <div class="flex-widgets-container" id="1613662762"></div> 2080 <section id="9328cbef" class="flex-element section" data-auto="flex-element-section"> <div id="1ebb7f19" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="6e06962d" class="flex-element group" data-auto="flex-element-group"> <div id="a019b36e" class="flex-element group" data-auto="flex-element-group"> <div id="934bad03" class="flex-element widget-wrapper YXTBUSNAME" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1506966255"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1506966255" new-inline-bind-applied="true" data-diy-text="" style=""> <h3 class="t-size-16 m-size-16 size-18 m-text-align-left"><span class="font-size-18 t-font-size-16 m-font-size-16" style="color: var(--color_2); display: unset;">Learn more about</span></h3> 2081 <h3 class="m-text-align-left"><span style="color: var(--color_2); display: initial;"><span class="inline-data-binding" data-encoded-value="SGlidSBQbHVtYmVycw==" data-inline-binding="" data-inline-binding-encoded="Y29udGVudF9saWJyYXJ5Lmdsb2JhbC5jb21wYW5
20815X25hbWU=">Huff's Tree Service</span></span></h3> 2082</div> 2083</div> 2084 <div id="6f8e19aa" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1661506068"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1661506068" new-inline-bind-applied="true" data-diy-text="" style=""><p class="text-align-left m-text-align-left"><span style="color: var(--color_2); display: initial;"><span class="inline-data-binding" data-encoded-value="VGhpcyBpcyB0aGUgVmlkZW8gVHJhbnNjcmlwdC4gRWRpdCBpbiB0aGUgQ29udGVudCBMaWJyYXJ5Lg==" data-inline-binding="" data-inline-binding-encoded="c2l0ZV90ZXh0LnZpZGVvIHRyYW5zY3JpcHQ=">Serving Sedgwick County, KS. Huff's Tree Service specializes in complete tree services, turf services, and arbor care. Certified arborists on staff. Emergency services available. Free same-day estimates. Contact us today.</span></span></p></div> 2085</div> 2086 <div id="bd7b2692" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1035845042"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton u_1035845042 button_2" file="false" href="/hibu-video-splash" data-element-type="dButtonLinkId" id="1035845042" link_type="popup" popup_target="hibu-video-splash"> <span class="iconBg" aria-hidden="true" id="1299251327"> <span class="icon hasFontIcon icon-star" id="1881817341"></span> 2087</span> 2088 <span class="text" id="1018125776">WATCH VIDEO</span> 2089</a> 2090</div> 2091</div> 2092 <div id="05e0ee19" class="flex-element group lazy" data-auto="flex-element-group" data-binding="eyJiaW5kaW5nTmFtZSI6ImJhY2tncm91bmQiLCJ2YWx1ZSI6InNpdGVfaW1hZ2VzLnBlcnNpc3RlZC5WaWRlbyBTcGxhc2ggSW1hZ2UifQ==" style="background-image: url('data:image/jpeg; base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAHAAoDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAMG/8QAHhAAAQQCAwEAAAAAAAAAAAAAAgABAwQFBgchQRH/xAAVAQEBAAAAAAAAAAAAAAAAAAAABP/EABgRAAMBAQAAAAAAAAAAAAAAAAECAwAR/9oADAMBAAIRAxEAPwDK6ZcyFTGTHStmJ+h46u/I22xu4NNH8Hpu0RQvd5ninDNe7//Z') !important;" data-background-image="https://le-cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/opt/video-huffs-tree-service-02-1920w.jpg"> <div id="a1b6269f" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1518332866"> <div class="widget-ca4188 u_1518332866 dmCustomWidget" data-lazy-load="" data-title="" id="1518332866" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="ca4188fe92024514a23a858f63ab6658" data-widget-version="18" data-widget-config="eyJ2aWRUaXRsZTEiOiIiLCJ2aWRUaXRsZTIiOiIiLCJwbGF5SWNvbiI6IjxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHdpZHRoPVwiMTAwXCIgaGVpZ2h0PVwiMTAwXCIgdmlld0JveD1cIjAgMCAxMDAgMTAwXCI+XG4gIDxwYXRoIGlkPVwiSWNvbl9mYS1yZWd1bGFyLWNpcmNsZS1wbGF5XCIgZGF0YS1uYW1lPVwiSWNvbiBmYS1yZWd1bGFyLWNpcmNsZS1wbGF5XCIgZD1cIk05MC42MjUsNTBBNDAuNjI1LDQwLjYyNSwwLDEsMCw1MCw5MC42MjUsNDAuNjI1LDQwLjYyNSwwLDAsMCw5MC42MjUsNTBaTTAsNTBhNTAsNTAsMCwxLDEsNTAsNTBBNTAsNTAsMCwwLDEsMCw1MFpNMzYuNzc3LDI4LjczYTQuNjkzLDQuNjkzLDAsMCwxLDQuNzQ2LjFMNjkuNjQ4LDQ2LjAxNmE0LjY5Miw0LjY5MiwwLDAsMSwwLDguMDA4TDQxLjUyMyw3MS4yMTFhNC43MzgsNC43MzgsMCwwLDEtNC43NDYuMSw0LjY1OCw0LjY1OCwwLDAsMS0yLjQtNC4wODJWMzIuODEzQTQuNjU4LDQuNjU4LDAsMCwxLDM2Ljc3NywyOC43M1pcIi8+XG48L3N2Zz5cbiIsInBsYXlMaW5rIjp7InZhbHVlIjoiaGlidS12aWRlby1zcGxhc2giLCJ0eXBlIjoicG9wdXAiLCJocmVmIjoiL2hpYnUtdmlkZW8tc3BsYXNoIiwicmF3X3VybCI6Ii9zaXRlLzc3MjBhNzk0OTM0MzRkN2RiZjBlMjgzZDdjNjQyM2U3L2hpYnUtdmlkZW8tc3BsYXNoP25lZT10cnVlJmVkPXRydWUmc2hvd09yaWdpbmFsPXRydWUmcHJldmlldz10cnVlJmRtX3RyeV9tb2RlPXRydWUmZG1fY2hlY2tTeW5jPTEiLCJwb3B1cF90YXJnZXQiOiJoaWJ1LXZpZGVvLXNwbGFzaCIsImxpbmtfdHlwZSI6InBvcHVwIn0sInRyYW5zY3JpcHRpb24iOiJTZXJ2aW5nIFNlZGd3aWNrIENvdW50eSwgS1MuIEh1ZmYncyBUcmVlIFNlcnZpY2Ugc3BlY2lhbGl6ZXMgaW4gY29tcGxldGUgdHJlZSBzZXJ2aWNlcywgdHVyZiBzZXJ2aWNlcywgYW5kIGFyYm9yIGNhcmUuIDUgY2VydGlmaWVkIGFyYm9yaXN0cyBvbiBzdGFmZi4gRW1lcmdlbmN5IHNlcnZpY2VzIGF2YWlsYWJsZS4gRnJlZSBzYW1lLWRheSBlc3RpbWF0ZXMuIENvbnRhY3QgdXMgdG9kYXkuIiwibmFtZSI6Ikh1ZmYncyBUcmVlIFNlcnZpY2UiLCJkZXNjcmlwdGlvbiI6IldlIHNwZWNpYWxpemUgaW4gdHJlZSBzZXJ2aWNlcywgdHVyZiwgYW5kIGFyYm9yIGNhcmUuIEVtZXJnZW5jeSBzZXJ2aWNlcyBhdmFpbGFibGUuIEZyZWUgc2FtZS1kYXkgZXN0aW1hdGVzLiBXZSBoYXZlIDUgY2VydGlmaWVkIGFyYm9yaXN0cyBvbiBzdGFmZi4iLCJ0aHVtYm5haWxVcmwiOiJodHRwczovL2Nkbi5oaWJ1d2Vic2l0ZXMuY29tLzc3MjBhNzk0OTM0MzRkN2RiZjBlMjgzZDdjNjQyM2U3L2RtczNyZXAvbXVsdGkvdmlkZW8taHVmZnMtdHJlZS1zZXJ2aWNlLTAyLmpwZyIsInVwbG9hZERhdGUiOiIyMDI2LTA4LTI1IiwiY29udGVudFVybCI6InZpZGVvcy5oaWJ1c3R1ZGlvLmNvbS8yMDI2L2h1ZmZzLXRyZWUtc2VydmljZS03MDAwMTM4MTg0Lm1wNCJ9"> <div class="vidWrapper" itemprop="video" itemscope="" itemtype="http://schema.org/VideoObject"> <meta itemprop="name" content="Huff's Tree Service"></meta> 2093 <meta itemprop="duration" content="T1M36S"></meta> 2094 <meta itemprop="uploadDate" content="2026-08-25"></meta> 2095 <meta itemprop="thumbnailUrl" content="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/dms3rep/multi/video-huffs-tree-service-02.jpg"></meta> 2096 <meta itemprop="contentURL" content="videos.hibustudio.com/2026/huffs-tree-service-7000138184.mp4"></meta> 2097 <meta itemprop="description" content="We specialize in tree services, turf, and arbor care. Emergency services available. Free same-day estimates. We have 5 certified arborists on staff."></meta> 2098 <meta itemprop="transcript" content=""></meta> 2099 <div class="vidInner"> <center> <p class="vidTitle1"></p> 2100 <p class="vidTitle2"></p> 2101 <div class="playIcon"> <a value="hibu-video-splash" type="popup" href="/hibu-video-splash" raw_url="/site/7720a79493434d7dbf0e283d7c6423e7/hibu-video-splash?nee=true&ed=true&showOriginal=true&preview=true&dm_try_mode=true&dm_checkSync=1" popup_target="hibu-video-splash" link_type="popup"> <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewbox="0 0 100 100"> <path id="Icon_fa-regular-circle-play" data-name="Icon fa-regular-circle-play" d="M90.625,50A40.625,40.625,0,1,0,50,90.625,40.625,40.625,0,0,0,90.625,50ZM0,50a50,50,0,1,1,50,50A50,50,0,0,1,0,50ZM36.777,28.73a4.693,4.693,0,0,1,4.746.1L69.648,46.016a4.692,4.692,0,0,1,0,8.008L41.523,71.211a4.738,4.738,0,0,1-4.746.1,4.658,4.658,0,0,1-2.4-4.082V32.813A4.658,4.658,0,0,1,36.777,28.73Z"></path> 2102</svg> 2103</a> 2104</div> 2105</center> 2106</div> 2107 <div class="vidOverlay"></div> 2108</div> 2109</div> 2110</div> 2111</div> 2112</div> 2113</div> 2114</section> 2115</div> 2116 <div data-layout-section="" data-auto="flex-section" id="1248306277" data-flex-id="b6b5923e"> <div class="flex-widgets-container" id="1193597235"></div> 2117 <section id="e4ad708c" class="flex-element section" data-auto="flex-element-section"> <div id="2bcd41ae" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="4efeffee" class="flex-element group" data-auto="flex-element-group"> <div id="de6ec6ce" class="flex-element group" data-auto="flex-element-group"> <div id="fd81f3e8" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1121588791"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1121588791" style=""> <h6><span style="color: var(--color_9); display: initial;">SERVING AREA</span></h6> 2118</div> 2119</div> 2120 <div id="9264746f" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="divider" data-external-id="1734677568"> <div class="dmDividerWrapper clearfix u_1734677568" data-element-type="dDividerId" data-layout="divider-style-1" data-widget-version="2" id="1734677568" layout="divider-gradient-line"><hr class="dmDivider" style="border-width:2px; border-top-style:solid; color:grey;" id="1267586379"/></div> 2121</div> 2122 <div id="d0a778c9" class="flex-element widget-wrapper YXTSERVICEAREA" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1986930894"> <div class="dmNewParagraph u_1986930894" data-element-type="paragraph" data-version="5" id="1986930894" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCJMb2MtMFwiLFwiZm5cIjpcIkZvb3Rlcl9TZXJ2aWNlX0FyZWFzXCJ9In1d" data-diy-text=""><p class="rteBlock">Andover, KS</p><p class="rteBlock">Wichita, KS</p><p class="rteBlock">Haysville, KS</p><p class="rteBlock">Park City, KS</p><p class="rteBlock">Derby, KS</p><p class="rteBlock">Eastborough, KS</p><p class="rteBlock">Colwich, KS</p><p class="rteBlock">Goddard, KS</p><p class="rteBlock">Valley Center, KS</p><p class="rteBlock">Sedgwick County, KS</p><p class="rteBlock">Harvey County, KS</p><p class="rteBlock">Butler County, KS</p></div> 2123</div> 2124 <div id="f589fd14" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1089632125"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1089632125" style=""><p class="text-align-left m-text-align-left t-size-15 m-size-15 size-15"><span class="font-size-15 t-font-size-15 m-font-size-15" style="color: var(--color_9); display: unset;">and surrounding areas</span></p></div> 2125</div> 2126 <div id="85709a0b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="spacer" data-external-id="1482902342"> <div data-element-type="spacer" class="dmSpacer" id="1482902342"></div> 2127</div> 2128</div> 2129 <div id="d0234170" class="flex-element group" data-auto="flex-element-group"> <div id="cbc8b291" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1563947725"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1563947725" style=""> <h6><span style="display: unset; color: var(--color_9);">CONTACT US</span></h6> 2130</div> 2131</div> 2132 <div id="0b55734b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="divider" data-external-id="1078075131">
2132 <div class="dmDividerWrapper clearfix u_1078075131" data-element-type="dDividerId" data-layout="divider-style-1" data-widget-version="2" id="1078075131" layout="divider-gradient-line"><hr class="dmDivider" style="border-width:2px; border-top-style:solid; color:grey;" id="1927534912"/></div> 2133</div> 2134 <div id="502c2597" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="spacer" data-external-id="1918773725"> <div data-element-type="spacer" class="dmSpacer" id="1918773725"></div> 2135</div> 2136 <div id="widget_k5l" class="flex-element widget-wrapper YXTPH" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1675397205"> <div class="dmNewParagraph u_1675397205" data-element-type="paragraph" data-version="5" id="1675397205" data-diy-text="" style="" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJjb250ZW50X2xpYnJhcnkuZ2xvYmFsLnBob25lLmxvYy0wIC0gbWFpbiJ9XQ==">(316) 871-3841</div> 2137</div> 2138 <div id="1db7e0c7" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="link" data-external-id="1199369758"> <a data-display-type="block" class="align-center dmButtonLink dmWidget dmWwr default dmOnlyButton dmDefaultGradient flexButton u_1199369758" file="false" href="/contact#ICcontactform" data-element-type="dButtonLinkId" id="1199369758"> <span class="iconBg" aria-hidden="true" id="1508234354"> <span class="icon hasFontIcon icon-star" id="1201354356"></span> 2139</span> 2140 <span class="text" id="1706213487">SEND A MESSAGE</span> 2141</a> 2142</div> 2143 <div id="widget_391" class="flex-element widget-wrapper YXTSOCIAL" data-auto="flex-element-widget-wrapper" data-widget-type="socialhub" data-external-id="1064639846"> <div class="align-center text-align-center u_1064639846 dmSocialHub gapSpacing" id="1064639846" dmle_extension="social_hub" data-element-type="social_hub" data-binding="W3siYmluZGluZ05hbWUiOiJzb2NpYWwiLCJ2YWx1ZSI6ImNvbnRlbnRfbGlicmFyeS5nbG9iYWwuc29jaWFsIn1d" wr="true" networks="" icon="true" surround="true" adwords=""> <div class="socialHubWrapper"> <div class="socialHubInnerDiv " data-auto="social-hub-inner"> <a href="https://facebook.com/423029848194509" target="_blank" dm_dont_rewrite_url="true" aria-label="facebook" onclick="dm_gaq_push_event && dm_gaq_push_event('socialLink', 'click', 'Facebook')"> <span class="dmSocialFacebook dm-social-icons-facebook oneIcon socialHubIcon style5" aria-hidden="true" data-hover-effect="zoomout"></span> 2144</a> 2145 <a href="https://instagram.com/huffstreeservice" target="_blank" dm_dont_rewrite_url="true" aria-label="instagram" onclick="dm_gaq_push_event && dm_gaq_push_event('socialLink', 'click', 'Instagram')"> <span class="dmSocialInstagram dm-social-icons-instagram oneIcon socialHubIcon style5" aria-hidden="true" data-hover-effect="zoomout"></span> 2146</a> 2147 <a href="https://youtube.com/@HuffsTreeService" target="_blank" dm_dont_rewrite_url="true" aria-label="youtube" onclick="dm_gaq_push_event && dm_gaq_push_event('socialLink', 'click', 'Youtube')"> <span class="dmSocialYoutube dm-social-icons-youtube oneIcon socialHubIcon style5" aria-hidden="true" data-hover-effect="zoomout"></span> 2148</a> 2149 <a href="https://linkedin.com/company/huff's-tree-service-llc" target="_blank" dm_dont_rewrite_url="true" aria-label="linkedin" onclick="dm_gaq_push_event && dm_gaq_push_event('socialLink', 'click', 'Linkedin')"> <span class="dmSocialLinkedin icon-linkedin oneIcon socialHubIcon style5" aria-hidden="true" data-hover-effect="zoomout"></span> 2150</a> 2151 <a href="https://www.tiktok.com/@@huffstreeservicellc" target="_blank" dm_dont_rewrite_url="true" aria-label="tiktok" onclick="dm_gaq_push_event && dm_gaq_push_event('socialLink', 'click', 'Tiktok')"> <span class="dmSocialTiktok dm-social-icons-tiktok oneIcon socialHubIcon style5" aria-hidden="true" data-hover-effect="zoomout"></span> 2152</a> 2153</div> 2154</div> 2155</div> 2156</div> 2157</div> 2158 <div id="f2debc4b" class="flex-element group" data-auto="flex-element-group"> <div id="65e14480" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="1332286019"> <div class="dmNewParagraph" data-element-type="paragraph" data-version="5" id="1332286019" style=""> <h6><span style="display: unset; color: var(--color_9);">BUSINESS HOURS</span></h6> 2159</div> 2160</div> 2161 <div id="c7f3ddf3" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="divider" data-external-id="1463975724"> <div class="dmDividerWrapper clearfix u_1463975724" data-element-type="dDividerId" data-layout="divider-style-1" data-widget-version="2" id="1463975724" layout="divider-gradient-line"><hr class="dmDivider" style="border-width:2px; border-top-style:solid; color:grey;" id="1907202694"/></div> 2162</div> 2163 <div id="618f39ae" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="spacer" data-external-id="1700615418"> <div data-element-type="spacer" class="dmSpacer" id="1700615418"></div> 2164</div> 2165 <div id="widget_6mu" class="flex-element widget-wrapper YXTBUSHOURS" data-auto="flex-element-widget-wrapper" data-widget-type="hoursOfOperation" data-external-id="1185800986"> <div class="default u_1185800986 dmHoursOfOperation" id="1185800986" dmle_extension="open_hours" data-element-type="open_hours" data-binding="W3siYmluZGluZ05hbWUiOiJidXNpbmVzc19ob3VycyIsInZhbHVlIjoiY29udGVudF9saWJyYXJ5Lmdsb2JhbC5idXNpbmVzc19ob3VycyJ9XQ==" time_format="12" wr="true" displaytitle="false" lang="" forcedisplay="false" icon="true" surround="true" adwords=""> <dl class="open-hours-data"> <div class="open-hours-item"> <dt day="0">Mon - Fri</dt> 2166 <dd> <time>8:00 am</time> 2167- <time>4:00 pm</time> 2168</dd> 2169</div> 2170 <div class="open-hours-item"> <dt day="5">Sat - Sun</dt> 2171 <dd>Closed</dd> 2172</div> 2173</dl> 2174</div> 2175</div> 2176 <div id="widget_9dv" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="paragraph" data-external-id="4279627036"> <div class="dmNewParagraph u_4279627036" data-element-type="paragraph" data-version="5" id="4279627036" data-binding="W3siYmluZGluZ05hbWUiOiJ0ZXh0IiwidmFsdWUiOiJTVEFUSUNfUEFHRV9DT0xMRUNUSU9OLntcImNuXCI6XCJMb2MtMFwiLFwiZm5cIjpcIkFkZGl0aW9uYWxfSG91cnNcIn0ifV0=" data-diy-text=""><p class="rteBlock">Emergency Services Available & After-Hours By Appointment Only</p></div> 2177</div> 2178</div> 2179</div> 2180</div> 2181</section> 2182</div> 2183 <div data-layout-section="" data-auto="flex-section" id="1344609592" data-flex-id="2f831c0f"> <div class="flex-widgets-container" id="1374258866"></div> 2184 <section id="71171ca4" class="flex-element section" data-auto="flex-element-section"> <div id="0253b4c6" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="d027d36f" class="flex-element group" data-auto="flex-element-group" data-hidden-on-tablet="" data-hidden-on-mobile=""> <div id="00841c9d" class="flex-element group" data-auto="flex-element-group"> <div id="7e326d80" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="ONELinksMenu" data-hidden-on-desktop="" data-external-id="1869341664"> <nav class="effect-bottom2 u_1869341664 main-navigation unifiednav dmLinksMenu" data-auto="links-menu" role="navigation" layout-main="horizontal_nav_layout_1" layout-sub="submenu_horizontal_1" data-show-vertical-sub-items="HOVER" id="1869341664" dmle_extension="onelinksmenu" data-element-type="onelinksmenu" data-logo-src="" alt="" data-nav-structure="HORIZONTAL" wr="true" icon="true" surround="true" adwords="" navigation-id="unifiedNav"> <ul role="menubar" class="unifiednav__container unav-top " data-auto="navigation-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/" class="unifiednav__item unav-item unav-top-item dmNavItemSelected dmUDNavigationItem_00 " target="" data-target-page-alias="" aria-current="page" data-auto="selected-page"> <span class="nav-item-text " data-link-text=" 2185 Home 2186 " data-auto="page-text-style">Home<span class="icon icon-angle-down"></span> 2187</span> 2188</a> 2189</li> 2190 <li role="menuitem" aria-haspopup="true" aria-expanded="false" data-sub-nav-menu="true" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/about" class="unifiednav__item unav-item unav-top-item dmUDNavigationItem_010101599305 unifiednav__item_has-sub-nav" target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="About" data-auto="page-text-style">About<span class="icon icon-angle-down"></span> 2191</span> 2192</a> 2193 <ul role="menu" class="unifiednav__container unifiednav__container_sub-nav unav-sub" data-depth="0" data-auto="sub-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/careers" class="unifiednav__item unav-item dmUDNavigationItem_010101402669 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Careers" data-auto="page-text-style">Careers<span class="icon icon-angle-right"></span> 2194</span> 2195</a> 2196</li> 2197 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/team" class="unifiednav__item unav-item dmUDNavigationItem_010101693489 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Team" data-auto="page-text-style">Team<span class="icon icon-angle-right"></span> 2198</span> 2199</a> 2200</li> 2201 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/faqs" class="unifiednav__item unav-item dmUDNavigationItem_010101347615 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="FAQs" data-auto="page-text-style">FAQs<span class="icon icon-angle-right"></span> 2202</span> 2203</a> 2204</li> 2205 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/gallery" class="unifiednav__item unav-item dmUDNavigationItem_010101776001 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Gallery" data-auto="page-text-style">Gallery<span class="icon icon-angle-right" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 2206</span> 2207</a> 2208</li> 2209 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/reviews" class="unifiednav__item unav-item dmUDNavigationItem_010101840192 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Reviews" data-auto="page-text-style">Reviews<span class="icon icon-angle-right"></span> 2210</span> 2211</a> 2212</li> 2213 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/blog" class="unifiednav__item unav-item dmUDNavigationItem_010101105406 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Blog" data-auto="page-text-style">Blog<span class="icon icon-angle-right"></span> 2214</span> 2215</a> 2216</li> 2217</ul> 2218</li> 2219 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/service-area" class="unifiednav__item unav-item unav-top-item dmUDNavigationItem_01010151303 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Serving Area" data-auto="page-text-style">Serving Area<span class="icon icon-angle-down" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 2220</span> 2221</a> 2222</li> 2223 <li role="menuitem" aria-haspopup="true" aria-expanded="false" data-sub-nav-menu="true" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/contact" class="unifiednav__item unav-item unav-top-item dmUDNavigationItem_010101152840 unifiednav__item_has-sub-nav" target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Contact" data-auto="page-text-style">Contact<span class="icon icon-angle-down"></span> 2224</span> 2225</a> 2226 <ul role="menu" class="unifiednav__container unifiednav__container_sub-nav unav-sub" data-depth="0" data-auto="sub-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/request-estimate-form" class="unifiednav__item unav-item dmUDNavigationItem_010101150108 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Request Estimate" data-auto="page-text-style">Request Estimate<span class="icon icon-angle-right"></span> 2227</span> 2228</a> 2229</li> 2230</ul> 2231</li> 2232 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/empty" class="unifiednav__item unav-item unav-top-item dmUDNavigationItem_010101434187 " target="" data-target-page-alias=""> <span class="nav-item-text " data-link-text="Poly Social Test" data-auto="page-text-style">Poly Social Test<span class="icon icon-angle-down"></span> 2233</span> 2234</a> 2235</li> 2236</ul> 2237</nav> 2238</div> 2239</div> 2240</div> 2241</div> 2242</section> 2243</div> 2244 <div data-layout-section="" data-auto="flex-section" id="1741943752" data-flex-id="54290af5" class="" data-hidden-on-desktop="true"> <div class="flex-widgets-container" id="1020340060"></div> 2245 <section id="0c6cf26f" class="flex-element section" data-auto="flex-element-section"> <div id="3989af5b" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="24eff763" class="flex-element group" data-auto="flex-element-group" data-hidden-on-tablet="" data-hidden-on-desktop="">
2245 <div id="7ca01c83" class="flex-element group" data-auto="flex-element-group"> <div id="34b9f983" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="ssrbreadcrumbs" data-external-id="1424178368"> <div id="1424178368" dmle_extension="ssrbreadcrumbs" data-element-type="ssrbreadcrumbs" class=""><span id="ssrWrap-1424178368" ><style data-styled="true" data-styled-version="5.3.11">.gCAEgf{color:rgba(102,102,102,1);}/*!sc*/ 2246data-styled.g18[id="sc-dLMFU"]{content:"gCAEgf,"}/*!sc*/ 2247#dm .dewijn.dewijn{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:10px;}/*!sc*/ 2248@media (min-width:768px){#dm .dewijn.dewijn{font-size:11px;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}}/*!sc*/ 2249@media (max-width:767px){#dm .dewijn.dewijn{font-size:11px;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}}/*!sc*/ 2250data-styled.g19[id="sc-eDPEul"]{content:"dewijn,"}/*!sc*/ 2251</style><div data-auto="runtime-breadcrumbs-widget"><nav class="sc-eDPEul dewijn bc-root dmBlockElement" aria-label="Breadcrumbs"><div class="sc-dLMFU gCAEgf bc-current-item" data-auto="bc-current-item">Home</div></nav></div></span></div> 2252</div> 2253</div> 2254</div> 2255</div> 2256</section> 2257</div> 2258</div> 2259 <div id="poweredBy" class="poweredBy poweredByHibu"> <div class="poweredLine1"> <a href="http://budurl.com/hibuprivacy" target="_blank">Privacy Policy</a>| <a href="http://budurl.com/hibucookie" target="_blank">Do Not Share My Information</a>| <a href="http://budurl.com/hibuconditionsofuse" target="_blank">Conditions of Use</a>| <a href="http://budurl.com/hibunotice" target="_blank">Notice and Take Down Policy</a>| <a href="http://b.link/accessibility" target="_blank">Website Accessibility Policy</a> 2260</div> 2261 <div class="poweredLine2">© <span id="hibuYear">2026</span> 2262The content on this website is owned by us and our licensors. Do not copy any content (including images) without our consent.</div> 2263</div> 2264</div> 2265 <div id="dmFlexStickyContainer" class="flex_hfcontainer"> <div id="flex-sticky"> <div data-layout-section="" data-auto="flex-section" id="1801865596" data-flex-id="8a9cfcfc"> <div class="flex-widgets-container" id="1548435334"></div> 2266 <section id="4a1fde56" class="flex-element section" data-auto="flex-element-section"> <div id="381d99f1" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="75ba1c41" class="flex-element group" data-auto="flex-element-group"> <div id="4f4d3298" class="flex-element group" data-auto="flex-element-group"> <div id="72168835" class="flex-element inner-grid" data-auto="flex-element-inner-grid"> <div id="widget_21v" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="graphic" data-keep-proportion="true" data-hidden-on-tablet="" data-hidden-on-desktop="" data-external-id="1389791254"> <div class="graphicWidget graphicWidgetV2 graphicWidgetV3 u_1389791254" data-element-type="graphic" data-widget-type="graphic" id="1389791254" data-layout="graphic-style-5"> <a href="/hibu-eng-menu" id="1685777839" link_type="popup" file="false" popup_target="hibu-eng-menu" aria-label="Contact Us"> <svg width="100%" height="100%" version="1.1" viewbox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" id="1047488693" class="svg u_1047488693" data-icon-custom="true" aria-labelledby="1665903033"> <title id="1665903033">Contact Us</title> 2267 <path d="m90.793 43.289h-34.086v-34.078c0-3.707-3.0039-6.707-6.707-6.707s-6.707 3-6.707 6.707v34.078h-34.086c-3.7031 0-6.707 3.0039-6.707 6.707s3.0039 6.707 6.707 6.707h34.086v34.086c0 3.707 3.0039 6.707 6.707 6.707s6.707-3 6.707-6.707v-34.086h34.086c3.7031 0 6.707-3 6.707-6.707 0-3.707-3.0039-6.707-6.707-6.707z"></path> 2268</svg> 2269</a> 2270</div> 2271</div> 2272 <div id="widget_fpt" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="3053959938"> <div class="widget-0c06e7 dmCustomWidget" data-lazy-load="true" data-title="" id="3053959938" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="0c06e70da5474879a21daa0d3b1192c0" data-widget-version="3" data-widget-config="e30="> <div class="cb1-theme-injector"></div> 2273</div> 2274</div> 2275 <div id="widget_mnf" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="3931136021"> <div class="widget-8eedf9 dmCustomWidget" data-lazy-load="true" data-title="" id="3931136021" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="8eedf98f346a42e0a55f9d6152653187" data-widget-version="2" data-widget-config="e30="> <div class="cb0-theme-injector"></div> 2276</div> 2277</div> 2278 <div id="widget_c5v" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="3659398620"> <div class="widget-1c20f5 dmCustomWidget" data-lazy-load="true" data-title="" id="3659398620" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="1c20f508b5474ea2b929959f7d5eff3d" data-widget-version="3" data-widget-config="e30="> <div class="dcbh3-theme-injector"></div> 2279</div> 2280</div> 2281 <div id="widget_doa" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="1889303332"> <div class="widget-403a95 dmCustomWidget" data-lazy-load="true" data-title="" id="1889303332" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="403a957a34f84bc8a342137c59c93b31" data-widget-version="3" data-widget-config="e30="> <div class="cb2-theme-injector"></div> 2282</div> 2283</div> 2284 <div id="widget_301" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="986065271"> <div class="widget-e0b1e5 dmCustomWidget" data-lazy-load="true" data-title="" id="986065271" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="e0b1e5b2d4394e69a98bd276fd6afe8b" data-widget-version="8" data-widget-config="e30="> <div class="cb1-theme-injector"></div> 2285</div> 2286</div> 2287 <div id="widget_61p" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="3078440210"> <div class="widget-2133bf dmCustomWidget" data-lazy-load="true" data-title="" id="3078440210" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="2133bfee2cb24e0c9db9468154881b94" data-widget-version="3" data-widget-config="e30="> <div class="cb1-theme-injector"></div> 2288</div> 2289</div> 2290</div> 2291</div> 2292</div> 2293</div> 2294</section> 2295</div> 2296</div> 2297</div> 2298 <div id="dmFlexMegaMenuContainer" class="flex_hfcontainer"> <div id="multi-mega-menu"> <div id="mega-menu-4dc8a903" name="Services"> <div data-flex-id="4dc8a903" data-auto="flex-section" id="1276875426" data-layout-section="" data-page-element-type="section" data-page-element-id="1232093299" class="" data-hidden-on-desktop="true"> <div class="flex-widgets-container" id="1497300766"></div> 2299 <section id="6c5257e3" class="flex-element section" data-auto="flex-element-section"> <div id="2cb3e9f9" class="flex-element grid lazy" data-auto="flex-element-grid" data-layout-grid="" data-background-image=""> <div id="27581a62" class="flex-element group" data-auto="flex-element-group" data-hidden-on-desktop=""> <div id="d200b2f7" class="flex-element group" data-auto="flex-element-group"> <div id="widget_cq9" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="ONELinksMenu" data-external-id="1459911792"> <nav class="u_1459911792 unifiednav_vertical effect-bottom2 main-navigation unifiednav dmLinksMenu" data-auto="links-menu" role="navigation" layout-main="vertical_nav_layout_2" layout-sub="" data-show-vertical-sub-items="SHOW" id="1459911792" dmle_extension="onelinksmenu" data-element-type="onelinksmenu" data-logo-src="" alt="" data-nav-structure="VERTICAL" wr="true" icon="true" surround="true" adwords="" navigation-id="unifiedNav"> <ul role="menubar" class="unifiednav__container unav-top " data-auto="navigation-pages"> <li role="menuitem" aria-haspopup="true" aria-expanded="false" data-sub-nav-menu="true" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/what-we-do/~page-item~" class="unifiednav__item unav-item unav-top-item unifiednav__item_has-sub-nav" target="" data-target-page-alias="cat-landing"> <span class="nav-item-text " data-link-text="Cat-Landing" data-auto="page-text-style">Cat-Landing<span class="icon icon-angle-down"></span> 2300</span> 2301</a> 2302 <ul role="menu" class="unifiednav__container unifiednav__container_sub-nav unav-sub" data-depth="0" data-auto="sub-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/services/~page-item~" class="unifiednav__item unav-item " target="" data-target-page-alias="core-page"> <span class="nav-item-text " data-link-text="Core Page" data-auto="page-text-style">
2302Core Page<span class="icon icon-angle-right" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 2303</span> 2304</a> 2305</li> 2306</ul> 2307</li> 2308</ul> 2309</nav> 2310</div> 2311 <div id="b51d88ee" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="ONELinksMenu" data-external-id="1723750523"> <nav class="u_1723750523 unifiednav_vertical effect-bottom2 main-navigation unifiednav dmLinksMenu" data-auto="links-menu" role="navigation" layout-main="vertical_nav_layout_2" layout-sub="" data-show-vertical-sub-items="SHOW" id="1723750523" dmle_extension="onelinksmenu" data-element-type="onelinksmenu" data-logo-src="" alt="" data-nav-structure="VERTICAL" wr="true" icon="true" surround="true" adwords="" navigation-id="unifiedNav"> <ul role="menubar" class="unifiednav__container unav-top " data-auto="navigation-pages"> <li role="menuitem" aria-haspopup="true" aria-expanded="false" data-sub-nav-menu="true" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/what-we-do/~page-item~" class="unifiednav__item unav-item unav-top-item unifiednav__item_has-sub-nav" target="" data-target-page-alias="cat-landing"> <span class="nav-item-text " data-link-text="Cat-Landing" data-auto="page-text-style">Cat-Landing<span class="icon icon-angle-down"></span> 2312</span> 2313</a> 2314 <ul role="menu" class="unifiednav__container unifiednav__container_sub-nav unav-sub" data-depth="0" data-auto="sub-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/services/~page-item~" class="unifiednav__item unav-item " target="" data-target-page-alias="core-page"> <span class="nav-item-text " data-link-text="Core Page" data-auto="page-text-style">Core Page<span class="icon icon-angle-right" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 2315</span> 2316</a> 2317</li> 2318</ul> 2319</li> 2320</ul> 2321</nav> 2322</div> 2323 <div id="5aa033c8" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="ONELinksMenu" data-external-id="1610592242"> <nav class="u_1610592242 unifiednav_vertical effect-bottom2 main-navigation unifiednav dmLinksMenu" data-auto="links-menu" role="navigation" layout-main="vertical_nav_layout_2" layout-sub="" data-show-vertical-sub-items="SHOW" id="1610592242" dmle_extension="onelinksmenu" data-element-type="onelinksmenu" data-logo-src="" alt="" data-nav-structure="VERTICAL" wr="true" icon="true" surround="true" adwords="" navigation-id="unifiedNav"> <ul role="menubar" class="unifiednav__container unav-top " data-auto="navigation-pages"> <li role="menuitem" aria-haspopup="true" aria-expanded="false" data-sub-nav-menu="true" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/what-we-do/~page-item~" class="unifiednav__item unav-item unav-top-item unifiednav__item_has-sub-nav" target="" data-target-page-alias="cat-landing"> <span class="nav-item-text " data-link-text="Cat-Landing" data-auto="page-text-style">Cat-Landing<span class="icon icon-angle-down"></span> 2324</span> 2325</a> 2326 <ul role="menu" class="unifiednav__container unifiednav__container_sub-nav unav-sub" data-depth="0" data-auto="sub-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/services/~page-item~" class="unifiednav__item unav-item " target="" data-target-page-alias="core-page"> <span class="nav-item-text " data-link-text="Core Page" data-auto="page-text-style">Core Page<span class="icon icon-angle-right" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 2327</span> 2328</a> 2329</li> 2330</ul> 2331</li> 2332</ul> 2333</nav> 2334</div> 2335</div> 2336 <div id="ad9cb284" class="flex-element group" data-auto="flex-element-group"> <div id="04df1da2" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="ONELinksMenu" data-external-id="1136789265"> <nav class="u_1136789265 unifiednav_vertical effect-bottom2 main-navigation unifiednav dmLinksMenu" data-auto="links-menu" role="navigation" layout-main="vertical_nav_layout_2" layout-sub="" data-show-vertical-sub-items="SHOW" id="1136789265" dmle_extension="onelinksmenu" data-element-type="onelinksmenu" data-logo-src="" alt="" data-nav-structure="VERTICAL" wr="true" icon="true" surround="true" adwords="" navigation-id="unifiedNav"> <ul role="menubar" class="unifiednav__container unav-top " data-auto="navigation-pages"> <li role="menuitem" aria-haspopup="true" aria-expanded="false" data-sub-nav-menu="true" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/what-we-do/~page-item~" class="unifiednav__item unav-item unav-top-item unifiednav__item_has-sub-nav" target="" data-target-page-alias="cat-landing"> <span class="nav-item-text " data-link-text="Cat-Landing" data-auto="page-text-style">Cat-Landing<span class="icon icon-angle-down"></span> 2337</span> 2338</a> 2339 <ul role="menu" class="unifiednav__container unifiednav__container_sub-nav unav-sub" data-depth="0" data-auto="sub-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/services/~page-item~" class="unifiednav__item unav-item " target="" data-target-page-alias="core-page"> <span class="nav-item-text " data-link-text="Core Page" data-auto="page-text-style">
2339Core Page<span class="icon icon-angle-right" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 2340</span> 2341</a> 2342</li> 2343</ul> 2344</li> 2345</ul> 2346</nav> 2347</div> 2348 <div id="f09d8243" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="ONELinksMenu" data-external-id="1968129260"> <nav class="u_1968129260 unifiednav_vertical effect-bottom2 main-navigation unifiednav dmLinksMenu" data-auto="links-menu" role="navigation" layout-main="vertical_nav_layout_2" layout-sub="" data-show-vertical-sub-items="SHOW" id="1968129260" dmle_extension="onelinksmenu" data-element-type="onelinksmenu" data-logo-src="" alt="" data-nav-structure="VERTICAL" wr="true" icon="true" surround="true" adwords="" navigation-id="unifiedNav"> <ul role="menubar" class="unifiednav__container unav-top " data-auto="navigation-pages"> <li role="menuitem" aria-haspopup="true" aria-expanded="false" data-sub-nav-menu="true" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/what-we-do/~page-item~" class="unifiednav__item unav-item unav-top-item unifiednav__item_has-sub-nav" target="" data-target-page-alias="cat-landing"> <span class="nav-item-text " data-link-text="Cat-Landing" data-auto="page-text-style">Cat-Landing<span class="icon icon-angle-down"></span> 2349</span> 2350</a> 2351 <ul role="menu" class="unifiednav__container unifiednav__container_sub-nav unav-sub" data-depth="0" data-auto="sub-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/services/~page-item~" class="unifiednav__item unav-item " target="" data-target-page-alias="core-page"> <span class="nav-item-text " data-link-text="Core Page" data-auto="page-text-style">Core Page<span class="icon icon-angle-right" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 2352</span> 2353</a> 2354</li> 2355</ul> 2356</li> 2357</ul> 2358</nav> 2359</div> 2360 <div id="899c2eb2" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="ONELinksMenu" data-external-id="1507374835"> <nav class="u_1507374835 unifiednav_vertical effect-bottom2 main-navigation unifiednav dmLinksMenu" data-auto="links-menu" role="navigation" layout-main="vertical_nav_layout_2" layout-sub="" data-show-vertical-sub-items="SHOW" id="1507374835" dmle_extension="onelinksmenu" data-element-type="onelinksmenu" data-logo-src="" alt="" data-nav-structure="VERTICAL" wr="true" icon="true" surround="true" adwords="" navigation-id="unifiedNav"> <ul role="menubar" class="unifiednav__container unav-top " data-auto="navigation-pages"> <li role="menuitem" aria-haspopup="true" aria-expanded="false" data-sub-nav-menu="true" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/what-we-do/~page-item~" class="unifiednav__item unav-item unav-top-item unifiednav__item_has-sub-nav" target="" data-target-page-alias="cat-landing"> <span class="nav-item-text " data-link-text="Cat-Landing" data-auto="page-text-style">Cat-Landing<span class="icon icon-angle-down"></span> 2361</span> 2362</a> 2363 <ul role="menu" class="unifiednav__container unifiednav__container_sub-nav unav-sub" data-depth="0" data-auto="sub-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/services/~page-item~" class="unifiednav__item unav-item " target="" data-target-page-alias="core-page"> <span class="nav-item-text " data-link-text="Core Page" data-auto="page-text-style">Core Page<span class="icon icon-angle-right" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 2364</span> 2365</a> 2366</li> 2367</ul> 2368</li> 2369</ul> 2370</nav> 2371</div> 2372</div> 2373 <div id="0190983d" class="flex-element group" data-auto="flex-element-group"> <div id="7b991c9b" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="ONELinksMenu" data-external-id="1801032432"> <nav class="u_1801032432 unifiednav_vertical effect-bottom2 main-navigation unifiednav dmLinksMenu" data-auto="links-menu" role="navigation" layout-main="vertical_nav_layout_2" layout-sub="" data-show-vertical-sub-items="SHOW" id="1801032432" dmle_extension="onelinksmenu" data-element-type="onelinksmenu" data-logo-src="" alt="" data-nav-structure="VERTICAL" wr="true" icon="true" surround="true" adwords="" navigation-id="unifiedNav"> <ul role="menubar" class="unifiednav__container unav-top " data-auto="navigation-pages"> <li role="menuitem" aria-haspopup="true" aria-expanded="false" data-sub-nav-menu="true" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/what-we-do/~page-item~" class="unifiednav__item unav-item unav-top-item unifiednav__item_has-sub-nav" target="" data-target-page-alias="cat-landing"> <span class="nav-item-text " data-link-text="Cat-Landing" data-auto="page-text-style">Cat-Landing<span class="icon icon-angle-down"></span> 2374</span> 2375</a> 2376 <ul role="menu" class="unifiednav__container unifiednav__container_sub-nav unav-sub" data-depth="0" data-auto="sub-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/services/~page-item~" class="unifiednav__item unav-item " target="" data-target-page-alias="core-page"> <span class="nav-item-text " data-link-text="Core Page" data-auto="page-text-style">
2376Core Page<span class="icon icon-angle-right" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 2377</span> 2378</a> 2379</li> 2380</ul> 2381</li> 2382</ul> 2383</nav> 2384</div> 2385 <div id="39a585e9" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="ONELinksMenu" data-external-id="1338154768"> <nav class="u_1338154768 unifiednav_vertical effect-bottom2 main-navigation unifiednav dmLinksMenu" data-auto="links-menu" role="navigation" layout-main="vertical_nav_layout_2" layout-sub="" data-show-vertical-sub-items="SHOW" id="1338154768" dmle_extension="onelinksmenu" data-element-type="onelinksmenu" data-logo-src="" alt="" data-nav-structure="VERTICAL" wr="true" icon="true" surround="true" adwords="" navigation-id="unifiedNav"> <ul role="menubar" class="unifiednav__container unav-top " data-auto="navigation-pages"> <li role="menuitem" aria-haspopup="true" aria-expanded="false" data-sub-nav-menu="true" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/what-we-do/~page-item~" class="unifiednav__item unav-item unav-top-item unifiednav__item_has-sub-nav" target="" data-target-page-alias="cat-landing"> <span class="nav-item-text " data-link-text="Cat-Landing" data-auto="page-text-style">Cat-Landing<span class="icon icon-angle-down"></span> 2386</span> 2387</a> 2388 <ul role="menu" class="unifiednav__container unifiednav__container_sub-nav unav-sub" data-depth="0" data-auto="sub-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/services/~page-item~" class="unifiednav__item unav-item " target="" data-target-page-alias="core-page"> <span class="nav-item-text " data-link-text="Core Page" data-auto="page-text-style">Core Page<span class="icon icon-angle-right" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 2389</span> 2390</a> 2391</li> 2392</ul> 2393</li> 2394</ul> 2395</nav> 2396</div> 2397 <div id="4310a1b0" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="ONELinksMenu" data-external-id="1201338092"> <nav class="u_1201338092 unifiednav_vertical effect-bottom2 main-navigation unifiednav dmLinksMenu" data-auto="links-menu" role="navigation" layout-main="vertical_nav_layout_2" layout-sub="" data-show-vertical-sub-items="SHOW" id="1201338092" dmle_extension="onelinksmenu" data-element-type="onelinksmenu" data-logo-src="" alt="" data-nav-structure="VERTICAL" wr="true" icon="true" surround="true" adwords="" navigation-id="unifiedNav"> <ul role="menubar" class="unifiednav__container unav-top " data-auto="navigation-pages"> <li role="menuitem" aria-haspopup="true" aria-expanded="false" data-sub-nav-menu="true" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/what-we-do/~page-item~" class="unifiednav__item unav-item unav-top-item unifiednav__item_has-sub-nav" target="" data-target-page-alias="cat-landing"> <span class="nav-item-text " data-link-text="Cat-Landing" data-auto="page-text-style">Cat-Landing<span class="icon icon-angle-down"></span> 2398</span> 2399</a> 2400 <ul role="menu" class="unifiednav__container unifiednav__container_sub-nav unav-sub" data-depth="0" data-auto="sub-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="1"> <a href="/services/~page-item~" class="unifiednav__item unav-item " target="" data-target-page-alias="core-page"> <span class="nav-item-text " data-link-text="Core Page" data-auto="page-text-style">Core Page<span class="icon icon-angle-right" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 2401</span> 2402</a> 2403</li> 2404</ul> 2405</li> 2406</ul> 2407</nav> 2408</div> 2409</div> 2410 <div id="group_9n6" class="flex-element group" data-auto="flex-element-group"> <div id="fe7f7167" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="ONELinksMenu" data-external-id="1401180572"> <nav class="u_1401180572 unifiednav_vertical effect-bottom2 main-navigation unifiednav dmLinksMenu" data-auto="links-menu" role="navigation" layout-main="vertical_nav_layout_2" layout-sub="" data-show-vertical-sub-items="SHOW" id="1401180572" dmle_extension="onelinksmenu" data-element-type="onelinksmenu" data-logo-src="" alt="" data-nav-structure="VERTICAL" wr="true" icon="true" surround="true" adwords="" navigation-id="unifiedNav"> <ul role="menubar" class="unifiednav__container unav-top " data-auto="navigation-pages"> <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/services/~page-item~" class="unifiednav__item unav-item unav-top-item " target="" data-target-page-alias="core-page"> <span class="nav-item-text " data-link-text="Core Page" data-auto="page-text-style">
2410Core Page<span class="icon icon-angle-down" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 2411</span> 2412</a> 2413</li> 2414 <li role="menuitem" class=" unifiednav__item-wrap " data-auto="more-pages" data-depth="0"> <a href="/services/~page-item~" class="unifiednav__item unav-item unav-top-item " target="" data-target-page-alias="core-page"> <span class="nav-item-text " data-link-text="Core Page" data-auto="page-text-style">Core Page<span class="icon icon-angle-down" data-hidden-on-mobile="" data-hidden-on-desktop="" data-hidden-on-tablet=""></span> 2415</span> 2416</a> 2417</li> 2418</ul> 2419</nav> 2420</div> 2421</div> 2422</div> 2423</div> 2424</section> 2425</div> 2426 <div data-layout-section="" data-auto="flex-section" id="1582186687" data-flex-id="2a501ecf"> <div class="flex-widgets-container" id="1924641454"></div> 2427 <section id="c55100d8" class="flex-element section" data-auto="flex-element-section"> <div id="57b153fb" class="flex-element grid" data-auto="flex-element-grid" data-layout-grid=""> <div id="08465346" class="flex-element group" data-auto="flex-element-group"> <div id="5a572945" class="flex-element group" data-auto="flex-element-group"> <div id="widget_gf3" class="flex-element widget-wrapper" data-auto="flex-element-widget-wrapper" data-widget-type="custom" data-external-id="224877366"> <div class="widget-3e38ec u_224877366 dmCustomWidget" data-lazy-load="true" data-title="" id="224877366" dmle_extension="custom_extension" data-element-type="custom_extension" icon="false" surround="false" data-widget-id="3e38ec713838428586c343d139994b6f" data-widget-version="58" data-widget-config="eyJjb2x1bW5Db3VudCI6IjMiLCJ1bmRlcmxpbmVTZWxlY3RlZCI6dHJ1ZSwic2VsZWN0ZWRCZ0NvbG9yIjoidHJhbnNwYXJlbnQiLCJleGNsdWRlUGFyZW50cyI6ImhvbWUsIGFib3V0LCBjb250YWN0LCBnYWxsZXJ5IiwiaW5jbHVkZVBhcmVudHMiOiIiLCJjaGV2cm9uSWNvbiI6IjxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwiY3VycmVudENvbG9yXCIgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCI+PHBhdGggZD1cIk03LjQxIDguNTlMMTIgMTMuMTdsNC41OS00LjU4TDE4IDEwbC02IDYtNi02IDEuNDEtMS40MXpcIi8+PC9zdmc+IiwiZXhwYW5kQWxsIjp0cnVlfQ=="><!-- === Real-Data Navigation Grid Widget (parent remains a hyperlink) === --> <div id="nav-grid-widget" data-columns="3" data-source="auto"></div> 2428</div> 2429</div> 2430</div> 2431</div> 2432</div> 2433</section> 2434</div> 2435</div> 2436</div> 2437</div> 2438 <div id="swh-9ab370bbf1f8432d9ed75fc7a4144f96"> <div data-wrapper-source="appstore"><!--audioeye-managed:accessibility-->
2438<script data-audioeye-managed="accessibility"> if (window.location.search.match(/[?,&]preview=true/) && window.top !== window) { window.__AudioEyePreviewMode=true; } </script>
2438 2439
2439<script type="text/javascript">!function(){ var b=function(){ window.__AudioEyeSiteHash = "97baf123d6fc43e96cd9872b3bf87456"; window.__AudioEyeInstallSource = "duda"; var a=document.createElement("script"); a.src="https://wsv3cdn.audioeye-services.com/aem.js"; a.type="text/javascript"; a.setAttribute("async",""); document.getElementsByTagName("body")[0].appendChild(a)}; "complete"!==document.readyState?window.addEventListener?window.addEventListener("load",b):window.attachEvent&&window.attachEvent("onload",b):b()}(); </script>
2439 2440</div> 2441</div> 2442</div> 2443</div> 2444</div> 2445</div> 2446</div> 2447</div> 2448 2449 </div> 2450</div> 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493<link rel="preload" href="https://cdn.hibuwebsites.com/fonts/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Be+Vietnam:ital,wght@0,100;0,200;0,300;0,400;0,600;0,700;0,800;0,900&family=Kumbh+Sans:ital,wght@0,100..900;1,100..900&family=Bebas+Neue:ital,wght@0,400&family=Red+Hat+Display:ital,wght@0,300..900;1,300..900&family=Questrial:ital,wght@0,400&subset=latin-ext&display=swap" as="style" fetchpriority="low" onload="loadCSS(this)" /> 2494 2495 2496 2497 2498 2499 2500<link rel="preload" as="style" fetchpriority="low" onload="loadCSS(this)" href="https://static-res-cdn.websites.hibu.com/mnlt/production/6839/_dm/s/rt/dist/css/d-css-runtime-flex-new-nav.min.css" /> 2501 2502 2503 2504<link rel="preload" href="https://cdn.hibuwebsites.com/WIDGET_CSS/fca9a6fe71e7ea866e7bf55ef055d883.css" id="widgetCSS" as="style" fetchpriority="low" onload="loadCSS(this)" /> 2505 2506 2507<style>img[width][height] { 2508 height: auto; 2509}</style> 2510 2511 2512<style> 2513 body[data-page-alias="home"] #dm [data-show-on-page-only="home"] { 2514 display: block !important; 2515 } 2516</style> 2517 2518 2519<style id="pageAdditionalWidgetsCss" type="text/css"> 2520</style> 2521 2522 2523 2524 2525 2526<link rel="preload" href="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/files/7720a79493434d7dbf0e283d7c6423e7_withFlex_1.min.css?v=5465c1c5c6af034c5a53c608608d3063" id="siteGlobalCss" as="style" fetchpriority="low" onload="loadCSS(this)" /> 2527 2528 2529 2530<link 2531 type="text/css" rel="stylesheet" 2532 href="/_dm/s/rt/css/hibu/hibu-runtime.css?version=2026-10-08T12_48_49" 2533/> 2534 2535 2536<style id="customWidgetStyle" type="text/css"> 2537 2538</style> 2539<style id="innerPagesStyle" type="text/css"> 2540 2541</style> 2542 2543 2544<style 2545 id="additionalGlobalCss" type="text/css" 2546> 2547</style> 2548 2549 2550<link rel="preload" href="https://cdn.hibuwebsites.com/7720a79493434d7dbf0e283d7c6423e7/files/7720a79493434d7dbf0e283d7c6423e7_home_withFlex_1.min.css?v=b0c4d42eafe1c63ded1abbd9a3107b76" id="homeCssLink" as="style" fetchpriority="low" onload="loadCSS(this)" /> 2551 2552<style id="pagestyle" type="text/css"> 2553 2554</style> 2555 2556<style id="pagestyleDevice" type="text/css"> 2557 2558</style> 2559 2560 2561 2562 2563 2564 2565 2566<style id="globalFontSizeStyle" type="text/css"> 2567 @media (min-width: 1025px) { [data-version] .size-13, [data-version] .font-size-13 {--font-size: 13;}[data-version] .size-20, [data-version] .font-size-20 {--font-size: 20;}[data-version] .size-18, [data-version] .font-size-18 {--font-size: 18;}[data-version] .size-15, [data-version] .font-size-15 {--font-size: 15;} }@media (min-width: 768px) and (max-width: 1024px) { [data-version] .t-size-13, [data-version] .t-font-size-13 {--font-size: 13;}[data-version] .t-size-17, [data-version] .t-font-size-17 {--font-size: 17;}[data-version] .t-size-16, [data-version] .t-font-size-16 {--font-size: 16;}[data-version] .t-size-15, [data-version] .t-font-size-15 {--font-size: 15;} }@media (max-width: 767px) { [data-version] .m-size-13, [data-version] .m-font-size-13 {--font-size: 13;}[data-version] .m-size-16, [data-version] .m-font-size-16 {--font-size: 16;}[data-version] .m-size-15, [data-version] .m-font-size-15 {--font-size: 15;} } 2568</style> 2569<style id="pageFontSizeStyle" type="text/css"> 2570</style> 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610
2611<script> 2612 var isWLR = true; 2613 2614 window.customWidgetsFunctions = {}; 2615 window.customWidgetsStrings = {}; 2616 window.collections = {}; 2617 window.currentLanguage = "ENGLISH" 2618 window.isSitePreview = false; 2619</script>
2619 2620 2621 2622
2623<script> 2624 window.customWidgetsFunctions["8ff5270554664bddaecbe7a0b9e45c81~14"] = function (element, data, api) { 2625 window.dmAPI.runOnReady( 2626 2627 'ucw-unified-' + 2628 2629 ( 2630 2631 element.id || 2632 2633 Math.random().toString(36).slice(2) 2634 2635 ), 2636 2637 async () => { 2638 2639 const root = element.querySelector('.ucw-wrapper'); 2640 2641 2642 2643 if (!root) return; 2644 2645 2646 2647 const calloutEl = root.querySelector('.ucw-callout'); 2648 2649 const calloutMount = root.querySelector('.ucw-callout__mount'); 2650 2651 const couponEl = root.querySelector('.ucw-coupon'); 2652 2653 const couponGrid = root.querySelector('.ucw-coupon__grid'); 2654 2655 const actionTemplate = root.querySelector('.ucw-action-template'); 2656 2657 2658 2659 if ( 2660 2661 !calloutEl || 2662 2663 !calloutMount || 2664 2665 !couponEl || 2666 2667 !couponGrid || 2668 2669 !actionTemplate 2670 2671 ) { 2672 2673 root.hidden = true; 2674 2675 return; 2676 2677 } 2678 2679 2680 2681 const config = data.config || {}; 2682 2683 2684 2685 /* 2686 2687 Prevent an older async run from overwriting a newer 2688 2689 Duda rerender of the same widget instance. 2690 2691 */ 2692 2693 const instanceToken = {}; 2694 2695 root.__ucwInstanceToken = instanceToken; 2696 2697 2698 2699 function isCurrentInstance() { 2700 2701 return root.__ucwInstanceToken === instanceToken; 2702 2703 } 2704 2705 2706 2707 if (root.__ucwEntranceObserver) { 2708 2709 root.__ucwEntranceObserver.disconnect(); 2710 2711 root.__ucwEntranceObserver = null; 2712 2713 } 2714 2715 2716 2717 function safeTrim(value) { 2718 2719 return value == null 2720 2721 ? '' 2722 2723 : String(value).trim(); 2724 2725 } 2726 2727 2728 2729 function stripHtml(value) { 2730 2731 const temporaryElement = 2732 2733 document.createElement('div'); 2734 2735 2736 2737 temporaryElement.innerHTML = 2738 2739 safeTrim(value); 2740 2741 2742 2743 return safeTrim( 2744 2745 temporaryElement.textContent || 2746 2747 temporaryElement.innerText || 2748 2749 '' 2750 2751 ); 2752 2753 } 2754 2755 2756 2757 function normalizeBoolean(value, fallbackValue) { 2758 2759 if (typeof value === 'boolean') { 2760 2761 return value; 2762 2763 } 2764 2765 2766 2767 if (value === 1 || value === '1') { 2768 2769 return true; 2770 2771 } 2772 2773 2774 2775 if (value === 0 || value === '0') { 2776 2777 return false; 2778 2779 } 2780 2781 2782 2783 const normalizedValue = 2784 2785 safeTrim(value).toLowerCase(); 2786 2787 2788 2789 if ( 2790 2791 [ 2792 2793 'true', 2794 2795 'yes', 2796 2797 'on', 2798 2799 'enabled' 2800 2801 ].includes(normalizedValue) 2802 2803 ) { 2804 2805 return true; 2806 2807 } 2808 2809 2810 2811 if ( 2812 2813 [ 2814 2815 'false', 2816 2817 'no', 2818 2819 'off', 2820 2821 'disabled' 2822 2823 ].includes(normalizedValue) 2824 2825 ) { 2826 2827 return false; 2828 2829 } 2830 2831 2832 2833 return fallbackValue; 2834 2835 } 2836 2837 2838 2839 function clampNumber( 2840 2841 value, 2842 2843 minimum, 2844 2845 maximum, 2846 2847 fallbackValue 2848 2849 ) { 2850 2851 const parsedValue = Number(value); 2852 2853 2854 2855 if (!Number.isFinite(parsedValue)) { 2856 2857 return fallbackValue; 2858 2859 } 2860 2861 2862 2863 return Math.min( 2864 2865 Math.max(parsedValue, minimum), 2866 2867 maximum 2868 2869 ); 2870 2871 } 2872 2873 2874 2875 function extractImageUrl(imageValue) { 2876 2877 if (!imageValue) return ''; 2878 2879 2880 2881 if (typeof imageValue === 'string') { 2882 2883 return safeTrim(imageValue); 2884 2885 } 2886 2887 2888 2889 if (typeof imageValue !== 'object') { 2890 2891 return ''; 2892 2893 } 2894 2895 2896 2897 const possibleValues = [ 2898 2899 imageValue.url, 2900 2901 imageValue.src, 2902 2903 imageValue.image_url, 2904 2905 imageValue.original_url, 2906 2907 imageValue.originalUrl, 2908 2909 imageValue.full, 2910 2911 imageValue.data && imageValue.data.url, 2912 2913 imageValue.data && imageValue.data.src 2914 2915 ]; 2916 2917 2918 2919 for (const possibleValue of possibleValues) { 2920 2921 const imageUrl = 2922 2923 safeTrim(possibleValue); 2924 2925 2926 2927 if (imageUrl) { 2928 2929 return imageUrl; 2930 2931 } 2932 2933 } 2934 2935 2936 2937 return ''; 2938 2939 } 2940 2941 2942 2943 function extractLinkValue(linkValue) { 2944 2945 if (!linkValue) return ''; 2946 2947 2948 2949 if (typeof linkValue === 'string') { 2950 2951 return safeTrim(linkValue); 2952 2953 } 2954 2955 2956 2957 if (typeof linkValue !== 'object') { 2958 2959 return ''; 2960 2961 } 2962 2963 2964 2965 const possibleValues = [ 2966 2967 linkValue.url, 2968 2969 linkValue.href, 2970 2971 linkValue.runtime_url, 2972 2973 linkValue.raw_url, 2974 2975 linkValue.value 2976 2977 ]; 2978 2979 2980 2981 for (const possibleValue of possibleValues) { 2982 2983 const link = 2984 2985 safeTrim(possibleValue); 2986 2987 2988 2989 if (link) { 2990 2991 return link; 2992 2993 } 2994 2995 } 2996 2997 2998 2999 return ''; 3000 3001 } 3002 3003 3004 3005 function getLastSlug(value) { 3006 3007 let normalizedValue = 3008 3009 safeTrim(value).toLowerCase(); 3010 3011 3012 3013 if (!normalizedValue) return ''; 3014 3015 3016
3017 try { 3018 3019 if ( 3020 3021 /^https?:\/\//i.test(normalizedValue) 3022 3023 ) { 3024 3025 normalizedValue = 3026 3027 new URL(normalizedValue).pathname; 3028 3029 } 3030 3031 } catch (e) { 3032 3033 // Retain the original value. 3034 3035 } 3036 3037 3038 3039 normalizedValue = normalizedValue 3040 3041 .split('?')[0] 3042 3043 .split('#')[0] 3044 3045 .replace(/^\/+|\/+$/g, ''); 3046 3047 3048 3049 const pathParts = 3050 3051 normalizedValue 3052 3053 .split('/') 3054 3055 .filter(Boolean); 3056 3057 3058 3059 return pathParts.length 3060 3061 ? pathParts[pathParts.length - 1] 3062 3063 : ''; 3064 3065 } 3066 3067 3068 3069 function getCurrentSlug() { 3070 3071 return getLastSlug( 3072 3073 window.location.pathname || '' 3074 3075 ); 3076 3077 } 3078 3079 3080 3081 function getSitePrefixFromOwnFrame() { 3082 3083 const ownPath = 3084 3085 window.location.pathname || ''; 3086 3087 3088 3089 const match = ownPath.match( 3090 3091 /^(\/site\/[^/]+)/ 3092 3093 ); 3094 3095 3096 3097 return match ? match[1] : ''; 3098 3099 } 3100 3101 3102 3103 function getPreviewParameters() { 3104 3105 const output = new URLSearchParams(); 3106 3107 3108 3109 try { 3110 3111 const currentParameters = 3112 3113 new URLSearchParams( 3114 3115 window.location.search || '' 3116 3117 ); 3118 3119 3120 3121 [ 3122 3123 'showOriginal', 3124 3125 'preview', 3126 3127 'insitepreview', 3128 3129 'dm_device', 3130 3131 't', 3132 3133 'dm_try_mode', 3134 3135 'dm_checkSync' 3136 3137 ].forEach(key => { 3138 3139 if (currentParameters.has(key)) { 3140 3141 output.set( 3142 3143 key, 3144 3145 currentParameters.get(key) 3146 3147 ); 3148 3149 } 3150 3151 }); 3152 3153 } catch (e) { 3154 3155 // Return an empty parameter set. 3156 3157 } 3158 3159 3160 3161 return output; 3162 3163 } 3164 3165 3166 3167 function normalizeButtonLink(linkValue) { 3168 3169 const rawLink = 3170 3171 extractLinkValue(linkValue); 3172 3173 3174 3175 if (!rawLink) return ''; 3176 3177 3178 3179 if ( 3180 3181 /^(javascript|data|vbscript):/i.test( 3182 3183 rawLink 3184 3185 ) 3186 3187 ) { 3188 3189 return ''; 3190 3191 } 3192 3193 3194 3195 if ( 3196 3197 /^(https?:|tel:|mailto:|sms:)/i.test( 3198 3199 rawLink 3200 3201 ) || 3202 3203 rawLink.startsWith('//') || 3204 3205 rawLink.startsWith('#') 3206 3207 ) { 3208 3209 return rawLink; 3210 3211 } 3212 3213 3214 3215 let pathPart = rawLink; 3216 3217 let hashPart = ''; 3218 3219 3220 3221 const hashIndex = 3222 3223 pathPart.indexOf('#'); 3224 3225 3226 3227 if (hashIndex !== -1) { 3228 3229 hashPart = pathPart.slice(hashIndex); 3230 3231 pathPart = pathPart.slice(0, hashIndex); 3232 3233 } 3234 3235 3236 3237 let queryString = ''; 3238 3239 const queryIndex = 3240 3241 pathPart.indexOf('?'); 3242 3243 3244 3245 if (queryIndex !== -1) { 3246 3247 queryString = pathPart.slice(queryIndex + 1); 3248 3249 pathPart = pathPart.slice(0, queryIndex); 3250 3251 } 3252 3253 3254 3255 pathPart = safeTrim(pathPart); 3256 3257 3258 3259 if (!pathPart.startsWith('/')) { 3260 3261 pathPart = '/' + pathPart; 3262 3263 } 3264 3265 3266 3267 const sitePrefix = 3268 3269 getSitePrefixFromOwnFrame(); 3270 3271 3272 3273 if ( 3274 3275 sitePrefix && 3276 3277 !pathPart.startsWith(sitePrefix + '/') 3278 3279 ) { 3280 3281 pathPart = sitePrefix + pathPart; 3282 3283 } 3284 3285 3286 3287 const combinedParameters = 3288 3289 new URLSearchParams(queryString); 3290 3291 3292 3293 getPreviewParameters().forEach( 3294 3295 (parameterValue, parameterName) => { 3296 3297 if ( 3298 3299 !combinedParameters.has( 3300 3301 parameterName 3302 3303 ) 3304 3305 ) { 3306 3307 combinedParameters.set( 3308 3309 parameterName, 3310 3311 parameterValue 3312 3313 ); 3314 3315 } 3316 3317 } 3318 3319 ); 3320 3321 3322 3323 const combinedQuery = 3324 3325 combinedParameters.toString(); 3326 3327 3328 3329 return ( 3330 3331 pathPart + 3332 3333 ( 3334 3335 combinedQuery 3336 3337 ? '?' + combinedQuery 3338 3339 : '' 3340 3341 ) + 3342 3343 hashPart 3344 3345 ); 3346 3347 } 3348 3349 3350 3351 function isEditorCanvasOnly() { 3352 3353 try { 3354 3355 const topHref = 3356 3357 window.top.location.href || ''; 3358 3359 3360 3361 if (topHref.includes('#preview')) { 3362 3363 return false; 3364 3365 } 3366 3367 3368 3369 if (topHref.includes('/home/site/')) { 3370 3371 return true; 3372 3373 } 3374 3375 } catch (e) { 3376 3377 return Boolean(data.inEditor); 3378 3379 } 3380 3381 3382 3383 return Boolean(data.inEditor); 3384 3385 } 3386 3387 3388 3389 if (root.__ucwEditorClickHandler) { 3390 3391 root.removeEventListener( 3392 3393 'click', 3394 3395 root.__ucwEditorClickHandler, 3396 3397 true 3398 3399 ); 3400 3401 } 3402 3403 3404 3405 root.__ucwEditorClickHandler = 3406 3407 event => { 3408 3409 const actionLink = 3410 3411 event.target.closest( 3412 3413 '.ucw-card__actionLink' 3414 3415 ); 3416 3417 3418 3419 if ( 3420 3421 actionLink && 3422 3423 root.contains(actionLink) && 3424 3425 isEditorCanvasOnly() 3426 3427 ) { 3428 3429 event.preventDefault(); 3430 3431 event.stopPropagation(); 3432 3433 event.stopImmediatePropagation(); 3434 3435 } 3436 3437 }; 3438 3439 3440 3441 root.addEventListener( 3442 3443 'click', 3444 3445 root.__ucwEditorClickHandler, 3446 3447 true 3448 3449 ); 3450 3451 3452 3453 const prefersReducedMotion = 3454 3455 window.matchMedia 3456 3457 ? window 3458 3459 .matchMedia( 3460 3461 '(prefers-reduced-motion: reduce)' 3462 3463 ) 3464 3465 .matches 3466 3467 : false;
3468 3469 3470 3471 /* 3472 3473 Shared across every copy of the widget on the page. 3474 3475 */ 3476 3477 function getSharedStore() { 3478 3479 if (!window.__ucwUnifiedSharedStore) { 3480 3481 window.__ucwUnifiedSharedStore = { 3482 3483 collectionsApiPromise: null, 3484 3485 contentLibraryPromise: null, 3486 3487 collectionPromises: {}, 3488 3489 defaultLogoPromise: null 3490 3491 }; 3492 3493 } 3494 3495 3496 3497 return window.__ucwUnifiedSharedStore; 3498 3499 } 3500 3501 3502 3503 function getCollectionsApi() { 3504 3505 const sharedStore = 3506 3507 getSharedStore(); 3508 3509 3510 3511 if (!sharedStore.collectionsApiPromise) { 3512 3513 sharedStore.collectionsApiPromise = 3514 3515 window.dmAPI 3516 3517 .loadCollectionsAPI() 3518 3519 .catch(error => { 3520 3521 sharedStore.collectionsApiPromise = 3522 3523 null; 3524 3525 3526 3527 throw error; 3528 3529 }); 3530 3531 } 3532 3533 3534 3535 return sharedStore.collectionsApiPromise; 3536 3537 } 3538 3539 3540 3541 function loadCollection(collectionName) { 3542 3543 const sharedStore = 3544 3545 getSharedStore(); 3546 3547 3548 3549 if ( 3550 3551 !sharedStore.collectionPromises[ 3552 3553 collectionName 3554 3555 ] 3556 3557 ) { 3558 3559 sharedStore.collectionPromises[ 3560 3561 collectionName 3562 3563 ] = getCollectionsApi() 3564 3565 .then(collections => 3566 3567 collections 3568 3569 .data(collectionName) 3570 3571 .get() 3572 3573 ) 3574 3575 .then(result => { 3576 3577 if ( 3578 3579 result && 3580 3581 Array.isArray(result.values) 3582 3583 ) { 3584 3585 return result.values; 3586 3587 } 3588 3589 3590 3591 if (Array.isArray(result)) { 3592 3593 return result; 3594 3595 } 3596 3597 3598 3599 return []; 3600 3601 }) 3602 3603 .catch(error => { 3604 3605 delete sharedStore 3606 3607 .collectionPromises[ 3608 3609 collectionName 3610 3611 ]; 3612 3613 3614 3615 throw error; 3616 3617 }); 3618 3619 } 3620 3621 3622 3623 return sharedStore.collectionPromises[ 3624 3625 collectionName 3626 3627 ]; 3628 3629 } 3630 3631 3632 3633 function loadContentLibrary() { 3634 3635 const sharedStore = 3636 3637 getSharedStore(); 3638 3639 3640 3641 if (!sharedStore.contentLibraryPromise) { 3642 3643 sharedStore.contentLibraryPromise = 3644 3645 window.dmAPI 3646 3647 .loadContentLibrary() 3648 3649 .catch(error => { 3650 3651 sharedStore.contentLibraryPromise = 3652 3653 null; 3654 3655 3656 3657 throw error; 3658 3659 }); 3660 3661 } 3662 3663 3664 3665 return sharedStore.contentLibraryPromise; 3666 3667 } 3668 3669 3670 3671 function loadDefaultLogo() { 3672 3673 const sharedStore = 3674 3675 getSharedStore(); 3676 3677 3678 3679 if (!sharedStore.defaultLogoPromise) { 3680 3681 sharedStore.defaultLogoPromise = 3682 3683 loadContentLibrary() 3684 3685 .then(contentLibrary => { 3686 3687 const siteImages = 3688 3689 contentLibrary && 3690 3691 Array.isArray( 3692 3693 contentLibrary.site_images 3694 3695 ) 3696 3697 ? contentLibrary.site_images 3698 3699 : []; 3700 3701 3702 3703 const logoEntry = 3704 3705 siteImages.find( 3706 3707 image => 3708 3709 image && 3710 3711 image.label === 3712 3713 'dark-logo' 3714 3715 ); 3716 3717 3718 3719 return logoEntry 3720 3721 ? extractImageUrl(logoEntry) 3722 3723 : ''; 3724 3725 }) 3726 3727 .catch(error => { 3728 3729 sharedStore.defaultLogoPromise = 3730 3731 null; 3732 3733 3734 3735 throw error; 3736 3737 }); 3738 3739 } 3740 3741 3742 3743 return sharedStore.defaultLogoPromise; 3744 3745 } 3746 3747 3748 3749 function getRowData(row) { 3750 3751 return row && row.data 3752 3753 ? row.data 3754 3755 : row || {}; 3756 3757 } 3758 3759 3760 3761 /* 3762 Notify the site's Dynamic Phone Number Insertion (DPNI) script 3763 after this widget has placed a phone number into the live DOM. 3764 3765 The site-level DPNI integration already listens for 3766 YextPhoneChangeEvent and reruns its replacement scan when that 3767 event is fired. Keeping this notification here makes the widget 3768 compatible with any phone number returned by Yext_Phones rather 3769 than tying it to a specific number or site. 3770 */ 3771 function notifyDynamicPhoneInsertion(phone) { 3772 if (!safeTrim(phone)) return; 3773 3774 const dispatchPhoneChangeEvent = () => { 3775 if (!isCurrentInstance()) return; 3776 3777 try { 3778 document.dispatchEvent( 3779 new Event('YextPhoneChangeEvent') 3780 ); 3781 } catch (e) { 3782 try { 3783 const phoneChangeEvent = 3784 document.createEvent('Event'); 3785 3786 phoneChangeEvent.initEvent( 3787 'YextPhoneChangeEvent', 3788 true, 3789 true 3790 ); 3791 3792 document.dispatchEvent( 3793 phoneChangeEvent 3794 ); 3795 } catch (legacyEventError) { 3796 // DPNI notification is optional; widget rendering continues. 3797 } 3798 } 3799 }; 3800 3801 /* 3802 Wait until the generated card/button has been committed to the 3803 DOM before asking DPNI to rescan it. A short delayed second pass 3804 also covers Duda/site scripts that finish their own ready work 3805 immediately after this widget renders. 3806 */ 3807 requestAnimationFrame(() => { 3808 dispatchPhoneChangeEvent(); 3809 3810 window.setTimeout( 3811 dispatchPhoneChangeEvent, 3812 100 3813 ); 3814 }); 3815 } 3816 3817 function loadPhone() { 3818 3819 return loadCollection('Yext_Phones') 3820 3821 .then(phoneRows => { 3822 3823 const mainPhoneRow = 3824 3825 phoneRows.find(row => { 3826 3827 const phoneData = 3828 3829 getRowData(row); 3830 3831 3832 3833 return safeTrim( 3834 3835 phoneData.Type 3836 3837 ).toLowerCase() === 3838 3839 'mainphone'; 3840 3841 }); 3842 3843 3844 3845 if (!mainPhoneRow) { 3846 3847 return ''; 3848 3849 } 3850 3851 3852 3853 const mainPhoneData = 3854 3855 getRowData(mainPhoneRow); 3856 3857 3858 3859 return safeTrim( 3860 3861 mainPhoneData.Phone 3862 3863 ); 3864 3865 }) 3866 3867 .catch(() => ''); 3868 3869 } 3870 3871 3872 3873 const cardDesign = 3874 3875 config.cardDesign || {}; 3876 3877 3878 3879 const logoDesign = 3880 3881 config.logoDesign || {}; 3882 3883 3884 3885 const buttonDesign = 3886 3887 config.buttonDesign || {}; 3888 3889 3890 3891 const animationDesign = 3892 3893 config.animationDesign || {}; 3894 3895 3896 3897 const calloutLayout = 3898 3899 config.calloutLayout || {}; 3900 3901 3902 3903 /* 3904 3905 Optional advanced spacing controls. 3906 3907 3908 3909 The master toggle is off by default so the original responsive 3910 3911 spacing remains completely unchanged until a designer enables it. 3912 3913 Values may live inside spacingDesign or directly on data.config. 3914 3915 */ 3916 3917 const spacingDesign = 3918 3919 config.spacingDesign || 3920 3921 config.spacing || 3922 3923 {}; 3924 3925 3926 3927 const cardContentAlign = 3928 3929 [ 3930 3931 'left', 3932 3933 'center', 3934 3935 'right' 3936 3937 ].includes( 3938 3939 safeTrim( 3940 3941 cardDesign.cardContentAlign || 3942 3943 config.cardContentAlign 3944 3945 ).toLowerCase() 3946 3947 ) 3948 3949 ? safeTrim( 3950 3951 cardDesign.cardContentAlign || 3952 3953 config.cardContentAlign 3954 3955 ).toLowerCase() 3956 3957 : 'center'; 3958 3959 3960 3961 const cardVerticalAlign = 3962 3963 [ 3964 3965 'top', 3966 3967 'middle', 3968 3969 'bottom' 3970 3971 ].includes( 3972 3973 safeTrim( 3974 3975 cardDesign.cardVerticalAlign || 3976 3977 config.cardVerticalAlign 3978 3979 ).toLowerCase() 3980 3981 ) 3982 3983 ? safeTrim( 3984 3985 cardDesign.cardVerticalAlign || 3986 3987 config.cardVerticalAlign 3988 3989 ).toLowerCase() 3990 3991 : 'top'; 3992 3993 3994 3995 function applyCardShadowTokens() { 3996 3997 const shadowPreset = 3998 3999 safeTrim( 4000 4001 cardDesign.cardShadow || 4002 4003 config.cardShadow || 4004 4005 'none' 4006 4007 ).toLowerCase(); 4008 4009 4010 4011 const shadowMap = { 4012 4013 none: 'none', 4014 4015 soft: 4016 4017 '0 2px 8px rgba(0, 0, 0, 0.08)', 4018 4019 medium: 4020 4021 '0 4px 16px rgba(0, 0, 0, 0.14)', 4022 4023 strong: 4024 4025 '0 8px 30px rgba(0, 0, 0, 0.22)', 4026 4027 accent: 4028 4029 '0 4px 20px var(--ucw-accent-shadow)' 4030 4031 }; 4032 4033 4034 4035 const hoverMap = { 4036 4037 none: 4038 4039 '0 8px 32px var(--ucw-accent-glow)', 4040 4041 soft: 4042 4043 '0 6px 20px rgba(0, 0, 0, 0.14)', 4044 4045 medium: 4046 4047 '0 10px 28px rgba(0, 0, 0, 0.20)', 4048 4049 strong: 4050 4051 '0 16px 40px rgba(0, 0, 0, 0.28)', 4052 4053 accent: 4054 4055 '0 8px 32px var(--ucw-accent-glow)' 4056 4057 }; 4058 4059 4060 4061 root.style.setProperty( 4062
4063 '--ucw-card-shadow', 4064 4065 shadowMap[shadowPreset] || 4066 4067 shadowMap.none 4068 4069 ); 4070 4071 4072 4073 root.style.setProperty( 4074 4075 '--ucw-card-shadow-hover', 4076 4077 hoverMap[shadowPreset] || 4078 4079 hoverMap.none 4080 4081 ); 4082 4083 } 4084 4085 4086 4087 const enableEntranceAnimation = 4088 4089 normalizeBoolean( 4090 4091 animationDesign.enableEntranceAnimation, 4092 4093 normalizeBoolean( 4094 4095 config.enableEntranceAnimation, 4096 4097 false 4098 4099 ) 4100 4101 ); 4102 4103 4104 4105 const enableCardHover = 4106 4107 normalizeBoolean( 4108 4109 animationDesign.enableCardHover, 4110 4111 normalizeBoolean( 4112 4113 config.enableCardHover, 4114 4115 false 4116 4117 ) 4118 4119 ); 4120 4121 4122 4123 const enableLogoHover = 4124 4125 normalizeBoolean( 4126 4127 animationDesign.enableLogoHover, 4128 4129 normalizeBoolean( 4130 4131 config.enableLogoHover, 4132 4133 false 4134 4135 ) 4136 4137 ); 4138 4139 4140 4141 const enableButtonHover = 4142 4143 normalizeBoolean( 4144 4145 animationDesign.enableButtonHover, 4146 4147 normalizeBoolean( 4148 4149 config.enableButtonHover, 4150 4151 false 4152 4153 ) 4154 4155 ); 4156 4157 4158 4159 const enableButtonRipple = 4160 4161 normalizeBoolean( 4162 4163 animationDesign.enableButtonRipple, 4164 4165 normalizeBoolean( 4166 4167 config.enableButtonRipple, 4168 4169 false 4170 4171 ) 4172 4173 ); 4174 4175 4176 4177 const enablePhonePulse = 4178 4179 normalizeBoolean( 4180 4181 animationDesign.enablePhonePulse, 4182 4183 normalizeBoolean( 4184 4185 config.enablePhonePulse, 4186 4187 false 4188 4189 ) 4190 4191 ); 4192 4193 4194 4195 root.classList.toggle( 4196 4197 'ucw-animate-entrance', 4198 4199 enableEntranceAnimation 4200 4201 ); 4202 4203 4204 4205 root.classList.toggle( 4206 4207 'ucw-animate-card-hover', 4208 4209 enableCardHover 4210 4211 ); 4212 4213 4214 4215 root.classList.toggle( 4216 4217 'ucw-animate-logo-hover', 4218 4219 enableLogoHover 4220 4221 ); 4222 4223 4224 4225 root.classList.toggle( 4226 4227 'ucw-animate-button-hover', 4228 4229 enableButtonHover 4230 4231 ); 4232 4233 4234 4235 root.classList.toggle( 4236 4237 'ucw-animate-phone-pulse', 4238 4239 enablePhonePulse 4240 4241 ); 4242 4243 4244 4245 const logoWidth = 4246 4247 Math.round( 4248 4249 clampNumber( 4250 4251 logoDesign.logoWidth || 4252 4253 config.logoWidth, 4254 4255 20, 4256 4257 1000, 4258 4259 220 4260 4261 ) 4262 4263 ); 4264 4265 4266 4267 const logoMaxHeight = 4268 4269 Math.round( 4270 4271 clampNumber( 4272 4273 logoDesign.logoMaxHeight || 4274 4275 config.logoMaxHeight, 4276 4277 20, 4278 4279 500, 4280 4281 100 4282 4283 ) 4284 4285 ); 4286 4287 4288 4289 const logoSpacing = 4290 4291 Math.round( 4292 4293 clampNumber( 4294 4295 logoDesign.logoSpacing || 4296 4297 config.logoSpacing, 4298 4299 0, 4300 4301 200, 4302 4303 12 4304 4305 ) 4306 4307 ); 4308 4309 4310 4311 const logoAlign = 4312 4313 [ 4314 4315 'left', 4316 4317 'center', 4318 4319 'right' 4320 4321 ].includes( 4322 4323 safeTrim( 4324 4325 logoDesign.logoAlign || 4326 4327 config.logoAlign || 4328 4329 'center' 4330 4331 ).toLowerCase() 4332 4333 ) 4334 4335 ? safeTrim( 4336 4337 logoDesign.logoAlign || 4338 4339 config.logoAlign || 4340 4341 'center' 4342 4343 ).toLowerCase() 4344 4345 : 'center'; 4346 4347 4348 4349 root.style.setProperty( 4350 4351 '--ucw-logo-width', 4352 4353 logoWidth + 'px' 4354 4355 ); 4356 4357 4358 4359 root.style.setProperty( 4360 4361 '--ucw-logo-max-height', 4362 4363 logoMaxHeight + 'px' 4364 4365 ); 4366 4367 4368 4369 root.style.setProperty( 4370 4371 '--ucw-logo-spacing', 4372 4373 logoSpacing + 'px' 4374 4375 ); 4376 4377 4378 4379 root.style.setProperty( 4380 4381 '--ucw-logo-align', 4382 4383 logoAlign 4384 4385 ); 4386 4387 4388 4389 const buttonLayout = 4390 4391 [ 4392 4393 'row', 4394 4395 'stacked' 4396 4397 ].includes( 4398 4399 safeTrim( 4400 4401 buttonDesign.buttonLayout || 4402 4403 config.buttonLayout || 4404 4405 'row' 4406 4407 ).toLowerCase() 4408 4409 ) 4410 4411 ? safeTrim( 4412 4413 buttonDesign.buttonLayout || 4414 4415 config.buttonLayout || 4416 4417 'row' 4418 4419 ).toLowerCase() 4420 4421 : 'row'; 4422 4423 4424 4425 const buttonAlign = 4426 4427 [ 4428 4429 'left', 4430 4431 'center', 4432 4433 'right' 4434 4435 ].includes( 4436 4437 safeTrim( 4438 4439 buttonDesign.buttonAlign || 4440 4441 config.buttonAlign || 4442 4443 'center' 4444 4445 ).toLowerCase() 4446 4447 ) 4448 4449 ? safeTrim( 4450 4451 buttonDesign.buttonAlign || 4452 4453 config.buttonAlign || 4454 4455 'center' 4456 4457 ).toLowerCase() 4458 4459 : 'center'; 4460 4461 4462 4463 const buttonGap = 4464 4465 Math.round( 4466 4467 clampNumber( 4468 4469 buttonDesign.buttonGap || 4470 4471 config.buttonGap, 4472 4473 0, 4474 4475 100, 4476 4477 12 4478 4479 ) 4480 4481 ); 4482 4483 4484 4485 const fullWidthButtonsMobile = 4486 4487 normalizeBoolean( 4488 4489 buttonDesign.fullWidthButtonsMobile, 4490 4491 normalizeBoolean( 4492 4493 config.fullWidthButtonsMobile, 4494 4495 true 4496 4497 ) 4498 4499 ); 4500 4501 4502 4503 root.style.setProperty( 4504 4505 '--ucw-button-gap', 4506 4507 buttonGap + 'px' 4508 4509 ); 4510 4511 4512 4513 root.classList.toggle( 4514 4515 'ucw-actions-stacked', 4516 4517 buttonLayout === 'stacked' 4518 4519 ); 4520 4521 4522 4523 root.classList.toggle( 4524 4525 'ucw-actions-align-left', 4526 4527 buttonAlign === 'left' 4528 4529 ); 4530 4531 4532 4533 root.classList.toggle( 4534 4535 'ucw-actions-align-center', 4536 4537 buttonAlign === 'center' 4538 4539 ); 4540 4541 4542 4543 root.classList.toggle( 4544 4545 'ucw-actions-align-right', 4546 4547 buttonAlign === 'right' 4548 4549 ); 4550 4551 4552 4553 root.classList.toggle( 4554 4555 'ucw-mobile-buttons-full', 4556 4557 fullWidthButtonsMobile 4558 4559 ); 4560 4561 4562 4563 /* 4564 4565 Advanced spacing is opt-in. When disabled, the CSS continues using 4566 4567 the widget's original desktop, tablet, and mobile spacing values. 4568 4569 */ 4570 4571 const customizeSpacing = 4572 4573 normalizeBoolean( 4574 4575 spacingDesign.customizeSpacing ?? 4576 4577 spacingDesign.enableCustomSpacing ?? 4578 4579 config.customizeSpacing ?? 4580 4581 config.enableCustomSpacing, 4582 4583 false 4584 4585 ); 4586 4587 4588 4589 const couponGap = 4590 4591 Math.round( 4592 4593 clampNumber( 4594 4595 spacingDesign.couponGap ?? 4596 4597 config.couponGap, 4598 4599 0, 4600 4601 100, 4602 4603 20 4604 4605 ) 4606 4607 ); 4608 4609 4610 4611 const logoBottomGap = 4612 4613 Math.round( 4614 4615 clampNumber( 4616 4617 spacingDesign.logoBottomGap ?? 4618 4619 config.logoBottomGap, 4620 4621 0, 4622 4623 100, 4624 4625 24 4626 4627 ) 4628 4629 ); 4630 4631 4632 4633 const headlineBottomGap = 4634 4635 Math.round( 4636 4637 clampNumber( 4638 4639 spacingDesign.headlineBottomGap ?? 4640 4641 config.headlineBottomGap, 4642 4643 0, 4644 4645 100, 4646 4647 12 4648 4649 ) 4650 4651 ); 4652 4653 4654 4655 const bodyBottomGap = 4656 4657 Math.round( 4658 4659 clampNumber( 4660 4661 spacingDesign.bodyBottomGap ?? 4662 4663 config.bodyBottomGap, 4664 4665 0, 4666 4667 100, 4668 4669 12 4670 4671 ) 4672 4673 ); 4674 4675 4676 4677 const ctaBottomGap = 4678 4679 Math.round( 4680 4681 clampNumber( 4682 4683 spacingDesign.ctaBottomGap ?? 4684 4685 config.ctaBottomGap, 4686 4687 0, 4688 4689 100, 4690 4691 12 4692 4693 ) 4694 4695 ); 4696 4697 4698 4699 const termsBottomGap = 4700 4701 Math.round( 4702 4703 clampNumber( 4704 4705 spacingDesign.termsBottomGap ?? 4706 4707 config.termsBottomGap, 4708 4709 0, 4710 4711 100, 4712 4713 12 4714 4715 ) 4716 4717 ); 4718 4719 4720 4721 const buttonBottomGap = 4722 4723 Math.round( 4724 4725 clampNumber( 4726 4727 spacingDesign.buttonBottomGap ?? 4728 4729 config.buttonBottomGap, 4730 4731 0, 4732 4733 100, 4734 4735 0 4736 4737 ) 4738 4739 ); 4740 4741 4742 4743 root.classList.toggle( 4744 4745 'ucw-custom-spacing', 4746 4747 customizeSpacing 4748 4749 ); 4750 4751 4752 4753 root.style.setProperty( 4754 4755 '--ucw-custom-coupon-gap', 4756 4757 couponGap + 'px' 4758 4759 ); 4760 4761 4762 4763 root.style.setProperty( 4764 4765 '--ucw-logo-bottom-gap', 4766 4767 logoBottomGap + 'px' 4768 4769 ); 4770 4771 4772 4773 root.style.setProperty( 4774 4775 '--ucw-headline-bottom-gap', 4776 4777 headlineBottomGap + 'px' 4778 4779 ); 4780 4781 4782 4783 root.style.setProperty( 4784 4785 '--ucw-body-bottom-gap', 4786 4787 bodyBottomGap + 'px' 4788 4789 ); 4790 4791 4792 4793 root.style.setProperty( 4794 4795 '--ucw-cta-bottom-gap', 4796 4797 ctaBottomGap + 'px' 4798 4799 ); 4800 4801 4802 4803 root.style.setProperty( 4804 4805 '--ucw-terms-bottom-gap', 4806 4807 termsBottomGap + 'px' 4808 4809 ); 4810 4811 4812 4813 root.style.setProperty( 4814 4815 '--ucw-button-bottom-gap', 4816 4817 buttonBottomGap + 'px' 4818 4819 ); 4820 4821 4822 4823 function attachRipple(buttonElement) { 4824 4825 if ( 4826 4827 prefersReducedMotion || 4828 4829 !enableButtonRipple || 4830 4831 !buttonElement || 4832 4833 buttonElement.dataset 4834 4835 .ucwRippleInitialized === 'true' 4836 4837 ) { 4838 4839 return; 4840 4841 } 4842 4843 4844 4845 buttonElement.dataset 4846 4847 .ucwRippleInitialized = 'true'; 4848 4849 4850 4851 buttonElement.addEventListener( 4852 4853 'pointerdown', 4854 4855 event => { 4856 4857 if ( 4858 4859 event.pointerType === 'mouse' && 4860 4861 event.button !== 0 4862 4863 ) { 4864 4865 return; 4866 4867 } 4868 4869 4870 4871 const buttonRectangle = 4872 4873 buttonElement 4874 4875 .getBoundingClientRect(); 4876 4877 4878 4879 const rippleSize = Math.max( 4880 4881 buttonRectangle.width, 4882 4883 buttonRectangle.height 4884 4885 ); 4886 4887 4888 4889 const ripple = 4890 4891 document.createElement('span'); 4892 4893 4894 4895 ripple.className = 'ucw-ripple'; 4896 4897 4898 4899 ripple.style.width = 4900 4901 rippleSize + 'px'; 4902 4903 4904 4905 ripple.style.height = 4906 4907 rippleSize + 'px'; 4908 4909 4910 4911 ripple.style.left = 4912 4913 ( 4914 4915 event.clientX - 4916 4917 buttonRectangle.left - 4918 4919 rippleSize / 2 4920 4921 ) + 'px'; 4922 4923 4924 4925 ripple.style.top = 4926 4927 ( 4928 4929 event.clientY - 4930 4931 buttonRectangle.top - 4932 4933 rippleSize / 2 4934 4935 ) + 'px'; 4936 4937 4938 4939 buttonElement.appendChild( 4940 4941 ripple 4942 4943 ); 4944 4945 4946 4947 ripple.addEventListener( 4948 4949 'animationend', 4950 4951 () => ripple.remove(), 4952 4953 { once: true } 4954 4955 ); 4956 4957 } 4958 4959 ); 4960 4961 } 4962 4963 4964
4965 let cardIdCounter = 0; 4966 4967 4968 4969 function createTextElement( 4970 4971 tagName, 4972 4973 className, 4974 4975 value 4976 4977 ) { 4978 4979 const text = stripHtml(value); 4980 4981 4982 4983 if (!text) return null; 4984 4985 4986 4987 const textElement = 4988 4989 document.createElement(tagName); 4990 4991 4992 4993 textElement.className = className; 4994 4995 textElement.textContent = text; 4996 4997 4998 4999 return textElement; 5000 5001 } 5002 5003 5004 5005 function createLogoElement( 5006 5007 rowLogoValue, 5008 5009 defaultLogoUrl, 5010 5011 useDefaultLogo 5012 5013 ) { 5014 5015 const rowLogoUrl = 5016 5017 extractImageUrl(rowLogoValue); 5018 5019 5020 5021 const logoUrl = 5022 5023 useDefaultLogo 5024 5025 ? defaultLogoUrl 5026 5027 : rowLogoUrl; 5028 5029 5030 5031 if (!logoUrl) return null; 5032 5033 5034 5035 const logoWrapper = 5036 5037 document.createElement('div'); 5038 5039 5040 5041 logoWrapper.className = 5042 5043 'ucw-card__logoWrap ' + 5044 5045 'ucw-card__logoWrap--' + 5046 5047 logoAlign; 5048 5049 5050 5051 logoWrapper.setAttribute( 5052 5053 'aria-hidden', 5054 5055 'true' 5056 5057 ); 5058 5059 5060 5061 const logoImage = 5062 5063 document.createElement('img'); 5064 5065 5066 5067 logoImage.className = 5068 5069 'ucw-card__logo'; 5070 5071 5072 5073 logoImage.src = logoUrl; 5074 5075 logoImage.alt = ''; 5076 5077 logoImage.loading = 'lazy'; 5078 5079 logoImage.decoding = 'async'; 5080 5081 5082 5083 logoWrapper.appendChild( 5084 5085 logoImage 5086 5087 ); 5088 5089 5090 5091 return logoWrapper; 5092 5093 } 5094 5095 5096 5097 function setDudaButtonLabel( 5098 5099 actionLink, 5100 5101 labelText 5102 5103 ) { 5104 5105 const buttonElement = 5106 5107 actionLink.querySelector( 5108 5109 '.ucw-card__action' 5110 5111 ); 5112 5113 5114 5115 if (!buttonElement) { 5116 5117 return false; 5118 5119 } 5120 5121 5122 5123 const labelElement = 5124 5125 buttonElement.querySelector( 5126 5127 '.text, .dmButtonLabel, .button-text, [data-button-text]' 5128 5129 ); 5130 5131 5132 5133 if (labelElement) { 5134 5135 labelElement.textContent = 5136 5137 labelText; 5138 5139 } else { 5140 5141 buttonElement.textContent = 5142 5143 labelText; 5144 5145 } 5146 5147 5148 5149 return true; 5150 5151 } 5152 5153 5154 5155 function cloneActionButton( 5156 5157 modifierClass, 5158 5159 labelText, 5160 5161 href, 5162 5163 ariaLabel 5164 5165 ) { 5166 5167 const templateLink = 5168 5169 actionTemplate.querySelector( 5170 5171 '.ucw-card__actionLink' 5172 5173 ); 5174 5175 5176 5177 if (!templateLink) { 5178 5179 return null; 5180 5181 } 5182 5183 5184 5185 const actionLink = 5186 5187 templateLink.cloneNode(true); 5188 5189 5190 5191 actionLink.classList.add( 5192 5193 modifierClass 5194 5195 ); 5196 5197 5198 5199 actionLink.href = href; 5200 5201 5202 5203 actionLink.setAttribute( 5204 5205 'aria-label', 5206 5207 ariaLabel 5208 5209 ); 5210 5211 5212 5213 if ( 5214 5215 !setDudaButtonLabel( 5216 5217 actionLink, 5218 5219 labelText 5220 5221 ) 5222 5223 ) { 5224 5225 return null; 5226 5227 } 5228 5229 5230 5231 const buttonElement = 5232 5233 actionLink.querySelector( 5234 5235 '.ucw-card__action' 5236 5237 ); 5238 5239 5240 5241 if (buttonElement) { 5242 5243 attachRipple(buttonElement); 5244 5245 } 5246 5247 5248 5249 return actionLink; 5250 5251 } 5252 5253 5254 5255 function createPhoneButton( 5256 5257 phone, 5258 5259 headline 5260 5261 ) { 5262 5263 const visiblePhone = 5264 5265 safeTrim(phone); 5266 5267 5268 5269 const cleanPhone = 5270 5271 visiblePhone.replace( 5272 5273 /[^0-9+]/g, 5274 5275 '' 5276 5277 ); 5278 5279 5280 5281 if (!visiblePhone || !cleanPhone) { 5282 5283 return null; 5284 5285 } 5286 5287 5288 5289 return cloneActionButton( 5290 5291 'ucw-card__phoneBtn', 5292 5293 visiblePhone, 5294 5295 'tel:' + cleanPhone, 5296 5297 'Call ' + 5298 5299 visiblePhone + 5300 5301 ( 5302 5303 headline 5304 5305 ? ' â ' + headline 5306 5307 : '' 5308 5309 ) 5310 5311 ); 5312 5313 } 5314 5315 5316 5317 function createStandardButton( 5318 5319 rowData, 5320 5321 headline 5322 5323 ) { 5324 5325 const buttonText = 5326 5327 stripHtml( 5328 5329 rowData['BUTTON NAME'] 5330 5331 ); 5332 5333 5334 5335 const buttonLink = 5336 5337 normalizeButtonLink( 5338 5339 rowData['BUTTON LINK'] 5340 5341 ); 5342 5343 5344 5345 if (!buttonText || !buttonLink) { 5346 5347 return null; 5348 5349 } 5350 5351 5352 5353 return cloneActionButton( 5354 5355 'ucw-card__btn', 5356 5357 buttonText, 5358 5359 buttonLink, 5360 5361 headline 5362 5363 ? buttonText + 5364 5365 ' â ' + 5366 5367 headline 5368 5369 : buttonText 5370 5371 ); 5372 5373 } 5374 5375 5376 5377 function createActions( 5378 5379 rowData, 5380 5381 phone, 5382 5383 headline, 5384 5385 showStandardButton, 5386 5387 showPhoneButton 5388 5389 ) { 5390 5391 const actions = 5392 5393 document.createElement('div'); 5394 5395 5396 5397 actions.className = 5398 5399 'ucw-card__actions'; 5400 5401 5402 5403 if (showStandardButton) { 5404 5405 const standardButton = 5406 5407 createStandardButton( 5408 5409 rowData, 5410 5411 headline 5412 5413 ); 5414 5415 5416 5417 if (standardButton) { 5418 5419 actions.appendChild( 5420 5421 standardButton 5422 5423 ); 5424 5425 } 5426 5427 } 5428 5429 5430 5431 if (showPhoneButton) { 5432 5433 const phoneButton = 5434 5435 createPhoneButton( 5436 5437 phone, 5438 5439 headline 5440 5441 ); 5442 5443 5444 5445 if (phoneButton) { 5446 5447 actions.appendChild( 5448 5449 phoneButton 5450 5451 ); 5452 5453 } 5454 5455 } 5456 5457 5458 5459 return actions.childElementCount 5460 5461 ? actions 5462 5463 : null; 5464 5465 } 5466 5467 5468 5469 function createCard( 5470 5471 rowData, 5472 5473 options 5474 5475 ) { 5476 5477 cardIdCounter += 1; 5478 5479 5480 5481 const card = 5482 5483 document.createElement('article'); 5484 5485 5486 5487 card.className = [ 5488 5489 'ucw-card', 5490 5491 options.isCoupon 5492 5493 ? 'ucw-card--coupon' 5494 5495 : 'ucw-card--callout', 5496
5497 'ucw-card--align-' + 5498 5499 cardContentAlign, 5500 5501 'ucw-card--valign-' + 5502 5503 cardVerticalAlign 5504 5505 ].join(' '); 5506 5507 5508 5509 if (options.isCoupon) { 5510 5511 card.setAttribute( 5512 5513 'role', 5514 5515 'listitem' 5516 5517 ); 5518 5519 } 5520 5521 5522 5523 const cardInner = 5524 5525 document.createElement('div'); 5526 5527 5528 5529 cardInner.className = 5530 5531 'ucw-card__inner'; 5532 5533 5534 5535 const logoElement = 5536 5537 createLogoElement( 5538 5539 rowData.LOGO, 5540 5541 options.defaultLogoUrl, 5542 5543 options.useDefaultLogo 5544 5545 ); 5546 5547 5548 5549 if (logoElement) { 5550 5551 cardInner.appendChild( 5552 5553 logoElement 5554 5555 ); 5556 5557 } 5558 5559 5560 5561 const headlineElement = 5562 5563 createTextElement( 5564 5565 'h3', 5566 5567 'ucw-card__head', 5568 5569 rowData.HEADLINE 5570 5571 ); 5572 5573 5574 5575 const headlineText = 5576 5577 headlineElement 5578 5579 ? headlineElement.textContent 5580 5581 : ''; 5582 5583 5584 5585 if (headlineElement) { 5586 5587 headlineElement.id = 5588 5589 'ucw-heading-' + 5590 5591 ( 5592 5593 element.id || 5594 5595 'widget' 5596 5597 ) + 5598 5599 '-' + 5600 5601 cardIdCounter; 5602 5603 5604 5605 card.setAttribute( 5606 5607 'aria-labelledby', 5608 5609 headlineElement.id 5610 5611 ); 5612 5613 5614 5615 cardInner.appendChild( 5616 5617 headlineElement 5618 5619 ); 5620 5621 } 5622 5623 5624 5625 const bodyElement = 5626 5627 createTextElement( 5628 5629 'p', 5630 5631 'ucw-card__body', 5632 5633 rowData.BODY 5634 5635 ); 5636 5637 5638 5639 if (bodyElement) { 5640 5641 cardInner.appendChild( 5642 5643 bodyElement 5644 5645 ); 5646 5647 } 5648 5649 5650 5651 const ctaElement = 5652 5653 createTextElement( 5654 5655 'p', 5656 5657 'ucw-card__cta', 5658 5659 rowData['CTA LEAD IN'] 5660 5661 ); 5662 5663 5664 5665 if (ctaElement) { 5666 5667 cardInner.appendChild( 5668 5669 ctaElement 5670 5671 ); 5672 5673 } 5674 5675 5676 5677 if ( 5678 5679 options.termsDisplayMode !== 5680 5681 'hidden' 5682 5683 ) { 5684 5685 const finePrintElement = 5686 5687 createTextElement( 5688 5689 'p', 5690 5691 'ucw-card__fine', 5692 5693 rowData[ 5694 5695 'TERMS OF CONDITION' 5696 5697 ] 5698 5699 ); 5700 5701 5702 5703 if (finePrintElement) { 5704 5705 finePrintElement.id = 5706 5707 'ucw-fine-' + 5708 5709 ( 5710 5711 element.id || 5712 5713 'widget' 5714 5715 ) + 5716 5717 '-' + 5718 5719 cardIdCounter; 5720 5721 5722 5723 if ( 5724 5725 options.termsDisplayMode === 5726 5727 'abbreviated' 5728 5729 ) { 5730 5731 finePrintElement.classList.add( 5732 5733 'ucw-card__fine--collapsible' 5734 5735 ); 5736 5737 } 5738 5739 5740 5741 /* 5742 5743 Keep the terms text and its optional See terms control 5744 5745 together so Gap Below Terms applies below the complete 5746 5747 terms section instead of between those two elements. 5748 5749 */ 5750 5751 const termsGroup = 5752 5753 document.createElement('div'); 5754 5755 5756 5757 termsGroup.className = 5758 5759 'ucw-card__termsGroup'; 5760 5761 5762 5763 termsGroup.appendChild( 5764 5765 finePrintElement 5766 5767 ); 5768 5769 5770 5771 cardInner.appendChild( 5772 5773 termsGroup 5774 5775 ); 5776 5777 } 5778 5779 } 5780 5781 5782 5783 const actions = 5784 5785 createActions( 5786 5787 rowData, 5788 5789 options.phone, 5790 5791 headlineText, 5792 5793 options.showStandardButton, 5794 5795 options.showPhoneButton 5796 5797 ); 5798 5799 5800 5801 if (actions) { 5802 5803 cardInner.appendChild(actions); 5804 5805 } 5806 5807 5808 5809 card.appendChild(cardInner); 5810 5811 5812 5813 return card; 5814 5815 } 5816 5817 5818 5819 function initializeFinePrint(card) { 5820 5821 const finePrint = 5822 5823 card.querySelector( 5824 5825 '.ucw-card__fine--collapsible' 5826 5827 ); 5828 5829 5830 5831 if ( 5832 5833 !finePrint || 5834 5835 finePrint.dataset 5836 5837 .ucwFineInitialized === 'true' 5838 5839 ) { 5840 5841 return; 5842 5843 } 5844 5845 5846 5847 finePrint.dataset 5848 5849 .ucwFineInitialized = 'true'; 5850 5851 5852 5853 const toggle = 5854 5855 document.createElement('button'); 5856 5857 5858 5859 toggle.className = 5860 5861 'ucw-fine-toggle'; 5862 5863 5864 5865 toggle.type = 'button'; 5866 5867 toggle.textContent = 5868 5869 'See terms â¾'; 5870 5871 5872 5873 toggle.setAttribute( 5874 5875 'aria-expanded', 5876 5877 'false' 5878 5879 ); 5880 5881 5882 5883 toggle.setAttribute( 5884 5885 'aria-controls', 5886 5887 finePrint.id 5888 5889 ); 5890 5891 5892 5893 toggle.addEventListener( 5894 5895 'click', 5896 5897 () => { 5898 5899 const expanded = 5900 5901 finePrint.classList.toggle( 5902 5903 'ucw-card__fine--expanded' 5904 5905 ); 5906 5907 5908 5909 toggle.textContent = 5910 5911 expanded 5912 5913 ? 'Hide terms â´' 5914 5915 : 'See terms â¾'; 5916 5917 5918 5919 toggle.setAttribute( 5920 5921 'aria-expanded', 5922 5923 String(expanded) 5924 5925 ); 5926 5927 } 5928 5929 ); 5930 5931 5932 5933 finePrint.insertAdjacentElement( 5934 5935 'afterend', 5936 5937 toggle 5938 5939 ); 5940 5941 } 5942 5943 5944 5945 function initializeFinePrintForCards( 5946 5947 cards 5948 5949 ) { 5950 5951 requestAnimationFrame(() => { 5952 5953 cards.forEach( 5954 5955 initializeFinePrint 5956 5957 ); 5958 5959 }); 5960 5961 } 5962 5963 5964 5965 function initializeEntrance(cards) { 5966 5967 if (!cards.length) return; 5968 5969 5970 5971 if ( 5972 5973 prefersReducedMotion || 5974 5975 !enableEntranceAnimation || 5976 5977 !window.IntersectionObserver 5978 5979 ) { 5980 5981 cards.forEach(card => { 5982 5983 card.classList.add( 5984 5985 'ucw-card--visible', 5986 5987 'ucw-card--settled' 5988 5989 ); 5990 5991 }); 5992 5993 5994 5995 return; 5996 5997 } 5998 5999 6000 6001 const observer = 6002 6003 new IntersectionObserver( 6004
6005 entries => { 6006 6007 entries.forEach(entry => { 6008 6009 if (!entry.isIntersecting) { 6010 6011 return; 6012 6013 } 6014 6015 6016 6017 const card = entry.target; 6018 6019 6020 6021 card.classList.add( 6022 6023 'ucw-card--visible' 6024 6025 ); 6026 6027 6028 6029 const settleCard = () => { 6030 6031 card.classList.add( 6032 6033 'ucw-card--settled' 6034 6035 ); 6036 6037 }; 6038 6039 6040 6041 card.addEventListener( 6042 6043 'transitionend', 6044 6045 settleCard, 6046 6047 { once: true } 6048 6049 ); 6050 6051 6052 6053 window.setTimeout( 6054 6055 settleCard, 6056 6057 750 6058 6059 ); 6060 6061 6062 6063 observer.unobserve(card); 6064 6065 }); 6066 6067 }, 6068 6069 { 6070 6071 threshold: 0.12 6072 6073 } 6074 6075 ); 6076 6077 6078 6079 root.__ucwEntranceObserver = 6080 6081 observer; 6082 6083 6084 6085 cards.forEach( 6086 6087 (card, cardIndex) => { 6088 6089 card.style.setProperty( 6090 6091 '--ucw-delay', 6092 6093 cardIndex * 80 + 'ms' 6094 6095 ); 6096 6097 6098 6099 observer.observe(card); 6100 6101 } 6102 6103 ); 6104 6105 } 6106 6107 6108 6109 function createSkeleton( 6110 6111 alignment 6112 6113 ) { 6114 6115 const skeleton = 6116 6117 document.createElement('div'); 6118 6119 6120 6121 skeleton.className = 6122 6123 'ucw-skeleton ucw-skeleton--' + 6124 6125 alignment; 6126 6127 6128 6129 skeleton.setAttribute( 6130 6131 'aria-hidden', 6132 6133 'true' 6134 6135 ); 6136 6137 6138 6139 [ 6140 6141 'title', 6142 6143 'body', 6144 6145 'body2', 6146 6147 'btn' 6148 6149 ].forEach(lineType => { 6150 6151 const line = 6152 6153 document.createElement('div'); 6154 6155 6156 6157 line.className = 6158 6159 'ucw-skeleton__line ' + 6160 6161 'ucw-skeleton__line--' + 6162 6163 lineType; 6164 6165 6166 6167 skeleton.appendChild(line); 6168 6169 }); 6170 6171 6172 6173 return skeleton; 6174 6175 } 6176 6177 6178 6179 function showSkeletons( 6180 6181 container, 6182 6183 count 6184 6185 ) { 6186 6187 container.replaceChildren(); 6188 6189 6190 6191 for ( 6192 6193 let index = 0; 6194 6195 index < count; 6196 6197 index += 1 6198 6199 ) { 6200 6201 container.appendChild( 6202 6203 createSkeleton( 6204 6205 cardContentAlign 6206 6207 ) 6208 6209 ); 6210 6211 } 6212 6213 } 6214 6215 6216 6217 function showEmptyState( 6218 6219 container, 6220 6221 message 6222 6223 ) { 6224 6225 container.replaceChildren(); 6226 6227 6228 6229 const emptyState = 6230 6231 document.createElement('p'); 6232 6233 6234 6235 emptyState.className = 6236 6237 'ucw-empty'; 6238 6239 6240 6241 emptyState.textContent = 6242 6243 message || 6244 6245 'Check back soon for offers.'; 6246 6247 6248 6249 container.appendChild( 6250 6251 emptyState 6252 6253 ); 6254 6255 } 6256 6257 6258 6259 function hideWidget() { 6260 6261 root.hidden = true; 6262 6263 root.setAttribute( 6264 6265 'aria-busy', 6266 6267 'false' 6268 6269 ); 6270 6271 } 6272 6273 6274 6275 function showMode(mode) { 6276 6277 root.hidden = false; 6278 6279 6280 6281 if (mode === 'callout') { 6282 6283 calloutEl.hidden = false; 6284 6285 couponEl.hidden = true; 6286 6287 } else { 6288 6289 calloutEl.hidden = true; 6290 6291 couponEl.hidden = false; 6292 6293 } 6294 6295 } 6296 6297 6298 6299 function parseAllowedSlugs(value) { 6300 6301 const plainValue = 6302 6303 stripHtml( 6304 6305 safeTrim(value) 6306 6307 .replace( 6308 6309 /<br\s*\/?>/gi, 6310 6311 ',' 6312 6313 ) 6314 6315 ); 6316 6317 6318 6319 if (!plainValue) return []; 6320 6321 6322 6323 return plainValue 6324 6325 .split(/[\n,]+/) 6326 6327 .map(getLastSlug) 6328 6329 .filter(Boolean); 6330 6331 } 6332 6333 6334 6335 function filterCouponRows( 6336 6337 rows, 6338 6339 options 6340 6341 ) { 6342 6343 if (options.showAll) { 6344 6345 return rows; 6346 6347 } 6348 6349 6350 6351 const manualSlugs = 6352 6353 safeTrim(options.filterValue) 6354 6355 .split(',') 6356 6357 .map(getLastSlug) 6358 6359 .filter(Boolean); 6360 6361 6362 6363 if (options.filterBySlug) { 6364 6365 const currentSlug = 6366 6367 getCurrentSlug(); 6368 6369 6370 6371 if (currentSlug) { 6372 6373 const currentPageMatches = 6374 6375 rows.filter(row => 6376 6377 getLastSlug( 6378 6379 row && 6380 6381 row.page_item_url 6382 6383 ) === currentSlug 6384 6385 ); 6386 6387 6388 6389 if ( 6390 6391 currentPageMatches.length 6392 6393 ) { 6394 6395 return currentPageMatches; 6396 6397 } 6398 6399 } 6400 6401 } 6402 6403 6404 6405 if (!manualSlugs.length) { 6406 6407 return rows; 6408 6409 } 6410 6411 6412 6413 return rows.filter(row => 6414 6415 manualSlugs.includes( 6416 6417 getLastSlug( 6418 6419 row && 6420 6421 row.page_item_url 6422 6423 ) 6424 6425 ) 6426 6427 ); 6428 6429 } 6430 6431 6432 6433 function selectCalloutRow( 6434 6435 rows, 6436 6437 options 6438 6439 ) { 6440 6441 if (!rows.length) { 6442 6443 return null; 6444 6445 } 6446 6447 6448 6449 if (options.explicitSlug) { 6450 6451 return ( 6452 6453 rows.find(row => 6454 6455 getLastSlug( 6456 6457 row && 6458 6459 row.page_item_url 6460 6461 ) === options.explicitSlug 6462 6463 ) || null 6464 6465 ); 6466 6467 } 6468 6469 6470 6471 if (options.filterBySlug) { 6472 6473 const currentSlug = 6474 6475 getCurrentSlug(); 6476 6477 6478 6479 if (currentSlug) { 6480 6481 const currentMatch = 6482 6483 rows.find(row => 6484 6485 getLastSlug( 6486 6487 row && 6488 6489 row.page_item_url 6490 6491 ) === currentSlug 6492 6493 ); 6494 6495 6496 6497 if (currentMatch) { 6498 6499 return currentMatch; 6500 6501 } 6502 6503 } 6504 6505 6506 6507 const allPagesMatch = 6508 6509 rows.find(row => 6510 6511 safeTrim( 6512 6513 row && 6514 6515 row.page_item_url 6516 6517 ) 6518 6519 .toLowerCase() === 6520 6521 '_all_' 6522 6523 ); 6524 6525 6526 6527 if (allPagesMatch) { 6528 6529 return allPagesMatch; 6530 6531 } 6532 6533 } 6534 6535 6536 6537 return rows[0]; 6538 6539 } 6540 6541 6542 6543 applyCardShadowTokens(); 6544 6545 6546 6547 const widgetMode = 6548 6549 safeTrim( 6550 6551 config.widgetMode || 6552 6553 'callout' 6554 6555 ).toLowerCase() === 'coupon' 6556 6557 ? 'coupon' 6558 6559 : 'callout'; 6560 6561 6562 6563 const useDefaultLogo = 6564 6565 normalizeBoolean( 6566 6567 config.useDefaultLogo, 6568 6569 false 6570 6571 ); 6572 6573 6574 6575 const showStandardButton = 6576 6577 normalizeBoolean( 6578 6579 config.showStandardButton, 6580 6581 true 6582 6583 ); 6584 6585 6586 6587 const showPhoneButton = 6588 6589 normalizeBoolean( 6590 6591 config.showPhoneButton, 6592 6593 true 6594 6595 ); 6596 6597 6598 6599 const termsDisplayMode = 6600 6601 [ 6602 6603 'full', 6604 6605 'abbreviated', 6606 6607 'hidden' 6608 6609 ].includes( 6610 6611 safeTrim( 6612 6613 config.termsDisplayMode || 6614 6615 'abbreviated' 6616 6617 ).toLowerCase() 6618 6619 ) 6620 6621 ? safeTrim( 6622 6623 config.termsDisplayMode || 6624 6625 'abbreviated' 6626 6627 ).toLowerCase() 6628 6629 : 'abbreviated'; 6630 6631 6632 6633 const couponColumns = 6634 6635 Math.round( 6636 6637 clampNumber( 6638 6639 config.couponColumns, 6640 6641 1, 6642 6643 4, 6644 6645 2 6646 6647 ) 6648 6649 ); 6650 6651 6652 6653 const showAll = 6654 6655 normalizeBoolean( 6656 6657 config.showAll, 6658 6659 false 6660 6661 ); 6662 6663 6664 6665 const couponFilterBySlug = 6666 6667 normalizeBoolean( 6668 6669 config.couponFilterBySlug, 6670 6671 false 6672 6673 ); 6674 6675 6676 6677 const calloutFilterBySlug = 6678 6679 normalizeBoolean( 6680 6681 config.filterBySlug, 6682 6683 false 6684 6685 ); 6686 6687 6688 6689 const calloutExplicitSlug = 6690 6691 getLastSlug( 6692 6693 config.calloutFilterValue 6694 6695 ); 6696 6697 6698 6699 const allowedSlugs = 6700 6701 parseAllowedSlugs( 6702 6703 config.allowedSlugs 6704 6705 ); 6706 6707 6708 6709 if ( 6710 6711 allowedSlugs.length && 6712 6713 !allowedSlugs.includes( 6714 6715 getCurrentSlug() 6716 6717 ) 6718 6719 ) { 6720 6721 hideWidget(); 6722 6723 return; 6724 6725 } 6726 6727 6728 6729 root.setAttribute( 6730 6731 'aria-busy', 6732 6733 'true' 6734 6735 ); 6736 6737 6738 6739 root.hidden = false;
6740 6741 6742 6743 const needsPhone = 6744 6745 showPhoneButton; 6746 6747 6748 6749 if (widgetMode === 'callout') { 6750 6751 showMode('callout'); 6752 6753 6754 6755 const calloutAlignValue = 6756 6757 safeTrim( 6758 6759 calloutLayout.calloutAlign || 6760 6761 config.calloutAlign || 6762 6763 'full' 6764 6765 ).toLowerCase(); 6766 6767 6768 6769 const calloutAlign = 6770 6771 [ 6772 6773 'full', 6774 6775 'left', 6776 6777 'center', 6778 6779 'right' 6780 6781 ].includes(calloutAlignValue) 6782 6783 ? calloutAlignValue 6784 6785 : 'full'; 6786 6787 6788 6789 const calloutMaxWidth = 6790 6791 Math.round( 6792 6793 clampNumber( 6794 6795 calloutLayout.calloutMaxWidth || 6796 6797 config.calloutMaxWidth, 6798 6799 200, 6800 6801 2000, 6802 6803 720 6804 6805 ) 6806 6807 ); 6808 6809 6810 6811 calloutEl.className = 6812 6813 'ucw-callout ' + 6814 6815 'ucw-callout--align-' + 6816 6817 calloutAlign; 6818 6819 6820 6821 calloutEl.style.setProperty( 6822 6823 '--callout-max-width', 6824 6825 calloutMaxWidth + 'px' 6826 6827 ); 6828 6829 6830 6831 showSkeletons( 6832 6833 calloutMount, 6834 6835 1 6836 6837 ); 6838 6839 6840 6841 try { 6842 6843 const [ 6844 6845 calloutRows, 6846 6847 defaultLogoUrl, 6848 6849 phone 6850 6851 ] = await Promise.all([ 6852 6853 loadCollection('CALLOUT 1'), 6854 6855 useDefaultLogo 6856 6857 ? loadDefaultLogo() 6858 6859 .catch(() => '') 6860 6861 : Promise.resolve(''), 6862 6863 needsPhone 6864 6865 ? loadPhone() 6866 6867 : Promise.resolve('') 6868 6869 ]); 6870 6871 6872 6873 if (!isCurrentInstance()) { 6874 6875 return; 6876 6877 } 6878 6879 6880 6881 const selectedRow = 6882 6883 selectCalloutRow( 6884 6885 calloutRows, 6886 6887 { 6888 6889 explicitSlug: 6890 6891 calloutExplicitSlug, 6892 6893 filterBySlug: 6894 6895 calloutFilterBySlug 6896 6897 } 6898 6899 ); 6900 6901 6902 6903 if (!selectedRow) { 6904 6905 hideWidget(); 6906 6907 return; 6908 6909 } 6910 6911 6912 6913 const card = createCard( 6914 6915 getRowData(selectedRow), 6916 6917 { 6918 6919 isCoupon: false, 6920 6921 defaultLogoUrl, 6922 6923 useDefaultLogo, 6924 6925 phone, 6926 6927 showStandardButton, 6928 6929 showPhoneButton, 6930 6931 termsDisplayMode 6932 6933 } 6934 6935 ); 6936 6937 6938 6939 calloutMount.replaceChildren(card); 6940 6941 6942 6943 notifyDynamicPhoneInsertion(phone); 6944 6945 6946 6947 initializeFinePrintForCards([ 6948 6949 card 6950 6951 ]); 6952 6953 6954 6955 initializeEntrance([ 6956 6957 card 6958 6959 ]); 6960 6961 6962 6963 root.setAttribute( 6964 6965 'aria-busy', 6966 6967 'false' 6968 6969 ); 6970 6971 } catch (e) { 6972 6973 if (isCurrentInstance()) { 6974 6975 hideWidget(); 6976 6977 } 6978 6979 } 6980 6981 6982 6983 return; 6984 6985 } 6986 6987 6988 6989 showMode('coupon'); 6990 6991 6992 6993 couponGrid.className = 6994 6995 'ucw-coupon__grid cols-' + 6996 6997 couponColumns; 6998 6999 7000 7001 couponGrid.style.setProperty( 7002 7003 '--coupon-cols', 7004 7005 String(couponColumns) 7006 7007 ); 7008 7009 7010 7011 showSkeletons( 7012 7013 couponGrid, 7014 7015 couponColumns 7016 7017 ); 7018 7019 7020 7021 try { 7022 7023 const [ 7024 7025 couponRows, 7026 7027 defaultLogoUrl, 7028 7029 phone 7030 7031 ] = await Promise.all([ 7032 7033 loadCollection('COUPON 1'), 7034 7035 useDefaultLogo 7036 7037 ? loadDefaultLogo() 7038 7039 .catch(() => '') 7040 7041 : Promise.resolve(''), 7042 7043 needsPhone 7044 7045 ? loadPhone() 7046 7047 : Promise.resolve('') 7048 7049 ]); 7050 7051 7052 7053 if (!isCurrentInstance()) { 7054 7055 return; 7056 7057 } 7058 7059 7060 7061 let visibleRows = 7062 7063 filterCouponRows( 7064 7065 couponRows, 7066 7067 { 7068 7069 showAll, 7070 7071 filterBySlug: 7072 7073 couponFilterBySlug, 7074 7075 filterValue: 7076 7077 config.filterValue 7078 7079 } 7080 7081 ); 7082 7083 7084 7085 if (!showAll) { 7086 7087 visibleRows = 7088 7089 visibleRows.slice( 7090 7091 0, 7092 7093 couponColumns 7094 7095 ); 7096 7097 } 7098 7099 7100 7101 if (!visibleRows.length) { 7102 7103 showEmptyState( 7104 7105 couponGrid 7106 7107 ); 7108 7109 7110 7111 root.setAttribute( 7112 7113 'aria-busy', 7114 7115 'false' 7116 7117 ); 7118 7119 7120 7121 return; 7122 7123 } 7124 7125 7126 7127 couponGrid.classList.toggle( 7128 7129 'single-card', 7130 7131 visibleRows.length === 1 7132 7133 ); 7134 7135 7136 7137 const cards = 7138 7139 visibleRows.map(row => 7140 7141 createCard( 7142 7143 getRowData(row), 7144 7145 { 7146 7147 isCoupon: true, 7148 7149 defaultLogoUrl, 7150 7151 useDefaultLogo, 7152 7153 phone, 7154 7155 showStandardButton, 7156 7157 showPhoneButton, 7158 7159 termsDisplayMode 7160 7161 } 7162 7163 ) 7164 7165 ); 7166 7167 7168 7169 couponGrid.replaceChildren( 7170 7171 ...cards 7172 7173 ); 7174 7175 7176 7177 notifyDynamicPhoneInsertion(phone); 7178 7179 7180 7181 initializeFinePrintForCards( 7182 7183 cards 7184 7185 ); 7186 7187 7188 7189 initializeEntrance(cards); 7190 7191 7192 7193 root.setAttribute( 7194 7195 'aria-busy', 7196 7197 'false' 7198 7199 ); 7200 7201 } catch (e) { 7202 7203 if (isCurrentInstance()) { 7204 7205 showEmptyState( 7206 7207 couponGrid 7208 7209 ); 7210 7211 7212 7213 root.setAttribute( 7214 7215 'aria-busy', 7216 7217 'false' 7218 7219 ); 7220 7221 } 7222 7223 } 7224 7225 } 7226 7227); 7228 }; 7229</script>
7229 7230
7231<script> 7232 window.customWidgetsFunctions["4e2b21efc370451a8e2c573f02104b04~22"] = function (element, data, api) { 7233 null 7234 }; 7235</script>
7235 7236
7237<script> 7238 window.customWidgetsFunctions["0c06e70da5474879a21daa0d3b1192c0~3"] = function (element, data, api) { 7239 window.dmAPI.runOnReady('cb1-h1-theme', () => { 7240 7241 function applyTheme() { 7242 // Try multiple candidate selectors for the h1 style source 7243 // to work in both the editor and the published/preview environment 7244 const candidates = [ 7245 '#dm h1', 7246 'h1', 7247 ]; 7248 7249 let h1Sample = null; 7250 for (const sel of candidates) { 7251 h1Sample = document.querySelector(sel); 7252 if (h1Sample) break; 7253 } 7254 7255 if (!h1Sample) return false; 7256 7257 const computed = window.getComputedStyle(h1Sample); 7258 7259 const fontFamily = computed.fontFamily; 7260 const fontSize = computed.fontSize; 7261 const fontWeight = computed.fontWeight; 7262 const lineHeight = computed.lineHeight; 7263 const color = computed.color; 7264 const letterSpacing = computed.letterSpacing; 7265 const textTransform = computed.textTransform; 7266 const fontStyle = computed.fontStyle; 7267 7268 // Skip if nothing meaningful was computed yet 7269 if (!fontFamily || fontFamily === '') return false; 7270 7271 const baseSelectors = [ 7272 `#dm .dmInner .widget-wrapper.DCBH1 .dmNewParagraph`, 7273 `#dm .dmInner .widget-wrapper.DCBH1 .dmNewParagraph p`, 7274 `#dm .dmInner .widget-wrapper.DCBH1 .dmNewParagraph .rteBlock`, 7275 `.dmInner .widget-wrapper.DCBH1 .dmNewParagraph`, 7276 `.dmInner .widget-wrapper.DCBH1 .dmNewParagraph p`, 7277 `.dmInner .widget-wrapper.DCBH1 .dmNewParagraph .rteBlock`, 7278 `.widget-wrapper.DCBH1 .dmNewParagraph`, 7279 `.widget-wrapper.DCBH1 .dmNewParagraph p`, 7280 `.widget-wrapper.DCBH1 .dmNewParagraph .rteBlock`, 7281 ]; 7282 7283 const allSelectors = baseSelectors.join(',\n '); 7284 7285 const css = ` 7286 ${allSelectors} { 7287 font-family: ${fontFamily} !important; 7288 font-size: ${fontSize} !important; 7289 font-weight: ${fontWeight} !important; 7290 line-height: ${lineHeight} !important; 7291 color: ${color} !important; 7292 letter-spacing: ${letterSpacing} !important; 7293 text-transform: ${textTransform} !important; 7294 font-style: ${fontStyle} !important; 7295 } 7296 `; 7297 7298 // Remove any previously injected tag before re-injecting 7299 const existing = document.querySelector('style[data-cb1-h1-theme]'); 7300 if (existing) existing.remove(); 7301 7302 const styleTag = document.createElement('style'); 7303 styleTag.setAttribute('data-cb1-h1-theme', 'true'); 7304 styleTag.textContent = css; 7305 document.head.appendChild(styleTag); 7306 7307 return true; 7308 } 7309 7310 // Try immediately 7311 if (applyTheme()) return; 7312 7313 // If not ready yet, retry with increasing delays to handle 7314 // async rendering in preview / published environments 7315 let attempts = 0; 7316 const maxAttempts = 20; 7317 const interval = setInterval(() => { 7318 attempts++; 7319 if (applyTheme() || attempts >= maxAttempts) { 7320 clearInterval(interval); 7321 } 7322 }, 300); 7323}); 7324 7325 }; 7326</script>
7326 7327
7328<script> 7329 window.customWidgetsFunctions["3e38ec713838428586c343d139994b6f~58"] = function (element, data, api) { 7330 window.dmAPI.runOnReady('navGridWidget', () => { 7331 const container = element.querySelector('#nav-grid-widget'); 7332 if(!container) return; 7333 7334 const cleanText = (el)=> (el?.textContent||'').trim().replace(/\s+/g,' '); 7335 const cleanUrl = (href)=>{ 7336 try{ 7337 const u=new URL(href,location.origin); 7338 const path = u.pathname.replace(/\/+$/,'')||'/'; 7339 return path + u.search; // Preserve query parameters for preview mode 7340 } 7341 catch{ return '#'; } 7342 }; 7343 7344 // Get column count from config (grid uses this; masonry uses this) 7345 const columnCount = parseInt(data.config['columnCount'] || '3', 10); 7346 7347 // Get exclusion list from config 7348 const excludeList = (data.config['excludeParents'] || '') 7349 .split(',') 7350 .map(s => s.trim().toLowerCase()) 7351 .filter(s => s.length > 0); 7352 7353 // Get inclusion list from config 7354 const includeList = (data.config['includeParents'] || '') 7355 .split(',') 7356 .map(s => s.trim().toLowerCase()) 7357 .filter(s => s.length > 0); 7358 7359 // Get chevron icon from config (Option B default: right-pointing) 7360 const chevronIcon = data.config['chevronIcon'] || 'â¸'; 7361 7362 // Get hover setting from config 7363 const openOnHover = data.config['openOnHover'] || false; 7364 7365 // Get expand all setting from config 7366 const expandAll = data.config['expandAll'] || false; 7367 7368 // Get masonry setting from config (NEW - separate from expandAll) 7369 const useMasonry = data.config['useMasonry'] || false; 7370 7371 // Set CSS custom property for column count - this works for both grid AND masonry 7372 container.style.setProperty('--column-count', String(columnCount)); 7373 7374 // Masonry is now controlled by its own toggle 7375 if(useMasonry) { 7376 container.setAttribute('data-masonry', 'true'); 7377 } else { 7378 container.removeAttribute('data-masonry'); 7379 } 7380 7381 // Set uppercase data attributes from config 7382 const uppercaseParents = data.config['uppercaseParents'] || false; 7383 const uppercaseChildren = data.config['uppercaseChildren'] || false; 7384 7385 // Get selected item styling from config 7386 const underlineSelected = data.config['underlineSelected'] !== false; 7387 const selectedBgColor = data.config['selectedBgColor'] || 'transparent'; 7388 7389 if(uppercaseParents) container.setAttribute('data-uppercase-parents', 'true'); 7390 else container.removeAttribute('data-uppercase-parents'); 7391 7392 if(uppercaseChildren) container.setAttribute('data-uppercase-children', 'true'); 7393 else container.removeAttribute('data-uppercase-children'); 7394 7395 if(underlineSelected) container.setAttribute('data-underline-selected', 'true'); 7396 else container.removeAttribute('data-underline-selected'); 7397 7398 container.style.setProperty('--selected-bg-color', selectedBgColor); 7399 7400 // Helpful attribute only 7401 container.setAttribute('data-columns', String(columnCount)); 7402 7403 // Get current page URL for active state detection 7404 const currentPagePath = cleanUrl(window.location.href); 7405 7406 // Recursive function to extract nested children 7407 function extractChildren(parentLi, level = 1) { 7408 const childUL = parentLi.querySelector(':scope > ul, :scope .sub-nav ul, :scope .submenu ul, :scope .dropdown ul, :scope .children, :scope ul'); 7409 const children = []; 7410 7411 if(childUL){ 7412 Array.from(childUL.querySelectorAll(':scope > li')).forEach(cli => { 7413 const a = cli.querySelector('a'); 7414 if(!a) return; 7415 const title = cleanText(a); 7416 const url = cleanUrl(a.getAttribute('href')||'#'); 7417 if(!title || !url || url === '#') return; 7418 7419 const nestedChildren = extractChildren(cli, level + 1); 7420 7421 children.push({ 7422 title, 7423 url, 7424 children: nestedChildren, 7425 level 7426 }); 7427 }); 7428 } 7429 7430 return children; 7431 } 7432 7433 function extractNavFromDOM(){ 7434 const navCandidates = [ 7435 'nav[role="navigation"]','.dmNavWrapper','.dmNav','.navigation','nav','header nav' 7436 ]; 7437 let navRoot=null; 7438 7439 for(const sel of navCandidates){ 7440 const el=document.querySelector(sel); 7441 if(!el) continue; 7442 if(el.querySelector('li ul, li .sub-nav, li .submenu, li .dropdown')){ navRoot=el; break; } 7443 if(!navRoot) navRoot=el; 7444 } 7445 if(!navRoot) return []; 7446 7447 const topUL = navRoot.querySelector('ul, .menu, .dmNav'); 7448 const topLIs = topUL 7449 ? Array.from(topUL.children).filter(li=>li.tagName==='LI') 7450 : Array.from(navRoot.querySelectorAll(':scope > li, :scope ul > li')); 7451 7452 const parents=[]; 7453 topLIs.forEach(li=>{ 7454 const parentLink = 7455 li.querySelector(':scope > a, :scope > .nav-item > a, :scope > .menu-item > a') || 7456 li.querySelector('a'); 7457 7458 const parentTitle = cleanText(parentLink); 7459 const parentUrl = cleanUrl(parentLink?.getAttribute('href')||'#'); 7460 7461 if(!parentTitle) return; 7462 7463 // Skip if parent title is in exclusion list 7464 if(excludeList.includes(parentTitle.toLowerCase())) return; 7465 7466 const children = extractChildren(li, 1); 7467 7468 // Include if: has children OR is in inclusion list 7469 const isInIncludeList = includeList.length > 0 && includeList.includes(parentTitle.toLowerCase()); 7470 7471 if(children.length > 0 || isInIncludeList) { 7472 parents.push({ title: parentTitle, url: parentUrl, children, level: 0 }); 7473 } 7474 }); 7475 7476 return parents; 7477 } 7478 7479 // Recursive function to render nested children 7480 function renderNestedChildren(children, parentPath = '') { 7481 return children.map((child, childIndex) => { 7482 const nodePath = `${parentPath}-${childIndex}`; 7483 const hasChildren = child.children && child.children.length > 0; 7484 const level = child.level || 1; 7485 const isActive = child.url === currentPagePath; 7486 const activeClass = isActive ? ' ngw-active' : ''; 7487 7488 if(hasChildren) { 7489 return ` 7490 <div class="ngw-nested-group" data-level="${level}" data-path="${nodePath}"> 7491 <div class="ngw-nested-parent" data-path="${nodePath}"> 7492 <a href="${child.url}" class="ngw-child-link${activeClass}">${child.title}</a> 7493 <button class="ngw-nested-toggle" type="button" aria-label="Toggle ${child.title}">
7494 <span class="ngw-chevron" aria-hidden="true">${chevronIcon}</span> 7495 </button> 7496 </div> 7497 <div class="ngw-nested-children" data-path="${nodePath}"> 7498 ${renderNestedChildren(child.children, nodePath)} 7499 </div> 7500 </div> 7501 `; 7502 } 7503 7504 return `<a href="${child.url}" class="ngw-child-link${activeClass}" data-level="${level}">${child.title}</a>`; 7505 }).join(''); 7506 } 7507 7508 function render(gridData){ 7509 container.innerHTML = gridData.map((parent, idx) => { 7510 const kids = renderNestedChildren(parent.children, `${idx}`); 7511 const hasChildren = parent.children && parent.children.length > 0; 7512 7513 const isParentActive = parent.url === currentPagePath; 7514 const activeClass = isParentActive ? ' ngw-active' : ''; 7515 7516 if(!hasChildren) { 7517 return ` 7518 <section class="ngw-group ngw-no-children" role="group" data-index="${idx}"> 7519 <div class="ngw-parent" data-index="${idx}"> 7520 <a href="${parent.url}" class="ngw-parent-link${activeClass}">${parent.title}</a> 7521 </div> 7522 </section> 7523 `; 7524 } 7525 7526 const initialExpanded = expandAll ? 'true' : 'false'; 7527 return ` 7528 <section class="ngw-group" role="group" aria-expanded="${initialExpanded}" data-index="${idx}"> 7529 <div class="ngw-parent" data-index="${idx}" aria-controls="ngw-children-${idx}"> 7530 <a href="${parent.url}" class="ngw-parent-link${activeClass}">${parent.title}</a> 7531 <button class="ngw-toggle" type="button" aria-label="Toggle ${parent.title}"> 7532 <span class="ngw-chevron" aria-hidden="true">${chevronIcon}</span> 7533 </button> 7534 </div> 7535 <div id="ngw-children-${idx}" class="ngw-children" role="region" aria-label="${parent.title} subpages"> 7536 ${kids} 7537 </div> 7538 </section> 7539 `; 7540 }).join(''); 7541 7542 // If expandAll is enabled, also expand all nested groups 7543 if(expandAll) { 7544 container.querySelectorAll('.ngw-nested-group').forEach(g => { 7545 g.setAttribute('aria-expanded', 'true'); 7546 }); 7547 } 7548 7549 function collapseAll(){ 7550 container.querySelectorAll('.ngw-group').forEach(g=>g.setAttribute('aria-expanded','false')); 7551 container.querySelectorAll('.ngw-nested-group').forEach(g=>g.removeAttribute('aria-expanded')); 7552 } 7553 function expandOnly(index){ 7554 container.querySelectorAll('.ngw-group').forEach((g)=> { 7555 const i = parseInt(g.getAttribute('data-index')||'-1',10); 7556 g.setAttribute('aria-expanded', String(i===index)); 7557 }); 7558 } 7559 7560 // Hover functionality - only if not in expandAll mode 7561 if(openOnHover && !expandAll) { 7562 container.addEventListener('mouseenter', (e) => { 7563 const group = e.target.closest('.ngw-group'); 7564 if(!group || group.classList.contains('ngw-no-children')) return; 7565 const index = parseInt(group.querySelector('.ngw-parent')?.getAttribute('data-index') || '-1', 10); 7566 if(index >= 0) expandOnly(index); 7567 }, true); 7568 7569 container.addEventListener('mouseleave', (e) => { 7570 if(e.target.closest('.ngw-group')) return; 7571 collapseAll(); 7572 }, true); 7573 7574 // Nested hover 7575 container.addEventListener('mouseenter', (e) => { 7576 const nestedGroup = e.target.closest('.ngw-nested-group'); 7577 if(!nestedGroup) return; 7578 nestedGroup.setAttribute('aria-expanded', 'true'); 7579 }, true); 7580 7581 container.addEventListener('mouseleave', (e) => { 7582 const nestedGroup = e.target.closest('.ngw-nested-group'); 7583 if(!nestedGroup) return; 7584 nestedGroup.removeAttribute('aria-expanded'); 7585 }, true); 7586 } 7587 7588 // ---------------------------- 7589 // Toggle behavior (works in BOTH modes) 7590 // - expandAll=false: row click toggles + only one open at a time 7591 // - expandAll=true : ONLY chevron buttons toggle; everything starts expanded 7592 // ---------------------------- 7593 container.addEventListener('click', (e) => { 7594 // 1) Parent chevron button toggles its group (works even when expandAll=true) 7595 const parentToggleBtn = e.target.closest('.ngw-toggle'); 7596 if (parentToggleBtn) { 7597 const group = parentToggleBtn.closest('.ngw-group'); 7598 if (!group || group.classList.contains('ngw-no-children')) return; 7599 7600 const isOpen = group.getAttribute('aria-expanded') === 'true'; 7601 7602 // In expandAll mode: toggle ONLY this group 7603 if (expandAll) { 7604 group.setAttribute('aria-expanded', String(!isOpen)); 7605 } else { 7606 // In normal mode: preserve "only one open at a time" 7607 const index = parseInt(group.getAttribute('data-index') || '-1', 10); 7608 if (index >= 0) { 7609 if (isOpen) collapseAll(); 7610 else expandOnly(index); 7611 } 7612 } 7613 7614 e.preventDefault(); 7615 e.stopPropagation(); 7616 return; 7617 } 7618 7619 // 2) Nested chevron button toggles its nested group (works even when expandAll=true) 7620 const nestedToggleBtn = e.target.closest('.ngw-nested-toggle'); 7621 if (nestedToggleBtn) { 7622 const nestedGroup = nestedToggleBtn.closest('.ngw-nested-group'); 7623 if (!nestedGroup) return; 7624 7625 const isOpen = nestedGroup.getAttribute('aria-expanded') === 'true'; 7626 if (isOpen) nestedGroup.removeAttribute('aria-expanded'); 7627 else nestedGroup.setAttribute('aria-expanded', 'true'); 7628 7629 e.preventDefault(); 7630 e.stopPropagation(); 7631 return; 7632 } 7633 7634 // 3) In expandAll mode, do NOT allow row-click toggling (only chevrons toggle) 7635 if (expandAll) return; 7636 7637 // 4) Normal mode: clicking anywhere on parent row toggles (except the parent hyperlink) 7638 const parentRow = e.target.closest('.ngw-parent'); 7639 if (!parentRow) return; 7640 7641 // If they clicked the parent hyperlink, let the browser navigate naturally 7642 if (e.target.closest('.ngw-parent-link')) return; 7643 7644 const index = parseInt(parentRow.getAttribute('data-index') || '-1', 10); 7645 if (index < 0) return; 7646 7647 const group = parentRow.closest('.ngw-group'); 7648 if (!group || group.classList.contains('ngw-no-children')) return; 7649 7650 const isOpen = group.getAttribute('aria-expanded') === 'true'; 7651 if (isOpen) collapseAll(); 7652 else expandOnly(index); 7653 }); 7654 7655 // Keyboard support 7656 container.addEventListener('keydown', (e) => { 7657 if (expandAll) return; // chevron buttons already work via native button behavior 7658 7659 const parentRow = e.target.closest('.ngw-parent'); 7660 const nestedParent = e.target.closest('.ngw-nested-parent'); 7661 7662 if (parentRow && !nestedParent) { 7663 if (document.activeElement && document.activeElement.classList.contains('ngw-parent-link') && e.key === 'Enter') { 7664 return; 7665 } 7666 const group = parentRow.closest('.ngw-group'); 7667 if (group && group.classList.contains('ngw-no-children')) return; 7668 7669 if (e.key === ' ' || e.key === 'Enter') { 7670 e.preventDefault(); 7671 const index = parseInt(parentRow.getAttribute('data-index') || '-1', 10); 7672 if (index < 0) return; 7673 const isOpen = group.getAttribute('aria-expanded') === 'true'; 7674 if (isOpen) collapseAll(); 7675 else expandOnly(index); 7676 } 7677 } 7678 7679 if (nestedParent) { 7680 if (document.activeElement && document.activeElement.classList.contains('ngw-child-link') && e.key === 'Enter') { 7681 return; 7682 } 7683 if (e.key === ' ' || e.key === 'Enter') { 7684 e.preventDefault(); 7685 const nestedGroup = nestedParent.closest('.ngw-nested-group'); 7686 if (!nestedGroup) return; 7687 const isOpen = nestedGroup.getAttribute('aria-expanded') === 'true'; 7688 if (isOpen) nestedGroup.removeAttribute('aria-expanded'); 7689 else nestedGroup.setAttribute('aria-expanded', 'true'); 7690 } 7691 } 7692 }); 7693 } 7694
7695 function init(){ 7696 const build = ()=>{ 7697 const navData = extractNavFromDOM(); 7698 if(navData && navData.length){ 7699 render(navData); 7700 return true; 7701 } 7702 return false; 7703 }; 7704 const okNow = build(); 7705 if(!okNow){ setTimeout(build, 350); } // retry once for late-loaded nav 7706 } 7707 7708 init(); 7709}); 7710 }; 7711</script>
7711 7712
7713<script> 7714 window.customWidgetsFunctions["31ea1ee9b19c4368abcc1dbd5ec6a0d6~2"] = function (element, data, api) { 7715 window.dmAPI.runOnReady('cross-collection-image', async () => { 7716 const containerEl = element.querySelector('.cross-collection-image'); 7717 const overlayEl = element.querySelector('.cross-collection-image-overlay'); 7718 7719 if (!containerEl) return; 7720 7721 const config = data.config || {}; 7722 7723 function safeTrim(value) { 7724 return value == null ? '' : String(value).trim(); 7725 } 7726 7727 function stripHtml(value) { 7728 const temporaryElement = document.createElement('div'); 7729 temporaryElement.innerHTML = safeTrim(value); 7730 7731 return safeTrim( 7732 temporaryElement.textContent || 7733 temporaryElement.innerText || 7734 '' 7735 ); 7736 } 7737 7738 function removeDiacritics(value) { 7739 const text = safeTrim(value); 7740 7741 if (typeof text.normalize !== 'function') { 7742 return text; 7743 } 7744 7745 return text 7746 .normalize('NFKD') 7747 .replace(/[\u0300-\u036f]/g, ''); 7748 } 7749 7750 function slugify(value) { 7751 return removeDiacritics(value) 7752 .toLowerCase() 7753 .replace(/[â']/g, '') 7754 .replace(/[^a-z0-9]+/g, '-') 7755 .replace(/-+/g, '-') 7756 .replace(/^-+|-+$/g, ''); 7757 } 7758 7759 /* 7760 Creates alternate URL slug versions. 7761 7762 Showers & Doors: 7763 - showers-and-doors 7764 - showers-doors 7765 7766 Showers and Doors: 7767 - showers-and-doors 7768 - showers-doors 7769 7770 A/C Repair: 7771 - a-c-repair 7772 - ac-repair 7773 7774 Heating/Cooling: 7775 - heating-cooling 7776 - heatingcooling 7777 */ 7778 function createSlugCandidates(value) { 7779 const originalText = stripHtml(value); 7780 const candidates = []; 7781 const seen = new Set(); 7782 7783 function addCandidate(candidateText) { 7784 const candidate = slugify(candidateText); 7785 7786 if (candidate && !seen.has(candidate)) { 7787 seen.add(candidate); 7788 candidates.push(candidate); 7789 } 7790 } 7791 7792 if (!originalText) { 7793 return candidates; 7794 } 7795 7796 const ampersandVariants = [ 7797 originalText.replace(/&/g, ' and '), 7798 originalText.replace(/&/g, ' '), 7799 originalText 7800 ]; 7801
7802 ampersandVariants.forEach(ampersandVariant => { 7803 const andVariants = [ 7804 ampersandVariant, 7805 ampersandVariant.replace(/\band\b/gi, ' ') 7806 ]; 7807 7808 andVariants.forEach(andVariant => { 7809 /* 7810 Treat a slash as a separator. 7811 7812 A/C Repair becomes a-c-repair. 7813 */ 7814 addCandidate( 7815 andVariant.replace(/\s*[\\/]+\s*/g, ' ') 7816 ); 7817 7818 /* 7819 Remove a slash completely. 7820 7821 A/C Repair becomes ac-repair. 7822 */ 7823 addCandidate( 7824 andVariant.replace(/\s*[\\/]+\s*/g, '') 7825 ); 7826 }); 7827 }); 7828 7829 return candidates; 7830 } 7831 7832 /* 7833 Supports stored values such as: 7834 7835 college-transcripts 7836 /category/college-transcripts/ 7837 https://example.com/category/college-transcripts/ 7838 */ 7839 function normalizeStoredSlug(value) { 7840 let slug = safeTrim(value); 7841 7842 if (!slug) return ''; 7843 7844 try { 7845 slug = decodeURIComponent(slug); 7846 } catch (e) { 7847 // Retain the original value. 7848 } 7849 7850 slug = slug 7851 .split('#')[0] 7852 .split('?')[0] 7853 .replace(/^https?:\/\/[^/]+/i, '') 7854 .replace(/^\/+|\/+$/g, ''); 7855 7856 if (slug.includes('/')) { 7857 slug = slug 7858 .split('/') 7859 .filter(Boolean) 7860 .pop() || ''; 7861 } 7862 7863 return safeTrim(slug).toLowerCase(); 7864 } 7865 7866 function getCurrentSlug() { 7867 const pathParts = (window.location.pathname || '') 7868 .split('/') 7869 .filter(Boolean); 7870 7871 return normalizeStoredSlug( 7872 pathParts.pop() || '' 7873 ); 7874 } 7875 7876 /* 7877 Used to find the collection row representing 7878 the current page. 7879 */ 7880 function getSourceEntrySlugs(entry) { 7881 if (!entry) return []; 7882 7883 const row = entry.data || {}; 7884 7885 return [ 7886 entry.page_item_url, 7887 row.page_item_url, 7888 entry.item, 7889 row.item, 7890 entry.name, 7891 row.name, 7892 entry.url, 7893 row.url 7894 ] 7895 .map(normalizeStoredSlug) 7896 .filter(Boolean); 7897 } 7898 7899 /* 7900 Destination matching is based on page_item_url. 7901 */ 7902 function getDestinationEntrySlugs(entry) { 7903 if (!entry) return []; 7904 7905 const row = entry.data || {}; 7906 7907 return [ 7908 entry.page_item_url, 7909 row.page_item_url 7910 ] 7911 .map(normalizeStoredSlug) 7912 .filter(Boolean); 7913 } 7914 7915 function findSourceEntry( 7916 entries, 7917 currentSlug, 7918 sourcePageType 7919 ) { 7920 if ( 7921 !Array.isArray(entries) || 7922 entries.length === 0 7923 ) { 7924 return null; 7925 } 7926 7927 if ( 7928 currentSlug && 7929 currentSlug !== '~page-item~' 7930 ) { 7931 const matchedEntry = entries.find(entry => 7932 getSourceEntrySlugs(entry).includes( 7933 currentSlug 7934 ) 7935 ); 7936 7937 if (matchedEntry) { 7938 return matchedEntry; 7939 } 7940 } 7941 7942 /* 7943 01 HOME normally contains one row. 7944 7945 Only Home Page mode may use the first row. 7946 Category Page mode must match the current URL slug. 7947 */ 7948 if (sourcePageType === 'home') { 7949 return entries[0]; 7950 } 7951 7952 return null; 7953 } 7954 7955 function findDestination( 7956 entries, 7957 slugCandidates 7958 ) { 7959 if ( 7960 !Array.isArray(entries) || 7961 !Array.isArray(slugCandidates) 7962 ) { 7963 return null; 7964 } 7965 7966 for (const candidate of slugCandidates) { 7967 const matchedEntry = entries.find(entry => 7968 getDestinationEntrySlugs(entry).includes( 7969 candidate 7970 ) 7971 ); 7972 7973 if (matchedEntry) { 7974 return { 7975 entry: matchedEntry, 7976 slug: candidate 7977 }; 7978 } 7979 } 7980 7981 return null; 7982 } 7983 7984 /* 7985 Supports either a plain image URL or an image object 7986 returned by a Duda collection image field. 7987 */ 7988 function extractImageUrl(imageValue) { 7989 if (!imageValue) return ''; 7990 7991 if (typeof imageValue === 'string') { 7992 return safeTrim(imageValue); 7993 } 7994 7995 if (typeof imageValue !== 'object') { 7996 return ''; 7997 } 7998 7999 const possibleValues = [ 8000 imageValue.url, 8001 imageValue.src, 8002 imageValue.image_url, 8003 imageValue.original_url, 8004 imageValue.originalUrl, 8005 imageValue.full, 8006 imageValue.data && imageValue.data.url, 8007 imageValue.data && imageValue.data.src 8008 ]; 8009 8010 for (const possibleValue of possibleValues) { 8011 const imageUrl = safeTrim(possibleValue); 8012 8013 if (imageUrl) { 8014 return imageUrl; 8015 } 8016 } 8017 8018 return ''; 8019 } 8020 8021 function normalizePageType(value) { 8022 const normalizedValue = 8023 safeTrim(value).toLowerCase(); 8024 8025 if ( 8026 normalizedValue === 'category' || 8027 normalizedValue === 'category page' 8028 ) { 8029 return 'category'; 8030 } 8031 8032 return 'home'; 8033 } 8034 8035 function getSelectedBlockNumber(value) { 8036 const configuredValue = safeTrim(value); 8037 8038 const numberMatch = configuredValue.match( 8039 /(?:^|\D)(10|[1-9])(?:\D|$)/ 8040 ); 8041 8042 return numberMatch 8043 ? numberMatch[1] 8044 : '1'; 8045 } 8046 8047 function normalizeDimension(value, fallbackValue) { 8048 const configuredValue = safeTrim(value); 8049 8050 if (!configuredValue) { 8051 return fallbackValue; 8052 } 8053 8054 if (/^\d+(\.\d+)?$/.test(configuredValue)) { 8055 return configuredValue + 'px'; 8056 } 8057 8058 if ( 8059 /^\d+(\.\d+)?(px|rem|em|vh|vw|%)$/i.test( 8060 configuredValue 8061 ) 8062 ) { 8063 return configuredValue; 8064 } 8065 8066 return fallbackValue; 8067 } 8068
8069 function normalizeBackgroundSize(value) { 8070 const configuredValue = 8071 safeTrim(value).toLowerCase(); 8072 8073 if ( 8074 configuredValue === 'contain' || 8075 configuredValue === 'auto' 8076 ) { 8077 return configuredValue; 8078 } 8079 8080 return 'cover'; 8081 } 8082 8083 function normalizeBackgroundPosition(value) { 8084 const configuredValue = 8085 safeTrim(value).toLowerCase(); 8086 8087 const allowedPositions = [ 8088 'center center', 8089 'top center', 8090 'bottom center', 8091 'center left', 8092 'center right', 8093 'top left', 8094 'top right', 8095 'bottom left', 8096 'bottom right' 8097 ]; 8098 8099 return allowedPositions.includes(configuredValue) 8100 ? configuredValue 8101 : 'center center'; 8102 } 8103 8104 function normalizeOpacity(value) { 8105 const parsedValue = Number(value); 8106 8107 if (!Number.isFinite(parsedValue)) { 8108 return 0; 8109 } 8110 8111 if (parsedValue > 1) { 8112 return Math.min( 8113 Math.max(parsedValue / 100, 0), 8114 1 8115 ); 8116 } 8117 8118 return Math.min( 8119 Math.max(parsedValue, 0), 8120 1 8121 ); 8122 } 8123 8124 function normalizeBoolean(value) { 8125 if (typeof value === 'boolean') { 8126 return value; 8127 } 8128 8129 const normalizedValue = 8130 safeTrim(value).toLowerCase(); 8131 8132 return [ 8133 'true', 8134 '1', 8135 'yes', 8136 'on', 8137 'enabled' 8138 ].includes(normalizedValue); 8139 } 8140 8141 function applyDesignSettings() { 8142 const imageHeight = normalizeDimension( 8143 config.imageHeight, 8144 '400px' 8145 ); 8146 8147 const borderRadius = normalizeDimension( 8148 config.borderRadius, 8149 '0px' 8150 ); 8151 8152 const backgroundSize =
8153 normalizeBackgroundSize( 8154 config.backgroundSize 8155 ); 8156 8157 const backgroundPosition = 8158 normalizeBackgroundPosition( 8159 config.backgroundPosition 8160 ); 8161 8162 const overlayColor = 8163 safeTrim(config.overlayColor) || 8164 '#000000'; 8165 8166 const overlayOpacity = 8167 normalizeOpacity( 8168 config.overlayOpacity 8169 ); 8170 8171 const enableHoverLift = 8172 normalizeBoolean( 8173 config.enableHoverLift 8174 ); 8175 8176 containerEl.style.setProperty( 8177 '--cross-image-height', 8178 imageHeight 8179 ); 8180 8181 containerEl.style.setProperty( 8182 '--cross-image-border-radius', 8183 borderRadius 8184 ); 8185 8186 containerEl.style.setProperty( 8187 '--cross-image-background-size', 8188 backgroundSize 8189 ); 8190 8191 containerEl.style.setProperty( 8192 '--cross-image-background-position', 8193 backgroundPosition 8194 ); 8195 8196 containerEl.classList.toggle( 8197 'hover-lift-enabled', 8198 enableHoverLift 8199 ); 8200 8201 if (overlayEl) { 8202 overlayEl.style.setProperty( 8203 '--cross-image-overlay-color', 8204 overlayColor 8205 ); 8206 8207 overlayEl.style.setProperty( 8208 '--cross-image-overlay-opacity', 8209 String(overlayOpacity) 8210 ); 8211 } 8212 } 8213 8214 function createCssBackgroundImage(imageUrl) { 8215 const escapedUrl = imageUrl 8216 .replace(/\\/g, '\\\\') 8217 .replace(/"/g, '\\"'); 8218 8219 return `url("${escapedUrl}")`; 8220 } 8221 8222 function showImage(imageUrl, accessibleLabel) { 8223 containerEl.style.backgroundImage = 8224 createCssBackgroundImage(imageUrl); 8225 8226 containerEl.setAttribute( 8227 'aria-busy', 8228 'false' 8229 ); 8230 8231 containerEl.setAttribute( 8232 'aria-hidden', 8233 'false' 8234 ); 8235 8236 containerEl.setAttribute( 8237 'aria-label', 8238 accessibleLabel || 'Page image' 8239 ); 8240 8241 containerEl.classList.remove( 8242 'is-hidden' 8243 ); 8244 8245 containerEl.classList.add( 8246 'is-loaded' 8247 ); 8248 } 8249 8250 function hideImage() { 8251 containerEl.style.backgroundImage = ''; 8252 8253 containerEl.setAttribute( 8254 'aria-busy', 8255 'false' 8256 ); 8257 8258 containerEl.setAttribute( 8259 'aria-hidden', 8260 'true' 8261 ); 8262 8263 containerEl.removeAttribute( 8264 'aria-label' 8265 ); 8266 8267 containerEl.classList.remove( 8268 'is-loaded' 8269 ); 8270 8271 containerEl.classList.add( 8272 'is-hidden' 8273 ); 8274 } 8275 8276 /* 8277 Collection requests are shared between multiple 8278 copies of this widget on the same page. 8279 */ 8280 function getCollectionCache() { 8281 if ( 8282 !window.__crossCollectionImageCache 8283 ) { 8284 window.__crossCollectionImageCache = {}; 8285 } 8286 8287 return window.__crossCollectionImageCache; 8288 } 8289 8290 function getCollectionsApiPromise() { 8291 if ( 8292 !window.__crossCollectionImageApiPromise 8293 ) { 8294 window.__crossCollectionImageApiPromise = 8295 dmAPI 8296 .loadCollectionsAPI() 8297 .catch(error => { 8298 delete window 8299 .__crossCollectionImageApiPromise; 8300 8301 throw error; 8302 }); 8303 } 8304 8305 return window.__crossCollectionImageApiPromise; 8306 } 8307 8308 function loadCollectionEntries(collectionName) { 8309 const collectionCache = 8310 getCollectionCache(); 8311 8312 if (!collectionCache[collectionName]) { 8313 collectionCache[collectionName] = 8314 getCollectionsApiPromise() 8315 .then(collectionApi => 8316 collectionApi 8317 .data(collectionName) 8318 .get() 8319 ) 8320 .then(result => { 8321 return Array.isArray( 8322 result && result.values 8323 ) 8324 ? result.values 8325 : []; 8326 }) 8327 .catch(error => { 8328 delete collectionCache[ 8329 collectionName 8330 ]; 8331 8332 throw error; 8333 }); 8334 } 8335 8336 return collectionCache[ 8337 collectionName 8338 ]; 8339 } 8340 8341 applyDesignSettings(); 8342 8343 try { 8344 const sourcePageType = 8345 normalizePageType( 8346 config.sourcePageType 8347 ); 8348 8349 const sourceCollectionName = 8350 sourcePageType === 'category' 8351 ? '02 CATEGORY' 8352 : '01 HOME'; 8353 8354 const currentSlug = 8355 getCurrentSlug(); 8356 8357 const sourceEntries = 8358 await loadCollectionEntries( 8359 sourceCollectionName 8360 ); 8361 8362 const sourceEntry = 8363 findSourceEntry( 8364 sourceEntries, 8365 currentSlug, 8366 sourcePageType 8367 ); 8368 8369 if (!sourceEntry) { 8370 hideImage(); 8371 return; 8372 } 8373 8374 const blockNumber = 8375 getSelectedBlockNumber( 8376 config.copyBlockNumber 8377 ); 8378 8379 const headlineFieldName = 8380 'COPY BLOCK ' + 8381 blockNumber + 8382 ' HEADLINE'; 8383 8384 const sourceRow = 8385 sourceEntry.data || 8386 sourceEntry; 8387 8388 const rawHeadline = 8389 sourceRow[headlineFieldName]; 8390 8391 const plainHeadline =
8392 stripHtml(rawHeadline); 8393 8394 const slugCandidates = 8395 createSlugCandidates(rawHeadline); 8396 8397 if ( 8398 slugCandidates.length === 0 8399 ) { 8400 hideImage(); 8401 return; 8402 } 8403 8404 /* 8405 Reuse 02 CATEGORY when it was already loaded 8406 as the source collection. 8407 */ 8408 const categoryEntriesPromise = 8409 sourceCollectionName === 8410 '02 CATEGORY' 8411 ? Promise.resolve(sourceEntries) 8412 : loadCollectionEntries( 8413 '02 CATEGORY' 8414 ).catch(() => []); 8415 8416 const coreEntriesPromise = 8417 loadCollectionEntries( 8418 '03 CORE' 8419 ).catch(() => []); 8420 8421 const [ 8422 categoryEntries, 8423 coreEntries 8424 ] = await Promise.all([ 8425 categoryEntriesPromise, 8426 coreEntriesPromise 8427 ]); 8428 8429 /* 8430 Home Page: 8431 1. Search 02 CATEGORY 8432 2. Search 03 CORE 8433 8434 Category Page: 8435 1. Search 03 CORE 8436 2. Search 02 CATEGORY 8437 */ 8438 const destinationSearchOrder = 8439 sourcePageType === 'home' 8440 ? [ 8441 categoryEntries, 8442 coreEntries 8443 ] 8444 : [ 8445 coreEntries, 8446 categoryEntries 8447 ]; 8448 8449 let matchedDestination = null; 8450 8451 for ( 8452 const destinationEntries 8453 of destinationSearchOrder 8454 ) { 8455 const match = findDestination( 8456 destinationEntries, 8457 slugCandidates 8458 ); 8459 8460 if (match) { 8461 matchedDestination = match; 8462 break; 8463 } 8464 } 8465 8466 if (!matchedDestination) { 8467 hideImage(); 8468 return; 8469 } 8470 8471 const destinationRow = 8472 matchedDestination.entry.data || 8473 matchedDestination.entry; 8474 8475 const heroImageUrl = 8476 extractImageUrl( 8477 destinationRow['HERO IMAGE'] 8478 ); 8479 8480 if (!heroImageUrl) { 8481 hideImage(); 8482 return; 8483 } 8484 8485 showImage( 8486 heroImageUrl, 8487 plainHeadline 8488 ); 8489 } catch (e) { 8490 hideImage(); 8491 } 8492}); 8493 }; 8494</script>
8494 8495
8496<script> 8497 window.customWidgetsFunctions["901b1c7285754fceac707cdcb08aa571~7"] = function (element, data, api) { 8498 window.dmAPI.runOnReady('hide-column-if-category-field-empty', function () { 8499 8500 var shouldHide = false; // track the decision so we can re-apply it 8501 var observer = null; // MutationObserver reference 8502 8503 function getLastSlug(value) { 8504 if (!value) return ''; 8505 8506 value = String(value).trim().toLowerCase(); 8507 8508 try { 8509 if (value.indexOf('http://') === 0 || value.indexOf('https://') === 0) { 8510 value = new URL(value).pathname; 8511 } 8512 } catch (e) {} 8513 8514 value = value.split('?')[0].split('#')[0]; 8515 value = value.replace(/\/+$/, ''); 8516 8517 var parts = value.split('/'); 8518 return parts[parts.length - 1] || ''; 8519 } 8520 8521 function getCurrentColumn() { 8522 var node = element.parentElement; // flex-element widget-wrapper 8523 8524 while (node && node !== document.body) { 8525 var cls = node.className || ''; 8526 8527 if (cls.indexOf('flex-element') !== -1 && cls.indexOf('group') !== -1) { 8528 return node; 8529 } 8530 8531 if ( 8532 node.matches('[data-layout-column]') || 8533 node.matches('.dmRespCol') || 8534 node.matches('[data-page-element-type="column"]') 8535 ) { 8536 return node; 8537 } 8538 8539 node = node.parentElement; 8540 } 8541 8542 return element.parentElement || null; 8543 } 8544 8545 function applyHide() { 8546 var column = getCurrentColumn(); 8547 8548 if (!column) return; 8549 8550 // Only touch the style if it isn't already correct â avoids triggering the observer 8551 if (shouldHide) { 8552 if (column.style.display !== 'none') { 8553 column.style.setProperty('display', 'none', 'important'); 8554 console.log('[HideColumn] (re-)applied hide to column:', column); 8555 } 8556 } else { 8557 column.style.removeProperty('display'); 8558 } 8559 } 8560 8561 function startObserver() { 8562 var column = getCurrentColumn(); 8563 8564 if (!column || observer) return; // don't double-attach 8565 8566 observer = new MutationObserver(function (mutations) { 8567 if (!shouldHide) return; 8568 8569 for (var i = 0; i < mutations.length; i++) { 8570 var m = mutations[i]; 8571 8572 if (m.type === 'attributes' && m.attributeName === 'style') { 8573 var col = getCurrentColumn(); 8574 8575 if (col && col.style.display !== 'none') { 8576 // Something reset the display â put it back 8577 col.style.setProperty('display', 'none', 'important'); 8578 console.log('[HideColumn] Observer re-hid column after external style reset'); 8579 } 8580 } 8581 } 8582 }); 8583 8584 observer.observe(column, { attributes: true, attributeFilter: ['style'] }); 8585 console.log('[HideColumn] MutationObserver attached to column:', column); 8586 } 8587 8588 function checkCollection(marker) { 8589 var collectionName = marker.getAttribute('data-collection-name') || '02 CATEGORY'; 8590 var requiredFieldName = marker.getAttribute('data-required-field') || 'COPY BLOCK 1 HEADLINE'; 8591 var currentSlug = getLastSlug(window.location.href); 8592 8593 console.log('[HideColumn] Current slug:', currentSlug); 8594 console.log('[HideColumn] Collection:', collectionName); 8595 console.log('[HideColumn] Required field:', requiredFieldName); 8596 8597 if (!window.dmAPI || typeof dmAPI.loadCollectionsAPI !== 'function') { 8598 console.warn('[HideColumn] Duda Collections API not available.'); 8599 return; 8600 } 8601 8602 dmAPI.loadCollectionsAPI() 8603 .then(function (collection) { 8604 return collection 8605 .data(collectionName) 8606 .pageSize(100) 8607 .get(); 8608 }) 8609 .then(function (result) { 8610 console.log('[HideColumn] Raw result:', result); 8611 8612 var rows = []; 8613 8614 if (result && Array.isArray(result.values)) { 8615 rows = result.values; 8616 } else if (Array.isArray(result)) { 8617 rows = result; 8618 } 8619 8620 console.log('[HideColumn] Total rows:', rows.length); 8621 8622 if (rows.length > 0) { 8623 console.log('[HideColumn] First row dump:', rows[0]); 8624 console.log('[HideColumn] First row keys:', Object.keys(rows[0] || {})); 8625 8626 if (rows[0] && rows[0].data) { 8627 console.log('[HideColumn] First row data keys:', Object.keys(rows[0].data || {})); 8628 } 8629 } 8630 8631 var matchingRow = null; 8632 8633 /* 8634 Special handling for 01 HOME: 8635 Do not match against the current URL slug. 8636 Just read the first row in the collection. 8637 Expected page_item_url is /home. 8638 */ 8639 if (collectionName === '01 HOME') { 8640 matchingRow = rows[0] || null; 8641 8642 if (matchingRow) { 8643 console.log('[HideColumn] 01 HOME detected â using first row:', matchingRow); 8644 } else { 8645 console.warn('[HideColumn] 01 HOME detected, but no rows were found.'); 8646 } 8647 8648 } else { 8649 8650 for (var i = 0; i < rows.length; i++) { 8651 var row = rows[i]; 8652 var rowData = row.data || row; 8653 8654 var rawSlugValue = 8655 row.page_item_url || 8656 rowData.page_item_url || 8657 rowData['page_item_url'] || 8658 rowData['item'] || 8659 rowData['slug'] || 8660 row.item || 8661 row.slug || 8662 ''; 8663 8664 var rowSlug = getLastSlug(rawSlugValue); 8665 8666 console.log('[HideColumn] Row', i, 'raw slug candidate:', rawSlugValue); 8667 console.log('[HideColumn] Row', i, 'normalized slug:', rowSlug); 8668 8669 if (rowSlug === currentSlug) { 8670 matchingRow = row; 8671 console.log('[HideColumn] Matching row found:', matchingRow); 8672 break; 8673 } 8674 } 8675 } 8676 8677 if (!matchingRow) { 8678 console.warn('[HideColumn] No matching row found for collection:', collectionName); 8679 return; 8680 } 8681 8682 var matchingRowData = matchingRow.data || matchingRow; 8683 var fieldValue = matchingRowData[requiredFieldName]; 8684 8685 console.log('[HideColumn] Field "' + requiredFieldName + '" value:', fieldValue); 8686 8687 var hasValue = 8688 fieldValue !== null && 8689 fieldValue !== undefined && 8690 String(fieldValue).trim() !== ''; 8691 8692 shouldHide = !hasValue; 8693 8694 if (shouldHide) { 8695 console.log('[HideColumn] Field is empty â hiding column.'); 8696 applyHide(); 8697 startObserver(); 8698 } else { 8699 console.log('[HideColumn] Field has value â column stays visible.'); 8700 applyHide(); 8701 } 8702 }) 8703 .catch(function (error) { 8704 console.warn('[HideColumn] Collection check failed:', error); 8705 }); 8706 } 8707 8708 function run() { 8709 var markers = element.querySelectorAll('.hide-column-if-category-field-empty'); 8710 8711 for (var i = 0; i < markers.length; i++) { 8712 checkCollection(markers[i]); 8713 } 8714 8715 // Retry after 1.5s and again after 4s to cover slow lazy-load scenarios 8716 setTimeout(function () { 8717 var markers2 = element.querySelectorAll('.hide-column-if-category-field-empty'); 8718 8719 for (var j = 0; j < markers2.length; j++) { 8720 checkCollection(markers2[j]); 8721 } 8722 }, 1500); 8723 8724 setTimeout(function () { 8725 // By now the decision is known â just re-apply in case something reset it 8726 applyHide(); 8727 }, 4000); 8728 } 8729 8730 run(); 8731 8732}); 8733 }; 8734</script>
8734 8735
8736<script> 8737 window.customWidgetsFunctions["6f306f3f1793463e9c5243713002bc78~4"] = function (element, data, api) { 8738 window.dmAPI.runOnReady('formTitleWidget', () => { 8739 const COLLECTION_NAME = 'form'; 8740 const FIELD_LABEL = 'Form Title'; 8741 const fallbackText = data.config['fallbackText'] || 'Request A Callback'; 8742 const outputElement = element.querySelector('.form-title-output'); 8743 8744 function htmlToPlain(textOrHtml) { 8745 if (textOrHtml == null) return ''; 8746 const div = document.createElement('div'); 8747 div.innerHTML = String(textOrHtml).replace(/<br\s*\/?>/gi, '\n'); 8748 const blocks = div.querySelectorAll('p, li, h1, h2, h3, h4, h5, h6, div'); 8749 if (blocks.length) { 8750 return Array.from(blocks).map(el => el.textContent.trim()).filter(Boolean).join(' '); 8751 } 8752 return div.textContent.trim(); 8753 } 8754 8755 function setOutput(text) { 8756 if (!outputElement) return; 8757 outputElement.textContent = text || fallbackText; 8758 } 8759 8760 function pickFirstNonEmpty(values) { 8761 for (const row of values || []) { 8762 const val = row && row.data ? row.data[FIELD_LABEL] : null; 8763 const plain = htmlToPlain(val); 8764 if (plain) return plain; 8765 } 8766 return ''; 8767 } 8768 8769 function loadAndRender() { 8770 if (typeof dmAPI === 'undefined' || !dmAPI.loadCollectionsAPI) { 8771 setOutput(fallbackText); 8772 return; 8773 } 8774 8775 dmAPI.loadCollectionsAPI() 8776 .then(collectionApi => collectionApi.data(COLLECTION_NAME).get()) 8777 .then(res => { 8778 const values = Array.isArray(res && res.values) ? res.values : []; 8779 const title = pickFirstNonEmpty(values); 8780 setOutput(title || fallbackText); 8781 }) 8782 .catch(() => setOutput(fallbackText)); 8783 } 8784 8785 loadAndRender(); 8786}); 8787 }; 8788</script>
8788 8789
8790<script> 8791 window.customWidgetsFunctions["1c20f508b5474ea2b929959f7d5eff3d~3"] = function (element, data, api) { 8792 window.dmAPI.runOnReady('dcbh3-h3-theme', () => { 8793 8794 function applyTheme() { 8795 // Try multiple candidate selectors for the H3 style source 8796 // to work in both the editor and the published/preview environment 8797 const candidates = [ 8798 '#dm h3', 8799 'h3', 8800 ]; 8801 8802 let h3Sample = null; 8803 for (const sel of candidates) { 8804 h3Sample = document.querySelector(sel); 8805 if (h3Sample) break; 8806 } 8807 8808 if (!h3Sample) return false; 8809 8810 const computed = window.getComputedStyle(h3Sample); 8811 8812 const fontFamily = computed.fontFamily; 8813 const fontSize = computed.fontSize; 8814 const fontWeight = computed.fontWeight; 8815 const lineHeight = computed.lineHeight; 8816 const color = computed.color; 8817 const letterSpacing = computed.letterSpacing; 8818 const textTransform = computed.textTransform; 8819 const fontStyle = computed.fontStyle; 8820 8821 // Skip if nothing meaningful was computed yet 8822 if (!fontFamily || fontFamily === '') return false; 8823 8824 // Build selectors for every u_ class found on CB1 dmNewParagraph divs 8825 const uSelectors = []; 8826 const paragraphEls = document.querySelectorAll( 8827 '#dm .dmInner .widget-wrapper.DCBH3 .dmNewParagraph, ' + 8828 '.dmInner .widget-wrapper.DCBH3 .dmNewParagraph, ' + 8829 '.widget-wrapper.DCBH3 .dmNewParagraph' 8830 ); 8831 paragraphEls.forEach(el => { 8832 el.classList.forEach(cls => { 8833 if (cls.startsWith('u_')) { 8834 uSelectors.push(`div.${cls} p`); 8835 uSelectors.push(`div.${cls} li`); 8836 uSelectors.push(`*#dm .dmInner div.${cls} p`); 8837 uSelectors.push(`*#dm .dmInner div.${cls} li`); 8838 } 8839 }); 8840 }); 8841 8842 const baseSelectors = [ 8843 `#dm .dmInner .widget-wrapper.DCBH3 .dmNewParagraph`, 8844 `#dm .dmInner .widget-wrapper.DCBH3 .dmNewParagraph p`, 8845 `#dm .dmInner .widget-wrapper.DCBH3 .dmNewParagraph li`, 8846 `#dm .dmInner .widget-wrapper.DCBH3 .dmNewParagraph .rteBlock`, 8847 `.dmInner .widget-wrapper.DCBH3 .dmNewParagraph`, 8848 `.dmInner .widget-wrapper.DCBH3 .dmNewParagraph p`, 8849 `.dmInner .widget-wrapper.DCBH3 .dmNewParagraph li`, 8850 `.dmInner .widget-wrapper.DCBH3 .dmNewParagraph .rteBlock`, 8851 `.widget-wrapper.DCBH3 .dmNewParagraph`, 8852 `.widget-wrapper.DCBH3 .dmNewParagraph p`, 8853 `.widget-wrapper.DCBH3 .dmNewParagraph li`, 8854 `.widget-wrapper.DCBH3 .dmNewParagraph .rteBlock`, 8855 ]; 8856 8857 const allSelectors = [...baseSelectors, ...uSelectors].join(',\n '); 8858 8859 const css = ` 8860 ${allSelectors} { 8861 font-family: ${fontFamily} !important; 8862 font-size: ${fontSize} !important; 8863 font-weight: ${fontWeight} !important; 8864 line-height: ${lineHeight} !important; 8865 color: ${color} !important; 8866 letter-spacing: ${letterSpacing} !important; 8867 text-transform: ${textTransform} !important; 8868 font-style: ${fontStyle} !important; 8869 } 8870 `; 8871 8872 // Remove any previously injected tag before re-injecting 8873 const existing = document.querySelector('style[data-dcbh3-h3-theme]'); 8874 if (existing) existing.remove(); 8875 8876 const styleTag = document.createElement('style'); 8877 styleTag.setAttribute('data-dcbh3-h3-theme', 'true'); 8878 styleTag.textContent = css; 8879 document.head.appendChild(styleTag); 8880 8881 return true; 8882 } 8883 8884 // Try immediately 8885 if (applyTheme()) return; 8886 8887 // If not ready yet, retry with increasing delays to handle 8888 // async rendering in preview / published environments 8889 let attempts = 0; 8890 const maxAttempts = 40; 8891 const interval = setInterval(() => { 8892 attempts++; 8893 if (applyTheme() || attempts >= maxAttempts) { 8894 clearInterval(interval); 8895 } 8896 }, 500); 8897}); 8898 8899 }; 8900</script>
8900 8901
8902<script> 8903 window.customWidgetsFunctions["5b093d0fb9474c1dabfa7807be463b12~52"] = function (element, data, api) { 8904 window.dmAPI.runOnReady('nmw-mega-nav', () => { 8905 'use strict'; 8906 8907 /* 8908 NMW NAVIGATION ARCHITECTURE 8909 8910 FULL WIDGET 8911 - Fetches 06 NAV MASTER, 02 CATEGORY, 03 CORE, and optionally CUSTOMNAV. 8912 - Reads configured native pages from the hidden .navmasterdefault Duda nav. 8913 - Builds one normalized three-level navigation model. 8914 - Renders the Full navigation and publishes the shared model through window.NMW. 8915 8916 MIRROR WIDGET 8917 - Never fetches collections. 8918 - Waits for the Full widget to publish shared data. 8919 - Renders the same data vertically and stays synchronized. 8920 8921 SHARED BEHAVIOR 8922 - Click and optional hover opening. 8923 - 200 ms hover-close delay. 8924 - Escape, focus-leave, link-click, and outside-click closing. 8925 - Active-page detection from the actual current URL. 8926 - Prefix-aware dynamic matching (for example /category/x and /services/x). 8927 - JavaScript owns menu state; CSS owns appearance, positioning, and animation. 8928 */ 8929 8930 const root = element.querySelector('.nmw-root'); 8931 if (!root) return; 8932 8933 /* 8934 DUDA EDITOR LIFECYCLE 8935 8936 Duda can execute the widget JavaScript again against the same DOM root when 8937 a panel value changes. The prior closure is not automatically destroyed. 8938 Without explicit cleanup, the old instance continues observing/fetching and 8939 can overwrite the navigation built with the new configuration. 8940 */ 8941 window.NMW_RUNTIME = window.NMW_RUNTIME || { instances: new WeakMap() }; 8942 const previousInstanceCleanup = window.NMW_RUNTIME.instances.get(root); 8943 if (typeof previousInstanceCleanup === 'function') { 8944 try { 8945 previousInstanceCleanup('reinitialized'); 8946 } catch (cleanupError) { 8947 console.warn('[NMW] Previous instance cleanup failed', cleanupError); 8948 } 8949 } 8950 8951 // Support both the rebuilt HTML and the original widget HTML. 8952 // Rebuilt HTML uses [data-nmw-render]; the original widget uses 8953 // .nmw-mobile-nav-wrapper as its render container. 8954 let renderHost = root.querySelector('[data-nmw-render]'); 8955 if (!renderHost) renderHost = root.querySelector('.nmw-mobile-nav-wrapper'); 8956 if (!renderHost) { 8957 renderHost = document.createElement('div'); 8958 renderHost.className = 'nmw-render'; 8959 renderHost.setAttribute('data-nmw-render', ''); 8960 root.appendChild(renderHost); 8961 } 8962 8963 // Startup marker used to confirm that Duda executed the runOnReady callback. 8964 root.dataset.nmwScriptStarted = 'true'; 8965 8966 // Show an immediate status only when the HTML does not provide a separate 8967 // loading host. The supplied Full/feature HTML uses [data-nmw-loading-view]. 8968 const separateLoadingHost = root.querySelector('[data-nmw-loading-view]'); 8969 if (renderHost && !renderHost.innerHTML.trim() && !separateLoadingHost) { 8970 renderHost.innerHTML = '<div class="nmw-runtime-status" data-nmw-runtime-status>Loading navigationâ¦</div>'; 8971 } 8972 8973 const loadingHost = separateLoadingHost || root.querySelector('.nmw-skeleton-nav'); 8974 const toolsHost = root.querySelector('[data-nmw-tools]'); 8975 const cfg = data.config || {}; 8976 const widgetMode = readString(configValue('widgetMode'), 'full').toLowerCase() === 'mirror' ? 'mirror' : 'full'; 8977 const instanceId = createInstanceId(widgetMode); 8978 const HOVER_CLOSE_DELAY = 200; 8979 const REBUILD_DEBOUNCE = 200; 8980 const NATIVE_RETRY_INTERVAL = 500; 8981 const NATIVE_MAX_WAIT = 15000; 8982 const MAX_DEPTH = 2; 8983 8984 // Dynamic page path controls from the widget panel. 8985 // Example: childUrlPrefix = "services" resolves HVAC against /services/hvac. 8986 // Multiple aliases are supported so existing or AI-created panel fields work. 8987 const CATEGORY_URL_PREFIX = normalizeUrlPrefix( 8988 configValue('categoryUrlPrefix', 'categoryPrefix', 'categoryPagePrefix'), 8989 'category' 8990 ); 8991 const CHILD_URL_PREFIX = normalizeUrlPrefix( 8992 configValue('childUrlPrefix', 'childPrefix', 'childPagePrefix', 'coreUrlPrefix', 'corePrefix'), 8993 'services' 8994 ); 8995 8996 root.dataset.nmwMode = widgetMode; 8997 root.classList.toggle('nmw-mirror', widgetMode === 'mirror'); 8998 root.classList.toggle('nmw-vertical', widgetMode === 'mirror'); 8999 root.dataset.nmwCategoryPrefix = CATEGORY_URL_PREFIX; 9000 root.dataset.nmwChildPrefix = CHILD_URL_PREFIX; 9001 9002 // The shared namespace survives Duda widget rerenders so Mirror can keep using 9003 // the last valid navigation while Full reinitializes. 9004 window.NMW = window.NMW || {}; 9005 Object.assign(window.NMW, { 9006 loading: Boolean(window.NMW.loading), 9007 ready: Boolean(window.NMW.ready), 9008 version: Number(window.NMW.version) || 0, 9009 data: Array.isArray(window.NMW.data) ? window.NMW.data : null, 9010 error: Boolean(window.NMW.error), 9011 warnings: Array.isArray(window.NMW.warnings) ? window.NMW.warnings : [], 9012 ownerId: window.NMW.ownerId || null, 9013 mirrorOwnerId: window.NMW.mirrorOwnerId || null, 9014 fullConfig: window.NMW.fullConfig || null, 9015 fullConfigSignature: window.NMW.fullConfigSignature || '', 9016 presentationVersion: Number(window.NMW.presentationVersion) || 0, 9017 megaGroupsUsed: Array.isArray(window.NMW.megaGroupsUsed) ? window.NMW.megaGroupsUsed : [], 9018 megaGroupCount: Number(window.NMW.megaGroupCount) || 0,
9019 megaLabels: window.NMW.megaLabels || {}, 9020 slugWarnings: Array.isArray(window.NMW.slugWarnings) ? window.NMW.slugWarnings : [] 9021 }); 9022 9023 const local = { 9024 cleaned: false, 9025 listenersAttached: false, 9026 hoverTimers: new Map(), 9027 anchorTimers: new Set(), 9028 closeJobs: new WeakMap(), 9029 closeTimers: new Set(), 9030 rebuildTimer: null, 9031 rebuildRunning: false, 9032 pendingRebuild: false, 9033 nativeObserver: null, 9034 nativeFinderObserver: null, 9035 manualObserver: null, 9036 nativeRetryTimer: null, 9037 nativeRetryStarted: 0, 9038 historyCleanup: null, 9039 customDraft: null, 9040 latestBuildWarnings: [], 9041 slugValidationWarnings: [], 9042 eventCleanups: [], 9043 removalObserver: null 9044 }; 9045 9046 function listen(targetNode, eventName, handler, options) { 9047 if (!targetNode || typeof targetNode.addEventListener !== 'function') return; 9048 targetNode.addEventListener(eventName, handler, options); 9049 local.eventCleanups.push(() => { 9050 try { targetNode.removeEventListener(eventName, handler, options); } 9051 catch (error) {} 9052 }); 9053 } 9054 9055 // --------------------------------------------------------------------------- 9056 // Generic helpers 9057 // --------------------------------------------------------------------------- 9058 9059 function readString(value, fallback = '') { 9060 if (value == null) return fallback; 9061 return String(value).trim() || fallback; 9062 } 9063 9064 function readBoolean(value, fallback = false) { 9065 if (value == null || value === '') return fallback; 9066 if (typeof value === 'boolean') return value; 9067 const normalized = String(value).trim().toLowerCase(); 9068 if (['true', '1', 'yes', 'on'].includes(normalized)) return true; 9069 if (['false', '0', 'no', 'off'].includes(normalized)) return false; 9070 return fallback; 9071 } 9072 9073 function readNumber(value, fallback, min = -Infinity, max = Infinity) { 9074 const parsed = Number(value); 9075 if (!Number.isFinite(parsed)) return fallback; 9076 return Math.min(max, Math.max(min, parsed)); 9077 } 9078 9079 function escapeHtml(value) { 9080 return String(value == null ? '' : value) 9081 .replace(/&/g, '&') 9082 .replace(/</g, '<') 9083 .replace(/>/g, '>') 9084 .replace(/"/g, '"') 9085 .replace(/'/g, '''); 9086 } 9087 9088 function cssValue(value, fallback) {
9089 let candidate = value; 9090 if (candidate && typeof candidate === 'object') { 9091 candidate = candidate.value 9092 ?? candidate.css 9093 ?? candidate.color 9094 ?? candidate.hex 9095 ?? candidate.fontFamily 9096 ?? candidate.family 9097 ?? candidate.name 9098 ?? ''; 9099 } 9100 const result = readString(candidate, ''); 9101 return result || fallback; 9102 } 9103 9104 function cssLength(value, fallback) { 9105 const result = cssValue(value, ''); 9106 if (!result) return fallback; 9107 return /^-?(?:\d+|\d*\.\d+)$/.test(result) ? `${result}px` : result; 9108 } 9109 9110 // Duda font controls may return a plain string, a number, or a nested 9111 // typography object. Read the requested part without assuming one exact shape. 9112 function readFontPart(value, part, fallback) { 9113 const visited = new Set(); 9114 9115 function parse(candidate, depth = 0) { 9116 if (candidate == null || depth > 6) return undefined; 9117 9118 if (typeof candidate === 'string') { 9119 const text = candidate.trim(); 9120 if (!text) return undefined; 9121 9122 // Some Duda controls serialize their configuration as JSON text. 9123 if ((text.startsWith('{') && text.endsWith('}')) || (text.startsWith('[') && text.endsWith(']'))) { 9124 try { 9125 const parsed = JSON.parse(text); 9126 const nested = parse(parsed, depth + 1); 9127 if (nested !== undefined) return nested; 9128 } catch (error) {} 9129 } 9130 9131 if (part === 'size') { 9132 const directLength = text.match(/^-?(?:\d+|\d*\.\d+)(?:px|rem|em|%|vw|vh|pt)?$/i); 9133 if (directLength) return cssLength(text, fallback); 9134 const embeddedLength = text.match(/(?:^|\s)(\d+(?:\.\d+)?(?:px|rem|em|%|vw|vh|pt))(?:\s|\/|$)/i); 9135 return embeddedLength ? embeddedLength[1] : undefined; 9136 } 9137 9138 if (part === 'weight') { 9139 if (/^(?:normal|bold|bolder|lighter|[1-9]00)$/i.test(text)) return text; 9140 return undefined; 9141 } 9142 9143 // A family string should not be mistaken for a size or weight. 9144 if (/^-?(?:\d+|\d*\.\d+)(?:px|rem|em|%|vw|vh|pt)?$/i.test(text)) return undefined; 9145 if (/^(?:normal|bold|bolder|lighter|[1-9]00)$/i.test(text)) return undefined; 9146 return text; 9147 } 9148 9149 if (typeof candidate === 'number') { 9150 if (part === 'size') return `${candidate}px`; 9151 if (part === 'weight') return String(candidate); 9152 return undefined; 9153 } 9154 9155 if (typeof candidate !== 'object') return undefined; 9156 if (visited.has(candidate)) return undefined; 9157 visited.add(candidate); 9158 9159 const keyMap = { 9160 family: ['fontFamily', 'font-family', 'family', 'fontName', 'font', 'name'], 9161 size: ['fontSize', 'font-size', 'size', 'textSize', 'text-size'], 9162 weight: ['fontWeight', 'font-weight', 'weight'] 9163 }; 9164 9165 for (const key of keyMap[part] || []) { 9166 if (Object.prototype.hasOwnProperty.call(candidate, key)) { 9167 const found = parse(candidate[key], depth + 1); 9168 if (found !== undefined) return found; 9169 } 9170 } 9171 9172 // Duda controls may wrap the typography value inside one of these keys. 9173 for (const key of ['value', 'typography', 'style', 'styles', 'settings', 'fontSettings', 'data']) { 9174 if (Object.prototype.hasOwnProperty.call(candidate, key)) { 9175 const found = parse(candidate[key], depth + 1); 9176 if (found !== undefined) return found; 9177 } 9178 } 9179 9180 // Last-resort recursive scan for an unfamiliar wrapper object. 9181 for (const child of Object.values(candidate)) { 9182 if (child && typeof child === 'object') { 9183 const found = parse(child, depth + 1); 9184 if (found !== undefined) return found; 9185 } 9186 } 9187 9188 return undefined; 9189 } 9190 9191 const result = parse(value); 9192 return result === undefined || result === '' ? fallback : result; 9193 } 9194 9195 function fontFamilyValue(value, fallback = 'inherit') { 9196 return readFontPart(value, 'family', fallback); 9197 } 9198 9199 function fontSizeValue(value, fallback = '16px') { 9200 return readFontPart(value, 'size', fallback); 9201 } 9202
9203 function fontWeightValue(value, fallback = '400') { 9204 return readFontPart(value, 'weight', fallback); 9205 } 9206 9207 function normalizeChevronStyle(value, fallback = 'filled') { 9208 const normalized = readString(value, fallback).toLowerCase(); 9209 if (['none', 'off', 'hidden'].includes(normalized)) return 'none'; 9210 if (['chevron', 'outline'].includes(normalized)) return 'chevron'; 9211 if (normalized === 'caret') return 'caret'; 9212 if (normalized === 'triangle') return 'triangle'; 9213 return 'filled'; 9214 } 9215 9216 function createInstanceId(mode) { 9217 return `nmw-${mode}-${Math.random().toString(36).slice(2, 9)}`; 9218 } 9219 9220 function field(row, ...names) { 9221 if (!row || typeof row !== 'object') return ''; 9222 for (const name of names) { 9223 if (Object.prototype.hasOwnProperty.call(row, name)) return row[name]; 9224 const key = Object.keys(row).find(item => item.toLowerCase() === String(name).toLowerCase()); 9225 if (key) return row[key]; 9226 } 9227 return ''; 9228 } 9229 9230 // Read a widget configuration value by key, including values placed inside 9231 // Duda panel groups. This makes fields such as childUrlPrefix work whether the 9232 // panel stores them directly on data.config or inside a grouped object. 9233 function configValue(...names) { 9234 const wanted = names.map(name => String(name).toLowerCase()); 9235 const visited = new Set(); 9236 9237 function search(value, depth) { 9238 if (!value || typeof value !== 'object' || Array.isArray(value) || depth > 6 || visited.has(value)) { 9239 return undefined; 9240 } 9241 visited.add(value); 9242 9243 for (const key of Object.keys(value)) { 9244 if (wanted.includes(key.toLowerCase()) && value[key] !== undefined) { 9245 return value[key]; 9246 } 9247 } 9248 9249 for (const key of Object.keys(value)) { 9250 const found = search(value[key], depth + 1); 9251 if (found !== undefined) return found; 9252 } 9253 9254 return undefined; 9255 } 9256 9257 return search(cfg, 0); 9258 } 9259 9260 9261 function configValueFrom(source, ...names) { 9262 const wanted = names.map(name => String(name).toLowerCase()); 9263 const visited = new Set(); 9264 9265 function search(value, depth) { 9266 if (!value || typeof value !== 'object' || depth > 8 || visited.has(value)) return undefined; 9267 visited.add(value); 9268 9269 if (!Array.isArray(value)) { 9270 for (const key of Object.keys(value)) { 9271 if (wanted.includes(key.toLowerCase()) && value[key] !== undefined) return value[key]; 9272 } 9273 } 9274 9275 for (const child of Object.values(value)) { 9276 if (child && typeof child === 'object') { 9277 const found = search(child, depth + 1); 9278 if (found !== undefined) return found; 9279 } 9280 } 9281 return undefined; 9282 } 9283 9284 return search(source, 0); 9285 } 9286
9287 // Search a configuration object while refusing to descend into named groups. 9288 // This is important for Duda Design Panels because Full and Mirror can contain 9289 // identical child keys (for example universalFontSize). Without excluding 9290 // mirrorStyles, the Full widget may accidentally read the hidden Mirror default. 9291 function configValueFromExcluding(source, excludedNames, ...names) { 9292 const wanted = names.map(name => String(name).toLowerCase()); 9293 const excluded = new Set((excludedNames || []).map(name => String(name).toLowerCase())); 9294 const visited = new Set(); 9295 9296 function search(value, depth) { 9297 if (!value || typeof value !== 'object' || depth > 8 || visited.has(value)) return undefined; 9298 visited.add(value); 9299 9300 if (!Array.isArray(value)) { 9301 for (const key of Object.keys(value)) { 9302 const lower = key.toLowerCase(); 9303 if (excluded.has(lower)) continue; 9304 if (wanted.includes(lower) && value[key] !== undefined) return value[key]; 9305 } 9306 } 9307 9308 for (const [key, child] of Object.entries(value)) { 9309 if (excluded.has(String(key).toLowerCase())) continue; 9310 if (child && typeof child === 'object') { 9311 const found = search(child, depth + 1); 9312 if (found !== undefined) return found; 9313 } 9314 } 9315 return undefined; 9316 } 9317 9318 return search(source, 0); 9319 } 9320 9321 function cloneSerializable(value) { 9322 try { return JSON.parse(JSON.stringify(value)); } 9323 catch (error) { return value; } 9324 } 9325 9326 function fullConfigRoot() { 9327 return widgetMode === 'mirror' && window.NMW.fullConfig ? window.NMW.fullConfig : cfg; 9328 } 9329 9330 function fullConfigValue(...names) { 9331 const found = configValueFrom(fullConfigRoot(), ...names); 9332 return found; 9333 } 9334 9335 function mirrorUsesSeparateStyling() { 9336 return readBoolean(configValue('useSeparateMirrorStyling'), false); 9337 } 9338 9339 function designConfigRoot(mode) { 9340 if (mode === 'mirror' && mirrorUsesSeparateStyling()) { 9341 // Search only inside the dedicated Mirror group when separate styling is on. 9342 return configValueFrom(cfg, 'mirrorStyles') || {}; 9343 } 9344 9345 // Full styling, and Mirror inheritance, must never descend into mirrorStyles. 9346 const base = mode === 'mirror' ? fullConfigRoot() : cfg; 9347 const fullStyles = configValueFromExcluding(base, ['mirrorStyles'], 'fullStyles'); 9348 return fullStyles && typeof fullStyles === 'object' ? fullStyles : base; 9349 } 9350 9351 function designValue(mode, names, fallback) { 9352 const list = Array.isArray(names) ? names : [names]; 9353 9354 if (mode === 'mirror' && mirrorUsesSeparateStyling()) { 9355 const mirrorRoot = designConfigRoot(mode); 9356 const mirrorFound = configValueFrom(mirrorRoot, ...list); 9357 return mirrorFound === undefined ? fallback : mirrorFound; 9358 } 9359 9360 // Exclude mirrorStyles so identically named Mirror fields cannot shadow the 9361 // active Full Design Panel values. This applies to Full and inherited Mirror. 9362 const base = mode === 'mirror' ? fullConfigRoot() : cfg; 9363 const designRoot = designConfigRoot(mode); 9364 let found = configValueFromExcluding(designRoot, ['mirrorStyles'], ...list); 9365 if (found === undefined && designRoot !== base) { 9366 found = configValueFromExcluding(base, ['mirrorStyles'], ...list); 9367 } 9368 return found === undefined ? fallback : found; 9369 } 9370 9371 // URL prefixes are entered in the Duda panel as simple values such as 9372 // "category" or "services". Leading/trailing slashes are removed, but an 9373 // intentionally blank prefix is allowed and resolves pages from the site root. 9374 function normalizeUrlPrefix(value, fallback) { 9375 const supplied = value === undefined || value === null ? fallback : String(value).trim(); 9376 return supplied.replace(/^\/+|\/+$/g, ''); 9377 } 9378 9379 function unique(values) { 9380 return [...new Set(values.filter(Boolean))]; 9381 } 9382 9383 // Display labels preserve their original punctuation. Slug candidates are used 9384 // only for collection matching and stable keys. 9385 function createSlugCandidates(value) { 9386 const original = readString(value, '').toLowerCase().replace(/\//g, '-'); 9387 const withAnd = original 9388 .replace(/\s*&\s*/g, '-and-') 9389 .replace(/[^a-z0-9\s-]/g, '') 9390 .replace(/\s+/g, '-') 9391 .replace(/-+/g, '-') 9392 .replace(/^-+|-+$/g, ''); 9393 const withoutAnd = original 9394 .replace(/\s*&\s*/g, '-') 9395 .replace(/[^a-z0-9\s-]/g, '') 9396 .replace(/\s+/g, '-') 9397 .replace(/-+/g, '-') 9398 .replace(/^-+|-+$/g, ''); 9399 return unique([withAnd, withoutAnd]); 9400 } 9401 9402 function slugify(value) { 9403 return createSlugCandidates(value)[0] || ''; 9404 } 9405 9406 function canonicalPath(value) { 9407 const raw = readString(value, ''); 9408 if (!raw) return ''; 9409 if (raw.startsWith('#')) return `${canonicalPathWithoutHash(window.location.href)}${raw}`; 9410 try { 9411 const url = new URL(raw, window.location.origin); 9412 let path = url.pathname || '/'; 9413 path = path.replace(/^\/(?:home\/)?site\/[^/]+/i, '') || '/'; 9414 path = path.replace(/\/+$/, '') || '/'; 9415 return `${path.toLowerCase()}${url.hash || ''}`; 9416 } catch (error) { 9417 const [pathPart, hashPart = ''] = raw.split('#'); 9418 let path = pathPart.split('?')[0].replace(/^\/(?:home\/)?site\/[^/]+/i, '').replace(/\/+$/, '') || '/'; 9419 return `${path.toLowerCase()}${hashPart ? `#${hashPart}` : ''}`; 9420 } 9421 } 9422 9423 function canonicalPathWithoutHash(value) { 9424 return canonicalPath(value).split('#')[0] || '/'; 9425 } 9426 9427 function getDudaBasePath() { 9428 try { 9429 const match = (window.location.pathname || '').match(/^\/site\/([0-9a-f]{32})(?:\/.*)?$/i); 9430 return match ? `/site/${match[1]}` : ''; 9431 } catch (error) { 9432 return ''; 9433 } 9434 } 9435 9436 function getDudaPreviewQuery() { 9437 try { 9438 const input = new URLSearchParams(window.location.search || ''); 9439 const output = new URLSearchParams(); 9440 ['showOriginal', 'preview', 'insitepreview', 'dm_device', 't', 'dm_try_mode', 'dm_checkSync'].forEach(key => { 9441 if (input.has(key)) output.set(key, input.get(key)); 9442 }); 9443 const value = output.toString(); 9444 return value ? `?${value}` : ''; 9445 } catch (error) { 9446 return ''; 9447 } 9448 } 9449 9450 function buildRuntimeFallbackUrl(pathValue) { 9451 const raw = readString(pathValue, '/') || '/'; 9452 if (/^(https?:)?\/\//i.test(raw) || raw.startsWith('#')) return raw; 9453 const hashIndex = raw.indexOf('#'); 9454 const hash = hashIndex >= 0 ? raw.slice(hashIndex) : ''; 9455 const withoutHash = hashIndex >= 0 ? raw.slice(0, hashIndex) : raw; 9456 const queryIndex = withoutHash.indexOf('?'); 9457 const existingQuery = queryIndex >= 0 ? withoutHash.slice(queryIndex) : ''; 9458 const pathOnly = queryIndex >= 0 ? withoutHash.slice(0, queryIndex) : withoutHash; 9459 const normalized = pathOnly.startsWith('/') ? pathOnly : `/${pathOnly}`; 9460 const basePath = getDudaBasePath(); 9461 const prefix = basePath && !normalized.startsWith(basePath + '/') && normalized !== basePath ? basePath
9461: ''; 9462 const previewQuery = existingQuery ? '' : getDudaPreviewQuery(); 9463 return `${prefix}${normalized}${existingQuery || previewQuery}${hash}`; 9464 } 9465 9466 function getLastPathSegment(value) { 9467 const path = canonicalPathWithoutHash(value); 9468 return path.split('/').filter(Boolean).pop() || ''; 9469 } 9470 9471 function isExternalUrl(value) { 9472 const raw = readString(value, ''); 9473 if (!raw || raw.startsWith('/') || raw.startsWith('#')) return false; 9474 try { 9475 return new URL(raw, window.location.origin).origin !== window.location.origin; 9476 } catch (error) { 9477 return false; 9478 } 9479 } 9480 9481 function stableStringify(value) { 9482 return JSON.stringify(value); 9483 } 9484 9485 function warn(code, message, context) { 9486 const warning = { code, message, context: context || null }; 9487 local.latestBuildWarnings.push(warning); 9488 console.warn(`[NMW:${code}] ${message}`, context || ''); 9489 } 9490 9491 // --------------------------------------------------------------------------- 9492 // Editor, preview, and Site Comments environment handling 9493 // --------------------------------------------------------------------------- 9494 9495 function isEditorCanvas() { 9496 try { 9497 const topHref = window.top && window.top.location ? window.top.location.href : ''; 9498 return topHref.includes('/home/site/') && !topHref.includes('#preview'); 9499 } catch (error) { 9500 return false; 9501 } 9502 } 9503 9504 /* 9505 Site Comments customer state may be written into the parent editor 9506 document after this widget has already rendered. Inspect the current 9507 document and every same-origin ancestor document each time the state 9508 is requested. 9509 9510 Do not depend on console output such as "Customer Detected". Console 9511 messages are not a reliable application-state API and may be emitted 9512 before this widget initializes. 9513 */ 9514 function isSiteCommentsCustomerMode() { 9515 try { 9516 const documents = []; 9517 const seenDocuments = new Set(); 9518 9519 function addDocument(candidateDocument) { 9520 if ( 9521 !candidateDocument || 9522 !candidateDocument.documentElement || 9523 seenDocuments.has(candidateDocument) 9524 ) { 9525 return; 9526 } 9527 9528 seenDocuments.add(candidateDocument); 9529 documents.push(candidateDocument); 9530 } 9531 9532 addDocument(document); 9533 9534 /* 9535 Walk upward only while the parent documents are same-origin. 9536 Cross-origin access is safely ignored. 9537 */ 9538 try { 9539 let currentWindow = window; 9540 9541 while ( 9542 currentWindow.parent && 9543 currentWindow.parent !== currentWindow 9544 ) { 9545 currentWindow = currentWindow.parent; 9546 addDocument(currentWindow.document); 9547 } 9548 } catch (error) { 9549 // A cross-origin ancestor cannot be inspected. 9550 } 9551 9552 const html = documents 9553 .map(candidateDocument => { 9554 try { 9555 return ( 9556 candidateDocument.documentElement.innerHTML || 9557 '' 9558 ); 9559 } catch (error) { 9560 return ''; 9561 } 9562 }) 9563 .join('\n'); 9564 9565 const hasSiteCommentsMarker = 9566 /SITE[_\s-]?COMMENTS/i.test(html); 9567 9568 const isCustomer = 9569 /["']?isCustomer["']?\s*:\s*true/i 9570 .test(html); 9571 9572 const isNonStaff = 9573 /["']?isStaffMember["']?\s*:\s*false/i 9574 .test(html); 9575 9576 const isStaff = 9577 /["']?isStaffMember["']?\s*:\s*true/i 9578 .test(html); 9579 9580 return ( 9581 hasSiteCommentsMarker && 9582 isCustomer && 9583 isNonStaff && 9584 !isStaff 9585 ); 9586 } catch (error) { 9587 return false; 9588 } 9589 } 9590 9591 function navigateSiteComments(link, event) { 9592 if (!isSiteCommentsCustomerMode()) return false; 9593 const href = link.getAttribute('href') || ''; 9594 const target = (link.getAttribute('target') || '_self').toLowerCase(); 9595 if (!href || href.startsWith('#') || target === '_blank' || /^(?:mailto:|tel:|sms:|javascript:|data:|blob:)/i.test(href)) return false; 9596 try { 9597 const parsed = new URL(href, window.location.origin); 9598 let topOrigin = window.location.origin; 9599 let topPath = '';
9600 try { 9601 topOrigin = window.top.location.origin || topOrigin; 9602 topPath = window.top.location.pathname || ''; 9603 } catch (error) {} 9604 // External web addresses must retain their original domain. Only rewrite 9605 // same-site links that need to escape the Site Comments preview iframe. 9606 if (parsed.origin !== window.location.origin && parsed.origin !== topOrigin) return false; 9607 const needsHomePrefix = parsed.pathname.startsWith('/site/') && topPath.startsWith('/home/site/'); 9608 const destination = `${topOrigin}${needsHomePrefix ? '/home' : ''}${parsed.pathname}${parsed.hash || ''}`; 9609 event.preventDefault(); 9610 event.stopPropagation(); 9611 try { 9612 window.top.location.href = destination; 9613 } catch (error) { 9614 window.location.href = destination; 9615 } 9616 return true; 9617 } catch (error) { 9618 return false; 9619 } 9620 } 9621 9622 // --------------------------------------------------------------------------- 9623 // Same-page anchor navigation 9624 // --------------------------------------------------------------------------- 9625 9626 /* 9627 Duda's native navigation can contain links to anchors on the current page. 9628 When the hash changes for the first time, normal browser navigation usually 9629 scrolls correctly. Once the visitor is already on that page, however, Duda's 9630 copied/native link behavior is not guaranteed to re-scroll for a second hash 9631 selection (or for the same hash selected again). 9632 9633 NMW therefore owns same-page anchor clicks. Cross-page anchor links continue 9634 to use normal navigation so Duda can load the destination page first. 9635 */ 9636 function decodeAnchorHash(hash) { 9637 const raw = readString(hash, '').replace(/^#/, ''); 9638 if (!raw) return ''; 9639 try { 9640 return decodeURIComponent(raw); 9641 } catch (error) { 9642 return raw; 9643 } 9644 } 9645 9646 function findAnchorTarget(hash) { 9647 const decoded = decodeAnchorHash(hash); 9648 if (!decoded) return null; 9649 9650 // IDs are the modern/default anchor mechanism. Check the decoded value first 9651 // and the literal hash value second in case an authored ID contains % signs. 9652 let target = document.getElementById(decoded); 9653 if (!target) { 9654 const literal = readString(hash, '').replace(/^#/, ''); 9655 if (literal && literal !== decoded) target = document.getElementById(literal); 9656 } 9657 9658 // Legacy named anchors are still supported by browsers and may exist on 9659 // older Duda sites. 9660 if (!target) { 9661 const named = document.getElementsByName(decoded); 9662 if (named && named.length) target = named[0]; 9663 } 9664 9665 return target || null; 9666 } 9667 9668 function collectTopOverlayCandidates() { 9669 const candidates = new Set(); 9670 9671 // Common Duda/site header selectors plus generic semantic header selectors. 9672 document.querySelectorAll([ 9673 'header', 9674 '[role="banner"]', 9675 '.dmHeader', 9676 '.dmHeaderContainer', 9677 '[data-element-type="header"]', 9678 '[class*="sticky"]', 9679 '[class*="fixed"]' 9680 ].join(',')) 9681 .forEach(node => candidates.add(node)); 9682 9683 // Also inspect what is physically covering the top-center of the viewport. 9684 // This catches custom sticky/fixed wrappers whose class names are unknown. 9685 try { 9686 const viewportWidth = document.documentElement.clientWidth || window.innerWidth || 0; 9687 const x = Math.max(1, Math.min(viewportWidth - 1, Math.round(viewportWidth / 2))); 9688 [1, 8, 16, 32].forEach(y => { 9689 const stack = typeof document.elementsFromPoint === 'function' 9690 ? document.elementsFromPoint(x, y) 9691 : []; 9692 9693 stack.forEach(node => { 9694 let current = node; 9695 while (current && current !== document.documentElement) { 9696 candidates.add(current); 9697 current = current.parentElement; 9698 } 9699 }); 9700 }); 9701 } catch (error) {} 9702 9703 return candidates; 9704 } 9705 9706 function getAnchorScrollOffset(target) { 9707 const viewportWidth = document.documentElement.clientWidth || window.innerWidth || 0; 9708 const viewportHeight = document.documentElement.clientHeight || window.innerHeight || 0; 9709 let overlayBottom = 0; 9710
9711 collectTopOverlayCandidates().forEach(node => { 9712 if (!node || node === target || node.contains?.(target)) return; 9713 9714 let style; 9715 let rect; 9716 try { 9717 style = window.getComputedStyle(node); 9718 rect = node.getBoundingClientRect(); 9719 } catch (error) { 9720 return; 9721 } 9722 9723 if (!style || !rect) return; 9724 if (!['fixed', 'sticky'].includes(style.position)) return; 9725 if (style.display === 'none' || style.visibility === 'hidden') return; 9726 if (Number(style.opacity) === 0) return; 9727 if (rect.height <= 0 || rect.width <= 0) return; 9728 if (rect.bottom <= 0 || rect.top > 12) return; 9729 9730 // Ignore small floating controls at the top edge; a navigation/header 9731 // overlay should span a meaningful portion of the viewport. 9732 if (viewportWidth > 0 && rect.width < viewportWidth * 0.30) return; 9733 9734 // Ignore pathological full-screen overlays. Those are not header offsets. 9735 if (viewportHeight > 0 && rect.height > viewportHeight * 0.60) return; 9736 9737 overlayBottom = Math.max(overlayBottom, Math.max(0, rect.bottom)); 9738 }); 9739 9740 let scrollMarginTop = 0; 9741 try { 9742 const targetStyle = window.getComputedStyle(target); 9743 scrollMarginTop = parseFloat(targetStyle.scrollMarginTop) || 0; 9744 } catch (error) {} 9745 9746 // Respect an authored scroll-margin if it is larger than the detected header. 9747 // Add a small breathing room so headings do not sit flush against the header. 9748 return Math.max(0, Math.max(overlayBottom, scrollMarginTop) + 8); 9749 } 9750 9751 function scrollAnchorTargetIntoPlace(target) { 9752 if (!target || !document.documentElement.contains(target)) return false; 9753 9754 const rect = target.getBoundingClientRect(); 9755 const currentScroll = window.pageYOffset 9756 || document.documentElement.scrollTop 9757 || document.body.scrollTop 9758 || 0; 9759 const offset = getAnchorScrollOffset(target); 9760 const absoluteTargetTop = currentScroll + rect.top; 9761 const scrollingElement = document.scrollingElement || document.documentElement; 9762 const maxScroll = Math.max(0, scrollingElement.scrollHeight - window.innerHeight); 9763 const desiredTop = Math.max(0, Math.min(maxScroll, absoluteTargetTop - offset)); 9764 9765 try { 9766 window.scrollTo({ top: desiredTop, left: window.pageXOffset || 0, behavior: 'auto' }); 9767 } catch (error) { 9768 window.scrollTo(window.pageXOffset || 0, desiredTop); 9769 } 9770 9771 return true; 9772 } 9773 9774 function scheduleAnchorCorrection(target) { 9775 // First pass occurs immediately after the click. A second pass happens after 9776 // menu close animations/layout changes so Mirror/mobile menus cannot shift the 9777 // target after it was measured. A final lightweight pass handles late sticky 9778 // header changes that appear only after scrolling. 9779 const delays = [0, 260, 520]; 9780 9781 delays.forEach(delay => { 9782 const timer = setTimeout(() => { 9783 local.anchorTimers.delete(timer); 9784 if (local.cleaned || !document.documentElement.contains(target)) return; 9785 scrollAnchorTargetIntoPlace(target); 9786 }, delay); 9787 9788 local.anchorTimers.add(timer); 9789 }); 9790 } 9791 9792 function samePageAnchorInfo(link) { 9793 if (!link) return null; 9794 9795 const href = readString(link.getAttribute('href'), ''); 9796 const target = readString(link.getAttribute('target'), '_self').toLowerCase(); 9797 9798 if ( 9799 !href || 9800 target === '_blank' || 9801 link.hasAttribute('download') || 9802 /^(?:mailto:|tel:|sms:|javascript:|data:|blob:)/i.test(href) 9803 ) { 9804 return null; 9805 } 9806 9807 let destination; 9808 try { 9809 destination = new URL(href, window.location.href); 9810 } catch (error) { 9811 return null; 9812 } 9813 9814 if (destination.origin !== window.location.origin || !destination.hash) return null; 9815 9816 const destinationPath = canonicalPathWithoutHash(destination.href); 9817 const currentPath = canonicalPathWithoutHash(window.location.href); 9818 if (!destinationPath || destinationPath !== currentPath) return null; 9819 9820 const anchorTarget = findAnchorTarget(destination.hash); 9821 if (!anchorTarget) return null; 9822 9823 return { 9824 destination, 9825 hash: destination.hash, 9826 target: anchorTarget 9827 }; 9828 } 9829 9830 function handleSamePageAnchorClick(link, event) { 9831 // Preserve normal browser behavior for modified clicks such as Ctrl/Cmd-click. 9832 if ( 9833 event && 9834 (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || (typeof event.button === 'number' && event.button !== 0)) 9835 ) { 9836 return false;
9837 } 9838 9839 const info = samePageAnchorInfo(link); 9840 if (!info) return false; 9841 9842 event.preventDefault(); 9843 event.stopPropagation(); 9844 9845 closeAllMenus(root, false); 9846 9847 // pushState changes the URL without triggering the browser's unreliable 9848 // one-time hash scrolling. Selecting the same anchor again still scrolls 9849 // because the explicit scroll routine below always runs. 9850 try { 9851 if (window.location.hash !== info.hash) { 9852 history.pushState(history.state, '', info.destination.href); 9853 } else { 9854 refreshActiveStates(root); 9855 } 9856 } catch (error) { 9857 // If history manipulation is unavailable, keep the current URL and still 9858 // perform the requested scroll. 9859 refreshActiveStates(root); 9860 } 9861 9862 scheduleAnchorCorrection(info.target); 9863 return true; 9864 } 9865 9866 // --------------------------------------------------------------------------- 9867 // Configuration model 9868 // --------------------------------------------------------------------------- 9869 9870 function getModeConfig(mode) { 9871 return designConfigRoot(mode); 9872 } 9873 9874 function behaviorValue(mode, names, fallback) { 9875 const list = Array.isArray(names) ? names : [names]; 9876 const fullFound = configValueFrom(fullConfigRoot(), ...list); 9877 9878 if (mode === 'mirror' && mirrorUsesSeparateStyling()) { 9879 const mirrorFound = configValueFrom(designConfigRoot('mirror'), ...list); 9880 if (mirrorFound !== undefined) return mirrorFound; 9881 } 9882 9883 return fullFound === undefined ? fallback : fullFound; 9884 } 9885 9886 function getBehaviorConfig(mode) { 9887 const fullHover = readBoolean(behaviorValue('full', 'openMenusOnHover', false), false); 9888 const mirrorOverride = mode === 'mirror' 9889 ? configValue('mirrorOpenMenusOnHover') 9890 : undefined; 9891 9892 return { 9893 hoverEnabled: mode === 'mirror' && mirrorOverride !== undefined && mirrorOverride !== null && mirrorOverride !== '' 9894 ? readBoolean(mirrorOverride, fullHover) 9895 : fullHover, 9896 animationsEnabled: readBoolean(behaviorValue(mode, ['animationsEnabled', 'animatedEffectsEnabled'], true), true), 9897 animateTopNav: readBoolean(behaviorValue(mode, 'animateTopNav', true), true), 9898 animateSubNav: readBoolean(behaviorValue(mode, 'animateSubNav', true), true), 9899 animateSubSubNav: readBoolean(behaviorValue(mode, 'animateSubSubNav', true), true), 9900 animateMegaMenu: readBoolean(behaviorValue(mode, 'animateMegaMenu', true), true), 9901 animateMegaFamilies: readBoolean(behaviorValue(mode, 'animateMegaFamilies', true), true), 9902 animateMirror: readBoolean(behaviorValue(mode, 'animateMirror', true), true), 9903 animateTopChevrons: readBoolean(behaviorValue(mode, 'animateTopChevrons', true), true), 9904 animateMegaChevrons: readBoolean(behaviorValue(mode, 'animateMegaChevrons', true), true), 9905 animateHoverEffects: readBoolean(behaviorValue(mode, 'animateHoverEffects', true), true) 9906 }; 9907 } 9908 9909 function getMegaGroupObject(groupNumber) { 9910 const safeGroup = Math.min(4, Math.max(1, Math.round(Number(groupNumber) || 1))); 9911 const key = `mega${safeGroup}`; 9912 const rootConfig = fullConfigRoot(); 9913 const direct = rootConfig && typeof rootConfig[key] === 'object' ? rootConfig[key] : null; 9914 return direct || configValueFrom(rootConfig, key) || {}; 9915 } 9916 9917 function getMegaLabel(groupNumber) { 9918 const safeGroup = Math.min(4, Math.max(1, Math.round(Number(groupNumber) || 1))); 9919 const key = `mega${safeGroup}`; 9920 const rootConfig = fullConfigRoot(); 9921 const group = getMegaGroupObject(safeGroup); 9922 const configured = group.label 9923 ?? configValueFrom(rootConfig, `${key}Label`, `megaLabel${safeGroup}`, `mega${safeGroup}Name`) 9924 ?? (safeGroup === 1 ? configValueFrom(rootConfig, 'servicesLabel') : undefined); 9925 9926 return readString(configured, `Mega ${safeGroup}`) || `Mega ${safeGroup}`; 9927 } 9928 9929 function getMegaExpandAll(groupNumber) { 9930 const safeGroup = Math.min(4, Math.max(1, Math.round(Number(groupNumber) || 1))); 9931 const key = `mega${safeGroup}`; 9932 const rootConfig = fullConfigRoot(); 9933 const group = getMegaGroupObject(safeGroup); 9934 const candidates = [ 9935 group.expandAll, 9936 group.childrenExpanded, 9937 group.childrenOpen, 9938 group.openChildren, 9939 configValueFrom(rootConfig, 9940 `${key}ExpandAll`, `${key}Expanded`, `${key}ChildrenExpanded`, 9941 `${key}ChildrenOpen`, `${key}OpenChildren`, 9942 `expandMega${safeGroup}`, `expandedMega${safeGroup}` 9943 ) 9944 ]; 9945 9946 if (safeGroup === 1) candidates.push(configValueFrom(rootConfig, 'expandedServices')); 9947 const configured = candidates.find(value => value !== undefined && value !== null && value !== ''); 9948 return readBoolean(configured, false); 9949 } 9950 9951 function getMegaConfig(groupNumber) { 9952 const safeGroup = Math.min(4, Math.max(1, Math.round(Number(groupNumber) || 1)));
9953 const key = `mega${safeGroup}`; 9954 const rootConfig = fullConfigRoot(); 9955 const group = getMegaGroupObject(safeGroup); 9956 9957 const columnsValue = group.columns ?? group.columnCount ?? configValueFrom( 9958 rootConfig, 9959 `${key}Columns`, `${key}ColumnCount`, `megaColumns${safeGroup}`, 9960 safeGroup === 1 ? 'compactColumnCount' : '__unused__', 9961 'megaColumns' 9962 ); 9963 const layoutValue = group.layout ?? group.layoutMode ?? configValueFrom( 9964 rootConfig, 9965 `${key}Layout`, `${key}LayoutMode`, `megaLayout${safeGroup}`, 'megaLayoutMode' 9966 ); 9967 const maxWidthValue = group.maxWidth ?? group.menuMaxWidth ?? configValueFrom( 9968 rootConfig, 9969 `${key}MaxWidth`, `${key}MenuMaxWidth`, `megaMaxWidth${safeGroup}`, 'megaMenuMaxWidth' 9970 ); 9971 const alphabetizeValue = group.alphabetize ?? configValueFrom( 9972 rootConfig, 9973 `${key}Alphabetize`, `alphabetizeMega${safeGroup}`, 'alphabetizeMega' 9974 ); 9975 const layout = readString(layoutValue, 'grid').toLowerCase(); 9976 9977 return { 9978 label: getMegaLabel(safeGroup), 9979 columns: Math.round(readNumber(columnsValue, 3, 1, 6)), 9980 layout: ['grid', 'masonry'].includes(layout) ? layout : 'grid', 9981 expandAll: getMegaExpandAll(safeGroup), 9982 maxWidth: readNumber(maxWidthValue, 1600, 320, 3000), 9983 alphabetize: readBoolean(alphabetizeValue, false) 9984 }; 9985 } 9986 9987 function updateMegaIndicators(items) { 9988 const groups = new Set(); 9989 9990 function walk(list) { 9991 (list || []).forEach(item => { 9992 if (item && item.megaGroup >= 1 && item.megaGroup <= 4) groups.add(item.megaGroup); 9993 walk(item && item.children); 9994 }); 9995 } 9996 9997 walk(items); 9998 const used = [...groups].sort((a, b) => a - b); 9999 const labels = Object.fromEntries([1, 2, 3, 4].map(number => [number, getMegaLabel(number)])); 10000 10001 window.NMW.megaGroupsUsed = used; 10002 window.NMW.megaGroupCount = used.length; 10003 window.NMW.megaLabels = labels; 10004 10005 root.dataset.nmwMegaCount = String(used.length); 10006 root.dataset.nmwMegaGroups = used.map(number => `mega${number}`).join(','); 10007 root.dataset.nmwMegaLabels = used.map(number => labels[number]).join(','); 10008 10009 [1, 2, 3, 4].forEach(number => { 10010 root.dataset[`nmwMega${number}Label`] = labels[number]; 10011 }); 10012 } 10013 10014 function applyDesignSettings(mode) { 10015 const behavior = getBehaviorConfig(mode); 10016 const universalColors = readBoolean(designValue(mode, 'useUniversalColors', false), false); 10017 // A separate background toggle is required because Duda color controls often 10018 // save individual default values (for example #ffffff). Without this switch, 10019 // those saved defaults always override universalBackgroundColor. 10020 const universalBackgrounds = readBoolean( 10021 designValue(mode, ['useUniversalBackgrounds', 'useUniversalBackground'], true), 10022 true 10023 ); 10024 const universalTypography = readBoolean(designValue(mode, 'useUniversalTypography', true), true); 10025 const universalChevrons = readBoolean(designValue(mode, 'useUniversalChevronSettings', false), false); 10026 10027 root.dataset.nmwUniversalColors = universalColors ? 'true' : 'false'; 10028 root.dataset.nmwUniversalBackgrounds = universalBackgrounds ? 'true' : 'false'; 10029 root.dataset.nmwUniversalTypography = universalTypography ? 'true' : 'false'; 10030 root.dataset.nmwUniversalChevrons = universalChevrons ? 'true' : 'false'; 10031 root.dataset.nmwAnimations = behavior.animationsEnabled ? 'on' : 'off'; 10032 root.dataset.nmwAnimateTop = behavior.animateTopNav ? 'on' : 'off'; 10033 root.dataset.nmwAnimateSub = behavior.animateSubNav ? 'on' : 'off'; 10034 root.dataset.nmwAnimateSubsub = behavior.animateSubSubNav ? 'on' : 'off'; 10035 root.dataset.nmwAnimateMega = behavior.animateMegaMenu ? 'on' : 'off'; 10036 root.dataset.nmwAnimateMegaFamilies = behavior.animateMegaFamilies ? 'on' : 'off'; 10037 root.dataset.nmwAnimateMirror = behavior.animateMirror ? 'on' : 'off'; 10038 root.dataset.nmwAnimateTopChevrons = behavior.animateTopChevrons ? 'on' : 'off'; 10039 root.dataset.nmwAnimateMegaChevrons = behavior.animateMegaChevrons ? 'on' : 'off'; 10040 root.dataset.nmwAnimateHover = behavior.animateHoverEffects ? 'on' : 'off';
10041 root.dataset.nmwHoverEnabled = behavior.hoverEnabled ? 'true' : 'false'; 10042 root.dataset.nmwAlignment = mode === 'mirror' 10043 ? readString(designValue(mode, 'mirrorAlignment', 'start'), 'start') 10044 : readString(designValue(mode, 'navAlignment', 'center'), 'center'); 10045 root.dataset.nmwPreset = readString( 10046 designValue( 10047 mode, 10048 mode === 'mirror' 10049 ? ['layoutPreset', 'mirrorLayoutPreset', 'mirrorPreset'] 10050 : ['layoutPreset', 'desktopPresetValue', 'desktopPreset'], 10051 mode === 'mirror' ? 'vertical-standard' : 'classic' 10052 ), 10053 mode === 'mirror' ? 'vertical-standard' : 'classic' 10054 ).toLowerCase(); 10055 root.dataset.nmwSeparateMirrorStyling = mode === 'mirror' && mirrorUsesSeparateStyling() ? 'true' : 'false'; 10056 root.classList.toggle('nmw-capitalize', readBoolean(behaviorValue(mode, 'capitalizeNav', false), false)); 10057 root.dataset.nmwUniversalUnderline = readBoolean( 10058 designValue( 10059 mode, 10060 ['universalUnderline', 'universalAutomaticUnderline', 'underlineLinksOnHover'], 10061 false 10062 ), 10063 false 10064 ) ? 'true' : 'false'; 10065 10066 const universalChevronStyle = normalizeChevronStyle( 10067 designValue(mode, ['universalChevronStyle', 'universalChevronType', 'chevronStyle', 'chevronType'], 'filled'), 10068 'filled' 10069 ); 10070 const topChevronStyle = universalChevrons 10071 ? universalChevronStyle 10072 : normalizeChevronStyle(designValue(mode, ['topChevronStyle', 'topChevronType', 'chevronType'], universalChevronStyle), universalChevronStyle); 10073 const megaChevronStyle = universalChevrons 10074 ? universalChevronStyle 10075 : normalizeChevronStyle(designValue(mode, ['megaChevronStyle', 'megaChevronType'], universalChevronStyle), universalChevronStyle); 10076 root.dataset.nmwTopChevronStyle = topChevronStyle; 10077 root.dataset.nmwMegaChevronStyle = megaChevronStyle; 10078 10079 const universalText = cssValue(designValue(mode, 'universalTextColor', '#111111'), '#111111'); 10080 const universalBg = cssValue(designValue(mode, 'universalBackgroundColor', '#ffffff'), '#ffffff'); 10081 10082 // The universal background controls every dropdown surface, including 10083 // Mega family/cards. The top navigation background remains independent. 10084 const subBackground = universalBackgrounds 10085 ? universalBg 10086 : cssValue(designValue(mode, 'subNavBackgroundColor', '#ffffff'), '#ffffff'); 10087 const subSubBackground = universalBackgrounds 10088 ? universalBg 10089 : cssValue(designValue(mode, 'subSubNavBackgroundColor', '#ffffff'), '#ffffff'); 10090 const megaBackground = universalBackgrounds 10091 ? universalBg 10092 : cssValue(designValue(mode, 'megaMenuBackgroundColor', '#ffffff'), '#ffffff'); 10093 const megaFamilyBackground = universalBackgrounds 10094 ? universalBg 10095 : cssValue(designValue(mode, 'megaFamilyBackgroundColor', 'transparent'), 'transparent'); 10096 10097 const universalFontSource = designValue( 10098 mode, 10099 ['universalFontFamily', 'universalFont', 'universalTypographyFont'], 10100 'inherit' 10101 ); 10102 const universalSizeSource = designValue( 10103 mode, 10104 ['universalFontSize', 'universalTextSize', 'universalSize', 'universalFontFamily', 'universalFont'], 10105 '16px' 10106 ); 10107 const universalWeightSource = designValue( 10108 mode, 10109 ['universalFontWeight', 'universalWeight', 'universalFontFamily', 'universalFont'], 10110 '500' 10111 ); 10112 10113 const universalFont = fontFamilyValue(universalFontSource, 'inherit'); 10114 const universalSize = fontSizeValue(universalSizeSource, '16px'); 10115 const universalWeight = fontWeightValue(universalWeightSource, '500'); 10116 const universalChevronColor = cssValue(designValue(mode, 'universalChevronColor', universalText), universalText); 10117 const universalChevronSize = cssLength(designValue(mode, ['universalChevronSize', 'chevronSize'], '10px'), '10px'); 10118 const universalChevronWeight = cssLength(designValue(mode, ['universalChevronWeight', 'chevronWeight'], '1.5px'), '1.5px'); 10119 10120 const variables = { 10121 '--nmw-universal-text': universalText, 10122 '--nmw-top-text': universalColors ? universalText : cssValue(designValue(mode, 'topTextColor', universalText), universalText), 10123 '--nmw-sub-text': universalColors ? universalText : cssValue(designValue(mode, 'subTextColor', universalText), universalText), 10124 '--nmw-subsub-text': universalColors ? universalText : cssValue(designValue(mode, 'subSubTextColor', universalText), universalText), 10125 '--nmw-mega-parent-text': universalColors ? universalText : cssValue(designValue(mode, 'megaParentTextColor', universalText), universalText), 10126 '--nmw-mega-child-text': universalColors ? universalText : cssValue(designValue(mode, 'megaChildTextColor', universalText), universalText), 10127 '--nmw-mega-grandchild-text': universalColors ? universalText : cssValue(designValue(mode, 'megaGrandchildTextColor', universalText), universalText), 10128 '--nmw-top-bg': cssValue(designValue(mode, 'topNavBackgroun
10128dColor', 'transparent'), 'transparent'), 10129 '--nmw-universal-bg': universalBg, 10130 '--nmw-sub-bg': subBackground, 10131 '--nmw-subsub-bg': subSubBackground, 10132 '--nmw-mega-bg': megaBackground, 10133 '--nmw-mega-family-bg': megaFamilyBackground, 10134 '--nmw-hover-text': cssValue(designValue(mode, ['hoverTextColor', 'globalHoverTextColor'], 'currentColor'), 'currentColor'), 10135 '--nmw-hover-bg': cssValue(designValue(mode, ['hoverBackgroundColor', 'globalSubNavHoverBg'], 'transparent'), 'transparent'), 10136 '--nmw-active-text': cssValue(designValue(mode, 'activeTextColor', 'currentColor'), 'currentColor'), 10137 '--nmw-universal-font': universalFont, 10138 '--nmw-universal-size': universalSize, 10139 '--nmw-universal-weight': universalWeight, 10140 '--nmw-top-font': universalTypography ? universalFont : fontFamilyValue(designValue(mode, ['topFontFamily', 'topFont'], universalFont), universalFont), 10141 '--nmw-top-size': universalTypography ? universalSize : fontSizeValue(designValue(mode, ['topFontSize', 'topTextSize', 'topFontFamily', 'topFont'], universalSize), universalSize), 10142 '--nmw-top-weight': universalTypography ? universalWeight : fontWeightValue(designValue(mode, ['topFontWeight', 'topWeight', 'topFontFamily', 'topFont'], universalWeight), universalWeight), 10143 '--nmw-sub-font': universalTypography ? universalFont : fontFamilyValue(designValue(mode, ['subFontFamily', 'subFont'], universalFont), universalFont), 10144 '--nmw-sub-size': universalTypography ? universalSize : fontSizeValue(designValue(mode, ['subFontSize', 'subTextSize', 'subFontFamily', 'subFont'], universalSize), universalSize), 10145 '--nmw-sub-weight': universalTypography ? universalWeight : fontWeightValue(designValue(mode, ['subFontWeight', 'subWeight', 'subFontFamily', 'subFont'], universalWeight), universalWeight), 10146 '--nmw-subsub-font': universalTypography ? universalFont : fontFamilyValue(designValue(mode, ['subSubFontFamily', 'subSubFont'], universalFont), universalFont), 10147 '--nmw-subsub-size': universalTypography ? universalSize : fontSizeValue(designValue(mode, ['subSubFontSize', 'subSubTextSize', 'subSubFontFamily', 'subSubFont'], universalSize), universalSize), 10148 '--nmw-subsub-weight': universalTypography ? universalWeight : fontWeightValue(designValue(mode, ['subSubFontWeight', 'subSubWeight', 'subSubFontFamily', 'subSubFont'], universalWeight), universalWeight), 10149 '--nmw-mega-parent-font': universalTypography ? universalFont : fontFamilyValue(designValue(mode, ['megaParentFontFamily', 'megaParentFont'], universalFont), universalFont), 10150 '--nmw-mega-parent-size': universalTypography ? universalSize : fontSizeValue(designValue(mode, ['megaParentFontSize', 'megaParentTextSize', 'megaParentFontFamily', 'megaParentFont'], universalSize), universalSize), 10151 '--nmw-mega-parent-weight': universalTypography ? universalWeight : fontWeightValue(designValue(mode, ['megaParentFontWeight', 'megaParentWeight', 'megaParentFontFamily', 'megaParentFont'], universalWeight), universalWeight), 10152 '--nmw-mega-child-font': universalTypography ? universalFont : fontFamilyValue(designValue(mode, ['megaChildFontFamily', 'megaChildFont'], universalFont), universalFont), 10153 '--nmw-mega-child-size': universalTypography ? universalSize : fontSizeValue(designValue(mode, ['megaChildFontSize', 'megaChildTextSize', 'megaChildFontFamily', 'megaChildFont'], universalSize), universalSize), 10154 '--nmw-mega-child-weight': universalTypography ? universalWeight : fontWeightValue(designValue(mode, ['megaChildFontWeight', 'megaChildWeight', 'megaChildFontFamily', 'megaChildFont'], universalWeight), universalWeight), 10155 '--nmw-mega-grandchild-font': universalTypography ? universalFont : fontFamilyValue(designValue(mode, ['megaGrandchildFontFamily', 'megaGrandchildFont'], universalFont), universalFont), 10156 '--nmw-mega-grandchild-size': universalTypography ? universalSize : fontSizeValue(designValue(mode, ['megaGrandchildFontSize', 'megaGrandchildTextSize', 'megaGrandchildFontFamily', 'megaGrandchildFont'], universalSize), universalSize), 10157 '--nmw-mega-grandchild-weight': universalTypography ? universalWeight : fontWeightV
10157alue(designValue(mode, ['megaGrandchildFontWeight', 'megaGrandchildWeight', 'megaGrandchildFontFamily', 'megaGrandchildFont'], universalWeight), universalWeight), 10158 '--nmw-top-chevron-color': universalChevrons ? universalChevronColor : cssValue(designValue(mode, 'topChevronColor', universalChevronColor), universalChevronColor), 10159 '--nmw-mega-chevron-color': universalChevrons ? universalChevronColor : cssValue(designValue(mode, 'megaChevronColor', universalChevronColor), universalChevronColor), 10160 '--nmw-chevron-size': universalChevronSize, 10161 '--nmw-chevron-weight': universalChevronWeight, 10162 '--nmw-top-gap': `${readNumber(designValue(mode, 'topLevelGap', 32), 32, 0, 120)}px`, 10163 // Controls the spacing between a synthetic Mega 1â4 label and its chevron. 10164 // Duda Design Panel field: megaTriggerChevronGap 10165 '--nmw-mega-trigger-chevron-gap': `${readNumber(designValue(mode, 'megaTriggerChevronGap', 12), 12, 0, 60)}px`, 10166 '--nmw-mirror-gap': `${readNumber(designValue(mode, 'mirrorItemGap', 0), 0, 0, 80)}px` 10167 }; 10168 10169 Object.entries(variables).forEach(([name, value]) => root.style.setProperty(name, value)); 10170 } 10171 10172 // --------------------------------------------------------------------------- 10173 // Shared state and root status 10174 // --------------------------------------------------------------------------- 10175 10176 function updateRootStatus() { 10177 const state = window.NMW; 10178 root.dataset.nmwLoading = state.loading ? 'true' : 'false'; 10179 root.dataset.nmwReady = state.ready ? 'true' : 'false'; 10180 root.dataset.nmwError = state.error ? 'true' : 'false'; 10181 root.dataset.nmwEmpty = Array.isArray(state.data) && state.data.length === 0 ? 'true' : 'false'; 10182 updateLoadingView(); 10183 } 10184 10185 function dispatchStateChanged() { 10186 window.dispatchEvent(new CustomEvent('nmw:state-changed', { 10187 detail: { loading: window.NMW.loading, ready: window.NMW.ready, error: window.NMW.error } 10188 })); 10189 } 10190 10191 function dispatchDataChanged() { 10192 window.dispatchEvent(new CustomEvent('nmw:data-changed', { 10193 detail: { version: window.NMW.version } 10194 })); 10195 } 10196 10197 function updateLoadingView() { 10198 if (!loadingHost) return; 10199 const initialLoading = window.NMW.loading && !window.NMW.ready; 10200 loadingHost.hidden = !initialLoading; 10201 if (!initialLoading) { 10202 loadingHost.innerHTML = ''; 10203 return; 10204 } 10205 const style = readString(configValueFrom(fullConfigRoot(), 'loadingAnimationStyle') ?? 'shimmer', 'shimmer').toLowerCase(); 10206 const count = Math.round(readNumber(configValueFrom(fullConfigRoot(), 'loadingItemCount'), 4, 1, 12)); 10207 if (style === 'spinner') { 10208 loadingHost.innerHTML = '<span class="nmw-loading-spinner" aria-hidden="true"></span>'; 10209 return; 10210 } 10211 loadingHost.innerHTML = `<div class="nmw-loading-items nmw-loading-${escapeHtml(style)}">${Array.from({ length: count }, (_, index) => `<span class="nmw-loading-item" style="--nmw-load-width:${55 + ((index * 17) % 40)}px"></span>`).join('')}</div>`; 10212 } 10213 10214 function showEditorMessage(message, duplicate = false) { 10215 if (!renderHost) return; 10216 if (!isEditorCanvas()) { 10217 renderHost.innerHTML = ''; 10218 return; 10219 } 10220 renderHost.innerHTML = `<div class="nmw-editor-warning${duplicate ? ' nmw-editor-warning-duplicate' : ''}">${escapeHtml(message)}</div>`; 10221 } 10222 10223 // --------------------------------------------------------------------------- 10224 // Ownership: exactly one Full and one Mirror are expected on a page 10225 // --------------------------------------------------------------------------- 10226 10227 function claimOwnership() { 10228 const key = widgetMode === 'full' ? 'ownerId' : 'mirrorOwnerId'; 10229 const existingId = window.NMW[key]; 10230 10231 // Duda can rerun widget JavaScript against the same existing DOM root when 10232 // code or panel settings change. In that case the old instance ID remains 10233 // on this same root even though its previous script lifecycle is obsolete. 10234 // Treat that as a replacement, not as a duplicate widget. 10235 if (existingId && existingId !== instanceId) { 10236 const existingRoot = Array.from(document.querySelectorAll('[data-nm
10236w-instance]')) 10237 .find(node => node.dataset.nmwInstance === existingId); 10238 10239 if (existingRoot && existingRoot !== root && document.documentElement.contains(existingRoot)) { 10240 warn('DUPLICATE_INSTANCE', `A second ${widgetMode} widget was found. Only one is allowed.`); 10241 showEditorMessage(`Duplicate ${widgetMode} navigation widget. Only one instance is allowed.`, true); 10242 return false; 10243 } 10244 10245 // The recorded owner is stale or belongs to this same widget root. 10246 // Clear it so the newly executed script can initialize normally. 10247 window.NMW[key] = null; 10248 } 10249 10250 window.NMW[key] = instanceId; 10251 root.dataset.nmwInstance = instanceId; 10252 return true; 10253 } 10254 10255 function releaseOwnership() { 10256 const key = widgetMode === 'full' ? 'ownerId' : 'mirrorOwnerId'; 10257 if (window.NMW[key] === instanceId) window.NMW[key] = null; 10258 } 10259 10260 // --------------------------------------------------------------------------- 10261 // Duda collection fetching 10262 // --------------------------------------------------------------------------- 10263 10264 let collectionsApiPromise = null; 10265 10266 /* 10267 COLLECTION REQUEST CACHE 10268 10269 A single Full-widget lifecycle can rebuild several times because Duda changes 10270 native-nav attributes or the hidden manual-item source. Those rebuilds do not 10271 mean the underlying collections changed, so repeating the same collection API 10272 requests only adds latency. 10273 10274 Cache the request Promise per collection for this JavaScript instance. Duda 10275 reruns the widget JavaScript when its panel/configuration lifecycle is replaced, 10276 which naturally creates a fresh cache. Failed requests are removed immediately 10277 so a later rebuild can retry. The debug helper can explicitly force a refresh. 10278 */ 10279 const collectionRequestCache = new Map(); 10280 10281 // Load Duda's collection API once and reuse the same API object for every 10282 // collection request. The original working widget followed this pattern. 10283 function getCollectionsApi() { 10284 if (!collectionsApiPromise) { 10285 collectionsApiPromise = dmAPI.loadCollectionsAPI(); 10286 } 10287 return collectionsApiPromise; 10288 } 10289 10290 // Preserve both layers of a Duda collection result. Dynamic collection 10291 // identifiers such as item, slug, uuid, and page_item_url may live on the 10292 // outer entry while editable collection fields live inside entry.data. 10293 // Flattening only entry.data discards the slug metadata and causes every 10294 // Navigation Tree validation check to report a false missing-slug warning. 10295 function normalizeFetchedCollectionEntry(entry) { 10296 if (!entry || typeof entry !== 'object') return entry; 10297 const nestedData = entry.data; 10298 if (!nestedData || typeof nestedData !== 'object' || Array.isArray(nestedData)) { 10299 return entry; 10300 } 10301 10302 // Nested collection fields are copied first and outer Duda metadata wins 10303 // when the same key exists at both levels. Keep data itself as well so any 10304 // future code can still inspect the original nested object. 10305 return { ...nestedData, ...entry }; 10306 } 10307 10308 async function fetchCollection(name, options = {}) { 10309 const forceRefresh = Boolean(options && options.forceRefresh); 10310 10311 if (!forceRefresh && collectionRequestCache.has(name)) { 10312 return collectionRequestCache.get(name); 10313 } 10314 10315 const request = (async () => { 10316 const api = await getCollectionsApi(); 10317 10318 // Duda allows a maximum page size of 100. 02 CATEGORY intentionally
10319 // stays capped at 100 rows. Other collections may load a second page, 10320 // giving them a maximum of 200 rows without an unnecessary extra request. 10321 const maxRows = name === '02 CATEGORY' ? 100 : 200; 10322 10323 const firstResult = await api 10324 .data(name) 10325 .pageSize(100) 10326 .pageNumber(0) 10327 .get(); 10328 10329 const firstRows = firstResult && Array.isArray(firstResult.values) 10330 ? firstResult.values 10331 : []; 10332 10333 let rows = [...firstRows]; 10334 10335 if (maxRows > 100 && firstRows.length === 100) { 10336 const secondResult = await api 10337 .data(name) 10338 .pageSize(100) 10339 .pageNumber(1) 10340 .get(); 10341 10342 const secondRows = secondResult && Array.isArray(secondResult.values) 10343 ? secondResult.values 10344 : []; 10345 10346 rows = rows.concat(secondRows); 10347 } 10348 10349 return rows 10350 .slice(0, maxRows) 10351 .map(normalizeFetchedCollectionEntry) 10352 .filter(Boolean); 10353 })(); 10354 10355 // Cache the Promise itself. This also coalesces two overlapping requests for 10356 // the same collection into one network request. 10357 collectionRequestCache.set(name, request); 10358 10359 try { 10360 return await request; 10361 } catch (error) { 10362 // Never cache a failed request. The next rebuild should be able to retry. 10363 if (collectionRequestCache.get(name) === request) { 10364 collectionRequestCache.delete(name); 10365 } 10366 throw error; 10367 } 10368 } 10369 10370 /* 10371 PROGRESSIVE FIRST RENDER 10372 10373 On the first Full-widget build, 06 NAV MASTER is enough to construct a 10374 working provisional navigation model. Render that model as soon as NAV 10375 MASTER is available instead of making the visitor wait for 02 CATEGORY and 10376 03 CORE validation to finish. 10377 10378 The provisional model is intentionally NOT published to window.NMW.data. 10379 Mirror therefore continues to wait for the final validated model. Once all 10380 required collections finish loading, runRebuild() replaces this provisional 10381 render with the normal final navigation. 10382 */ 10383 function renderProvisionalNavigation(navMasterRows) { 10384 if ( 10385 widgetMode !== 'full' || 10386 window.NMW.ready || 10387 !isCurrentInstance() || 10388 !Array.isArray(navMasterRows) || 10389 !navMasterRows.length 10390 ) { 10391 return; 10392 } 10393 10394 try {
10395 let provisionalModel = normalizeNavMasterFallback(navMasterRows); 10396 10397 // Include any configured native navigation that is already available. 10398 // If Duda inserts the native wrapper later, the existing discovery 10399 // observer will schedule the normal rebuild and the final model will pick 10400 // it up without delaying this first visible render. 10401 const nativeItems = normalizeConfiguredNativeNavigation(); 10402 provisionalModel = [...provisionalModel, ...nativeItems]; 10403 10404 // Manual Content Panel items are available without waiting for Category 10405 // or Core and should appear in the same first render when configured. 10406 provisionalModel = layerManualNavigationItems(provisionalModel, false); 10407 10408 // Preserve Mega grouping and the configured top-line presentation so the 10409 // provisional navigation visually matches the final navigation. 10410 provisionalModel = groupMegaNavigationItems(provisionalModel); 10411 10412 if ( 10413 !provisionalModel.length || 10414 !isCurrentInstance() || 10415 window.NMW.ready 10416 ) { 10417 return; 10418 } 10419 10420 root.dataset.nmwProvisional = 'true'; 10421 renderNavigation(provisionalModel, 'full'); 10422 } catch (error) { 10423 // A provisional-render failure must never prevent the normal final build. 10424 console.warn('[NMW] Provisional navigation render failed', error); 10425 } 10426 } 10427 10428 async function fetchRequiredCollections() { 10429 const useCustomNavOnly = readBoolean( 10430 configValueFrom(cfg, 'useCustomNavOnly'), 10431 false 10432 ); 10433 10434 const output = {}; 10435 let hadError = false; 10436 10437 // CUSTOMNAV mode retains its existing loading behavior because 06 NAV 10438 // MASTER is not the active source in that mode. 10439 if (useCustomNavOnly) { 10440 try { 10441 output.CUSTOMNAV = await fetchCollection('CUSTOMNAV'); 10442 } catch (error) { 10443 output.CUSTOMNAV = []; 10444 hadError = true; 10445 warn( 10446 'COLLECTION_FETCH_FAILED', 10447 'Could not fetch collection "CUSTOMNAV".', 10448 error 10449 ); 10450 } 10451 10452 return { collections: output, hadError }; 10453 } 10454 10455 // Normal mode deliberately loads NAV MASTER first. As soon as it resolves, 10456 // render a provisional top navigation before waiting for validation data. 10457 try { 10458 output['06 NAV MASTER'] = await fetchCollection('06 NAV MASTER'); 10459 } catch (error) { 10460 output['06 NAV MASTER'] = []; 10461 hadError = true; 10462 warn( 10463 'COLLECTION_FETCH_FAILED', 10464 'Could not fetch collection "06 NAV MASTER".', 10465 error 10466 ); 10467 } 10468 10469 if (output['06 NAV MASTER'].length) { 10470 renderProvisionalNavigation(output['06 NAV MASTER']); 10471 } 10472 10473 // Preserve the existing sequential loading behavior for Category and Core. 10474 // This remains safer in the Duda editor than starting simultaneous loaders. 10475 for (const name of ['02 CATEGORY', '03 CORE']) { 10476 try { 10477 output[name] = await fetchCollection(name); 10478 } catch (error) { 10479 output[name] = []; 10480 hadError = true; 10481 warn( 10482 'COLLECTION_FETCH_FAILED', 10483 `Could not fetch collection "${name}".`, 10484 error 10485 ); 10486 } 10487 } 10488 10489 return { collections: output, hadError }; 10490 } 10491 10492 10493 // Lightweight runtime diagnostic available from the browser console. 10494 // Run nmwDebug() to confirm startup, render-host detection, shared state, 10495 // and whether the required Duda collections can be loaded. 10496 const runtimeDebug = async function nmwRuntimeDebug() { 10497 const report = { 10498 widgetMode, 10499 instanceId, 10500 rootFound: Boolean(root), 10501 renderHostFound: Boolean(renderHost), 10502 renderHostClass: renderHost ? renderHost.className : '', 10503 categoryUrlPrefix: CATEGORY_URL_PREFIX, 10504 childUrlPrefix: CHILD_URL_PREFIX, 10505 design: { 10506 useUniversalBackgrounds: readBoolean( 10507 designValue(widgetMode, ['useUniversalBackgrounds', 'useUniversalBackground'], true), 10508 true 10509 ), 10510 universalBackgroundColor: designValue(widgetMode, 'universalBackgroundColor', '#ffffff'), 10511 resolvedSubmenuBackground: root.style.getPropertyValue('--nmw-sub-bg'),
10512 resolvedThirdLevelBackground: root.style.getPropertyValue('--nmw-subsub-bg'), 10513 resolvedMegaBackground: root.style.getPropertyValue('--nmw-mega-bg'), 10514 resolvedTopBackground: root.style.getPropertyValue('--nmw-top-bg'), 10515 resolvedMegaFamilyBackground: root.style.getPropertyValue('--nmw-mega-family-bg'), 10516 useUniversalTypography: readBoolean( 10517 designValue(widgetMode, 'useUniversalTypography', true), 10518 true 10519 ), 10520 universalFontFamily: designValue(widgetMode, ['universalFontFamily', 'universalFont'], 'inherit'), 10521 universalFontSize: designValue(widgetMode, ['universalFontSize', 'universalTextSize', 'universalFontFamily', 'universalFont'], '16px'), 10522 universalFontWeight: designValue(widgetMode, ['universalFontWeight', 'universalFontFamily', 'universalFont'], '500'), 10523 resolvedUniversalFontFamily: root.style.getPropertyValue('--nmw-universal-font'), 10524 resolvedUniversalFontSize: root.style.getPropertyValue('--nmw-universal-size'), 10525 resolvedUniversalFontWeight: root.style.getPropertyValue('--nmw-universal-weight') 10526 }, 10527 sharedState: window.NMW 10528 }; 10529 10530 console.group(`NMW Runtime Debug (${widgetMode})`); 10531 console.log('Startup report:', report); 10532 10533 // Full is the collection owner. Mirror intentionally does not fetch. 10534 if (widgetMode === 'full') { 10535 const collectionNames = readBoolean(configValueFrom(cfg, 'useCustomNavOnly'), false) 10536 ? ['CUSTOMNAV'] 10537 : ['06 NAV MASTER', '02 CATEGORY', '03 CORE']; 10538 10539 for (const name of collectionNames) { 10540 try { 10541 const rows = await fetchCollection(name, { forceRefresh: true }); 10542 const sampleSlugs = name === '02 CATEGORY' || name === '03 CORE' 10543 ? rows.slice(0, 10).flatMap(extractCollectionSlugs) 10544 : []; 10545 console.log(`${name}: ${rows.length} row(s) loaded`, { 10546 sampleRows: rows.slice(0, 3), 10547 sampleSlugs 10548 }); 10549 } catch (error) { 10550 console.error(`${name}: FAILED`, error); 10551 } 10552 } 10553 } else { 10554 console.log('Mirror uses Full shared data and does not fetch collections.'); 10555 } 10556 10557 console.groupEnd(); 10558 return report; 10559 }; 10560 10561 window[`nmwDebug${widgetMode === 'full' ? 'Full' : 'Mirror'}`] = runtimeDebug; 10562 // Do not let a later Mirror initialization replace the primary Full debug helper. 10563 if (widgetMode === 'full' || typeof window.nmwDebug !== 'function') { 10564 window.nmwDebug = runtimeDebug; 10565 } 10566 10567 // --------------------------------------------------------------------------- 10568 // Dynamic collection indexes 10569 // --------------------------------------------------------------------------- 10570 10571 function extractPageItemUrl(row) { 10572 const raw = field(row, 'page_item_url', 'Page Item URL', 'PAGE ITEM URL', 'item_url', 'URL'); 10573 if (raw && typeof raw === 'object') return readString(raw.href || raw.url || '', ''); 10574 return readString(raw, ''); 10575 } 10576 10577 function buildDynamicIndex(rows) { 10578 const items = (rows || []).map((row, order) => { 10579 const url = extractPageItemUrl(row); 10580 return { 10581 row, 10582 order, 10583 url, 10584 canonicalPath: canonicalPathWithoutHash(url), 10585 slug: getLastPathSegment(url) 10586 }; 10587 }).filter(item => item.url); 10588 10589 /* 10590 Keep the original ordered items for compatibility, but also build an O(1) 10591 path lookup. If duplicate canonical paths exist, preserve the first row just 10592 as Array.find() did in the original implementation. 10593 */ 10594 const byCanonicalPath = new Map(); 10595 items.forEach(item => { 10596 if (item.canonicalPath && !byCanonicalPath.has(item.canonicalPath)) { 10597 byCanonicalPath.set(item.canonicalPath, item); 10598 } 10599 }); 10600 10601 return { items, byCanonicalPath }; 10602 } 10603 10604 10605 // Build a simple combined slug inventory for Navigation Tree warnings. 10606 // This intentionally ignores which collection the slug is stored in. A slug 10607 // is considered valid when it exists in either 02 CATEGORY or 03 CORE. 10608 function normalizeCollectionSlug(value) { 10609 let raw = value; 10610 if (raw && typeof raw === 'object') { 10611 raw = raw.item 10612 ?? raw.slug 10613 ?? raw.value 10614 ?? raw.href 10615 ?? raw.url 10616 ?? raw.name 10617 ?? ''; 10618 } 10619 10620 const textValue = readString(raw, ''); 10621 if (!textValue) return ''; 10622 10623 // URLs and paths use their final segment. Bare collection item values are 10624 // already slugs and are normalized directly. 10625 if (/^(https?:)?\/\//i.test(textValue) || textValue.includes('/') || textValue.includes('?') || textValue.includes('#')) { 10626 const segment = getLastPathSegment(textValue); 10627 if (segment) return segment.toLowerCase(); 10628 } 10629 10630 return textValue 10631 .toLowerCase() 10632 .split(/[?#]/)[0] 10633 .replace(/^\/+|\/+$/g, '') 10634 .split('/') 10635 .filter(Boolean) 10636 .pop() || ''; 10637 } 10638 10639 function extractCollectionSlugs(row) { 10640 if (!row || typeof row !== 'object') return []; 10641 10642 // Inspect both the flattened row and the original nested data object. This 10643 // supports either Duda response shape without depending on where the item 10644 // slug or dynamic page URL happens to be stored. 10645 const sources = [row]; 10646 if (row.data && typeof row.data === 'object' && !Array.isArray(row.data)) { 10647 sources.push(row.data); 10648 } 10649 10650 const rawValues = [];
10651 sources.forEach(source => { 10652 rawValues.push( 10653 field(source, 'item', 'Item', 'ITEM'), 10654 field(source, 'slug', 'Slug', 'SLUG'), 10655 field(source, 'name', 'Name', 'NAME'), 10656 extractPageItemUrl(source) 10657 ); 10658 }); 10659 10660 return unique(rawValues.map(normalizeCollectionSlug)); 10661 } 10662 10663 function buildCombinedCollectionSlugSet(categoryRows, coreRows) { 10664 const slugs = new Set(); 10665 [...(categoryRows || []), ...(coreRows || [])].forEach(row => { 10666 extractCollectionSlugs(row).forEach(slug => { 10667 if (slug) slugs.add(slug); 10668 }); 10669 }); 10670 return slugs; 10671 } 10672 10673 function buildSlugValidationWarnings(tree, categoryRows, coreRows) { 10674 const availableSlugs = buildCombinedCollectionSlugSet(categoryRows, coreRows); 10675 const warnings = []; 10676 10677 function walk(nodes) { 10678 (nodes || []).forEach(node => { 10679 if (!node || node.invalid || node.depth > MAX_DEPTH) return; 10680 10681 const isHome = node.depth === 0 && node.label.toLowerCase() === 'home'; 10682 if (!isHome) { 10683 const candidates = createSlugCandidates(node.label); 10684 const found = candidates.some(slug => availableSlugs.has(slug)); 10685 10686 if (!found) { 10687 const validChildren = (node.children || []).filter(child => child && !child.invalid && child.depth <= MAX_DEPTH); 10688 const suggestedCollection = usesCategorySource(node.depth, validChildren) 10689 ? '02 CATEGORY' 10690 : '03 CORE'; 10691 10692 warnings.push({ 10693 label: node.label, 10694 slugs: candidates, 10695 suggestedCollection 10696 }); 10697 } 10698 } 10699 10700 walk(node.children || []); 10701 }); 10702 } 10703 10704 walk(tree || []); 10705 return warnings; 10706 } 10707 10708 // Build complete expected paths from Page Name and the configured prefix. 10709 // The display label is never changed. Only lookup candidates are normalized. 10710 // "Heating/Cooling" with prefix "services" becomes /services/heating-cooling. 10711 // "Boats & Cars" checks both /.../boats-and-cars and /.../boats-cars. 10712 function buildExpectedDynamicPaths(pageName, prefix) { 10713 return createSlugCandidates(pageName).map(slug => { 10714 const path = prefix ? `/${prefix}/${slug}` : `/${slug}`; 10715 return canonicalPathWithoutHash(path); 10716 }); 10717 } 10718 10719 // Match only the complete expected dynamic-page path. The configured prefix 10720 // is authoritative. A row with the same final slug under a different prefix 10721 // must not be selected, because that would make categoryUrlPrefix and 10722 // childUrlPrefix appear to be ignored. The Map lookup keeps the original 10723 // collection-order behavior when both supported ampersand variants exist. 10724 function findDynamicMatch(index, pageName, prefix) { 10725 const expectedPaths = buildExpectedDynamicPaths(pageName, prefix); 10726 if (!index || !expectedPaths.length) return null; 10727 10728 if (index.byCanonicalPath instanceof Map) { 10729 let earliest = null; 10730 10731 expectedPaths.forEach(path => { 10732 const match = index.byCanonicalPath.get(path); 10733 if (match && (!earliest || match.order < earliest.order)) { 10734 earliest = match; 10735 } 10736 }); 10737 10738 return earliest; 10739 } 10740 10741 // Defensive compatibility fallback for any older array-shaped index. 10742 const items = Array.isArray(index) 10743 ? index 10744 : (Array.isArray(index.items) ? index.items : []); 10745 10746 return items.find(item => expectedPaths.includes(item.canonicalPath)) || null; 10747 } 10748 10749 // Build the internal dynamic URL dictated by the configured Category/Core 10750 // prefix. This is the fallback when the corresponding collection does not yet 10751 // contain an exact page_item_url. It keeps the item visible without allowing a 10752 // legacy Page Link or a same-slug row under another prefix to override the panel. 10753 function buildConfiguredDynamicUrl(pageName, prefix) { 10754 const slug = slugify(pageName); 10755 const path = `/${prefix ? `${prefix}/` : ''}${slug}`; 10756 return buildRuntimeFallbackUrl(path); 10757 } 10758 10759 // Category pages are structural navigation parents. Any navigation item with 10760 // no valid children is treated as a Core page, even when it is top-level or 10761 // assigned to a Mega group. Mega controls presentation only. 10762 function usesCategorySource(depth, children) { 10763 const childCount = Array.isArray(children) ? children.length : 0; 10764 return Number(depth) < MAX_DEPTH && childCount > 0; 10765 } 10766 10767 // --------------------------------------------------------------------------- 10768 // 06 NAV MASTER normalization 10769 // --------------------------------------------------------------------------- 10770 10771 function parseMegaGroup(value) { 10772 // Duda collection fields may arrive as strings, booleans, or small objects 10773 // depending on whether the Mega column is configured as text, select, or switch. 10774 let raw = value; 10775 if (raw && typeof raw === 'object') { 10776 raw = raw.value 10777 ?? raw.label 10778 ?? raw.name 10779 ?? raw.text 10780 ?? raw.selected 10781 ?? raw.checked 10782 ?? raw.id 10783 ?? ''; 10784 } 10785 10786 if (raw === true) return 1; 10787 if (raw === false || raw == null) return 0; 10788 10789 const normalized = readString(raw, 'No') 10790 .toLowerCase() 10791 .replace(/[\s_-]+/g, ''); 10792 10793 if (['yes', 'true', 'on', 'mega', 'mega1', '1'].includes(normalized)) return 1; 10794 if (['mega2', '2'].includes(normalized)) return 2; 10795 if (['mega3', '3'].includes(normalized)) return 3; 10796 if (['mega4', '4'].includes(normalized)) return 4; 10797 return 0; 10798 } 10799 10800 function extractNavMasterPageLink(row) { 10801 const raw = field( 10802 row, 10803 'Page Link', 10804 'page_link', 10805 'PAGE LINK', 10806 'Page URL', 10807 'page_url', 10808 'Link' 10809 ); 10810 10811 if (raw && typeof raw === 'object') { 10812 return readString(raw.href ?? raw.url ?? raw.value ?? '', ''); 10813 } 10814 10815 return readString(raw, ''); 10816 } 10817 10818 function buildCollectionTree(navRows) { 10819 const nodes = []; 10820 const byName = new Map(); 10821
10822 (navRows || []).forEach((row, order) => { 10823 const label = readString(field(row, 'Page Name'), ''); 10824 if (!label) return; 10825 const nameKey = label.toLowerCase(); 10826 if (byName.has(nameKey)) { 10827 warn('DUPLICATE_PAGE_NAME', `Duplicate Page Name "${label}" was ignored.`, row); 10828 return; 10829 } 10830 const node = { 10831 raw: row, 10832 label, 10833 parentName: readString(field(row, 'Parent 1'), ''), 10834 topMegaValue: field(row, 'Mega'), 10835 pageLink: extractNavMasterPageLink(row), 10836 order, 10837 children: [], 10838 parent: null 10839 }; 10840 nodes.push(node); 10841 byName.set(nameKey, node); 10842 }); 10843 10844 const roots = []; 10845 nodes.forEach(node => { 10846 if (!node.parentName) { 10847 roots.push(node); 10848 return; 10849 } 10850 const parent = byName.get(node.parentName.toLowerCase()); 10851 if (!parent || parent === node) { 10852 warn('MISSING_PARENT', `"${node.label}" was skipped because Parent 1 "${node.parentName}" was not found.`, node.raw); 10853 node.invalid = true; 10854 return; 10855 } 10856 node.parent = parent; 10857 parent.children.push(node); 10858 }); 10859 10860 function sortAndValidate(list, depth) { 10861 list.sort((a, b) => a.order - b.order); 10862 list.forEach(node => { 10863 node.depth = depth; 10864 if (depth > MAX_DEPTH) { 10865 node.invalid = true; 10866 warn('MAX_DEPTH_EXCEEDED', `"${node.label}" was ignored because navigation supports only three levels.`, node.raw); 10867 } 10868 sortAndValidate(node.children, depth + 1); 10869 }); 10870 } 10871 sortAndValidate(roots, 0); 10872 return roots.filter(node => !node.invalid); 10873 } 10874 10875 function normalizeCollectionNavigation(navRows, categoryRows, coreRows) { 10876 const tree = buildCollectionTree(navRows); 10877 const categoryIndex = buildDynamicIndex(categoryRows); 10878 const coreIndex = buildDynamicIndex(coreRows); 10879 10880 // Navigation Tree warnings use one combined slug inventory. The actual
10881 // collection only matters as a suggestion when a slug is absent from both. 10882 local.slugValidationWarnings = buildSlugValidationWarnings(tree, categoryRows, coreRows); 10883 10884 function normalizeNode(node, ancestors, inheritedMegaGroup) { 10885 if (node.invalid || node.depth > MAX_DEPTH) return null; 10886 const isRoot = node.depth === 0; 10887 const megaGroup = isRoot ? parseMegaGroup(node.topMegaValue) : inheritedMegaGroup; 10888 if (!isRoot && parseMegaGroup(node.topMegaValue) && parseMegaGroup(node.topMegaValue) !== inheritedMegaGroup) { 10889 warn('DESCENDANT_MEGA_IGNORED', `Mega value on descendant "${node.label}" was ignored; descendants inherit the top-level mega group.`, node.raw); 10890 } 10891 10892 const validChildren = node.children 10893 .map(child => normalizeNode(child, [...ancestors, node], megaGroup)) 10894 .filter(Boolean); 10895 const hasGrandchildren = node.depth === 1 && validChildren.length > 0; 10896 10897 const isHome = node.depth === 0 && node.label.toLowerCase() === 'home'; 10898 const expectsCategory = usesCategorySource(node.depth, validChildren); 10899 const expectedIndex = expectsCategory ? categoryIndex : coreIndex; 10900 const expectedPrefix = expectsCategory ? CATEGORY_URL_PREFIX : CHILD_URL_PREFIX; 10901 const match = isHome ? null : findDynamicMatch(expectedIndex || [], node.label, expectedPrefix); 10902 const navMasterUrl = node.pageLink ? buildRuntimeFallbackUrl(node.pageLink) : ''; 10903 let type = 'page'; 10904 let url = ''; 10905 10906 if (isHome) { 10907 const nativeHome = findTreeItem(parseNativeNavigation(), item => item.type === 'page' && item.canonicalPath === '/'); 10908 url = nativeHome && nativeHome.url 10909 ? nativeHome.url 10910 : (navMasterUrl || buildRuntimeFallbackUrl('/')); 10911 } else { 10912 // Prefix controls are authoritative for collection navigation. Prefer the 10913 // exact page_item_url only when it matches the configured full path. If 10914 // that row is missing, construct the URL from the configured prefix. 10915 // Page Link remains structure/reference data and no longer overrides the 10916 // Category/Core prefix fields for internal dynamic pages. 10917 url = match ? match.url : buildConfiguredDynamicUrl(node.label, expectedPrefix); 10918 } 10919 10920 if (!isHome && !match) { 10921 warn('DYNAMIC_PREFIX_CONSTRUCTED_FALLBACK', `"${node.label}" used the configured prefix because no exact dynamic collection path was found.`, { 10922 depth: node.depth, 10923 expectedCollection: expectsCategory ? '02 CATEGORY' : '03 CORE', 10924 configuredPrefix: expectedPrefix, 10925 ignoredPageLink: node.pageLink || '', 10926 expectedPaths: buildExpectedDynamicPaths(node.label, expectedPrefix), 10927 constructedUrl: url 10928 }); 10929 } 10930 10931 // Standard top-level structural parents without a matching Category page 10932 // may still act as folders when they have valid children and no explicit 10933 // Mega assignment. Mega families remain clickable as Category parents. 10934 if (!isHome && node.depth === 0 && megaGroup === 0 && !match && validChildren.length && !node.pageLink) { 10935 type = 'folder'; 10936 url = ''; 10937 } 10938 10939 const hierarchySlugs = [...ancestors.map(item => slugify(item.label)), slugify(node.label)]; 10940 const key = `collection:${hierarchySlugs.join('/')}`; 10941 const presentation = megaGroup ? 'mega' : 'standard'; 10942 return { 10943 key, 10944 parentKey: ancestors.length ? `collection:${ancestors.map(item => slugify(item.label)).join('/')}` : null, 10945 source: 'collection', 10946 type, 10947 presentation, 10948 megaGroup, 10949 depth: node.depth, 10950 order: node.order, 10951 label: node.label, 10952 slug: slugify(node.label), 10953 canonicalPath: url ? canonicalPath(url) : '', 10954 url, 10955 target: '_self', 10956 isExternal: isExternalUrl(url), 10957 hasChildren: validChildren.length > 0, 10958 children: validChildren 10959 }; 10960 } 10961 10962 let normalized = tree.map(rootNode =>
10962 normalizeNode(rootNode, [], 0)).filter(Boolean); 10963 10964 // Mega family alphabetization is applied only after top-level families are 10965 // grouped under their synthetic Mega trigger. Child and grandchild order is 10966 // always preserved from 06 NAV MASTER. 10967 return normalized; 10968 } 10969 10970 // --------------------------------------------------------------------------- 10971 // Native Duda navigation from .navmasterdefault 10972 // --------------------------------------------------------------------------- 10973 10974 function getNativeWrapper() { 10975 return document.querySelector('.navmasterdefault'); 10976 } 10977 10978 function nativeAnchorLabel(anchor) { 10979 if (!anchor) return ''; 10980 const textNode = anchor.querySelector('[data-link-text]'); 10981 return readString(textNode?.getAttribute('data-link-text') || textNode?.textContent || anchor.textContent, ''); 10982 } 10983 10984 function nativeAnchorHref(anchor) { 10985 if (!anchor) return ''; 10986 const values = [ 10987 anchor.getAttribute('href'), 10988 anchor.getAttribute('runtime_url'), 10989 anchor.getAttribute('data-href'), 10990 anchor.getAttribute('raw_url') 10991 ].map(value => readString(value, '')); 10992 10993 // Preserve Duda's current rendered href whenever it is usable. If href is 10994 // only a folder placeholder, fall through to runtime_url/raw_url. 10995 return values.find(value => value && value !== '#' && !value.toLowerCase().startsWith('javascript:')) 10996 || values.find(Boolean) 10997 || ''; 10998 } 10999 11000 function nativeAnchorRawUrl(anchor) { 11001 if (!anchor) return ''; 11002 return readString( 11003 anchor.getAttribute('raw_url') || 11004 anchor.getAttribute('runtime_url') || 11005 anchor.getAttribute('data-href') || 11006 anchor.getAttribute('href'), 11007 '' 11008 ); 11009 } 11010 11011 function readNativeNode(li, depth, parentKey) { 11012 if (!li || depth > MAX_DEPTH) return null; 11013 const anchor = li.querySelector(':scope > a, :scope > span > a, :scope > div > a'); 11014 const href = nativeAnchorHref(anchor); 11015 const rawUrl = nativeAnchorRawUrl(anchor); 11016 // Preserve Duda-generated link metadata/classes from the native navigation. 11017 // Anchor links can rely on these attributes for Duda's own scrolling and 11018 // fixed-header compensation behavior. linkHtml() already knows how to carry 11019 // linkAttributes/linkClassName into the rebuilt NMW anchor. 11020 const nativeLinkData = anchor ? manualLinkFromAnchor(anchor) : { attributes: {}, className: '' }; 11021 const label = nativeAnchorLabel(anchor) || readString(li.getAttribute('data-link-text'), ''); 11022 const isFolder = !href || href === '#' || !anchor; 11023 const canonical = isFolder ? '' : canonicalPath(rawUrl || href); 11024 const key = isFolder 11025 ? `native-folder:${parentKey || 'root'}/${slugify(label)}` 11026 : `native:${canonical || canonicalPath(href)}`; 11027 const childList = li.querySelector(':scope > ul[data-auto="sub-pages"], :scope > ul.unav-sub, :scope > ul'); 11028 const childLis = childList ? Array.from(childList.querySelectorAll(':scope > li')) : []; 11029 const children = childLis.map(child => readNativeNode(child, depth + 1, key)).filter(Boolean); 11030 return { 11031 key, 11032 parentKey, 11033 source: 'native', 11034 type: isFolder ? 'folder' : 'page', 11035 presentation: 'standard', 11036 megaGroup: 0, 11037 depth, 11038 order: 0, 11039 label, 11040 slug: slugify(label), 11041 canonicalPath: canonical, 11042 url: isFolder ? '' : href, 11043 target: anchor ? readString(anchor.getAttribute('target'), '_self') : '_self', 11044 isExternal: isExternalUrl(href), 11045 linkAttributes: nativeLinkData.attributes || {}, 11046 linkClassName: readString(nativeLinkData.className, ''), 11047 hasChildren: children.length > 0, 11048 children 11049 }; 11050 } 11051 11052 function parseNativeNavigation() { 11053 const wrapper = getNativeWrapper(); 11054 if (!wrapper) return []; 11055 const nav = wrapper.querySelector('nav[data-element-type="onelinksmenu"], nav.unifiednav, nav'); 11056 if (!nav) return []; 11057 const topList = nav.querySelector(':scope > ul[data-auto="navigation-pages"], :scope > ul'); 11058 if (!topList) return []; 11059 return Array.from(topList.querySelectorAll(':scope > li')).map(li =>
11059 readNativeNode(li, 0, null)).filter(Boolean); 11060 } 11061 11062 function configuredNativeParents() { 11063 const configured = configValueFrom(cfg, 'nativeParents'); 11064 const list = Array.isArray(configured) ? configured : []; 11065 return list.map((item, order) => ({ 11066 url: readString(item.url?.href || item.url, ''), 11067 canonicalPath: canonicalPath(item.url?.href || item.url), 11068 label: readString(item.label, ''), 11069 showParent: readBoolean(item.showParent, false), 11070 pullChildren: readBoolean(item.pullChildren, false), 11071 order 11072 })); 11073 } 11074 11075 function cloneNativeBranch(node, config, depth = 0, parentKey = null) { 11076 if (!node || depth > MAX_DEPTH) return null; 11077 const children = config.pullChildren 11078 ? node.children.map(child => cloneNativeBranch(child, { ...config, label: '', showParent: true, pullChildren: true }, depth + 1, node.key)).filter(Boolean) 11079 : []; 11080 11081 // A folder without pulled valid children has no useful action and is omitted. 11082 if (node.type === 'folder' && !children.length) return null; 11083 11084 return { 11085 ...node, 11086 parentKey, 11087 depth, 11088 order: config.order, 11089 label: depth === 0 && config.label ? config.label : node.label, 11090 hasChildren: children.length > 0, 11091 children 11092 }; 11093 } 11094 11095 function normalizeConfiguredNativeNavigation() { 11096 const parsed = parseNativeNavigation(); 11097 const configs = configuredNativeParents(); 11098 const result = []; 11099 const seen = new Set(); 11100 11101 configs.forEach(config => { 11102 if (!config.showParent) return; 11103 if (!config.canonicalPath || seen.has(config.canonicalPath)) { 11104 if (seen.has(config.canonicalPath)) warn('DUPLICATE_NATIVE_CONFIG', `Native URL "${config.url}" was configured more than once; the first entry was kept.`); 11105 return; 11106 } 11107 seen.add(config.canonicalPath); 11108 const match = parsed.find(item => item.canonicalPath === config.canonicalPath); 11109 if (!match) { 11110 warn('NATIVE_URL_NOT_FOUND', `Configured native URL "${config.url}" was not found in .navmasterdefault.`); 11111 return; 11112 } 11113 const normalized = cloneNativeBranch(match, config, 0, null); 11114 if (normalized) result.push(normalized); 11115 }); 11116 11117 return result; 11118 } 11119 11120 // --------------------------------------------------------------------------- 11121 // Manual navigation items from the Duda Content Panel 11122 // --------------------------------------------------------------------------- 11123 11124 /* 11125 Manual items are layered onto either navigation source: 11126 - Normal mode: 06 NAV MASTER + configured native pages + manual items. 11127 - CUSTOMNAV-only mode: CUSTOMNAV collection + manual items. 11128 11129 Duda link inputs must be rendered with the custom_link Handlebars helper so 11130 page, dynamic-page, popup, anchor, email, telephone, and download behavior 11131 retains the attributes Duda generates. The matching HTML writes those links 11132 into a hidden manual-item source. JavaScript reads the generated anchors and 11133 carries their attributes into the final navigation markup. 11134 */ 11135 11136 function normalizeManualLevel(value) { 11137 const normalized = readString(value, 'top').toLowerCase().replace(/[\s_-]+/g, ''); 11138 if (['2', 'grandchild', 'subsub', 'third', 'thirdlevel'].includes(normalized)) return 2; 11139 if (['1', 'child', 'sub', 'second', 'secondlevel'].includes(normalized)) return 1; 11140 return 0; 11141 } 11142 11143 function normalizeManualPlacement(value) { 11144 const normalized = readString(value, 'after-native').toLowerCase().replace(/[\s_]+/g, '-'); 11145 if (['afterhome', 'after-home', 'home'].includes(normalized)) return 'after-home'; 11146 if (['aftercollection', 'after-collection', 'collection'].includes(normalized)) return 'after-collection'; 11147 return 'after-native'; 11148 } 11149 11150 function resolveManualRuntimeHref(value) { 11151 const raw = readString(value, ''); 11152 if (!raw) return ''; 11153 11154 // Duda-generated special links already contain the required scheme/action. 11155 if (/^(?:https?:|mailto:|tel:|sms:|javascript:|data:|blob:)/i.test(raw) || raw.startsWith('//') || raw.startsWith('#')) { 11156 return raw; 11157 } 11158 11159 return buildRuntimeFallbackUrl(raw); 11160 } 11161 11162 function manualLinkValue(value) { 11163 if (value == null) return { href: '', target: '_self', attributes: {}, className: '' }; 11164 if (typeof value === 'string') { 11165 return { href: resolveManualRuntimeHref(value), target: '_self', attributes: {}, className: '' }; 11166 } 11167 11168 if (typeof value !== 'object') { 11169 return { href: '', target: '_self', attributes: {}, className: '' }; 11170 } 11171 11172 const href = readString( 11173 value.href 11174 ?? value.url 11175 ?? value.runtime_url 11176 ?? value.runtimeUrl 11177 ?? value.raw_url 11178 ?? value.rawUrl 11179 ?? value.value 11180 ?? value.path 11181 ?? '', 11182 '' 11183 ); 11184 const opensNewWindow = readBoolean(value.newWindow ?? value.openInNewWindow ?? value.new_window, false); 11185 const target = readString(value.target, opensNewWindow ? '_blank' : '_self'); 11186 const attributes = {}; 11187 11188 // Preserve common Duda link metadata when the configuration object exposes it.
11189 Object.entries(value).forEach(([name, attributeValue]) => { 11190 const lower = String(name).toLowerCase(); 11191 if (!attributeValue && attributeValue !== 0) return; 11192 if (['href', 'url', 'runtime_url', 'runtimeurl', 'raw_url', 'rawurl', 'value', 'path', 'target', 'class', 'classname', 'style', 'id'].includes(lower)) return; 11193 if (lower.startsWith('data-') || ['rel', 'download', 'title', 'onclick'].includes(lower)) { 11194 attributes[name] = String(attributeValue); 11195 } 11196 }); 11197 11198 return { 11199 href: resolveManualRuntimeHref(href), 11200 target, 11201 attributes, 11202 className: readString(value.className ?? value.class, '') 11203 }; 11204 } 11205 11206 function manualLinkFromAnchor(anchor) { 11207 if (!anchor) return { href: '', target: '_self', attributes: {}, className: '' }; 11208 const attributes = {}; 11209 11210 Array.from(anchor.attributes || []).forEach(attribute => { 11211 const name = attribute.name; 11212 const lower = name.toLowerCase(); 11213 if (['href', 'target', 'class', 'style', 'id', 'role', 'aria-current'].includes(lower)) return; 11214 // Retain Duda's link behavior metadata, including popup/download handlers. 11215 if (lower.startsWith('data-') || lower.startsWith('aria-') || lower.startsWith('on') || ['rel', 'download', 'title', 'name', 'type'].includes(lower)) { 11216 attributes[name] = attribute.value; 11217 } 11218 }); 11219 11220 return { 11221 href: readString(anchor.getAttribute('href'), ''), 11222 target: readString(anchor.getAttribute('target'), '_self'), 11223 attributes, 11224 className: readString(anchor.getAttribute('class'), '') 11225 }; 11226 } 11227 11228 function manualRowFromDom(node, index) { 11229 const anchor = node.querySelector('a'); 11230 return { 11231 manualItemKey: node.getAttribute('data-manual-item-key') || '', 11232 manualLabel: node.getAttribute('data-manual-label') || '', 11233 manualType: node.getAttribute('data-manual-type') || 'page', 11234 manualLevel: node.getAttribute('data-manual-level') || 'top', 11235 manualParent: node.getAttribute('data-manual-parent') || '', 11236 manualPlacement: node.getAttribute('data-manual-placement') || 'after-native', 11237 manualOrder: node.getAttribute('data-manual-order') || index, 11238 manualMegaGroup: node.getAttribute('data-manual-mega-group') || '0', 11239 manualShowItem: node.getAttribute('data-manual-show-item'), 11240 // Return null until Duda's custom_link helper has produced a real anchor. 11241 // This allows normalizeManualPanelItems() to fall back to data.config. 11242 __manualLink: anchor ? manualLinkFromAnchor(anchor) : null 11243 }; 11244 } 11245 11246 function configuredManualRows() { 11247 const configured = configValueFrom(cfg, 'manualNavigationItems'); 11248 const configRows = Array.isArray(configured) ? configured : [];
11249 const domNodes = Array.from(root.querySelectorAll('[data-nmw-manual-item]')); 11250 const domRows = domNodes.map(manualRowFromDom); 11251 11252 if (!domRows.length) return configRows; 11253 if (!configRows.length) return domRows; 11254 11255 // Duda can update the repeat-group configuration and the hidden Handlebars 11256 // output a few milliseconds apart. Merge both representations so a new row 11257 // can appear from data.config immediately, then receive the final custom_link 11258 // attributes as soon as Duda writes them into the hidden source. 11259 const configByKey = new Map(); 11260 configRows.forEach((row, index) => { 11261 const key = readString(row && (row.manualItemKey ?? row.itemKey ?? row.key), '').toLowerCase(); 11262 if (key && !configByKey.has(key)) configByKey.set(key, { row, index }); 11263 }); 11264 11265 const usedConfigIndexes = new Set(); 11266 const merged = domRows.map((domRow, index) => { 11267 const key = readString(domRow.manualItemKey, '').toLowerCase(); 11268 const keyed = key ? configByKey.get(key) : null; 11269 const configIndex = keyed ? keyed.index : index; 11270 const configRow = keyed ? keyed.row : (configRows[configIndex] || {}); 11271 usedConfigIndexes.add(configIndex); 11272 11273 // DOM attributes are the newest visible Handlebars output. Config values 11274 // supply fields that are not yet represented in the DOM, especially links. 11275 return { ...configRow, ...domRow }; 11276 }); 11277 11278 configRows.forEach((row, index) => { 11279 if (!usedConfigIndexes.has(index)) merged.push(row); 11280 }); 11281 11282 return merged; 11283 } 11284 11285 function normalizeManualPanelItems() { 11286 const output = []; 11287 const usedKeys = new Set(); 11288 11289 configuredManualRows().forEach((row, index) => { 11290 const showValue = row.manualShowItem ?? row.showItem ?? row.show; 11291 if (showValue !== undefined && showValue !== null && showValue !== '' && !readBoolean(showValue, true)) return; 11292 11293 const label = readString(row.manualLabel ?? row.label ?? row.pageName, ''); 11294 if (!label) return; 11295 11296 const type = readString(row.manualType ?? row.type, 'page').toLowerCase() === 'folder' ? 'folder' : 'page'; 11297 const requestedDepth = normalizeManualLevel(row.manualLevel ?? row.level); 11298 const parentReference = readString(row.manualParent ?? row.parentReference ?? row.parent, ''); 11299 const placement = normalizeManualPlacement(row.manualPlacement ?? row.placement); 11300 const order = readNumber(row.manualOrder ?? row.order, index, -100000, 100000); 11301 const configuredMegaGroup = parseMegaGroup(row.manualMegaGroup ?? row.megaGroup ?? 0); 11302 const configuredLinkData = manualLinkValue(row.manualLink ?? row.link ?? row.url); 11303 const domLinkData = row.__manualLink && readString(row.__manualLink.href, '') 11304 ? row.__manualLink 11305 : null; 11306 const linkData = domLinkData || configuredLinkData; 11307 // Folder items are structural controls and never require or output a link. 11308 const url = type === 'folder' ? '' : resolveManualRuntimeHref(linkData.href); 11309 11310 if (type === 'page' && !url) { 11311 warn('MANUAL_LINK_MISSING', `Manual navigation item "${label}" was skipped because it has no configured link.`); 11312 return; 11313 } 11314 11315 const suppliedKey = readString(row.manualItemKey ?? row.itemKey ?? row.key, ''); 11316 let key = suppliedKey || `manual:${slugify(label) || 'item'}-${index + 1}`; 11317 if (!key.toLowerCase().startsWith('manual:')) key = `manual:${key}`; 11318 if (usedKeys.has(key.toLowerCase())) { 11319 warn('MANUAL_DUPLICATE_KEY', `Manual navigation key "${key}" was used more than once; the later item was skipped.`); 11320 return; 11321 } 11322 usedKeys.add(key.toLowerCase()); 11323 11324 output.push({ 11325 key, 11326 parentKey: null, 11327 source: 'manual', 11328 type, 11329 presentation: configuredMegaGroup ? 'mega' : 'standard', 11330 megaGroup: configuredMegaGroup, 11331 depth: requestedDepth, 11332 order, 11333 label, 11334 slug: slugify(label), 11335 canonicalPath: url && !/^(?:mailto:|tel:|sms:|javascript:)/i.test(url) ? canonicalPath(url) : '', 11336 url, 11337 target: readString(linkData.target, '_self'), 11338 isExternal: isExternalUrl(url), 11339 hasChildren: false, 11340 children: [], 11341 linkAttributes: linkData.attributes || {}, 11342 linkClassName: readString(linkData.className, ''), 11343 _manualRequestedDepth: requestedDepth, 11344 _manualParentReference: parentReference, 11345 _manualPlacement: placement 11346 }); 11347 }); 11348 11349 return output; 11350 } 11351 11352 function buildManualParentIndex(baseItems, manualItems) { 11353 const byKey = new Map(); 11354 const byLabel = new Map(); 11355 const bySlug = new Map(); 11356 11357 function add(item) { 11358 if (!item) return;
11359 const key = readString(item.key, '').toLowerCase(); 11360 const label = readString(item.label, '').toLowerCase(); 11361 const slug = readString(item.slug, slugify(item.label)).toLowerCase(); 11362 if (key && !byKey.has(key)) byKey.set(key, item); 11363 if (label) { 11364 if (!byLabel.has(label)) byLabel.set(label, []); 11365 byLabel.get(label).push(item); 11366 } 11367 if (slug) { 11368 if (!bySlug.has(slug)) bySlug.set(slug, []); 11369 bySlug.get(slug).push(item); 11370 } 11371 (item.children || []).forEach(add); 11372 } 11373 11374 (baseItems || []).forEach(add); 11375 (manualItems || []).forEach(add); 11376 return { byKey, byLabel, bySlug }; 11377 } 11378 11379 function resolveManualParent(reference, index) { 11380 const raw = readString(reference, ''); 11381 if (!raw) return null; 11382 const lower = raw.toLowerCase(); 11383 const keyCandidates = unique([lower, lower.startsWith('manual:') ? lower : `manual:${lower}`]); 11384 for (const key of keyCandidates) { 11385 if (index.byKey.has(key)) return index.byKey.get(key); 11386 } 11387 11388 const labelMatches = index.byLabel.get(lower) || []; 11389 if (labelMatches.length) { 11390 if (labelMatches.length > 1) { 11391 warn('MANUAL_PARENT_AMBIGUOUS', `Parent reference "${raw}" matched more than one Page Name. The first match was used; use an Item Key for an exact match.`); 11392 } 11393 return labelMatches[0]; 11394 } 11395 11396 const slugMatches = index.bySlug.get(slugify(raw)) || []; 11397 if (slugMatches.length) { 11398 if (slugMatches.length > 1) { 11399 warn('MANUAL_PARENT_AMBIGUOUS', `Parent reference "${raw}" matched more than one slug. The first match was used; use an Item Key for an exact match.`); 11400 } 11401 return slugMatches[0]; 11402 } 11403 11404 return null; 11405 } 11406 11407 function manualParentCreatesCycle(item, parent, manualByKey) {
11408 let current = parent; 11409 const seen = new Set([item.key]); 11410 while (current) { 11411 if (seen.has(current.key)) return true; 11412 seen.add(current.key); 11413 const parentReference = current._manualParentReference; 11414 if (!parentReference) return false; 11415 current = manualByKey.get(readString(parentReference, '').toLowerCase()) 11416 || manualByKey.get(`manual:${readString(parentReference, '').toLowerCase()}`) 11417 || null; 11418 } 11419 return false; 11420 } 11421 11422 function finalizeManualLayer(items, depth = 0, parentKey = null, inheritedMegaGroup = 0) { 11423 const sourceItems = (items || []).filter(Boolean); 11424 // Top-level placement is already explicitly assembled as After Home, 11425 // After Collection, and After Native. Preserve that order. Child and 11426 // grandchild siblings use the numeric Order field. 11427 if (depth > 0) sourceItems.sort((a, b) => Number(a.order || 0) - Number(b.order || 0)); 11428 return sourceItems.map(item => { 11429 item.depth = depth; 11430 item.parentKey = parentKey; 11431 const group = depth === 0 ? Math.round(Number(item.megaGroup) || 0) : inheritedMegaGroup; 11432 item.megaGroup = group >= 1 && group <= 4 ? group : 0; 11433 item.presentation = item.megaGroup ? 'mega' : 'standard'; 11434 item.children = finalizeManualLayer(item.children || [], depth + 1, item.key, item.megaGroup); 11435 item.hasChildren = item.children.length > 0; 11436 delete item._manualRequestedDepth; 11437 delete item._manualParentReference; 11438 delete item._manualPlacement; 11439 return item; 11440 }); 11441 } 11442 11443 function insertManualRoots(baseItems, manualRoots, customNavMode) { 11444 const afterHome = manualRoots.filter(item => item._manualPlacement === 'after-home').sort((a, b) => a.order - b.order); 11445 const afterCollection = manualRoots.filter(item => item._manualPlacement === 'after-collection').sort((a, b) => a.order - b.order); 11446 const afterNative = manualRoots.filter(item => item._manualPlacement === 'after-native').sort((a, b) => a.order - b.order); 11447 11448 // CUSTOMNAV is itself the collection-backed base. Preserve its authored order 11449 // and layer the panel items around that complete base rather than re-sorting it 11450 // by each row's SOURCE metadata. 11451 if (customNavMode) { 11452 const base = [...baseItems]; 11453 const homeIndex = base.findIndex(item => readString(item.label, '').toLowerCase() === 'home' || item.canonicalPath === '/'); 11454 if (afterHome.length) base.splice(homeIndex >= 0 ? homeIndex + 1 : 0, 0, ...afterHome); 11455 return [...base, ...afterCollection, ...afterNative]; 11456 } 11457 11458 const firstNativeIndex = baseItems.findIndex(item => item.source === 'native'); 11459 const collectionBlock = firstNativeIndex >= 0 ? baseItems.slice(0, firstNativeIndex) : [...baseItems]; 11460 const nativeBlock = firstNativeIndex >= 0 ? baseItems.slice(firstNativeIndex) : []; 11461 const homeIndex = collectionBlock.findIndex(item => readString(item.label, '').toLowerCase() === 'home' || item.canonicalPath === '/'); 11462 if (afterHome.length) collectionBlock.splice(homeIndex >= 0 ? homeIndex + 1 : 0, 0, ...afterHome);
11463 return [...collectionBlock, ...afterCollection, ...nativeBlock, ...afterNative]; 11464 } 11465 11466 function layerManualNavigationItems(baseItems, customNavMode) { 11467 const manualItems = normalizeManualPanelItems(); 11468 if (!manualItems.length) return baseItems; 11469 11470 const manualByKey = new Map(manualItems.map(item => [item.key.toLowerCase(), item])); 11471 const index = buildManualParentIndex(baseItems, manualItems); 11472 const roots = []; 11473 11474 manualItems.forEach(item => { 11475 const requestedDepth = item._manualRequestedDepth; 11476 if (requestedDepth === 0) { 11477 if (item._manualParentReference) { 11478 warn('MANUAL_TOP_PARENT_IGNORED', `Manual top-level item "${item.label}" has a Parent value; the Parent value was ignored.`); 11479 } 11480 roots.push(item); 11481 return; 11482 } 11483 11484 const parent = resolveManualParent(item._manualParentReference, index); 11485 if (!parent) { 11486 warn('MANUAL_PARENT_NOT_FOUND', `Manual navigation item "${item.label}" was skipped because parent "${item._manualParentReference}" was not found.`); 11487 item.invalid = true; 11488 return; 11489 } 11490 if (manualParentCreatesCycle(item, parent, manualByKey)) { 11491 warn('MANUAL_PARENT_CYCLE', `Manual navigation item "${item.label}" was skipped because its parent configuration creates a cycle.`); 11492 item.invalid = true; 11493 return; 11494 } 11495 11496 const requiredParentDepth = requestedDepth - 1; 11497 const parentDepth = Number(parent._manualRequestedDepth ?? parent.depth ?? 0); 11498 if (parentDepth !== requiredParentDepth) { 11499 warn('MANUAL_LEVEL_MISMATCH', `Manual navigation item "${item.label}" was skipped because its selected level does not immediately follow parent "${parent.label}".`); 11500 item.invalid = true; 11501 return; 11502 } 11503 11504 item.parentKey = parent.key; 11505 parent.children = parent.children || []; 11506 parent.children.push(item); 11507 parent.hasChildren = true; 11508 }); 11509 11510 const validRoots = roots.filter(item =>
11510 !item.invalid); 11511 let merged = insertManualRoots(baseItems, validRoots, customNavMode); 11512 merged = finalizeManualLayer(merged, 0, null, 0); 11513 11514 // On live/preview pages an empty folder has no useful navigation action, so 11515 // omit it. In the editor, retain it as a disabled preview row so changing a 11516 // manual item from Page to Folder produces an immediate visible response and 11517 // clearly indicates that a child still needs to be assigned. 11518 function removeEmptyFolders(items) { 11519 return (items || []).filter(item => { 11520 item.children = removeEmptyFolders(item.children || []); 11521 item.hasChildren = item.children.length > 0; 11522 if (item.source === 'manual' && item.type === 'folder' && !item.hasChildren) { 11523 if (isEditorCanvas()) { 11524 item._manualEmptyFolderPreview = true; 11525 return true; 11526 } 11527 warn('MANUAL_EMPTY_FOLDER', `Manual folder "${item.label}" was skipped because it has no valid children.`); 11528 return false; 11529 } 11530 return true; 11531 }); 11532 } 11533 11534 return removeEmptyFolders(merged); 11535 } 11536 11537 // --------------------------------------------------------------------------- 11538 // CUSTOMNAV mode and export-compatible normalization 11539 // --------------------------------------------------------------------------- 11540 11541 function normalizeCustomNavRows(rows) { 11542 const flat = []; 11543 const byKey = new Map(); 11544 (rows || []).forEach((row, index) => { 11545 const showRaw = field(row, 'SHOW ITEM', 'show_item', 'SHOW', 'show'); 11546 if (showRaw !== '' && showRaw !== undefined && showRaw !== null && !readBoolean(showRaw, true)) return; 11547 11548 const key = readString(field(row, 'ITEM KEY', 'item_key'), `custom:${index}`); 11549 if (byKey.has(key)) { 11550 warn('CUSTOMNAV_DUPLICATE_KEY', `CUSTOMNAV key "${key}" was used more than once; the later row was skipped.`); 11551 return; 11552 } 11553 const source = readString(field(row, 'SOURCE', 'source'), 'manual').toLowerCase(); 11554 const type = readString(field(row, 'TYPE', 'type'), 'page').toLowerCase() === 'folder' ? 'folder' : 'page'; 11555 const label = readString(field(row, 'PAGE NAME', 'LABEL', 'page_name', 'label'), ''); 11556 if (!label) return; 11557 const rawUrl = type === 'folder' ? '' : readString(field(row, 'URL', 'url'), ''); 11558 const url = source === 'manual' && rawUrl ? buildRuntimeFallbackUrl(rawUrl) : rawUrl; 11559 const item = { 11560 key, 11561 parentKey: readString(field(row, 'PARENT KEY', 'parent_key'), '') || null, 11562 source: ['native', 'collection', 'manual'].includes(source) ? source : 'manual', 11563 type, 11564 presentation: readString(field(row, 'PRESENTATION', 'presentation'), 'standard').toLowerCase() === 'mega' ? 'mega' : 'standard', 11565 megaGroup: Math.round(readNumber(field(row, 'MEGA GROUP', 'mega_group'), 0, 0, 4)), 11566 depth: Math.round(readNumber(field(row, 'DEPTH', 'depth'), 0, 0, 2)), 11567 order: Math.round(readNumber(field(row, 'ORDER', 'order'), index, 0, 100000)), 11568 label, 11569 slug: readString(field(row, 'SLUG', 'slug'), slugify(label)), 11570 canonicalPath: readString(field(row, 'CANONICAL PATH', 'canonical_path'), canonicalPath(url)), 11571 url, 11572 target: readString(field(row, 'TARGET', 'target'), '_self'), 11573 isExternal: readBoolean(field(row, 'IS EXTERNAL', 'is_external'), isExternalUrl(url)), 11574 hasChildren: false, 11575 children: [] 11576 }; 11577 flat.push(item); 11578 byKey.set(key, item); 11579 }); 11580 11581 const roots = []; 11582 flat.sort((a, b) => a.order - b.order).forEach(item => { 11583 if (!item.parentKey) { 11584 roots.push(item); 11585 return; 11586 } 11587 const parent = byKey.get(item.parentKey); 11588 if (!parent || parent === item) { 11589 warn('CUSTOMNAV_PARENT_INVALID', `CUSTOMNAV item "${item.label}" was skipped because its parent is invalid.`); 11590 item.invalid = true; 11591 return; 11592 } 11593 parent.children.push(item); 11594 parent.hasChildren = true; 11595 }); 11596 11597 function normalizeDepth(items, depth = 0, parentKey = null) { 11598 return items 11599 .filter(item =>
11599 !item.invalid) 11600 .sort((a, b) => a.order - b.order) 11601 .map(item => { 11602 if (depth > MAX_DEPTH) { 11603 warn('CUSTOMNAV_DEPTH_INVALID', `CUSTOMNAV item "${item.label}" was skipped because navigation supports three content levels.`); 11604 return null; 11605 } 11606 item.depth = depth; 11607 item.parentKey = parentKey; 11608 item.children = normalizeDepth(item.children || [], depth + 1, item.key); 11609 item.hasChildren = item.children.length > 0; 11610 return item; 11611 }) 11612 .filter(Boolean); 11613 } 11614 11615 return normalizeDepth(roots); 11616 } 11617 11618 // Re-resolve source-backed CUSTOMNAV links so preview/live URLs do not become stale. 11619 function refreshCustomUrls(items, categoryRows, coreRows) { 11620 const native = parseNativeNavigation(); 11621 const categoryIndex = buildDynamicIndex(categoryRows || []); 11622 const coreIndex = buildDynamicIndex(coreRows || []); 11623 function walk(item) { 11624 const copy = { ...item, children: item.children.map(walk) }; 11625 if (item.source === 'native' && item.canonicalPath) { 11626 const match = findTreeItem(native, candidate => candidate.canonicalPath === item.canonicalPath); 11627 if (match && match.url) copy.url = match.url; 11628 } 11629 if (item.source === 'collection' && item.slug) { 11630 const isHome = item.depth === 0 && ( 11631 readString(item.label, '').toLowerCase() === 'home' || 11632 canonicalPathWithoutHash(item.canonicalPath || item.url) === '/' 11633 ); 11634 11635 if (isHome) { 11636 copy.url = item.url || buildRuntimeFallbackUrl('/'); 11637 copy.canonicalPath = '/'; 11638 } else { 11639 const expectsCategory = usesCategorySource(item.depth, item.children || []); 11640 const index = expectsCategory ? categoryIndex : coreIndex; 11641 const prefix = expectsCategory ? CATEGORY_URL_PREFIX : CHILD_URL_PREFIX; 11642 const match = findDynamicMatch(index, item.label || item.slug, prefix); 11643 copy.url = match 11644 ? match.url 11645 : buildConfiguredDynamicUrl(item.label || item.slug, prefix); 11646 copy.canonicalPath = canonicalPath(copy.url); 11647 } 11648 } 11649 copy.hasChildren = copy.children.length > 0; 11650 return copy; 11651 } 11652 return items.map(walk); 11653 } 11654 11655 function findTreeItem(items, predicate) { 11656 for (const item of items || []) { 11657 if (predicate(item)) return item; 11658 const nested = findTreeItem(item.children, predicate); 11659 if (nested) return nested; 11660 } 11661 return null; 11662 } 11663 11664 11665 // Build a guaranteed fallback from 06 NAV MASTER alone. Structural items 11666 // with children use the Category prefix; leaf items use the Core prefix, even 11667 // when they are top-level or assigned to a Mega group. Category/Core 11668 // collections are still preferred for exact page_item_url values, but a 11669 // temporarily unavailable validation collection no longer blanks the nav. 11670 function normalizeNavMasterFallback(navRows) { 11671 const tree = buildCollectionTree(navRows || []); 11672 11673 function walk(node, ancestors, inheritedMegaGroup) { 11674 if (!node || node.invalid || node.depth > MAX_DEPTH) return null; 11675 11676 const megaGroup = node.depth === 0 11677 ? parseMegaGroup(node.topMegaValue) 11678 : inheritedMegaGroup; 11679 11680 const children = node.children 11681 .map(child => walk(child, [...ancestors, node], megaGroup)) 11682 .filter(Boolean); 11683 11684 const slug = slugify(node.label); 11685 const isHome = node.depth === 0 && node.label.toLowerCase() === 'home'; 11686 const expectsCategory = usesCategorySource(node.depth, children); 11687 const prefix = expectsCategory ? CATEGORY_URL_PREFIX : CHILD_URL_PREFIX; 11688 const configuredPageLink = node.pageLink ? buildRuntimeFallbackUrl(node.pageLink) : ''; 11689 const url = isHome 11690 ? (configuredPageLink || buildRuntimeFallbackUrl('/')) 11691 : buildConfiguredDynamicUrl(node.label, prefix); 11692 const hierarchySlugs = [...ancestors.map(item => slugify(item.label)), slug]; 11693 11694 return { 11695 key: `collection:${hierarchySlugs.join('/')}`, 11696 parentKey: ancestors.length 11697 ? `collection:${ancestors.map(item => slugify(item.label)).join('/')}` 11698 : null, 11699 source: 'collection', 11700 type: 'page', 11701 presentation: megaGroup ? 'mega' : 'standard', 11702 megaGroup, 11703 depth: node.depth, 11704 order: node.order, 11705 label: node.label, 11706 slug, 11707 canonicalPath: canonicalPath(url), 11708 url, 11709 target: '_self', 11710 isExternal: false, 11711 hasChildren: children.length > 0, 11712 children 11713 }; 11714 } 11715 11716 return tree.map(rootNode =>
11716 walk(rootNode, [], 0)).filter(Boolean); 11717 } 11718 11719 // --------------------------------------------------------------------------- 11720 // Group top-level mega families under one synthetic trigger per Mega group 11721 // --------------------------------------------------------------------------- 11722 11723 function shiftMegaFamilyDepth(item, parentKey, depthOffset = 1) { 11724 const nextDepth = Math.max(0, Number(item.depth) || 0) + depthOffset; 11725 const shifted = { 11726 ...item, 11727 parentKey, 11728 depth: nextDepth, 11729 presentation: 'mega', 11730 children: [] 11731 }; 11732 11733 shifted.children = (item.children || []).map(child => 11734 shiftMegaFamilyDepth(child, shifted.key, depthOffset) 11735 ); 11736 shifted.hasChildren = shifted.children.length > 0; 11737 return shifted; 11738 } 11739 11740 function groupMegaNavigationItems(items) { 11741 const sourceItems = Array.isArray(items) ? items : []; 11742 const groupedFamilies = new Map(); 11743 const firstIndexes = new Map(); 11744 11745 sourceItems.forEach((item, index) => { 11746 const groupNumber = Math.round(Number(item && item.megaGroup) || 0); 11747 const isSyntheticGroup = readString(item && item.key, '').startsWith('mega-group:'); 11748 if (groupNumber < 1 || groupNumber > 4 || isSyntheticGroup) return; 11749 11750 if (!groupedFamilies.has(groupNumber)) { 11751 groupedFamilies.set(groupNumber, []); 11752 firstIndexes.set(groupNumber, index); 11753 } 11754 groupedFamilies.get(groupNumber).push(item); 11755 }); 11756 11757 if (!groupedFamilies.size) return sourceItems; 11758 11759 const output = []; 11760 const insertedGroups = new Set(); 11761 11762 sourceItems.forEach((item, index) => { 11763 const groupNumber = Math.round(Number(item && item.megaGroup) || 0); 11764 const isSyntheticGroup = readString(item && item.key, '').startsWith('mega-group:'); 11765 11766 if (groupNumber >= 1 && groupNumber <= 4 && !isSyntheticGroup) { 11767 if (insertedGroups.has(groupNumber)) return; 11768 if (firstIndexes.get(groupNumber) !== index) return; 11769 11770 const key = `mega-group:${groupNumber}`; 11771 const megaCfg = getMegaConfig(groupNumber); 11772 const sourceFamilies = [...(groupedFamilies.get(groupNumber) || [])]; 11773 if (megaCfg.alphabetize) { 11774 sourceFamilies.sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: 'base' })); 11775 } 11776 const families = sourceFamilies.map(family => 11777 shiftMegaFamilyDepth(family, key, 1) 11778 ); 11779 11780 output.push({ 11781 key, 11782 parentKey: null, 11783 source: 'generated', 11784 type: 'folder', 11785 presentation: 'mega', 11786 megaGroup: groupNumber, 11787 depth: 0, 11788 order: index, 11789 label: megaCfg.label, 11790 slug: slugify(megaCfg.label), 11791 canonicalPath: '', 11792 url: '', 11793 target: '_self', 11794 isExternal: false, 11795 hasChildren: families.length > 0, 11796 children: families 11797 }); 11798 insertedGroups.add(groupNumber); 11799 return; 11800 } 11801 11802 output.push(item); 11803 }); 11804 11805 return output; 11806 } 11807 11808 // --------------------------------------------------------------------------- 11809 // Build and publish the final shared model 11810 // --------------------------------------------------------------------------- 11811 11812 async function buildNavigationModel() { 11813 local.latestBuildWarnings = []; 11814 local.slugValidationWarnings = []; 11815 const fetched = await fetchRequiredCollections(); 11816 const collections = fetched.collections; 11817 let hadError = fetched.hadError; 11818 let model; 11819 11820 if (readBoolean(configValueFrom(cfg, 'useCustomNavOnly'), false)) { 11821 model = normalizeCustomNavRows(collections.CUSTOMNAV || []); 11822 // Optional URL refresh data is fetched when any CUSTOMNAV item at any 11823 // hierarchy level is backed by a native or collection source. 11824 const needsRefresh = Boolean(findTreeItem(model, item => item.source !== 'manual')); 11825 if (needsRefresh) { 11826 const secondary = await Promise.allSettled([fetchCollection('02 CATEGORY'), fetchCollection('03 CORE')]); 11827 const categories = secondary[0].status === 'fulfilled' ? secondary[0].value : []; 11828 const cores = secondary[1].status === 'fulfilled' ? secondary[1].value : []; 11829 if (secondary.some(result => result.status === 'rejected')) { 11830 hadError = true; 11831 warn('CUSTOMNAV_URL_REFRESH_FAILED', 'One or more source collections could not be loaded while refreshing CUSTOMNAV URLs.'); 11832 } 11833 model = refreshCustomUrls(model, categories, cores); 11834 } 11835 } else { 11836 const navMasterRows = collections['06 NAV MASTER'] || []; 11837 let collectionItems; 11838 11839 if (hadError && navMasterRows.length) {
11840 // Do not report missing slugs when one of the source collections failed 11841 // to load; absence cannot be confirmed until both collections are available. 11842 local.slugValidationWarnings = []; 11843 warn( 11844 'COLLECTION_VALIDATION_UNAVAILABLE', 11845 'One or more validation collections could not be loaded. Rendering NAV MASTER with constructed URLs for this build.' 11846 ); 11847 collectionItems = normalizeNavMasterFallback(navMasterRows); 11848 } else { 11849 collectionItems = normalizeCollectionNavigation( 11850 navMasterRows, 11851 collections['02 CATEGORY'] || [], 11852 collections['03 CORE'] || [] 11853 ); 11854 11855 if (!collectionItems.length && navMasterRows.length) { 11856 warn( 11857 'VALIDATION_FALLBACK', 11858 'Category/Core validation produced no items. Rendering NAV MASTER with constructed URLs instead.' 11859 ); 11860 collectionItems = normalizeNavMasterFallback(navMasterRows); 11861 } 11862 } 11863 11864 const nativeItems = normalizeConfiguredNativeNavigation(); 11865 model = [...collectionItems, ...nativeItems]; 11866 } 11867 11868 // Panel-created manual items are additive in both modes. In CUSTOMNAV-only 11869 // mode they are layered on top of the CUSTOMNAV collection; in normal mode 11870 // they are layered on top of Collection + Native navigation. 11871 model = layerManualNavigationItems( 11872 model, 11873 readBoolean(configValueFrom(cfg, 'useCustomNavOnly'), false) 11874 ); 11875 11876 // A Mega value assigns a top-level family to a shared group. The visible 11877 // trigger is the configured Mega label, while assigned parents become 11878 // families inside that single dropdown. Yes and Mega1 both map to group 1. 11879 model = groupMegaNavigationItems(model); 11880 11881 return { 11882 model, 11883 hadError, 11884 warnings: local.latestBuildWarnings, 11885 slugWarnings: local.slugValidationWarnings 11886 }; 11887 } 11888 11889 function isCurrentInstance() { 11890 const ownerKey = widgetMode === 'full' ? 'ownerId' : 'mirrorOwnerId'; 11891 return !local.cleaned 11892 && root.dataset.nmwInstance === instanceId 11893 && window.NMW[ownerKey] === instanceId; 11894 } 11895 11896 async function runRebuild() { 11897 if (!isCurrentInstance()) return; 11898 if (local.rebuildRunning) { 11899 local.pendingRebuild = true; 11900 return; 11901 } 11902 11903 local.rebuildRunning = true; 11904 window.NMW.loading = true; 11905 updateRootStatus(); 11906 dispatchStateChanged(); 11907 11908 try { 11909 const result = await buildNavigationModel(); 11910 11911 // A newer Duda panel execution may have replaced this instance while the 11912 // asynchronous collection requests were running. Never allow a stale 11913 // build to render or alter shared state. 11914 if (!isCurrentInstance()) return; 11915 11916 const nextData = result.model || []; 11917 const previousSignature = stableStringify(window.NMW.data || []); 11918 const nextSignature = stableStringify(nextData); 11919 const dataChanged = previousSignature !== nextSignature; 11920 11921 const nextFullConfig = cloneSerializable(cfg) || {}; 11922 let nextConfigSignature = ''; 11923 try { nextConfigSignature = stableStringify(nextFullConfig); } 11924 catch (error) { nextConfigSignature = String(Date.now()); } 11925 const presentationChanged = window.NMW.fullConfigSignature !== nextConfigSignature; 11926 11927 window.NMW.error = result.hadError; 11928 window.NMW.warnings = result.warnings; 11929 window.NMW.slugWarnings = Array.isArray(result.slugWarnings) ? result.slugWarnings : []; 11930 window.NMW.ready = true; 11931 window.NMW.data = nextData; 11932 window.NMW.fullConfig = nextFullConfig; 11933 window.NMW.fullConfigSignature = nextConfigSignature; 11934 11935 // Always render the current Full instance. Duda Design/Content Panel 11936 // changes such as Mega columns, expanded/collapsed families, max width, 11937 // hover behavior, or tool visibility may not alter the normalized model. 11938 // Skipping render when data is unchanged is what previously caused panel 11939 // changes to appear stuck until a refresh. This also replaces any 11940 // NAV-MASTER-only provisional render with the final validated model. 11941 root.removeAttribute('data-nmw-provisional'); 11942 renderNavigation(nextData, 'full'); 11943 11944 if (dataChanged || presentationChanged) { 11945 window.NMW.version += 1; 11946 if (presentationChanged) window.NMW.presentationVersion += 1; 11947 dispatchDataChanged(); 11948 } 11949 } catch (error) { 11950 if (!isCurrentInstance()) return; 11951 window.NMW.error = true; 11952 window.NMW.ready = true; 11953 if (!Array.isArray(window.NMW.data)) window.NMW.data = []; 11954 warn('BUILD_FAILED', 'Navigation build failed.', error); 11955 if (!window.NMW.data.length && renderHost) { 11956 renderHost.innerHTML = `<div class="nmw-empty">Navigation build failed: ${escapeHtml(error && error.message ? error.message :
11956String(error))}</div>`; 11957 } 11958 } finally { 11959 local.rebuildRunning = false; 11960 11961 // Only the currently registered instance may clear the shared loading 11962 // state or launch a queued rebuild. This prevents a replaced instance 11963 // from leaving the editor stuck on Loading navigationâ¦. 11964 if (isCurrentInstance()) { 11965 window.NMW.loading = false; 11966 updateRootStatus(); 11967 updateTools(); 11968 dispatchStateChanged(); 11969 if (local.pendingRebuild) { 11970 local.pendingRebuild = false; 11971 runRebuild(); 11972 } 11973 } 11974 } 11975 } 11976 11977 function scheduleRebuild(immediate = false) { 11978 if (local.cleaned) return; 11979 clearTimeout(local.rebuildTimer); 11980 if (immediate) { 11981 runRebuild(); 11982 return; 11983 } 11984 local.rebuildTimer = setTimeout(runRebuild, REBUILD_DEBOUNCE); 11985 } 11986 11987 // --------------------------------------------------------------------------- 11988 // Renderers 11989 // --------------------------------------------------------------------------- 11990 11991 function itemClasses(item) { 11992 return [ 11993 'nmw-item', 11994 `nmw-source-${item.source}`, 11995 `nmw-type-${item.type}`, 11996 `nmw-presentation-${item.presentation}`, 11997 `nmw-depth-${item.depth}`, 11998 item.megaGroup ? `nmw-mega-group-${item.megaGroup}` : '' 11999 ].filter(Boolean).join(' '); 12000 } 12001 12002 function linkHtml(item, mode, extraClass = '') { 12003 const editorDisabled = isEditorCanvas() && !isSiteCommentsCustomerMode(); 12004 const inheritedClasses = readString(item.linkClassName, '') 12005 .split(/\s+/) 12006 .filter(className => className && className !== 'nmw-link') 12007 .join(' '); 12008 const attributes = item.linkAttributes && typeof item.linkAttributes === 'object' 12009 ? Object.entries(item.linkAttributes).map(([name, value]) => { 12010 const safeName = String(name).trim(); 12011 if (!/^(?:data-[\w:-]+|aria-[\w:-]+|rel|download|title|name|type|onclick)$/i.test(safeName)) return ''; 12012 return value === '' ? ` ${safeName}` : ` ${safeName}="${escapeHtml(value)}"`; 12013 }).join('') 12014 : ''; 12015 const className = ['nmw-link', extraClass, inheritedClasses].filter(Boolean).join(' '); 12016 return `<a class="${escapeHtml(className)}" href="${escapeHtml(item.url)}" target="${escapeHtml(item.target || '_self')}" data-nmw-key="${escapeHtml(item.key)}" data-nmw-path="${escapeHtml(item.canonicalPath)}"${attributes}${editorDisabled ? ' data-nmw-editor-disabled="true"' : ''}><span class="nmw-label">${escapeHtml(item.label)}</span></a>`; 12017 } 12018 12019 function toggleHtml(item, submenuId, folder = false, megaFamily = false) { 12020 const label = folder ? item.label : `${item.label} submenu`; 12021 const className = folder ? 'nmw-folder-button' : `nmw-toggle${megaFamily ? ' nmw-mega-family-toggle' : ''}`; 12022 return `<button class="${className}" type="button" data-nmw-toggle data-nmw-key="${escapeHtml(item.key)}" aria-label="Toggle ${escapeHtml(label)}" aria-expanded="false" aria-controls="${escapeHtml(submenuId)}"><span class="nmw-label">${folder ? escapeHtml(item.label) : ''}</span><span class="nmw-toggle-icon" aria-hidden="true"></span></button>`; 12023 } 12024 12025 function emptyFolderPreviewHtml(item) { 12026 return `<button class="nmw-folder-button nmw-empty-folder-preview" type="button" disabled aria-disabled="true" title="Add a valid child item to this folder"><span class="nmw-label">${escapeHtml(item.label)}</span><span class="nmw-empty-folder-note" aria-hidden="true">Add child</span></button>`; 12027 } 12028
12029 function renderStandardItem(item, mode, idState) { 12030 const submenuId = item.hasChildren ? `nmw-${mode}-submenu-${++idState.value}` : ''; 12031 let row; 12032 if (item.type === 'folder' && item._manualEmptyFolderPreview) { 12033 row = `<div class="nmw-row">${emptyFolderPreviewHtml(item)}</div>`; 12034 } else if (item.type === 'folder') { 12035 row = `<div class="nmw-row">${toggleHtml(item, submenuId, true)}</div>`; 12036 } else if (item.hasChildren) { 12037 row = `<div class="nmw-row">${linkHtml(item, mode)}${toggleHtml(item, submenuId, false)}</div>`; 12038 } else { 12039 row = `<div class="nmw-row">${linkHtml(item, mode)}</div>`; 12040 } 12041 12042 const children = item.hasChildren 12043 ? `<ul class="nmw-submenu nmw-standard-submenu nmw-depth-${item.depth + 1}" id="${submenuId}" data-nmw-parent-key="${escapeHtml(item.key)}" hidden>${item.children.map(child => renderStandardItem(child, mode, idState)).join('')}</ul>` 12044 : ''; 12045 return `<li class="${itemClasses(item)}" data-nmw-item data-nmw-key="${escapeHtml(item.key)}">${row}${children}</li>`; 12046 } 12047 12048 function familySize(item) { 12049 return 1 + (item.children || []).reduce((sum, child) => sum + familySize(child), 0); 12050 } 12051 12052 function distributeFamilies(families, columns) { 12053 const output = Array.from({ length: columns }, () => ({ weight: 0, items: [] })); 12054 families.forEach(family => { 12055 let targetIndex = 0; 12056 for (let index = 1; index < output.length; index += 1) { 12057 if (output[index].weight < output[targetIndex].weight) targetIndex = index; 12058 } 12059 output[targetIndex].items.push(family); 12060 output[targetIndex].weight += familySize(family); 12061 }); 12062 return output.map(column => column.items); 12063 } 12064 12065 function renderMegaGrandchild(item, mode) { 12066 const content = item.type === 'folder' 12067 ? `<span class="nmw-mega-grandchild-label"><span class="nmw-label">${escapeHtml(item.label)}</span></span>` 12068 : linkHtml(item, mode, 'nmw-mega-grandchild-link'); 12069 return `<li class="${itemClasses(item)} nmw-mega-grandchild" data-nmw-item data-nmw-key="${escapeHtml(item.key)}"><div class="nmw-row">${content}</div></li>`; 12070 } 12071 12072 function renderMegaChild(item, mode) { 12073 const grandchildren = item.children || []; 12074 const content = item.type === 'folder' 12075 ? `<span class="nmw-mega-child-label"><span class="nmw-label">${escapeHtml(item.label)}</span></span>` 12076 : linkHtml(item, mode, 'nmw-mega-child-link'); 12077 const nested = grandchildren.length 12078 ? `<ul class="nmw-mega-grandchildren" data-nmw-parent-key="${escapeHtml(item.key)}">${grandchildren.map(child => renderMegaGrandchild(child, mode)).join('')}</ul>` 12079 : ''; 12080 return `<li class="${itemClasses(item)} nmw-mega-child${grandchildren.length ? ' nmw-has-grandchildren' : ''}" data-nmw-item data-nmw-key="${escapeHtml(item.key)}"><div class="nmw-row">${content}</div>${nested}</li>`; 12081 } 12082 12083 function renderMegaFamily(family, mode, idState, expandAll) { 12084 const hasChildren = family.children.length > 0; 12085 const familyId = hasChildren ? `nmw-${mode}-mega-family-${++idState.value}` : ''; 12086 const familyLink = family.type === 'page' ? linkHtml(family, mode, 'nmw-mega-family-link') : ''; 12087 let row; 12088 12089 if (!hasChildren || expandAll) { 12090 row = `<div class="nmw-row">${family.type === 'folder' ? `<span class="nmw-folder-label"><span class="nmw-label">${escapeHtml(family.label)}</span></span>` : familyLink}</div>`; 12091 } else if (family.type === 'folder') { 12092 row = `<div class="nmw-row">${toggleHtml(family, familyId, true, true)}</div>`; 12093 } else { 12094 row = `<div class="nmw-row">${familyLink}${toggleHtml(family, familyId, false, true)}</div>`; 12095 } 12096 12097 const children = hasChildren 12098 ? `<ul class="nmw-mega-family-children${expandAll ? ' nmw-open' : ''}" id="${familyId}" data-nmw-parent-key="${escapeHtml(family.key)}"${expandAll ? '' : ' hidden'}>${family.children.map(child => renderMegaChild(child, mode)).join('')}</ul>` 12099 : ''; 12100 12101 return `<div class="nmw-mega-family${expandAll ? ' nmw-open' : ''}" data-nmw-item data-nmw-key="${escapeHtml(family.key)}">${row}${children}</div>`; 12102 } 12103 12104 function renderMegaItem(item, mode, idState) { 12105 const submenuId = `nmw-${mode}-mega-${++idState.value}`;
12106 const row = item.type === 'folder' 12107 ? `<div class="nmw-row">${toggleHtml(item, submenuId, true)}</div>` 12108 : `<div class="nmw-row">${linkHtml(item, mode)}${toggleHtml(item, submenuId, false)}</div>`; 12109 const megaCfg = getMegaConfig(item.megaGroup || 1); 12110 12111 let content; 12112 if (mode === 'mirror') { 12113 // Mirror always uses a single vertical list â layout setting does not apply. 12114 content = `<div class="nmw-mega-vertical">${item.children.map(family => renderMegaFamily(family, mode, idState, megaCfg.expandAll)).join('')}</div>`; 12115 } else if (megaCfg.layout === 'masonry') { 12116 // Masonry: shortest-column balancing. distributeFamilies() assigns each 12117 // family to the column with the lowest accumulated navigation weight so 12118 // differently sized families remain visually balanced across columns. 12119 // Each resulting group is wrapped in a .nmw-mega-column flex container. 12120 const columns = distributeFamilies(item.children, megaCfg.columns); 12121 content = `<div class="nmw-mega-inner" style="--nmw-mega-max-width:${megaCfg.maxWidth}px;--nmw-mega-columns:${megaCfg.columns}" data-nmw-mega-layout="masonry"><div class="nmw-mega-columns">${columns.map(column => `<div class="nmw-mega-column">${column.map(family => renderMegaFamily(family, mode, idState, megaCfg.expandAll)).join('')}</div>`).join('')}</div></div>`; 12122 } else { 12123 // Grid: families are placed directly inside the CSS Grid container in 12124 // their current (or alphabetized) source order. CSS grid-auto-flow: row 12125 // fills each row from left to right before beginning the next row. 12126 // No column wrappers are emitted â each .nmw-mega-family is a direct 12127 // grid child and occupies exactly one grid cell. 12128 const families = item.children 12129 .map(family => renderMegaFamily(family, mode, idState, megaCfg.expandAll)) 12130 .join(''); 12131 content = `<div class="nmw-mega-inner" style="--nmw-mega-max-width:${megaCfg.maxWidth}px;--nmw-mega-columns:${megaCfg.columns}" data-nmw-mega-layout="grid"><div class="nmw-mega-columns">${families}</div></div>`; 12132 } 12133 12134 return `<li class="${itemClasses(item)}" data-nmw-item data-nmw-key="${escapeHtml(item.key)}" data-nmw-mega-label="${escapeHtml(megaCfg.label)}">${row}<div class="nmw-submenu nmw-mega-menu" id="${submenuId}" data-nmw-parent-key="${escapeHtml(item.key)}" data-nmw-mega-group="${item.megaGroup || 1}" data-nmw-mega-label="${escapeHtml(megaCfg.label)}" aria-label="${escapeHtml(megaCfg.label)}" hidden>${content}</div></li>`; 12135 } 12136 12137 function renderNavigation(items, mode) { 12138 if (!renderHost) return; 12139 applyDesignSettings(mode); 12140 updateMegaIndicators(items); 12141 if (!Array.isArray(items) || !items.length) { 12142 renderHost.innerHTML = '<div class="nmw-empty">Navigation could not be built. Check collection data and native navigation configuration.</div>'; 12143 updateTools(); 12144 return; 12145 } 12146 const idState = { value: 0 }; 12147 const navId = mode === 'full' ? 'nmw-full-main-nav' : `nmw-mirror-main-nav-${instanceId}`; 12148 const list = items.map(item => item.presentation === 'mega' 12149 ? renderMegaItem(item, mode, idState) 12150 : renderStandardItem(item, mode, idState)).join(''); 12151 if (loadingHost && loadingHost !== renderHost) loadingHost.hidden = true; 12152 renderHost.innerHTML = `<nav class="nmw-nav nmw-topnav" id="${escapeHtml(navId)}" aria-label="Main navigation"><ul class="nmw-list nmw-top-list">${list}</ul></nav>`; 12153 closeAllMenus(root, false); 12154 refreshActiveStates(root); 12155 updateTools(); 12156 } 12157 12158 // --------------------------------------------------------------------------- 12159 // Menu opening, closing, animation, hover, and delegated interaction 12160 // --------------------------------------------------------------------------- 12161 12162 function findControlledSubmenu(toggle) { 12163 const id = toggle?.getAttribute('aria-controls'); 12164 return id ? root.querySelector(`#${CSS.escape(id)}`) : null; 12165 } 12166 12167 function getTransitionMs(elementNode) { 12168 if (!elementNode || getBehaviorConfig(widgetMode).animationsEnabled === false) return 0; 12169 const style = window.getComputedStyle(elementNode); 12170 if (style.transitionProperty === 'none') return 0; 12171 const durations = style.transitionDuration.split(',').map(value => parseFloat(value) * (value.includes('ms') ? 1 : 1000)); 12172 const delays = style.transitionDelay.split(',').map(value => parseFloat(value) * (value.includes('ms') ? 1 : 1000)); 12173 const measured = Math.max(0, ...durations.map((duration, index) => duration + (delays[index] || delays[0] || 0))); 12174 return measured > 0 ? measured : 0; 12175 } 12176 12177 function cancelCloseJob(submenu) { 12178 const job = local.closeJobs.get(submenu); 12179 if (!job) return; 12180 clearTimeout(job.timer); 12181 local.closeTimers.delete(job.timer); 12182 submenu.removeEventListener('transitionend', job.finish); 12183 local.closeJobs.delete(submenu); 12184 } 12185 12186 function updateFlyoutDirection(submenu) { 12187 if (!submenu || widgetMode === 'mirror' || !submenu.classList.contains('nmw-standard-submenu')) return; 12188 const nested = submenu.parentElement?.closest?.('.nmw-standard-submenu'); 12189 if (!nested) { 12190 submenu.classList.remove('nmw-flip-left'); 12191 return; 12192 } 12193 12194 submenu.classList.remove('nmw-flip-left'); 12195 const rect = submenu.getBoundingClientRect(); 12196 const viewportWidth = document.documentElement.clientWidth || window.innerWidth || 0; 12197 if (rect.right > viewportWidth - 8) submenu.classList.add('nmw-flip-left'); 12198 } 12199 12200 function openMenu(item, toggle, submenu) { 12201 if (!item || !toggle || !submenu) return; 12202 cancelCloseJob(submenu); 12203 closeSiblingMenus(item); 12204 item.classList.remove('nmw-closing'); 12205 submenu.classList.remove('nmw-closing'); 12206 submenu.hidden = false;
12207 requestAnimationFrame(() => { 12208 if (local.cleaned || !document.documentElement.contains(submenu)) return; 12209 updateFlyoutDirection(submenu); 12210 item.classList.add('nmw-open'); 12211 submenu.classList.add('nmw-open'); 12212 toggle.setAttribute('aria-expanded', 'true'); 12213 }); 12214 } 12215 12216 function closeMenu(item, toggle, submenu, returnFocus = false) { 12217 if (!item || !toggle || !submenu || submenu.hidden) return; 12218 cancelCloseJob(submenu); 12219 item.classList.remove('nmw-open'); 12220 submenu.classList.remove('nmw-open'); 12221 item.classList.add('nmw-closing'); 12222 submenu.classList.add('nmw-closing'); 12223 toggle.setAttribute('aria-expanded', 'false'); 12224 12225 let jobTimer = null; 12226 const finish = event => { 12227 if (event && event.target !== submenu) return; 12228 submenu.hidden = true; 12229 item.classList.remove('nmw-closing'); 12230 submenu.classList.remove('nmw-closing'); 12231 submenu.removeEventListener('transitionend', finish); 12232 local.closeJobs.delete(submenu); 12233 if (jobTimer) local.closeTimers.delete(jobTimer); 12234 if (returnFocus) toggle.focus(); 12235 }; 12236 const duration = getTransitionMs(submenu); 12237 if (!duration) { 12238 finish(); 12239 return; 12240 } 12241 submenu.addEventListener('transitionend', finish); 12242 jobTimer = setTimeout(finish, duration + 50); 12243 local.closeTimers.add(jobTimer); 12244 local.closeJobs.set(submenu, { timer: jobTimer, finish }); 12245 } 12246 12247 function closeSiblingMenus(item) { 12248 let siblings = []; 12249 12250 if (item.classList.contains('nmw-mega-family')) { 12251 const megaMenu = item.closest('.nmw-mega-menu'); 12252 siblings = megaMenu 12253 ? Array.from(megaMenu.querySelectorAll('.nmw-mega-family[data-nmw-item]')) 12254 : []; 12255 } else { 12256 const parent = item.parentElement; 12257 siblings = parent ? Array.from(parent.children).filter(node => node.matches?.('[data-nmw-item]')) : []; 12258 } 12259 12260 siblings.forEach(sibling => { 12261 if (sibling === item) return; 12262 const toggle = sibling.querySelector(':scope > .nmw-row [data-nmw-toggle]'); 12263 const submenu = toggle ? findControlledSubmenu(toggle) : null; 12264 if (toggle && submenu) closeMenu(sibling, toggle, submenu, false); 12265 }); 12266 } 12267 12268 function closeAllMenus(scope, returnFocus = false) {
12269 scope.querySelectorAll('[data-nmw-toggle][aria-expanded="true"]').forEach(toggle => { 12270 const item = toggle.closest('[data-nmw-item]'); 12271 const submenu = findControlledSubmenu(toggle); 12272 if (item && submenu) closeMenu(item, toggle, submenu, returnFocus); 12273 }); 12274 local.hoverTimers.forEach(timer => clearTimeout(timer)); 12275 local.hoverTimers.clear(); 12276 } 12277 12278 function toggleMenu(toggle) { 12279 const item = toggle.closest('[data-nmw-item]'); 12280 const submenu = findControlledSubmenu(toggle); 12281 if (!item || !submenu) return; 12282 const isOpen = toggle.getAttribute('aria-expanded') === 'true'; 12283 if (isOpen) closeMenu(item, toggle, submenu, false); 12284 else openMenu(item, toggle, submenu); 12285 } 12286 12287 function nearestOpenToggle(target) { 12288 let node = target && target.closest ? target.closest('[data-nmw-item], .nmw-submenu, .nmw-mega-family-children') : null; 12289 12290 while (node && root.contains(node)) { 12291 if (node.matches?.('[data-nmw-item]')) { 12292 const ownToggle = node.querySelector(':scope > .nmw-row [data-nmw-toggle][aria-expanded="true"]'); 12293 if (ownToggle) return ownToggle; 12294 } 12295 12296 const submenu = node.matches?.('.nmw-submenu, .nmw-mega-family-children') 12297 ? node 12298 : node.closest?.('.nmw-submenu, .nmw-mega-family-children'); 12299 if (!submenu) return null; 12300 12301 const parentKey = submenu.getAttribute('data-nmw-parent-key'); 12302 if (parentKey) { 12303 const parentToggle = root.querySelector(`[data-nmw-toggle][data-nmw-key="${CSS.escape(parentKey)}"][aria-expanded="true"]`); 12304 if (parentToggle) return parentToggle; 12305 } 12306 12307 node = submenu.parentElement?.closest?.('[data-nmw-item], .nmw-submenu, .nmw-mega-family-children') || null; 12308 } 12309 12310 return null; 12311 } 12312 12313 function attachDelegatedInteractions() { 12314 if (local.listenersAttached) return; 12315 local.listenersAttached = true; 12316 12317 listen(root, 'click', event => { 12318 const toggle = event.target.closest('[data-nmw-toggle]'); 12319 if (toggle && root.contains(toggle)) { 12320 event.preventDefault(); 12321 toggleMenu(toggle); 12322 return; 12323 } 12324 12325 const link = event.target.closest('a.nmw-link'); 12326 if (!link || !root.contains(link)) return; 12327 12328 /* 12329 Recheck Site Comments at click time. 12330 12331 The navigation may have rendered before Duda finished identifying 12332 the visitor as a customer. In that case the link can still contain 12333 a stale data-nmw-editor-disabled attribute even though the console 12334 later reports "Customer Detected". 12335 */ 12336 if (isSiteCommentsCustomerMode()) { 12337 /* 12338 Remove stale editor-disabled markers from every rendered link so 12339 the Full and Mirror navigation instances immediately reflect the 12340 confirmed customer state. 12341 */ 12342 root 12343 .querySelectorAll( 12344 'a.nmw-link[data-nmw-editor-disabled="true"]' 12345 ) 12346 .forEach(customerLink => { 12347 customerLink.removeAttribute( 12348 'data-nmw-editor-disabled' 12349 ); 12350 }); 12351 12352 /* 12353 Same-site links use the existing Site Comments top-window 12354 navigation. Links intentionally excluded by that functionâ 12355 anchors, target="_blank", external sites, telephone, email, 12356 SMS, downloads, and similar linksâretain normal browser behavior. 12357 */ 12358 // Same-page anchors are handled inside the current site document so 12359 // repeated anchor selections work without reloading the Site Comments shell. 12360 if (handleSamePageAnchorClick(link, event)) return; 12361 12362 if (navigateSiteComments(link, event)) return; 12363 12364 closeAllMenus(root, false); 12365 return; 12366 } 12367 12368 /* 12369 Outside confirmed customer Site Comments mode, preserve the 12370 original editor safety behavior. 12371 */ 12372 if (link.dataset.nmwEditorDisabled === 'true') { 12373 event.preventDefault(); 12374 return; 12375 } 12376 12377 // Explicitly own same-page anchor navigation. This fixes repeated anchor 12378 // selections on the same page and corrects the final position for sticky 12379 // or fixed headers. Cross-page anchors continue with normal navigation. 12380 if (handleSamePageAnchorClick(link, event)) return; 12381 12382 closeAllMenus(root, false); 12383 }); 12384 12385 listen(root, 'keydown', event => { 12386 if (event.key !== 'Escape') return; 12387 const toggle = nearestOpenToggle(event.target); 12388 if (!toggle) return; 12389 event.preventDefault();
12390 const item = toggle.closest('[data-nmw-item]'); 12391 const submenu = findControlledSubmenu(toggle); 12392 if (item && submenu) closeMenu(item, toggle, submenu, true); 12393 }); 12394 12395 listen(root, 'focusout', event => { 12396 requestAnimationFrame(() => { 12397 if (local.cleaned) return; 12398 if (!root.contains(document.activeElement)) closeAllMenus(root, false); 12399 }); 12400 }); 12401 12402 // Hover uses the same JavaScript-owned state as click. CSS never opens menus 12403 // independently, which keeps hidden and aria-expanded synchronized. 12404 listen(root, 'pointerover', event => { 12405 if (!getBehaviorConfig(widgetMode).hoverEnabled || event.pointerType === 'touch') return; 12406 const item = event.target.closest('[data-nmw-item]'); 12407 if (!item || !root.contains(item)) return; 12408 const toggle = item.querySelector(':scope > .nmw-row [data-nmw-toggle]'); 12409 const submenu = toggle ? findControlledSubmenu(toggle) : null; 12410 if (!toggle || !submenu) return; 12411 const timer = local.hoverTimers.get(item); 12412 if (timer) clearTimeout(timer); 12413 local.hoverTimers.delete(item); 12414 openMenu(item, toggle, submenu); 12415 }); 12416 12417 listen(root, 'pointerout', event => { 12418 if (!getBehaviorConfig(widgetMode).hoverEnabled || event.pointerType === 'touch') return; 12419 const item = event.target.closest('[data-nmw-item]'); 12420 if (!item || !root.contains(item)) return; 12421 const related = event.relatedTarget; 12422 if (related && item.contains(related)) return; 12423 const toggle = item.querySelector(':scope > .nmw-row [data-nmw-toggle]'); 12424 const submenu = toggle ? findControlledSubmenu(toggle) : null; 12425 if (!toggle || !submenu) return; 12426 const timer = setTimeout(() => { 12427 if (!item.matches(':hover')) closeMenu(item, toggle, submenu, false); 12428 local.hoverTimers.delete(item); 12429 }, HOVER_CLOSE_DELAY); 12430 local.hoverTimers.set(item, timer); 12431 }); 12432 12433 listen(document, 'pointerdown', handleOutsidePointer, true); 12434 } 12435 12436 function handleOutsidePointer(event) { 12437 if (!root.contains(event.target)) closeAllMenus(root, false); 12438 } 12439 12440 // --------------------------------------------------------------------------- 12441 // Active-page state from the actual current URL 12442 // --------------------------------------------------------------------------- 12443 12444 function currentComparablePath() { 12445 return canonicalPath(window.location.href); 12446 } 12447 12448 function refreshActiveStates(scope) { 12449 const current = currentComparablePath(); 12450 scope.querySelectorAll('a[data-nmw-path]').forEach(link => { 12451 const path = link.getAttribute('data-nmw-path') || ''; 12452 const active = path && path === current; 12453 link.classList.toggle('nmw-active', active); 12454 if (active) link.setAttribute('aria-current', 'page'); 12455 else link.removeAttribute('aria-current'); 12456 });
12457 scope.querySelectorAll('[data-nmw-item]').forEach(item => { 12458 const ownLink = item.querySelector(':scope > .nmw-row a.nmw-active'); 12459 const activeDescendant = item.querySelector('.nmw-submenu a.nmw-active, .nmw-mega-family-children a.nmw-active'); 12460 item.classList.toggle('nmw-child-active', !ownLink && Boolean(activeDescendant)); 12461 }); 12462 } 12463 12464 function observeHistoryChanges() { 12465 const marker = '__nmwHistoryWrapped'; 12466 if (history[marker]) return () => {}; 12467 history[marker] = true; 12468 const originalPush = history.pushState; 12469 const originalReplace = history.replaceState; 12470 const notify = () => window.dispatchEvent(new Event('nmw:url-changed')); 12471 history.pushState = function (...args) { 12472 const result = originalPush.apply(this, args); 12473 notify(); 12474 return result; 12475 }; 12476 history.replaceState = function (...args) { 12477 const result = originalReplace.apply(this, args); 12478 notify(); 12479 return result; 12480 }; 12481 return () => {}; 12482 } 12483 12484 function handleUrlChanged() { 12485 refreshActiveStates(root); 12486 } 12487 12488 // --------------------------------------------------------------------------- 12489 // Manual-item source observation 12490 // --------------------------------------------------------------------------- 12491 12492 function attachManualSourceObserver() { 12493 const source = root.querySelector('[data-nmw-manual-source]'); 12494 if (!source || local.manualObserver) return false; 12495 12496 local.manualObserver = new MutationObserver(mutations => { 12497 const relevant = mutations.some(mutation => { 12498 if (mutation.type === 'childList') return true; 12499 if (mutation.type !== 'attributes') return false; 12500 const name = mutation.attributeName || ''; 12501 return name === 'href' 12502 || name === 'target' 12503 || name === 'class' 12504 || name.startsWith('data-manual-') 12505 || name.startsWith('data-') 12506 || name.startsWith('aria-'); 12507 }); 12508 12509 if (relevant) scheduleRebuild(false); 12510 }); 12511 12512 local.manualObserver.observe(source, { 12513 childList: true, 12514 subtree: true, 12515 attributes: true 12516 }); 12517 12518 return true; 12519 } 12520 12521 // --------------------------------------------------------------------------- 12522 // Native-nav observation and startup discovery 12523 // --------------------------------------------------------------------------- 12524 12525 function attachNativeObserver() { 12526 const wrapper = getNativeWrapper(); 12527 if (!wrapper || local.nativeObserver) return false; 12528 local.nativeObserver = new MutationObserver(() => scheduleRebuild(false)); 12529 local.nativeObserver.observe(wrapper, { 12530 childList: true, 12531 subtree: true, 12532 attributes: true, 12533 attributeFilter: ['href', 'raw_url', 'runtime_url', 'aria-current', 'class'] 12534 }); 12535 if (local.nativeFinderObserver) { 12536 local.nativeFinderObserver.disconnect(); 12537 local.nativeFinderObserver = null; 12538 } 12539 return true; 12540 } 12541 12542 function beginNativeDiscovery() { 12543 local.nativeRetryStarted = Date.now(); 12544 let isFirstAttempt = true; 12545 12546 const attempt = () => { 12547 if (local.cleaned) return; 12548 12549 // If the document-level finder already attached the native observer, the 12550 // retry loop has nothing left to do. This prevents a later timeout rebuild. 12551 if (local.nativeObserver) return; 12552 12553 if (attachNativeObserver()) { 12554 /* 12555 initializeFull() performs an immediate rebuild right after starting 12556 discovery. When .navmasterdefault already exists on the first attempt, 12557 scheduling another rebuild here caused the collections to be processed 12558 twice during startup. Only rebuild here when native navigation appeared 12559 after that initial attempt. 12560 */ 12561 if (!isFirstAttempt) scheduleRebuild(false); 12562 isFirstAttempt = false; 12563 return; 12564 } 12565 12566 isFirstAttempt = false; 12567 12568 if (Date.now() - local.nativeRetryStarted >= NATIVE_MAX_WAIT) { 12569 warn('NATIVE_NAV_TIMEOUT', '.navmasterdefault was not found within 15 seconds. Collection navigation will still render.'); 12570 scheduleRebuild(true); 12571 return; 12572 } 12573 12574 local.nativeRetryTimer = setTimeout(attempt, NATIVE_RETRY_INTERVAL); 12575 }; 12576 12577 attempt(); 12578 12579 // If the native wrapper already existed, no document-wide finder is needed. 12580 if (local.nativeObserver || local.cleaned) return; 12581 12582 // During delayed Duda insertion, this lightweight observer notices the 12583 // wrapper, attaches the targeted observer, rebuilds once, then disconnects. 12584 local.nativeFinderObserver = new MutationObserver(() => { 12585 if (local.cleaned || local.nativeObserver) return; 12586 if (attachNativeObserver()) scheduleRebuild(false); 12587 }); 12588 local.nativeFinderObserver.observe(document.body, { childList: true, subtree: true }); 12589 } 12590 12591 // --------------------------------------------------------------------------- 12592 // Tree preview and CUSTOMNAV builder 12593 // --------------------------------------------------------------------------- 12594 12595 function updateTools() { 12596 if (!toolsHost) return; 12597 const treeEnabled = readBoolean(configValueFrom(cfg, 'enableNavigationTreePreview'), false); 12598 const builderEnabled = readBoolean(configValueFrom(cfg, 'enableCustomNavigationBuilder'), false); 12599 const visibleEnvironment = isEditorCanvas() || location.href.includes('/preview/') || location.hash.includes('preview'); 12600 if (!visibleEnvironment || (!treeEnabled && !builderEnabled)) { 12601 toolsHost.innerHTML = ''; 12602 return; 12603 } 12604 toolsHost.innerHTML = [ 12605 treeEnabled ? '<button type="button" class="nmw-tool-button" data-nmw-open-tree>View Navigation Tree</button>' : '', 12606 builderEnabled ? '<button type="button" class="nmw-tool-button" data-nmw-open-builder>Open Custom Navigation Builder</button>' : '' 12607 ].join(''); 12608 } 12609 12610 function treeLines(items, prefix = '') { 12611 const output = [];
12612 (items || []).forEach(item => { 12613 output.push(`${prefix}${item.label}`); 12614 output.push(...treeLines(item.children || [], `${prefix} `)); 12615 }); 12616 return output; 12617 } 12618 12619 function renderSlugWarning(item) { 12620 const slugText = (item.slugs || []).join(' or '); 12621 return `<li><strong>${escapeHtml(item.label)}</strong><br>` + 12622 `Slug not found: ${escapeHtml(slugText)}<br>` + 12623 `Suggested collection: ${escapeHtml(item.suggestedCollection)}</li>`; 12624 } 12625 12626 function openTreePreview() { 12627 const warnings = Array.isArray(window.NMW.slugWarnings) ? window.NMW.slugWarnings : []; 12628 const treeOutput = treeLines(window.NMW.data || []).join('\n') || 'No navigation items.'; 12629 const warningSection = warnings.length 12630 ? `<section class="nmw-tree-warnings"><h3>Warnings</h3><ul>${warnings.map(renderSlugWarning).join('')}</ul></section>` 12631 : ''; 12632 const body = `<pre class="nmw-tree-output">${escapeHtml(treeOutput)}</pre>${warningSection}`; 12633 openModal('Navigation Tree Preview', body, 'tree'); 12634 } 12635 12636 function cloneData(value) { 12637 return JSON.parse(JSON.stringify(value || [])); 12638 } 12639 12640 function shiftDraftDepth(item, offset, parentKey = null) { 12641 const copy = cloneData(item); 12642 copy.depth = Math.max(0, (Number(copy.depth) || 0) + offset); 12643 copy.parentKey = parentKey; 12644 copy.children = (copy.children || []).map(child => shiftDraftDepth(child, offset, copy.key)); 12645 copy.hasChildren = copy.children.length > 0; 12646 return copy; 12647 } 12648 12649 // The runtime model contains synthetic Mega trigger rows. CUSTOMNAV should 12650 // store the actual family roots with MEGA GROUP values so loading CUSTOMNAV 12651 // can recreate the trigger without adding an extra persisted hierarchy level. 12652 function draftSourceFromSharedModel() { 12653 const output = []; 12654 (window.NMW.data || []).forEach(item => { 12655 if (readString(item.key, '').startsWith('mega-group:')) { 12656 (item.children || []).forEach(family => { 12657 const copy = shiftDraftDepth(family, -1, null); 12658 copy.megaGroup = item.megaGroup || copy.megaGroup || 0; 12659 copy.presentation = copy.megaGroup ? 'mega' : copy.presentation; 12660 output.push(copy); 12661 }); 12662 } else { 12663 output.push(shiftDraftDepth(item, 0, null)); 12664 } 12665 }); 12666 return output; 12667 } 12668 12669 function flattenDraft(items, output = []) { 12670 items.forEach(item => { 12671 output.push(item); 12672 flattenDraft(item.children, output); 12673 }); 12674 return output; 12675 } 12676 12677 function renderBuilderRows(items) { 12678 return items.map(item => `<div class="nmw-builder-row" draggable="true" data-builder-key="${escapeHtml(item.key)}" style="--nmw-builder-depth:${item.depth}"><span class="nmw-builder-handle" aria-hidden="true">â®â®</span><span class="nmw-builder-label">${escapeHtml(item.label)}</span><span class="nmw-builder-meta">${escapeHtml(item.source)} · ${escapeHtml(item.type)}${item.megaGroup ? ` · ${escapeHtml(getMegaLabel(item.megaGroup))}` : ''}</span><button type="button" data-builder-left data-key="${escapeHtml(item.key)}" aria-label="Move ${escapeHtml(item.label)} left">â</button><button type="button" data-builder-right data-key="${escapeHtml(item.key)}" aria-label="Move ${escapeHtml(item.label)} right">â</button><button type="button" data-builder-remove data-key="${escapeHtml(item.key)}" aria-label="Remove ${escapeHtml(item.label)}">Remove</button></div>`).join(''); 12679 } 12680 12681 function openBuilder() { 12682 local.customDraft = draftSourceFromSharedModel(); 12683 const body = `<div class="nmw-builder-toolbar"><button type="button" data-builder-add>Add Manual Item</button><button type="button" data-builder-reset>Reset Draft</button><button type="button" data-builder-validate>Validate</button><button type="button" data-builder-export="json">Export JSON</button><button type="button" data-builder-export="csv">Export CSV</button><button type="button" data-builder-export="payload">Export Duda Payload</button></div><p class="nmw-builder-help">Drag rows to reorder. Use â and â to promote or demote. Maximum depth is three levels.</p><div class="nmw-builder-list" data-builder-list>${renderBuilderRows(flattenDraft(local.customDraft))}</div><div class="nmw-builder-status" data-builder-status></div>`; 12684 openModal('Custom Navigation Builder', body, 'builder'); 12685 } 12686 12687 function openModal(title, body, type) { 12688 closeModal(); 12689 const modal = document.createElement('div'); 12690 modal.className = 'nmw-modal-backdrop'; 12691 modal.dataset.nmwModal = type; 12692 modal.innerHTML = `<section class="nmw-modal" role="dialog" aria-modal="true" aria-labelledby="nmw-modal-title-${instanceId}"><header class="nmw-modal-header"><h2 id="nmw-modal-title-${instanceId}">${escapeHtml(title)}</h2><button type="button" class="nmw-modal-close" data-nmw-close-modal aria-label="Close">Ã</button></header><div class="nmw-modal-body">${body}</div></section>`; 12693 document.body.appendChild(modal);
12694 modal.querySelector('[data-nmw-close-modal]').focus(); 12695 if (type === 'builder') attachBuilderInteractions(modal); 12696 } 12697 12698 function closeModal() { 12699 document.querySelectorAll('.nmw-modal-backdrop[data-nmw-modal]').forEach(node => node.remove()); 12700 } 12701 12702 function findDraftLocation(key, items = local.customDraft, parent = null) { 12703 for (let index = 0; index < items.length; index += 1) { 12704 if (items[index].key === key) return { item: items[index], items, index, parent }; 12705 const found = findDraftLocation(key, items[index].children, items[index]); 12706 if (found) return found; 12707 } 12708 return null; 12709 } 12710 12711 function recalculateDraft(items = local.customDraft, depth = 0, parentKey = null) { 12712 items.forEach((item, order) => { 12713 item.depth = depth; 12714 item.parentKey = parentKey; 12715 item.order = order; 12716 item.hasChildren = item.children.length > 0; 12717 recalculateDraft(item.children, depth + 1, item.key); 12718 }); 12719 } 12720 12721 function refreshBuilder(modal, message = '') { 12722 recalculateDraft(); 12723 const list = modal.querySelector('[data-builder-list]'); 12724 if (list) list.innerHTML = renderBuilderRows(flattenDraft(local.customDraft)); 12725 const status = modal.querySelector('[data-builder-status]'); 12726 if (status) status.textContent = message; 12727 } 12728 12729 function validateDraft() { 12730 const errors = []; 12731 const keys = new Set(); 12732 function walk(items, ancestors = []) { 12733 items.forEach(item => { 12734 if (keys.has(item.key)) errors.push(`Duplicate key: ${item.key}`); 12735 keys.add(item.key); 12736 if (item.depth > MAX_DEPTH) errors.push(`${item.label} exceeds three levels.`); 12737 if (ancestors.includes(item.key)) errors.push(`${item.label} is nested beneath itself.`); 12738 if (item.type === 'page' && !item.url) errors.push(`${item.label} is a page without a URL.`); 12739 walk(item.children, [...ancestors, item.key]); 12740 }); 12741 } 12742 walk(local.customDraft || []); 12743 return errors; 12744 } 12745 12746 function addManualDraftItem() { 12747 const label = window.prompt('Manual item label:'); 12748 if (!readString(label, '')) return; 12749 const type = window.prompt('Type "page" or "folder":', 'page'); 12750 const isFolder = readString(type, 'page').toLowerCase() === 'folder'; 12751 const url = isFolder ? '' : readString(window.prompt('URL:', '/'), ''); 12752 const key = `manual:${slugify(label)}-${Math.random().toString(36).slice(2, 6)}`; 12753 local.customDraft.push({ 12754 key, 12755 parentKey: null, 12756 source: 'manual', 12757 type: isFolder ? 'folder' : 'page', 12758 presentation: 'standard', 12759 megaGroup: 0, 12760 depth: 0, 12761 order: local.customDraft.length, 12762 label, 12763 slug: slugify(label), 12764 canonicalPath: isFolder ? '' : canonicalPath(url), 12765 url, 12766 target: '_self', 12767 isExternal: isExternalUrl(url), 12768 hasChildren: false, 12769 children: [] 12770 }); 12771 } 12772 12773 function moveDraftLeft(key) { 12774 const location = findDraftLocation(key); 12775 if (!location || !location.parent) return; 12776 const parentLocation = findDraftLocation(location.parent.key); 12777 location.items.splice(location.index, 1); 12778 parentLocation.items.splice(parentLocation.index + 1, 0, location.item); 12779 } 12780 12781 function moveDraftRight(key) { 12782 const location = findDraftLocation(key); 12783 if (!location || location.index === 0 || location.item.depth >= MAX_DEPTH) return; 12784 const previousSibling = location.items[location.index - 1]; 12785 location.items.splice(location.index, 1); 12786 previousSibling.children.push(location.item); 12787 } 12788 12789 function removeDraftItem(key) { 12790 const location = findDraftLocation(key); 12791 if (!location) return; 12792 location.items.splice(location.index, 1); 12793 } 12794 12795 function reorderDraft(dragKey, targetKey) { 12796 if (!dragKey || dragKey === targetKey) return; 12797 const drag = findDraftLocation(dragKey); 12798 const target = findDraftLocation(targetKey); 12799 if (!drag || !target || drag.items !== target.items) return; 12800 drag.items.splice(drag.index, 1); 12801 const newTarget = findDraftLocation(targetKey); 12802 newTarget.items.splice(newTarget.index, 0, drag.item); 12803 } 12804 12805 function customRowsFromDraft() { 12806 recalculateDraft();
12807 return flattenDraft(local.customDraft).map(item => ({ 12808 'ITEM KEY': item.key, 12809 'PARENT KEY': item.parentKey || '', 12810 'PAGE NAME': item.label, 12811 SOURCE: item.source, 12812 TYPE: item.type, 12813 PRESENTATION: item.presentation, 12814 'MEGA GROUP': item.megaGroup, 12815 DEPTH: item.depth, 12816 ORDER: item.order, 12817 URL: item.url || '', 12818 'CANONICAL PATH': item.canonicalPath || '', 12819 SLUG: item.slug || '', 12820 TARGET: item.target || '_self', 12821 'IS EXTERNAL': item.isExternal, 12822 'SHOW ITEM': true 12823 })); 12824 } 12825 12826 function downloadText(filename, content, mime = 'text/plain') { 12827 const blob = new Blob([content], { type: `${mime};charset=utf-8` }); 12828 const url = URL.createObjectURL(blob); 12829 const anchor = document.createElement('a'); 12830 anchor.href = url; 12831 anchor.download = filename; 12832 document.body.appendChild(anchor); 12833 anchor.click(); 12834 anchor.remove(); 12835 URL.revokeObjectURL(url); 12836 } 12837 12838 function exportDraft(format) { 12839 const errors = validateDraft(); 12840 if (errors.length) { 12841 window.alert(`Fix these issues before exporting:\n\n${errors.join('\n')}`); 12842 return; 12843 } 12844 const rows = customRowsFromDraft(); 12845 if (format === 'json') { 12846 downloadText('CUSTOMNAV.json', JSON.stringify(rows, null, 2), 'application/json'); 12847 return; 12848 } 12849 if (format === 'payload') { 12850 downloadText('CUSTOMNAV-duda-payload.json', JSON.stringify({ data: rows }, null, 2), 'application/json'); 12851 return; 12852 } 12853 const headers = Object.keys(rows[0] || {}); 12854 const escapeCsv = value => `"${String(value == null ? '' : value).replace(/"/g, '""')}"`; 12855 const csv = [headers.map(escapeCsv).join(','), ...rows.map(row => headers.map(header => escapeCsv(row[header])).join(','))].join('\n'); 12856 downloadText('CUSTOMNAV.csv', csv, 'text/csv'); 12857 } 12858 12859 function attachBuilderInteractions(modal) { 12860 let draggedKey = ''; 12861 modal.addEventListener('dragstart', event => { 12862 const row = event.target.closest('[data-builder-key]'); 12863 if (!row) return; 12864 draggedKey = row.dataset.builderKey; 12865 event.dataTransfer.effectAllowed = 'move'; 12866 }); 12867 modal.addEventListener('dragover', event => { 12868 if (event.target.closest('[data-builder-key]')) event.preventDefault(); 12869 }); 12870 modal.addEventListener('drop', event => { 12871 const target = event.target.closest('[data-builder-key]'); 12872 if (!target) return; 12873 event.preventDefault(); 12874 reorderDraft(draggedKey, target.dataset.builderKey); 12875 refreshBuilder(modal, 'Draft reordered.'); 12876 }); 12877 modal.addEventListener('click', event => { 12878 const left = event.target.closest('[data-builder-left]'); 12879 const right = event.target.closest('[data-builder-right]'); 12880 const remove = event.target.closest('[data-builder-remove]'); 12881 if (left) { moveDraftLeft(left.dataset.key); refreshBuilder(modal, 'Item promoted.'); return; } 12882 if (right) { moveDraftRight(right.dataset.key); refreshBuilder(modal, 'Item demoted.'); return; } 12883 if (remove) { removeDraftItem(remove.dataset.key); refreshBuilder(modal, 'Item removed from draft.'); return; } 12884 if (event.target.closest('[data-builder-add]')) { addManualDraftItem(); refreshBuilder(modal, 'Manual item added.'); return; } 12885 if (event.target.closest('[data-builder-reset]')) { local.customDraft = draftSourceFromSharedModel(); refreshBuilder(modal, 'Draft reset.'); return; } 12886 if (event.target.closest('[data-builder-validate]')) { 12887 const errors = validateDraft(); 12888 refreshBuilder(modal, errors.length ? errors.join(' ') : 'Structure is valid.'); 12889 return; 12890 } 12891 const exportButton = event.target.closest('[data-builder-export]'); 12892 if (exportButton) exportDraft(exportButton.dataset.builderExport); 12893 }); 12894 } 12895 12896 function handleToolClick(event) { 12897 if (event.target.closest('[data-nmw-open-tree]')) openTreePreview(); 12898 if (event.target.closest('[data-nmw-open-builder]')) openBuilder(); 12899 } 12900 12901 function handleModalClick(event) { 12902 const backdrop = event.target.closest('.nmw-modal-backdrop'); 12903 if (!backdrop) return; 12904 if (event.target.matches('.nmw-modal-backdrop') || event.target.closest('[data-nm
12904w-close-modal]')) closeModal(); 12905 } 12906 12907 function handleModalKeydown(event) { 12908 if (event.key === 'Escape' && document.querySelector('.nmw-modal-backdrop')) closeModal(); 12909 } 12910 12911 // --------------------------------------------------------------------------- 12912 // Reset action hooks 12913 // --------------------------------------------------------------------------- 12914 12915 // Duda panel switches cannot directly erase saved panel values. These hooks 12916 // expose one-shot reset requests as data attributes/classes so the panel or a 12917 // future config migration can repopulate defaults without touching structure. 12918 function applyResetRequests() { 12919 if (readBoolean(configValueFrom(cfg, 'restoreFullDefaults'), false) && widgetMode === 'full') root.dataset.nmwRestoreDefaults = 'full-requested'; 12920 if (readBoolean(configValueFrom(cfg, 'restoreMirrorDefaults'), false) && widgetMode === 'mirror') root.dataset.nmwRestoreDefaults = 'mirror-requested'; 12921 } 12922 12923 // --------------------------------------------------------------------------- 12924 // Cleanup 12925 // --------------------------------------------------------------------------- 12926 12927 function cleanup(reason = 'removed') { 12928 if (local.cleaned) return; 12929 local.cleaned = true; 12930 clearTimeout(local.rebuildTimer); 12931 clearTimeout(local.nativeRetryTimer); 12932 local.hoverTimers.forEach(timer => clearTimeout(timer)); 12933 local.anchorTimers.forEach(timer => clearTimeout(timer)); 12934 local.anchorTimers.clear(); 12935 local.closeTimers.forEach(timer => clearTimeout(timer)); 12936 local.closeTimers.clear(); 12937 local.nativeObserver?.disconnect(); 12938 local.nativeFinderObserver?.disconnect(); 12939 local.manualObserver?.disconnect(); 12940 local.removalObserver?.disconnect(); 12941 if (typeof local.historyCleanup === 'function') local.historyCleanup(); 12942 local.eventCleanups.splice(0).forEach(remove => { 12943 try { remove(); } catch (error) {} 12944 }); 12945 window.removeEventListener('nmw:data-changed', handleMirrorDataChanged); 12946 window.removeEventListener('nmw:state-changed', handleSharedStateChanged); 12947 window.removeEventListener('nmw:url-changed', handleUrlChanged); 12948 window.removeEventListener('popstate', handleUrlChanged); 12949 window.removeEventListener('hashchange', handleUrlChanged); 12950 document.removeEventListener('pointerdown', handleOutsidePointer, true); 12951 document.removeEventListener('click', handleModalClick); 12952 document.removeEventListener('keydown', handleModalKeydown); 12953 toolsHost?.removeEventListener('click', handleToolClick); 12954 closeModal(); 12955 releaseOwnership(); 12956 12957 // Remove this closure only when it is still the registered lifecycle for 12958 // the root. A newer execution may already have replaced it. 12959 if (window.NMW_RUNTIME?.instances?.get(root) === cleanup) { 12960 window.NMW_RUNTIME.instances.delete(root); 12961 } 12962 12963 console.info('[NMW] Cleaned up instance', { widgetMode, instanceId, reason }); 12964 } 12965 12966 // Duda does not provide a universal destroy callback for all widget contexts, 12967 // so this observer performs cleanup if the widget root is removed. 12968 local.removalObserver = new MutationObserver(() => { 12969 if (!document.documentElement.contains(root)) { 12970 local.removalObserver.disconnect(); 12971 cleanup(); 12972 } 12973 }); 12974 local.removalObserver.observe(document.documentElement, { childList: true, subtree: true }); 12975 12976 // --------------------------------------------------------------------------- 12977 // Full and Mirror initialization 12978 // --------------------------------------------------------------------------- 12979 12980 function handleMirrorDataChanged() { 12981 if (widgetMode !== 'mirror') return; 12982 // Full may have changed Design Panel values without changing collection 12983 // structure. Refresh inherited Mirror classes and CSS variables before 12984 // rendering the shared model. 12985 applyDesignSettings('mirror'); 12986 renderNavigation(window.NMW.data || [], 'mirror'); 12987 updateRootStatus(); 12988 } 12989 12990 function handleSharedStateChanged() { 12991 updateRootStatus(); 12992 } 12993 12994 function initializeFull() { 12995 // This instance now owns the Full widget. Reset stale editor state left by 12996 // an interrupted prior execution, then rebuild with the current panel data. 12997 window.NMW.loading = false;
12998 applyDesignSettings('full'); 12999 applyResetRequests(); 13000 attachDelegatedInteractions(); 13001 attachManualSourceObserver(); 13002 beginNativeDiscovery(); 13003 local.historyCleanup = observeHistoryChanges(); 13004 listen(window, 'nmw:url-changed', handleUrlChanged); 13005 listen(window, 'popstate', handleUrlChanged); 13006 listen(window, 'hashchange', handleUrlChanged); 13007 if (toolsHost) listen(toolsHost, 'click', handleToolClick); 13008 listen(document, 'click', handleModalClick); 13009 listen(document, 'keydown', handleModalKeydown); 13010 scheduleRebuild(true); 13011 } 13012 13013 function initializeMirror() { 13014 applyDesignSettings('mirror'); 13015 applyResetRequests(); 13016 attachDelegatedInteractions(); 13017 local.historyCleanup = observeHistoryChanges(); 13018 listen(window, 'nmw:data-changed', handleMirrorDataChanged); 13019 listen(window, 'nmw:state-changed', handleSharedStateChanged); 13020 listen(window, 'nmw:url-changed', handleUrlChanged); 13021 listen(window, 'popstate', handleUrlChanged); 13022 listen(window, 'hashchange', handleUrlChanged); 13023 if (toolsHost) listen(toolsHost, 'click', handleToolClick); 13024 listen(document, 'click', handleModalClick); 13025 listen(document, 'keydown', handleModalKeydown); 13026 updateRootStatus(); 13027 if (window.NMW.ready) renderNavigation(window.NMW.data || [], 'mirror'); 13028 } 13029 13030 try { 13031 if (!claimOwnership()) return; 13032 root.dataset.nmwInstance = instanceId; 13033 13034 // Register this lifecycle only after ownership succeeds. The next Duda 13035 // panel execution on the same root will call this cleanup before starting. 13036 window.NMW_RUNTIME.instances.set(root, cleanup); 13037 console.info('[NMW] Initialized', { widgetMode, instanceId, renderHost }); 13038 updateRootStatus(); 13039 if (widgetMode === 'full') initializeFull(); 13040 else initializeMirror(); 13041 } catch (error) { 13042 console.error('[NMW] Startup failed', error); 13043 if (renderHost) { 13044 renderHost.innerHTML = `<div class="nmw-empty">Navigation startup failed: ${escapeHtml(error && error.message ? error.message : String(error))}</div>`; 13045 } 13046 } 13047}); 13048 }; 13049</script>
13049 13050
13051<script> 13052 window.customWidgetsFunctions["e0b1e5b2d4394e69a98bd276fd6afe8b~8"] = function (element, data, api) { 13053 window.dmAPI.runOnReady('HH1', () => { 13054 13055 const STYLE_ID = 'HH1-theme-style'; 13056 const HH1_SELECTOR = '.widget-wrapper.HH1'; 13057 13058 let updateTimer = null; 13059 let lastSignature = ''; 13060 13061 /** 13062 * Find a usable H1 that is NOT inside the HH1 widget. 13063 */ 13064 function findThemeH1() { 13065 const candidates = Array.from( 13066 document.querySelectorAll('#dm h1, h1') 13067 ); 13068 13069 for (const el of candidates) { 13070 13071 // Do not use our own HH1 widget as the source 13072 if (el.closest(HH1_SELECTOR)) { 13073 continue; 13074 } 13075 13076 // Ignore disconnected elements 13077 if (!el.isConnected) { 13078 continue; 13079 } 13080 13081 const computed = window.getComputedStyle(el); 13082 13083 // Ignore elements that are completely unavailable 13084 if ( 13085 computed.display === 'none' || 13086 computed.visibility === 'hidden' 13087 ) { 13088 continue; 13089 } 13090 13091 // Make sure we actually got useful typography 13092 if (!computed.fontFamily || !computed.fontSize) { 13093 continue; 13094 } 13095 13096 return el; 13097 } 13098 13099 return null; 13100 } 13101 13102 13103 /** 13104 * Read H1 typography and apply it to HH1 widgets. 13105 */ 13106 function applyTheme() { 13107 13108 const h1Sample = findThemeH1(); 13109 13110 if (!h1Sample) { 13111 return false; 13112 } 13113 13114 const computed = window.getComputedStyle(h1Sample); 13115 13116 const styles = { 13117 fontFamily: computed.fontFamily, 13118 fontSize: computed.fontSize, 13119 fontWeight: computed.fontWeight, 13120 lineHeight: computed.lineHeight, 13121 letterSpacing: computed.letterSpacing, 13122 textTransform: computed.textTransform, 13123 fontStyle: computed.fontStyle, 13124 fontVariant: computed.fontVariant, 13125 fontStretch: computed.fontStretch 13126 }; 13127 13128 /* 13129 * Create a signature so we're not constantly rewriting 13130 * the stylesheet when nothing has actually changed. 13131 */ 13132 const signature = JSON.stringify(styles); 13133 13134 if (signature === lastSignature) { 13135 return true; 13136 } 13137 13138 lastSignature = signature; 13139 13140 13141 /* 13142 * Target the widget plus all common Duda RTE descendants. 13143 * The wildcard selector is intentional so inline/nested 13144 * typography cannot override the inherited H1 theme. 13145 */ 13146 const selectors = [ 13147 '#dm .dmInner .widget-wrapper.HH1 .dmNewParagraph', 13148 '#dm .dmInner .widget-wrapper.HH1 .dmNewParagraph p', 13149 '#dm .dmInner .widget-wrapper.HH1 .dmNewParagraph span', 13150 '#dm .dmInner .widget-wrapper.HH1 .dmNewParagraph .rteBlock', 13151 '#dm .dmInner .widget-wrapper.HH1 .dmNewParagraph .rteBlock *', 13152 13153 '.dmInner .widget-wrapper.HH1 .dmNewParagraph', 13154 '.dmInner .widget-wrapper.HH1 .dmNewParagraph p', 13155 '.dmInner .widget-wrapper.HH1 .dmNewParagraph span', 13156 '.dmInner .widget-wrapper.HH1 .dmNewParagraph .rteBlock', 13157 '.dmInner .widget-wrapper.HH1 .dmNewParagraph .rteBlock *', 13158 13159 '.widget-wrapper.HH1 .dmNewParagraph', 13160 '.widget-wrapper.HH1 .dmNewParagraph p', 13161 '.widget-wrapper.HH1 .dmNewParagraph span', 13162 '.widget-wrapper.HH1 .dmNewParagraph .rteBlock', 13163 '.widget-wrapper.HH1 .dmNewParagraph .rteBlock *' 13164 ]; 13165 13166 const css = ` 13167${selectors.join(',\n')} { 13168 font-family: ${styles.fontFamily} !important; 13169 font-size: ${styles.fontSize} !important; 13170 font-weight: ${styles.fontWeight} !important; 13171 line-height: ${styles.lineHeight} !important; 13172 letter-spacing: ${styles.letterSpacing} !important; 13173 text-transform: ${styles.textTransform} !important; 13174 font-style: ${styles.fontStyle} !important; 13175 font-variant: ${styles.fontVariant} !important; 13176 font-stretch: ${styles.fontStretch} !important; 13177} 13178`; 13179 13180 let styleTag = document.getElementById(STYLE_ID); 13181 13182 if (!styleTag) { 13183 styleTag = document.createElement('style'); 13184 styleTag.id = STYLE_ID; 13185 styleTag.setAttribute('data-HH1', 'true'); 13186 document.head.appendChild(styleTag); 13187 } 13188 13189 styleTag.textContent = css; 13190 13191 return true; 13192 } 13193 13194 13195 /** 13196 * Debounce updates so Duda can make several DOM changes 13197 * without us recalculating after every individual mutation. 13198 */ 13199 function scheduleUpdate(delay = 100) { 13200 13201 clearTimeout(updateTimer); 13202 13203 updateTimer = setTimeout(() => { 13204 applyTheme(); 13205 }, delay); 13206 } 13207 13208 13209 /** 13210 * INITIAL LOAD 13211 * 13212 * Run several times because Duda/theme/font loading can occur 13213 * after dmAPI.runOnReady(). 13214 */ 13215 applyTheme(); 13216 13217 setTimeout(applyTheme, 250); 13218 setTimeout(applyTheme, 500); 13219 setTimeout(applyTheme, 1000); 13220 setTimeout(applyTheme, 2000); 13221 setTimeout(applyTheme, 4000); 13222 13223 13224 /** 13225 * WATCH DUDA DOM CHANGES 13226 * 13227 * Dynamic collections, responsive rendering, widgets, and 13228 * editor/preview changes can alter the page after initial load. 13229 */ 13230 const observer = new MutationObserver((mutations) => { 13231 13232 let relevantChange = false;
13233 13234 for (const mutation of mutations) { 13235 13236 /* 13237 * Ignore mutations caused only by our own style tag. 13238 */ 13239 if ( 13240 mutation.target && 13241 ( 13242 mutation.target.id === STYLE_ID || 13243 mutation.target.closest?.(`#${STYLE_ID}`) 13244 ) 13245 ) { 13246 continue; 13247 } 13248 13249 relevantChange = true; 13250 break; 13251 } 13252 13253 if (relevantChange) { 13254 scheduleUpdate(150); 13255 } 13256 13257 }); 13258 13259 observer.observe(document.body, { 13260 childList: true, 13261 subtree: true, 13262 attributes: true, 13263 attributeFilter: [ 13264 'class', 13265 'style' 13266 ] 13267 }); 13268 13269 13270 /** 13271 * RESPONSIVE CHANGES 13272 * 13273 * H1 typography may change between desktop/tablet/mobile. 13274 */ 13275 window.addEventListener('resize', () => { 13276 scheduleUpdate(150); 13277 }); 13278 13279 13280 /** 13281 * ORIENTATION CHANGE 13282 */ 13283 window.addEventListener('orientationchange', () => { 13284 scheduleUpdate(250); 13285 }); 13286 13287 13288 /** 13289 * FONT LOADING 13290 * 13291 * Reapply after web fonts finish loading. 13292 */ 13293 if (document.fonts && document.fonts.ready) { 13294 13295 document.fonts.ready.then(() => { 13296 13297 // Force refresh even if we previously captured fallback font 13298 lastSignature = ''; 13299 13300 applyTheme(); 13301 13302 }).catch(() => { 13303 // Nothing required 13304 }); 13305 13306 } 13307 13308}); 13309 }; 13310</script>
13310 13311
13312<script> 13313 window.customWidgetsFunctions["f19f9b2806104edb81a7816f71967887~13"] = function (element, data, api) { 13314 window.dmAPI.runOnReady('copy-block-link-widget', async () => { 13315 const anchor = element.querySelector('.copy-block-link-anchor'); 13316 const buttonElement = element.querySelector('.copy-block-link-button'); 13317 13318 if (!anchor || !buttonElement) return; 13319 13320 const config = data.config || {}; 13321 13322 function safeTrim(value) { 13323 return value == null ? '' : String(value).trim(); 13324 } 13325 13326 function stripHtml(value) { 13327 const temporaryElement = document.createElement('div'); 13328 temporaryElement.innerHTML = safeTrim(value); 13329 13330 return safeTrim( 13331 temporaryElement.textContent || 13332 temporaryElement.innerText || 13333 '' 13334 ); 13335 } 13336 13337 function removeDiacritics(value) { 13338 const text = safeTrim(value); 13339 13340 if (typeof text.normalize !== 'function') { 13341 return text; 13342 } 13343 13344 return text 13345 .normalize('NFKD') 13346 .replace(/[\u0300-\u036f]/g, ''); 13347 } 13348 13349 function slugify(value) { 13350 return removeDiacritics(value) 13351 .toLowerCase() 13352 .replace(/[â']/g, '') 13353 .replace(/[^a-z0-9]+/g, '-') 13354 .replace(/-+/g, '-') 13355 .replace(/^-+|-+$/g, ''); 13356 } 13357 13358 /* 13359 Creates possible URL versions. 13360 13361 Showers & Doors: 13362 - showers-and-doors 13363 - showers-doors 13364 13365 Showers and Doors: 13366 - showers-and-doors 13367 - showers-doors 13368 13369 A/C Repair: 13370 - a-c-repair 13371 - ac-repair 13372 */ 13373 function createSlugCandidates(value) { 13374 const originalText = stripHtml(value); 13375 const candidates = []; 13376 const seen = new Set(); 13377 13378 function addCandidate(candidateText) { 13379 const candidate = slugify(candidateText); 13380 13381 if (candidate && !seen.has(candidate)) { 13382 seen.add(candidate); 13383 candidates.push(candidate); 13384 } 13385 } 13386 13387 if (!originalText) { 13388 return candidates; 13389 } 13390 13391 const ampersandVariants = [ 13392 originalText.replace(/&/g, ' and '), 13393 originalText.replace(/&/g, ' '), 13394 originalText 13395 ]; 13396
13397 ampersandVariants.forEach(ampersandVariant => { 13398 const andVariants = [ 13399 ampersandVariant, 13400 ampersandVariant.replace(/\band\b/gi, ' ') 13401 ]; 13402 13403 andVariants.forEach(andVariant => { 13404 /* 13405 Treat the slash as a separator. 13406 13407 A/C Repair becomes a-c-repair. 13408 */ 13409 addCandidate( 13410 andVariant.replace(/\s*[\\/]+\s*/g, ' ') 13411 ); 13412 13413 /* 13414 Remove the slash completely. 13415 13416 A/C Repair becomes ac-repair. 13417 */ 13418 addCandidate( 13419 andVariant.replace(/\s*[\\/]+\s*/g, '') 13420 ); 13421 }); 13422 }); 13423 13424 return candidates; 13425 } 13426 13427 /* 13428 Accepts any of these page_item_url formats: 13429 13430 college-transcripts 13431 /category/college-transcripts/ 13432 https://example.com/category/college-transcripts/ 13433 */ 13434 function normalizeStoredSlug(value) { 13435 let slug = safeTrim(value); 13436 13437 if (!slug) return ''; 13438 13439 try { 13440 slug = decodeURIComponent(slug); 13441 } catch (e) { 13442 // Keep the original value. 13443 } 13444 13445 slug = slug 13446 .split('#')[0] 13447 .split('?')[0] 13448 .replace(/^https?:\/\/[^/]+/i, '') 13449 .replace(/^\/+|\/+$/g, ''); 13450 13451 if (slug.includes('/')) { 13452 slug = slug 13453 .split('/') 13454 .filter(Boolean) 13455 .pop() || ''; 13456 } 13457 13458 return safeTrim(slug).toLowerCase(); 13459 } 13460 13461 function getCurrentSlug() { 13462 const pathParts = (window.location.pathname || '') 13463 .split('/') 13464 .filter(Boolean); 13465 13466 return normalizeStoredSlug( 13467 pathParts.pop() || '' 13468 ); 13469 } 13470 13471 /* 13472 Checks several properties when finding the source row. 13473 13474 page_item_url is preferred, but the other values help 13475 with differences in Duda collection response structures. 13476 */ 13477 function getSourceEntrySlugs(entry) { 13478 if (!entry) return []; 13479 13480 const row = entry.data || {}; 13481 13482 return [ 13483 entry.page_item_url, 13484 row.page_item_url, 13485 entry.item, 13486 row.item, 13487 entry.name, 13488 row.name, 13489 entry.url, 13490 row.url 13491 ] 13492 .map(normalizeStoredSlug) 13493 .filter(Boolean); 13494 } 13495 13496 /* 13497 Destination pages must match page_item_url. 13498 */ 13499 function getDestinationEntrySlugs(entry) { 13500 if (!entry) return []; 13501 13502 const row = entry.data || {}; 13503 13504 return [ 13505 entry.page_item_url, 13506 row.page_item_url 13507 ] 13508 .map(normalizeStoredSlug) 13509 .filter(Boolean); 13510 } 13511 13512 function findSourceEntry( 13513 entries, 13514 currentSlug, 13515 sourcePageType 13516 ) { 13517 if ( 13518 !Array.isArray(entries) || 13519 entries.length === 0 13520 ) { 13521 return null; 13522 } 13523 13524 /* 13525 Match the current page slug when possible. 13526 */ 13527 if ( 13528 currentSlug && 13529 currentSlug !== '~page-item~' 13530 ) { 13531 const matchedEntry = entries.find(entry => 13532 getSourceEntrySlugs(entry).includes( 13533 currentSlug 13534 ) 13535 ); 13536 13537 if (matchedEntry) { 13538 return matchedEntry; 13539 } 13540 } 13541 13542 /* 13543 01 HOME is expected to have one row. 13544 13545 Only Home Page mode may use the first row. 13546 Category Page mode must match the current slug. 13547 */ 13548 if (sourcePageType === 'home') { 13549 return entries[0]; 13550 } 13551 13552 return null; 13553 } 13554 13555 function findDestination( 13556 entries, 13557 slugCandidates 13558 ) { 13559 if ( 13560 !Array.isArray(entries) || 13561 !Array.isArray(slugCandidates) 13562 ) { 13563 return null; 13564 } 13565 13566 /* 13567 Candidate order is preserved. 13568 13569 This means the more natural slug is checked before 13570 alternate ampersand and slash versions. 13571 */ 13572 for (const candidate of slugCandidates) { 13573 const matchedEntry = entries.find(entry => 13574 getDestinationEntrySlugs(entry).includes( 13575 candidate 13576 ) 13577 ); 13578 13579 if (matchedEntry) { 13580 return { 13581 entry: matchedEntry, 13582 slug: candidate 13583 }; 13584 } 13585 } 13586 13587 return null; 13588 } 13589 13590 function cleanPrefix(value, fallbackValue) { 13591 const configuredValue = safeTrim(value); 13592 const prefix = 13593 configuredValue || fallbackValue; 13594 13595 return safeTrim(prefix) 13596 .replace(/^\/+|\/+$/g, ''); 13597 } 13598 13599 function getSitePrefixFromOwnFrame() { 13600 const ownPath = 13601 window.location.pathname || ''; 13602 13603 const match = ownPath.match( 13604 /^(\/site\/[^/]+)/ 13605 ); 13606 13607 return match ? match[1] : ''; 13608 } 13609 13610 function getPreviewQueryString() { 13611 try { 13612 const currentParameters = 13613 new URLSearchParams( 13614 window.location.search || '' 13615 ); 13616 13617 const outputParameters = 13618 new URLSearchParams(); 13619 13620 [ 13621 'showOriginal', 13622 'preview', 13623 'insitepreview', 13624 'dm_device', 13625 't', 13626 'dm_try_mode', 13627 'dm_checkSync' 13628 ].forEach(key => { 13629 if (currentParameters.has(key)) { 13630 outputParameters.set( 13631 key, 13632 currentParameters.get(key) 13633 ); 13634 } 13635 }); 13636 13637 const queryString = 13638 outputParameters.toString(); 13639 13640 return queryString 13641 ? '?' + queryString 13642 : ''; 13643 } catch (e) { 13644 return ''; 13645 } 13646 } 13647 13648 /* 13649 Block navigation only in the normal editor canvas. 13650 13651 Navigation remains available in: 13652 - Editor Preview 13653 - Preview links 13654 - Published websites 13655 */ 13656 function isEditorCanvasOnly() { 13657 if (!data.inEditor) { 13658 return false;
13659 } 13660 13661 try { 13662 const topHref = 13663 window.top.location.href || ''; 13664 13665 if (topHref.includes('#preview')) { 13666 return false; 13667 } 13668 13669 return true; 13670 } catch (e) { 13671 return true; 13672 } 13673 } 13674 13675 function setPendingState() { 13676 anchor.removeAttribute('href'); 13677 anchor.setAttribute( 13678 'aria-disabled', 13679 'true' 13680 ); 13681 anchor.setAttribute( 13682 'aria-busy', 13683 'true' 13684 ); 13685 anchor.setAttribute( 13686 'tabindex', 13687 '-1' 13688 ); 13689 13690 anchor.classList.remove('is-disabled'); 13691 buttonElement.classList.remove( 13692 'is-disabled' 13693 ); 13694 } 13695 13696 function disableButton() { 13697 anchor.removeAttribute('href'); 13698 anchor.setAttribute( 13699 'aria-disabled', 13700 'true' 13701 ); 13702 anchor.setAttribute( 13703 'aria-busy', 13704 'false' 13705 ); 13706 anchor.setAttribute( 13707 'tabindex', 13708 '-1' 13709 ); 13710 13711 anchor.classList.add('is-disabled'); 13712 buttonElement.classList.add( 13713 'is-disabled' 13714 ); 13715 } 13716 13717 function enableButton(destination) { 13718 anchor.setAttribute( 13719 'href', 13720 destination 13721 ); 13722 13723 anchor.setAttribute( 13724 'aria-disabled', 13725 'false' 13726 ); 13727 13728 anchor.setAttribute( 13729 'aria-busy', 13730 'false' 13731 ); 13732 13733 anchor.removeAttribute('tabindex'); 13734 13735 anchor.classList.remove('is-disabled'); 13736 buttonElement.classList.remove( 13737 'is-disabled' 13738 ); 13739 } 13740 13741 /* 13742 Use one click handler for both disabled-state 13743 protection and editor-canvas protection. 13744 */ 13745 anchor.addEventListener( 13746 'click', 13747 event => { 13748 const isDisabled = 13749 anchor.getAttribute( 13750 'aria-disabled' 13751 ) === 'true'; 13752 13753 if ( 13754 isDisabled || 13755 isEditorCanvasOnly() 13756 ) { 13757 event.preventDefault(); 13758 event.stopPropagation(); 13759 event.stopImmediatePropagation(); 13760 13761 return false; 13762 } 13763 }, 13764 true 13765 ); 13766 13767 /* 13768 Share collection requests between multiple copies 13769 of this widget on the same page. 13770 */ 13771 function getCollectionCache() { 13772 if ( 13773 !window.__copyBlockLinkCollectionCache 13774 ) { 13775 window.__copyBlockLinkCollectionCache = 13776 {}; 13777 } 13778 13779 return window 13780 .__copyBlockLinkCollectionCache; 13781 } 13782 13783 function getCollectionsApiPromise() { 13784 if ( 13785 !window.__copyBlockLinkCollectionsApiPromise 13786 ) { 13787 window 13788 .__copyBlockLinkCollectionsApiPromise = 13789 dmAPI 13790 .loadCollectionsAPI() 13791 .catch(error => { 13792 delete window 13793 .__copyBlockLinkCollectionsApiPromise; 13794 13795 throw error; 13796 }); 13797 } 13798 13799 return window 13800 .__copyBlockLinkCollectionsApiPromise; 13801 } 13802 13803 function loadCollectionEntries( 13804 collectionName 13805 ) { 13806 const collectionCache = 13807 getCollectionCache(); 13808 13809 if (!collectionCache[collectionName]) { 13810 collectionCache[collectionName] = 13811 getCollectionsApiPromise() 13812 .then(async collectionApi => { 13813 const PAGE_SIZE = 100; 13814 const MAX_RECORDS = 200; 13815 13816 async function getPage(pageNumber) { 13817 let request = 13818 collectionApi 13819 .data(collectionName); 13820 13821 if ( 13822 request && 13823 typeof request.pageSize === 'function' 13824 ) { 13825 request = 13826 request.pageSize(PAGE_SIZE); 13827 } 13828 13829 if ( 13830 request && 13831 typeof request.pageNumber === 'function' 13832 ) { 13833 request = 13834 request.pageNumber(pageNumber); 13835 } 13836 13837 const result = 13838 await request.get(); 13839 13840 return Array.isArray( 13841 result && result.values 13842 ) 13843 ? result.values 13844 : []; 13845 } 13846 13847 /* 13848 Duda collection pages are capped at 100 records. 13849 13850 Load page 0 first. If it is full, load page 1 and 13851 combine both pages so this widget can search up to 13852 200 records. 13853 */ 13854 const firstPage = 13855 await getPage(0); 13856 13857 let entries = 13858 [...firstPage]; 13859 13860 if ( 13861 firstPage.length === PAGE_SIZE &&
13862 entries.length < MAX_RECORDS 13863 ) { 13864 const secondPage = 13865 await getPage(1); 13866 13867 entries = 13868 entries.concat(secondPage); 13869 } 13870 13871 return entries.slice( 13872 0, 13873 MAX_RECORDS 13874 ); 13875 }) 13876 .catch(error => { 13877 delete collectionCache[ 13878 collectionName 13879 ]; 13880 13881 throw error; 13882 }); 13883 } 13884 13885 return collectionCache[ 13886 collectionName 13887 ]; 13888 } 13889 13890 setPendingState(); 13891 13892 const buttonName = 13893 safeTrim(config.buttonName) || 13894 'Learn More'; 13895 13896 anchor.setAttribute( 13897 'aria-label', 13898 buttonName 13899 ); 13900 13901 try { 13902 /* 13903 Accepted Page Type values: 13904 13905 home 13906 Home Page 13907 category 13908 Category Page 13909 */ 13910 const sourcePageTypeValue = 13911 safeTrim( 13912 config.sourcePageType 13913 ).toLowerCase(); 13914 13915 const sourcePageType = 13916 sourcePageTypeValue === 'category' || 13917 sourcePageTypeValue === 13918 'category page' 13919 ? 'category' 13920 : 'home'; 13921 13922 const sourceCollectionName = 13923 sourcePageType === 'category' 13924 ? '02 CATEGORY' 13925 : '01 HOME'; 13926 13927 const currentSlug = 13928 getCurrentSlug(); 13929 13930 /* 13931 Load the source collection. 13932 */ 13933 const sourceEntries = 13934 await loadCollectionEntries( 13935 sourceCollectionName 13936 ); 13937 13938 const sourceEntry = 13939 findSourceEntry( 13940 sourceEntries, 13941 currentSlug, 13942 sourcePageType 13943 ); 13944 13945 if (!sourceEntry) { 13946 disableButton(); 13947 return; 13948 } 13949 13950 /* 13951 Accepts either: 13952 13953 1 13954 COPY BLOCK HEADLINE 1 13955 COPY BLOCK 1 HEADLINE 13956 */ 13957 const configuredBlockValue = 13958 safeTrim( 13959 config.copyBlockNumber 13960 ); 13961 13962 const blockNumberMatch = 13963 configuredBlockValue.match( 13964 /(?:^|\D)(10|[1-9])(?:\D|$)/ 13965 ); 13966 13967 const blockNumber = 13968 blockNumberMatch 13969 ? blockNumberMatch[1] 13970 : '1'; 13971 13972 const fieldName = 13973 'COPY BLOCK ' + 13974 blockNumber + 13975 ' HEADLINE'; 13976 13977 const sourceRow = 13978 sourceEntry.data || 13979 sourceEntry; 13980 13981 const rawHeadline = 13982 sourceRow[fieldName]; 13983 13984 const slugCandidates = 13985 createSlugCandidates( 13986 rawHeadline 13987 ); 13988 13989 if ( 13990 slugCandidates.length === 0 13991 ) { 13992 disableButton(); 13993 return; 13994 } 13995 13996 /* 13997 Load both possible destination collections. 13998 13999 Reuse 02 CATEGORY if it was already loaded 14000 as the source collection. 14001 */ 14002 const categoryEntriesPromise = 14003 sourceCollectionName === 14004 '02 CATEGORY' 14005 ? Promise.resolve(sourceEntries) 14006 : loadCollectionEntries( 14007 '02 CATEGORY' 14008 ).catch(() => []); 14009 14010 const coreEntriesPromise = 14011 loadCollectionEntries( 14012 '03 CORE' 14013 ).catch(() => []); 14014 14015 const [ 14016 categoryEntries, 14017 coreEntries 14018 ] = await Promise.all([ 14019 categoryEntriesPromise, 14020 coreEntriesPromise 14021 ]); 14022 14023 const categoryPrefix = 14024 cleanPrefix( 14025 config.categoryPrefix, 14026 'category' 14027 ); 14028 14029 const corePrefix = 14030 cleanPrefix( 14031 config.corePrefix, 14032 'core' 14033 ); 14034 14035 /* 14036 Home Page destination priority: 14037 14038 1. 02 CATEGORY 14039 2. 03 CORE 14040 14041 Category Page destination priority: 14042 14043 1. 03 CORE 14044 2. 02 CATEGORY 14045 */ 14046 const destinationSearchOrder = 14047 sourcePageType === 'home' 14048 ? [ 14049 { 14050 entries: 14051 categoryEntries, 14052 prefix: 14053 categoryPrefix 14054 }, 14055 { 14056 entries: 14057 coreEntries, 14058 prefix: 14059 corePrefix 14060 } 14061 ] 14062 : [ 14063 { 14064 entries: 14065 coreEntries, 14066 prefix: 14067 corePrefix 14068 }, 14069 { 14070 entries: 14071 categoryEntries, 14072 prefix: 14073 categoryPrefix 14074 } 14075 ]; 14076 14077 let destinationMatch = null; 14078 let destinationPrefix = ''; 14079 14080 for ( 14081 const destinationCollection 14082 of destinationSearchOrder 14083 ) { 14084 const match = 14085 findDestination( 14086 destinationCollection.entries, 14087 slugCandidates 14088 ); 14089 14090 if (match) { 14091 destinationMatch = match; 14092 destinationPrefix = 14093 destinationCollection.prefix; 14094 14095 break; 14096 } 14097 } 14098 14099 /* 14100 Never create an unverified URL. 14101 14102 The generated slug must exist as a 14103 page_item_url in 02 CATEGORY or 03 CORE. 14104 */ 14105 if ( 14106 !destinationMatch || 14107 !destinationMatch.slug 14108 ) { 14109 disableButton(); 14110 return; 14111 } 14112 14113 const destinationPath = 14114 '/' + 14115 [ 14116 destinationPrefix, 14117 destinationMatch.slug 14118 ] 14119 .filter(Boolean) 14120 .join('/') + 14121 '/'; 14122 14123 const destination = 14124 getSitePrefixFromOwnFrame() + 14125 destinationPath + 14126 getPreviewQueryString(); 14127 14128 enableButton( 14129 destination || destinationPath 14130 ); 14131 } catch (e) { 14132 disableButton(); 14133 } 14134}); 14135 }; 14136</script>
14136 14137
14138<script> 14139 window.customWidgetsFunctions["9015bcbf1ace437aa6f0e66d5bb2e7d3~25"] = function (element, data, api) { 14140 $(document).ready(function(){ 14141 $.getScript('https://widget.hibu.us/static/js/index.js') 14142 //$.getScript('//survlywidget-uat.firebaseapp.com/static/js/index.js') 14143 .done(function(){ 14144 dmAPI.runOnReady('hibu_header_reviews',function(){ 14145 window.renderApp(); 14146 }); 14147 14148 }) 14149 .fail(function(){ 14150 console.log("failed to load header reviews js file") 14151 }); 14152 14153 element.children[0].removeAttribute(`rteblock"`) 14154 var merchantId = data.config.merchantId 14155 merchantId = merchantId.replace(/<p.*?>/g, '') 14156 merchantId = merchantId.replace(/"/g, '"') 14157 merchantId = merchantId.replace(/\<\/p\>/g, '') 14158 14159 element.children[0].setAttribute('data-merchant', merchantId) 14160}) 14161 14162 14163 }; 14164</script>
14164 14165
14166<script> 14167 window.customWidgetsFunctions["2133bfee2cb24e0c9db9468154881b94~3"] = function (element, data, api) { 14168 window.dmAPI.runOnReady('HH2', () => { 14169 14170 const STYLE_ID = 'HH2-theme-style'; 14171 const HH2_SELECTOR = '.widget-wrapper.HH2'; 14172 14173 let updateTimer = null; 14174 let lastSignature = ''; 14175 14176 /** 14177 * Find a usable H2 that is NOT inside the HH2 widget. 14178 */ 14179 function findThemeH2() { 14180 const candidates = Array.from( 14181 document.querySelectorAll('#dm h2, h2') 14182 ); 14183 14184 for (const el of candidates) { 14185 14186 // Do not use our own HH2 widget as the source 14187 if (el.closest(HH2_SELECTOR)) { 14188 continue; 14189 } 14190 14191 // Ignore disconnected elements 14192 if (!el.isConnected) { 14193 continue; 14194 } 14195 14196 const computed = window.getComputedStyle(el); 14197 14198 // Ignore elements that are completely unavailable 14199 if ( 14200 computed.display === 'none' || 14201 computed.visibility === 'hidden' 14202 ) { 14203 continue; 14204 } 14205 14206 // Make sure we actually got useful typography 14207 if (!computed.fontFamily || !computed.fontSize) { 14208 continue; 14209 } 14210 14211 return el; 14212 } 14213 14214 return null; 14215 } 14216 14217 14218 /** 14219 * Read H2 typography and apply it to HH2 widgets. 14220 */ 14221 function applyTheme() { 14222 14223 const h2Sample = findThemeH2(); 14224 14225 if (!h2Sample) { 14226 return false; 14227 } 14228 14229 const computed = window.getComputedStyle(h2Sample); 14230 14231 const styles = { 14232 fontFamily: computed.fontFamily, 14233 fontSize: computed.fontSize, 14234 fontWeight: computed.fontWeight, 14235 lineHeight: computed.lineHeight, 14236 letterSpacing: computed.letterSpacing, 14237 textTransform: computed.textTransform, 14238 fontStyle: computed.fontStyle, 14239 fontVariant: computed.fontVariant, 14240 fontStretch: computed.fontStretch 14241 }; 14242 14243 /* 14244 * Create a signature so we're not constantly rewriting 14245 * the stylesheet when nothing has actually changed. 14246 */ 14247 const signature = JSON.stringify(styles); 14248 14249 if (signature === lastSignature) { 14250 return true; 14251 } 14252 14253 lastSignature = signature; 14254 14255 14256 /* 14257 * Target the widget plus all common Duda RTE descendants. 14258 * The wildcard selector is intentional so inline/nested 14259 * typography cannot override the inherited H2 theme. 14260 */ 14261 const selectors = [ 14262 '#dm .dmInner .widget-wrapper.HH2 .dmNewParagraph', 14263 '#dm .dmInner .widget-wrapper.HH2 .dmNewParagraph p', 14264 '#dm .dmInner .widget-wrapper.HH2 .dmNewParagraph span', 14265 '#dm .dmInner .widget-wrapper.HH2 .dmNewParagraph .rteBlock', 14266 '#dm .dmInner .widget-wrapper.HH2 .dmNewParagraph .rteBlock *', 14267 14268 '.dmInner .widget-wrapper.HH2 .dmNewParagraph', 14269 '.dmInner .widget-wrapper.HH2 .dmNewParagraph p', 14270 '.dmInner .widget-wrapper.HH2 .dmNewParagraph span', 14271 '.dmInner .widget-wrapper.HH2 .dmNewParagraph .rteBlock', 14272 '.dmInner .widget-wrapper.HH2 .dmNewParagraph .rteBlock *', 14273 14274 '.widget-wrapper.HH2 .dmNewParagraph', 14275 '.widget-wrapper.HH2 .dmNewParagraph p', 14276 '.widget-wrapper.HH2 .dmNewParagraph span', 14277 '.widget-wrapper.HH2 .dmNewParagraph .rteBlock', 14278 '.widget-wrapper.HH2 .dmNewParagraph .rteBlock *' 14279 ]; 14280 14281 const css = ` 14282${selectors.join(',\n')} { 14283 font-family: ${styles.fontFamily} !important; 14284 font-size: ${styles.fontSize} !important; 14285 font-weight: ${styles.fontWeight} !important; 14286 line-height: ${styles.lineHeight} !important; 14287 letter-spacing: ${styles.letterSpacing} !important; 14288 text-transform: ${styles.textTransform} !important; 14289 font-style: ${styles.fontStyle} !important; 14290 font-variant: ${styles.fontVariant} !important; 14291 font-stretch: ${styles.fontStretch} !important; 14292} 14293`; 14294 14295 let styleTag = document.getElementById(STYLE_ID); 14296 14297 if (!styleTag) { 14298 styleTag = document.createElement('style'); 14299 styleTag.id = STYLE_ID; 14300 styleTag.setAttribute('data-HH2', 'true'); 14301 document.head.appendChild(styleTag); 14302 } 14303 14304 styleTag.textContent = css; 14305 14306 return true; 14307 } 14308 14309 14310 /** 14311 * Debounce updates so Duda can make several DOM changes 14312 * without us recalculating after every individual mutation. 14313 */ 14314 function scheduleUpdate(delay = 100) { 14315 14316 clearTimeout(updateTimer); 14317 14318 updateTimer = setTimeout(() => { 14319 applyTheme(); 14320 }, delay); 14321 } 14322 14323 14324 /** 14325 * INITIAL LOAD 14326 * 14327 * Run several times because Duda/theme/font loading can occur 14328 * after dmAPI.runOnReady(). 14329 */ 14330 applyTheme(); 14331 14332 setTimeout(applyTheme, 250); 14333 setTimeout(applyTheme, 500); 14334 setTimeout(applyTheme, 1000); 14335 setTimeout(applyTheme, 2000); 14336 setTimeout(applyTheme, 4000); 14337 14338 14339 /** 14340 * WATCH DUDA DOM CHANGES 14341 */ 14342 const observer = new MutationObserver((mutations) => { 14343 14344 let relevantChange = false;
14345 14346 for (const mutation of mutations) { 14347 14348 /* 14349 * Ignore mutations caused only by our own style tag. 14350 */ 14351 if ( 14352 mutation.target && 14353 ( 14354 mutation.target.id === STYLE_ID || 14355 mutation.target.closest?.(`#${STYLE_ID}`) 14356 ) 14357 ) { 14358 continue; 14359 } 14360 14361 relevantChange = true; 14362 break; 14363 } 14364 14365 if (relevantChange) { 14366 scheduleUpdate(150); 14367 } 14368 14369 }); 14370 14371 observer.observe(document.body, { 14372 childList: true, 14373 subtree: true, 14374 attributes: true, 14375 attributeFilter: [ 14376 'class', 14377 'style' 14378 ] 14379 }); 14380 14381 14382 /** 14383 * RESPONSIVE CHANGES 14384 * 14385 * H2 typography may change between desktop/tablet/mobile. 14386 */ 14387 window.addEventListener('resize', () => { 14388 scheduleUpdate(150); 14389 }); 14390 14391 14392 /** 14393 * ORIENTATION CHANGE 14394 */ 14395 window.addEventListener('orientationchange', () => { 14396 scheduleUpdate(250); 14397 }); 14398 14399 14400 /** 14401 * FONT LOADING 14402 * 14403 * Reapply after web fonts finish loading. 14404 */ 14405 if (document.fonts && document.fonts.ready) { 14406 14407 document.fonts.ready.then(() => { 14408 14409 // Force refresh even if we previously captured fallback font 14410 lastSignature = ''; 14411 14412 applyTheme(); 14413 14414 }).catch(() => { 14415 // Nothing required 14416 }); 14417 14418 } 14419 14420}); 14421 }; 14422</script>
14422 14423
14424<script> 14425 window.customWidgetsFunctions["ca4188fe92024514a23a858f63ab6658~18"] = function (element, data, api) { 14426 null 14427 }; 14428</script>
14428 14429
14430<script> 14431 window.customWidgetsFunctions["c4b2f903d115403c8c21e9ec6044a4fe~59"] = function (element, data, api) { 14432 null 14433 }; 14434</script>
14434 14435
14436<script> 14437 window.customWidgetsFunctions["ab442ac754384e98a02c4f630b481f5e~9"] = function (element, data, api) { 14438 window.dmAPI.runOnReady('hide-section-if-category-field-empty', function () { 14439 14440 function getLastSlug(value) { 14441 if (!value) return ''; 14442 14443 value = String(value).trim().toLowerCase(); 14444 14445 try { 14446 if (value.indexOf('http://') === 0 || value.indexOf('https://') === 0) { 14447 value = new URL(value).pathname; 14448 } 14449 } catch (e) {} 14450 14451 value = value.split('?')[0].split('#')[0]; 14452 value = value.replace(/\/+$/, ''); 14453 14454 var parts = value.split('/'); 14455 return parts[parts.length - 1] || ''; 14456 } 14457 14458 function hasVisibleText(value) { 14459 if (value === null || value === undefined) { 14460 return false; 14461 } 14462 14463 var temporaryElement = document.createElement('div'); 14464 temporaryElement.innerHTML = String(value); 14465 14466 var text = 14467 temporaryElement.textContent || 14468 temporaryElement.innerText || 14469 ''; 14470 14471 text = text 14472 .replace(/\u00A0/g, ' ') 14473 .replace(/[\u200B-\u200D\uFEFF]/g, '') 14474 .trim(); 14475 14476 return text.length > 0; 14477 } 14478 14479 function getCurrentSection(marker) { 14480 return ( 14481 marker.closest('[data-layout-section]') || 14482 marker.closest('section.flex-element') || 14483 marker.closest("[data-page-element-type='section']") || 14484 marker.closest('.dmRespRow') || 14485 marker.closest('.flex-section') || 14486 marker.closest('section') 14487 ); 14488 } 14489 14490 function hideSectionForMarker(marker) { 14491 var section = getCurrentSection(marker); 14492 14493 if (section) { 14494 section.style.setProperty('display', 'none', 'important'); 14495 console.log('[HideSection] Section hidden:', section); 14496 } else { 14497 console.warn('[HideSection] Could not find parent section for marker:', marker); 14498 } 14499 } 14500 14501 function showSectionForMarker(marker) { 14502 var section = getCurrentSection(marker); 14503 14504 if (section) { 14505 section.style.removeProperty('display'); 14506 console.log('[HideSection] Section shown:', section); 14507 } 14508 } 14509 14510 function checkCollection(marker) { 14511 var collectionName = marker.getAttribute('data-collection-name') || '02 CATEGORY'; 14512 var requiredFieldName = marker.getAttribute('data-required-field') || 'COPY BLOCK 1 HEADLINE'; 14513 var currentSlug = getLastSlug(window.location.href); 14514 14515 console.log('[HideSection] Current slug:', currentSlug); 14516 console.log('[HideSection] Collection:', collectionName); 14517 console.log('[HideSection] Required field:', requiredFieldName); 14518 14519 if (!window.dmAPI || typeof dmAPI.loadCollectionsAPI !== 'function') { 14520 console.warn('[HideSection] Duda Collections API not available.'); 14521 return; 14522 } 14523 14524 dmAPI.loadCollectionsAPI() 14525 .then(function (collection) { 14526 return collection 14527 .data(collectionName) 14528 .pageSize(100) 14529 .get(); 14530 }) 14531 .then(function (result) { 14532 console.log('[HideSection] Raw result:', result); 14533 14534 var rows = []; 14535 14536 if (result && Array.isArray(result.values)) { 14537 rows = result.values; 14538 } else if (Array.isArray(result)) { 14539 rows = result; 14540 } 14541 14542 console.log('[HideSection] Total rows:', rows.length); 14543 14544 if (rows.length > 0) { 14545 console.log('[HideSection] First row dump:', rows[0]); 14546 console.log('[HideSection] First row keys:', Object.keys(rows[0] || {})); 14547 14548 if (rows[0] && rows[0].data) { 14549 console.log('[HideSection] First row data keys:', Object.keys(rows[0].data || {})); 14550 } 14551 } 14552 14553 var matchingRow = null; 14554 14555 if (collectionName === '01 HOME') { 14556 matchingRow = rows[0] || null; 14557 14558 if (matchingRow) { 14559 console.log('[HideSection] 01 HOME detected â using first row:', matchingRow); 14560 } else { 14561 console.warn('[HideSection] 01 HOME detected, but no rows were found.'); 14562 } 14563 14564 } else { 14565 14566 for (var i = 0; i < rows.length; i++) { 14567 var row = rows[i]; 14568 var rowData = row.data || row; 14569 14570 var rawSlugValue = 14571 row.page_item_url || 14572 rowData.page_item_url || 14573 rowData['page_item_url'] || 14574 rowData['item'] || 14575 rowData['slug'] || 14576 row.item || 14577 row.slug || 14578 ''; 14579 14580 var rowSlug = getLastSlug(rawSlugValue); 14581 14582 console.log('[HideSection] Row', i, 'raw slug candidate:', rawSlugValue); 14583 console.log('[HideSection] Row', i, 'normalized slug:', rowSlug); 14584 14585 if (rowSlug === currentSlug) { 14586 matchingRow = row; 14587 console.log('[HideSection] Matching row found:', matchingRow); 14588 break; 14589 } 14590 } 14591 } 14592 14593 if (!matchingRow) {
14594 console.warn('[HideSection] No matching row found for collection:', collectionName); 14595 return; 14596 } 14597 14598 var matchingRowData = matchingRow.data || matchingRow; 14599 var fieldValue = matchingRowData[requiredFieldName]; 14600 14601 console.log('[HideSection] Field "' + requiredFieldName + '" value:', fieldValue); 14602 14603 var hasValue = hasVisibleText(fieldValue); 14604 14605 if (!hasValue) { 14606 console.log('[HideSection] Field has no visible text â hiding section.'); 14607 hideSectionForMarker(marker); 14608 } else { 14609 console.log('[HideSection] Field has visible text â section stays visible.'); 14610 showSectionForMarker(marker); 14611 } 14612 }) 14613 .catch(function (error) { 14614 console.warn('[HideSection] Collection check failed:', error); 14615 }); 14616 } 14617 14618 function run() { 14619 var markers = element.querySelectorAll('.hide-section-if-category-field-empty'); 14620 14621 for (var i = 0; i < markers.length; i++) { 14622 checkCollection(markers[i]); 14623 } 14624 14625 setTimeout(function () { 14626 var markers2 = element.querySelectorAll('.hide-section-if-category-field-empty'); 14627 14628 for (var j = 0; j < markers2.length; j++) { 14629 checkCollection(markers2[j]); 14630 } 14631 }, 1500); 14632 } 14633 14634 run(); 14635 14636}); 14637 }; 14638</script>
14638 14639
14640<script> 14641 window.customWidgetsFunctions["8eedf98f346a42e0a55f9d6152653187~2"] = function (element, data, api) { 14642 window.dmAPI.runOnReady('dcbh2-h2-theme', () => { 14643 14644 const STYLE_ID = 'dcbh2-h2-theme-style'; 14645 const TARGET_SELECTOR = '.widget-wrapper.DCBH2'; 14646 14647 let updateTimer = null; 14648 let lastSignature = ''; 14649 14650 /** 14651 * Find a usable H2 that is NOT inside the DCBH2 widget. 14652 */ 14653 function findThemeH2() { 14654 const candidates = Array.from( 14655 document.querySelectorAll('#dm h2, h2') 14656 ); 14657 14658 for (const el of candidates) { 14659 14660 // Do not use our own DCBH2 widget as the source 14661 if (el.closest(TARGET_SELECTOR)) { 14662 continue; 14663 } 14664 14665 // Ignore disconnected elements 14666 if (!el.isConnected) { 14667 continue; 14668 } 14669 14670 const computed = window.getComputedStyle(el); 14671 14672 // Ignore unavailable / hidden elements 14673 if ( 14674 computed.display === 'none' || 14675 computed.visibility === 'hidden' 14676 ) { 14677 continue; 14678 } 14679 14680 // Make sure useful typography has loaded 14681 if (!computed.fontFamily || !computed.fontSize) { 14682 continue; 14683 } 14684 14685 return el; 14686 } 14687 14688 return null; 14689 } 14690 14691 14692 /** 14693 * Read H2 typography and apply it to DCBH2 widgets. 14694 */ 14695 function applyTheme() { 14696 14697 const h2Sample = findThemeH2(); 14698 14699 if (!h2Sample) { 14700 return false; 14701 } 14702 14703 const computed = window.getComputedStyle(h2Sample); 14704 14705 const styles = { 14706 fontFamily: computed.fontFamily, 14707 fontSize: computed.fontSize, 14708 fontWeight: computed.fontWeight, 14709 lineHeight: computed.lineHeight, 14710 color: computed.color, 14711 letterSpacing: computed.letterSpacing, 14712 textTransform: computed.textTransform, 14713 fontStyle: computed.fontStyle, 14714 fontVariant: computed.fontVariant, 14715 fontStretch: computed.fontStretch 14716 }; 14717 14718 /** 14719 * Only rewrite the stylesheet if something actually changed. 14720 */ 14721 const signature = JSON.stringify(styles); 14722 14723 if (signature === lastSignature) { 14724 return true; 14725 } 14726 14727 lastSignature = signature; 14728 14729 14730 /** 14731 * Target Duda RTE elements, including nested spans. 14732 */ 14733 const selectors = [ 14734 '#dm .dmInner .widget-wrapper.DCBH2 .dmNewParagraph', 14735 '#dm .dmInner .widget-wrapper.DCBH2 .dmNewParagraph p', 14736 '#dm .dmInner .widget-wrapper.DCBH2 .dmNewParagraph span', 14737 '#dm .dmInner .widget-wrapper.DCBH2 .dmNewParagraph .rteBlock', 14738 '#dm .dmInner .widget-wrapper.DCBH2 .dmNewParagraph .rteBlock *', 14739 14740 '.dmInner .widget-wrapper.DCBH2 .dmNewParagraph', 14741 '.dmInner .widget-wrapper.DCBH2 .dmNewParagraph p', 14742 '.dmInner .widget-wrapper.DCBH2 .dmNewParagraph span', 14743 '.dmInner .widget-wrapper.DCBH2 .dmNewParagraph .rteBlock', 14744 '.dmInner .widget-wrapper.DCBH2 .dmNewParagraph .rteBlock *', 14745 14746 '.widget-wrapper.DCBH2 .dmNewParagraph', 14747 '.widget-wrapper.DCBH2 .dmNewParagraph p', 14748 '.widget-wrapper.DCBH2 .dmNewParagraph span', 14749 '.widget-wrapper.DCBH2 .dmNewParagraph .rteBlock', 14750 '.widget-wrapper.DCBH2 .dmNewParagraph .rteBlock *' 14751 ]; 14752 14753 const css = ` 14754${selectors.join(',\n')} { 14755 font-family: ${styles.fontFamily} !important; 14756 font-size: ${styles.fontSize} !important; 14757 font-weight: ${styles.fontWeight} !important; 14758 line-height: ${styles.lineHeight} !important; 14759 color: ${styles.color} !important; 14760 letter-spacing: ${styles.letterSpacing} !important; 14761 text-transform: ${styles.textTransform} !important; 14762 font-style: ${styles.fontStyle} !important; 14763 font-variant: ${styles.fontVariant} !important; 14764 font-stretch: ${styles.fontStretch} !important; 14765} 14766`; 14767 14768 let styleTag = document.getElementById(STYLE_ID); 14769 14770 if (!styleTag) { 14771 styleTag = document.createElement('style'); 14772 styleTag.id = STYLE_ID; 14773 styleTag.setAttribute('data-dcbh2-h2-theme', 'true'); 14774 document.head.appendChild(styleTag); 14775 } 14776 14777 styleTag.textContent = css; 14778 14779 return true; 14780 } 14781 14782 14783 /** 14784 * Debounce repeated Duda DOM changes. 14785 */ 14786 function scheduleUpdate(delay = 100) { 14787 14788 clearTimeout(updateTimer); 14789 14790 updateTimer = setTimeout(() => { 14791 applyTheme(); 14792 }, delay); 14793 } 14794 14795 14796 /** 14797 * Initial passes. 14798 * 14799 * Duda/theme/font rendering can continue after runOnReady. 14800 */ 14801 applyTheme(); 14802 14803 setTimeout(applyTheme, 250); 14804 setTimeout(applyTheme, 500); 14805 setTimeout(applyTheme, 1000); 14806 setTimeout(applyTheme, 2000); 14807 setTimeout(applyTheme, 4000); 14808 14809 14810 /** 14811 * Watch for Duda re-rendering or dynamic content changes. 14812 */ 14813 const observer = new MutationObserver((mutations) => { 14814 14815 let relevantChange = false;
14816 14817 for (const mutation of mutations) { 14818 14819 // Ignore our own injected stylesheet 14820 if ( 14821 mutation.target && 14822 ( 14823 mutation.target.id === STYLE_ID || 14824 mutation.target.closest?.(`#${STYLE_ID}`) 14825 ) 14826 ) { 14827 continue; 14828 } 14829 14830 relevantChange = true; 14831 break; 14832 } 14833 14834 if (relevantChange) { 14835 scheduleUpdate(150); 14836 } 14837 14838 }); 14839 14840 observer.observe(document.body, { 14841 childList: true, 14842 subtree: true, 14843 attributes: true, 14844 attributeFilter: [ 14845 'class', 14846 'style' 14847 ] 14848 }); 14849 14850 14851 /** 14852 * Responsive breakpoint changes. 14853 */ 14854 window.addEventListener('resize', () => { 14855 scheduleUpdate(150); 14856 }); 14857 14858 14859 /** 14860 * Mobile orientation changes. 14861 */ 14862 window.addEventListener('orientationchange', () => { 14863 scheduleUpdate(250); 14864 }); 14865 14866 14867 /** 14868 * Reapply after web fonts finish loading. 14869 */ 14870 if (document.fonts && document.fonts.ready) { 14871 14872 document.fonts.ready.then(() => { 14873 14874 lastSignature = ''; 14875 14876 applyTheme(); 14877 14878 }).catch(() => { 14879 // Nothing required 14880 }); 14881 14882 } 14883 14884}); 14885 }; 14886</script>
14886 14887
14888<script> 14889 window.customWidgetsFunctions["403a957a34f84bc8a342137c59c93b31~3"] = function (element, data, api) { 14890 window.dmAPI.runOnReady('dcbp-p-theme', () => { 14891 'use strict'; 14892 14893 const STYLE_ID = 'dcbp-p-theme-styles'; 14894 14895 function getParagraphFontFamily() { 14896 const source = 14897 document.querySelector( 14898 '.widget-403a95 .cb2-theme-injector .dmNewParagraph p' 14899 ) || 14900 document.querySelector( 14901 '.widget-403a95 .cb2-theme-injector p' 14902 ) || 14903 document.querySelector( 14904 '.widget-403a95 .dmNewParagraph p' 14905 ) || 14906 document.querySelector( 14907 '.widget-403a95 p' 14908 ); 14909 14910 if (!source) { 14911 return null; 14912 } 14913 14914 const computed = window.getComputedStyle(source); 14915 const fontFamily = computed.fontFamily; 14916 14917 if (!fontFamily || fontFamily.trim() === '') { 14918 return null; 14919 } 14920 14921 return fontFamily; 14922 } 14923 14924 function applyTheme() { 14925 const dcbpElements = document.querySelectorAll( 14926 '#dm .DCBP, ' + 14927 '.DCBP, ' + 14928 '#dm .widget-wrapper.DCBP, ' + 14929 '.widget-wrapper.DCBP' 14930 ); 14931 14932 if (!dcbpElements.length) { 14933 return false; 14934 } 14935 14936 const fontFamily = getParagraphFontFamily(); 14937 14938 if (!fontFamily) { 14939 return false; 14940 } 14941 14942 const uSelectors = new Set(); 14943 14944 const paragraphElements = document.querySelectorAll( 14945 '#dm .DCBP .dmNewParagraph, ' + 14946 '.DCBP .dmNewParagraph' 14947 ); 14948 14949 paragraphElements.forEach(element => { 14950 element.classList.forEach(className => { 14951 if (!className.startsWith('u_')) { 14952 return; 14953 } 14954 14955 uSelectors.add(`div.${className}`); 14956 uSelectors.add(`div.${className} p`); 14957 uSelectors.add(`div.${className} li`); 14958 uSelectors.add(`div.${className} span`); 14959 14960 uSelectors.add(`#dm .dmInner div.${className}`); 14961 uSelectors.add(`#dm .dmInner div.${className} p`); 14962 uSelectors.add(`#dm .dmInner div.${className} li`); 14963 uSelectors.add(`#dm .dmInner div.${className} span`); 14964 }); 14965 }); 14966 14967 const baseSelectors = [ 14968 '#dm .dmInner .widget-wrapper.DCBP .dmNewParagraph', 14969 '#dm .dmInner .widget-wrapper.DCBP .dmNewParagraph p', 14970 '#dm .dmInner .widget-wrapper.DCBP .dmNewParagraph li', 14971 '#dm .dmInner .widget-wrapper.DCBP .dmNewParagraph span', 14972 '#dm .dmInner .widget-wrapper.DCBP .dmNewParagraph .rteBlock', 14973 14974 '.dmInner .widget-wrapper.DCBP .dmNewParagraph', 14975 '.dmInner .widget-wrapper.DCBP .dmNewParagraph p', 14976 '.dmInner .widget-wrapper.DCBP .dmNewParagraph li', 14977 '.dmInner .widget-wrapper.DCBP .dmNewParagraph span', 14978 '.dmInner .widget-wrapper.DCBP .dmNewParagraph .rteBlock', 14979 14980 '.widget-wrapper.DCBP .dmNewParagraph', 14981 '.widget-wrapper.DCBP .dmNewParagraph p', 14982 '.widget-wrapper.DCBP .dmNewParagraph li', 14983 '.widget-wrapper.DCBP .dmNewParagraph span', 14984 '.widget-wrapper.DCBP .dmNewParagraph .rteBlock', 14985 14986 '#dm .DCBP .dmNewParagraph', 14987 '#dm .DCBP .dmNewParagraph p', 14988 '#dm .DCBP .dmNewParagraph li', 14989 '#dm .DCBP .dmNewParagraph span', 14990 14991 '.DCBP .dmNewParagraph', 14992 '.DCBP .dmNewParagraph p', 14993 '.DCBP .dmNewParagraph li', 14994 '.DCBP .dmNewParagraph span' 14995 ]; 14996 14997 const allSelectors = [ 14998 ...baseSelectors, 14999 ...uSelectors 15000 ].join(',\n'); 15001 15002 const css = ` 15003${allSelectors} { 15004 font-family: ${fontFamily} !important; 15005} 15006`; 15007 15008 let styleTag = document.getElementById(STYLE_ID); 15009 15010 if (!styleTag) { 15011 styleTag = document.createElement('style'); 15012 styleTag.id = STYLE_ID; 15013 styleTag.setAttribute('data-dcbp-p-theme', 'true'); 15014 document.head.appendChild(styleTag); 15015 } 15016 15017 styleTag.textContent = css; 15018 15019 return true; 15020 } 15021 15022 if (applyTheme()) { 15023 return; 15024 } 15025 15026 let attempts = 0; 15027 const maxAttempts = 30; 15028 15029 const interval = window.setInterval(() => { 15030 attempts += 1; 15031 15032 if (applyTheme() || attempts >= maxAttempts) { 15033 window.clearInterval(interval); 15034 } 15035 }, 300); 15036}); 15037 }; 15038</script>
15038 15039
15040<script> 15041 window.customWidgetsFunctions["328e6f1fbcec4101ac4f8d9184710a14~7"] = function (element, data, api) { 15042 $(document).ready(function(){ 15043 $.getScript('https://widget.hibu.us/static/js/recent.js') 15044 .done(function(){ 15045 dmAPI.runOnReady('hibu_recent_reviews',function(){ 15046 //window.renderApp(); 15047 }); 15048 15049 }) 15050 .fail(function(){ 15051 console.log("failed to load recent reviews js file") 15052 }); 15053 15054 element.children[0].removeAttribute(`rteblock"`) 15055 var merchantId = data.config.merchantId 15056 merchantId = merchantId.replace(/<p.*?>/g, '') 15057 merchantId = merchantId.replace(/"/g, '"') 15058 merchantId = merchantId.replace(/\<\/p\>/g, '') 15059 15060 element.children[0].setAttribute('data-merchant', merchantId) 15061}) 15062 }; 15063</script>
15063 15064 15065
15066<script type="text/javascript"> 15067 15068 var d_version = "production_6839"; 15069 var build = "2026-10-08T12_48_49"; 15070 window['v' + 'ersion'] = d_version; 15071 15072 function buildEditorParent() { 15073 window.isMultiScreen = true; 15074 window.editorParent = {}; 15075 window.previewParent = {}; 15076 try { 15077 var _p = window.parent; 15078 if (_p && _p.document && _p.$ && _p.$.dmfw) { 15079 window.editorParent = _p; 15080 } else if (_p.isSitePreview) { 15081 window.previewParent = _p; 15082 } 15083 } catch (e) { 15084 15085 } 15086 } 15087 15088 buildEditorParent(); 15089</script>
15089 15090 15091 15092 15093<!-- Injecting site-wide before scripts --> 15094 15095
15096<script src="https://app.termly.io/resource-blocker/a6624115-6b28-428b-a8ca-0b421ba3abff?autoBlock=on" data-swh-uuid="749960c3c115439e9d6946a9cd4b81ce"> 15097</script>
15097 15098 15099 15100 15101 15102 15103 15104 15105 15106 15107 15108 15109 15110 15111 15112 15113 15114 15115 15116
15117<script type="text/javascript" id="d_track_campaign" data-entry-referrer data-utm-cookies></script>
15117 15118
15119<script type="text/javascript" > 15120 var _dm_gaq = {}; 15121 var _gaq = _gaq || []; 15122 var _dm_insite = []; 15123</script>
15123 15124 15125 15126 15127
15128<script async src="https://www.googletagmanager.com/gtm.js?id=GTM-W487CGFD" id="d-js-gtm" 15129 onload="window.dispatchEvent(new CustomEvent('gtmLoaded', { bubbles: true }))"></script>
15129 15130
15131<script type="text/javascript" id="d_track_ga"> 15132 window.dataLayer = window.dataLayer || []; 15133 _dm_gaq.siteAlias = '7720a79493434d7dbf0e283d7c6423e7'; 15134 _dm_gaq.externalGaqID = 'non-empty'; 15135 15136 function gtag() { dataLayer.push(arguments); } 15137 15138 function pushInsiteImpressions(id) { 15139 _dm_insite.forEach((rule) => { 15140 _dm_gaq.pushEvent(id, 'insite_impression', 'insite', rule.ruleType + '__' + rule.ruleId); 15141 }); 15142 } 15143 15144 _dm_gaq.pushEvent = function(trackingId, event, category, label, value, additionalParams = {}) { 15145 const eventProps = { 15146 event_category: category, 15147 event_label: label, 15148 value, 15149 ...additionalParams 15150 }; 15151 gtag('event', event, eventProps); 15152 } 15153 15154 gtag('js', new Date()) 15155 15156 15157gtag('set', 'developer_id.dMDU5Nj', true); 15158 15159 _dm_gaq.pushEvent('', 'page_view'); 15160 15161 pushInsiteImpressions(_dm_gaq.externalGaqID); 15162</script>
15162 15163 15164 15165 15166 15167 15168 15169<!-- End Injecting site-wide to the head --> 15170 15171 15172 15173 15174 15175
15176<script> 15177 window.cookiesNotificationMarkupPreview = 'null'; 15178</script>
15178 15179 15180
15181<script id='d-js-params'> 15182 window.INSITE = window.INSITE || {}; 15183 window.INSITE.device = "desktop"; 15184 15185 window.rtCommonProps = {}; 15186 rtCommonProps["runtimecollector.url"] = 'https://rtc.hibuwebsites.com'; 15187 rtCommonProps["performance.tabletPreview.removeScroll"] = 'false'; 15188 rtCommonProps["inlineEditGrid.snap"] =true; 15189 rtCommonProps["popup.insite.cookie.ttl"] = '0.5'; 15190 rtCommonProps["common.mapbox.token"] = 'pk.eyJ1IjoiZGFubnliMTIzIiwiYSI6ImNqMGljZ256dzAwMDAycXBkdWxwbDgzeXYifQ.Ck5P-0NKPVKAZ6SH98gxxw'; 15191 rtCommonProps["common.mapbox.js.override"] =false; 15192 rtCommonProps["common.here.appId"] = 'iYvDjIQ2quyEu0rg0hLo'; 15193 rtCommonProps["common.here.appCode"] = '1hcIxLJcbybmtBYTD9Z1UA'; 15194 rtCommonProps["ecommerce.ecwid.script"] = 'https://app.multiscreenstore.com/script.js'; 15195 rtCommonProps["common.build.dist.folder"] = 'production/6839'; 15196 rtCommonProps["common.resources.cdn.host"] = 'https://static-res-cdn.websites.hibu.com'; 15197 rtCommonProps["common.resources.folder"] = 'https://static-res-cdn.websites.hibu.com/mnlt/production/6839'; 15198 rtCommonProps["common.fonts.api.v2.url"] = 'https://cdn.hibuwebsites.com/fonts/css2?family='; 15199 rtCommonProps["feature.flag.runtime.backgroundSlider.preload.slowly"] =true; 15200 rtCommonProps["feature.flag.runtime.newAnimation.jitAnimation.enabled"] =true; 15201 rtCommonProps["feature.flag.sites.google.analytics.gtag"] =true; 15202 rtCommonProps["feature.flag.runOnReadyNewTask"] =true; 15203 rtCommonProps["isAutomation.test"] =false; 15204 rtCommonProps["booking.cal.api.domain"] = 'api.cal.com'; 15205 15206 15207 rtCommonProps['common.mapsProvider'] = 'mapbox'; 15208 15209 rtCommonProps['common.mapsProvider.version'] = '0.52.0'; 15210 rtCommonProps['common.geocodeProvider'] = 'mapbox'; 15211 rtCommonProps['server.for.resources'] = ''; 15212 rtCommonProps['feature.flag.lazy.widgets'] = true; 15213 rtCommonProps['feature.flag.single.wow'] = false; 15214 rtCommonProps['feature.flag.disallowPopupsInEditor'] = true; 15215 rtCommonProps['feature.flag.mark.anchors'] = true; 15216 rtCommonProps['captcha.public.key'] = '6LffcBsUAAAAAMU-MYacU-6QHY4iDtUEYv_Ppwlz'; 15217 rtCommonProps['captcha.invisible.public.key'] = '6LeiWB8UAAAAAHYnVJM7_-7ap6bXCUNGiv7bBPME'; 15218 rtCommonProps["images.sizes.small"] =160; 15219 rtCommonProps["images.sizes.mobile"] =640; 15220 rtCommonProps["images.sizes.tablet"] =1280; 15221 rtCommonProps["images.sizes.desktop"] =1920; 15222 rtCommonProps["import.images.storage.imageCDN"] = 'https://le-cdn.hibuwebsites.com/'; 15223 rtCommonProps["feature.flag.performance.logs"] =false; 15224 rtCommonProps["site.widget.form.captcha.type"] = 'g_recaptcha'; 15225 rtCommonProps["friendly.captcha.site.key"] = 'FCMGSQG9GVNMFS8K'; 15226 rtCommonProps["cookiebot.mapbox.consent.category"] = 'marketing'; 15227 rtCommonProps["termly.mapbox.consent.category"] = 'performance'; 15228 // feature flags that's used out of runtime module (in legacy files) 15229 rtCommonProps["platform.monolith.personalization.dateTimeCondition.popupMsgAction.moveToclient.enabled"] =true; 15230 15231 window.rtFlags = {}; 15232 rtFlags["unsuspendEcwidStoreOnRuntime.enabled"] =false; 15233 rtFlags["scripts.widgetCount.enabled"] =true; 15234 rtFlags["fnb.animations.tracking.enabled"] =true; 15235 rtFlags["ecom.ecwidNewUrlStructure.enabled"] = false; 15236 rtFlags["ecom.ecwid.accountPage.emptyBaseUrl.enabled"] = true; 15237 rtFlags["ecom.ecwid.accountPage.repeatOrderRedirect.enabled"] = false; 15238 rtFlags["ecom.ecwid.oldStore.keepScrollOnLoad.enabled"] = true; 15239 rtFlags["ecom.ecwid.storefrontV3.enabled"] = false; 15240 rtFlags["ecom.monolith.legacy.js.api.disabled.for.new.sites"] = false; 15241 rtFlags["geocode.search.localize"] =false; 15242 rtFlags["feature.flag.runtime.newAnimation.asyncInit.setTimeout.enabled"] =false; 15243 rtFlags["twitter.heightLimit.enabled"] = true; 15244 rtFlags["streamline.monolith.personalization.supportMultipleConditions.enabled"] =false; 15245 rtFlags["flex.animation.design.panel.layout"] =true; 15246 rtFlags["runtime.cwv.report.cls.enabled"] =false; 15247 rtFlags["runtime.cwv.report.lcp.enabled"] =false; 15248 rtFlags["runtime.lcp.preload.selfheal.enabled"] =true; 15249 rtFlags["runtime.lcp.preload.bootstrap.enabled"] =true; 15250 rtFlags["runtime.lcp.preload.monitor.enabled"] =false; 15251 rtFlags["runtime.customwidget.heightpin.enabled"] =true; 15252 rtFlags["runtime.video.widget.lazy.enabled"] =true; 15253 rtFlags["contact.form.useActiveForm"] =true; 15254 rtFlags["contact.form.custom.errors.enabled"] =false; 15255 rtFlags["runtime.ssr.productStore.internal.observer"] =true; 15256 rtFlags["editor.widget.form.a11y"] =true; 15257</script>
vendor: 1 bytes, line 15257
15257
15258<script src="https://static-res-cdn.websites.hibu.com/mnlt/production/6839/_dm/s/rt/dist/scripts/d-js-runtime-flex-package.min.js" id="d-js-core" defer></script>
15258 15259 15260 15261 15262 15263 15264 15265 15266 15267 15268 15269 15270 15271 15272 15273 15274
15275<script> 15276 document.addEventListener('DOMContentLoaded', () => 15277 window.runtime.initLayout() 15278 ); 15279</script>
15279 15280 15281 15282 15283 15284 15285 15286 15287 15288 15289 15290 15291 15292 15293 15294 15295 15296 15297 15298
15299<script type="text/javascript" id="d_track_sp"> 15300 ;(function(p,l,o,w,i,n,g){if(!p[i]){p.GlobalSnowplowNamespace=p.GlobalSnowplowNamespace||[]; 15301 p.GlobalSnowplowNamespace.push(i);p[i]=function(){(p[i].q=p[i].q||[]).push(arguments) 15302 };p[i].q=p[i].q||[];n=l.createElement(o);g=l.getElementsByTagName(o)[0];n.async=1; 15303 n.src=w;g.parentNode.insertBefore(n,g)}}(window,document,"script","//d32hwlnfiv2gyn.cloudfront.net/sp-2.0.0-dm-0.1.min.js","snowplow")); 15304 window.dmsnowplow = window.snowplow; 15305 15306 dmsnowplow('newTracker', 'cf', 'd32hwlnfiv2gyn.cloudfront.net', { // Initialise a tracker 15307 appId: '7720a79493434d7dbf0e283d7c6423e7' 15308 }); 15309 15310 // snowplow queries element styles so we wait until CSS calculations are done. 15311 requestAnimationFrame(() => { 15312 dmsnowplow('trackPageView'); 15313 _dm_insite.forEach((rule) => { 15314 // Specifically in popup only the client knows if it is shown or not so we don't always want to track its impression here 15315 // the tracking is in popup.js 15316 if (rule.actionName !== "popup") { 15317 dmsnowplow('trackStructEvent', 'insite', 'impression', rule.ruleType, rule.ruleId); 15318 } 15319 window?.waitForDeferred?.('dmAjax', () => { 15320 $.DM.events.trigger('event-ruleTriggered', {value: rule}); 15321 }); 15322 }); 15323 }); 15324</script>
15324 15325 15326 15327 15328<div style="display:none;" id="P6iryBW0Wu"></div> 15329 15330 15331 15332 15333 15334 15335 15336 15337 15338 15339 15340<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true"> 15341 15342 15343 <div class="pswp__bg"></div> 15344 15345 15346 <div class="pswp__scroll-wrap"> 15347 15348 15349 <div class="pswp__container"> 15350 <div class="pswp__item"></div> 15351 <div class="pswp__item"></div> 15352 <div class="pswp__item"></div> 15353 </div> 15354 15355 15356 <div class="pswp__ui pswp__ui--hidden"> 15357 15358 <div class="pswp__top-bar"> 15359 15360 15361 15362 <div class="pswp__counter"></div> 15363 15364 <button class="pswp__button pswp__button--close" data-auto="pswp-close" title="Close (Esc)"></button> 15365 15366 <button class="pswp__button pswp__button--share" data-auto="pswp-share" title="Share"></button> 15367 15368 <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button> 15369 15370 <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button> 15371 15372 15373 15374 <div class="pswp__preloader"> 15375 <div class="pswp__preloader__icn"> 15376 <div class="pswp__preloader__cut"> 15377 <div class="pswp__preloader__donut"></div> 15378 </div> 15379 </div> 15380 </div> 15381 </div> 15382 15383 <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap"> 15384 <div class="pswp__share-tooltip"></div> 15385 </div> 15386 15387 <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)"> 15388 </button> 15389 15390 <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"> 15391 </button> 15392 15393 <div class="pswp__caption"> 15394 <div class="pswp__caption__center"></div> 15395 </div> 15396 15397 </div> 15398 15399 </div> 15400 15401</div> 15402<div id="fb-root" 15403 data-locale="en"></div> 15404<!-- Alias: 7720a79493434d7dbf0e283d7c6423e7 -->
15405<script id="d_track_personalization"> 15406 window?.waitForDeferred?.('dmAjax', () => { 15407 // Collects client data and updates cookies used by smart sites 15408 window.expireDays = 365; 15409 window.visitLength = 30 * 60000; 15410 $.setCookie("dm_timezone_offset", (new Date()).getTimezoneOffset(), window.expireDays); 15411 setSmartSiteCookiesInternal("dm_this_page_view","dm_last_page_view","dm_total_visits","dm_last_visit"); 15412 }); 15413</script>
vendor: 1 bytes, line 15413
15413
15414<script type="text/javascript"> 15415 15416 Parameters.NavigationAreaParams.MoreButtonText = 'MORE'; 15417 15418 Parameters.NavigationAreaParams.LessButtonText = 'LESS'; 15419 </script>
vendor: 1 bytes, line 15419
15419
15420<script id="ssr-empty-script" type="text/javascript"></script>
15420<!-- Begin Body End Markup --> 15421<!-- Begin Body End Markup --><!-- Begin Name of Code --><!-- End Name of Code --><div id="placeholder_retargeting_pixel" style="display: none;" data-inject="placeholder_retargeting_pixel"> 15422
15422<script> 15423//<![CDATA[ 15424(function(w,d,t,r,u){var f,n,i;w[u]=w[u]||[],f=function(){var o={ti:"187277395"};o.q=w[u],w[u]=new UET(o),w[u].push("pageLoad")},n=d.createElement(t),n.src=r,n.async=1,n.onload=n.onreadystatechange=function(){var s=this.readyState;s&&s!=="loaded"&&s!=="complete"||(f(),n.onload=n.onreadystatechange=null)},i=d.getElementsByTagName(t)[0],i.parentNode.insertBefore(n,i)})(window,document,"script","//bat.bing.com/bat.js","uetq"); 15425//]]> 15426 </script>
15426 15427 <noscript> 15428 <img src="//bat.bing.com/action/0?ti=187277395&Ver=2" height="0" width="0" style="display:none; visibility: hidden;"/> 15429 </noscript> 15430 <img src="//servedby.ipromote.com/ad/?src=pixel_cid&nid=2185&cid=JB6DQPDXT6BK&cat=2795" width="1" height="1" border="0" alt=""/> 15431</div> 15432<div id="placeholder_dpni" style="display: none;" data-inject="placeholder_dpni"> 15433 15434 15435 15436 15437 {{placeholder_dpni}} 15438</div> 15439<div id="placeholder_analytics" style="display: none;" data-inject="placeholder_analytics"> 15440
15440<script> 15441 15442 15443 15444//<![CDATA[ 15445 15446//yellAnalyticsConfig need to set before s_code.js 15447var yellAnalyticsConfig = { 15448"global" : { 15449 "trackDownloadLinks": true, 15450 "downloadFileTypes": "exe,zip,wav,mp3,mov,mpg,avi,wmv,pdf,doc,docx,xls,xlsx,ppt,pptx", 15451 "currency": "USD", 15452 "trackExternalLinks": true, 15453 "internalDomains": "javascript:", 15454 "charset": "UTF-8" 15455}, 15456"omniture" : { 15457 "enabled": true, 15458 "server": "yellgroup.122.2o7.net", 15459 "serverSecure": "yellgroup.122.2o7.net", 15460 "namespace": "yellgroup", 15461 "account": "yelldudalive", 15462 "campaign": "CID|cam" 15463}} 15464var hibuWebsiteConfig={ 15465 "prodSKU":"WBS-PRO-01", 15466 "assetID":"700149502", 15467 "customerID":"7000138184" 15468} 15469 15470//]]> 15471 15472 15473 15474 </script>
15474 15475
15475<script type="text/javascript" src="https://dh-static-files.s3.amazonaws.com/prod/AppMeasurement.js"> 15476 15477 15478//<![CDATA[ 15479 15480 15481//]]> 15482 15483 15484 </script>
15484 15485
15485<script type="text/javascript" src="https://dh-static-files.s3.amazonaws.com/prod/hibu-analytics.min.js" defer=""> 15486 15487 15488//<![CDATA[ 15489 15490 15491//]]> 15492 15493 15494 </script>
15494 15495
15495<script type="text/javascript" src="https://dh-static-files.s3.amazonaws.com/prod/omn_setting.js" defer=""> 15496 15497 15498//<![CDATA[ 15499 15500 15501//]]> 15502 15503 15504 </script>
15504 15505</div> 15506<div id="placeholder_footer_reserve1" style="display: none;" data-inject="placeholder_footer_reserve1"> 15507 <style> 15508 15509 15510 iframe[name="google_conversion_frame"] {height: 0 !important;width: 0 !important;line-height: 0 !important;font-size: 0 !important;margin-top: -13px;float: left;} 15511 15512 15513 </style> 15514</div> 15515<div id="placeholder_footer_reserve2" style="display: none;" data-inject="placeholder_footer_reserve2"> 15516 <!-- Facebook Pixel Code -->
15516<script nonce="kQuLB4k1"> 15517 15518//<![CDATA[
vendor: 397 bytes, lines 15518-15526
15518 15519 15520!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod? 15521n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n; 15522n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; 15523t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window, 15524document,'script','https://connect.facebook.net/en_US/fbevents.js'); 15525 15526fbq('init', '
155262205560163633541
vendor: 30 bytes, lines 15526-15527
15526'); 15527fbq('track', "PageView");
15528//]]> 15529 15530 </script>
15530 15531 <noscript> 15532 <img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=2205560163633541&ev=PageView&noscript=1"/> 15533 </noscript> 15534 <!-- End Facebook Pixel Code --> 15535</div> 15536<div id="placeholder_footer_reserve3" style="display: none;" data-inject="placeholder_footer_reserve3"> 15537
15537<script> 15538 15539 15540 15541//<![CDATA[ 15542 15543 (() => { 15544 // Hide any flex wrapper whose button text contains "do not use" 15545 function hideDoNotUse(root = document) { 15546 const wrappers = root.querySelectorAll('.flex-element.widget-wrapper'); 15547 wrappers.forEach(wrap => { 15548 const btn = wrap.querySelector('a.dmButtonLink, a.flexButton, a[data-element-type="dButtonLinkId"]'); 15549 if (!btn) return; 15550 const text = (btn.textContent || '').toLowerCase().trim(); 15551 if (text.includes('do not use')) { 15552 wrap.style.display = 'none'; 15553 wrap.setAttribute('data-hidden-reason', 'do-not-use'); 15554 } 15555 }); 15556 } 15557 // Run once on ready 15558 if (document.readyState === 'loading') { 15559 document.addEventListener('DOMContentLoaded', () => hideDoNotUse()); 15560 } else { 15561 hideDoNotUse(); 15562 } 15563 // Watch for dynamically inserted content or text changes 15564 const mo = new MutationObserver(mutations => { 15565 for (const m of mutations) { 15566 m.addedNodes.forEach(node => { 15567 if (node.nodeType !== 1) return; 15568 if (node.matches && node.matches('.flex-element.widget-wrapper')) { 15569 hideDoNotUse(node); 15570 } else { 15571 // Check if a new/changed node sits inside a wrapper 15572 const wrap = node.closest && node.closest('.flex-element.widget-wrapper'); 15573 if (wrap) hideDoNotUse(wrap); 15574 else hideDoNotUse(node); 15575 } 15576 }); 15577 if (m.type === 'characterData' || m.type === 'childList') { 15578 const wrap = m.target.closest && m.target.closest('.flex-element.widget-wrapper'); 15579 if (wrap) hideDoNotUse(wrap); 15580 } 15581 } 15582 }); 15583 mo.observe(document.documentElement, { 15584 childList: true, 15585 subtree: true, 15586 characterData: true 15587 }); 15588})(); 15589 15590//]]> 15591 15592 15593 15594 </script>
15594 15595</div> 15596<div id="placeholder_footer_reserve4" style="display: none;" data-inject="placeholder_footer_reserve4"> 15597 15598 15599 15600 15601 {{placeholder_footer_reserve4}} 15602</div> 15603<div id="placeholder_footer_reserve5" style="display: none;" data-inject="placeholder_footer_reserve5"> 15604 15605 15606 15607 15608 {{placeholder_footer_reserve5}} 15609</div> 15610<div id="placeholder_footer_reserve6" style="display: none;" data-inject="placeholder_footer_reserve6"> 15611 15612 15613 15614 15615 {{placeholder_footer_reserve6}} 15616</div> 15617<div id="placeholder_footer_reserve7" style="display: none;" data-inject="placeholder_footer_reserve7"> 15618 15619 15620 15621 15622 {{placeholder_footer_reserve7}} 15623</div> 15624<!-- End Body End Markup --><!-- form dropdown code begin -->
15624<script> 15625//<![CDATA[ 15626function waitForDmAPI(callback) { 15627 if (typeof dmAPI !== 'undefined') { 15628 callback(); 15629 } else { 15630 setTimeout(() => waitForDmAPI(callback), 100); 15631 } 15632} 15633 15634document.addEventListener("DOMContentLoaded", function () { 15635 waitForDmAPI(async function () { 15636 async function getServicesAndProducts() { 15637 try { 15638 var collection = await dmAPI.loadCollectionsAPI(); 15639 var formData = await collection.data("form").get(); 15640 15641 if (formData?.values?.length > 0) { 15642 let servicesHtml = formData.values[0].data["Services & Products"]; 15643 15644 let tempDiv = document.createElement("div"); 15645 tempDiv.innerHTML = servicesHtml; 15646 15647 return Array.from(tempDiv.querySelectorAll("p")).map(p => 15648 p.textContent.trim() 15649 ); 15650 } 15651 } catch (err) { 15652 console.error("Failed to load form data:", err); 15653 } 15654 15655 return []; 15656 } 15657 15658 async function replaceInputWithDropdown() { 15659 let servicesArray = await getServicesAndProducts(); 15660 if (servicesArray.length === 0) return; 15661 15662 // Add "Services" to the beginning and "Other" to the end 15663 servicesArray = [...servicesArray, "Other"]; 15664 15665 let labels = document.querySelectorAll("label"); 15666 labels.forEach(label => { 15667 let labelText = label.textContent.trim(); 15668 if ( 15669 labelText.includes("Services") || 15670 labelText.includes("Products") || 15671 labelText.includes("Case Study") 15672 ) { 15673 let input = label.parentElement.querySelector("input[type='text']"); 15674 if (input) { 15675 let select = document.createElement("select"); 15676 select.name = input.name; 15677 select.id = input.id; 15678 15679 servicesArray.forEach(service => { 15680 let option = document.createElement("option"); 15681 option.value = service; 15682 option.textContent = service; 15683 select.appendChild(option); 15684 }); 15685 15686 input.replaceWith(select); 15687 } 15688 } 15689 }); 15690 } 15691 15692 await replaceInputWithDropdown(); 15693 }); 15694}); 15695//]]> 15696</script>
15696 15697<!-- form dropdown code end --><!-- form button code begin -->
15697<script> 15698//<![CDATA[ 15699 15700 function waitForDmAPI(callback) { 15701 if (typeof dmAPI !== 'undefined') { 15702 callback(); 15703 } else { 15704 setTimeout(() => waitForDmAPI(callback), 100); 15705 } 15706 } 15707 15708 async function getFormText() { 15709 var collection = await dmAPI.loadCollectionsAPI(); 15710 var buttonsData = await collection.data("buttons").get(); 15711 15712 if (buttonsData.values.length > 0) { 15713 let formHtml = buttonsData.values[0].data.Form_Button; 15714 let tempDiv = document.createElement("div"); 15715 tempDiv.innerHTML = formHtml; 15716 return tempDiv.textContent || tempDiv.innerText; 15717 } 15718 15719 return null; 15720 } 15721 15722 async function updateSubmitButton() { 15723 try { 15724 let formText = await getFormText(); 15725 if (!formText) { 15726 console.warn("No form text found."); 15727 return; 15728 } 15729 15730 let buttons = document.querySelectorAll('input[type="submit"][value="Form Button"]'); 15731 buttons.forEach(button => { 15732 button.value = formText; 15733 }); 15734 15735 console.log("Updated submit buttons with new value:", formText); 15736 } catch (error) { 15737 console.error("Error updating submit buttons:", error); 15738 } 15739 } 15740 15741 document.addEventListener("DOMContentLoaded", function () { 15742 waitForDmAPI(updateSubmitButton); 15743 }); 15744 15745//]]> 15746</script>
15746 15747<!-- form button code end --><!-- End Body End Markup --> 15748<!-- Site Wide Html Markup --> 15749<!-- Site Wide Html Markup --> 15750<!-- Begin Product Custom HTML Markup --> 15751<div id="fb-root"></div>
15752<script>(function(d, s, id) { 15753var js, fjs = d.getElementsByTagName(s)[0]; 15754if (d.getElementById(id)) return; 15755js = d.createElement(s); js.id = id; 15756js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.8&appId=1822295708016537"; 15757fjs.parentNode.insertBefore(js, fjs); 15758}(document, 'script', 'facebook-jssdk'));</script>
vendor: 2 bytes, line 15758
15758
15759<script> 15760//make sure video's on iOS load first screen of the video. 15761dmAPI.runOnReady('russTest',function() { 15762 var _hibu_vid = document.getElementsByTagName('video'); 15763 for (var i = 0; i < _hibu_vid.length; i++) { 15764 _hibu_vid[i].load(); 15765 } 15766}) 15767</script>
vendor: 2 bytes, line 15767
15767
15768<script> 15769//simple addition by Russ to add consent banner link into footer - updated by Adrian to account for Termly installs. 15770(function () { 15771 var poweredByFirstAnchor = document.querySelector('.poweredBy a:first-child'); 15772 if (!poweredByFirstAnchor) return; 15773 15774 if (window.Termly) { 15775 var termlySpan = document.createElement('span'); 15776 termlySpan.className = 'termly-display-preferences'; 15777 termlySpan.textContent = 'Manage Consent Preferences'; 15778 poweredByFirstAnchor.insertAdjacentElement('afterend', termlySpan); 15779 } else { 15780 var spSpan = document.createElement('span'); 15781 spSpan.id = 'spConsentWrapper'; 15782 poweredByFirstAnchor.insertAdjacentElement('afterend', spSpan); 15783 window.localStorage.setItem('__springtime__repop__target', '#spConsentWrapper'); 15784 } 15785})(); 15786</script>
15786 15787<style> 15788 #spConsentWrapper:before, 15789 .poweredBy .termly-display-preferences:before { content: " | " } 15790 .poweredBy .termly-display-preferences { cursor: pointer; } 15791</style>
15792<script> 15793if (window.location.search.indexOf('preview') > 0) { 15794 window.localStorage.setItem('ae_user_consent_decision_has_been_made', true); 15795 var spEl = document.getElementById('spConsentWrapper'); 15796 if (spEl) spEl.remove(); 15797} 15798</script>
15798<!-- End Product Custom HTML Markup --> 15799</body> 15800</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.