/*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();

COOK AND GATHER OUTSIDE

Custom Outdoor Kitchens & BBQ Areas Built for Metro Vancouver Entertaining

Fully equipped outdoor kitchens with custom countertops, built in grills, and durable finishes for year round entertaining. An outdoor kitchen should fit the patio or deck, the way people cook and the services the selected appliances require. VALROC reviews the base, layout, weather exposure and utility routes before defining the build.

Appliances, utilities and weather protection are planned around how the outdoor kitchen will be used.

Covered patio deck under construction with brick home exterior and VALROC excavator on site
LAYOUT

Plan the cooking flow

Locate preparation, cooking and serving zones around safe circulation.

BASE

Check the supporting surface

Assess the patio or deck before adding cabinets and appliances.

SERVICES

Coordinate utilities early

Plan gas, power, water and drainage only where selected and feasible.

PLAN THE COOKING SPACE

Define the outdoor kitchen build sequence

Outdoor kitchen construction begins with how you cook and entertain, followed by base review, appliance layout, material selection, utility coordination, assembly and finishing. The sequence responds to the property and selected features.

Hardscape Construction in Action, Maximize Potential

This video showcases VALROC’s hardscape construction projects across Metro Vancouver, including retaining walls, outdoor kitchens, patios, and structural security installations. Each installation reflects our in-house approach to excavation, concrete work, and integrated outdoor construction built for long-term durability and performance.

can you 

A SPACE BUILT TO BE USED

Fit the kitchen to cooking and gathering

Custom outdoor kitchens built to support everyday cooking, entertaining, and year round use.

Fully integrated utilities including gas, plumbing, lighting, and heating for safe, reliable operation.

Durable, weather resistant materials selected for long term performance in Metro Vancouver conditions.

VALROC Development Ltd. designs and builds functional, stylish outdoor kitchens that turn your backyard into a year round destination. Our expertise lies in creating unique spaces tailored to meet your culinary needs, whether you’re grilling for the family or hosting guests. Our custom solutions integrate seamlessly with your outdoor space, providing comfort and convenience.

Designs That Fit Your Cooking Style

When designing an outdoor kitchen, it’s essential to consider your cooking style and preferences. We work closely with you to ensure the layout and features reflect your culinary habits, allowing you to enjoy every moment spent in your outdoor kitchen.

Every kitchen is built to fit your lifestyle, whether it’s weekday dinners or weekend hosting.

Everything You Need, Outdoors

One popular design trend is creating zones within your outdoor kitchen for different cooking styles, which can enhance functionality and make entertaining easier. For example, you could dedicate one area for grilling and another for pizza making, ensuring a variety of cooking options at your fingertips.

With careful planning and design, your outdoor kitchen can become a highlight of your home, perfect for social gatherings, family meals, and everything in between. Imagine hosting summer barbecues with friends, where the outdoor kitchen serves as the hub for cooking and socializing, or enjoying quiet evenings cooking under the stars.

Outdoor kitchens and BBQ areas combine a durable base, usable counters, selected cooking equipment and weather appropriate materials. The right layout depends on how the yard connects to the home and whether qualified trades must provide gas, electrical or plumbing work.

COOKING

Choose equipment first

Use appliance dimensions and clearances to inform the layout.

COUNTERS

Make room to prepare

Plan working surfaces, storage and serving space.

WEATHER

Select outdoor materials

Review exposure, cleaning and seasonal protection.

ACCESS

Connect the gathering area

Consider paths, seating and movement around hot surfaces.

SELECT FOR THE SITE

Outdoor kitchen choices to make with context

Plan the outdoor kitchen around how you cook, serve and entertain. Appliances, counters, storage, seating, lighting and utility connections can be coordinated for the available space and seasonal use.

Outdoor kitchen and BBQ area project support

Included in our service:

  • • Outdoor kitchen layout and use planning

  • • Patio, counter and appliance coordination

  • • Gas, electrical and plumbing trade planning

  • • Weather resistant material selections

  • • Drainage and finished elevation review

  • • Established supplier and delivery scheduling

  • • Lighting, seating and storage integration

  • • Permit coordination when required

  • • Construction phase walkthroughs

  • • Final setup review and project handoff

BBQ equipment, countertop materials, cabinets, seating, lighting and utility connections can be combined around the way you cook, serve and entertain outdoors.

Build around the way you entertain

PLAN THE INTERFACES

Connect the kitchen to the outdoor space

An outdoor kitchen can connect naturally with a concrete patio, walkway, steps, drainage and the wider home renovation or custom build. Planning these interfaces together can create a more comfortable and useful outdoor living area.

Patios, walkways, steps, weather protection and utility routes can be coordinated as connected services when they support the property and outdoor kitchen design.

  • Reinforcing steel for concrete patio installation in Vancouver.

    Concrete patios for outdoor kitchens and BBQ areas

    • Outdoor kitchen patio
    • Concrete entertaining area
    • BBQ space

    A concrete patio can provide the durable floor and gathering space around an outdoor kitchen. Coordinating the slab layout with cooking zones, dining space and appliance clearances creates a more usable backyard.

    Explore concrete patio installation
  • Man working on staircase construction in Vancouver, BC, residential project, building new wooden steps.

    Concrete steps for raised outdoor cooking areas

    • Outdoor kitchen steps
    • Patio access
    • Elevation transition

    Steps may be needed where an outdoor kitchen connects to a raised doorway, patio or sloped yard. Planning landings and travel routes with the cooking area improves access and keeps movement away from hot surfaces.

    Explore concrete steps and staircases
  • Sidewalk leading up to the front door through engineered concrete walls. The sidewalk still have the wooden forms as they are freshly poured with concrete.

    Concrete walkways connecting outdoor kitchens

    • Outdoor kitchen walkway
    • Backyard access
    • Concrete path

    A sidewalk can create a comfortable route between the house, outdoor kitchen, garden and side yard. Coordinating walkway width and finished elevations makes serving, entertaining and everyday access easier.

    Explore concrete sidewalk installation
  • Luxury custom home build with lots of amazing features, showing a construction sign of Valroc Development Ltd. showing it's thier construction site

    Outdoor kitchens planned with custom homes

    • Custom home outdoor kitchen
    • Outdoor living
    • Utility planning

    A custom home build offers the opportunity to coordinate outdoor cooking, utilities, doors and covered living areas from the beginning. Early planning can create a stronger connection between the interior kitchen and backyard.

    Explore custom home construction
  • Complete home renovation in progress with exposed framing, scaffolding, and excavation

    Outdoor kitchens within home renovation plans

    • Renovation outdoor kitchen
    • Backyard entertaining
    • Indoor outdoor living

    A whole home renovation can extend living space outdoors with a coordinated kitchen and entertaining area. Aligning doors, patios, lighting and utilities helps the new outdoor area feel connected to the home.

    Explore whole home renovations

DOCUMENTED EXPERIENCE

Outdoor kitchen experience shaped around the property

VALROC brings concrete, drainage, structural and complete property improvement experience to outdoor kitchens across Metro Vancouver. This broader knowledge helps connect the cooking area to patios, walkways, utilities, weather protection and the way people gather outdoors. From Langley neighbourhoods such as Willoughby and Walnut Grove to South Surrey, White Rock and Burnaby, we understand how outdoor living plans must respond to lot size, access, weather exposure and local building requirements.

PLAN THE OUTDOOR KITCHEN

Plan an outdoor kitchen around your property

Share the property, intended use and available plans with VALROC. An onsite review can shape an outdoor kitchen plan around the space and the way you want to use it.

  • Share the project

    Explain the site, intended use and known constraints.

  • Review the property

    Review the existing patio or deck, available space, wind and rain exposure, appliance plans, access and potential utility routes before designing the outdoor kitchen.

  • Shape the kitchen plan

    Review the layout, selected features, connected work and next steps.

  • What affects an outdoor kitchen estimate?

    Base condition, layout, materials, appliances, utility distances, access and weather protection choices shape the outdoor kitchen investment. A property review is needed before providing a specific price.

    What affects an outdoor kitchen estimate?

    Base condition, layout, materials, appliances, utility distances, access and weather protection choices shape the outdoor kitchen investment. A property review is needed before providing a specific price.

    Request Your Free On-site Estimate

    REVIEW THE SITE CONDITIONS

    Assess the site before designing the kitchen

    Review the existing patio or deck, available space, wind and rain exposure, appliance plans, access and potential utility routes before designing the outdoor kitchen.

  • 01

    Define the intended use

    Explain what the completed outdoor space must support.

  • 02

    Review the property

    Review the existing patio or deck, available space, wind and rain exposure, appliance plans, access and potential utility routes before designing the outdoor kitchen.

  • 03

    Identify approvals

    Check drawings, permits and inspection responsibilities for the proposed work.

  • 04

    Coordinate the complete space

    Connect appliances, utilities, finishes, access and adjoining outdoor areas.

  • What needs confirmation

    An existing deck may need a capacity review, and gas, electrical or plumbing work requires qualified trades and applicable approvals. Manufacturer clearances must govern the selected appliances.

    What needs confirmation

    An existing deck may need a capacity review, and gas, electrical or plumbing work requires qualified trades and applicable approvals. Manufacturer clearances must govern the selected appliances.

    ANSWERS REQUIRE SITE CONTEXT

    Questions about outdoor kitchens and BBQ areas

    The linked questions address features, materials, utilities, appliance selection, permits and Metro Vancouver weather. Each answer must be checked against the selected product and actual site.

    What are the benefits of having an outdoor kitchen or BBQ area?

    An outdoor kitchen or BBQ area expands how you use your property and makes outdoor spaces more practical.

    • Creates additional cooking and dining space outside the home.
    • Makes it easier to host family gatherings or casual get-togethers.
    • Reduces traffic in the indoor kitchen during events.
    • Adds long-term functional value to the property.
    • Allows cooking areas to be designed for weather and outdoor use.

    When planned properly, outdoor kitchens become a natural extension of the home.

    What are the benefits of having an outdoor kitchen or BBQ area?

    An outdoor kitchen or BBQ area expands how you use your property and makes outdoor spaces more practical.

    • Creates additional cooking and dining space outside the home.
    • Makes it easier to host family gatherings or casual get-togethers.
    • Reduces traffic in the indoor kitchen during events.
    • Adds long-term functional value to the property.
    • Allows cooking areas to be designed for weather and outdoor use.

    When planned properly, outdoor kitchens become a natural extension of the home.

    What features can VALROC integrate into an outdoor kitchen?

    Outdoor kitchens are designed around how the space will be used.

    • Built-in BBQs, grills, or smokers.
    • Sinks and plumbing for food preparation and cleanup.
    • Refrigeration and beverage storage.
    • Concrete, stone, or stainless-steel countertops.
    • Bar seating and prep areas.
    • Storage cabinets designed for outdoor conditions.
    • Lighting and power for evening use.

    All features are planned to work together safely and efficiently.

    What features can VALROC integrate into an outdoor kitchen?

    Outdoor kitchens are designed around how the space will be used.

    • Built-in BBQs, grills, or smokers.
    • Sinks and plumbing for food preparation and cleanup.
    • Refrigeration and beverage storage.
    • Concrete, stone, or stainless-steel countertops.
    • Bar seating and prep areas.
    • Storage cabinets designed for outdoor conditions.
    • Lighting and power for evening use.

    All features are planned to work together safely and efficiently.

    What materials does VALROC use for outdoor kitchens & BBQ areas?

    Materials are selected for durability, safety, and long-term outdoor use.

    • Concrete countertops for heat resistance and longevity.
    • Stainless steel for appliances and cabinetry.
    • Natural stone or brick for structure and finishes.
    • Composite or treated wood for seating and accents.
    • Non-slip tile or stone for flooring and work surfaces.

    Each material is chosen based on exposure, use, and maintenance requirements.

    What materials does VALROC use for outdoor kitchens & BBQ areas?

    Materials are selected for durability, safety, and long-term outdoor use.

    • Concrete countertops for heat resistance and longevity.
    • Stainless steel for appliances and cabinetry.
    • Natural stone or brick for structure and finishes.
    • Composite or treated wood for seating and accents.
    • Non-slip tile or stone for flooring and work surfaces.

    Each material is chosen based on exposure, use, and maintenance requirements.

    Does VALROC handle gas, electrical, and plumbing for outdoor kitchens?

    Yes. Outdoor kitchens are built as complete systems rather than standalone features.

    • Gas lines for BBQs, pizza ovens, and fire features.
    • Electrical wiring for lighting, outlets, refrigeration, and equipment.
    • Plumbing for sinks, water supply, and drainage.

    All work is coordinated to meet safety standards and local code requirements.

    Does VALROC handle gas, electrical, and plumbing for outdoor kitchens?

    Yes. Outdoor kitchens are built as complete systems rather than standalone features.

    • Gas lines for BBQs, pizza ovens, and fire features.
    • Electrical wiring for lighting, outlets, refrigeration, and equipment.
    • Plumbing for sinks, water supply, and drainage.

    All work is coordinated to meet safety standards and local code requirements.

    What types of BBQs and cooking appliances can be installed?

    Outdoor kitchens can support a wide range of cooking equipment.

    • Gas or propane BBQs for everyday use.
    • Charcoal grills and smokers for slow cooking.
    • Pizza ovens, either gas or wood-fired.
    • Side burners or griddles for additional cooking space.
    • Rotisserie or infrared cooking equipment where required.

    Appliance selection is based on cooking preferences and available space.

    What types of BBQs and cooking appliances can be installed?

    Outdoor kitchens can support a wide range of cooking equipment.

    • Gas or propane BBQs for everyday use.
    • Charcoal grills and smokers for slow cooking.
    • Pizza ovens, either gas or wood-fired.
    • Side burners or griddles for additional cooking space.
    • Rotisserie or infrared cooking equipment where required.

    Appliance selection is based on cooking preferences and available space.

    Do outdoor kitchens require permits?

    Permits may be required depending on the features included in the outdoor kitchen.

    • Gas connections for BBQs, pizza ovens, or heaters.
    • Electrical work for lighting, outlets, or appliances.
    • Plumbing for sinks, refrigerators, or water supply.
    • Covered structures such as pergolas, pavilions, or permanent roofs.

    Permit requirements vary by municipality, and we confirm them before construction begins.

    Do outdoor kitchens require permits?

    Permits may be required depending on the features included in the outdoor kitchen.

    • Gas connections for BBQs, pizza ovens, or heaters.
    • Electrical work for lighting, outlets, or appliances.
    • Plumbing for sinks, refrigerators, or water supply.
    • Covered structures such as pergolas, pavilions, or permanent roofs.

    Permit requirements vary by municipality, and we confirm them before construction begins.

    How do outdoor kitchens hold up in Metro Vancouver’s climate?

    Outdoor kitchens are built to handle moisture, rain, and seasonal temperature changes.

    • Weather-resistant materials such as concrete, stone, and stainless steel.
    • Covered or partially covered layouts to limit direct exposure.
    • Proper drainage to prevent water pooling or damage.
    • Plumbing designed to be drained or protected during colder months.

    With the right materials and detailing, outdoor kitchens remain low maintenance year-round.

    How do outdoor kitchens hold up in Metro Vancouver’s climate?

    Outdoor kitchens are built to handle moisture, rain, and seasonal temperature changes.

    • Weather-resistant materials such as concrete, stone, and stainless steel.
    • Covered or partially covered layouts to limit direct exposure.
    • Proper drainage to prevent water pooling or damage.
    • Plumbing designed to be drained or protected during colder months.

    With the right materials and detailing, outdoor kitchens remain low maintenance year-round.

    Can an outdoor kitchen be installed on an existing patio or deck?

    Outdoor kitchens can often be added to existing structures if they can support the load.

    • Evaluating deck framing and footing capacity.
    • Adding reinforcement where required.
    • Installing proper bases for heavy appliances.
    • Integrating utilities safely and to code.

    Each installation starts with a structural and safety assessment.

    Can an outdoor kitchen be installed on an existing patio or deck?

    Outdoor kitchens can often be added to existing structures if they can support the load.

    • Evaluating deck framing and footing capacity.
    • Adding reinforcement where required.
    • Installing proper bases for heavy appliances.
    • Integrating utilities safely and to code.

    Each installation starts with a structural and safety assessment.

    METRO VANCOUVER HARDSCAPE

    Outdoor kitchen work across Metro Vancouver

    From our Langley construction yard, VALROC coordinates outdoor kitchens and BBQ areas around patios, covered spaces and the way homeowners entertain. Projects in Langley and Surrey can combine counters, appliances, storage, seating, lighting and utility preparation within one connected outdoor living plan.

    In White Rock, weather exposure and covered cooking areas can shape material and equipment selections, while Burnaby and Delta properties may require careful use of available backyard space. Gas, electrical, plumbing and drainage connections are coordinated with the approved layout and surrounding hardscape.