/*prevent FOUC on mobile when using sidebar */
.dwc-mobile :is(.bricks-is-frontend.brx-header-left, .bricks-is-frontend.brx-header-right) #brx-header {
  position: relative;
  inline-size: 100%;
  flex-direction: column;
}

.dwc-mobile .bricks-is-frontend:is(.brx-header-left, .brx-header-right) :is(#brx-content, #brx-footer) {
  margin-inline-start: 0;
}

/*prevent FOUC on desktop when using sidebar */
.bricks-is-frontend:is(.brx-header-left, .brx-header-right):not(.show-nav) .dwc-nav-wrapper {
  display: none;
}

/*=== sidebar css ===*/
html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header {
  flex-direction: column;
  box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.7);  
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]).no-scroll {
  overflow: visible;
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header .dwc-nest-menu.brxe-nav-nested .brx-nav-nested-items {
  max-block-size: 100dvb;
  padding-block-end: 12rem;
  overscroll-behavior: contain;
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header .dwc-nav-wrapper {
  position: relative;
  overflow: hidden;
  block-size: 100%;
  transform: translateX(0%);
  visibility: visible;
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) .dwc-nest-menu .brxe-toggle {
  display: none !important;
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header .dwc-nest-menu {
  display: flex;
  flex-direction: column;
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header .dwc-nest-header > div {
  display: flex;
  grid-template-columns: 1fr;
  block-size: 100%;
  flex-direction: column;
  justify-content: flex-start;
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header .dwc-menu-wrap {
  inline-size: 100%;
  display: grid;
  grid-template-columns: 1fr;
  block-size: 100%;
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header :is(.brxe-code, .dwc-nest-menu-overlay) {
  display: none;
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header .dwc-nest-header {
  inline-size: 100%;
  padding-inline: 0;
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header .dwc-nest-menu-top {
  min-block-size: var(--top-offset);
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header .dwc-nest-menu:not( [data-hide-close-bar = 'true']) .brx-dropdown-content {
  inset-block-start: calc(var(--top-offset) + 1px) !important;

}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header .dwc-nest-menu:not( [data-submenu-reveal = 'slide']) .brx-dropdown-content:not([data-submenu-reveal = 'slide'] *) {  
  inset-inline-start: 0;
  inset-block-start: unset !important;
  overflow: hidden;
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header .dwc-nest-menu:not([data-submenu-reveal = 'slide']) .brxe-dropdown:not(.open.active) > .brx-dropdown-content > .brxe-dropdown:not([data-submenu-reveal = 'slide'] *){
  visibility: hidden;  
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header .dwc-nest-menu.brxe-nav-nested.brx-open .brxe-dropdown > .brx-dropdown-content {
  overscroll-behavior: contain;
  min-inline-size: var(--mobile-menu-width);

}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header .dwc-nest-menu .brxe-dropdown.open > .brx-submenu-toggle button:not([data-submenu-reveal = 'expand'] button)  {
  min-block-size: calc(var(--top-offset) - 1px);
  inset-block-start: 0;
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header .dwc-nest-menu .brxe-dropdown.open[data-submenu-reveal = 'slide'] > .brx-submenu-toggle button  {
  min-block-size: calc(var(--top-offset) - 1px);
  inset-block-start: 0;
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header .dwc-nest-menu .brxe-dropdown .brx-submenu-toggle button {
  min-block-size: 0;    
}

/* sidebar css ends*/



/*sidebar in builder*/
/*=== sidebar css ===*/
:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header {
  flex-direction: column;
  box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.7);
  --top-offset: 40px;
}

:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header .dwc-nest-menu.brxe-nav-nested .brx-nav-nested-items {
  max-block-size: 100dvb;
  padding-block-end: 12rem;
  overscroll-behavior: contain;
}

:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header .dwc-nav-wrapper {
  position: relative;
  overflow: hidden;
  block-size: 100%;
  transform: translateX(0%);
  visibility: visible;
}

body:is(.brx-header-left, .brx-header-right)[data-builder-window] .dwc-nest-menu .brxe-toggle {
  display: none !important;
}

:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header .dwc-nest-menu {
  display: flex;
  flex-direction: column;
}

:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header .dwc-nest-header > div {
  display: flex;
  grid-template-columns: 1fr;
  block-size: 100%;
  flex-direction: column;
  justify-content: flex-start;
}

:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header .dwc-menu-wrap {
  inline-size: 100%;
  display: grid;
  grid-template-columns: 1fr;
  block-size: 100%;
}

:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header .dwc-nest-header {
  inline-size: 100%;
  padding-inline: 0;
}

:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header .dwc-nest-menu-top {
  min-block-size: var(--top-offset);
}

:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header .dwc-nest-menu .brx-dropdown-content {
  inset-block-start: calc(var(--top-offset) - 1px) !important;
}

:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header .dwc-nest-menu.brxe-nav-nested.brx-open .brxe-dropdown > .brx-dropdown-content {
  overscroll-behavior: contain;  
}

:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header .dwc-nest-menu .brxe-dropdown.open > .brx-submenu-toggle button {
  min-block-size: calc(var(--top-offset) - 1px);
  inset-block-start: 0;
}

:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header .dwc-nest-menu .brxe-dropdown .brx-submenu-toggle button {
  min-block-size: 0;    
}

:is(.brx-header-left, .brx-header-right)[data-builder-window] .dwc-nest-menu {
  margin: 0 !important;
}

:is(.brx-header-left, .brx-header-right)[data-builder-window] .brx-nav-nested-items {  
  flex-direction: column !important;  
}
   
:is(.brx-header-left, .brx-header-right)[data-builder-window] .dwc-nest-toggle--open.brxe-toggle {
  display: flex !important;
}
 
:is(.brx-header-left, .brx-header-right)[data-builder-window] .dwc-nest-menu .brx-nav-nested-items {
  position: relative !Important;
  background: var(--mobile-menu-bg) !important;
  align-items: stretch;
  flex: 1;
}

:where(.brx-header-left, .brx-header-right)[data-builder-mode]:not(:has(.dwc-sidebar)) .dwc-nest-menu-top::before {
    content: 'this space is the back text bar';
    padding: 1rem;
    background-color: gray;
    color: white;
    width: 100%;
    text-transform: uppercase;
    font-size: 12px;
    font-weight: bold;
    letter-spacing: 1px;
}
 
/* MENU CTA (LAST BUTTON) */
:is(.brx-header-left, .brx-header-right)[data-builder-window] [data-last-item-is-button="true"].dwc-nest-menu .brx-nav-nested-items > .menu-item:last-of-type {
  padding-inline: var(--menu-item-inline-padding) !important;
  padding-block: var(--menu-item-block-padding) !important;
}
 
:is(.brx-header-left, .brx-header-right)[data-builder-window] .dwc-nest-menu-top {
  min-block-size: 80px !important;
}
 
:is(.brx-header-left, .brx-header-right)[data-builder-window] .dwc-nest-nav-items {
  overflow-y: scroll;
}

:is(.brx-header-left, .brx-header-right)[data-builder-mode] .brx-dropdown-content {
  min-inline-size: var(--mobile-menu-width);
  position: static;
}

:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header .dwc-nest-menu.brxe-nav-nested .brx-nav-nested-items {
  flex-wrap: nowrap;
}
:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header .dwc-nest-menu .brx-dropdown-content {   
  visibility: visible !important;
  opacity: 1;
}

/*OVERLAY SIDEBAR*/


html:not(.dwc-mobile):has([data-overlay-sidebar=true])  {
 --mobile-menu-bg: rgb(255 255 255 / 0%);
  --menu-item-border: solid 1px rgb(255 255 255 / 50%);
 
}

html:not(.dwc-mobile):has([data-overlay-sidebar=true]) :is(.brx-header-left, .brx-header-right):not([data-builder-modee]) :is(main, footer){
  margin: 0 !important
}

html:not(.dwc-mobile):has([data-overlay-sidebar=true]) :is(.brx-header-left, .brx-header-right):not([data-builder-modee]) :is(main, footer) :where(section):not(section>section) {
  padding-inline-start: calc(var(--mobile-menu-width) + clamp(1.5rem, calc(0.625vw + 1.375rem), 1.875rem));
  max-inline-size: 100%
}

html:not(.dwc-mobile):has([data-overlay-sidebar=true]) :is(.brx-header-left, .brx-header-right):not([data-builder-modee]) #brx-header {
  border-radius: var(--overlay-sidebar-radius);
  overflow: hidden;
  background: var(--overlay-sidebar-bg);
  box-shadow: var(--overlay-sidebar-shadow) !important;
  inset: var(--overlay-sidebar-inset);
}

html:not(.dwc-mobile):has([data-overlay-sidebar=true]) :is(.brx-header-left, .brx-header-right):not([data-builder-modee]) .dwc-nest-header{
  backdrop-filter: blur(13px);
  background: transparent !important;
}

html:not(.dwc-mobile):has([data-overlay-sidebar=true]):not([data-builder-modee])  .brx-dropdown-content {
   background-color: rgb(255 255 255 / 100%);
}

/*NO BRX-OPEN STYLES*/
html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) #brx-header .dwc-nest-menu.brxe-nav-nested .brx-nav-nested-items {
  display: flex;
  flex-wrap: nowrap;
  flex-direction: column !important;
}


  html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) .dwc-nest-menu.brxe-nav-nested .brxe-dropdown .brx-dropdown-content {
      visibility: visible;
      min-inline-size: var(--mobile-menu-width) !important;
  }


  html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) .dwc-nest-menu[data-submenu-reveal="expand"] .brxe-dropdown.open>.brx-dropdown-content {
   position: static;
}


class SidebarNavigation {
  constructor(options = {}) {
    // Basic configuration properties
    this.config = {
      minWidth: options.minWidth || MegaMenuCONFIG.minWidth, // Using external minWidth variable
      menuSelector: options.menuSelector || '.dwc-nest-menu',
      openClass: options.openClass || 'brx-open',
      activeClasses: options.activeClasses || ['open', 'active'],
      leftHeaderClass: options.leftHeaderClass || 'brx-header-left',
      rightHeaderClass: options.rightHeaderClass || 'brx-header-right',
      debounceDelay: options.debounceDelay || 100,
      menuItemClickDelay: options.menuItemClickDelay || 300
    };
    
    // Set dependent selectors
    const menuSelector = this.config.menuSelector;
    this.config.submenuToggleSelector = options.submenuToggleSelector || `${menuSelector} .brx-submenu-toggle`;
    this.config.dropdownSelector = options.dropdownSelector || `${menuSelector} .brxe-dropdown`;
    this.config.dropdownContentSelector = options.dropdownContentSelector || `${menuSelector} .brx-dropdown-content`;
    
    // State
    this.previousHeaderClass = null;
    this.dropdownClickHandlers = new Map();
    this.menuHoverHandlers = null;
    this.menuItemClickTimeout = null;
    this.keyboardNavHandler = null;
    this.cachedFocusableElements = null;
    this.cachedElements = {
      menuElement: null,
      navElement: null,
      dropdowns: null,
      dropdownToggles: null,
      menuItems: null
    };
    
    // Bind methods to this instance
    this.handleResize = this.debounce(this.handleMenu.bind(this), this.config.debounceDelay);
    this.handleOutsideClick = this.handleOutsideClick.bind(this);
  }
  
  // Initialize everything - called once
  init() {
    // Wait for DOM to be fully loaded before attaching events
    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', () => {
        this.initAfterDOMLoaded();
      }, { once: true });
    } else {
      this.initAfterDOMLoaded();
    }
    
    return this;
  }
  
  // Separate initialization method to run after DOM is loaded
  initAfterDOMLoaded() {
    // Cache DOM elements once
    this.cacheElements();
    
    // Setup resize event with passive flag
    window.addEventListener('resize', this.handleResize, { passive: true });
    
    // Setup mutation observer for critical class changes only
    this.setupMutationObserver();
    
    // Initial setup based on current screen size
    this.handleMenu();
    
    // Cache focusable elements once if header class is present
    if (this.hasHeaderClass()) {
      this.cacheFocusableElements();
      this.setupMenuFocusNavigation();
    }
  }
  
  // Cache all required DOM elements upfront
  cacheElements() {
    this.cachedElements.menuElement = document.querySelector(this.config.menuSelector);
    
    if (this.cachedElements.menuElement) {
      this.cachedElements.navElement = this.cachedElements.menuElement.querySelector('.dwc-nest-nav-items');
      this.cachedElements.dropdowns = Array.from(document.querySelectorAll(this.config.dropdownSelector));
      this.cachedElements.dropdownToggles = Array.from(document.querySelectorAll(this.config.submenuToggleSelector));
      this.cachedElements.menuItems = Array.from(document.querySelectorAll(`${this.config.menuSelector} .menu-item`));
    }
  }
  
  // Set up a focused mutation observer only for dropdown state changes
  setupMutationObserver() {
    if (!this.cachedElements.dropdowns || this.cachedElements.dropdowns.length === 0) return;
    
    const callback = (mutations) => {
      for (let mutation of mutations) {
        if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
          const target = mutation.target;
          const prevClassList = mutation.oldValue ? mutation.oldValue.split(' ') : [];
          const hadBothBefore = prevClassList.includes('open') && prevClassList.includes('active');
          const hasBothNow = target.classList.contains('open') && target.classList.contains('active');
    
          if (hadBothBefore !== hasBothNow) {
            this.updateDropdownAccessibility();
            break; // Only need to update once per batch
          }
        }
      }
    };
    
    // Create observer with optimized options
    this.classObserver = new MutationObserver(callback);
    
    // Observe only the dropdown elements
    this.cachedElements.dropdowns.forEach(dropdown => {
      this.classObserver.observe(dropdown, { 
        attributes: true, 
        attributeFilter: ['class'], 
        attributeOldValue: true 
      });
    });
  }
  
  // Cache focusable elements for keyboard navigation
  cacheFocusableElements() {
    if (!this.cachedElements.navElement) return;
    
    // Get direct children of nav
    const directChildren = Array.from(this.cachedElements.navElement.children);
    
    // Find the first focusable element within each direct child
    this.cachedFocusableElements = directChildren.map(child => {
      // Check if the child itself is focusable
      if (child.matches('a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])')) {
        return child;
      }
      // Otherwise, find the first focusable element within this child
      return child.querySelector('a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])');
    }).filter(Boolean); // Remove null/undefined values
  }
  
  // Clean up all event listeners and observers
  destroy() {
    // Clean up the mutation observer
    if (this.classObserver) {
      this.classObserver.disconnect();
      this.classObserver = null;
    }
    
    // Clean up resize listener
    window.removeEventListener('resize', this.handleResize);
    
    // Clean up click handlers
    if (this.dropdownClickHandlers.size > 0) {
      this.dropdownClickHandlers.forEach((handler, toggle) => {
        toggle.removeEventListener('click', handler);
      });
      this.dropdownClickHandlers.clear();
    }
    
    // Clean up hover handlers
    this.cleanupMenuHover();
    
    // Clean up menu item click handlers
    this.cleanupMenuItemClicks();
    
    // Clean up outside click handler
    document.removeEventListener('click', this.handleOutsideClick);
    
    // Clean up keyboard navigation
    if (this.keyboardNavHandler) {
      document.removeEventListener('keydown', this.keyboardNavHandler);
      this.keyboardNavHandler = null;
    }
    
    // Clear any pending timeouts
    if (this.menuItemClickTimeout) {
      clearTimeout(this.menuItemClickTimeout);
      this.menuItemClickTimeout = null;
    }
  }
  
  // Utility methods
  hasHeaderClass() {
    return document.body.classList.contains(this.config.leftHeaderClass) || 
           document.body.classList.contains(this.config.rightHeaderClass);
  }
  
  debounce(func, delay) {
    let timer;
    return (...args) => {
      clearTimeout(timer);
      timer = setTimeout(() => func(...args), delay);
    };
  }

  // Check if an element has all the required active classes
  hasAllActiveClasses(element) {
    return this.config.activeClasses.every(className => element.classList.contains(className));
  }
  
  // Toggle all active classes on an element
  toggleActiveClasses(element) {
    this.config.activeClasses.forEach(className => {
      element.classList.toggle(className);
    });
  }
  
  // Core functionality methods
  handleMenu() {
    if (!this.cachedElements.menuElement) return;
    if (!this.hasHeaderClass() && !this.previousHeaderClass) return;

    const screenWidth = window.innerWidth;
    const isLargeScreen = screenWidth >= this.config.minWidth;
    const menuElement = this.cachedElements.menuElement;

    if (!isLargeScreen) {
      // Save which class was present before removal
      if (this.hasHeaderClass()) {
        this.previousHeaderClass = document.body.classList.contains(this.config.leftHeaderClass) 
          ? this.config.leftHeaderClass 
          : this.config.rightHeaderClass;
        
        // Remove header classes
        document.body.classList.remove(this.config.leftHeaderClass, this.config.rightHeaderClass);
        menuElement.classList.remove(this.config.openClass);
        
        // Reset accessibility attributes
        this.resetAccessibilityAttributes();
      }
      
      // Clean up event handlers for mobile view
      this.cleanupMenuHover();
      this.cleanupMenuItemClicks();
      this.cleanupDropdownHandlers();
      document.removeEventListener('click', this.handleOutsideClick);
      
      return;
    }

    // Large screen behavior
    if (!this.hasHeaderClass() && this.previousHeaderClass) {
      document.body.classList.add(this.previousHeaderClass);
    }

    if (this.hasHeaderClass()) {
      if (!menuElement.classList.contains(this.config.openClass)) {
        menuElement.classList.add(this.config.openClass);
      }
      
      // Setup elements for large screen view
      this.setupMenuHover();
      this.setupMenuItemClicks();
      this.setupDropdownHandlers();
      this.setupMenuFocusNavigation();
      this.updateDropdownAccessibility();
      
      // Ensure outside click handler is set up
      document.removeEventListener('click', this.handleOutsideClick);
      document.addEventListener('click', this.handleOutsideClick, { passive: false });
    }
  }
  
  // Reset accessibility attributes when switching to mobile
  resetAccessibilityAttributes() {
    if (!this.cachedElements.dropdowns) return;
    
    // Remove all inert attributes from dropdown contents
    this.cachedElements.dropdowns.forEach(dropdown => {
      const content = dropdown.querySelector(this.config.dropdownContentSelector);
      if (content) {
        content.removeAttribute('inert');
      }
      
      const button = dropdown.querySelector('button');
      if (button) {
        button.setAttribute('aria-expanded', 'false');
      }
    });
  }
  
  setupMenuFocusNavigation() {
    // Only run if hasHeaderClass() is true and we have focusable elements
    if (!this.hasHeaderClass() || !this.cachedFocusableElements || this.cachedFocusableElements.length === 0) {
      return;
    }
    
    // Clean up previous handler if it exists
    if (this.keyboardNavHandler) {
      document.removeEventListener('keydown', this.keyboardNavHandler, true);
      this.keyboardNavHandler = null;
    }
    
    const navMenu = this.cachedElements.menuElement;
    const focusableElements = this.cachedFocusableElements;
    const firstFocusableElement = focusableElements[0];
    const lastFocusableElement = focusableElements[focusableElements.length - 1];
    
    // Find adjacent focusable elements outside the menu (only once during setup)
    const headerElement = navMenu.closest('header') || document.querySelector('header');
    
    // Prepare variables to hold adjacent elements
    let prevFocusableElement = null;
    let nextFocusableElement = null;
    let firstElementAfterHeader = null;
    
    if (headerElement) {
      // Get all focusable elements within the header - do this once and cache the result
      const headerFocusables = Array.from(
        headerElement.querySelectorAll('a:not([tabindex="-1"]), button:not([tabindex="-1"]), input:not([tabindex="-1"]), select:not([tabindex="-1"]), textarea:not([tabindex="-1"]), [tabindex]:not([tabindex="-1"])')
      ).filter(el => window.getComputedStyle(el).display !== 'none');
      
      // Find the index of our first and last menu elements in one pass
      const menuStartIndex = headerFocusables.indexOf(firstFocusableElement);
      const menuEndIndex = headerFocusables.indexOf(lastFocusableElement);
      
      // Cache the adjacent elements
      if (menuStartIndex > 0) {
        prevFocusableElement = headerFocusables[menuStartIndex - 1];
      }
      
      if (menuEndIndex !== -1 && menuEndIndex < headerFocusables.length - 1) {
        nextFocusableElement = headerFocusables[menuEndIndex + 1];
      }
      
      // Pre-calculate the first element after header - but only if needed
      if (!nextFocusableElement) {
        // Use a more efficient selector that targets immediate children of body that aren't the header
        const selector = 'body > *:not(header)';
        const nonHeaderElements = document.querySelectorAll(selector);
        
        // Only process if we have elements
        if (nonHeaderElements.length > 0) {
          // Create a function to find the first focusable element (used later if needed)
          this.findFirstFocusableAfterHeader = () => {
            for (const element of nonHeaderElements) {
              const focusable = element.querySelector('a:not([tabindex="-1"]), button:not([tabindex="-1"]), input:not([tabindex="-1"]), select:not([tabindex="-1"]), textarea:not([tabindex="-1"]), [tabindex]:not([tabindex="-1"])');
              if (focusable && window.getComputedStyle(focusable).display !== 'none') {
                return focusable;
              }
            }
            return null;
          };
        }
      }
    }
    
    // Create keyboard navigation handler with closure over the cached elements
    this.keyboardNavHandler = (e) => {
      // Quick check for Tab key first
      if (e.key !== 'Tab') return;
      
      // Then check if focus is inside the menu
      if (!navMenu.contains(document.activeElement)) return;
      
      let targetElement = null;
      
      // Handle tab navigation at boundaries only
      if (!e.shiftKey && document.activeElement === lastFocusableElement) {
        // Forward tab from last element
        e.preventDefault();
        e.stopPropagation();
        
        if (nextFocusableElement) {
          targetElement = nextFocusableElement;
        } else if (this.findFirstFocusableAfterHeader) {
          // Only search for elements after header if needed and not already found
          firstElementAfterHeader = this.findFirstFocusableAfterHeader();
          targetElement = firstElementAfterHeader;
        }
        
        // Focus on the target or body as fallback
        setTimeout(() => {
          if (targetElement) {
            targetElement.focus();
          } else {
            document.body.setAttribute('tabindex', '-1');
            document.body.focus();
            document.body.removeAttribute('tabindex');
          }
        }, 10);
      } 
      else if (e.shiftKey && document.activeElement === firstFocusableElement) {
        // Backward tab from first element
        e.preventDefault();
        e.stopPropagation();
        
        setTimeout(() => {
          if (prevFocusableElement) {
            prevFocusableElement.focus();
          } else {
            document.body.setAttribute('tabindex', '-1');
            document.body.focus();
            document.body.removeAttribute('tabindex');
          }
        }, 10);
      }
    };
    
    // Use capture phase for the event
    document.addEventListener('keydown', this.keyboardNavHandler, true);
  }
  
  setupMenuHover() {
    const menuElement = this.cachedElements.menuElement;
    if (!menuElement) return;
    
    // Clean up existing hover handlers first
    this.cleanupMenuHover();
    
    // Create event handlers
    const mouseenterHandler = () => {
      menuElement.classList.add(this.config.openClass);
    };
    
    const mouseleaveHandler = () => {
      menuElement.classList.remove(this.config.openClass);
    };
    
    // Add event listeners with passive flag for better performance
    menuElement.addEventListener('mouseenter', mouseenterHandler, { passive: true });
    menuElement.addEventListener('mouseleave', mouseleaveHandler, { passive: true });
    
    // Store the handlers for cleanup
    this.menuHoverHandlers = {
      element: menuElement,
      mouseenter: mouseenterHandler,
      mouseleave: mouseleaveHandler
    };
  }
  
  cleanupMenuHover() {
    if (this.menuHoverHandlers) {
      const { element, mouseenter, mouseleave } = this.menuHoverHandlers;
      element.removeEventListener('mouseenter', mouseenter);
      element.removeEventListener('mouseleave', mouseleave);
      this.menuHoverHandlers = null;
    }
  }
  
  setupMenuItemClicks() {
    if (!this.cachedElements.menuItems || this.cachedElements.menuItems.length === 0) return;
    
    // Clean up existing handlers first
    this.cleanupMenuItemClicks();
    
    const menuElement = this.cachedElements.menuElement;
    const menuItemHandlers = new Map();
    
    this.cachedElements.menuItems.forEach(item => {
      const clickHandler = () => {
        if (this.hasHeaderClass()) {
          // Clear any existing timeout
          if (this.menuItemClickTimeout) {
            clearTimeout(this.menuItemClickTimeout);
          }
          
          // Set timeout before adding the class
          this.menuItemClickTimeout = setTimeout(() => {
            if (!menuElement.classList.contains(this.config.openClass)) {
              menuElement.classList.add(this.config.openClass);
            }
          }, this.config.menuItemClickDelay);
        }
      };
      
      menuItemHandlers.set(item, clickHandler);
      item.addEventListener('click', clickHandler);
    });
    
    this.menuItemClickHandlers = menuItemHandlers;
  }
  
  cleanupMenuItemClicks() {
    if (this.menuItemClickHandlers && this.menuItemClickHandlers instanceof Map) {
      this.menuItemClickHandlers.forEach((handler, item) => {
        item.removeEventListener('click', handler);
      });
      this.menuItemClickHandlers.clear();
    }
    
    if (this.menuItemClickTimeout) {
      clearTimeout(this.menuItemClickTimeout);
      this.menuItemClickTimeout = null;
    }
  }
  
  setupDropdownHandlers() {
    if (!this.hasHeaderClass() || !this.cachedElements.dropdownToggles) return;
    
    // Clean up existing handlers first
    this.cleanupDropdownHandlers();
    
    this.cachedElements.dropdownToggles.forEach(toggle => {
      const clickHandler = (event) => {
        event.stopPropagation();
        event.preventDefault();
        
        const dropdown = toggle.closest(this.config.dropdownSelector);
        if (dropdown) {
          this.toggleActiveClasses(dropdown);
          this.updateDropdownAccessibility();
        }
      };
      
      this.dropdownClickHandlers.set(toggle, clickHandler);
      toggle.addEventListener('click', clickHandler);
    });
  }
  
  cleanupDropdownHandlers() {
    if (this.dropdownClickHandlers.size > 0) {
      this.dropdownClickHandlers.forEach((handler, toggle) => {
        toggle.removeEventListener('click', handler);
      });
      this.dropdownClickHandlers.clear();
    }
  }
  
  handleOutsideClick(event) {
    if (event.target.tagName === 'A') return;
    if (!event.target.closest(this.config.dropdownSelector)) return;
    if (!event.target.closest(this.config.submenuToggleSelector)) {
      event.preventDefault();
      event.stopPropagation();
    }
  }
  
  updateDropdownAccessibility() {
    // Only run if hasHeaderClass() is true
    if (!this.hasHeaderClass() || !this.cachedElements.dropdowns) return;
    
    this.cachedElements.dropdowns.forEach(dropdown => {
      const content = dropdown.querySelector(this.config.dropdownContentSelector);
      const button = dropdown.querySelector('button');
      
      // Check if dropdown has all active classes
      const isOpen = this.hasAllActiveClasses(dropdown);
      
      if (content) {
        if (isOpen) {
          content.removeAttribute('inert');
        } else {
          content.setAttribute('inert', '');
        }
      }
      
      if (button) {
        button.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
      }
    });
  }
}


const sidebarNav = new SidebarNavigation().init();

New Westminster construction services

Construction Services Informed by Heritage and Urban Development in New Westminster, BC

From heritage restorations to modern property transformations, VALROC delivers full-scope construction services across New Westminster, combining engineering, craftsmanship, and hands-on experience to build from the front of your property to the back.

Customer confidence

Why New Westminster customers can plan with confidence

New Westminster construction often requires thoughtful planning around older buildings, heritage context, compact lots, lanes, mature infrastructure, and limited staging.

What clients value

  • Insurance and liability coverage that helps protect the homeowner
  • Detailed contracts covering materials, payment schedules, walkthroughs, and warranties
  • Competitive pricing supported by coordinated scheduling and in-house services
  • One accountable contractor for communication, scheduling, trades, and project efficiencies
  • Reliable crews, consistent communication, and project accountability from start to finish

Careful planning for established New Westminster properties

Older buildings, compact lots, lanes, mature infrastructure, and close neighbours can make sequencing as important as the work itself in New Westminster. We examine these conditions before setting the approach.

Customers receive a coordinated plan for access, protection, equipment, materials, disposal, and the services required to complete the agreed result.

Local construction planning

Construction support for New Westminster properties

Construction planning in New Westminster starts with the property, the municipal jurisdiction, and the practical conditions that affect approvals, access, sequencing, equipment, and material movement.

CONSTRUCTION SERVICE DIRECTORY

Browse construction services by category

Open the complete construction service hub, choose a service category, or go directly to a core service.

Decisions before construction

What we assess during a New Westminster on-site visit

A site conversation can identify alternatives before costs are committed, particularly where tight staging, lanes, neighbouring buildings, existing services, traffic, deliveries, and occupied spaces affect the plan.

01

Property and access

Review tight staging, lanes, neighbouring buildings, existing services, traffic, deliveries, and occupied spaces in relation to the result you want and the equipment or material movement the work may require.

02

City of New Westminster requirements

Identify likely City building and demolition requirements, utility-locate responses, disposal requirements, and property-specific questions before finalizing the sequence.

03

Phasing around the property

Coordinate crews, deliveries, occupied areas, hauling, and site protection so the construction sequence reflects how this New Westminster property is actually used.

A practical route forward

How a New Westminster project moves from idea to construction

The exact sequence depends on the work and property. Early review of City of New Westminster requirements, access, disposal, equipment, and customer priorities helps turn an idea into a coordinated plan.

Confirm City requirements

Identify likely New Westminster permits, heritage or property considerations, utility locates, disposal needs, and technical details.

Plan compact-site logistics

Coordinate crews, smaller or specialized equipment, deliveries, hauling, protection, and staging around active streets and neighbours.

Complete and document the work

Build the agreed scope in sequence, review important existing and finished details, and provide a clear customer handoff.

Understand the existing property

Review the intended result, older construction, access, lanes, neighbours, utilities, drainage, and the room available for work.

What customers gain from the way we work

Customer benefits behind a well-planned New Westminster project

These advantages help customers evaluate more than a price, including project clarity, relevant experience, site coordination, in-house capability, and the way disruption will be managed.

Customer benefit icon

Minimal Disruptions, Maximum Efficiency

We respect your time and space, ensuring efficient construction with minimal disruptions to your home or business.

Customer benefit icon

Comprehensive Contracts – No Surprises, Just Clarity

Our contracts eliminate guesswork with clearly defined terms, pricing, timelines, and warranties, ensuring total transparency and peace of mind.

Customer benefit icon

Expertise Built on Hundreds of Completed Projects

With a strong portfolio of completed work, our experience ensures high-quality craftsmanship and efficient project execution.

Customer benefit icon

Advanced Service Fleet & Specialized Equipment

Our extensive fleet of heavy-duty machinery, mobile service trucks, and specialized tools ensures unmatched efficiency and precision on every job site.

In-house capability

Equipment that supports construction work in New Westminster

Our Langley yard provides a base for selecting and staging equipment for New Westminster projects around access, excavation depth, hauling, material movement, compaction, and the actual scope of work.

John Deere excavator representing VALROC's compact to large excavator fleet.
Excavation and demolition site in Metro Vancouver with heavy machinery preparing for new construction.

Excavation fleet

Excavators matched to the site

Our in-house range includes compact machines for tight access, mid-size excavators for precise residential work, larger Deere excavators for deeper excavation and material handling, plus hydraulic breaker capability for concrete and rock removal.

  • Large, medium, small excavators
  • Demolition, Site preparation
  • Hydraulic hammers, crushers
  • Multiple attachments
Ammann ARX 2.1-2 and ARX 2-2 light tandem rollers featuring advanced articulation joints and electronic drive levers for precise asphalt and soil compaction.
Asphalt paving with a modern roller compactor in Metro Vancouver construction site.

Heavy Machinery & Earthmoving Equipment

Tandem Roller Compactor

Delivers smooth, even asphalt and soil compaction, improving surface durability and road longevity.

Heavy-duty flatbed service and delivery truck used for transporting equipment, towing gooseneck trailers, and carrying on-site fuel tanks.
Modern building renovation site in Vancouver featuring VALROC Development Ltd. truck for construction and building improvements.

Mobile Construction Equipped Service Vehicles

Flatbed Service & Delivery Truck

Facilitates equipment and material transport, allowing us to move multiple machines and long materials efficiently.

Wacker Neuson DT08 track dumper – compact 0.8-ton payload machine with hydrostatic drive and 79 cm width, ideal for confined construction sites.
Efficient street paving in Vancouver with Wacker Neuson mini dumper for smooth road construction.

Heavy Machinery & Earthmoving Equipment

Rubber Track Dumper

A compact, maneuverable track dumper that allows us to transport materials through tight spaces, improving site logistics and reducing manual labour.

International single-axle dump truck used for hauling materials, demolition debris, and construction site logistics.
Professional construction truck at VALROC Development Ltd. site in Metro Vancouver, showcasing quality renovation and development services.

Heavy Machinery & Earthmoving Equipment

Single Axle Dump Truck

A high-capacity hauler for transporting materials, debris, and equipment, streamlining job site cleanup and logistics.

Hino 198 box truck – a fully equipped 3-ton mobile service truck carrying essential contracting tools for concrete, asphalt, and carpentry work.
Reliable Vancouver-based construction and development services by Valroc Development Ltd. in Metro Vancouver.

Mobile Construction Equipped Service Vehicles

Fully Stocked Mobile Service Truck

Our fully equipped mobile service truck, essential for transporting contracting tools, materials, and heavy-duty equipment, ensuring on-site readiness and maximum efficiency.

John Deere 320D Skid Steer Loader with a 63 hp engine and 2,000 lbs operating capacity, ideal for versatile construction tasks.
Excavator working in a lush forested area for land clearing and excavation services.

Heavy Machinery & Earthmoving Equipment

Versatile Skid Steer Loader

A compact excavator with strong digging power, perfect for tight job sites requiring precision excavation.

High-value planning information

Local resources for construction decisions

Verified municipal, utility, recycling, and disposal contacts for construction decisions in New Westminster. Use each section for a focused task, then confirm current requirements with the authority before acting.

Municipal information for construction planning in New Westminster, British Columbia.

Common local questions

Frequently asked questions for New Westminster

Open only the answer you need. These questions remain connected through the existing Location relationship.

Do I need a permit for a new driveway in New Westminster?

If you are constructing a brand-new driveway in New Westminster, you will likely need a permit. The city requires permits for modifications that alter the existing layout, size, or access points.

However, repairs or resurfacing of an existing driveway may not require a permit, depending on the scope of work. The Engineering Department at City Hall can provide official guidelines, but before you go through that process, VALROC Development Ltd. can assist in determining whether a permit is necessary and guide you through the approval process.

New Westminster has specific regulations concerning driveway width, materials, and placement to ensure alignment with zoning and road safety bylaws. Many homeowners prefer working with experienced contractors like VALROC to handle this process smoothly. If you’re considering a new driveway installation or replacement, contact us first for a consultation and on-site assessment.

Do I need a permit for a new driveway in New Westminster?

If you are constructing a brand-new driveway in New Westminster, you will likely need a permit. The city requires permits for modifications that alter the existing layout, size, or access points.

However, repairs or resurfacing of an existing driveway may not require a permit, depending on the scope of work. The Engineering Department at City Hall can provide official guidelines, but before you go through that process, VALROC Development Ltd. can assist in determining whether a permit is necessary and guide you through the approval process.

New Westminster has specific regulations concerning driveway width, materials, and placement to ensure alignment with zoning and road safety bylaws. Many homeowners prefer working with experienced contractors like VALROC to handle this process smoothly. If you’re considering a new driveway installation or replacement, contact us first for a consultation and on-site assessment.

What types of construction projects has VALROC completed in New Westminster?

New Westminster is a city with a rich architectural history and evolving infrastructure, making it an exciting place for construction projects of all sizes. We’ve worked on heritage restorations, custom homes, commercial sites, and municipal projects, tailoring our approach to the city’s unique building requirements. Our experience includes:

Heritage Restorations & Historic Property Upgrades

With its deep-rooted history, New Westminster has many designated heritage homes and commercial properties. We have worked on exterior restorations, foundation reinforcements, and facade preservation projects, ensuring compliance with heritage conservation policies while modernizing structures for durability and energy efficiency.

Custom Home Builds & Major Renovations

From expanding character homes to building modern custom residences, we’ve helped homeowners enhance their properties. Whether it’s a full remodel, a home addition, or a high-end new build, we bring expertise in both contemporary and traditional construction methods.

Concrete Driveways, Sidewalks & Structural Pads

We’ve constructed reinforced driveways, walkways, and concrete pads that align with city guidelines. Our team understands the terrain challenges of New Westminster and ensures proper drainage, compaction, and finishing techniques to maximize longevity.

Commercial & Industrial Construction

Business owners in New Westminster have trusted us for tenant improvements, storefront renovations, warehouse expansions, and foundation work. We prioritize efficient scheduling to minimize downtime while delivering high-quality, code-compliant commercial builds.

Asphalt Paving for Parking Lots & Roadways

From parking lot resurfacing to new roadway installations, our asphalt services provide smooth, durable surfaces that withstand heavy traffic and varied weather conditions. We ensure all paving work meets municipal specifications for proper grading and drainage.

Excavation & Site Preparation

Whether for new home construction or commercial development, our excavation and site preparation services ensure solid groundwork. We manage grading, trenching, foundation digs, and drainage solutions to support long-term structural integrity.

If you’re planning a construction project in New Westminster, we’d love to discuss your vision and guide you through the process. Contact VALROC Development Ltd. today for expert planning, execution, and quality workmanship.

What types of construction projects has VALROC completed in New Westminster?

New Westminster is a city with a rich architectural history and evolving infrastructure, making it an exciting place for construction projects of all sizes. We’ve worked on heritage restorations, custom homes, commercial sites, and municipal projects, tailoring our approach to the city’s unique building requirements. Our experience includes:

Heritage Restorations & Historic Property Upgrades

With its deep-rooted history, New Westminster has many designated heritage homes and commercial properties. We have worked on exterior restorations, foundation reinforcements, and facade preservation projects, ensuring compliance with heritage conservation policies while modernizing structures for durability and energy efficiency.

Custom Home Builds & Major Renovations

From expanding character homes to building modern custom residences, we’ve helped homeowners enhance their properties. Whether it’s a full remodel, a home addition, or a high-end new build, we bring expertise in both contemporary and traditional construction methods.

Concrete Driveways, Sidewalks & Structural Pads

We’ve constructed reinforced driveways, walkways, and concrete pads that align with city guidelines. Our team understands the terrain challenges of New Westminster and ensures proper drainage, compaction, and finishing techniques to maximize longevity.

Commercial & Industrial Construction

Business owners in New Westminster have trusted us for tenant improvements, storefront renovations, warehouse expansions, and foundation work. We prioritize efficient scheduling to minimize downtime while delivering high-quality, code-compliant commercial builds.

Asphalt Paving for Parking Lots & Roadways

From parking lot resurfacing to new roadway installations, our asphalt services provide smooth, durable surfaces that withstand heavy traffic and varied weather conditions. We ensure all paving work meets municipal specifications for proper grading and drainage.

Excavation & Site Preparation

Whether for new home construction or commercial development, our excavation and site preparation services ensure solid groundwork. We manage grading, trenching, foundation digs, and drainage solutions to support long-term structural integrity.

If you’re planning a construction project in New Westminster, we’d love to discuss your vision and guide you through the process. Contact VALROC Development Ltd. today for expert planning, execution, and quality workmanship.

How do I choose the right construction contractor in New Westminster?

Choosing the right contractor is one of the most critical steps in your construction project. Here’s what you should look for:

  • Experience & Specialization – Ensure your contractor has relevant experience with projects similar to yours.
  • Licensing & Insurance – Always verify that the contractor is licensed and carries liability insurance and WorkSafeBC coverage.
  • Local Reputation – Read reviews, ask for references, and check portfolios of past work.
  • Transparent Pricing & Contracts – A reputable contractor provides detailed quotes and clear contracts outlining materials, timelines, and expectations.

VALROC Development Ltd. has built a strong reputation in New Westminster, with completed projects ranging from high-end residential builds to commercial site work. Contact us to see how we can help with your construction needs.

How do I choose the right construction contractor in New Westminster?

Choosing the right contractor is one of the most critical steps in your construction project. Here’s what you should look for:

  • Experience & Specialization – Ensure your contractor has relevant experience with projects similar to yours.
  • Licensing & Insurance – Always verify that the contractor is licensed and carries liability insurance and WorkSafeBC coverage.
  • Local Reputation – Read reviews, ask for references, and check portfolios of past work.
  • Transparent Pricing & Contracts – A reputable contractor provides detailed quotes and clear contracts outlining materials, timelines, and expectations.

VALROC Development Ltd. has built a strong reputation in New Westminster, with completed projects ranging from high-end residential builds to commercial site work. Contact us to see how we can help with your construction needs.

What should I know before starting a construction project in New Westminster?

Before beginning a construction project, consider these key points:

  • Permitting & Zoning – Some projects require permits, which we can assist in obtaining.
  • Project Timeline – Factor in planning, permit approval, and material procurement when setting deadlines.
  • Budgeting & Costs – Have a clear understanding of project costs and potential contingencies.
  • Contractor Selection – Work with a trusted contractor to manage all aspects of your project.

Our team at VALROC Development Ltd. can walk you through every step, from planning to execution, ensuring a stress-free experience.

What should I know before starting a construction project in New Westminster?

Before beginning a construction project, consider these key points:

  • Permitting & Zoning – Some projects require permits, which we can assist in obtaining.
  • Project Timeline – Factor in planning, permit approval, and material procurement when setting deadlines.
  • Budgeting & Costs – Have a clear understanding of project costs and potential contingencies.
  • Contractor Selection – Work with a trusted contractor to manage all aspects of your project.

Our team at VALROC Development Ltd. can walk you through every step, from planning to execution, ensuring a stress-free experience.

How does zoning affect my construction project in New Westminster?

Zoning laws in New Westminster regulate land use, building height, property setbacks, and lot coverage. Before starting any construction, you need to ensure your project complies with local zoning regulations. Certain neighbourhoods may also have heritage designations requiring additional approvals.

Our team has extensive experience navigating local zoning requirements. If you’re unsure about how zoning affects your project, VALROC can assess your plans and help streamline the approval process, reducing potential roadblocks.

How does zoning affect my construction project in New Westminster?

Zoning laws in New Westminster regulate land use, building height, property setbacks, and lot coverage. Before starting any construction, you need to ensure your project complies with local zoning regulations. Certain neighbourhoods may also have heritage designations requiring additional approvals.

Our team has extensive experience navigating local zoning requirements. If you’re unsure about how zoning affects your project, VALROC can assess your plans and help streamline the approval process, reducing potential roadblocks.

What should I do if I have concerns during my construction project?

Open communication is key to a successful construction project. If you have concerns:

  • Document the issue – Take photos and notes on any areas of concern.
  • Communicate with your contractor – Raise issues promptly to address them before they escalate.
  • Refer to your contract – Ensure all work aligns with the agreed-upon terms.

At VALROC, we prioritize transparency and customer satisfaction. If something doesn’t seem right, we work with our clients to resolve issues quickly and professionally.

What should I do if I have concerns during my construction project?

Open communication is key to a successful construction project. If you have concerns:

  • Document the issue – Take photos and notes on any areas of concern.
  • Communicate with your contractor – Raise issues promptly to address them before they escalate.
  • Refer to your contract – Ensure all work aligns with the agreed-upon terms.

At VALROC, we prioritize transparency and customer satisfaction. If something doesn’t seem right, we work with our clients to resolve issues quickly and professionally.

How can I ensure my project stays on schedule?

Several factors influence a project’s timeline, including permit approvals, weather, and material availability. To keep your project on track:

  • Plan ahead – Finalize design choices and permit applications early.
  • Choose a reliable contractor – Work with a team that manages timelines effectively.
  • Maintain clear communication – Regular updates between the contractor and client prevent misalignment.

VALROC Development Ltd. takes a proactive approach to project scheduling, ensuring efficient and timely completion of every job.


For more information about starting your construction project in New Westminster, contact VALROC Development Ltd. today. We’re here to assist with everything from planning and permits to full-scale execution!

How can I ensure my project stays on schedule?

Several factors influence a project’s timeline, including permit approvals, weather, and material availability. To keep your project on track:

  • Plan ahead – Finalize design choices and permit applications early.
  • Choose a reliable contractor – Work with a team that manages timelines effectively.
  • Maintain clear communication – Regular updates between the contractor and client prevent misalignment.

VALROC Development Ltd. takes a proactive approach to project scheduling, ensuring efficient and timely completion of every job.


For more information about starting your construction project in New Westminster, contact VALROC Development Ltd. today. We’re here to assist with everything from planning and permits to full-scale execution!