/* ========================================
MOBILE ONLY STYLES
add and modify varibales for mobile breakpoint
========================================= */
html.dwc-mobile {
  --mobile-menu-width: min(450px, 100%);
  --menu-item-font-size: 18px;
  --dropdown-item-font-size: var(--menu-item-font-size);
  --back-text-font-size: 16px;
  --menu-item-hover-border-bg: initial;
}

/* ======================================= 
  GENERAL NAV STYLES 
========================================= */
:root {
  /* ========================
 GENERAL COLORS/BACKGROUND
  ======================== */
  --primary-clr: orangered;
  --header-bg: white;
  --dropdown-content-bg: white;
  --mobile-menu-bg: white;
  --mobile-menu-topbar-bg: white;


  /* ===============================
   GENERAL WIDTH | HEIGHT | SPACINGS
  ================================== */
  --mobile-menu-width: min(300px, 100%); /* mobile & offcanvas */
  --multilevel-dropdown-width: 200px;  
  --dropdown-content-gap: 1px; /* header -> dropdown gap, add unit (e.g. 0px) */
  --header-min-height: 60px;
  --fullscreen-mobile-menu-top-height: 60px;  
  --top-offset: 40px; /* when nav is below header */ 
  --dropdown-content-default-width: 1080px;  /* preview width & default width for dropdown content */


  /* ==============================================
    GENERAL BORDERS | SHADOWS | OVERLAY BACKDROP
  ================================================= */
  /* dropdown content */
  --dropdown-content-border-radius: 0px;
  --dropdown-content-shadow: 0px 5px 15px -10px rgb(0 0 0 / 0%);  
  --dropdown-content-border-size: 1px; /* at least 1px */
  --dropdown-content-border-color: var(--dropdown-content-bg);   

  /* overlay backdrop */
  --nav-overlay-backdrop-blur: 0px;
  --nav-overlay-backdrop-clr: rgba(0, 0, 0, 0.3);

  /* sidebar nav */
  --sidebar-shadow: 0px 0px 2px rgba(0, 0, 0, 0.7);

  /* radius for special mobile style on overlay header*/
  --mobile-menu-radius: var(--overlay-header-radius);

  /* 	mobile & offcanvas */
  --slide-out-speed: 1.3;


  /* ===============================
  MENU TOGGLE - Hamburger 
  (additional settings at line 202)
  ================================== */
  --menu-toggle-clr: var(--menu-item-clr);
  --menu-close-toggle-clr: var(--menu-item-clr);
  --menu-toggle-hover-clr: var(--menu-item-hover-clr);


  /* ========================
  MENU ITEMS
  ======================== */
  /* DEFAULT STATE */
  --menu-item-clr: #000;
  --menu-item-font-size: 14px;
  --menu-item-font-weight: 500;
  --menu-item-bg: initial; 

  /* HOVER STATE */
  --menu-item-hover-clr: var(--primary-clr);
  --menu-item-hover-bg: initial;
  --menu-item-hover-border-bg: var(--menu-item-active-border-bg);
  --menu-item-hover-border-height: var(--menu-item-active-border-height);

  /* ACTIVE STATE 
  (to exclude a link from this style, 
  add .dwc-exclude to its container)*/
  --menu-item-active-clr: var(--menu-item-hover-clr);
  --menu-item-active-bg: initial;
  --menu-item-active-border-bg: var(--primary-clr);
  --menu-item-active-border-height: 2px;

  /* PADDING | GAP */
  --menu-item-inline-padding: 1.1rem;
  --menu-item-block-padding: 1rem;
  --menu-items-gap: 0;

  /* BORDERS | RADIUS */
  --menu-item-border: 1px solid rgba(0, 0, 0, 0.1);
  --menu-item-radius: 0;
  
  /* CHEVRON (dropdown arrow) */
  --chevron-size: 14px;
  --chevron-clr: var(--menu-item-clr);
  --chevron-hover-clr: var(--menu-item-hover-clr);


  /* ========================
  MULTILEVEL DROPDOWN LINKS
  ======================== */
  /* DEFAULT STATE */
  --dropdown-item-clr: var(--menu-item-clr);
  --dropdown-item-font-size: var(--menu-item-font-size);
  --dropdown-item-bg: initial;
  --dropdown-indent-bg: rgb(0 0 0 / 5%);
  --dropdown-heading-clr: var(--primary-clr);

  /* HOVER STATE */
  --dropdown-item-hover-clr: var(--menu-item-hover-clr);
  --dropdown-item-hover-bg: white;

  /* EXPANDED STATE (PARENT) - mobile */
  /* when [data-submenu-reveal="expand"] */
  --dropdown-expanded-clr: white;
  --dropdown-expanded-bg: black;

  /* PADDING | GAP | INDENT */
  --dropdown-item-inline-padding: var(--menu-item-inline-padding);
  --dropdown-item-block-padding: var(--menu-item-block-padding);
  --dropdown-indent: 0.6rem;
  --dropdown-indent-item-pad-offset: 0.5;
  --dropdown-indent-line: solid 1px rgb(0 0 0 / 25%);

  /* OTHERS */
  --dropdown-inactive-overlay: rgb(0 0 0 / 10%);


  /* ========================
  MENU CTA BUTTON (ALL BUTTONS)
  ======================== */
  /* all cta buttons max width on mobile */
  --cta-width: 100%;

  /* gap offset between 2 or 3 cta buttons on mobile/offcanvas/sidebar*/
  --cta-gap-offset: 0;

  /* gap between breakout cta and menu toggle on mobile */
  --cta-breakout-gap: 20px;


  /* ========================
  MENU CTA BUTTON (LAST BUTTON)
  ======================== */
  /* DEFAULT STATE */
  --menu-cta-clr: white;
  --menu-cta-bg: black;
  --menu-cta-inline-padding: calc(var(--menu-item-inline-padding) * 1.3);
  --menu-cta-block-padding: var(--menu-item-block-padding);
  --menu-cta-border: none;
  --menu-cta-radius: 0em;

  /* HOVER STATE */
  --menu-cta-hover-clr: white;
  --menu-cta-hover-bg: var(--primary-clr);


  /* ========================
  MENU CTA BUTTON (SECOND BUTTON)
  ======================== */
  /* DEFAULT STATE */
  --menu-cta-2-clr: white;
  --menu-cta-2-bg: black;
  --menu-cta-2-inline-padding: var(--menu-cta-inline-padding);
  --menu-cta-2-block-padding: var(--menu-cta-block-padding);
  --menu-cta-2-border: var(--menu-cta-border);
  --menu-cta-2-radius: var(--menu-cta-radius);

  /* HOVER STATE */
  --menu-cta-2-hover-clr: white;
  --menu-cta-2-hover-bg: var(--primary-clr);


  /* ========================
  MENU CTA BUTTON (THIRD BUTTON)
  ======================== */
  /* DEFAULT STATE */
  --menu-cta-3-clr: white;
  --menu-cta-3-bg: black;
  --menu-cta-3-inline-padding: var(--menu-cta-inline-padding);
  --menu-cta-3-block-padding: var(--menu-cta-block-padding);
  --menu-cta-3-border: var(--menu-cta-border);
  --menu-cta-3-radius: var(--menu-cta-radius);

  /* HOVER STATE */
  --menu-cta-3-hover-clr: white;
  --menu-cta-3-hover-bg: var(--primary-clr);


  /* ========================
  MENU TOGGLE - Hamburger additional settings
  ======================== */
  --open-icon-size: 40px;
  --open-icon-line-height: 4px;
  --icon-line-gap: 0.7em;   /* gap between the lines*/
  --open-icon-line-variance: 9px;  /* line width variation, e.g. 0 = same width*/
  --open-icon-align: 0;  /* 0 = right | auto = left */
  --open-icon-horizontal-offset: 0px; /* nudge icon left or right from edge of screen*/
  --open-icon-close-offset: 1.2; /* nudge icon left or right when close icon is active */


  /* ======================================
  ADAPTIVE HEIGHT/ STRIPE BG COLOR/BORDER
  ========================================= */
  --adaptive-height-bg: #fff;
  --adaptive-height-border: 1px solid #fff;
  --adaptive-height-shadow: 0 0 30px rgb(39 50 59 / 10%);


  /* ========================
  STRIPE - when [data-optimize-stripe="true"]
  ======================== */
  --stripe-border-radius: 10px;


  /* ========================
  MOBILE/OFFCANVAS MENU
  ======================== */
  --mobile-menu-ttf: cubic-bezier(0.8, 0.07, 0.2, 0.95);
  /* Transition timing function */


  /* =================
  OVERLAY HEADER
  ================== */
  --overlay-header-width: 1400px;
  --overlay-header-inset: 1rem;
  --overlay-header-bg: rgb(255 255 255 / 100%);
  --overlay-header-bg-active: rgb(255 255 255 / 100%);
  --overlay-header-blur: 10px;
  --overlay-header-radius: 1rem;
  --overlay-header-shadow: 0px 2px 20px rgb(0 0 0 / 20%);
  --overlay-offset-padding: clamp(5rem, 1.875rem + 12.5vw, 11.25rem);


  /* ========================
  BACK TEXT
  ======================== */
  --back-text-clr: var(--menu-item-clr);
  --back-text-font-size: 12px;
  --back-text-font-weight: 600;
  --back-text-transform: uppercase;
  --back-text-bg: var(--mobile-menu-topbar-bg);


  /* ========================
  SIDEBAR NAV - OVERLAY MODE
  ======================== */
  --overlay-sidebar-radius: 1rem;
  --overlay-sidebar-bg: rgb(255 255 255 / 80%);
  --overlay-sidebar-shadow: 0 0 30px rgb(39 50 59 / 10%);
  --overlay-sidebar-inset: 12px;


  /* ======== DO NOT EDIT THIS VARIABLES! ======== */
  --iw: calc(var(--open-icon-size) - var(--open-icon-line-variance));
  --aw: calc(var(--iw) - var(--open-icon-line-variance));  
  --caret-size: calc(var(--dropdown-content-gap) + var(--dropdown-content-border-size));
  --dropdown-content-border: solid var(--dropdown-content-border-color) var(--dropdown-content-border-size); 
}


/* SIDEBAR BACK TEXT BAR HEIGHT WHEN BACK TEXT OVERLAYS LOGO */
#brx-header:has([data-sidebar-back-text-on-logo="true"]) {
  --top-offset: var(--mobile-menu-top-height);
}


/* ========================
  STICKY HEADER STYLES
add variables to modify for sticky header
  ======================== */
.sticky.scrolling {
  /* add your sticky styles variable here */
}

/* ========================
DROPDOWN ITEM IS BUTTON OR ICON 
======================== */

[data-is-button]>.brx-submenu-toggle {
  --menu-item-bg: black;
  --menu-item-clr: white;
  --menu-item-hover-clr: white;
  --menu-item-hover-bg: black;
  --menu-item-radius: 50vw;
  --menu-item-hover-border-height: 0;
  --chevron-size: 0;
  --chevron-color: white;
  --menu-item-inline-padding: 1.5rem;
  --menu-item-block-padding: 1rem;
  /* mobile only*/
  --menu-item-width: 200px;
  --menu-item-border: solid 1px transparent;
  --menu-item-hover-border: solid 1px transparent;

}

[data-is-icon]>.brx-submenu-toggle {
  --menu-item-bg: black;
  --menu-item-clr: white;
  --menu-item-hover-clr: white;
  --menu-item-hover-bg: black;
  --icon-clr: white;
  --icon-hover-clr: white;
  --icon-size: 14px;
  --menu-item-inline-padding: 1.1rem;
  --button-max-diameter: 45px;
  --menu-item-radius: 50vw;
  --menu-item-border: solid 1px transparent;
  --menu-item-hover-border: solid 1px transparent;
}

/* ========== NAV STYLES END ============== */



/* ======= STICKY HEADER WITH OVERLAY SPECIAL STYLES ===== */

/* SVG STYLES BEFORE SCROLLING - REVERTS TO INITIAL VALUES WHEN DROPDOWN IS OPEN */
html:not(.dwc-mobile):has([data-sticky-overlay-special-style="true"]) .bricks-is-frontend .sticky:not(.scrolling) .dwc-nest-header:not(:has(.brxe-dropdown.open)) :is(path, .cls-1):not(:is(.brx-submenu-toggle path)) {
  fill: white;
}



/* STYLES BEFORE SCROLLING  - REVERTS TO INITIAL VALUES WHEN DROPDOWN IS OPEN */
html:not(.dwc-mobile):has([data-sticky-overlay-special-style="true"]) .bricks-is-frontend .sticky:not(.scrolling) .dwc-nest-header:not(:has(.brxe-dropdown.open)) {
  --menu-item-clr: white;
  --chevron-clr: white;
  --menu-item-hover-clr: white;
  --menu-item-hover-border-bg: white;
  --overlay-header-bg: transparent;
  --overlay-header-shadow: none;
}

/* STYLES BEFORE SCROLLING */
html:not(.dwc-mobile):has([data-sticky-overlay-special-style="true"]) .bricks-is-frontend .sticky:not(.scrolling) {
  --link-transition: 0s;
  --transition: 0.2s;
}


/* STYLES WHEN SCROLLING */
html:not(.dwc-mobile):has([data-sticky-overlay-special-style="true"]) .bricks-is-frontend .sticky.scrolling {
  --overlay-header-bg: white;
}

/* STYLES WHEN SCROLLING :HOVER*/
html:not(.dwc-mobile):has([data-sticky-overlay-special-style="true"]) .bricks-is-frontend .sticky.scrolling .dwc-nest-header:has(.brxe-dropdown.open) {
  /* add and update variable here */

}


/* DEFAULT STYLES FOR OVERLAY HEADER  */
html:not(.dwc-mobile):has([data-sticky-overlay-special-style="true"]) .bricks-is-frontend .sticky {
  --menu-item-hover-bg: initial;
  --menu-item-bg: initial;
  --overlay-header-inset: 0;
  --overlay-header-width: 100%;
  --overlay-header-radius: 0;
}

/* RESET STICKY HEADER TRANSITION*/
html:not(.dwc-mobile):has([data-sticky-overlay-special-style="true"]) .bricks-is-frontend #brx-header.sticky .dwc-nest-header {
  transition: var(--transition);
}


/* ======= END STICKY HEADER WITH OVERLAY SPECIAL STYLES ===== */



/* ======== CHANGE postid-xxxx TO THIS TEMPLATE'S ID ========= */

/*hide sidebar in builder */
:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header:not(.postid-23338 *, :has(.dwc-sidebar) *) {
  display: none !important;
}

[data-builder-window] #brx-header:has([data-offcanvas="true"]):not(.postid-23338 *, :has(.dwc-sidebar) *) :is(.dwc-nav-wrapper, .dwc-nest-menu) {
  display: none !important;
}


:is(.brx-header-left, .brx-header-right)[data-builder-window] :is(#brx-content, #brx-footer):not(.postid-23338 *, :has(.dwc-sidebar) *) {
  margin: unset !important;
}

[data-builder-mode]:is(.brx-header-left, .brx-header-right).postid-23338::before {
  display: none
}
const MegaMenuCONFIG = {
  // Minimum width threshold for desktop behavior,
  // should be 1px larger than mobile (max-width) breakpoint in the "MENU Styles/Options" CSS code block
  //IMPORTANT: Also change min-width in the "MEGA MENU Codes" CSS code block
  minWidth: 1201,

  // automatically open the current menu panel/dropdown (mobile, offcanvas & sidebar)
  menuAutoExpansion: true,

  swipeToClose: true,

  // show or hide swipe to close hint
  toolTip: true,

  // adaptive height animation
  adaptiveHeight: 0,

  // Stripe menu animation
  stripeStyle: 0,

  headerSelector: '.dwc-nest-header',
  nestMenuSelector: '.dwc-nest-menu',

  closeNavOnClick: 1,
  closeOnHashClickOnly: 0,
  breakinToNavList: 0, /*do not enable if using last item is button*/

  // Selectors (e.g. .class-name, #id_name, tag-name, .complex > selectors etc.) that should NOT close the navigation when clicked
  // Separate multiple selectors with a comma e.g. '.class-one, #id_one, tag'
  closeNavOnClickExclude: '.js-wpml-ls-item-toggle',

  // New properties for dropdown positioning
  shiftFactor: 1,  // Factor to shift overflow
  minOverflow: 10,   // Minimum overflow threshold 
  reinitializeOnURLchange: false, //when using page transition API
  
  //move backdrop overlay element Inside header
  //placing it inside header will allow backdrop overlay/blur to affect header, but won't work when data-overlay-header is enabled. 
  overlayInsideHeader:0

};

// Centered Logo Configuration
const CenteredLogoCONFIG = {
  enable: 0,
  centerGuide: 1,
  forceCenteredLogo: 1,
  // move the navigation left 
  // or right using negative or positive value
  centerNudge: 0,
  // allow centered logo when no. of 
  // menu items are odd e.g. 5 or 7
  allowOddItems: 1,
  // place logo 'before' or 'after' the odd menu item
  roundOffFactor: 'before'
};
/* DO NOT ADD ANY CODE IN THIS CODE BLOCK */

/*MOBILE MENU/OFFCANVAS/SIDEBAR STYLES*/




@media only screen and (max-width: 1200px) {
    .desktop-centered header:has([data-fix-centered-logo-fouc="true"]) {
        opacity: 0;
    }

    .dwc-nest-menu__logo[data-breakout-link] {
        margin-inline-end: auto
    }
  
/*mobile logo*/
  .dwc-nest-menu__mobile-logo > :is(svg, img) {
    height: 100%;
}
  
  .dwc-nest-menu__mobile-logo:not([data-show-mobile-logo="true"] .dwc-nest-menu__mobile-logo){
  display: none;
}


[data-sidebar-back-text-on-logo="true"] .dwc-nest-menu__mobile-logo {      
   --dwc-nest-header-height: var(--mobile-menu-top-height);
}

    /*special mobile menu styles for overlay header UPDATED */

    .dwc-mobile .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"] .brx-nav-nested-items {
        transform: translateY(-100%);
    }


    .dwc-mobile .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"].brx-open .brx-nav-nested-items {
        transform: translateY(0%);
    }

    .dwc-mobile .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"] .brx-nav-nested-items {
        transition: 0.45s;
        transition-timing-function: var(--mobile-menu-ttf);
        inset-block-start: calc(min(var(--overlay-header-radius), 2em) * -1);
    }


    .dwc-mobile .bricks-is-frontend [data-overlay-header-mobile="true"] .dwc-nest-menu[data-slide-in-direction="top"][data-submenu-reveal="expand"][data-match-overlay-header-width="true"] .brx-nav-nested-items {
        inset-block-start: calc(var(--dwc-nest-header-height) / -2);
    }


    .dwc-mobile .dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"] .brx-nav-nested-items {
        --mobile-menu-width: 100% !important;
        inline-size: var(--mobile-menu-width);
        border-bottom-left-radius: min(var(--mobile-menu-radius), 2em);
        border-bottom-right-radius: min(var(--mobile-menu-radius), 2em);
        padding-block-start: calc(var(--dwc-nest-header-height) / 2);
        overflow-x: hidden;
    }

    .dwc-mobile .dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"][data-submenu-reveal="expand"] .brx-nav-nested-items {
        max-block-size: fit-content;
    }

    .dwc-mobile .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"] .dwc-nav-wrapper {
        transform: translateY(0%);
        border-radius: min(var(--overlay-header-radius), 2em);
        overflow: hidden !important;
        inset-block-start: var(--overlay-header-inset);

    }

    .dwc-mobile .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"].brx-open .dwc-nav-wrapper {
        transform: translateY(0%);
    }

    .dwc-mobile .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"] :is(.dwc-nav-wrapper) {
        --mobile-menu-width: min(calc(100% - (var(--overlay-header-inset) * 2)), 100%) !important;
        inline-size: var(--mobile-menu-width) !important;
        inset-inline-end: var(--overlay-header-inset) !important;
        block-size: calc(100dvb - (var(--overlay-header-inset) * 2));
    }

    .dwc-mobile .dwc-nest-menu.brxe-nav-nested[data-slide-in-direction="top"][data-match-overlay-header-width="true"] .brxe-dropdown:not(.open) .brx-dropdown-content:not([data-builder-mode] .brx-dropdown-content) {
        height: 0;
    }


    .dwc-mobile .dwc-nest-header:has(.dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"]) {
        padding-inline: initial
    }


    .dwc-mobile .dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"] .dwc-nest-menu-top {
        border-block-end: initial;
    }


    /* .dwc-mobile .dwc-nest-header:has(.dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"]:not([data-submenu-reveal="expand"])) .dwc-nest-nav-items:has(.open.active) .brx-submenu-toggle>button:not(.brxe-dropdown.open.active .brx-submenu-toggle > button) {
opacity: 0;
} */

    .dwc-mobile .dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"][data-submenu-reveal="slide"] .brx-has-megamenu.brxe-dropdown .brx-dropdown-content:not([data-hide-close-bar="true"] ul, [data-submenu-reveal="expand"].brx-has-megamenu ul) {
        inset-block-start: min(var(--overlay-header-radius), 2em) !important;
        padding-block-start: 50px;
    }


    .dwc-mobile .dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"][data-submenu-reveal="slide"] .brxe-dropdown:not(.brx-has-megamenu, [data-submenu-reveal="expand"]) .brx-dropdown-content:not([data-hide-close-bar="true"] ul),
    .bricks-is-frontend [data-submenu-reveal="slide"].brxe-dropdown .brx-dropdown-content:not([data-hide-close-bar="true"] ul) {
        inset-block-start: min(var(--overlay-header-radius), 2em) !important;
        padding-block-start: 50px;
    }


    .dwc-mobile .dwc-nest-menu[data-submenu-reveal="slide"][data-slide-in-direction="top"][data-match-overlay-header-width="true"] .open.active>.brx-submenu-toggle>button:not([data-hide-close-bar="true"] button, [data-submenu-reveal="expand"] button, .open.active:has(.open.active)>.brx-submenu-toggle > button) {
        z-index: 9999;
        min-inline-size: 100%;
        min-block-size: 50px;
        inset-block-start: min(var(--overlay-header-radius), 2em);
    }


    .dwc-mobile .dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"][data-submenu-reveal="slide"] .brxe-dropdown:not(:is([data-submenu-reveal="expand"], .brx-has-megamenu)) .brx-dropdown-content:not([data-submenu-reveal="expand"] *),
    .bricks-is-frontend [data-submenu-reveal="slide"].brxe-dropdown:not(.brx-has-megamenu) .brx-dropdown-content {
        min-block-size: 100%;
    }



    .dwc-mobile .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"][data-submenu-reveal="slide"] .brxe-dropdown.brx-has-megamenu:not(:is([data-submenu-reveal="expand"])) .brx-dropdown-content:not([data-submenu-reveal="expand"] .brx-dropdown-content)>li {
        padding-block-end: 40px;
    }

    .dwc-mobile .dwc-nest-header[data-overlay-header-mobile="true"]>div {
        padding-inline: var(--menu-item-inline-padding);
        border-radius: var(--overlay-header-radius);
    }

    /* special style UPDATED ends*/



    .dwc-nest-menu .brx-nav-nested-items {
        width: var(--mobile-menu-width);
    }

    /*  unset default values */

    [data-offcanvas="true"] .open:has(.open) .brx-dropdown-content::before {
        display: none !important;
    }

    [data-offcanvas="true"] .brx-nav-nested-items {
        flex-wrap: nowrap;
    }

    .dwc-nest-menu .brx-nav-nested-items {
        gap: 0;
    }


    .dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(.open) .brx-dropdown-content:not([data-builder-mode] .brx-dropdown-content) {
        display: flex;
        visibility: hidden;
    }

    [data-overlay-header="true"] .dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(.open) .brx-dropdown-content:not([data-builder-mode] .brx-dropdown-content),
    .dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(.open) .brx-dropdown-content:not([data-builder-mode] .brx-dropdown-content) {
        min-inline-size: 0 !important;
    }

    .dwc-nest-menu.brxe-nav-nested.brx-open .brxe-dropdown>.brx-dropdown-content {
        overflow-y: auto;
    }

    .dwc-nest-menu .brx-nav-nested-items {
        flex-direction: column !important;
        flex-wrap: nowrap;

    }

    .dwc-nest-toggle--open.brxe-toggle {
        display: flex !important;
        place-items: center;
    }

    .dwc-nest-menu .brx-nav-nested-items {
        position: relative !Important;
        background: var(--mobile-menu-bg) !important;
        align-items: stretch;
        flex: 1;
    }





    .dwc-nest-menu .brx-nav-nested-items:not(.brx-open .brx-nav-nested-items) {
        transform: unset
    }

    .dwc-nest-menu .brxe-dropdown:not(.brx-has-megamenu)>.brx-dropdown-content {
        transform: translateZ(0);
        transform: unset;
    }

    .dwc-nest-menu.brxe-nav-nested.brx-closing .brx-nav-nested-items {
        opacity: unset !important;
        visibility: unset !important;
    }

    .dwc-nest-menu.brxe-nav-nested .brx-nav-nested-items {
        overflow-y: auto;
        scrollbar-width: none;
        justify-content: flex-start !important;
    }


    /* set new values  */

    .dwc-nav-wrapper {
        position: fixed;
        inset-block: 0;
        inset-inline-end: 0;
        transform: translateX(100%);
        background-color: var(--mobile-menu-bg);
        transition: 0.45s;
        transition-timing-function: var(--mobile-menu-ttf);
        z-index: 1;
        flex-wrap: nowrap;
        inline-size: var(--mobile-menu-width);
        visibility: hidden;
    }

   

    .brx-open .dwc-nav-wrapper {
        transform: translateX(0%);
        visibility: visible;
    }



    .dwc-nest-menu-top {
        background-color: var(--mobile-menu-topbar-bg);
        border-block-end: var(--menu-item-border);
        min-block-size: var(--dwc-nest-header-height);
        display: flex;
        flex-direction: row;
        align-items: center;
    }



    .dwc-nest-menu .brxe-dropdown.brx-has-megamenu,
    .dwc-nest-menu .brxe-dropdown:not(.brx-has-megamenu)>.menu-item>a {
        border-block-end: var(--menu-item-border);
    }

    .dwc-nest-menu .brxe-dropdown:not(.brx-has-megamenu):not(.open, :has(.open)),
    .dwc-nest-menu .brxe-dropdown:not(.brx-has-megamenu) >.brxe-dropdown:not(.open, :has(.open)) {
        border-block-end: var(--menu-item-border);
    }



    /* MENU CTA (LAST BUTTON) */

    :is([data-last-item-is-button="true"], [data-last-item-is-button="true-2"], [data-last-item-is-button="true-3"]).dwc-nest-menu .brx-nav-nested-items>.menu-item:last-of-type,
    :is([data-last-item-is-button="true-2"], [data-last-item-is-button="true-3"]).dwc-nest-menu .brx-nav-nested-items>.menu-item:nth-last-of-type(-n+2),
    [data-last-item-is-button="true-3"].dwc-nest-menu .brx-nav-nested-items>.menu-item:nth-last-of-type(-n+3) {
        padding-inline: var(--menu-item-inline-padding) !important;
        padding-block: var(--menu-item-block-padding) !important;
        inline-size: 100%;
        margin-inline: auto;
        max-inline-size: var(--cta-width);
    }

    [data-last-item-is-button="true-2"].dwc-nest-menu .brx-nav-nested-items>.menu-item:nth-last-of-type(-n+2)+li {
        padding-block-start: var(--cta-gap-offset) !important
    }

    [data-last-item-is-button="true-3"].dwc-nest-menu .brx-nav-nested-items>.menu-item:nth-last-of-type(-n+3)+li {
        padding-block-start: var(--cta-gap-offset) !important
    }


    :is([data-last-item-is-button="true"], [data-last-item-is-button="true-2"], [data-last-item-is-button="true-3"]).dwc-nest-menu .brx-nav-nested-items>.menu-item:last-of-type a,
    :is([data-last-item-is-button="true-2"], [data-last-item-is-button="true-3"]).dwc-nest-menu .brx-nav-nested-items>.menu-item:nth-last-of-type(-n+2) a,
    [data-last-item-is-button="true-3"].dwc-nest-menu .brx-nav-nested-items>.menu-item:nth-last-of-type(-n+3) a {
        justify-content: center;
    }



    /* MOBILE MENU SLIDE IN DIRECTION */
    .bricks-is-frontend [data-slide-in-direction="left"] .dwc-nav-wrapper {
        transform: translateX(-100%);
        inset-inline-start: 0;
        overflow: hidden;
    }

    /* RTL */
    [dir="rtl"] .bricks-is-frontend [data-slide-in-direction="left"] .dwc-nav-wrapper {
        inset-inline-start: initial;
        inset-inline-end: 0;
    }

    [dir="rtl"] .bricks-is-frontend [data-slide-in-direction="left"] .dwc-nav-wrapper {
        inset-inline-start: initial;
        inset-inline-end: 0;
    }

    [dir="rtl"] .bricks-is-frontend [data-submenu-reveal="slide"][data-slide-in-direction="left"] .open.active>.brx-submenu-toggle button:not([data-hide-close-bar="true"] button, [data-submenu-reveal="expand"] button),

    [dir="rtl"] .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="left"] [data-submenu-reveal="slide"].open.active>.brx-submenu-toggle button:not([data-hide-close-bar="true"] button, [data-submenu-reveal="expand"] button) {
        inset-inline-start: initial;
        inset-inline-end: 0;
        justify-content: flex-end;
    }




    .bricks-is-frontend [data-slide-in-direction="left"].brx-open .dwc-nav-wrapper {
        transform: translateX(0);
    }

    /* SLIDE IN TOP */
    .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="top"].brx-open .dwc-nav-wrapper,
    .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="left top"].brx-open .dwc-nav-wrapper {
        transform: translateY(0%);
    }

    .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="top"] .dwc-nav-wrapper,
    .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="left top"] .dwc-nav-wrapper {
        transform: translateY(-100%);
    }

    /* SLIDE IN BOTTOM */

    .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="bottom"].brx-open .dwc-nav-wrapper,
    .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="left bottom"].brx-open .dwc-nav-wrapper {
        transform: translateY(0%);
    }

    .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="bottom"] .dwc-nav-wrapper,
    .bricks-is-frontend .dwc-nest-menu[data-slide-in-direction="left bottom"] .dwc-nav-wrapper {
        transform: translateY(100%);
    }

    .bricks-is-frontend [data-slide-in-direction="left bottom"] .dwc-nav-wrapper,
    .bricks-is-frontend [data-slide-in-direction="left top"] .dwc-nav-wrapper {
        inset-inline-start: 0;
        overflow: hidden;
    }


    .dwc-nest-menu.brxe-nav-nested .brxe-dropdown>.brx-dropdown-content::-webkit-scrollbar-track,
    .dwc-nest-menu .brx-nav-nested-items::-webkit-scrollbar-track {
        border-radius: 50vw;
        background-color: transparent;
    }

    .dwc-nest-menu.brxe-nav-nested .brxe-dropdown>.brx-dropdown-content::-webkit-scrollbar,
    .dwc-nest-menu .brx-nav-nested-items::-webkit-scrollbar {
        inline-size: 0px;
        background-color: transparent;
    }

    .dwc-nest-menu.brxe-nav-nested .brxe-dropdown>.brx-dropdown-content::-webkit-scrollbar-thumb,
    .dwc-nest-menu .brx-nav-nested-items::-webkit-scrollbar-thumb {
        border-radius: 50vw;
        background-color: #55565d;
    }

    /* SCROLLBARS END */



    /*  SLIDE IN DIRECTION - DROPDOWN ITEMS*/
    .bricks-is-frontend [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(:is([data-submenu-reveal="expand"])) .brx-dropdown-content:not([data-submenu-reveal="expand"] *),
    .bricks-is-frontend [data-submenu-reveal="slide"].brxe-dropdown .brx-dropdown-content {
        max-block-size: unset;
        position: absolute !important;
        opacity: 1;
        transition-duration: 0.45s !important;
        transition-timing-function: var(--mobile-menu-ttf);
        padding-block-end: 50px;
    }

    .bricks-is-frontend .dwc-nest-menu [data-submenu-reveal="expand"].brx-has-megamenu>ul {
        position: static !important;
        padding-block-end: 0 !important;
        transition: 0.3s ease-in-out !important;
    }



    .bricks-is-frontend [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brx-has-megamenu.brxe-dropdown .brx-dropdown-content:not([data-submenu-reveal="expand"].brx-has-megamenu ul) {
        inset: 0 !important;
        transform: translateX(100%);
        transition-property: opacity, transform, visibility;
        min-block-size: calc(100dvb - var(--dwc-nest-header-height));
        position: fixed !important;
    }

    .bricks-is-frontend [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brx-has-megamenu.brxe-dropdown .brx-dropdown-content:not([data-hide-close-bar="true"] ul, [data-submenu-reveal="expand"].brx-has-megamenu ul) {
        inset-block-start: var(--dwc-nest-header-height) !important;
    }

    .bricks-is-frontend :is([data-slide-in-direction="left"], [data-slide-in-direction="left bottom"], [data-slide-in-direction="left top"])[data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brx-has-megamenu.brxe-dropdown .brx-dropdown-content:not([data-submenu-reveal="expand"].brx-has-megamenu ul),
    .bricks-is-frontend.brx-header-left [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brx-has-megamenu.brxe-dropdown .brx-dropdown-content:not([data-submenu-reveal="expand"].brx-has-megamenu ul) {
        transform: translateX(-100%);
    }

    .bricks-is-frontend :is([data-slide-in-direction="left"], [data-slide-in-direction="left bottom"], [data-slide-in-direction="left top"], [data-submenu-reveal="slide"]).dwc-nest-menu.brx-open .brx-has-megamenu.brxe-dropdown.open>.brx-dropdown-content:not([data-submenu-reveal="expand"].brx-has-megamenu ul) {
        transform: translateX(0) !important;
    }

    html:not(.dwc-mobile) .bricks-is-frontend:is(.brx-header-left, .brx-header-right) :is([data-slide-in-direction="left"], [data-slide-in-direction="left bottom"], [data-slide-in-direction="left top"], [data-submenu-reveal="slide"]).dwc-nest-menu .brx-has-megamenu.brxe-dropdown.open>.brx-dropdown-content:not([data-submenu-reveal="expand"].brx-has-megamenu ul) {
        transform: translateX(0) !important;
        visibility: visible;
    }

    /*  SLIDE IN  - mult-level DROPDOWN ITEMS*/
    .bricks-is-frontend [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(:is([data-submenu-reveal="expand"], .brx-has-megamenu)) .brx-dropdown-content:not([data-submenu-reveal="expand"] *),
    .bricks-is-frontend [data-submenu-reveal="slide"].brxe-dropdown:not(.brx-has-megamenu) .brx-dropdown-content {
        inset-block: 0 !important;
        inline-size: 100%;
        transition-property: inset-inline-start, visibility, opacity;
        inset-inline-start: 100% !important;
        min-block-size: 100dvb;
        position: fixed !important;
    }

    .bricks-is-frontend :is([data-slide-in-direction="left"], [data-slide-in-direction="left bottom"], [data-slide-in-direction="left top"])[data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(.brx-has-megamenu, .open, [data-submenu-reveal="expand"]) .brx-dropdown-content:not([dir="rtl"] .brx-dropdown-content),
    .bricks-is-frontend :is([data-slide-in-direction="left"], [data-slide-in-direction="left bottom"], [data-slide-in-direction="left top"]) [data-submenu-reveal="slide"].brxe-dropdown:not(.brx-has-megamenu, .open) .brx-dropdown-content:not([dir="rtl"] .brx-dropdown-content),
    .bricks-is-frontend.brx-header-left [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(.brx-has-megamenu, [data-submenu-reveal="expand"], .open) .brx-dropdown-content:not([dir="rtl"] .brx-dropdown-content) {
        inset-inline-start: -100% !important;
    }

    /* RTL */
    [dir="rtl"] .brx-header-right.bricks-is-frontend [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested:not([data-slide-in-direction="left"], [data-slide-in-direction="left bottom"], [data-slide-in-direction="left top"]) .brxe-dropdown:not(.brx-has-megamenu, [data-submenu-reveal="expand"]) .brx-dropdown-content,
    [dir="rtl"] .brx-header-right.bricks-is-frontend .dwc-nest-menu:not([data-slide-in-direction="left"], [data-slide-in-direction="left bottom"], [data-slide-in-direction="left top"]) [data-submenu-reveal="slide"].brxe-dropdown:not(.brx-has-megamenu) .brx-dropdown-content,
    [dir="rtl"] .bricks-is-frontend [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested:not([data-slide-in-direction="left"], [data-slide-in-direction="left bottom"], [data-slide-in-direction="left top"]) .brxe-dropdown:not(.brx-has-megamenu, [data-submenu-reveal="expand"], .open) .brx-dropdown-content,
    [dir="rtl"] .bricks-is-frontend .dwc-nest-menu:not([data-slide-in-direction="left"], [data-slide-in-direction="left bottom"], [data-slide-in-direction="left top"]) [data-submenu-reveal="slide"].brxe-dropdown:not(.brx-has-megamenu, .open) .brx-dropdown-content {
        inset-inline-start: -100% !important;
    }

    [dir="rtl"] .brx-header-left.bricks-is-frontend :is([data-slide-in-direction="left"], [data-slide-in-direction="left bottom"], [data-slide-in-direction="left top"])[data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(.brx-has-megamenu, .open) .brx-dropdown-content,
    [dir="rtl"] .brx-header-left.bricks-is-frontend :is([data-slide-in-direction="left"], [data-slide-in-direction="left bottom"], [data-slide-in-direction="left top"]) [data-submenu-reveal="slide"].brxe-dropdown:not(.brx-has-megamenu, .open) .brx-dropdown-content,
    [dir="rtl"] .brx-header-left.bricks-is-frontend [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(.brx-has-megamenu, [data-submenu-reveal="expand"], .open) .brx-dropdown-content {
        inset-inline-start: 100% !important;
    }



    .bricks-is-frontend [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(.brx-has-megamenu, [data-submenu-reveal="expand"]) .brx-dropdown-content:not([data-hide-close-bar="true"] ul),
    .bricks-is-frontend [data-submenu-reveal="slide"].brxe-dropdown .brx-dropdown-content:not([data-hide-close-bar="true"] ul) {
        inset-block-start: var(--dwc-nest-header-height) !important;
    }

    .bricks-is-frontend [data-submenu-reveal="slide"].brxe-nav-nested.brx-open .brxe-dropdown.open:not(.brx-has-megamenu, [data-submenu-reveal="expand"])>.brx-dropdown-content,
    .bricks-is-frontend .brx-open [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-dropdown-content,
    .bricks-is-frontend .brx-open [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-dropdown-content .open>.brx-dropdown-content {
        inset-inline-start: 0 !important;
    }

    html:not(.dwc-mobile) .bricks-is-frontend:is(.brx-header-left, .brx-header-right) [data-submenu-reveal="slide"].brxe-nav-nested .brxe-dropdown.open:not(.brx-has-megamenu, [data-submenu-reveal="expand"])>.brx-dropdown-content,
    html:not(.dwc-mobile) .bricks-is-frontend:is(.brx-header-left, .brx-header-right) [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-dropdown-content,
    html:not(.dwc-mobile) .bricks-is-frontend:is(.brx-header-left, .brx-header-right) [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-dropdown-content .open>.brx-dropdown-content {
        inset-inline-start: 0 !important;
        visibility: visible;
    }

    .bricks-is-frontend .dwc-nest-menu .brxe-dropdown {
        position: static;
    }


    .bricks-is-frontend [data-submenu-reveal="slide"] .brx-submenu-toggle button svg:not([data-submenu-reveal="expand"] svg) {
        transform: rotate(270deg)
    }


    /*  EXPAND  - mult-level DROPDOWN ITEMS*/
    .bricks-is-frontend .dwc-nest-menu .brxe-dropdown[data-submenu-reveal="expand"]:not(.brx-has-megamenu)>.brx-dropdown-content>li,
    .bricks-is-frontend .dwc-nest-menu .brxe-dropdown[data-submenu-reveal="expand"]:not(.brx-has-megamenu)>.brx-dropdown-content>.brxe-dropdown .brx-dropdown-content>li,
    .bricks-is-frontend .dwc-nest-menu[data-submenu-reveal="expand"] .brxe-dropdown:not(.brx-has-megamenu, .open) .brx-dropdown-content>.menu-item:not([data-submenu-reveal="slide"] li) {
        transform: translateY(-100px);
        opacity: 0;
        transition: transform 0s, opacity 0s
    }

    .bricks-is-frontend .dwc-nest-menu .brxe-dropdown.open[data-submenu-reveal="expand"]:not(.brx-has-megamenu)>.brx-dropdown-content>li,
    .bricks-is-frontend .dwc-nest-menu .brxe-dropdown.open[data-submenu-reveal="expand"]:not(.brx-has-megamenu)>.brx-dropdown-content>.brxe-dropdown.open .brx-dropdown-content>li,
    .bricks-is-frontend .dwc-nest-menu[data-submenu-reveal="expand"] .brxe-dropdown:not(.brx-has-megamenu).open>.brx-dropdown-content>.menu-item {
        transform: translateY(0);
        opacity: 1 !important;
        transition: transform 0.4s, opacity 0.4s
    }

    /* MOBILE LOGO */
    .dwc-nest-menu:not([data-submenu-reveal="expand"]):has(.brxe-dropdown.open) .dwc-nest-menu__mobile-logo {
        opacity: 0;
        transition: 0s;
    }

    .dwc-nest-menu__mobile-logo {
        opacity: 1;
        transition: opacity 0.45s 0.15s var(--mobile-menu-ttf);
    }

    .dwc-nest-menu__mobile-logo:not(.brx-header-left *, .brx-header-right *) {
        min-block-size: var(--dwc-nest-header-height);
    }

    .brx-header-left .dwc-nest-menu__mobile-logo,
    .brx-header-right .dwc-nest-menu__mobile-logo {
        min-block-size: var(--top-offset);
    }

    :where(.brx-header-left, .brx-header-right) #brx-header:has([data-sidebar-back-text-on-logo="true"]) .dwc-nest-menu__logo {
        display: none;
    }

    :where(.brx-header-left, .brx-header-right) #brx-header:has([data-sidebar-back-text-on-logo="true"]) .dwc-nest-menu__mobile-logo {
        display: flex;
    }

    /* DROPDOWN INDENT */


    .dwc-nest-menu[data-submenu-reveal="expand"] .brxe-dropdown:not(.brx-has-megamenu)>.brx-dropdown-content:not(.brxe-dropdown[data-submenu-reveal="slide"] .brx-dropdown-content),
    .dwc-nest-menu .brxe-dropdown[data-submenu-reveal="expand"]:not(.brx-has-megamenu) .brx-dropdown-content {
        padding-inline-start: var(--dropdown-indent) !important;
        padding-inline-end: calc(var(--dropdown-indent) * 0) !important;
        border-left: var(--dropdown-indent-line);
        background-color: var(--dropdown-indent-bg)
    }


    .dwc-nest-menu[data-submenu-reveal="expand"] .brxe-dropdown:not(.brx-has-megamenu)>.brx-dropdown-content:not(.brxe-dropdown[data-submenu-reveal="slide"] *)>*> :is(a, .brx-submenu-toggle),
    .dwc-nest-menu .brxe-dropdown[data-submenu-reveal="expand"]:not(.brx-has-megamenu)>.brx-dropdown-content>*> :is(a, .brx-submenu-toggle) {
        padding-inline-start: calc(var(--dropdown-item-inline-padding) * var(--dropdown-indent-item-pad-offset)) !important;
    }


    .dwc-nest-menu[data-submenu-reveal="expand"] .brxe-dropdown.open>.brx-submenu-toggle,
    .dwc-nest-menu [data-submenu-reveal="expand"].brxe-dropdown.open>.brx-submenu-toggle {
        background-color: var(--dropdown-expanded-bg);
        color: var(--dropdown-expanded-clr);
    }

    .dwc-nest-menu[data-submenu-reveal="expand"] .brxe-dropdown.open>.brx-submenu-toggle svg, 
.dwc-nest-menu [data-submenu-reveal="expand"].brxe-dropdown.open>.brx-submenu-toggle svg{
    color: var(--dropdown-expanded-clr) !important;
}


    /* BACK BUTTON POSITIONING */
    .bricks-is-frontend [data-submenu-reveal="slide"] .open.active>.brx-submenu-toggle button:not([data-hide-close-bar="true"] button, [data-submenu-reveal="expand"] button),
    .bricks-is-frontend [data-submenu-reveal="slide"].open.active>.brx-submenu-toggle button:not([data-hide-close-bar="true"] button, [data-submenu-reveal="expand"] button) {
        min-inline-size: 70%;
        position: fixed;
        inset-block-start: 0;
        transform: translateY(0%) !important;
        inset-inline-start: var(--menu-item-inline-padding);
        color: var(--back-text-clr);
        text-transform: var(--back-text-transform);
        letter-spacing: 1px;
        /* padding-inline: 1rem !important; */
        z-index: 1000;
        font-size: var(--back-text-font-size);
        font-weight: var(--back-text-font-weight);
        background-color: var(--back-text-bg);
        min-block-size: calc(var(--dwc-nest-header-height) - 2px);
        -webkit-animation: dwc-nest-fade-in 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.3s both;
        animation: dwc-nest-fade-in 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.3s both;
    }




    /* BACK BUTTON TEXT, (ATTR SET BY JS) */
    .bricks-is-frontend [data-submenu-reveal="slide"] .open.active>.brx-submenu-toggle button[data-back-text="auto"]:not([data-submenu-reveal="expand"] button, [data-hide-close-bar="true"] button):after,
    .bricks-is-frontend [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-submenu-toggle button[data-back-text="auto"]:not([data-hide-close-bar="true"] button):after {
        content: attr(data-text);
    }

    /* FORCE TO USE 'BACK' AS BACK BUTTON TEXT */

    .bricks-is-frontend .dwc-nest-menu:not([data-submenu-reveal="expand"]) .brxe-dropdown.open:not([data-submenu-reveal="expand"])>.brx-submenu-toggle button:not([data-back-text="auto"])::after {
        content: attr(data-back-text) !important;
    }

    .dwc-nest-menu:not([data-submenu-reveal="expand"]) .brxe-dropdown:not([data-submenu-reveal="expand"]) .brx-submenu-toggle button[aria-expanded] {
        transition: unset !important;
    }

    /* BACK BUTTON CHEVRON ARROW direction */
    .bricks-is-frontend [data-submenu-reveal="slide"] .brxe-dropdown.open>.brx-submenu-toggle button svg:not([data-submenu-reveal="expand"] svg),
    .bricks-is-frontend [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-submenu-toggle button svg {
        transform: rotate(90deg);
        margin-inline-end: 0.5em;
        inline-size: 10px;
    }

    /* RTL */
    [dir="rtl"] .bricks-is-frontend [data-submenu-reveal="slide"] .brxe-dropdown.open:not([data-submenu-reveal="expand"])>.brx-submenu-toggle button svg,
    [dir="rtl"] .bricks-is-frontend [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-submenu-toggle button svg {
        order: 2;
        margin-inline-end: initial;
        margin-inline-start: 0.5em;
    }




    /* overlay back button on logo*/
    body:has(.brx-open .open.active:not([data-submenu-reveal="expand"], [data-submenu-reveal="expand"] .open)) [data-mobile-top-transparent="true"]:not([data-submenu-reveal="expand"], [data-below-header="true"]) .dwc-nest-menu-top {
        background-color: var(--mobile-menu-topbar-bg) !important;
        -webkit-animation: dwc-nest-fade-in 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.2s both;
        animation: dwc-nest-fade-in 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.2s both;
    }

    body:has([data-submenu-reveal="slide"].brxe-dropdown.open, [data-submenu-reveal="slide"] .brxe-dropdown.open:not([data-submenu-reveal="expand"], [data-submenu-reveal="expand"] .open)) [data-mobile-top-transparent="true"] .dwc-nest-menu-top:not([data-below-header="true"] *) {
        background-color: var(--mobile-menu-topbar-bg) !important;
    }

    .dwc-mobile [data-mobile-top-transparent="true"] .dwc-nav-wrapper:not([data-below-header="true"] .dwc-nav-wrapper, [data-show-mobile-logo="true"] .dwc-nav-wrapper, [data-fullscreen-mobile-menu="true"] .dwc-nav-wrapper) {
        background-color: transparent !important;
    }


    .dwc-mobile [data-mobile-top-transparent="true"] .dwc-nest-menu-top:not([data-below-header="true"] *, [data-show-mobile-logo="true"] *) {
        background-color: transparent !important;
    }




    /* MENU BELOW HEADER */
     .bricks-is-frontend [data-below-header="true"].dwc-nest-menu .dwc-nav-wrapper {
    inset-block-start: calc(var(--dwc-nest-header-height) + var(--wp-admin--admin-bar--height, 0px));
}

    [data-below-header="true"] .dwc-nest-menu-top {
        min-block-size: var(--top-offset);
    }

    .bricks-is-frontend [data-below-header="true"] .brxe-dropdown.open>.brx-submenu-toggle button:not([data-hide-close-bar="true"] button, [data-submenu-reveal="expand"] button) {
        min-block-size: calc(var(--top-offset) - 1px);
        padding-block: 0 !important;
    }


    .bricks-is-frontend [data-below-header="true"].dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(.brx-has-megamenu) .brx-dropdown-content:not([data-hide-close-bar="true"] ul),
    .bricks-is-frontend [data-submenu-reveal="slide"].brxe-dropdown .brx-dropdown-content:not([data-hide-close-bar="true"] ul) {
        inset-block-start: calc(var(--top-offset) + 1px) !important;
    }

    .bricks-is-frontend [data-below-header="true"].dwc-nest-menu.brxe-nav-nested .brx-has-megamenu.brxe-dropdown .brx-dropdown-content:not([data-hide-close-bar="true"] ul, [data-submenu-reveal="expand"].brx-has-megamenu ul) {
        inset-block-start: calc(var(--top-offset) + 1px) !important;
    }

    .dwc-nest-menu[data-below-header="true"] .dwc-nest-menu__mobile-logo {
        display: none;
    }



    /* tooltip */

    .dwc-nest-tooltip:not(.dwc-nav-wrapper:has(.open.active) .dwc-nest-tooltip, .dwc-tabbed-nav-list__li.active ~ .dwc-nest-tooltip) {
        opacity: 0 !important;
    }


    @keyframes slideIn {
        0% {
            transform: translateX(-100%);
            opacity: 0;
        }

        100% {
            transform: translateX(0);
            opacity: 1;
        }
    }

    @keyframes fadeOut {
        0% {
            transform: translateX(0);
            opacity: 1;
        }

        100% {
            transform: translateX(50%);
            opacity: 0;
        }
    }

    .dwc-nest-tooltip {
        animation: slideIn 0.4s ease-in-out both, fadeOut 0.4s ease-in-out 2s both;
        text-transform: initial;
    }


    /* EXPAND DROP DOWN */
    /* EXPAND MEGA MENU DROP DOWN */

    [data-submenu-reveal="expand"] .brx-has-megamenu .brx-dropdown-content {
        display: grid !important;
        grid-template-rows: 0fr;
        grid-template-columns: 1fr;
        transition: 0.3s ease-in-out;
        overflow: hidden;
        position: static;
        visibility: visible;
        opacity: 1;
    }

    [data-submenu-reveal="expand"] .brx-has-megamenu.brxe-dropdown.open.active .brx-dropdown-content {
        grid-template-rows: 1fr;
        grid-template-columns: 1fr;

    }

    [data-submenu-reveal="expand"] .brx-has-megamenu .brx-dropdown-content> :is(div, li) {
        padding-block: 0 !important;
        opacity: 0;
        transition: opacity 0.3s ease;
    }

    [data-submenu-reveal="expand"] .brx-has-megamenu .brx-dropdown-content :is(div, li):not([data-submenu-reveal="slide"] *) {
        flex-wrap: nowrap !important;
        min-block-size: 0 !important;
    }

    [data-submenu-reveal="expand"] .brx-has-megamenu.brxe-dropdown.open.active .brx-dropdown-content> :is(div, li) {
        opacity: 1;
        transition: opacity 0.25s 0.25s ease;
    }

    /* EXPAND MEGA MENU DROP DOWN -- MODULAR*/

    [data-submenu-reveal="expand"].brx-has-megamenu .brx-dropdown-content {
        display: grid !important;
        grid-template-rows: 0fr;
        grid-template-columns: 1fr;
        transition: 0.3s ease-in-out;
        overflow: hidden;
        position: static;
        visibility: visible;
        opacity: 1;
    }

    [data-submenu-reveal="expand"].brx-has-megamenu.brxe-dropdown.open.active .brx-dropdown-content {
        grid-template-rows: 1fr;
        grid-template-columns: 1fr;
    }

    [data-submenu-reveal="expand"].brx-has-megamenu .brx-dropdown-content> :is(div, li) {
        padding-block: 0 !important;
        opacity: 0;
        transition: opacity 0.3s ease;
    }

    [data-submenu-reveal="expand"].brx-has-megamenu .brx-dropdown-content :is(div, li) {
        flex-wrap: nowrap !important;
        min-block-size: 0 !important;
    }

    [data-submenu-reveal="expand"].brx-has-megamenu.brxe-dropdown.open.active .brx-dropdown-content> :is(div, li) {
        opacity: 1;
        transition: opacity 0.8s 0.25s ease;
    }

    /* HIDE TOP CLOSE BAR */
    [data-hide-close-bar='true'] .dwc-nest-menu-top {
        display: none;
    }



    /* hide close button, bring main hamburger to front */

    .dwc-nest-menu .brxe-toggle {
        position: relative;
    }

    [data-mobile-top-transparent="true"]:not(:has(.brxe-dropdown.open)) .brxe-toggle[aria-label="Open Menu"] {
        z-index: 9999;
    }

    [data-show-toggle-always="true"] .brxe-toggle[aria-label="Open Menu"] {
        z-index: 9999;
    }

    .dwc-nest-menu:not([data-mobile-top-transparent="true"], [data-below-header="true"]) .brxe-toggle[aria-label="Close Menu"] {
        display: grid;
        place-items: center;
        height: 100%;
    }

    .dwc-nest-menu .brx-nav-nested-items>.brxe-dropdown>.brx-dropdown-content {
        transform: unset;
    }

    .dwc-nest-menu .brx-nav-nested-items>.brxe-dropdown.open>.brx-dropdown-content {
        transform: unset;
    }

    .dwc-stripe-style .dwc-nest-header::after,
    .dwc-stripe-style .dwc-nest-header::before {
        display: none !important;
    }


    /* builder */
    [data-builder-mode] .dwc-nest-menu-top {
        min-block-size: 80px !important;
    }

    [data-builder-mode] .dwc-nest-nav-items {
        overflow-y: scroll;
    }

    /* in builder ends*/

    /*==========RTL=============*/

    [dir=rtl] .bricks-is-frontend [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested:not([data-slide-in-direction="right"]) .brx-has-megamenu.brxe-dropdown .brx-dropdown-content:not([data-submenu-reveal="expand"].brx-has-megamenu ul) {
        transform: translateX(-100%);
    }

    [dir=rtl] nav:not(.brx-open, [data-slide-in-direction="right"]) .dwc-nav-wrapper {
        transform: translateX(-100%);
    }

    [dir=rtl] .bricks-is-frontend [data-submenu-reveal="slide"] .brx-submenu-toggle button svg:not([data-submenu-reveal="expand"] svg) {
        transform: rotate(-270deg);
    }

    /* ================== BRICKS RESET LAYER ========================== */

    @layer bricks.reset {

        /* multilevel dropdown slide in */


        .bricks-is-frontend [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(:is([data-submenu-reveal="expand"], .brx-has-megamenu)) .brx-dropdown-content:not([data-submenu-reveal="expand"] *, .brx-header-left *, .brx-header-right *),
        .bricks-is-frontend [data-submenu-reveal="slide"].brxe-dropdown:not(.brx-has-megamenu) .brx-dropdown-content:not(.brx-header-left *, .brx-header-right *) {
            inset-inline-start: 100% !important;
        }

        [dir=rtl] .bricks-is-frontend [data-slide-in-direction="right"][data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(:is([data-submenu-reveal="expand"], .brx-has-megamenu), .open) .brx-dropdown-content:not([data-submenu-reveal="expand"] *),
        [dir=rtl] .bricks-is-frontend [data-slide-in-direction="right"][data-submenu-reveal="slide"].brxe-dropdown:not(.brx-has-megamenu, .open) .brx-dropdown-content {
            inset-inline-start: -100% !important;
        }

        .bricks-is-frontend [data-submenu-reveal="slide"][data-slide-in-direction^="left"].dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(:is([data-submenu-reveal="expand"], .brx-has-megamenu)) .brx-dropdown-content:not([data-submenu-reveal="expand"] *, .brx-header-left *, .brx-header-right *),
        .bricks-is-frontend [data-submenu-reveal="slide"].brxe-dropdown:not(.brx-has-megamenu) .brx-dropdown-content:not(.brx-header-left *, .brx-header-right *) {
            inset-inline-start: -100% !important;
        }

        /*sidebar*/
        .bricks-is-frontend:is(.brx-header-right, brx-header-left) [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(:is([data-submenu-reveal="expand"], .brx-has-megamenu, .open)) .brx-dropdown-content:not([data-submenu-reveal="expand"] *, .-brx-header-left *, .-brx-header-right *),
        .bricks-is-frontend:is(.brx-header-right, brx-header-left) [data-submenu-reveal="slide"].brxe-dropdown:not(.brx-has-megamenu, .open) .brx-dropdown-content:not(.brx-header-left *, .brx-header-right *) {
            inset-inline-start: 100% !important;
        }





        .bricks-is-frontend [data-submenu-reveal="slide"].brxe-nav-nested.brx-open .brxe-dropdown.open:not(.brx-has-megamenu, [data-submenu-reveal="expand"])>.brx-dropdown-content,
        .bricks-is-frontend .brx-open [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-dropdown-content,
        .bricks-is-frontend .brx-open [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-dropdown-content .open>.brx-dropdown-content {
            inset-inline-start: 0 !important;
        }


        .bricks-is-frontend [data-submenu-reveal="slide"][data-slide-in-direction^="left"].brxe-nav-nested.brx-open .brxe-dropdown.open:not(.brx-has-megamenu, [data-submenu-reveal="expand"])>.brx-dropdown-content,
        .bricks-is-frontend [data-slide-in-direction^="left"] .brx-open [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-dropdown-content,
        .bricks-is-frontend [data-slide-in-direction^="left"] .brx-open [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-dropdown-content .open>.brx-dropdown-content {
            inset-inline-start: 0 !important;
        }

        /*sidebar*/
        .bricks-is-frontend:is(.brx-header-right, brx-header-left) [data-submenu-reveal="slide"].brxe-nav-nested .brxe-dropdown.open:not(.brx-has-megamenu, [data-submenu-reveal="expand"])>.brx-dropdown-content,
        .bricks-is-frontend:is(.brx-header-right, brx-header-left) [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-dropdown-content,
        .bricks-is-frontend:is(.brx-header-right, brx-header-left) [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-dropdown-content .open>.brx-dropdown-content {
            inset-inline-start: 0 !important;
        }

        .brx-closing.brxe-nav-nested .brx-nav-nested-items {
            opacity: 1 !important;
        }

        .dwc-nest-menu.brxe-nav-nested.brx-closing .brx-nav-nested-items {
            opacity: unset !important;
            visibility: unset !important;
        }

    }

    /* ================== END BRICKS RESET LAYER ========================== */

}


/* END MEDIA QUERY*/



@media (min-width: 640px) and (max-width: 1200px) {

    /* ================== BRICKS RESET LAYER ========================== */

    @layer bricks.reset {

        /*special mobile style on tablet */

        .dwc-mobile .bricks-is-frontend [data-mobile-special-style="slide-split"] [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(:is([data-submenu-reveal="expand"], .brx-has-megamenu)) .brx-dropdown-content:not([data-submenu-reveal="expand"] *),
        .bricks-is-frontend [data-mobile-special-style="slide-split"] [data-submenu-reveal="slide"].brxe-dropdown:not(.brx-has-megamenu) .brx-dropdown-content {

            inset-inline-start: auto !important;
            inset-inline-end: -100% !important;
        }

        .dwc-mobile .bricks-is-frontend [data-mobile-special-style="slide-split"] [data-submenu-reveal="slide"].brxe-nav-nested.brx-open .brxe-dropdown.open:not(.brx-has-megamenu, [data-submenu-reveal="expand"])>.brx-dropdown-content,
        .bricks-is-frontend [data-mobile-special-style="slide-split"] .brx-open [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-dropdown-content,
        .bricks-is-frontend [data-mobile-special-style="slide-split"] .brx-open [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-dropdown-content .open>.brx-dropdown-content {
            inset-inline-end: 0% !important;
            inset-inline-start: auto !important;
        }



    }

    /* ================== END BRICKS RESET LAYER ========================== */
}

/* END MEDIA QUERY*/
@media (min-width: 1201px){
  .dwc-mobile header{
      display: none;
  }  
  
  @layer bricks.reset{
.brx-dropdown-content:not(.brx-submenu-positioned) {
    display: flex!important;
}
}

  
  /* CENTERED LOGO*/

  /*force center align for centered logo menu */

.dwc-nest-header__container.dwc-logo-is-centered {
    justify-content: center;
}
  
  .dwc-logo-is-centered .dwc-nest-menu .brx-nav-nested-items{
  justify-content: center;
}


/*remvoe bricks default margin left*/
#brx-header .dwc-logo-is-centered .dwc-nest-menu li:not(.brx-dropdown-content *){
  
    margin-inline: 0 !important;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

/* prevent logo from shrinking on sceen resize*/
#brx-header .dwc-logo-is-centered .dwc-header-logo-item{
   flex-shrink: 0;
} 

.dwc-center-guide {
  background-color: rgba(132, 255, 0, 0.32);
  position: fixed;
  top: 0;
  bottom: 0;  
  align-self: center;
  height: 100dvb;
  z-index: 9999;
  pointer-events: none;
}
  
  body:not(:has([data-fix-centered-logo-fouc="true"])) .dwc-center-guide::before {
    content: 'To fix FOUC on the header, Go to Header Pro div > Attribute > data-fix-centered-logo-fouc, set the value to "true"';
    position: absolute;
    top: 30vh;
    padding: 1rem;
   background-color: white;
 
}

.dwc-logo-is-centered .dwc-menu-wrap{
  inline-size:100%
}


  
  .dwc-nest-header .brx-nav-nested-items {    
    transition-property: opacity,transform;   
}
  
  body.adaptive-height-active:has([data-fix-centered-logo-fouc="true"]):not(:has(.dwc-logo-is-centered))::before {
    content: 'Go to the Header Pro section > Attribute > data-fix-centered-logo-fouc, remove the value "true" OR enable Centered Logo';
}
  

}

/*=======================================  MIN WIDTH MEDIA QUERY ENDS  ==============================================================*/

  body:has([data-overlay-header="true"]) .dwc-nest-menu-overlay {   
    inset-block-start: 0 ;  
}

/*fix centered logo fouc*/
  html:not(.dwc-mobile)  .bricks-is-frontend header:has([data-fix-centered-logo-fouc="true"]):not(.desktop-centered header) {
    opacity: 0;
}



/*end fix fouc*/

.dwc-adaptive-height:not(.dwc-stripe-style){
    --dropdown-content-gap: 0 
}

html:not(.dwc-mobile) .bricks-is-frontend:not(.brx-header-right, .brx-header-left) .dwc-nest-menu:not([data-offcanvas="true"]) .brxe-dropdown:not(.brx-has-megamenu) .brx-dropdown-content:not(.brx-dropdown-content .brx-dropdown-content){
  inset-inline-start: 0 !important;
}



html:not(.dwc-mobile) .bricks-is-frontend .dwc-nest-menu .brx-dropdown-content .brx-dropdown-content:not(.brx-sub-submenu-overflow-right, .brx-submenu-overflow-right){
inset-inline-start: 100% !important;
}


html:not(.dwc-mobile) .bricks-is-frontend .dwc-nest-menu .brxe-dropdown:not(.brx-has-megamenu) .brx-dropdown-content{
    min-inline-size: var(--multilevel-dropdown-width) !important;    
}

html:not(.dwc-mobile) .bricks-is-frontend .dwc-nest-menu .brx-dropdown-content{ 
  box-shadow: var(--dropdown-content-shadow);
}

html:not(.dwc-mobile) .bricks-is-frontend:not(.brx-header-left, .brx-header-right) .dwc-nest-menu:not([data-offcanvas="true"]) .brx-has-megamenu .brx-dropdown-content > *{ 
  max-block-size: calc(95dvb - calc(var(--dwc-nest-header-height) + var(--wp-admin--admin-bar--height, 0px)));
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin !important;
}


.dwc-nest-menu[data-submenu-reveal="expand"] .brx-nav-nested-items > .brxe-dropdown:not([data-submenu-reveal="slide"], .brx-has-megamenu)  > .brx-submenu-toggle {
transform: translateY(0);
z-index: 9999;
}


:is([data-submenu-reveal="expand"][data-offcanvas="true"]) .brxe-dropdown:not(.brx-has-megamenu) .brx-dropdown-content,
:is(.brx-header-right, .brx-header-left) [data-submenu-reveal="expand"] .brxe-dropdown:not(.brx-has-megamenu) .brx-dropdown-content{
inset-block-start: 0;
transition: 0s;
min-inline-size: var(--mobile-menu-width);
}

.dwc-nest-toggle--open.brxe-toggle .brxa-inner:before {   
block-size: var(--open-icon-line-height);
inset-inline-end: var(--open-icon-align);       
}

.dwc-nest-toggle--open.brxa--vortex .brxa-inner:before {   
inline-size: var(--open-icon-size);      
}

.dwc-nest-toggle--open.brxa--vortex .brxa-inner:not(.is-active .brxa-inner):before {   
inset-block-start: calc(var(--icon-line-gap) * -1); 
}

.dwc-nest-toggle--open.brxa--vortex .brxa-inner:not(.is-active .brxa-inner):after {   
inset-block-end: calc(var(--icon-line-gap) * -1); 
}

.dwc-nest-toggle--open.brxe-toggle .brxa-inner{
block-size: var(--open-icon-line-height);
inset-inline-end:  var(--open-icon-horizontal-offset);      
}

.dwc-nest-toggle--open.brxa--vortex .brxa-inner{
inline-size:var(--iw);    
}

.dwc-nest-toggle--open.brxe-toggle .brxa-inner:after {   
block-size: var(--open-icon-line-height);
inset-inline-end:  var(--open-icon-align);
}

.dwc-nest-toggle--open.brxa--vortex .brxa-inner:after {   
inline-size: var(--aw);
}


.dwc-nest-toggle--open.brxa--vortex.is-active .brxa-inner:after, 
.dwc-nest-toggle--open.brxa--vortex.is-active .brxa-inner {
    inline-size: calc(var(--iw) * var(--open-icon-close-offset));
}


.dwc-nest-toggle--open.brxa--vortex .brxa-wrap{
inline-size: var(--open-icon-size)
}

.dwc-nest-menu .brxa-inner, 
.dwc-nest-menu .brxa-inner:after, 
.dwc-nest-menu .brxa-inner:before{
background-color: var(--menu-toggle-clr)
}

.dwc-nest-menu.brxe-nav-nested .brxe-toggle[aria-label="Close Menu"] i{
color: var(--menu-close-toggle-clr)
}

.dwc-nest-menu .brxa-wrap:hover .brxa-inner,
.dwc-nest-menu .brxa-wrap:hover .brxa-inner:after, 
.dwc-nest-menu .brxa-wrap:hover .brxa-inner:before {
background-color: var(--menu-toggle-hover-clr) !important
}

/* icon animation */

.dwc-nest-toggle--open.brxa--vortex .brxa-inner {
transition-duration: .3s;
transition-timing-function: ease-in-out;
}

.dwc-nest-toggle--open.brxa--vortex.is-active .brxa-inner {
transform: rotate(225deg);
transition-timing-function: ease-in-out;
}

.dwc-nest-toggle--open.brxa--vortex.is-active .brxa-inner:before {
opacity: 0;
inset-block-start: calc(var(--icon-line-gap) * -1);
inline-size: 0px !important;   
}

.dwc-nest-toggle--open .brxa-inner:before {
transition-duration: 0.25s;
transition-property: inline-size, tansform !important;

}



/* MENU ITEMS SPACING AND COLOR*/
/* Shared styles for both menu types */
.dwc-nest-menu .brx-nav-nested-items > li > a:not(.dwc-nest-menu__logo),
.dwc-nest-menu .brx-nav-nested-items > li .brx-submenu-toggle,
.dwc-nest-menu .brx-dropdown-content > .menu-item > a {
font-weight: var(--menu-item-font-weight);
font-size: var(--menu-item-font-size);
color: var(--menu-item-clr);
background-color: var(--menu-item-bg);
inline-size: 100%;
}

.dwc-nest-menu .brx-dropdown-content > .brxe-dropdown > .brx-submenu-toggle,
.dwc-nest-menu .brx-dropdown-content > .menu-item > a {
  --menu-item-font-size: var(--dropdown-item-font-size)
}

/* Specific padding for nested menu items */
.dwc-nest-menu .brx-nav-nested-items > li > a,
.dwc-nest-menu .brx-nav-nested-items > li.brx-has-megamenu .brx-submenu-toggle {
padding-block: var(--menu-item-block-padding);
padding-inline: var(--menu-item-inline-padding) !important;
}

/* Specific padding for dropdown items */

.dwc-nest-menu .brx-dropdown-content > .menu-item > a {
  padding-block: var(--dropdown-item-block-padding);
  padding-inline: var(--dropdown-item-inline-padding) !important;
}

.dwc-nest-menu .brx-nav-nested-items > .brxe-dropdown:not(.brx-has-megamenu) li .brx-submenu-toggle{
padding-block: var(--dropdown-item-block-padding);
  padding-inline: var(--dropdown-item-inline-padding) !important;
}

.dwc-nest-menu .brx-nav-nested-items > li:not(.brx-has-megamenu) .brx-submenu-toggle:not(.brxe-dropdown li .brx-submenu-toggle){
padding-block: var(--menu-item-block-padding);
  padding-inline: var(--menu-item-inline-padding) !important;

}
/* .dwc-nest-menu .brx-dropdown-content > .menu-item > a,
.dwc-nest-menu .brx-nav-nested-items > li:not(.brx-has-megamenu) .brx-submenu-toggle {
padding-block: var(--dropdown-item-block-padding);
padding-inline: var(--dropdown-item-inline-padding) !important;
} */

.dwc-nest-menu .brx-dropdown-content > .menu-item > a:not([aria-current="page"], li:hover > *),
li:not(.brx-has-megamenu) .brx-submenu-toggle:not( .brx-nav-nested-items > li > *, li:hover > *, .open.active *) {
color: var(--dropdown-item-clr) !important;
}


/* DROPDOWN MENU ITEMS BG COLOR */
.dwc-nest-menu .brx-dropdown-content > .menu-item > a:not(.brx-has-megamenu a),
li:not(.brx-has-megamenu) .brx-submenu-toggle:not( .brx-nav-nested-items > li > *) {
background-color: var(--dropdown-item-bg)
}

/* DROPDOWN BG COLOR */
.dwc-nest-menu .brxe-dropdown:not(.brx-has-megamenu) .brx-dropdown-content {
background-color: var(--dropdown-content-bg);
}

/* HOVER STYLES */
.dwc-nest-menu .brx-nav-nested-items > li:hover > a,
.dwc-nest-menu .brx-nav-nested-items > li:hover > .brx-submenu-toggle,
.dwc-nest-menu .brx-dropdown-content > li:hover > .brx-submenu-toggle,
.dwc-nest-menu .brx-dropdown-content > .menu-item:hover > a {
color: var(--menu-item-hover-clr);
background-color: var(--menu-item-hover-bg)
}

.dwc-nest-nav-dropdown-link:hover {
color: var(--menu-item-hover-clr);
}

.dwc-nest-menu .brx-nav-nested-items > li > a:not([data-last-item-is-button="true"] .brx-nav-nested-items > .menu-item:last-of-type a, [data-last-item-is-button="true-2"] .brx-nav-nested-items > .menu-item:nth-last-of-type(-n+2) a, [data-last-item-is-button="true-3"] .brx-nav-nested-items > .menu-item:nth-last-of-type(-n+3) a, .dwc-nest-menu__logo):hover::before,
body:not(.brx-header-left, .brx-header-right) .dwc-nest-menu .brx-nav-nested-items > li > a:not([data-last-item-is-button="true"] .brx-nav-nested-items > .menu-item:last-of-type a, [data-last-item-is-button="true-2"] .brx-nav-nested-items > .menu-item:nth-last-of-type(-n+2) a, [data-last-item-is-button="true-3"] .brx-nav-nested-items > .menu-item:nth-last-of-type(-n+3) a, .dwc-nest-menu__logo):focus-visible::before,
.dwc-nest-menu .brx-nav-nested-items > li:hover > .brx-submenu-toggle::before,
body:not(.brx-header-left, .brx-header-right) .dwc-nest-menu .brx-nav-nested-items > li:focus-within > .brx-submenu-toggle::before{
    content: '';
    background-color: var(--menu-item-hover-border-bg);
    inline-size: 100%;
    block-size: var(--menu-item-hover-border-height);
    position: absolute;
    inset-block-start: calc(100% - var(--menu-item-hover-border-height));
    inset-inline-start: 0;
}

.dwc-nest-menu .brx-nav-nested-items > li.menu-item:has(> a),
.dwc-nest-menu .brx-nav-nested-items > li.menu-item:has(> .brx-submenu-toggle) {
   position: relative; 
}

/* ACTIVE STYLES */
/* links and dropdwon active styles */
.dwc-nest-menu .brx-nav-nested-items a[aria-current="page"]:not(.brxe-button, .dwc-exclude, .dwc-exclude a, li:hover > a, a:hover, .dwc-nest-menu__logo, 
[data-last-item-is-button="true"] .brx-nav-nested-items > .menu-item:last-of-type a, 
[data-last-item-is-button="true-2"] .brx-nav-nested-items > .menu-item:nth-last-of-type(-n+2) a, 
[data-last-item-is-button="true-3"] .brx-nav-nested-items > .menu-item:nth-last-of-type(-n+3) a),
.dwc-nest-menu .brx-nav-nested-items > li:has([aria-current="page"]:not(.dwc-exclude)):not(li:hover) > .brx-submenu-toggle {
color: var(--menu-item-active-clr);
background-color: var(--menu-item-active-bg);
}

.dwc-nest-menu .brx-nav-nested-items .brx-submenu-toggle > a[aria-current="page"]{   
  background-color: initial !important;  
}

.dwc-nest-menu .brx-nav-nested-items a[aria-current="page"]:not(.brxe-button, .dwc-exclude, .dwc-exclude a, .dwc-nest-menu__logo),
.dwc-nest-menu .brx-nav-nested-items > li .brx-submenu-toggle{
  position: relative;
}

.dwc-nest-menu .brx-nav-nested-items a[aria-current="page"]:not(.brxe-button, .dwc-exclude, .dwc-exclude a, [data-last-item-is-button="true"] .brx-nav-nested-items > .menu-item:last-of-type a, 
[data-last-item-is-button="true-2"] .brx-nav-nested-items > .menu-item:nth-last-of-type(-n+2) a, 
[data-last-item-is-button="true-3"] .brx-nav-nested-items > .menu-item:nth-last-of-type(-n+3) a, .dwc-nest-menu__logo, .brx-submenu-toggle > a)::before,
.dwc-nest-menu .brx-nav-nested-items > li:has([aria-current="page"]:not(.dwc-exclude)) > .brx-submenu-toggle::before{
  content: '';
  background-color: var(--menu-item-active-border-bg);
  inline-size: 100%;
  block-size: var(--menu-item-active-border-height);
  position: absolute; 
  inset-block-start: calc(100% - var(--menu-item-active-border-height));
  inset-inline-start: 0;  
}

.dwc-nest-menu .brx-nav-nested-items > li:has([aria-current="page"]:not(.dwc-exclude)) > .brx-submenu-toggle > :is(a:not(.dwc-nest-menu__logo), svg, button, span){
color: var(--menu-item-active-clr);
}


/* DROPDOWN HOVER BG */
.dwc-nest-menu .brx-dropdown-content > li:hover > .brx-submenu-toggle:not(.brx-has-megamenu *), 
.dwc-nest-menu .brx-dropdown-content > li:hover > a:not(.brx-has-megamenu a){
background-color: var(--dropdown-item-hover-bg) ;
color: var(--dropdown-item-hover-clr);
}


.dwc-nest-menu.brxe-nav-nested .brx-submenu-toggle {
justify-content: space-between;
}

/* DROPDOWN INDENT */

:is(.dwc-mobile, .brx-header-left, .brx-header-right, body:has([data-offcanvas="true"])) 
:is([data-submenu-reveal="expand"])
.brxe-dropdown:not(.brx-has-megamenu) > 
.brx-dropdown-content:not(.brxe-dropdown[data-submenu-reveal="slide"] *) {
padding-inline-start: var(--dropdown-indent) !important;
padding-inline-end: calc(var(--dropdown-indent) * 0) !important;
border-left: var(--dropdown-indent-line);  
background-color: var(--dropdown-indent-bg)
}

:is(.dwc-mobile, .brx-header-left, .brx-header-right, body:has([data-offcanvas="true"])) 
:is([data-submenu-reveal="expand"]) 
.brxe-dropdown:not(.brx-has-megamenu) > 
.brx-dropdown-content:not(.brxe-dropdown[data-submenu-reveal="slide"] *) > * > :is(a, .brx-submenu-toggle){
padding-inline-start: calc(var(--dropdown-item-inline-padding) * var(--dropdown-indent-item-pad-offset)) !important;
}

/* :is(.dwc-mobile, .brx-header-left, .brx-header-right, body:has([data-offcanvas="true"])) 
:is([data-submenu-reveal="expand"]) 
.open.active.brxe-dropdown > .brx-submenu-toggle{
background-color: var(--dropdown-expanded-bg);
color: var(--dropdown-expanded-clr);
} */

:is(.dwc-mobile, .brx-header-left, .brx-header-right, body:has([data-offcanvas="true"])) 
:is([data-submenu-reveal="expand"]) 
.open.active.brxe-dropdown > .brx-submenu-toggle svg:not(.open.active.brxe-dropdown:hover > .brx-submenu-toggle svg){
color: var(--dropdown-expanded-clr);
}


/* MENU ITEMS COLOR */
.dwc-nest-menu .brx-nav-nested-items > li .brx-submenu-toggle :where(span, a, svg) {
color: inherit;
font-weight: inherit;
} 

/* CHEVRON */
.dwc-nest-menu .brx-nav-nested-items > li:not(li:has([aria-current="page"]:not(.dwc-exclude)), li:hover) .brx-submenu-toggle svg{
color: var(--chevron-clr);
}

.dwc-nest-menu .brx-nav-nested-items > li .brx-submenu-toggle svg{
  font-size: var(--chevron-size);
  color: var(--chevron-clr);
  }
  .dwc-nest-menu .brx-nav-nested-items > li:has([aria-current="page"]:not(.dwc-exclude)) > .brx-submenu-toggle svg,
.dwc-nest-menu .brx-nav-nested-items  li:hover > .brx-submenu-toggle svg{  
  color: var(--chevron-hover-clr);
  }

[data-align-dropdown-top="true"] .brx-dropdown-content .brxe-dropdown { 
position: static;   
}

.brx-dropdown-content:not(.brx-has-megamenu .brx-dropdown-content) {
padding-inline-end: 0 !important;
}


/*OVERLAY*/
html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right):not([data-builder-window]) :is(.brxe-code, .dwc-nest-menu-overlay),
body:has([data-hide-overlay="true"]) .dwc-nest-menu-overlay,
[data-builder-mode] .dwc-nest-menu-overlay {
display: none;
}

.bricks-is-frontend #brx-header .dwc-nest-menu[data-offcanvas="true"]:not([data-submenu-reveal = 'slide']) .brxe-dropdown:not(.open.active) > .brx-dropdown-content > .brxe-dropdown:not([data-submenu-reveal = 'slide'] *){
visibility: hidden;
}

/* builder */

[data-builder-mode] [data-offcanvas="true"] .dwc-nest-menu-top {
min-block-size: 80px !important;
}



/* ===========DESKTOP ONLY ============== */

:is( html:not(.dwc-mobile) .dwc-nest-header:not([data-overlay-header="true"]) [data-mobile-top-transparent="true"]) :is(.dwc-nest-menu-top:not([data-below-header="true"] *, :has(.open.active)), 
.dwc-nav-wrapper:not([data-below-header="true"] *, :has(.open.active))) {
  background-color: transparent !important;
}


html:not(.dwc-mobile):has(:is([data-last-item-is-button-alignment="center"], [data-last-item-is-button-alignment="left"])[data-last-item-is-button="true"]) :is(.dwc-menu-wrap, .dwc-nest-menu){
inline-size: 100%;
}

html:not(.dwc-mobile) [data-last-item-is-button-alignment="center"][data-last-item-is-button="true"].dwc-nest-menu:not(.brx-open) .dwc-nest-nav-items > li:is(:last-of-type, :first-of-type){
margin-inline-start: auto;
}

html:not(.dwc-mobile) [data-last-item-is-button-alignment="left"][data-last-item-is-button="true"].dwc-nest-menu:not(.brx-open) .dwc-nest-nav-items > li:is(:last-of-type) {
margin-inline-start: auto;
}

html:not(.dwc-mobile) .dwc-nest-tooltip {
    display: none !important;
    clip: rect(1px,1px,1px,1px);
    word-wrap: normal!important;
    border: 0;
    clip-path: inset(50%);
    height: 1px !important;
    margin: -1px;
    overflow: hidden;
    overflow-wrap: normal!important;
    padding: 0 !important;
    width: 1px;
}


html:not(.dwc-mobile)  .open:has(.open) .open:has(.brxe-dropdown:hover) .brx-dropdown-content:not(.brx-header-left *, .brx-header-right *, [data-offcanvas="true"] *)  {
box-shadow: 0px 10px 30px -10px rgba(0, 0, 0, 30%);
}

html:not(.dwc-mobile) :is(.brx-header-left, .brx-header-right) .brxe-nav-nested .brxe-dropdown.open>.brx-dropdown-content {
  display: flex;
  min-width: auto;
  opacity: 1;
  overflow-y: auto;
  position: static;
  visibility: visible;
  
}

/* EXTEND DROPDWON BUTTON TO AVOID LOSING FOCUS/CLOSING ON DROPDOWN CONTENT */


html:not(.dwc-mobile) body:not(.brx-header-right, .brx-header-left) .dwc-nest-menu:not([data-offcanvas="true"]) .open .brx-dropdown-content .brxe-dropdown:has( > .brx-sub-submenu-overflow-right):hover::after {
    inset-inline-end: 100%;
    inset-inline-start: auto;
}

html:not(.dwc-mobile) body:not(.brx-header-right, .brx-header-left) .dwc-nest-menu:not([data-offcanvas="true"]) .open  .brx-dropdown-content .brxe-dropdown:not(.brxe-dropdown:has( > .brx-sub-submenu-overflow-right)):hover::after {   
   inset-inline-start: 100%;
}


html:not(.dwc-mobile) body:not(.brx-header-right, .brx-header-left) .dwc-nest-menu:not([data-offcanvas="true"]) .open  .brx-dropdown-content .brxe-dropdown:hover::after {
    content: "";
    position: absolute;
    inset-block-end: 0;
    block-size: 100%;
    inline-size: 100%;
    z-index: -1;
 inset-inline-end: auto;
}


/*DIM DROPDOWN PARENT WHOSE CHILD DROPDOWN CONTENT IS SHOWING  */
html:not(.dwc-mobile) .open:has(.open) >  .brx-dropdown-content:not(.brx-header-left *, .brx-header-right *)::before {
content: "";
position: absolute;
inset: 0;
background-color: var(--dropdown-inactive-overlay);
pointer-events: none;
border-radius: var(--dropdown-content-border-radius);
z-index: 1;
}

html:not(.dwc-mobile) .open:has(.open) >   .brxe-dropdown:not(.open, .brx-header-left *, .brx-header-right *){
    position: static;
}
html:not(.dwc-mobile) .open:has(.open) > .brxe-dropdown:not(.open, .brx-header-left *, .brx-header-right *) > ul{
    opacity: 0;
    transition: 0s
}

html:not(.dwc-mobile) .brxe-dropdown.open:not(.brx-has-megamenu, .brx-header-left *, .brx-header-right *){   
     z-index: 1; 
}

/* LAST BUTTON LEFT PADDDING ON DESKTOP */
html:not(.dwc-mobile) [data-last-item-is-button="true"].dwc-nest-menu .brx-nav-nested-items > .menu-item:last-of-type {
padding-inline-start: var(--menu-item-inline-padding);
}

/* hide toggle with back button appears */
html:not(.dwc-mobile) body:has(.brxe-dropdown.open) [data-offcanvas="true"] .brxe-toggle[aria-label="Open Menu"] {
z-index: 1;
}

/* fades in close button when the main toggle is covered by the back button */
html:not(.dwc-mobile) body:has(.brxe-dropdown.open) [data-offcanvas="true"] .brxe-toggle[aria-label="Close Menu"]:not([data-submenu-reveal="expand"] *){
opacity: 1;
}

html:not(.dwc-mobile) [data-mobile-top-transparent="true"][data-offcanvas="true"]:not([data-show-mobile-logo="true"]) .brxe-toggle[aria-label="Close Menu"] {
opacity: 0;
}

html:not(.dwc-mobile) [data-show-mobile-logo="true"] .dwc-nav-wrapper{
  z-index: 9999
  }

html:not(.dwc-mobile) [data-offcanvas="true"].dwc-nest-menu .brxe-toggle {
display: flex;
}

/* STRIPE STYLE */
html:not(.dwc-mobile) .dwc-stripe-style .brxe-dropdown.brx-has-megamenu .brx-dropdown-content:not([data-offcanvas="true"] .brx-has-megamenu .brx-dropdown-content, .brx-header-left .brx-has-megamenu .brx-dropdown-content, .brx-header-right .brx-has-megamenu .brx-dropdown-content) {
background: transparent !important;
}

html:not(.dwc-mobile) .dwc-stripe-style .brx-has-megamenu > .brx-submenu-toggle:not([data-offcanvas="true"] .brx-submenu-toggle, .brx-header-left .brx-submenu-toggle, .brx-header-right .brx-submenu-toggle),
html:not(.dwc-mobile) .dwc-stripe-style .brx-has-megamenu > .brx-submenu-toggle:not([data-offcanvas="true"] .brx-submenu-toggle, .brx-header-left .brx-submenu-toggle, .brx-header-right .brx-submenu-toggle) > a,
html:not(.dwc-mobile) .dwc-stripe-style .brx-has-megamenu > .brx-submenu-toggle:not([data-offcanvas="true"] .brx-submenu-toggle, .brx-header-left .brx-submenu-toggle, .brx-header-right .brx-submenu-toggle) > button {
cursor: default;
}

/* handles translate and opacity animation for stripe style on desktop */
/*
html:not(.dwc-mobile) .dwc-stripe-style .brx-has-megamenu.open .brx-dropdown-content:not([data-offcanvas="true"] .brx-has-megamenu .brx-dropdown-content, .brx-header-left .brx-has-megamenu .brx-dropdown-content, .brx-header-right .brx-has-megamenu .brx-dropdown-content) > * {
transform: translateX(0);
}

html:not(.dwc-mobile) .dwc-stripe-style .brx-has-megamenu.open .brx-dropdown-content:not([data-offcanvas="true"] .brx-has-megamenu .brx-dropdown-content, .brx-header-left .brx-has-megamenu .brx-dropdown-content, .brx-header-right .brx-has-megamenu .brx-dropdown-content) > * {
transition: transform 0.4s, opacity 0s 0.15s;
opacity: 1;
}

html:not(.dwc-mobile) .dwc-stripe-style .brx-has-megamenu .brx-dropdown-content:not([data-offcanvas="true"] .brx-has-megamenu .brx-dropdown-content, .brx-header-left .brx-has-megamenu .brx-dropdown-content, .brx-header-right .brx-has-megamenu .brx-dropdown-content) > * {
transition: transform 0.4s, opacity 0s;
opacity: 0;
}

html:not(.dwc-mobile) .dwc-stripe-style .brx-has-megamenu.open + .brx-has-megamenu .brx-dropdown-content:not([data-offcanvas="true"] .brx-has-megamenu .brx-dropdown-content, .brx-header-left .brx-has-megamenu .brx-dropdown-content, .brx-header-right .brx-has-megamenu .brx-dropdown-content) > * {
transform: translateX(5%);
}

html:not(.dwc-mobile) .dwc-stripe-style .brx-has-megamenu:has(+ .brx-has-megamenu.open) .brx-dropdown-content:not([data-offcanvas="true"] .brx-has-megamenu .brx-dropdown-content, .brx-header-left .brx-has-megamenu .brx-dropdown-content, .brx-header-right .brx-has-megamenu .brx-dropdown-content) > * {
transform: translateX(-5%);
}
*/

/* handles translate and opacity animation for stripe style on desktop - NEW */
html:not(.dwc-mobile) .dwc-stripe-style .brx-has-megamenu.open .brx-dropdown-content:not([data-offcanvas="true"] .brx-has-megamenu .brx-dropdown-content, .brx-header-left .brx-has-megamenu .brx-dropdown-content, .brx-header-right .brx-has-megamenu .brx-dropdown-content) > * > *{
transform: translateX(0);
}

html:not(.dwc-mobile) .dwc-stripe-style .brx-has-megamenu .brx-dropdown-content:not([data-offcanvas="true"] .brx-has-megamenu .brx-dropdown-content, .brx-header-left .brx-has-megamenu .brx-dropdown-content, .brx-header-right .brx-has-megamenu .brx-dropdown-content) > * > *{
transition: transform 0.4s;
}

html:not(.dwc-mobile) .dwc-stripe-style .brx-has-megamenu.open + .brx-has-megamenu .brx-dropdown-content:not([data-offcanvas="true"] .brx-has-megamenu .brx-dropdown-content, .brx-header-left .brx-has-megamenu .brx-dropdown-content, .brx-header-right .brx-has-megamenu .brx-dropdown-content) > * > *{
transform: translateX(50px);
}

html:not(.dwc-mobile) .dwc-stripe-style .brx-has-megamenu:has(+ .brx-has-megamenu.open) .brx-dropdown-content:not([data-offcanvas="true"] .brx-has-megamenu .brx-dropdown-content, .brx-header-left .brx-has-megamenu .brx-dropdown-content, .brx-header-right .brx-has-megamenu .brx-dropdown-content) > * > *{
transform: translateX(-50px);
}

html:not(.dwc-mobile) .dwc-stripe-style .brx-has-megamenu.open .brx-dropdown-content:not([data-offcanvas="true"] .brx-has-megamenu .brx-dropdown-content, .brx-header-left .brx-has-megamenu .brx-dropdown-content, .brx-header-right .brx-has-megamenu .brx-dropdown-content) > * {   
    overflow-x: hidden;
}


/* mobile logo */
html:not(.dwc-mobile) .dwc-nest-menu__mobile-logo:not([data-offcanvas="true"]:not(.brx-header-left *, .brx-header-right *) .dwc-nest-menu__mobile-logo) {
display: none;
}


/* prevent fouc when offcanvas is enabled and anime height */
body.bricks-is-frontend:has([data-offcanvas="true"])
.dwc-nav-wrapper:not(.sidebar-ready .dwc-nav-wrapper){
display: none;
}

.dwc-mobile [data-hide-close-bar = 'true'] .dwc-nav-wrapper{
inset-block-start: var(--dwc-nest-header-height) 
}

:is(.brx-header-left, .brx-header-right) .dwc-nest-header::before{
display: none;
}

/* mobile menu from top behind header */
.dwc-mobile :is([data-slide-in-direction="top"], [data-slide-in-direction="top left"]):not([data-match-overlay-header-width="true"]) .dwc-nav-wrapper:has(.brxe-dropdown.open.active) {
  z-index: unset !important;
}

.dwc-mobile :is([data-slide-in-direction="top"], [data-slide-in-direction="top left"]) .dwc-nav-wrapper {
z-index: -1;
}

.dwc-mobile .dwc-nest-header__container:has(:is([data-slide-in-direction="top"], [data-slide-in-direction="top left"])) {
  background-color: var(--header-bg)
}

/************************************
MENU HEIGHT/ STRIPE STYLE
************************************/

:is([data-builder-mode], .brx-header-right, .brx-header-left) .dwc-nest-header::after,
body:has([data-offcanvas="true"]) .dwc-nest-header::after {
display: none;
}

.dwc-nest-header:not(:is(.dwc-adaptive-height, .dwc-stripe-style) .dwc-nest-header)::after{
display: none;
}


html:not(.dwc-mobile) .dwc-nest-header::after {
  display: none;
  content: '';
  min-block-size: 0;
  inset-inline-start: 0;
  inline-size: 100%;
  transition-delay: 0.1s !important;
  pointer-events: none;
  transition: inline-size 0.2s,
    block-size 0.2s,
    opacity 0.2s,
    inset-inline-start 0.2s,
    transform 0.2s !important;
  will-change: block-size, inline-size, inset-inline-start, transform, opacity;
  contain: layout paint;
  z-index: -1;
}

html:not(.dwc-mobile) .dwc-nest-header[data-overlay-header="true"][data-overlay-header-optimize-adaptive-height="true"]::after {
  position: fixed;
}

html:not(.dwc-mobile) .dwc-adaptive-height:not(.dwc-stripe-style) .dwc-nest-header[data-overlay-header="true"][data-overlay-header-optimize-adaptive-height="true"]::after {
  inset-block-start: 0;
}

html:not(.dwc-mobile) .dwc-nest-header:not([data-overlay-header="true"][data-overlay-header-optimize-adaptive-height="true"])::after {
  position: absolute;
  inset-block-end: calc(100% - var(--dwc-nest-header-height));
  block-size: 1000px;
  transform: translateY(calc(var(--dropdown-menu-height) * 1.01)) translateZ(0);
}


html:not(.dwc-mobile) .adaptive-height-active:is(.dwc-stripe-style, .dwc-adaptive-height) .dwc-nest-header::after {
  display: block;
}

.dwc-nest-menu .brx-has-megamenu .brx-dropdown-content:not(.show-nav .brx-dropdown-content, [data-builder-mode] .brx-dropdown-content){
  display:none
}

html:not(.dwc-mobile) body:has(.brx-has-megamenu.open) .dwc-nest-header::after {
transition-delay: 0s !important;
}

/* STRIPE STYLE */
html:not(.dwc-mobile) .dwc-stripe-style.bricks-is-frontend .brx-has-megamenu .brx-dropdown-content:not([data-offcanvas="true"] .brx-dropdown-content),
html:not(.dwc-mobile) .dwc-adaptive-height.bricks-is-frontend .brx-has-megamenu .brx-dropdown-content:not([data-offcanvas="true"] .brx-dropdown-content) {
transition-delay: 0s;
box-shadow: none !important;
transition-duration: 0s;
}

html:not(.dwc-mobile) .dwc-stripe-style.bricks-is-frontend .brx-has-megamenu .brx-dropdown-content:not([data-offcanvas="true"] .brx-dropdown-content) {
overflow-x: hidden;
}

html:not(.dwc-mobile) .dwc-stripe-style .open.brx-has-megamenu .brx-dropdown-content:not([data-offcanvas="true"] .brx-dropdown-content),
html:not(.dwc-mobile) .dwc-adaptive-height .open.brx-has-megamenu .brx-dropdown-content:not([data-offcanvas="true"] .brx-dropdown-content) {
transition-delay: 0.1s;
transition-duration: .2s;
}


html:not(.dwc-mobile) .dwc-stripe-style .open.brx-has-megamenu:not([data-offcanvas="true"] .brx-has-megamenu)::before {
    content: '';
    position: absolute;
    inset-block-start: 100%;
    block-size: calc(var(--dwc-nest-header-height)* 0.5);
    inline-size: min(var(--dropdown-menu-width), 40vw);
    transform: translateX(-50%);
    inset-inline-start: 0;
}

html:not(.dwc-mobile) .dwc-stripe-style .brx-nav-nested-items>.brxe-dropdown.brx-has-megamenu>.brx-dropdown-content:not([data-offcanvas="true"] .brx-dropdown-content) {
overflow-x: hidden;
border-radius: var(--stripe-border-radius);
}


html:not(.dwc-mobile) .dwc-nest-header {
position: relative;
}

html:not(.dwc-mobile) .dwc-stripe-style .dwc-nest-header::before {
content: '';
inline-size: calc(max(var(--dropdown-content-gap) + 2.5px, 16px) * 1.1);
block-size: calc(max(var(--dropdown-content-gap) + 2.5px, 16px) * 1.1);
background-color: var(--adaptive-height-bg);
position: absolute;
inset-block-start: 100%;
transition: 0s;
transition-property: inset-inline-start, transform, opacity;
inset-inline-start: var(--navlink-midpoint);
transform: translateX(-50%) rotate(45deg) translateY(calc(50% + 0px));
pointer-events: none;
border-top: var(--adaptive-height-border);
border-left: var(--adaptive-height-border);
z-index: 999;
}

html:not(.dwc-mobile) .dwc-stripe-style .dwc-nest-header:has(.brxe-dropdown.brx-has-megamenu.open:hover)::before {
  transition: 
    opacity 0.2s 0.1s, 
    transform 0.2s 0s,
  inset-inline-start 0.2s 0s;
}

html:not(.dwc-mobile) .dwc-nest-header::before{
opacity: 0 ;
}

html:not(.dwc-mobile) .dwc-nest-header.hide-menu-animation::after {
  opacity: 0 !important;
  }

html:not(.dwc-mobile) .dwc-stripe-style .dwc-nest-header.show-menu-animation:has(.brx-has-megamenu:hover)::before,
html:not(.dwc-mobile) .dwc-nest-header.show-menu-animation::after {
opacity: 1;
}

html:not(.dwc-mobile) .dwc-nest-header.show-menu-animation::after {
  box-shadow: var(--adaptive-height-shadow)
  }


html:not(.dwc-mobile) .dwc-stripe-style .dwc-nest-header::after {
border: var(--adaptive-height-border);
}




html:not(.dwc-mobile) .dwc-stripe-style .dwc-nest-header::after {
inset-inline-start: calc(var(--dropdown-menu-x) - 2.5rem);
inline-size: calc(var(--dropdown-menu-width) + 5rem);
transform: unset;
inset-block-start: calc(var(--dwc-nest-header-height) + max(var(--dropdown-content-gap), 16px));
block-size: var(--dropdown-menu-height);
z-index: 1;
opacity: 0;
}

html:not(.dwc-mobile) .dwc-stripe-style:has(.brx-has-megamenu.open):not(:has([data-optimize-stripe=true])) .dwc-nest-header::after {
block-size: calc(var(--dropdown-menu-height) + 0rem) !important;
opacity: 1;
}

/* hide nav content until js is ready*/
html:not(.dwc-mobile) .dwc-stripe-style .brx-has-megamenu>.brx-dropdown-content:not(.show-nav .brx-dropdown-content, [data-offcanvas="true"] .brx-dropdown-content) {
opacity: 0;
}



body:has(.brx-has-megamenu.open) .sticky .dwc-nest-header::after {
background-color: var(--adaptive-height-bg) !important;
}

body:has(.brx-has-megamenu.open) .brx-sticky .dwc-nest-header::after {
  background-color: var(--adaptive-height-bg) !important;
  }

.dwc-nest-header::after {
background-color: var(--adaptive-height-bg) !important;
opacity: 0;
}

html:not(.dwc-mobile) .dwc-stripe-style:has([data-optimize-stripe=true]) .dwc-nest-header::after {
inset-inline-start: calc(var(--dropdown-menu-x) - 1.5px);
inline-size: calc(var(--dropdown-menu-width) + 2.5px);
/*transform: unset;*/
block-size: calc(var(--dropdown-menu-height) + 3px) !important;
z-index: 1;
border-radius: var(--stripe-border-radius);
transform: translateZ(0);
opacity: 1
}


html:not(.dwc-mobile) .dwc-stripe-style:has([data-optimize-stripe=true]) .dwc-nest-header::after {
border: var(--adaptive-height-border);
}


html:not(.dwc-mobile) :not(.brx-header-left, .brx-header-right).dwc-stripe-style:has([data-optimize-stripe=true]) .brx-nav-nested-items>.brxe-dropdown.brx-has-megamenu>.brx-dropdown-content:not([data-offcanvas="true"] .brx-dropdown-content) {
transform: translateY(16px) !important; 
inset-block-start: 100%;
}


.dwc-nest-header:not(.show-nav .dwc-nest-header)::after {
display: none;
}

/* STRIP FIX FOR DYNAMIC NAV  */
html:not(.dwc-mobile) 
:not(.brx-header-left, .brx-header-right).dwc-stripe-style:has([data-optimize-stripe=true]) 
.brx-nav-nested-items> li > .brxe-dropdown.brx-has-megamenu>.brx-dropdown-content:not([data-offcanvas="true"] .brx-dropdown-content) {
    transform: translateY(max(calc(var(--dropdown-content-gap) + 2.5px), 17px)) !important;
    inset-block-start: 100%;   
}


html:not(.dwc-mobile) .dwc-stripe-style .show-menu-animation .dwc-nest-header:has(.brx-has-megamenu:hover)::before, 
html:not(.dwc-mobile) .show-menu-animation::after {
    opacity: 1;
}

html:not(.dwc-mobile) .hide-menu-animation .dwc-nest-header::after {
    opacity: 0 !important;
}

html:not(.dwc-mobile) .dwc-stripe-style:has([data-optimize-stripe=true]) .dwc-nest-header::after {
     block-size: calc(var(--dropdown-menu-height) + 6px) !important; 
}


/****************
MENU OVERLAY
***************/

.dwc-nest-menu-overlay {
position: fixed;
inline-size: 100%;
block-size: 100%;
inset-inline-start: 0;
inset-block-end: 0;
background: var(--nav-overlay-backdrop-clr) !important;
z-index: 2;   
opacity: 0;
transition: 0.4s;
backdrop-filter: blur(var(--nav-overlay-backdrop-blur));
}

html:not(.dwc-mobile) .dwc-nest-header:has(.dwc-nest-menu-overlay) .brxe-nav-nested{
    z-index: 3
}

[data-overlay-header=true].dwc-nest-header .dwc-nest-menu-overlay{
    display: none;
} 

body:not(:has([data-overlay-header-optimize-adaptive-height="true"][data-overlay-header="true"])) .dwc-nest-menu-overlay  {
  inset-block-start: var(--dwc-nest-header-height);
}

.logged-in:not(:has([data-overlay-header-optimize-adaptive-height="true"][data-overlay-header="true"])) .dwc-nest-menu-overlay:not(:has(+ .x-header)) {
  inset-block-start: calc(var(--dwc-nest-header-height) + var(--wp-admin--admin-bar--height, 0px));
  }

body:has([data-overlay-header-optimize-adaptive-height="true"][data-overlay-header="true"], [data-overlay-on-header="true"]) .dwc-nest-menu-overlay  {
  inset-block-start: 0 !important;
}








.dwc-nest-menu-overlay {
pointer-events: none;
}

.no-scroll .dwc-nest-menu-overlay {
opacity: 1;  
}

:is(.brx-header-right, .brx-header-left) .dwc-nest-header__container {
padding-inline: 0
}



/*fade in back button*/
@-webkit-keyframes dwc-nest-fade-in {
0% {
  opacity: 0;
}
100% {
  opacity: 1;
}
}
@keyframes slide-in-right {
0% {
  opacity: 0;
}
100% {   
  opacity: 1;
}
}

/* configurable menu and submenu slide out speed */
.dwc-mobile .bricks-is-frontend [data-submenu-reveal="slide"].dwc-nest-menu :is(.brx-dropdown-content, .dwc-nav-wrapper),
.bricks-is-frontend :is([data-submenu-reveal="slide"][data-offcanvas="true"]).dwc-nest-menu :is(.brx-dropdown-content, .dwc-nav-wrapper),
:is(.bricks-is-frontend.brx-header-right, .bricks-is-frontend.brx-header-left) :is([data-submenu-reveal="slide"]).dwc-nest-menu :is(.brx-dropdown-content, .dwc-nav-wrapper){
transition-duration: calc(0.5s / var(--slide-out-speed)) !important;    
}

#brx-header{
--content-gap: 0;
--at-container-gap: 0;
}


/* overlay header */
html:not(.dwc-mobile) .bricks-is-frontend 
#brx-header:has([data-overlay-header = "true"]) {
padding: var(--overlay-header-inset);  
}

html:not(.dwc-mobile) .bricks-is-frontend 
#brx-header:has([data-overlay-header = "true"]):not(.sticky, .brx-sticky) {
position: absolute;
inset-block-start: 0;
inset-inline: 0; 
}

html:not(.dwc-mobile) .bricks-is-frontend #brx-header > 
.dwc-nest-header[data-overlay-header = "true"]{
border-radius: var(--overlay-header-radius);
background-color: var(--overlay-header-bg);
box-shadow: var(--overlay-header-shadow);
max-inline-size: var(--overlay-header-width);
}


html:not(.dwc-mobile) .bricks-is-frontend #brx-header > 
.dwc-nest-header[data-overlay-header = "true"]:not(:has([data-offcanvas="true"])){
backdrop-filter: blur(var(--overlay-header-blur));
}


html:not(.dwc-mobile) .bricks-is-frontend #brx-header:has(.open) > 
.dwc-nest-header[data-overlay-header = "true"]{
background-color: var(--overlay-header-bg-active) !important;
}

/* overlay on mobile */
.dwc-mobile .bricks-is-frontend 
#brx-header:has([data-overlay-header-mobile = "true"]) {
padding: var(--overlay-header-inset);  
}

.dwc-mobile .bricks-is-frontend 
#brx-header:has([data-overlay-header-mobile = "true"]):not(.sticky, .brx-sticky) {
position: absolute;
inset-block-start: 0;
inset-inline: 0; 
}

.dwc-mobile .bricks-is-frontend #brx-header > 
.dwc-nest-header[data-overlay-header-mobile = "true"]{
border-radius: var(--overlay-header-radius);
background-color: var(--overlay-header-bg);
box-shadow: var(--overlay-header-shadow);
max-inline-size: var(--overlay-header-width);
}

/*offset hero top padding when overlay header is active */
#brx-header:has([data-offset-section-padding="true"]) + main > :is(section, div) {
  padding-block-start: var(--overlay-offset-padding);
}

/* menu height anime on overlay header  */

html:not(.dwc-mobile) .bricks-is-frontend.dwc-adaptive-height:not(.dwc-stripe-style) #brx-header:has([data-overlay-header = "true"]) .dwc-nest-header::after {
border-radius: min(var(--overlay-header-radius), 2em);
inset-block-end: calc(100% + var(--overlay-header-inset));
opacity: 1;    
}

html:not(.dwc-mobile) .bricks-is-frontend:is(.dwc-adaptive-height):not(.dwc-stripe-style)
#brx-header:has([data-overlay-header = "true"]:not([data-overlay-header-optimize-adaptive-height="true"])) 
.dwc-nest-header.show-menu-animation::after {
    transform: translateY( calc((var(--dropdown-menu-height) + (var(--dwc-nest-header-height) * 1.5)))) translateZ(0)
}

html:not(.dwc-mobile) .bricks-is-frontend:is(.dwc-adaptive-height):not(.dwc-stripe-style) #brx-header:has([data-overlay-header="true"][data-overlay-header-optimize-adaptive-height="true"]) .dwc-nest-header.show-menu-animation::after {
  block-size: calc((var(--dropdown-menu-height) + (var(--dwc-nest-header-height) * 1.5)));
}

/* we need to reposition the overlay outside the header */
html:not(.dwc-mobile) .bricks-is-frontend:has( .dwc-nest-menu .open):not(:has([data-offcanvas="true"])) .dwc-nest-menu-overlay{
  opacity: 1;
 }

/*menu items border radius desktop only*/
html:not(.dwc-mobile) .dwc-nest-menu .brx-nav-nested-items > li > 
:is(a:not([data-last-item-is-button="true"] .brx-nav-nested-items > .menu-item:last-of-type a, [data-last-item-is-button="true-2"] .brx-nav-nested-items > .menu-item:nth-last-of-type(-n+2) a, [data-last-item-is-button="true-3"] .brx-nav-nested-items > .menu-item:nth-last-of-type(-n+3) a, .dwc-nest-menu__logo ), .brx-submenu-toggle){
border-radius: var(--menu-item-radius);
}

html:not(.dwc-mobile) .dwc-nest-menu .brx-nav-nested-items {
  gap: var(--menu-items-gap);
}

/* dynamic dropdown conten width and position */

html:not(.dwc-mobile) :is(:not(.brx-header-left, .brx-header-right)).bricks-is-frontend .dwc-nest-menu:not([data-offcanvas="true"]) .brx-has-megamenu .brx-dropdown-content:not([data-use-selector="true"]) {
  min-inline-size: var(--dropdown-content-width, var(--dropdown-content-default-width)) !important;
  inset-inline-start: var(--left-position)!important;
}

html:not(.dwc-mobile) :is(:not(.brx-header-left, .brx-header-right)).bricks-is-frontend .dwc-nest-menu:not([data-offcanvas="true"]) .brx-dropdown-content {
  border-radius: var(--dropdown-content-border-radius);
}

.dwc-nest-header{
  position: relative;
  z-index: 9999;
  
}

/* optimize multi row header*/
.dwc-mobile .dwc-nest-header[data-fullscreen-mobile-menu="true"]{
  --dwc-nest-header-height:var(--fullscreen-mobile-menu-top-height) !important
}

.dwc-mobile .dwc-nest-header[data-fullscreen-mobile-menu="true"] .dwc-nest-menu-top:not([data-below-header="true"] *) {
    background-color: var(--mobile-menu-topbar-bg) !important;
   align-items: center !important;
  animation: none !important;
}

.dwc-mobile .dwc-nest-header[data-fullscreen-mobile-menu="true"] .dwc-nav-wrapper{
  z-index: 99999
}

.dwc-mobile .dwc-nest-header[data-fullscreen-mobile-menu="true"] .dwc-nest-menu-top .brxe-toggle {
    display: block;
}


.dwc-mobile .dwc-nest-header[data-fullscreen-mobile-menu="true"]:not([data-hide-mobile-logo="true"]) .dwc-nest-menu__mobile-logo {
    display: flex;
}

/* overlay header on multirow*/
html:not(.dwc-mobile) .dwc-nest-header[data-fullscreen-mobile-menu="true"][data-overlay-header="true"] > div:first-child{
    border-top-left-radius: var(--overlay-header-radius);
   border-top-right-radius: var(--overlay-header-radius);
}

/* BricksExtras support*/

html:not(.dwc-mobile) #brx-header .brxe-xheaderrow:has(.dwc-nest-header){
    position: relative;
    z-index:1;
}

html:not(.dwc-mobile) #brx-header .brxe-xheaderrow:first-child{
    position: relative;
    z-index: 99991;
}




[data-x-overlay]:not([data-x-overlay="none"]) .dwc-nest-header{
background: var(--x-overlay-header-background)!important;
 }

html:not(.dwc-mobile) .brxe-xheaderrow .dwc-nest-header::after {
  block-size: 1000px;
}



/* in builder */
[data-builder-mode] [data-offcanvas="true"] .dwc-nest-toggle--open{
display: none !important;
}

[data-builder-mode] [data-offcanvas="true"] .dwc-nest-menu-top{
  display: none;
}


:is(.brx-header-left, .brx-header-right) [data-builder-mode] .brx-nav-nested-items,
[data-builder-mode] .brx-open.dwc-nest-menu[data-offcanvas="true"] .brx-nav-nested-items {
  overflow-y: auto;
  scrollbar-width: thin !important;
  justify-content: flex-start !important;
box-shadow: var(--sidebar-shadow);
}


:is(.brx-header-left, .brx-header-right) [data-builder-mode] .dwc-nav-wrapper,
[data-builder-mode] [data-offcanvas="true"] .dwc-nav-wrapper {
  inset-inline-end: auto ;
  inset-inline-start: 0;
}

/* preview dropdown content width in builder*/

[data-builder-mode]:not(.brx-header-left, .brx-header-right) .dwc-nest-menu:not(.brx-open) .brx-has-megamenu .brx-dropdown-content:not([data-offcanvas="true"] .brx-dropdown-content, .brx-open .brx-dropdown-content){
  min-inline-size:var(--dropdown-content-width, var(--dropdown-content-default-width)) !important;  
  transform: translatex(50px);
  border: dotted #00b0f4 2px
}

[data-builder-mode]:not(.brx-header-left, .brx-header-right) .dwc-nest-menu .brx-has-megamenu .brx-dropdown-content:not([data-offcanvas="true"] .brx-dropdown-content, .brx-open .brx-dropdown-content):not([data-hide-instruction="true"])::after{
    content: 'Set dropdown Content width value in dropdown Content ATTRIBUTES > data-content-width, do not add a unit e.g. px. Leave empty to use global content width, set in Nav Nestable ATTRIBUTES > data-global-content-width. | Set alignment in ATTRIBUTES > data-content-align, values: left, right, center. This aligns the dropdown content to the dropdown button, leave empty to align center to the header. aligments are applied on frontend only. | TIP: click here to select dropdown Content';
    position: absolute;
    inset-block-start: 102%;
    color: #e1e1e1;
    font-size: 12px;    
    letter-spacing: 0.5px;
    line-height: 1.5;
    background: #2b2b2b;
    min-block-size: fit-content;
    padding: 1em;
}

/*set alignment for sidebar edit on desktop*/
:is(.brx-header-left, .brx-header-right)[data-builder-mode] .dwc-nest-menu.brxe-nav-nested .brx-nav-nested-items,
[data-builder-mode] .dwc-nest-menu.brxe-nav-nested[data-offcanvas="true"] .brx-nav-nested-items {
    justify-content: flex-start !important;
}

[data-builder-mode]:is(.brx-header-left, .brx-header-right)::before {
    content: 'To view sidebar, go to the MENU Styles/Options code block CSS, scroll to the end, and replace all the postid-xxxx in the CSS rules with this template post id';   
}


:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header .dwc-nest-menu:not(.brx-open)::after {
    content: 'To edit Sidebar, select the Nav (Nestable), go to the CONTENT tab > MOBILE MENU, enable "Keep open while styling" | TIP: click here to select Nav (Nestable)';
    position: absolute;    
    padding-inline-start: 20px;
    color: #e1e1e1;
    font-size: 12px;    
    line-height: 1.5;
    background: #2b2b2b;
    min-block-size: fit-content;
    padding: 1em;
    inline-size: 250px;
}

.brx-header-left[data-builder-window] #brx-header .dwc-nest-menu:not(.brx-open)::after {
  inset-inline-start: 100%;
}

.brx-header-right[data-builder-window] #brx-header .dwc-nest-menu:not(.brx-open)::after {
  inset-inline-end: 100%;
}

[data-builder-window] #brx-header .dwc-nest-menu[data-offcanvas="true"]:not(.brx-open)::after{
     content: 'To edit in Offcanvas mode, select the Nav (Nestable), go to the CONTENT tab > MOBILE MENU, enable "Keep open while styling" | TIP: click here to select Nav (Nestable)';
    position: absolute;
    inset-block-start: 100%;
    padding-block-start: 20px;
    color: #e1e1e1;
    font-size: 12px;    
    line-height: 1.5;
    background: #2b2b2b;
    min-block-size: fit-content;
    padding: 1em;
    inline-size: 250px;
}

@media (max-width: 1200px){
  [data-builder-window] #brx-header .dwc-nest-menu[data-offcanvas="true"]:not(.brx-open)::after{
     content: 'To edit in Offcanvas mode, select the Nav (Nestable), go to the CONTENT tab > MOBILE MENU, enable "Keep open while styling" ';
    position: absolute;
    inset-inline-start: var(--mobile-menu-width);
    padding-inline-start: 20px;
  }
}

[data-builder-mode] [data-offcanvas="true"]:not(.brx-open) .dwc-nav-wrapper {
    transform: translateX(0);
    visibility: visible;
}

[data-builder-window] [data-last-item-is-button="true"][data-offcanvas="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]  .brxe-nav-nested .brxe-dropdown .brx-dropdown-content:not(.brx-open .brx-dropdown-content) {
    display: none;
}


:is(.brx-header-left, .brx-header-right)[data-builder-window] #brx-header .dwc-nest-menu.brxe-nav-nested .brx-nav-nested-items {   
    scrollbar-width: none;
}


/* stripe style fix*/
html:not(.dwc-mobile) .dwc-stripe-style:not(.brx-header-left, .brx-header-right) .dwc-nest-header__container:not(:has([data-offcanvas="true"])) {
    align-items: stretch !important;
  }
  
  html:not(.dwc-mobile) .dwc-stripe-style:not(.brx-header-left, .brx-header-right) .dwc-nest-menu:not([data-offcanvas="true"]) .dwc-nav-wrapper,
  html:not(.dwc-mobile) .dwc-stripe-style:not(.brx-header-left, .brx-header-right) .dwc-nest-menu:not([data-offcanvas="true"]) .brx-nav-nested-items,
  html:not(.dwc-mobile) .dwc-stripe-style:not(.brx-header-left, .brx-header-right) .dwc-nest-menu:not([data-offcanvas="true"]) .brx-nav-nested-items > .brxe-dropdown,
  html:not(.dwc-mobile) .dwc-stripe-style:not(.brx-header-left, .brx-header-right) .dwc-nest-menu:not([data-offcanvas="true"]) .brx-nav-nested-items > .brxe-dropdown > .brx-submenu-toggle,
  html:not(.dwc-mobile) .dwc-stripe-style:not(.brx-header-left, .brx-header-right) .dwc-nest-menu:not([data-offcanvas="true"]) .brx-nav-nested-items > li > 
  a:not([data-last-item-is-button="true"] .menu-item:last-of-type a, [data-last-item-is-button="true-2"] .menu-item:nth-last-of-type(-n+2) a, [data-last-item-is-button="true-3"] .menu-item:nth-last-of-type(-n+3) a, .dwc-nest-menu__logo)
  /* a:not(:is([data-last-item-is-button="true"], [data-last-item-is-button="true-2"], [data-last-item-is-button="true-3"]).dwc-nest-menu .brx-nav-nested-items>:is(.menu-item:last-of-type, .menu-item:nth-last-of-type(-n+2), .menu-item:nth-last-of-type(-n+3)) a) */ { 
    height: 100%;
  }
  
  html:not(.dwc-mobile) .dwc-stripe-style:not(.brx-header-left, .brx-header-right) .dwc-nest-menu:not([data-offcanvas="true"]) .brx-nav-nested-items > li.menu-item {
    height: 100%;
    display: flex;
    align-items: center;
  }



/*fix overlay in boxed mode*/
.brx-boxed .dwc-nest-menu-overlay {
    inline-size: var(--boxed-width, 100%);
}

/*wait for stripe style to load before active */
body:is(.dwc-stripe-style, .dwc-adaptive-height):not(.adaptive-height-active, .brx-header-right, .brx-header-left) .dwc-nest-menu:not([data-offcanvas="true"]) .brx-has-megamenu{
  pointer-events: none;
}


/* LAST CTA BUTTONS */
/* Button styling for FRIST BUTTON*/
:is([data-last-item-is-button="true"], [data-last-item-is-button="true-2"], [data-last-item-is-button="true-3"]).dwc-nest-menu .brx-nav-nested-items > .menu-item:last-of-type a {
    color: var(--menu-cta-clr);
    background-color: var(--menu-cta-bg);
    border-radius: var(--menu-cta-radius) !important;
    padding-inline: var(--menu-cta-inline-padding) !important;
    padding-block: var(--menu-cta-block-padding) !important;
    border: var(--menu-cta-border);
}

:is([data-last-item-is-button="true"], [data-last-item-is-button="true-2"], [data-last-item-is-button="true-3"]).dwc-nest-menu .brx-nav-nested-items > .menu-item:nth-last-of-type(1) a:hover {
    color: var(--menu-cta-hover-clr);
    background-color: var(--menu-cta-hover-bg);
}

/* Button styling for second button*/
:is([data-last-item-is-button="true-2"], [data-last-item-is-button="true-3"]).dwc-nest-menu .brx-nav-nested-items > .menu-item:nth-last-of-type(2) a {
    color: var(--menu-cta-2-clr);
    background-color: var(--menu-cta-2-bg);
    border-radius: var(--menu-cta-2-radius) !important;
    padding-inline: var(--menu-cta-2-inline-padding) !important;
    padding-block: var(--menu-cta-2-block-padding) !important;
    border: var(--menu-cta-2-border);
}

:is([data-last-item-is-button="true-2"], [data-last-item-is-button="true-3"]).dwc-nest-menu .brx-nav-nested-items > .menu-item:nth-last-of-type(2) a:hover {
    color: var(--menu-cta-2-hover-clr);
    background-color: var(--menu-cta-2-hover-bg);
}

/* Button styling for third button */
[data-last-item-is-button="true-3"].dwc-nest-menu .brx-nav-nested-items > .menu-item:nth-last-of-type(3) a {
    color: var(--menu-cta-3-clr);
    background-color: var(--menu-cta-3-bg);
    border-radius: var(--menu-cta-3-radius) !important;
    padding-inline: var(--menu-cta-3-inline-padding) !important;
    padding-block: var(--menu-cta-3-block-padding) !important;
    border: var(--menu-cta-3-border);
}

[data-last-item-is-button="true-3"].dwc-nest-menu .brx-nav-nested-items > .menu-item:nth-last-of-type(3) a:hover {
    color: var(--menu-cta-3-hover-clr);
    background-color: var(--menu-cta-3-hover-bg);
}

/* Adjust padding for all variants in desktop mode */
html:not(.dwc-mobile) [data-last-item-is-button="true"].dwc-nest-menu .brx-nav-nested-items > .menu-item:last-of-type,
html:not(.dwc-mobile) [data-last-item-is-button="true-2"].dwc-nest-menu .brx-nav-nested-items > .menu-item:nth-last-of-type(-n+2),
html:not(.dwc-mobile) [data-last-item-is-button="true-3"].dwc-nest-menu .brx-nav-nested-items > .menu-item:nth-last-of-type(-n+3) {
    padding-inline-start: var(--menu-item-inline-padding);
}

/* Center alignment for single button case */
html:not(.dwc-mobile) [data-last-item-is-button-alignment="center"][data-last-item-is-button="true"].dwc-nest-menu:not(.brx-open) .dwc-nest-nav-items > li:is(:last-of-type, :first-of-type) {
    margin-inline-start: auto;
}

/* Center alignment for two buttons case */
html:not(.dwc-mobile) [data-last-item-is-button-alignment="center"][data-last-item-is-button="true-2"].dwc-nest-menu:not(.brx-open) .dwc-nest-nav-items > li:is(:nth-last-of-type(2), :first-of-type) {
    margin-inline-start: auto;
}

/* Center alignment for three buttons case */
html:not(.dwc-mobile) [data-last-item-is-button-alignment="center"][data-last-item-is-button="true-3"].dwc-nest-menu:not(.brx-open) .dwc-nest-nav-items > li:is(:nth-last-of-type(3), :first-of-type) {
    margin-inline-start: auto;
}

/* Left alignment for single button case */
html:not(.dwc-mobile) [data-last-item-is-button-alignment="left"][data-last-item-is-button="true"].dwc-nest-menu:not(.brx-open) .dwc-nest-nav-items > li:last-of-type {
    margin-inline-start: auto;
}

/* Left alignment for two buttons case */
html:not(.dwc-mobile) [data-last-item-is-button-alignment="left"][data-last-item-is-button="true-2"].dwc-nest-menu:not(.brx-open) .dwc-nest-nav-items > li:nth-last-of-type(2) {
    margin-inline-start: auto;
}

/* Left alignment for three buttons case */
html:not(.dwc-mobile) [data-last-item-is-button-alignment="left"][data-last-item-is-button="true-3"].dwc-nest-menu:not(.brx-open) .dwc-nest-nav-items > li:nth-last-of-type(3) {
    margin-inline-start: auto;
}

/* General width rule for all button cases and alignments */
html:not(.dwc-mobile):has(:is([data-last-item-is-button-alignment="center"], [data-last-item-is-button-alignment="left"]):is([data-last-item-is-button="true"], [data-last-item-is-button="true-2"], [data-last-item-is-button="true-3"])) :is(.dwc-menu-wrap, .dwc-nest-menu) {
    inline-size: 100%;
}



/* align dropdown content to bottom */
html:not(.dwc-mobile) .bricks-is-frontend:not(.brx-header-left, .brx-header-right) .dwc-nest-header__container:has([data-align-content-bottom="true"]):not(:has([data-offcanvas="true"])) {
  align-items: stretch !important;
}

html:not(.dwc-mobile) .bricks-is-frontend:not(.brx-header-left, .brx-header-right) .dwc-nest-menu[data-align-content-bottom="true"]:not([data-offcanvas="true"]) .dwc-nav-wrapper,
html:not(.dwc-mobile) .bricks-is-frontend:not(.brx-header-left, .brx-header-right) .dwc-nest-menu[data-align-content-bottom="true"]:not([data-offcanvas="true"]) .brx-nav-nested-items,
html:not(.dwc-mobile) .bricks-is-frontend:not(.brx-header-left, .brx-header-right) .dwc-nest-menu[data-align-content-bottom="true"]:not([data-offcanvas="true"]) .brx-nav-nested-items > .brxe-dropdown,
html:not(.dwc-mobile) .bricks-is-frontend:not(.brx-header-left, .brx-header-right) .dwc-nest-menu[data-align-content-bottom="true"]:not([data-offcanvas="true"]) .brx-nav-nested-items > .brxe-dropdown > .brx-submenu-toggle,
html:not(.dwc-mobile) .bricks-is-frontend:not(.brx-header-left, .brx-header-right) .dwc-nest-menu[data-align-content-bottom="true"]:not([data-offcanvas="true"]) .brx-nav-nested-items > li > 
a:not([data-last-item-is-button="true"] .menu-item:last-of-type a, [data-last-item-is-button="true-2"] .menu-item:nth-last-of-type(-n+2) a, [data-last-item-is-button="true-3"] .menu-item:nth-last-of-type(-n+3) a, .dwc-nest-menu__logo)
/* a:not(:is([data-last-item-is-button="true"], [data-last-item-is-button="true-2"], [data-last-item-is-button="true-3"]).dwc-nest-menu .brx-nav-nested-items>:is(.menu-item:last-of-type, .menu-item:nth-last-of-type(-n+2), .menu-item:nth-last-of-type(-n+3)) a, .dwc-nest-menu__logo)*/ { 
  height: 100%;
}

html:not(.dwc-mobile) .bricks-is-frontend:not(.brx-header-left, .brx-header-right) .dwc-nest-menu[data-align-content-bottom="true"]:not([data-offcanvas="true"]) .brx-nav-nested-items > li.menu-item {
  height: 100%;
  display: flex;
  align-items: center;
}

/* dropdown content gap */
html:not(.dwc-mobile) body:not(.brx-header-left, .brx-header-right) .dwc-nest-menu:not([data-offcanvas="true"]) .brxe-dropdown.open > .brx-dropdown-content:not(.brx-dropdown-content .brx-dropdown-content) {
 transform: translateY(calc(var(--caret-size) - var(--dropdown-content-border-size))) scaleX(1) scaleY(1);
}

html:not(.dwc-mobile) body:not(.brx-header-left, .brx-header-right) .dwc-nest-menu:not([data-offcanvas="true"]) .brxe-dropdown.open > .brx-dropdown-content .brx-dropdown-content{
  transform: translateY(0) scaleX(1) scaleY(1);
}

html:not(.dwc-mobile) .brx-dropdown-content:not(.open .brx-dropdown-content){
    --dropdown-content-border: solid transparent var(--dropdown-content-border-size);
}



html:not(.dwc-mobile) body:not(.brx-header-right, .brx-header-left) .dwc-nest-menu[data-align-content-bottom="true"][data-caret="true"]:not([data-offcanvas="true"]) .brx-nav-nested-items > .brxe-dropdown.open:not(.dwc-stripe-style .brx-has-megamenu)::after {
    inline-size: calc((var(--dropdown-content-gap) * 1.414) - var(--dropdown-content-border-size));
    aspect-ratio: 1;
    opacity: 1;
    transition: opacity 0.2s 0.1s;
}

html:not(.dwc-mobile) body:not(.brx-header-right, .brx-header-left) .dwc-nest-menu[data-align-content-bottom="true"][data-caret="true"]:not([data-offcanvas="true"]) .brx-nav-nested-items > .brxe-dropdown:not(.dwc-stripe-style .brx-has-megamenu)::after {
    content: '';
    position: absolute;
    background-color: var(--dropdown-content-bg);
    transform: rotate(45deg);
    inset-block-end: calc((-1 * var(--dropdown-content-gap) - (var(--dropdown-content-gap) * 1.414 / 2.2)) + var(--dropdown-content-border-size));
    inset-inline-start: calc(50% - var(
  --dropdown-content-gap));
    opacity: 0;
}


html:not(.dwc-mobile) body:not(.brx-header-right, .brx-header-left) .dwc-nest-menu:not([data-offcanvas="true"]) .brx-nav-nested-items > .brxe-dropdown:not(.dwc-stripe-style .brx-has-megamenu)::after { 
  border-top: var(--dropdown-content-border);
  border-left: var(--dropdown-content-border);
  z-index: 9999;
  inset-block-end: calc(var(--dropdown-content-gap) * -1.55);

}

html:not(.dwc-mobile) body:not(.brx-header-left, .brx-header-right) .dwc-nest-menu:not([data-offcanvas="true"]) .brx-nav-nested-items > .brxe-dropdown:not(.dwc-stripe-style .brx-has-megamenu)  .brx-dropdown-content{
 outline: var(--dropdown-content-border);
} 




/* === ends == */

body:not(.adaptive-height-active) .brxe-dropdown::after{
display: none;
}

/* multi-level dropdwon arrow > */

html:not(.dwc-mobile) body:not(.brx-header-left, .brx-header-right) 
.dwc-nest-menu:not([data-offcanvas="true"])
.brxe-dropdown:not(.brx-has-megamenu) .brxe-dropdown .brx-submenu-toggle button 
svg {
  transform: rotate(270deg);
}


/* align dropwdown in builder */

[data-builder-mode]:not(.brx-header-left, .brx-header-right) .brx-has-megamenu .brx-dropdown-content[data-content-align="left"][preview-alignment="true"]{
left: 0 !important;
right: auto !important;
}

[data-builder-mode]:not(.brx-header-left, .brx-header-right) .brx-has-megamenu .brx-dropdown-content[data-content-align="right"][preview-alignment="true"]{
left: auto !important;
right: 0 !important; 
}

[data-builder-mode]:not(.brx-header-left, .brx-header-right) .dwc-nest-menu:not(.brx-open) .brx-has-megamenu .brx-dropdown-content[data-content-align="center"][preview-alignment="true"]{
left: 50% !important;
transform: translatex(-50%) !important;
}


/* BREAKOUT ITEM */
.dwc-nest-menu > [data-breakout-link]:not(.dwc-nest-menu__logo){
      color: var(--menu-cta-clr);
    background-color: var(--menu-cta-bg);
    border-radius: var(--menu-cta-radius) !important;
    padding-inline: var(--menu-cta-inline-padding) !important;
    padding-block: var(--menu-cta-block-padding) !important;
    border: var(--menu-cta-border);   
}

.dwc-nest-menu > [data-breakout-link="before"],
.dwc-nest-menu > [data-breakout-link]:not([data-breakout-link="after"], .dwc-nest-menu__logo){   
  margin-inline-end: var(--cta-breakout-gap);
  margin-inline-start: auto;
}

.dwc-nest-menu > [data-breakout-link="after"]{   
  margin-inline-start: var(--cta-breakout-gap);
  order: 1;
}

.dwc-menu-wrap:has(.dwc-nest-menu__logo[data-breakout-link]),
.brxe-nav-nested:has(.dwc-nest-menu__logo[data-breakout-link]){
inline-size: 100% !important;
}

.dwc-stripe-style .dwc-menu-wrap:has(.dwc-nest-menu__logo[data-breakout-link]), 
.dwc-stripe-style .brxe-nav-nested:has(.dwc-nest-menu__logo[data-breakout-link]) {   
    min-height: var(--header-min-height);
}

.dwc-nest-header__container:has(.brx-nav-nested-items .dwc-nest-menu__logo[data-breakout-link]) { 
  flex-direction: column !important;
  justify-content: center !important;
}


.dwc-nest-menu > [data-breakout-link="after"] + .brxe-toggle[aria-label="Open Menu"]{
    margin-inline-start: auto;
}


/* BREAKIN ITEM */

.dwc-mobile .dwc-nav-wrapper:has([data-breakin]) {
background: linear-gradient(to top, var(--mobile-menu-bg) 0%, var(--mobile-menu-bg) calc(100% - var(--dwc-nest-header-height)), transparent calc(100% - var(--dwc-nest-header-height)), transparent 100%);

}


.dwc-mobile .dwc-nav-wrapper:has([data-breakin]) .breakin-container{
   inline-size: 100%;
}

.dwc-mobile .dwc-nav-wrapper:has([data-breakin="end"]) .breakin-container{
   margin-block-start: auto;
}

html:not(.dwc-mobile) .breakin-container{
display: none;
}



/* ==== DYNAMIC NAV CUSTOM CSS ==== */

[data-builder-mode] .dwc-nest-menu .brx-nav-nested-items > a:not(.dwc-nest-menu__logo){
    font-weight: var(--menu-item-font-weight);
    font-size: var(--menu-item-font-size);
    color: var(--menu-item-clr);
    background-color: var(--menu-item-bg);
    padding-block: var(--menu-item-block-padding);
    padding-inline: var(--menu-item-inline-padding) !important;
  
}


[data-builder-mode] .dwc-nest-menu .brx-dropdown-content > a:not(.brx-has-megamenu a) {
    background-color: var(--dropdown-item-bg);
        padding-block: var(--dropdown-item-block-padding);
    padding-inline: var(--dropdown-item-inline-padding) !important;
        font-weight: var(--menu-item-font-weight);
    font-size: var(--menu-item-font-size);
    color: var(--menu-item-clr);   
    inline-size: 100%;
}

[data-builder-mode] .dwc-nest-menu .brx-dropdown-content > a:hover:not(.brx-has-megamenu a) {
    background-color: var(--dropdown-item-hover-bg);
    color: var(--dropdown-item-hover-clr);
}


body:not([data-builder-mode]) .dwc-nest-menu .brx-nav-nested-items > li:empty{
    visibility: hidden;
}


.dwc-nest-menu .brx-nav-nested-items > * > .brxe-dropdown:not(.brx-has-megamenu) li .brx-submenu-toggle {
    padding-block: var(--dropdown-item-block-padding);
    padding-inline: var(--dropdown-item-inline-padding) !important;
}

/* ==== END DYNAMIC NAV CUSTOM CSS ==== */



/* CARET FIX FOR DYNAMIC MENU STRUCTURE*/


.dwc-nest-menu .brx-nav-nested-items > 
li> .brx-has-megamenu.open > .brx-dropdown-content {
    opacity: 1;
    visibility: visible;
}

html:not(.dwc-mobile) 
body:not(.brx-header-right, .brx-header-left) .dwc-nest-menu[data-align-content-bottom="true"][data-caret="true"]:not([data-offcanvas="true"]) 
.brx-nav-nested-items > li:has(.brx-has-megamenu.open):not(.dwc-stripe-style .brx-nav-nested-items > li)::after {
    inline-size: calc((var(--dropdown-content-gap) * 1.414) - var(--dropdown-content-border-size));
    aspect-ratio: 1;
    opacity: 1;
    transition: opacity 0.2s 0.1s;
}

html:not(.dwc-mobile) 
body:not(.brx-header-right, .brx-header-left) .dwc-nest-menu[data-align-content-bottom="true"][data-caret="true"]:not([data-offcanvas="true"]) 
.brx-nav-nested-items > li:has(.brx-has-megamenu):not(.dwc-stripe-style .brx-nav-nested-items > li)::after {
      content: '';
    position: absolute;
    background-color: var(--dropdown-content-bg);
    transform: rotate(45deg);
    inset-block-end: calc((-1 * var(--dropdown-content-gap) - (var(--dropdown-content-gap) * 1.414 / 2.2)) + var(--dropdown-content-border-size));
    inset-inline-start: calc(50% - var(
  --dropdown-content-gap));
    opacity: 0;
}


html:not(.dwc-mobile) 
.bricks-is-frontend:not(.brx-header-left, .brx-header-right) 
.dwc-nest-menu[data-align-content-bottom="true"]:not([data-offcanvas="true"]) 
.brx-nav-nested-items > li {
    height: 100%;
    display: flex;
    align-items: center;
}

html:not(.dwc-mobile) 
.bricks-is-frontend:not(.brx-header-left, .brx-header-right) .dwc-nest-menu[data-align-content-bottom="true"]:not([data-offcanvas="true"]) 
.brx-nav-nested-items > li > .brxe-dropdown > .brx-submenu-toggle,
html:not(.dwc-mobile) 
.bricks-is-frontend:not(.brx-header-left, .brx-header-right) .dwc-nest-menu[data-align-content-bottom="true"]:not([data-offcanvas="true"]) 
.brx-nav-nested-items > li > .brxe-dropdown{
height: 100%
    }

.brx-nav-nested-items > li:has(> a),
.brx-nav-nested-items > li:has(> .brx-submenu-toggle) {
    position: relative;
}

/* END CARET FIX FOR DYNAMIC MENU STRUCTURE*/

/* SPECIAL MOBILE STYLES TABLET ONLY */


@media (min-width: 640px) and (max-width: 1200px) {

    /* mega menu */
    .dwc-mobile .bricks-is-frontend [data-mobile-special-style="slide-split"] .dwc-nav-wrapper {
        --mobile-menu-width: min(720px, 100%);
      align-items: flex-end;
    }

    .dwc-mobile .bricks-is-frontend [data-mobile-special-style="slide-split"] [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brx-has-megamenu.brxe-dropdown .brx-dropdown-content:not([data-hide-close-bar="true"] ul, [data-submenu-reveal="expand"].brx-has-megamenu ul) {
        inline-size: min(400px, 100%);
        box-shadow: 0px 0px 15px -10px #000000b3
    }

     .dwc-mobile .bricks-is-frontend [data-mobile-special-style="slide-split"] [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brx-has-megamenu.brxe-dropdown .brx-dropdown-content:not([data-submenu-reveal="expand"].brx-has-megamenu ul) {
        inset-inline-end: 0 !important;
        inset-inline-start: auto !important;
        inset-block-start: 0 !important;
    }

/*dropdown*/


     .dwc-mobile .bricks-is-frontend [data-mobile-special-style="slide-split"] [data-submenu-reveal="slide"].dwc-nest-menu.brxe-nav-nested .brxe-dropdown:not(:is([data-submenu-reveal="expand"], .brx-has-megamenu)) .brx-dropdown-content:not([data-submenu-reveal="expand"] *),
     .dwc-mobile .bricks-is-frontend [data-mobile-special-style="slide-split"] [data-submenu-reveal="slide"].brxe-dropdown:not(.brx-has-megamenu) .brx-dropdown-content {
        transition-property: inset-inline-start, inset-inline-end, visibility, opacity !important;
        inset-inline-start: auto !important;
        width: 400px;
        box-shadow: 0px 0px 15px -10px #000000b3;
        inset-block-start: 0 !important;
        inset-inline-end: -100% !important;
    }

     .dwc-mobile .bricks-is-frontend [data-mobile-special-style="slide-split"] [data-submenu-reveal="slide"].brxe-nav-nested.brx-open .brxe-dropdown.open:not(.brx-has-megamenu, [data-submenu-reveal="expand"])>.brx-dropdown-content,
     .dwc-mobile .bricks-is-frontend [data-mobile-special-style="slide-split"] .brx-open [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-dropdown-content,
     .dwc-mobile .bricks-is-frontend [data-mobile-special-style="slide-split"] .brx-open [data-submenu-reveal="slide"].brxe-dropdown.open>.brx-dropdown-content .open>.brx-dropdown-content {
        inset-inline-end: 0% !important;
        inset-inline-start: auto !important;
    }

  /*active styles*/
   .dwc-mobile  body:not(.brx-header-right, .brx-header-left) [data-mobile-special-style="slide-split"] .brx-nav-nested-items > li > .brx-has-megamenu.open > .brx-submenu-toggle{
    background-color: var(--menu-item-active-bg);
}

 .dwc-mobile  body:not(.brx-header-right, .brx-header-left) [data-mobile-special-style="slide-split"]  .brx-nav-nested-items > li.open > .brx-submenu-toggle{
    background-color: var(--menu-item-active-bg);
}
    

}

/* END SPECIAL MOBILE STYLES TABLET ONLY */


/* OVERLAY HEADER NO TOP GAP */

    .bricks-is-frontend [data-overlay-header-no-top-gap="true"] .dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"] .dwc-nav-wrapper {
        inset-block-start: 0 !important;
        }
        
        .bricks-is-frontend [data-overlay-header-no-top-gap="true"] .dwc-nest-menu[data-slide-in-direction="top"][data-match-overlay-header-width="true"] .brx-nav-nested-items {
             inset-block-start: calc((var(--dwc-nest-header-height) / 2) * -1) !important;
        }
        
        .bricks-is-frontend [data-overlay-header-no-top-gap="true"] .dwc-nest-menu[data-submenu-reveal="slide"][data-slide-in-direction="top"][data-match-overlay-header-width="true"] .open.active>.brx-submenu-toggle > button:not([data-hide-close-bar="true"] button, [data-submenu-reveal="expand"] button, .open.active:has(.open.active)>.brx-submenu-toggle > button) {
          inset-block-start: calc(var(--dwc-nest-header-height) / 2);
           
        }
        
        .bricks-is-frontend #brx-header > 
        .dwc-nest-header[data-overlay-header-no-top-gap="true"] {
            border-top-left-radius: 0 !important;
            border-top-right-radius: 0 !important;
        }
        
         .bricks-is-frontend 
        #brx-header:has([data-overlay-header-no-top-gap="true"]) {
            padding-block-start: 0 !important;
        }

/* END OVERLAY HEADER NO TOP GAP */


/* DROPDOWN ITEM IS BUTTON OR ICON */

/* IS ICON */
.brxe-dropdown[data-is-icon]{
  padding-inline: var(--menu-item-inline-padding);
}

/* remove the underline */
.brxe-dropdown[data-is-icon] > .brx-submenu-toggle::before{
display: none;
}

/* general styling */
.dwc-nest-menu .brx-nav-nested-items > .brxe-dropdown[data-is-icon] > .brx-submenu-toggle{
       height: auto !important;
    width: auto;
  min-width: var(--button-max-diameter);    
    aspect-ratio: 1;
    border-radius: var(--menu-item-radius) !important;
    padding: 0 !important;
    margin-inline-start: auto;
    margin-block: auto;
    transition: 0.4s;
  border: var(--menu-item-border)
}


.dwc-nest-menu .brx-nav-nested-items > .brxe-dropdown[data-is-icon]:hover > .brx-submenu-toggle{
  border: var(--menu-item-hover-border)
}

.dwc-mobile .dwc-nest-menu .brx-nav-nested-items > .brxe-dropdown[data-is-icon] > .brx-submenu-toggle{
max-width: var(--button-max-diameter);
}


/* centralize */
.brxe-dropdown[data-is-icon] > .brx-submenu-toggle > button{
  margin: auto;
  color: var(--icon-clr);
  font-size: var(--icon-size);
}

.brxe-dropdown[data-is-icon]:hover > .brx-submenu-toggle > button{
  color: var(--icon-hover-clr);
}

/* reset rotation on icon when hovered */
.brxe-dropdown[data-is-icon] > .brx-submenu-toggle button[aria-expanded="true"] > * {
    transform: rotateZ(0deg);
}

/* reset margin left on mobile*/
.dwc-mobile .dwc-nest-menu .brx-nav-nested-items > .brxe-dropdown[data-is-icon] > .brx-submenu-toggle{
 margin-inline-start: initial;
}

/* remove inner span from document flow and hide visually*/

.brxe-dropdown[data-is-icon] > .brx-submenu-toggle > span{
      clip: rect(1px,1px,1px,1px);
    word-wrap: normal!important;
    border: 0;
    clip-path: inset(50%);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    overflow-wrap: normal!important;
    padding: 0;
    position: absolute!important;
    width: 1px;
}

/* IS ICON ENDS */

/* IS BUTTON */

.brxe-dropdown[data-is-button] > .brx-submenu-toggle{
  height: auto !important;
    margin-block: auto;
  border-radius: var(--menu-item-radius) !important;
    max-width: var(--menu-item-width); 
  border: var(--menu-item-border);
}

.brxe-dropdown[data-is-button]:hover > .brx-submenu-toggle { 
    border: var(--menu-item-hover-border);
}


/* centralize text in span */

.brxe-dropdown[data-is-button] > .brx-submenu-toggle > span{
  margin-inline: auto;
}

/* remove button from document flow to allow text to centralize, but keep accessible*/
.brxe-dropdown[data-is-button="no-chevron"] > .brx-submenu-toggle > button{
      clip: rect(1px,1px,1px,1px);
    word-wrap: normal!important;
    border: 0;
    clip-path: inset(50%);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    overflow-wrap: normal!important;
    padding: 0;
    position: absolute!important;
    width: 1px;
}

/* block padding on mobile */
.dwc-mobile .brxe-dropdown:is([data-is-icon], [data-is-button]){  
padding-block: var(--menu-item-block-padding);
 padding-inline: var(--menu-item-inline-padding);
}

/* IS BUTTON ENDS */

/* DROPDWON ITEM IS BUTTON OR ICON ENDS */

/* RTL */

html:not(.dwc-mobile) :is(:not(.brx-header-left, .brx-header-right)).bricks-is-frontend .dwc-nest-menu:not([data-offcanvas="true"]) .brx-has-megamenu .brx-dropdown-content:not([data-use-selector="true"]) {
   inset-inline-end: var(--right-position)!important;
}

html:not(.dwc-mobile)[dir=rtl] .dwc-stripe-style .open.brx-has-megamenu:not([data-offcanvas="true"] .brx-has-megamenu)::before {
    transform: translateX(50%); 
}

html:not(.dwc-mobile)[dir=rtl] body:not(.brx-header-left, .brx-header-right) 
.dwc-nest-menu:not([data-offcanvas="true"])
.brxe-dropdown:not(.brx-has-megamenu) .brxe-dropdown .brx-submenu-toggle button 
svg {
    transform: rotate(-270deg);
}




/*RTL ENDS */


/* FIXES */
.dwc-nest-nav-items > li {
    width: auto;
}

li {
  -webkit-tap-highlight-color: transparent;
}

html:not(.dwc-mobile) #brx-header > *:not(.dwc-nest-header){
    z-index: 99999;
    position: relative;
}

/* account for admn bar on mobile menu */
.dwc-mobile .dwc-nav-wrapper {
    inset-block-start: var(--wp-admin--admin-bar--height, 0px);
}

.dwc-mobile .brxe-nav-nested.brx-open .brx-nav-nested-items {
 top:0;
}

    /* fix safari issue on fixed element inside scrollable container */
 .dwc-mobile .dwc-nest-menu.brxe-nav-nested:not([data-submenu-reveal="expand"]) .brx-nav-nested-items:has(.brxe-dropdown.open.active:not([data-submenu-reveal="expand"])){
        overflow-y: hidden;
    } 


[data-builder-window] .dwc-nest-menu{
  --global-width: attr(builder-preview-content-width px);
}

//document.body.classList.add('adaptive-height-active');
document.body.classList.add('show-nav');

function updateMobileClass(minWidth = MegaMenuCONFIG.minWidth) {
    const classList = document.documentElement.classList;
    const viewportWidth = document.documentElement.clientWidth;
    const isMobile = viewportWidth < minWidth;

    if (isMobile) {
        classList.add('dwc-mobile');
    } else {
        classList.remove('dwc-mobile');
    }
}
updateMobileClass();

// Centered Logo functionality
class CenteredLogoController {
    constructor(config = {}) {
        this.config = {
            enable: config.enable ?? CenteredLogoCONFIG.enable,
            allowOddItems: config.allowOddItems ?? CenteredLogoCONFIG.allowOddItems,
            forceCenteredLogo: config.forceCenteredLogo ?? CenteredLogoCONFIG.forceCenteredLogo,
            centerNudge: config.centerNudge ?? CenteredLogoCONFIG.centerNudge,
            roundOffFactor: config.roundOffFactor || CenteredLogoCONFIG.roundOffFactor,
            headerSelector: config.headerSelector || MegaMenuCONFIG.headerSelector
        };

        this.logoListItem = null;
        this.listItems = [];
        this.resizedFinished = null;
        this.isInitialized = false;
    }

    // Method to check if DOM elements are ready
    checkDOMReady() {
        const headerLogo = document.querySelector(`${this.config.headerSelector} .dwc-nest-menu__logo`);
        const headerInner = document.querySelector(`${this.config.headerSelector} .dwc-nest-header__container`);
        const menu = document.querySelector(`${this.config.headerSelector} .dwc-nest-menu`);
        const listParent = document.querySelector(`${this.config.headerSelector} .brx-nav-nested-items`);

        return headerLogo && headerInner && menu && listParent;
    }

    // Early initialization attempt
    initializeEarly() {
        if (!this.config.enable || this.isInitialized) return;

        // Try immediate initialization if elements are ready
        if (this.checkDOMReady()) {
            document.body.classList.add('dom-ready')
            this.setupElements();
            this.initialize();
            return;
        }

        // If not ready, use polling with shorter intervals for faster response
        const pollForElements = () => {
            if (this.checkDOMReady()) {
                this.setupElements();
                this.initialize();
                return;
            }
            // Poll every 10ms for very fast response
            setTimeout(pollForElements, 10);
        };

        pollForElements();
    }

    setupElements() {
        this.elements = {
            headerLogo: document.querySelector(`${this.config.headerSelector} .dwc-nest-menu__logo`),
            headerInner: document.querySelector(`${this.config.headerSelector} .dwc-nest-header__container`),
            menu: document.querySelector(`${this.config.headerSelector} .dwc-nest-menu`),
            listParent: document.querySelector(`${this.config.headerSelector} .brx-nav-nested-items`)
        };
    }

    initialize() {

        if (!this.config.enable || this.isInitialized) {
            return;
        }

        // Ensure elements are set up before proceeding
        if (!this.elements) {
            this.setupElements();
        }

        // Check if all required elements exist
        if (!this.elements.headerLogo || !this.elements.headerInner ||
            !this.elements.menu || !this.elements.listParent) {
            return;
        }

        this.isInitialized = true;

        // Create logo list item
        this.logoListItem = document.createElement('li');
        this.logoListItem.classList.add('dwc-header-logo-item');

        // Get list items excluding those with toggle divs, and exclude empty li
        this.listItems = Array.from(this.elements.listParent.children).filter(item => {
            const hasToggleDiv = item.querySelector('.brx-toggle-div');
            const isEmpty = item.matches('li:empty');
            const hasExclude = item.querySelector('.dwc-exclude')
            return !hasToggleDiv && !isEmpty && !hasExclude;
        });


        // Calculate position
        const halfIndex = this.listItems.length / 2;
        const logoOrder = this.roundHalfIndex(halfIndex, this.config.roundOffFactor);
        this.logoListItem.style.order = logoOrder;


        // Apply centering immediately
        this.centerLogo(logoOrder);



        // Add resize listener
        window.addEventListener('resize', this.centerLogo.bind(this, logoOrder));
    }

    roundHalfIndex(halfIndex, roundOffFactor) {
        if (roundOffFactor === 'before') {
            return Math.floor(halfIndex + 1);
        } else {
            return Math.ceil(halfIndex + 1);
        }
    }

    centerLogo(logoOrder) {
        if (!this.config.allowOddItems && this.listItems.length % 2 !== 0) {
            return;
        }

        clearTimeout(this.resizedFinished);

        this.resizedFinished = setTimeout(() => {
            const isDesktop = window.innerWidth >= MegaMenuCONFIG.minWidth;

            if (isDesktop) {
                document.body.classList.add('desktop-centered')
                let listID = 1;

                // Set order for list items
                this.listItems.forEach(listItem => {
                    if (!listItem.dataset.id) {
                        listItem.dataset.id = listID++;
                    }
                    this.logoListItem.style.order = logoOrder;
                    listItem.style.order = listItem.getAttribute('data-id');
                });

                if (!this.elements.listParent.contains(this.logoListItem) ||
                    !this.elements.listParent.contains(this.elements.headerLogo)) {

                    this.elements.listParent.prepend(this.logoListItem);
                    this.logoListItem.append(this.elements.headerLogo);
                    this.elements.headerInner.classList.add('dwc-logo-is-centered');

                    const logoBounds = this.elements.headerLogo.getBoundingClientRect();
                    const viewportWidth = document.documentElement.clientWidth;
                    const logoWidth = this.elements.headerLogo.offsetWidth;
                    const distanceRight = logoBounds.x;

                    // Force center if needed
                    if (this.config.forceCenteredLogo) {
                        const rightOffset = ((distanceRight + (logoWidth / 2)) + this.config.centerNudge) - (viewportWidth / 2);
                        const offsetMargin = rightOffset * 2;
                        this.elements.menu.style.marginRight = offsetMargin + 'px';
                    }

                    if (CenteredLogoCONFIG.centerGuide) {
                        if (document.body.classList.contains('logged-in')) {
                            // Check if the indicator already exists
                            if (!document.querySelector('.dwc-center-guide')) {
                                const indicatorEl = document.createElement('div')
                                indicatorEl.classList.add('dwc-center-guide')
                                indicatorEl.style.width = this.elements.headerLogo.offsetWidth + 'px';
                                document.body.appendChild(indicatorEl)
                            }
                        }
                    }

                }

            } else {
                document.body.classList.remove('desktop-centered');
                this.elements.headerInner.classList.add('dwc-logo-is-centered');
                this.elements.menu.style.marginRight = null;
                this.elements.headerInner.prepend(this.elements.headerLogo);
                this.logoListItem.style.order = null;
                this.listItems.forEach(listItem => {
                    listItem.style.order = null;
                });
            }
        }, 500);
    }
}

class MenuAnimationController {
    constructor(config = {}) {
        this.config = {
            minWidthThreshold: config.minWidthThreshold || MegaMenuCONFIG.minWidth,
            stripeStyle: config.stripeStyle ?? MegaMenuCONFIG.stripeStyle,
            adaptiveHeight: config.adaptiveHeight ?? MegaMenuCONFIG.adaptiveHeight,
            toolTip: config.toolTip ?? MegaMenuCONFIG.toolTip,
            menuAutoExpansion: config.menuAutoExpansion ?? MegaMenuCONFIG.menuAutoExpansion,
            headerSelector: config.headerSelector || MegaMenuCONFIG.headerSelector,
            megaMenuLinksSelector: `${config.headerSelector || MegaMenuCONFIG.headerSelector} .brx-has-megamenu`,
            offCanvasSelector: `${config.headerSelector || MegaMenuCONFIG.headerSelector} .dwc-nest-menu[data-offcanvas="true"]`,
            shiftFactor: config.shiftFactor ?? MegaMenuCONFIG.shiftFactor,  // Added shiftFactor
            minOverflow: config.minOverflow ?? MegaMenuCONFIG.minOverflow   // Added minOverflow
        };

        this.megaMenuLinks = document.querySelectorAll(this.config.megaMenuLinksSelector);
        this.header = document.querySelector(this.config.headerSelector);

        this.maxMenuWidth = 0;
        this.maxMenuHeight = 0;
        this.headerTimeoutId = null;
        this.mobileMenuTimeoutId = null;

        this.applyConfigClasses();
    }

    applyConfigClasses() {
        if (MegaMenuCONFIG.stripeStyle) {
            document.body.classList.add('dwc-stripe-style');
        }
        if (MegaMenuCONFIG.adaptiveHeight) {
            document.body.classList.add('dwc-adaptive-height');
        }

        if (this.header) {
            this.header.style.setProperty('--stripe-style-enabled', this.config.stripeStyle ? '1' : '0');
            this.header.style.setProperty('--height-animation-enabled', this.config.adaptiveHeight ? '1' : '0');
        }
    }
    /*
    isAboveMinWidth() {
        return window.innerWidth >= this.config.minWidthThreshold;
    }
    */

    getViewportWidth() {
        // Check if window exists (for SSR/Node environments)
        if (typeof window === 'undefined') return 0;

        return window.innerWidth ||
            document.documentElement?.clientWidth ||
            document.body?.clientWidth ||
            0;
    }

    isAboveMinWidth() {
        return this.getViewportWidth() >= this.config.minWidthThreshold;
    }


    isOffCanvas() {
        return !!document.querySelector(this.config.offCanvasSelector);
    }

    hasHeaderClass() {
        return document.body.classList.contains('brx-header-left') ||
            document.body.classList.contains('brx-header-right');
    }

    updateMenuVariables() {
        if (!this.isAboveMinWidth() || !this.header) return;

        // Cache RTL detection for performance - only check once per method call
        const isRTLLayout = this.isRTL ? this.isRTL() : false;

        let menuOpened = false;
        let menuWidth = 0;
        let menuHeight = 0;
        let menuOffset = 0; // Renamed for direction-agnostic naming

        this.megaMenuLinks.forEach(link => {
            if (link.classList.contains('open')) {
                requestAnimationFrame(() => {
                    let dropdownMenu = link.querySelector('.brx-dropdown-content');
                    let nestHeader = link.closest(this.config.headerSelector);

                    if (dropdownMenu) {
                        // Get dimensions (direction-agnostic)
                        menuWidth = dropdownMenu.offsetWidth;
                        menuHeight = dropdownMenu.offsetHeight;

                        // RTL-aware offset calculation
                        if (isRTLLayout) {
                            // RTL: Calculate offset from right edges
                            // Formula: distance from header's right edge to menu's right edge
                            const headerRect = nestHeader.getBoundingClientRect();
                            const menuRect = dropdownMenu.getBoundingClientRect();
                            menuOffset = (headerRect.right - menuRect.right) + window.scrollX;
                        } else {
                            // LTR: Original left-based calculation (unchanged for backwards compatibility)
                            menuOffset = Number(dropdownMenu.getBoundingClientRect().left) - Number(nestHeader.getBoundingClientRect().left) + window.scrollX;
                        }

                        // Update maximum dimensions (direction-agnostic)
                        this.maxMenuWidth = Math.max(this.maxMenuWidth, menuWidth);
                        this.maxMenuHeight = Math.max(this.maxMenuHeight, menuHeight);

                        // Calculate scaling factors (direction-agnostic)
                        let scaleX = menuWidth / this.maxMenuWidth;
                        let scaleY = menuHeight / this.maxMenuHeight;

                        // Set adaptive height if enabled (direction-agnostic)
                        if (this.config.adaptiveHeight || this.config.stripeStyle) {
                            this.header.style.setProperty('--dropdown-menu-height', `${menuHeight}px`);
                        }

                        // Set stripe-style variables with RTL awareness
                        if (this.config.stripeStyle) {
                            // Position variable - RTL-aware naming and calculation
                            if (isRTLLayout) {
                                // Set RTL-specific position variable
                                this.header.style.setProperty('--dropdown-menu-x-rtl', `${menuOffset}px`);
                                // Also set the standard variable for CSS that expects it
                                this.header.style.setProperty('--dropdown-menu-x', `${menuOffset}px`);
                            } else {
                                // LTR: Use standard left-based positioning
                                this.header.style.setProperty('--dropdown-menu-x', `${menuOffset}px`);
                                // Clear any RTL variable that might exist
                                this.header.style.removeProperty('--dropdown-menu-x-rtl');
                            }

                            // Set dimension and scaling variables (direction-agnostic)
                            this.header.style.setProperty('--dropdown-menu-width', `${menuWidth}px`);
                            this.header.style.setProperty('--dropdown-menu-max-width', `${this.maxMenuWidth}px`);
                            this.header.style.setProperty('--dropdown-menu-max-height', `${this.maxMenuHeight}px`);
                            this.header.style.setProperty('--dropdown-menu-scale-x', scaleX.toString());
                            this.header.style.setProperty('--dropdown-menu-scale-y', scaleY.toString());

                            // Set direction indicator for CSS usage
                            this.header.style.setProperty('--dropdown-menu-direction', isRTLLayout ? 'rtl' : 'ltr');
                        }
                    }
                });

                menuOpened = true;
                this.header.classList.add('show-menu-animation');
                this.header.classList.remove('hide-menu-animation');
            }
        });

        // Handle menu closing (unchanged logic, direction-agnostic)
        if (!menuOpened) {
            const hasAdaptiveHeight = document.body.classList.contains('dwc-adaptive-height');
            const hasStripeStyle = document.body.classList.contains('dwc-stripe-style');

            if (hasAdaptiveHeight && !hasStripeStyle) {
                this.header.style.setProperty('--dropdown-menu-height', '0px');
            }

            this.header.style.setProperty('--dropdown-menu-scale-y', '0');

            if (this.header) {
                this.header.classList.add('hide-menu-animation');
                this.header.classList.remove('show-menu-animation');
            }
        }
    }


    updateDropdownPositions() {
    const viewportWidth = document.documentElement.clientWidth;
    if (viewportWidth < this.config.minWidthThreshold) return; // Run only on desktop

    const dropdowns = document.querySelectorAll(`${this.config.headerSelector} .dwc-nest-menu .brx-has-megamenu .brx-dropdown-content`);
    const defaultElement = document.querySelector('#brx-header');
    const defaultRect = defaultElement ? defaultElement.getBoundingClientRect() : null;
    const isRTL = this.isRTL();

    requestAnimationFrame(() => {
        // Handle vertical positioning (global top or stripe style)
        this.handleVerticalPositioning();

        // Handle width and horizontal alignment positioning
        dropdowns.forEach((dropdown) => {
            this.setDropdownWidth(dropdown);
            this.positionDropdownHorizontally(dropdown, defaultRect, viewportWidth, isRTL);
        });
    });
}

/**
 * Detect if the document is using RTL (Right-to-Left) layout
 */
isRTL() {
    const htmlDir = document.documentElement.dir?.toLowerCase();
    if (htmlDir) return htmlDir === 'rtl';
    
    const computedDirection = getComputedStyle(document.documentElement).direction;
    return computedDirection === 'rtl';
}

/**
 * Handle vertical positioning for dropdowns (global top positioning or stripe style)
 */
handleVerticalPositioning() {
    const nestMenu = document.querySelector('.dwc-nest-menu');
    const globalTopSelector = nestMenu ? nestMenu.getAttribute('data-global-content-vertical') : null;

    if (globalTopSelector) {
        this.positionDropdownsRelativeToElement(globalTopSelector, 'global top element');
    } else if (this.config.stripeStyle) {
        this.positionDropdownsRelativeToElement('#brx-header', '#brx-header bottom (stripe style)');
    }
}

/**
 * Position dropdowns relative to a specified element
 */
positionDropdownsRelativeToElement(selector, description) {
    const targetElement = document.querySelector(selector);
    if (!targetElement) return;

    const positioningDropdowns = document.querySelectorAll(`${this.config.headerSelector} .dwc-nest-menu .brx-dropdown-content:not(.brx-dropdown-content .brx-dropdown-content)`);
    const targetRect = targetElement.getBoundingClientRect();

    positioningDropdowns.forEach(dropdown => {
        const menuItem = dropdown.closest('.menu-item') || dropdown.parentElement;
        const menuItemRect = menuItem.getBoundingClientRect();
        
        const topPosition = menuItemRect.height + targetRect.bottom - menuItemRect.bottom;
        dropdown.style.top = `${topPosition}px`;
    });

    // console.log(`Positioned dropdowns relative to ${description}`);
}

/**
 * Set dropdown width based on data attributes or global settings
 */
setDropdownWidth(dropdown) {
    // Check for individual data-content-width attribute first
    const localSelector = dropdown.getAttribute('data-content-width');
    
    if (localSelector) {
        this.applyWidthFromSelector(dropdown, localSelector);
        return;
    }

    // Fall back to global data-global-content-width setting
    const nestMenu = document.querySelector('.dwc-nest-menu');
    const globalSelector = nestMenu ? nestMenu.getAttribute('data-global-content-width') : null;
    
    if (globalSelector) {
        this.applyWidthFromSelector(dropdown, globalSelector);
    }
}

/**
 * Apply width to dropdown based on selector (number, CSS value, CSS variable, or element selector)
 */
applyWidthFromSelector(dropdown, selector) {
    // Check if it's a number or value with CSS units
    if (/^\d+(\.\d+)?(px|rem|em|%|vh|vw|ch|ex|cm|mm|in|pt|pc)?$/i.test(selector)) {
        const hasUnit = /\d+(px|rem|em|%|vh|vw|ch|ex|cm|mm|in|pt|pc)$/i.test(selector);
        const widthValue = hasUnit ? selector : `${selector}px`;
        dropdown.style.setProperty('--dropdown-content-width', widthValue);
    }
    // Check if it's a CSS variable (starts with var( and ends with ))
    else if (/^var\(--[\w-]+\)$/.test(selector)) {
        this.applyWidthFromCSSVariable(dropdown, selector);
    }
    // Treat as element selector
    else {
        this.applyWidthFromElement(dropdown, selector);
    }
}

/**
 * Apply width from CSS variable
 */
applyWidthFromCSSVariable(dropdown, variableSelector) {
    const variableName = variableSelector.match(/^var\((--[\w-]+)\)$/)[1];
    const computedValue = getComputedStyle(document.documentElement).getPropertyValue(variableName).trim();

    if (computedValue) {
        const hasUnit = /\d+(px|rem|em|%|vh|vw|ch|ex|cm|mm|in|pt|pc)$/i.test(computedValue);
        const widthValue = hasUnit ? computedValue : `${computedValue}px`;
        dropdown.style.setProperty('--dropdown-content-width', widthValue);
    }
}

/**
 * Apply width from target element
 */
applyWidthFromElement(dropdown, selector) {
    const targetElement = document.querySelector(selector);
    if (targetElement) {
        const targetWidth = targetElement.getBoundingClientRect().width;
        dropdown.style.setProperty('--dropdown-content-width', `${targetWidth}px`);
    }
}

/**
 * Handle horizontal positioning of dropdown with RTL support and overflow management
 * FIXED VERSION - Properly handles RTL overflow prevention
 */
positionDropdownHorizontally(dropdown, defaultRect, viewportWidth, isRTL) {
    const parentLi = dropdown.closest('.brx-has-megamenu.brxe-dropdown');
    if (!parentLi) return;

    const contentAlign = dropdown.getAttribute('data-content-align');
    let actualDropdownWidth = this.getActualDropdownWidth(dropdown);
    const liRect = parentLi.getBoundingClientRect();

    // Constrain width to viewport if dropdown is wider
    if (actualDropdownWidth > viewportWidth) {
        dropdown.style.setProperty('--dropdown-content-width', `${viewportWidth}px`);
        actualDropdownWidth = viewportWidth;
    }

    // Calculate initial position based on alignment and RTL
    let position = this.calculateInitialPosition(dropdown, parentLi, contentAlign, actualDropdownWidth, defaultRect, isRTL);

    // Apply overflow corrections with proper RTL support
    position = this.handleOverflowAdjustments(position, liRect, actualDropdownWidth, viewportWidth, isRTL);

    // Set final position using appropriate CSS property
    if (isRTL) {
        // In RTL, we need to calculate right-based positioning
        const rightPosition = liRect.width - position - actualDropdownWidth;
        dropdown.style.setProperty('--right-position', `${rightPosition}px`);
        dropdown.style.removeProperty('--left-position');
    } else {
        // LTR uses left-based positioning (existing behavior)
        dropdown.style.setProperty('--left-position', `${position}px`);
        dropdown.style.removeProperty('--right-position');
        
        // Fallback for existing CSS that expects --left-position
        if (!dropdown.style.getPropertyValue('--left-position')) {
            dropdown.style.setProperty('--left-position', '0px');
        }
    }
}

/**
 * Get actual dropdown width accounting for CSS transforms
 */
getActualDropdownWidth(dropdown) {
    const computedStyle = getComputedStyle(dropdown);
    const dropdownRect = dropdown.getBoundingClientRect();

    // Extract scale factor from transform
    const transform = computedStyle.transform || computedStyle.webkitTransform;
    let scaleX = 1;

    if (transform && transform !== 'none') {
        const matrix = transform.match(/^matrix\((.+)\)$/);
        if (matrix) {
            const values = matrix[1].split(', ');
            scaleX = parseFloat(values[0]);
        }
    }

    return dropdownRect.width / scaleX;
}

/**
 * Calculate initial dropdown position based on alignment and RTL settings
 * ENHANCED VERSION with improved RTL positioning
 */
calculateInitialPosition(dropdown, parentLi, contentAlign, actualDropdownWidth, defaultRect, isRTL) {
    const validAlignments = ['left', 'center', 'right'];
    const hasValidAlignment = contentAlign && validAlignments.includes(contentAlign);
    const liRect = parentLi.getBoundingClientRect();

    if (!hasValidAlignment) {
        // Default centering behavior
        return this.calculateCenteredPosition(actualDropdownWidth, defaultRect, liRect, isRTL);
    }

    // Apply RTL-aware alignment mapping
    const effectiveAlignment = this.getEffectiveAlignment(contentAlign, isRTL);
    
    // Calculate position relative to parent element
    switch (effectiveAlignment) {
        case 'left':
            return isRTL ? liRect.width : 0;
        case 'right':
            return isRTL ? 0 : (liRect.width - actualDropdownWidth);
        case 'center':
            return (liRect.width - actualDropdownWidth) / 2;
        default:
            return isRTL ? liRect.width : 0;
    }
}


/**
 * Map alignment values for RTL layouts
 */
getEffectiveAlignment(contentAlign, isRTL) {
    if (!isRTL) return contentAlign;
    
    // RTL alignment mapping
    switch (contentAlign) {
        case 'left': return 'right';
        case 'right': return 'left';
        case 'center': return 'center';
        default: return contentAlign;
    }
}


/**
 * Calculate centered position for default alignment
 * ENHANCED VERSION with better RTL support
 */
calculateCenteredPosition(actualDropdownWidth, defaultRect, liRect, isRTL) {
    if (!defaultRect) return isRTL ? liRect.width / 2 : 0;

    const defaultElement = document.querySelector('#brx-header');
    const headerRect = defaultElement ? defaultElement.getBoundingClientRect() : null;

    if (headerRect) {
        const centerOffset = (defaultRect.width - actualDropdownWidth) / 2;
        
        if (isRTL) {
            // RTL: Calculate position relative to parent's right edge
            const headerRightOffset = headerRect.right;
            const liRightOffset = liRect.right;
            return centerOffset - (headerRightOffset - liRightOffset);
        } else {
            // LTR: Calculate position relative to parent's left edge (existing logic)
            const headerLeftOffset = headerRect.left + window.scrollX;
            return centerOffset - (liRect.left - headerLeftOffset);
        }
    }

    return isRTL ? liRect.width / 2 : 0;
}

/**
 * Handle viewport overflow adjustments with proper RTL support
 * COMPLETELY REWRITTEN for accurate RTL edge calculations
 */
handleOverflowAdjustments(position, liRect, actualDropdownWidth, viewportWidth, isRTL) {
    // Calculate edges based on layout direction
    let leftEdge, rightEdge;
    
    if (isRTL) {
        // RTL: position is relative to parent's right edge, calculate absolute edges
        const parentRight = liRect.right;
        rightEdge = parentRight - position;
        leftEdge = rightEdge - actualDropdownWidth;
    } else {
        // LTR: position is relative to parent's left edge (existing logic)
        leftEdge = liRect.left + position;
        rightEdge = leftEdge + actualDropdownWidth;
    }

    let adjustedPosition = position;
    const isViewportConstrained = actualDropdownWidth >= viewportWidth;

    // Check for left viewport overflow
    if (leftEdge < 0) {
        const leftOverflow = Math.abs(leftEdge);
        
        if (isViewportConstrained) {
            // For viewport-constrained dropdowns, use exact positioning
            if (isRTL) {
                // RTL: adjust position to align left edge with viewport
                adjustedPosition = position - leftOverflow;
            } else {
                // LTR: adjust position to align left edge with viewport
                adjustedPosition += leftOverflow;
            }
        } else {
            // For normal dropdowns, use configured shift behavior
            const adjustedOverflow = leftOverflow < this.config.minOverflow ? this.config.minOverflow : leftOverflow;
            if (isRTL) {
                adjustedPosition -= adjustedOverflow * this.config.shiftFactor;
            } else {
                adjustedPosition += adjustedOverflow * this.config.shiftFactor;
            }
        }
    }

    // Recalculate right edge after left adjustments
    let adjustedRightEdge;
    if (isRTL) {
        const parentRight = liRect.right;
        adjustedRightEdge = parentRight - adjustedPosition;
    } else {
        adjustedRightEdge = liRect.left + adjustedPosition + actualDropdownWidth;
    }
    
    // Check for right viewport overflow
    if (adjustedRightEdge > viewportWidth) {
        const rightOverflow = adjustedRightEdge - viewportWidth;
        
        if (isViewportConstrained) {
            // For viewport-constrained dropdowns, position exactly at viewport edge
            if (isRTL) {
                // RTL: adjust position to align right edge with viewport
                adjustedPosition += rightOverflow;
            } else {
                // LTR: adjust position to align right edge with viewport
                adjustedPosition -= rightOverflow;
            }
            
            // Double-check: if this causes opposite overflow, prioritize based on RTL
            let finalLeftEdge, finalRightEdge;
            if (isRTL) {
                const parentRight = liRect.right;
                finalRightEdge = parentRight - adjustedPosition;
                finalLeftEdge = finalRightEdge - actualDropdownWidth;
            } else {
                finalLeftEdge = liRect.left + adjustedPosition;
                finalRightEdge = finalLeftEdge + actualDropdownWidth;
            }
            
            if (finalLeftEdge < 0) {
                if (isRTL) {
                    // In RTL, prioritize right edge - align dropdown to right edge of viewport
                    adjustedPosition = liRect.right - viewportWidth;
                } else {
                    // In LTR, prioritize left edge - align dropdown to left edge of viewport
                    adjustedPosition = -liRect.left;
                }
            }
        } else {
            // For normal dropdowns, use configured shift behavior
            const adjustedOverflow = rightOverflow < this.config.minOverflow ? this.config.minOverflow : rightOverflow;
            if (isRTL) {
                adjustedPosition += adjustedOverflow * this.config.shiftFactor;
            } else {
                adjustedPosition -= adjustedOverflow * this.config.shiftFactor;
            }
        }
    }

    return adjustedPosition;
}

/**
 * Handle dropdowns that are wider than the viewport
 */
handleWideDropdownOverflow(liRect, actualDropdownWidth, viewportWidth, isRTL) {
    // For dropdowns wider than viewport, prioritize showing the start of content
    // In RTL, this means showing the right side; in LTR, the left side
    if (isRTL) {
        // Align to right edge of viewport
        return viewportWidth - liRect.left - actualDropdownWidth;
    } else {
        // Align to left edge of viewport
        return -liRect.left;
    }
}


    setCurrentPageDropdownActive() {
        if (!this.config.menuAutoExpansion) return;

        const isDesktop = window.innerWidth >= this.config.minWidthThreshold;
        const hasSpecialHeader = document.body.classList.contains('brx-header-left') ||
            document.body.classList.contains('brx-header-right');
        const isOffCanvas = !!document.querySelector(this.config.offCanvasSelector);

        if (isDesktop && !hasSpecialHeader && !isOffCanvas) return;

        const currentPageLink = document.querySelector('[aria-current="page"]');

        if (currentPageLink) {
            const parentDropdown = currentPageLink.closest('.brxe-dropdown');
            let tabbedParentDropdown = currentPageLink.closest('.dwc-tabbed-nav-list__li');

            // If tabbedParentDropdown has currentPageLink as a direct child, ignore it
            if (tabbedParentDropdown) {
                const directPageLink = tabbedParentDropdown.querySelector(':scope > a[aria-current="page"]');
                if (directPageLink) {
                    tabbedParentDropdown = null; // Ignore tabbedParentDropdown
                }
            }

            if (parentDropdown) {
                setTimeout(() => {
                    //console.log(tabbedParentDropdown);
                    parentDropdown.classList.add('open', 'active');

                    // Only add 'active' class if tabbedParentDropdown exists
                    if (tabbedParentDropdown) {
                        tabbedParentDropdown.classList.add('active');
                    }

                    const submenuToggle = parentDropdown.querySelector('.brx-submenu-toggle');
                    let button = submenuToggle ? submenuToggle.querySelector('button') : null;
                    const menuToggle = document.querySelector('.dwc-nest-menu .brxe-toggle');

                    if (button) {
                        menuToggle.addEventListener('click', () => {
                            setTimeout(() => {
                                const submenuIsOpen = parentDropdown.classList.contains('open', 'active');
                                if (submenuIsOpen) {
                                    button.setAttribute('aria-expanded', 'true');
                                }
                            }, 100);
                        });
                    }

                    setTimeout(() => {
                        currentPageLink.scrollIntoView({
                            behavior: 'smooth',
                            block: 'nearest'
                        });
                    }, 600);
                }, 700);
            }
        }
    }

    updateChevronPosition(targetLink) {
        if (!this.config.stripeStyle) return;

        requestAnimationFrame(() => {
            let headerElement = document.querySelector(this.config.headerSelector);
            if (!headerElement) {
                console.error('Chevron parent element not found.');
                return;
            }

            // Cache RTL detection for performance within this animation frame
            const isRTLLayout = this.isRTL ? this.isRTL() : false;

            // Get element dimensions and positions
            let linkRect = targetLink.getBoundingClientRect();
            let headerRect = headerElement.getBoundingClientRect();

            // Calculate link midpoint (geometric center - always the same regardless of direction)
            let linkMidpoint = linkRect.left + linkRect.width / 2;

            // RTL-aware reference point calculation
            let headerReferenceOffset, navlinkMidpointOffset, navlinkEdgeOffset;

            if (isRTLLayout) {
                // RTL: Use right edge as reference point
                let headerRightOffset = headerRect.right + window.scrollX;

                // Calculate offsets relative to header's right edge
                navlinkMidpointOffset = headerRightOffset - linkMidpoint;
                navlinkEdgeOffset = headerRightOffset - linkRect.right;
                headerReferenceOffset = headerRightOffset;

                // Set RTL-specific CSS variables
                headerElement.style.setProperty('--chevron-parent-right', `${headerReferenceOffset}px`);
                headerElement.style.setProperty('--navlink-midpoint-rtl', `${navlinkMidpointOffset}px`);
                headerElement.style.setProperty('--navlink-right', `${navlinkEdgeOffset}px`);

                // Set unified variables for CSS that expects them (RTL context)
                headerElement.style.setProperty('--navlink-midpoint', `${navlinkMidpointOffset}px`);
                headerElement.style.setProperty('--navlink-edge', `${navlinkEdgeOffset}px`);

            } else {
                // LTR: Original left-based calculation (unchanged for perfect backwards compatibility)
                let headerLeftOffset = headerRect.left + window.scrollX;

                // Calculate offsets relative to header's left edge (original logic)
                navlinkMidpointOffset = linkMidpoint - headerLeftOffset;
                navlinkEdgeOffset = linkRect.left - headerLeftOffset;
                headerReferenceOffset = headerLeftOffset;

                // Set standard LTR CSS variables (original behavior)
                headerElement.style.setProperty('--chevron-parent-left', `${headerReferenceOffset}px`);
                headerElement.style.setProperty('--navlink-midpoint', `${navlinkMidpointOffset}px`);
                headerElement.style.setProperty('--navlink-left', `${navlinkEdgeOffset}px`);

                // Set unified edge variable for consistency
                headerElement.style.setProperty('--navlink-edge', `${navlinkEdgeOffset}px`);

                // Clean up any RTL variables that might exist from previous state
                headerElement.style.removeProperty('--chevron-parent-right');
                headerElement.style.removeProperty('--navlink-midpoint-rtl');
                headerElement.style.removeProperty('--navlink-right');
            }

            // Set direction-agnostic variables (same for both LTR and RTL)
            headerElement.style.setProperty('--chevron-parent-width', `${headerRect.width}px`);
            headerElement.style.setProperty('--navlink-width', `${linkRect.width}px`);

            // Set direction indicator for CSS conditional logic
            headerElement.style.setProperty('--chevron-direction', isRTLLayout ? 'rtl' : 'ltr');

            // Set boolean flags for easier CSS targeting
            if (isRTLLayout) {
                headerElement.style.setProperty('--is-rtl', '1');
                headerElement.style.removeProperty('--is-ltr');
            } else {
                headerElement.style.setProperty('--is-ltr', '1');
                headerElement.style.removeProperty('--is-rtl');
            }
        });
    }


    updateHeaderHeight() {
        if (this.headerTimeoutId) {
            clearTimeout(this.headerTimeoutId);
        }

        requestAnimationFrame(() => {
            if (this.header) {
                this.headerTimeoutId = setTimeout(() => {
                    let headerHeight = this.header.offsetHeight;
                    document.body.style.setProperty('--dwc-nest-header-height', `${headerHeight}px`);
                }, 300);
            }
        });
    }

    setMobileMenuTopHeight() {
        if (this.mobileMenuTimeoutId) {
            clearTimeout(this.mobileMenuTimeoutId);
        }

        let mobileMenuTop = document.querySelector('.dwc-nest-menu-top');
        if (!mobileMenuTop) {
            console.error('Mobile menu top element not found');
            return;
        }

        this.mobileMenuTimeoutId = setTimeout(() => {
            let menuTopHeight = mobileMenuTop.offsetHeight;
            document.body.style.setProperty('--mobile-menu-top-height', `${menuTopHeight}px`);
        }, 1000);
    }


    updateMobileLogo() {
        let mobileLogo = document.querySelector('.dwc-nest-menu__mobile-logo');
        let desktopLogo = document.querySelector('.dwc-nest-menu__logo');

        if (!mobileLogo) {
            console.error('Mobile logo container not found');
            return;
        }

        if (!desktopLogo) {
            console.error('Desktop logo container not found');
            return;
        }

        // Updated to check for either img or svg in desktop logo
        let desktopLogoElement = desktopLogo.querySelector('img, svg');
        if (!desktopLogoElement) return;

        // Check if mobile logo has an image or SVG
        const currentMobileLogo = mobileLogo.querySelector('img, svg');

        // Store original logo data if not already stored
        if (!mobileLogo.hasAttribute('data-original-logo-type') && currentMobileLogo) {
            // Get logo type (img or svg)
            const logoType = currentMobileLogo.tagName.toLowerCase();
            mobileLogo.setAttribute('data-original-logo-type', logoType);

            if (logoType === 'img') {
                mobileLogo.setAttribute('data-original-logo-src', currentMobileLogo.src);
                mobileLogo.setAttribute('data-original-logo-alt', currentMobileLogo.alt || '');
                mobileLogo.setAttribute('data-original-logo-class', currentMobileLogo.className || '');
            } else if (logoType === 'svg') {
                // Store SVG content as a string
                mobileLogo.setAttribute('data-original-logo-content', currentMobileLogo.outerHTML);
                mobileLogo.setAttribute('data-original-logo-class', currentMobileLogo.getAttribute('class') || '');
            }
        }

        if (this.isAboveMinWidth()) {
            if (currentMobileLogo) {
                mobileLogo.removeChild(currentMobileLogo);
            }

            // Clone desktop logo (either img or svg)
            let newLogo = desktopLogoElement.cloneNode(true);
            newLogo.removeAttribute('id');
            //  mobileLogo.appendChild(newLogo);
        } else {
            // For mobile view
            const originalLogoType = mobileLogo.getAttribute('data-original-logo-type');

            if (!currentMobileLogo) {
                // If no current logo, clone desktop logo
                let mobileLogoElement = desktopLogoElement.cloneNode(true);
                mobileLogoElement.removeAttribute('id');
                mobileLogo.appendChild(mobileLogoElement);
            } else if (originalLogoType) {
                mobileLogo.removeChild(currentMobileLogo);

                if (originalLogoType === 'img') {
                    // Restore original img
                    let mobileLogoImage = document.createElement('img');
                    mobileLogoImage.src = mobileLogo.getAttribute('data-original-logo-src');
                    mobileLogoImage.alt = mobileLogo.getAttribute('data-original-logo-alt') || '';
                    mobileLogoImage.className = mobileLogo.getAttribute('data-original-logo-class') || '';
                    mobileLogo.appendChild(mobileLogoImage);
                } else if (originalLogoType === 'svg') {
                    // Restore original SVG
                    const svgContent = mobileLogo.getAttribute('data-original-logo-content');
                    if (svgContent) {
                        const tempContainer = document.createElement('div');
                        tempContainer.innerHTML = svgContent;
                        const svgElement = tempContainer.querySelector('svg');
                        if (svgElement) {
                            mobileLogo.appendChild(svgElement.cloneNode(true));
                        }
                    }
                }
            }
        }
    }


    initDesktopNav() {
        if (this.isOffCanvas() || !this.header || this.hasHeaderClass()) return;

        let menuElement = this.header.querySelector('.dwc-nest-menu');
        if (menuElement) {
            menuElement.classList.remove('brx-open');
            menuElement.querySelectorAll('.brxe-dropdown').forEach(dropdown => {
                dropdown.classList.remove('active', 'open');
            });
        }
    }

    initializeMaxDimensions() {
        if (!this.isAboveMinWidth()) return;

        this.megaMenuLinks.forEach(link => {
            let dropdown = link.querySelector('.brx-dropdown-content');
            if (dropdown) {
                this.maxMenuWidth = Math.max(this.maxMenuWidth, dropdown.offsetWidth);
                this.maxMenuHeight = Math.max(this.maxMenuHeight, dropdown.offsetHeight + 10);
            }
        });

        this.header.style.setProperty('--dropdown-menu-max-width', `${this.maxMenuWidth}px`);
        this.header.style.setProperty('--dropdown-menu-max-height', `${this.maxMenuHeight}px`);
        this.header.style.setProperty('--dropdown-menu-scale-x', '0');
        this.header.style.setProperty('--dropdown-menu-scale-y', '0');
    }

    resetForMobile() {
        this.header.style.setProperty('--dropdown-menu-scale-x', '0');
        this.header.style.setProperty('--dropdown-menu-scale-y', '0');
        this.header.style.setProperty('--dropdown-menu-width', '0');

        if (this.header) {
            this.header.classList.remove('show-menu-animation', 'hide-menu-animation');
        }
    }

    setBoxedWidthVariable() {
        // Check if body has the brx-boxed class
        if (document.body.classList.contains('brx-boxed')) {
            // Get computed style for the body
            const computedStyle = window.getComputedStyle(document.body);

            // Get the max-width value
            const maxWidth = computedStyle.getPropertyValue('max-width');

            // Set the max-width as a CSS variable on the body
            document.body.style.setProperty('--boxed-width', maxWidth);

            return maxWidth;
        } else {
            return null;
        }
    }

    closeNavOnClick() {
        if (MegaMenuCONFIG.closeNavOnClick) {

            const allLinks = document.querySelectorAll('.dwc-nest-menu a');
            const menuContainer = document.querySelector('.dwc-nest-menu');
            const menuItemLinks = Array.from(allLinks).filter(link => {
                return link.parentElement !== menuContainer;
            });

            const menuToggle = document.querySelector('.dwc-nest-menu .brxe-toggle');

            // Always remove existing event listeners first
            menuItemLinks.forEach(link => {
                const storedHandler = link._clickHandler;
                if (storedHandler) {
                    link.removeEventListener('click', storedHandler);
                    delete link._clickHandler;
                }
            });

            // Check condition - if true, exit without adding new listeners
            if (this.isAboveMinWidth() && !this.isOffCanvas()) return;

            // Helper function to check if element has excluded selector
            const hasExcludedSelector = (element) => {
                if (!MegaMenuCONFIG.closeNavOnClickExclude) return false;

                const excludedSelectors = MegaMenuCONFIG.closeNavOnClickExclude
                    .split(',')
                    .map(selector => selector.trim());

                return excludedSelectors.some(selector => {
                    try {
                        return element.matches(selector);
                    } catch (error) {
                        // Fallback for invalid selectors - log warning and skip
                        console.warn(`Invalid selector: "${selector}"`, error);
                        return false;
                    }
                });
            };

            // Helper function to check if link has a hash
            const hasHashLink = (link) => {
                const href = link.getAttribute('href');
                return href && href.includes('#');
            };

            // Only add new event listeners if the condition is false
            menuItemLinks.forEach(link => {
                // Skip this link if it has any excluded classes
                if (hasExcludedSelector(link)) return;

                // If closeOnHashClickOnly is true, skip links without hash
                if (MegaMenuCONFIG.closeOnHashClickOnly && !hasHashLink(link)) return;

                const clickHandler = () => {
                    if (menuToggle) {
                        menuToggle.click();
                    }
                };

                link._clickHandler = clickHandler;
                link.addEventListener('click', clickHandler);
            });
        }
    }
}

class TooltipManager {
    constructor(config) {
        this.config = {
            toolTip: config.toolTip || false
        };
        this.targetButton = null;
        this.tooltipProcessed = false;
    }

    setBackText() {
        let menuElement = document.querySelector('.dwc-nest-menu');
        let forcedBackText = menuElement.getAttribute('data-back-text')
        document.querySelectorAll('.brx-submenu-toggle').forEach(submenu => {
            const textContent = submenu.textContent.trim();
            const button = submenu.querySelector('.brx-submenu-toggle > button');
            if (button) {
                button.setAttribute('data-text', textContent);
                button.setAttribute('data-back-text', forcedBackText);
            }
        });
    }

    updateTooltipDataText(button) {
        if (!this.config.toolTip) return;

        let menuElement = document.querySelector('.dwc-nest-menu');
        let toolTipBackText = menuElement.getAttribute('data-tooltip-back-text')

        const closestUl = button.closest('.dwc-nav-wrapper, .dwc-tabbed-nav__list-wrapper');
        if (closestUl) {
            const tooltip = closestUl.querySelector('.dwc-nest-tooltip');
            if (tooltip) {
                const buttonText = button.getAttribute('data-text') ||
                    button.querySelector('i')?.getAttribute('data-text');
                tooltip.setAttribute('data-text', buttonText);
                tooltip.innerText = toolTipBackText + ' ' + buttonText;                
            }
            //console.log('button: ', button)
            //console.log('closet ul: ', closestUl)
        }

    }

    addTooltip(button) {
        if (!this.config.toolTip) return;

        let menuElement = document.querySelector('.dwc-nest-menu');
        let toolTipBackText = menuElement.getAttribute('data-tooltip-back-text')

        const closestUl = button.closest('.dwc-nav-wrapper, .dwc-tabbed-nav__list-wrapper');
        if (!closestUl) return;

        this.removeTooltipFrom(closestUl);

        const tooltip = document.createElement('div');
        tooltip.className = 'dwc-nest-tooltip';
        tooltip.innerText = toolTipBackText;
        tooltip.style.position = 'fixed';
        tooltip.style.bottom = '12px';
        tooltip.style.left = '12px';
        tooltip.style.background = 'rgb(0 0 0 / 30%)';
        tooltip.style.color = 'white';
        tooltip.style.padding = '5px 10px';
        tooltip.style.borderRadius = '5px';
        tooltip.style.fontSize = '12px';
        tooltip.style.zIndex = '9999';
        tooltip.style.opacity = '0';
        tooltip.style.transition = 'opacity 1.5s';
        tooltip.style.pointerEvents = 'none';
        closestUl.appendChild(tooltip);

        requestAnimationFrame(() => {
            tooltip.style.opacity = '1';
        });
    }

    removeAllTooltips() {
        document.querySelectorAll('.dwc-nest-tooltip').forEach(tooltip => tooltip.remove());
    }

    removeTooltipFrom(ulElement) {
        const existingTooltip = ulElement.querySelector('.dwc-nest-tooltip');
        if (existingTooltip) existingTooltip.remove();
    }

    setupTooltipObserver() {
        const tooltipObserver = new MutationObserver((mutationsList) => {
            if (this.tooltipProcessed) return;

            for (const mutation of mutationsList) {
                if (mutation.type === 'childList') {
                    for (const node of mutation.addedNodes) {
                        if (node.nodeType === Node.ELEMENT_NODE &&
                            node.classList.contains('dwc-nest-tooltip') &&
                            !this.tooltipProcessed) {
                            const button = document.querySelector('.open.active > .brx-submenu-toggle > button:not(.open .open button)');
                            if (button) {
                                this.updateTooltipDataText(button);
                                this.tooltipProcessed = true;
                                return;
                            }
                        }
                    }
                }
            }
        });

        tooltipObserver.observe(document.body, { childList: true, subtree: true });
    }
}

class SwipeGestureHandler {
    constructor(config) {
        this.config = {
            swipeToClose: config.swipeToClose || false
        };
        this.targetButton = null;
        this.startX = 0;
        this.startY = 0;
        this.endX = 0;
        this.endY = 0;
        
        // Cache RTL detection for performance during touch events
        this.isRTLLayout = null;
        this.cacheRTLStatus();
    }

    /**
     * Cache RTL status and set up listener for direction changes
     */
    cacheRTLStatus() {
        this.isRTLLayout = this.isRTL();
        
        // Listen for potential direction changes (rare but possible)
        const observer = new MutationObserver(() => {
            const newRTLStatus = this.isRTL();
            if (newRTLStatus !== this.isRTLLayout) {
                this.isRTLLayout = newRTLStatus;
            }
        });
        
        observer.observe(document.documentElement, {
            attributes: true,
            attributeFilter: ['dir', 'class', 'style']
        });
    }

    /**
     * Detect if the document is using RTL (Right-to-Left) layout
     * Follows the same pattern as MenuAnimationController
     */
    isRTL() {
        const htmlDir = document.documentElement.dir?.toLowerCase();
        if (htmlDir) return htmlDir === 'rtl';
        
        const computedDirection = getComputedStyle(document.documentElement).direction;
        return computedDirection === 'rtl';
    }

    initialize() {
        if (!this.config.swipeToClose) return;

        document.addEventListener('touchstart', this.handleTouchStart.bind(this));
        document.addEventListener('touchend', this.handleTouchEnd.bind(this));
    }

    handleTouchStart(event) {
        if (!this.isMobileMenuOpen()) return;

        this.startX = event.touches[0].clientX;
        this.startY = event.touches[0].clientY;
    }

    handleTouchEnd(event) {
        if (!this.isMobileMenuOpen()) return;

        this.endX = event.changedTouches[0].clientX;
        this.endY = event.changedTouches[0].clientY;

        const diffX = this.endX - this.startX;
        const diffY = Math.abs(this.endY - this.startY);
        
        // RTL-aware swipe detection
        const isValidSwipe = this.isValidSwipeGesture(diffX, diffY);

        if (isValidSwipe && this.targetButton) {
            this.targetButton.click();
            this.targetButton = null;
        }
    }

    /**
     * Determine if the swipe gesture is valid based on layout direction
     * @param {number} diffX - Horizontal distance (positive = right, negative = left)
     * @param {number} diffY - Vertical distance (absolute value)
     * @returns {boolean} True if the swipe should trigger menu close
     */
    isValidSwipeGesture(diffX, diffY) {
        const swipeThreshold = 50;
        const verticalTolerance = 30;
        
        // Vertical movement must be within tolerance
        if (diffY >= verticalTolerance) return false;

        if (this.isRTLLayout) {
            // RTL: Accept right-to-left swipes (negative diffX)
            return diffX < -swipeThreshold;
        } else {
            // LTR: Accept left-to-right swipes (positive diffX) - existing behavior
            return diffX > swipeThreshold;
        }
    }

    isMobileMenuOpen() {
        return document.querySelector('.dwc-nest-menu')?.classList.contains('brx-open');
    }

    setTargetButton(button) {
        this.targetButton = button;
    }

    /**
     * Get current layout direction (for debugging)
     * @returns {string} 'rtl' or 'ltr'
     */
    getLayoutDirection() {
        return this.isRTLLayout ? 'rtl' : 'ltr';
    }
}

class OffcanvasMenuHandler {
    constructor(config) {
        this.config = config || {};
    }

    applyMobileStyles() {
        let offcanvasMenu = document.querySelector(this.config.offCanvasSelector);
        let hasHeaderPosition = ['brx-header-left', 'brx-header-right'].some(cls =>
            document.body.classList.contains(cls)
        );

        if (!offcanvasMenu && !hasHeaderPosition) return;

        let styleSheet = document.querySelector('[data-stylesheet]');
        if (!styleSheet) return;

        let styleElement = styleSheet.querySelector('style');
        if (!styleElement) return;

        let originalStyles = styleElement.textContent || styleElement.innerText;
        let modifiedStyles = originalStyles.replace(/\(max-width:\s*\d+px\)/g, '(max-width: 5000px)');

        let newStyleElement = document.createElement('style');
        newStyleElement.id = 'dwc-offcanvas-styles';
        newStyleElement.textContent = modifiedStyles;

        document.head.appendChild(newStyleElement);

        setTimeout(() => {
            document.body.classList.add('show-nav');
             document.body.classList.add('sidebar-ready');

        }, 100);

        styleSheet.remove();
    }
}



class MobileMenuScrollReset {
    constructor(config = {}) {
        this.config = {
            minWidthThreshold: config.minWidthThreshold || MegaMenuCONFIG.minWidth,
            headerSelector: config.headerSelector || MegaMenuCONFIG.headerSelector,
            scrollResetDelay: config.scrollResetDelay || 300
        };

        this.menuElement = null;
        this.nestedItemsElement = null;
        this.scrollResetTimeout = null;
        this.isInitialized = false;
    }

    initialize() {
        if (this.isInitialized) return;

        this.menuElement = document.querySelector(`${this.config.headerSelector} .dwc-nest-menu`);
        this.nestedItemsElement = document.querySelector(`${this.config.headerSelector} .brx-nav-nested-items`);

        if (!this.menuElement || !this.nestedItemsElement) {
            console.warn('Mobile menu scroll reset: Required elements not found');
            return;
        }

        this.setupMutationObserver();
        this.isInitialized = true;
    }

    setupMutationObserver() {
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
                    this.handleMenuClassChange();
                }
            });
        });

        observer.observe(this.menuElement, {
            attributes: true,
            attributeFilter: ['class']
        });
    }

    handleMenuClassChange() {
        // Only run on mobile
        if (!this.isMobile()) return;

        const isMenuOpen = this.menuElement.classList.contains('brx-open');

        // If menu is now closed, set timeout to reset scroll
        if (!isMenuOpen) {
            this.scheduleScrollReset();
        } else {
            // If menu is opened, cancel any pending scroll reset
            this.cancelScrollReset();
        }
    }

    scheduleScrollReset() {
        // Clear any existing timeout
        this.cancelScrollReset();

        // Set new timeout
        this.scrollResetTimeout = setTimeout(() => {
            this.resetScroll();
        }, this.config.scrollResetDelay);
    }

    cancelScrollReset() {
        if (this.scrollResetTimeout) {
            clearTimeout(this.scrollResetTimeout);
            this.scrollResetTimeout = null;
        }
    }

    resetScroll() {
        if (this.nestedItemsElement && this.isMobile()) {
            this.nestedItemsElement.scrollTop = 0;
        }
    }

    isMobile() {
        return window.innerWidth < this.config.minWidthThreshold;
    }

    // Method to reinitialize (useful for your reinitialize functionality)
    reinitialize() {
        this.cancelScrollReset();
        this.isInitialized = false;
        this.initialize();
    }
}


class MenuSystem {
    constructor(config = {}) {
        this.config = {
            minWidthThreshold: config.minWidthThreshold || MegaMenuCONFIG.minWidth,
            stripeStyle: config.stripeStyle ?? MegaMenuCONFIG.stripeStyle,
            adaptiveHeight: config.adaptiveHeight ?? MegaMenuCONFIG.adaptiveHeight,
            toolTip: config.toolTip ?? MegaMenuCONFIG.toolTip,
            swipeToClose: config.swipeToClose ?? MegaMenuCONFIG.swipeToClose,
            headerSelector: config.headerSelector || MegaMenuCONFIG.headerSelector,
            megaMenuLinksSelector: `${config.headerSelector || MegaMenuCONFIG.headerSelector} .brx-has-megamenu`,
            offCanvasSelector: `${config.headerSelector || MegaMenuCONFIG.headerSelector} .dwc-nest-menu[data-offcanvas="true"]`,
            shiftFactor: config.shiftFactor ?? MegaMenuCONFIG.shiftFactor,
            minOverflow: config.minOverflow ?? MegaMenuCONFIG.minOverflow
        };

        this.animationController = new MenuAnimationController(this.config);
        this.tooltipManager = new TooltipManager(this.config);
        this.swipeHandler = new SwipeGestureHandler(this.config);
        this.offcanvasHandler = new OffcanvasMenuHandler(this.config);
        this.centeredLogoController = new CenteredLogoController(this.config);
        this.mobileScrollReset = new MobileMenuScrollReset(this.config);

        // Flag to track if updateDropdownPositions has been called via user interaction
        this.hasUpdatedDropdowns = false;

        this.centeredLogoController.initializeEarly();
    }


    // New method to handle the DOMContentLoaded logic, replaces former menuSystem.initialize()
    setupMenu() {
        let overlay = document.querySelector('.dwc-nest-menu-overlay');
        if (!overlay) {
            overlay = document.createElement('nav-overlay');
            overlay.className = 'dwc-nest-menu-overlay';
            const overlayParent = document.querySelector('.dwc-nest-header__container');
            const header = document.querySelector('#brx-header');
            if (overlayParent && MegaMenuCONFIG.overlayInsideHeader) {
                overlayParent.parentNode.prepend(overlay, overlayParent);
            } else if (header) {
                header.parentNode.insertBefore(overlay, header);
            }
        }

     
        this.offcanvasHandler.applyMobileStyles();
        this.animationController.updateHeaderHeight();
        this.animationController.initializeMaxDimensions();
        this.animationController.setMobileMenuTopHeight();
        this.animationController.updateMobileLogo();
        this.animationController.setCurrentPageDropdownActive();
        this.tooltipManager.setBackText();
        this.tooltipManager.setupTooltipObserver();
        this.animationController.closeNavOnClick();
        this.centeredLogoController.initialize();
        this.mobileScrollReset.initialize();


        if (this.animationController.isAboveMinWidth()) {
            this.setupDesktopBehavior();
        } else {
            this.swipeHandler.initialize();
        }

        this.setupEventListeners();

        if (!this.animationController.isAboveMinWidth()) {
            this.animationController.resetForMobile();
        }

        setTimeout(() => {
            document.body.classList.add('show-nav');
            this.animationController.updateHeaderHeight();
        }, 0);

        setTimeout(() => {
            document.body.classList.add('adaptive-height-active');
            if (this.animationController.isAboveMinWidth()) {
                this.animationController.updateDropdownPositions();
                this.animationController.setBoxedWidthVariable();
            }
        }, 500);
    }

    // Original initialize method (unchanged) now calls the setupMenu()
    initialize() {
        updateMobileClass(this.config.minWidthThreshold);
        document.addEventListener('DOMContentLoaded', () => {
            this.setupMenu();
        });
        return this;
    }

    // Updated reinitialize method - to call: mainMenu.reinitialize();
    reinitialize() {
        // Reset critical states
        this.centeredLogoController.isInitialized = false;
        this.animationController.maxMenuWidth = 0;
        this.animationController.maxMenuHeight = 0;
        this.tooltipManager.tooltipProcessed = false;

        // Clear breakinto states ← ADD THIS
        const breakintoElements = document.querySelectorAll('[data-breakinto]');
        breakintoElements.forEach(element => {
            breakintoOriginalParents.delete(element);
            breakintoOriginalIndexes.delete(element);
            breakintoItemStates.delete(element);
            element.removeAttribute('data-breakinto-moved');
        });

        // Clear existing timeouts
        if (this.animationController.headerTimeoutId) {
            clearTimeout(this.animationController.headerTimeoutId);
        }
        if (this.animationController.mobileMenuTimeoutId) {
            clearTimeout(this.animationController.mobileMenuTimeoutId);
        }
        if (this.centeredLogoController.resizedFinished) {
            clearTimeout(this.centeredLogoController.resizedFinished);
        }

        // Remove added DOM elements and classes
        const overlay = document.querySelector('.dwc-nest-menu-overlay');
        if (overlay) overlay.remove();
        document.body.classList.remove('show-nav', 'adaptive-height-active', 'desktop-centered', 'dom-ready');
        this.tooltipManager.removeAllTooltips();
        const offcanvasStyles = document.querySelector('#dwc-offcanvas-styles');
        if (offcanvasStyles) offcanvasStyles.remove();

        // Reset mobile logo
        const mobileLogo = document.querySelector('.dwc-nest-menu__mobile-logo');
        if (mobileLogo) {
            const currentMobileLogo = mobileLogo.querySelector('img, svg');
            if (currentMobileLogo) currentMobileLogo.remove();
        }

        // Re-run setup
        updateMobileClass(this.config.minWidthThreshold);
        this.setupMenu();
        this.mobileScrollReset.reinitialize();
        console.log('Mega Menu Pro reinitialized...')
    }



    setupDesktopBehavior() {
        this.animationController.megaMenuLinks.forEach(link => {
            link.removeEventListener('mouseenter', this.handleMouseEnter);
            link.addEventListener('mouseenter', this.handleMouseEnter);
        });
    }

    handleMouseEnter = (event) => {
        this.animationController.updateChevronPosition(event.target);
        // Call updateDropdownPositions on mouseenter if not already called via interaction
        if (this.animationController.isAboveMinWidth() && !this.hasUpdatedDropdowns) {
            this.animationController.updateDropdownPositions();
            this.animationController.updateMenuVariables();
            this.hasUpdatedDropdowns = true;
        }
    };

    setupEventListeners() {
        let observer = new MutationObserver(mutations => {
            mutations.forEach(mutation => {
                if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
                    this.animationController.updateMenuVariables();
                }
            });
        });

        this.animationController.megaMenuLinks.forEach(link =>
            observer.observe(link, { attributes: true })
        );

        document.addEventListener('click', event => {
            let submenuToggle = event.target.closest('.brx-submenu-toggle, .dwc-tabbed-nav-list__li');
            if (submenuToggle) {
                setTimeout(() => {
                    let openButtons = document.querySelectorAll('.brxe-dropdown.open.active button, .dwc-tabbed-nav-list__li.active button');
                    let targetButton = Array.from(openButtons).find(button => {
                        let parentDropdown = button.closest('.brxe-dropdown.open.active, .dwc-tabbed-nav-list__li.active');
                        return parentDropdown &&
                            parentDropdown.tagName.toLowerCase() === 'li' &&
                            !parentDropdown.querySelector('.brxe-dropdown.open.active:not(:scope), .dwc-tabbed-nav-list__li.active:not(:scope)');
                    });

                    if (targetButton) {
                        this.swipeHandler.setTargetButton(targetButton);
                        if (this.config.toolTip) {
                            this.tooltipManager.removeAllTooltips();
                            this.tooltipManager.addTooltip(targetButton);
                            this.tooltipManager.updateTooltipDataText(targetButton);
                        }
                    }
                }, 50);
            }
        });

        window.addEventListener('resize', this.debounce(() => {
            updateMobileClass(this.config.minWidthThreshold);
            this.animationController.updateHeaderHeight();
            this.animationController.initializeMaxDimensions();
            this.animationController.setMobileMenuTopHeight();
            this.animationController.updateMobileLogo();
            this.animationController.closeNavOnClick();

            if (this.animationController.isAboveMinWidth()) {
                this.animationController.updateMenuVariables();
                this.animationController.initDesktopNav();
                this.setupDesktopBehavior();
                // Reset flag on resize to desktop and call updateDropdownPositions       
                this.hasUpdatedDropdowns = false;
                this.animationController.updateDropdownPositions();
            } else {
                this.animationController.resetForMobile();
                this.swipeHandler.initialize();
                // Reset flag on resize to mobile               
                this.hasUpdatedDropdowns = false;
            }
        }, 300));
    }

    debounce(func, delay) {
        let timeoutId;
        return function (...args) {
            clearTimeout(timeoutId);
            timeoutId = setTimeout(() => func.apply(this, args), delay);
        };
    }
}

const mainMenu = new MenuSystem().initialize();


// RECALCULATE DROPDOWN POSITION ON LAYOUT SHIFTS

const debouncedUpdate = mainMenu.debounce(() => {
    //console.log('updated')
    mainMenu.animationController.updateDropdownPositions();
    mainMenu.animationController.updateMenuVariables();

    if (!mainMenu.animationController.menuOpened) {
        mainMenu.animationController.header.style.setProperty('--dropdown-menu-width', '100px');
        // console.log('less')
    }

}, 300);



if (window.visualViewport) {
    window.visualViewport.addEventListener('resize', debouncedUpdate);
}




//==== HEADER INSTANCE EXPERIMENTAL ====
/*
const secondaryMenu = new MenuSystem({   
headerSelector: '.second.dwc-nest-header',
adaptiveHeight: 1,
stripeStyle: 0,
shiftFactor: 1.5,  // Example override
minOverflow: 300   // Example override
}).initialize();
*/


/* BREAKOUT LINK & BREAKIN FUNCTIONALITY */

// WeakMaps for breakinto feature state management
const breakintoOriginalParents = new WeakMap(); // Track original parents for breakinto items
const breakintoOriginalIndexes = new WeakMap(); // Track original child indexes for breakinto items  
const breakintoItemStates = new WeakMap(); // Track individual breakinto item states

// Use WeakMap for better garbage collection
const originalParents = new WeakMap();
const itemStates = new WeakMap(); // Track individual item states
const breakinOriginalParents = new WeakMap(); // Track original parents for breakin items
const breakinOriginalIndexes = new WeakMap(); // Track original child indexes for breakin items
const breakinItemStates = new WeakMap(); // Track individual breakin item states
let isMobileView = null;
let resizeTimer;
let breakinContainer = null;

function ensureBreakInContainer() {
    // Check if any breakin elements exist in the header first
    const hasBreakInElements = document.querySelector('#brx-header [data-breakin]');
    if (!hasBreakInElements) return null;

    // Select nav wrapper based on config
    const navWrapperSelector = MegaMenuCONFIG.breakinToNavList
        ? '.dwc-nest-menu .brx-nav-nested-items'
        : '.dwc-nav-wrapper';

    const navWrapper = document.querySelector(navWrapperSelector);
    if (!navWrapper) return null;

    if (!breakinContainer) {
        breakinContainer = navWrapper.querySelector('.breakin-container');
        if (!breakinContainer) {
            // Create element based on config
            breakinContainer = MegaMenuCONFIG.breakinToNavList
                ? document.createElement('li')
                : document.createElement('div');

            breakinContainer.className = 'breakin-container';
            navWrapper.appendChild(breakinContainer);
        }
    }

    return breakinContainer;
}

function handleBreakInItems() {
    const currentWidth = window.innerWidth;
    const container = ensureBreakInContainer();
    if (!container) return;

    // Get all breakin items from both original locations and breakin container
    const breakinItemsInOriginal = document.querySelectorAll('#brx-header [data-breakin]:not(.breakin-container [data-breakin])');
    const breakinItemsInContainer = container.querySelectorAll('[data-breakin]');

    // Combine both nodelets into a single array
    const breakinItems = [...breakinItemsInOriginal, ...breakinItemsInContainer];

    breakinItems.forEach(item => {
        const breakpointAttr = item.getAttribute('data-breakin');

        // Set default breakpoint if not defined or invalid
        let breakpoint;
        if (!breakpointAttr || breakpointAttr.trim() === '') {
            breakpoint = MegaMenuCONFIG.minWidth - 1;
        } else {
            breakpoint = parseInt(breakpointAttr, 10);
            if (isNaN(breakpoint)) {
                breakpoint = MegaMenuCONFIG.minWidth - 1;
            }
        }

        // Continue with your logic using the breakpoint value...

        // Determine if item should be in mobile state (moved into container)
        const shouldBeInContainer = currentWidth <= breakpoint;

        // Get current state of this breakin item
        const currentItemState = breakinItemStates.get(item);

        // Only process if this item's state changed
        if (currentItemState !== shouldBeInContainer) {
            breakinItemStates.set(item, shouldBeInContainer);

            if (shouldBeInContainer) {
                // Move to breakin container

                // Store original parent and index if not already stored
                if (!breakinOriginalParents.has(item)) {
                    const originalParent = item.parentElement;
                    const originalIndex = Array.from(originalParent.children).indexOf(item);
                    breakinOriginalParents.set(item, originalParent);
                    breakinOriginalIndexes.set(item, originalIndex);
                }

                // Move item to breakin container
                container.appendChild(item);

            } else {
                // Move back to original parent at original position
                const originalParent = breakinOriginalParents.get(item);
                const originalIndex = breakinOriginalIndexes.get(item);

                if (originalParent && originalIndex !== undefined) {
                    const children = originalParent.children;

                    if (originalIndex >= children.length) {
                        // Insert at the end if original index is beyond current children
                        originalParent.appendChild(item);
                    } else {
                        // Insert at the original position
                        originalParent.insertBefore(item, children[originalIndex]);
                    }
                }
            }
        }
    });
}

function handleBreakIntoItems() {
    const currentWidth = window.innerWidth;

    // Get all breakinto items from both original locations and target containers
    const breakintoItemsInOriginal = document.querySelectorAll('[data-breakinto]:not([data-breakinto=""])');
    const breakintoItemsInContainers = document.querySelectorAll('[data-breakinto-moved="true"]');

    // Combine both nodelets into a single array
    const breakintoItems = [...breakintoItemsInOriginal, ...breakintoItemsInContainers];

    breakintoItems.forEach(item => {
        const breakintoAttr = item.getAttribute('data-breakinto');

        // Skip if no breakinto attribute or empty value
        if (!breakintoAttr || breakintoAttr.trim() === '') {
            return;
        }

        // Parse the attribute value for container selector and optional breakpoint
        let containerSelector, customBreakpoint;

        if (breakintoAttr.includes('|')) {
            // Format: '.class | 767' or '#id | 1024'
            const parts = breakintoAttr.split('|').map(part => part.trim());
            containerSelector = parts[0];
            customBreakpoint = parseInt(parts[1], 10);

            // Validate custom breakpoint
            if (isNaN(customBreakpoint)) {
                console.warn(`Invalid breakpoint in data-breakinto="${breakintoAttr}". Using global breakpoint.`);
                customBreakpoint = null;
            }
        } else {
            // Format: '.class' or '#id'
            containerSelector = breakintoAttr.trim();
            customBreakpoint = null;
        }

        // Find the target container
        let targetContainer;
        try {
            targetContainer = document.querySelector(containerSelector);
        } catch (error) {
            console.error(`Invalid selector in data-breakinto="${breakintoAttr}":`, error);
            return;
        }

        if (!targetContainer) {
            console.warn(`Target container "${containerSelector}" not found for data-breakinto element.`);
            return;
        }

        // Determine breakpoint to use (custom or global)
        const breakpoint = customBreakpoint !== null ? customBreakpoint : MegaMenuCONFIG.minWidth;

        // Determine if item should be in target container (moved state)
        const shouldBeInContainer = currentWidth <= breakpoint;

        // Get current state of this breakinto item
        const currentItemState = breakintoItemStates.get(item);

        // Only process if this item's state changed
        if (currentItemState !== shouldBeInContainer) {
            breakintoItemStates.set(item, shouldBeInContainer);

            if (shouldBeInContainer) {
                // Move to target container

                // Store original parent and index if not already stored
                if (!breakintoOriginalParents.has(item)) {
                    const originalParent = item.parentElement;
                    const originalIndex = Array.from(originalParent.children).indexOf(item);
                    breakintoOriginalParents.set(item, originalParent);
                    breakintoOriginalIndexes.set(item, originalIndex);
                }

                // Mark item as moved and move to target container
                item.setAttribute('data-breakinto-moved', 'true');
                targetContainer.appendChild(item);

            } else {
                // Move back to original parent at original position
                const originalParent = breakintoOriginalParents.get(item);
                const originalIndex = breakintoOriginalIndexes.get(item);

                if (originalParent && originalIndex !== undefined) {
                    const children = originalParent.children;

                    // Remove the moved marker
                    item.removeAttribute('data-breakinto-moved');

                    if (originalIndex >= children.length) {
                        // Insert at the end if original index is beyond current children
                        originalParent.appendChild(item);
                    } else {
                        // Insert at the original position
                        originalParent.insertBefore(item, children[originalIndex]);
                    }
                }
            }
        }
    });
}

function handleResponsiveMenu() {
    const currentIsMobile = window.innerWidth < MegaMenuCONFIG.minWidth;
    const currentWidth = window.innerWidth;

    const nestMenu = document.querySelector('.dwc-nest-menu');
    if (!nestMenu) return;

    // Get all target items from both original locations and nest menu
    const targetItemsInOriginal = document.querySelectorAll('.brx-nav-nested-items > .menu-item > [data-breakout-link]');
    const targetItemsInNest = nestMenu.querySelectorAll('[data-breakout-link]');

    // Combine both nodelets into a single array
    const targetItems = [...targetItemsInOriginal, ...targetItemsInNest];
    let hasStateChange = false;

    targetItems.forEach(item => {

        if (item.closest('.dwc-header-logo-item')) return; // don't interfere with centerd logo item

        const parent = item.parentElement;
        const breakpointAttr = item.getAttribute('data-breakout-link');

        // Determine if item should be in mobile state
        let shouldBeMobile;

        if (!breakpointAttr || breakpointAttr.trim() === '') {
            // No custom breakpoint - use global mobile view logic
            shouldBeMobile = currentIsMobile;
        } else {
            // Custom breakpoint - check if within range
            const customBreakpoint = parseInt(breakpointAttr, 10);
            if (isNaN(customBreakpoint)) {
                // Invalid breakpoint value - fallback to global logic
                shouldBeMobile = currentIsMobile;
            } else {
                // Within custom range: between customBreakpoint and MegaMenuCONFIG.minWidth (exclusive)
                shouldBeMobile = currentWidth >= customBreakpoint && currentWidth < MegaMenuCONFIG.minWidth;
            }
        }

        // Get current state of this item
        const currentItemState = itemStates.get(item);

        // Only process if this item's state changed
        if (currentItemState !== shouldBeMobile) {
            hasStateChange = true;
            itemStates.set(item, shouldBeMobile);

            if (shouldBeMobile) {
                // Move to mobile state
                parent.classList.add('has-breakout-link');

                // Store original parent if not already stored
                if (!originalParents.has(item)) {
                    originalParents.set(item, parent);
                }

                // Move item to nest menu
                nestMenu.insertBefore(item, nestMenu.firstChild);

                // Hide the original parent
                parent.style.display = 'none';
            } else {
                // Move to desktop state - restore to original parent
                const originalParent = originalParents.get(item);
                if (originalParent) {
                    originalParent.appendChild(item);
                    originalParent.style.display = '';
                    originalParent.classList.remove('has-breakout-link');
                }
            }
        }
    });

    // Update global mobile view state only if there was a global state change
    if (isMobileView !== currentIsMobile) {
        isMobileView = currentIsMobile;
    }

    // Optional: You can add logic here if you need to do something when any state changes
    if (hasStateChange) {
        // Any additional logic when items change state
    }
}

function handleAllResponsiveElements() {
    handleResponsiveMenu(); // Handle breakout functionality
    handleBreakInItems();   // Handle breakin functionality
    handleBreakIntoItems(); // Handle breakinto functionality ← ADD THIS LINE
}

// Run on page load
handleAllResponsiveElements();

// Debounce resize events
window.addEventListener('resize', () => {
    clearTimeout(resizeTimer);
    resizeTimer = setTimeout(handleAllResponsiveElements, 150);
});

// Optional: Add for better initial load behavior
document.addEventListener('DOMContentLoaded', handleAllResponsiveElements);




// REINITIALIZE ON URL CHANGE
if (MegaMenuCONFIG.reinitializeOnURLchange) {
    console.log('on URL change active')
    function onUrlChange() {
        setTimeout(function () {
            mainMenu.reinitialize();
        }, 1500); // Delay execution by 1.5 seconds
    }

    // Listen for popstate event (history navigation)
    window.addEventListener('popstate', onUrlChange);

    // Listen for hashchange event (URL hash change)
    window.addEventListener('hashchange', onUrlChange);

    // Handle pushState and replaceState
    (function (history) {
        const pushState = history.pushState;
        const replaceState = history.replaceState;

        history.pushState = function (state) {
            const result = pushState.apply(history, arguments);
            onUrlChange(); // Call the function when pushState is used
            return result;
        };

        history.replaceState = function (state) {
            const result = replaceState.apply(history, arguments);
            onUrlChange(); // Call the function when replaceState is used
            return result;
        };
    })(window.history);
}

console.log('%c<Mega Menu Pro v1.4.2>', 'color: #b388eb');
/*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();

De beste zoekmachines voor Pentesters

Search engines voor pentesters zijn gespecialiseerde zoekmachines waarmee beveiligingsonderzoekers, ethical hackers en penetration testers informatie kunnen verzamelen over systemen, netwerken, applicaties en datalekken. Deze tools spelen een belangrijke rol binnen Open Source Intelligence (OSINT) en ondersteunen het in kaart brengen van potentiële kwetsbaarheden zonder directe interactie met het doelwit.

Deze zoekmachines zijn anders dan de bekende zoekmachines als Google of Bing. Ze zijn gebouwd voor specifieke doelen zoals:

  • Het ontdekken van openstaande poorten of kwetsbare services
  • Het analyseren van SSL-certificaten of misconfiguraties
  • Het zoeken naar gelekte e-mailadressen of API keys
  • Het verzamelen van threat intelligence over IP-ranges of domeinen
  • Het indexeren van broncode in publieke repositories

Deze tools maken gebruik van geavanceerde technieken zoals internet-wide scans, certificate transparency logs, passieve data-verzameling en deep packet inspection. Ze leveren waardevolle inzichten op die worden ingezet bij hacking-simulaties en Red Team-operaties.

Wat zijn search engines in cybersecurity?

Search engines in cybersecurity zijn platforms die grote hoeveelheden informatie verzamelen, analyseren en doorzoekbaar maken. Denk hierbij aan:

  • Servers die per ongeluk publiek beschikbaar zijn gesteld
  • Devices die via het internet benaderbaar zijn, zoals camera’s of routers
  • Domeinnamen gekoppeld aan specifieke infrastructuur
  • Publiek beschikbare code of configuratiebestanden

Het verschil met gewone zoekmachines zit in de inhoud en toegang. Terwijl Google vooral webpagina’s indexeert, richten deze cybersecurity tools zich op netwerkdata, infrastructuur en gevoelige metadata.

Waarom pentesters deze tools gebruiken

Pentesters zetten deze tools in om zonder directe aanval al veel informatie te verzamelen. Dat maakt ze waardevol voor onder andere:

  • Reconnaissance: het verkennen van een doelwit vóór actieve scans plaatsvinden
  • Attack Surface Mapping: inzicht krijgen in systemen en assets die publiekelijk beschikbaar zijn
  • Vulnerability Hunting: gericht zoeken naar foutieve configuraties of kwetsbare versies van software
  • Leak Detection: ontdekken van e-mailadressen, credentials of data die onbedoeld openbaar is

Deze manier van werken is efficiënt, minder opvallend en voorkomt dat het doelwit direct wordt benaderd of gewaarschuwd.

Verschil tussen OSINT, threat intelligence en server search

Er bestaan verschillende categorieën binnen de wereld van search engines voor pentesters. Elke tool richt zich op een eigen stuk van de informatiepuzzel:

  • OSINT-tools (zoals IntelX en Hunter.io): gericht op het verzamelen van openbare informatie uit diverse bronnen zoals sociale media, databases en pastebin-sites.
  • Threat Intelligence-tools (zoals GreyNoise en Pulsedive): leveren context over IP-adressen, malwarecampagnes en bekende aanvallen.
  • Server Search-tools (zoals Shodan, Censys en Onyphe): indexeren servers en devices wereldwijd en tonen kwetsbaarheden of foutieve configuraties.
  • Code Search-tools (zoals grep.app en Searchcode): zoeken naar publiek gedeelde broncode, API keys en configbestanden op platforms als GitHub.
  • Attack Surface Management-tools (zoals Netlas en FullHunt): bieden inzicht in het totale aanvalsoppervlak van een organisatie.

De overlap tussen deze categorieën is soms groot. Een pentester kiest afhankelijk van het doel de juiste combinatie van tools.

Rood en zwart pictogram van een schild met een hangslot in het midden, dat veiligheid of bescherming vertegenwoordigt.

1. Shodan.io (Server)

Shodan.io server search is een van de meest gebruikte tools binnen penetration testing. Deze zoekmachine scant continu het internet op apparaten en systemen die via publieke IP-adressen bereikbaar zijn. Denk aan routers, camera’s, industriële systemen, webservers en IoT-devices. De tool wordt vaak omschreven als de “search engine for the Internet of Things”.

Shodan is niet bedoeld om websites te indexeren, maar focust zich op technische details van apparaten: open poorten, bannerinformatie, gebruikte software en zelfs foutmeldingen. Voor pentesters is dit een krachtig middel om snel zicht te krijgen op kwetsbare systemen die per ongeluk of onwetend aan het internet hangen.

Wat is Shodan en hoe werkt het?

Shodan werkt op basis van een continu draaiend netwerk van scanners die poorten en services op het internet afspeuren. Deze informatie wordt opgeslagen in een doorzoekbare database.

De zoekmachine toont onder andere:

  • IP-adres en hostnaam
  • Land en stad van herkomst
  • Open poorten en gebruikte protocollen
  • Bannerinformatie van services zoals FTP, SSH, HTTP
  • Versienummers van software en gebruikte certificaten

Een eenvoudige zoekopdracht als port:21 country:NL levert alle FTP-servers in Nederland op die publiekelijk bereikbaar zijn.

Shodan maakt gebruik van filters zoals:

  • org: voor specifieke organisaties
  • hostname: voor bepaalde domeinen
  • os: om het besturingssysteem te detecteren
  • product: om gerichte softwareversies op te sporen

Voorbeelden van apparaten die je kunt vinden

Shodan onthult vaak apparaten die onbedoeld op het internet staan. Enkele veelvoorkomende voorbeelden:

  • Beveiligingscamera’s zonder wachtwoord of met standaard inlog
  • Industriële systemen (SCADA/ICS) die nooit direct toegankelijk horen te zijn
  • Printers en netwerkshares met gevoelige documenten
  • Databases zoals MongoDB of Elasticsearch zonder authenticatie
  • Remote desktopservices met verouderde versies

Veel van deze systemen zijn kwetsbaar voor exploits, vooral als ze draaien op oude firmware of slecht geconfigureerde firewalls.

Voordelen en risico’s van gebruik

Voordelen voor pentesters:

  • Snel overzicht van de attack surface van een organisatie
  • Detectie van shadow IT of ongepatchte systemen
  • Input voor rapportages en risico-inschatting
  • Passieve reconnaissance zonder directe interactie

Risico’s of aandachtspunten:

  • Shodan-gegevens kunnen verouderd zijn; bevestiging via actieve scans is nodig
  • Niet alles wat Shodan toont is daadwerkelijk kwetsbaar
  • Verkeerd gebruik of ongeautoriseerde scanning kan leiden tot juridische problemen
  • Sommige apparaten zijn expres publiek toegankelijk (denk aan honeypots)

Shodan in een pentest workflow

Shodan is vooral waardevol in de beginfase van een pentest: de reconnaissance-fase. Het helpt om doelwitten te selecteren, kwetsbare services te identificeren en prioriteiten te stellen.

Praktisch gebruik:

  • OSINT voorafgaand aan een test: Zoek publieke IP’s gekoppeld aan het domein van het doelwit
  • Identificatie van exposed assets: Zoals testservers of vergeten apparaten
  • Verificatie van configuraties: Check of beveiligingsmaatregelen zoals VPN-tunnels effectief zijn
  • Onderbouwing van bevindingen: Screenshots uit Shodan kunnen als bewijs dienen in rapportages

Daarnaast biedt Shodan een API die eenvoudig te integreren is in eigen scripts of tools. Hierdoor is geautomatiseerde analyse van grotere datasets mogelijk.

Een close up van een computerscherm met de interface van de inbox van gmail in de webbrowser safari, waarmee het belang van cyberbeveiliging tegen verschillende soorten cyberaanvallen wordt benadrukt.

2. Google.com (Dorks)

Google Dorks pentesting is een krachtige techniek waarbij geavanceerde zoekopdrachten worden gebruikt om gevoelige of slecht beveiligde informatie op websites te vinden via Google. Deze methode, ook wel Google Hacking genoemd, is verrassend effectief en vereist geen speciale tools. Alleen een browser en een goed begrip van de zoekoperators zijn genoeg om waardevolle data boven water te halen.

Voor pentesters is het een snelle en stille manier om kwetsbaarheden bloot te leggen, zoals open directory’s, config-bestanden, exposed API keys of inlogpagina’s van beheersystemen. Het grote voordeel: de dork-opdrachten maken gebruik van publieke data die al door Google is geïndexeerd, waardoor dit volledig passief is.

Wat zijn Google Dorks?

Google Dorks zijn zoekopdrachten die gebruikmaken van advanced search operators. Deze operators filteren de resultaten op basis van specifieke criteria zoals bestandstype, locatie op de website, of exacte woordencombinaties in URL’s of titels.

Voorbeelden van veelgebruikte operators:

  • site: beperkt de zoekopdracht tot een specifieke website of domein
  • filetype: zoekt naar bestanden met een bepaalde extensie, zoals PDF of .env
  • inurl: zoekt naar woorden in de URL, bijvoorbeeld admin of login
  • intitle: filtert op woorden in de paginatitel
  • intext: zoekt naar exacte woorden binnen de inhoud van de pagina

Combinaties van deze operators leveren krachtigere resultaten op. Een simpele dork als:

filetype:env intext:AWS_SECRET_ACCESS_KEY

kan direct inloggegevens voor cloudinfrastructuur opleveren.

Populaire dorking technieken

Er zijn duizenden dork-combinaties mogelijk, maar deze worden vaak toegepast door pentesters:

  • Directory listing detectie
    intitle:"index of" "backup"
    Zoekt naar open directory’s met mogelijk gevoelige back-upbestanden.
  • Open config-bestanden
    filetype:env OR filetype:ini inurl:config
    Spoort configuratiebestanden op met mogelijke wachtwoorden of tokens.
  • Exposed admin panels
    inurl:admin/login
    Helpt bij het vinden van toegankelijke beheerdersportalen.
  • SQL errors
    intext:"You have an error in your SQL syntax"
    Kan wijzen op onveilige query-verwerking en mogelijke SQL-injectie.
  • PDF documenten met login info
    filetype:pdf intext:"username" intext:"password"
    Spoort documenten op waarin per ongeluk inloggegevens zijn achtergelaten.

Voorbeelden van gevoelige informatie die je kunt vinden

Pentesters vinden via Google Dorks regelmatig:

  • Inloggegevens of API-sleutels in .env- of .xml-bestanden
  • Klantenlijsten of facturen in onbeveiligde Excel-bestanden
  • Back-upbestanden zoals .zip- of .sql-bestanden
  • Pagina’s met debug-informatie die interne IP-adressen onthullen
  • Inlogportalen van tools als phpMyAdmin, Jenkins of WordPress

Hoewel de data publiek is, betekent dit niet dat de eigenaar deze bewust heeft gedeeld. Vaak gaat het om verkeerde instellingen of vergeten directories die door Google zijn geïndexeerd.

Grenzen en legaliteit

Hoewel Google Dorking passief is, zijn er wel ethische en juridische grenzen. Belangrijke aandachtspunten:

  • Alleen gebruiken met toestemming
    Dorking op een organisatie zonder toestemming is onderdeel van ongeautoriseerde OSINT en kan als voorbereiding op een aanval worden gezien.
  • Geen data downloaden of verspreiden
    Het bekijken van een directory is anders dan het downloaden van vertrouwelijke documenten.
  • Houd je aan responsible disclosure
    Als je kwetsbaarheden vindt, meld deze via de juiste kanalen.

Voor pentesters binnen een legaal traject is Google Dorking een waardevolle OSINT-methode. Buiten die context kan het echter snel uitmonden in onwettig gedrag. Gebruik het dus altijd binnen de afgesproken scope.

Close-up van een laptopscherm met daarop cybersecuritytools in een gedetailleerd spreadsheet, compleet met verschillende gekleurde indicatoren en gegevenskolommen, tegen de achtergrond van een kantooromgeving.
Hacking.nl zei:

3. Wigle.net (WiFi Networks)

Wigle WiFi networks is een unieke OSINT-tool die wereldwijd draadloze netwerken in kaart brengt. Pentesters gebruiken Wigle om zicht te krijgen op WiFi-dekking, SSID-namen en locatie-informatie van netwerken — zonder ooit fysiek verbinding te maken met het netwerk zelf. De tool wordt vaak gebruikt in combinatie met wardriving en field tests, en vormt een waardevolle bron van locatiegebonden netwerkdata.

Wigle.net (Wireless Geographic Logging Engine) is vooral bekend bij beveiligingsonderzoekers, bug bounty hunters en hobbyisten. De database bevat miljoenen WiFi-netwerken die zijn verzameld via mobiele apps, GPS en scanners. Voor pentesting is dit ideaal om bijvoorbeeld:

  • Locaties van access points in kaart te brengen
  • SSID’s van doelorganisaties te identificeren
  • Netwerkconfiguraties te analyseren op naming patterns
  • Shadow IT of rogue access points te detecteren

Wat is Wigle.net?

Wigle.net is een openbare zoekmachine die wereldwijd draadloze netwerken verzamelt en indexeert. De gegevens zijn crowdsourced en worden verzameld via mobiele apps of apparaten met WiFi-scanning aan boord. Elke ingestuurde scan bevat:

  • SSID (netwerknaam)
  • MAC-adres van de access point
  • Locatie (GPS-coördinaten)
  • Encryptie-informatie (WEP, WPA, WPA2, open)
  • Signaalsterkte en kanaal

De zoekinterface maakt het mogelijk om gericht te zoeken op:

  • Specifieke SSID-namen
  • Locatiecoördinaten of geofences
  • Organisatienamen of naming patterns
  • Bepaalde beveiligingstypes zoals open netwerken

De data is passief verzameld: alleen het uitzenden van een SSID is genoeg om geregistreerd te worden.

Toepassingen voor pentesters

Wigle is vooral nuttig bij fysieke pentests en Red Team-operaties. Het biedt informatie die normaal gesproken alleen lokaal zichtbaar is, maar nu wereldwijd beschikbaar is via één platform.

Pentesters gebruiken Wigle onder andere voor:

  • Vooronderzoek bij fysieke toegangstests
    Door te zoeken naar de SSID’s van een doelwit kan worden vastgesteld op welke locaties het netwerk actief is.
  • Detectie van open netwerken
    Open WiFi-netwerken bij organisaties kunnen risico’s vormen, vooral als ze toegang bieden tot interne systemen.
  • Naming conventions analyseren
    SSID’s als “HR-Printer” of “Office-Cam” geven directe hints over de rol van het netwerk of apparaat.
  • Verificatie van rogue access points
    Door publieke SSID’s te vergelijken met lokale netwerken kan een rogue AP worden ontdekt.
  • Locatiebepaling bij OSINT-onderzoek
    Als een gelekte SSID of device-naam bekend is, kan Wigle helpen de fysieke locatie van dat netwerk te achterhalen.

WiFi privacy en risico’s

Hoewel Wigle alleen gegevens toont die netwerken zélf uitzenden, zijn er wel privacy-implicaties.

Risico’s die pentesters kunnen aantonen via Wigle:

  • Locatieherkenning van thuisnetwerken
    Unieke SSID’s zijn vaak aan één huishouden of kantoor te koppelen.
  • Open netwerken zonder wachtwoord
    Veel cafés of winkels hebben nog steeds onversleutelde WiFi, wat misbruik mogelijk maakt.
  • Naamgevingsfouten
    SSID’s die persoonsnamen, afdelingen of functies bevatten, leveren OSINT-voordelen op voor social engineering.
  • SSID-reuse
    Sommige bedrijven hergebruiken SSID’s op meerdere locaties, wat herleidbaarheid verhoogt.

Als onderdeel van een pentestrapport helpt Wigle bij het aantonen van blootgestelde WiFi-infrastructuur.

Praktisch gebruik in field tests

Wigle komt vooral tot zijn recht bij:

  • Physical Red Team assessments
  • Bug bounty reconnaissance rond hoofdkantoren
  • OSINT-analyses voor social engineering
  • Validatie van WiFi-segmentatiebeleid

De mobiele app kan onderweg SSID’s verzamelen. Deze data kan daarna offline worden geanalyseerd of geüpload naar de centrale Wigle-database.

Integratie met tools als Kismet of Aircrack-ng maakt het mogelijk om meer technische gegevens uit de omgeving te verzamelen, zoals beacon frames of clientverbindingen.

Een vintage beige computer met een CRT-monitor toont programmeercode op een terminal, wat de geest van een tijdperk kanaliseert waarin hacklegendes als Kevin Mitnick floreerden. Een toetsenbord en een deel van iemands hand hinten naar de geheime vaardigheden achter deze versleten, oude machine.

4. Intelx.io (OSINT)

IntelligenceX OSINT search is een geavanceerde zoekmachine waarmee pentesters toegang krijgen tot een breed scala aan openbare en gelekte informatie. De tool doorzoekt onder andere het dark web, paste-sites, historische domeingegevens en publieke lekdatabases. Waar Google stopt, begint IntelX.

Voor ethical hacking en OSINT-onderzoek is dit een krachtig hulpmiddel. Het stelt onderzoekers in staat om bijvoorbeeld gelekte e-mailadressen, documenten of domeinkoppelingen op te sporen — zonder op verdachte websites te hoeven rondkijken. De zoekresultaten worden gestructureerd weergegeven, inclusief metadata, waardoor analyses efficiënt en overzichtelijk blijven.

Wat IntelX biedt

IntelX verzamelt en indexeert data uit onder meer:

  • Paste-sites zoals Pastebin (en alternatieven)
  • Dark web forums en .onion-sites
  • Gedeelde documenten op publieke cloudopslag
  • Leaked credential databases (zoals combo lists)
  • WHOIS- en DNS-records
  • Publieke PGP-keys
  • Sociale media posts (beperkt)

Elke zoekopdracht levert niet alleen het resultaat op, maar ook context zoals herkomstbron, datum van ontdekking en gerelateerde entiteiten.

Wat IntelX onderscheidt van andere tools is de multi-source dekking gecombineerd met een krachtige zoektaal en een lange opslag van historische gegevens.

Data categorieën

IntelX categoriseert de zoekresultaten, wat gericht zoeken makkelijker maakt:

  • Identities – E-mailadressen, telefoonnummers, namen
  • Domains – Domeinnamen, subdomeinen, reverse lookups
  • Documents – PDF’s, Word-bestanden, spreadsheet-lekken
  • Leaked Credentials – Gebruikersnamen met wachtwoorden
  • Infrastructure – IP’s, ASN’s, DNS-records
  • Dark Web Sources – .onion-content en mirrorplatforms
  • PGP Data – Sleutels gekoppeld aan e-mailadressen

Zo kan een pentester met één zoekopdracht een volledig OSINT-profiel van een doelwit opbouwen, inclusief gelekte accounts, verbonden domeinen en gevoelige documenten.

Dark web en surface web zoeken

Een belangrijke kracht van IntelX is de brug tussen surface web en deep/dark web. Het doorzoekt automatisch mirrors van dark web bronnen. Hierdoor:

  • Is geen TOR-browser nodig
    Alle data wordt ontsloten via de veilige IntelX-interface
  • Worden .onion-links automatisch omgezet naar toegangbare content
  • Blijft het zoeken legaal en gecontroleerd, zolang men alleen observeert en niet deelneemt aan illegale handel

IntelX detecteert regelmatig accounts, API-sleutels en configbestanden die per ongeluk zijn gepubliceerd op paste-sites, of gelekt via data breaches.

Praktische pentest toepassingen

Pentesters zetten IntelX in voor uiteenlopende doelen:

  • Credential stuffing voorbereiden (legaal binnen scope)
    Door e-mailadressen en bekende wachtwoorden te vinden
  • Subdomeinen of testomgevingen ontdekken
    Via gelekte URLs of configuratiebestanden
  • Social engineering ondersteunen
    Door persoonlijke informatie uit paste-sites of dark web-forums te analyseren
  • Validatie van datalekken
    Controleren of een organisatie voorkomt in een bekende breach
  • Externe domeinkoppelingen controleren
    Domeinen die in het verleden gelinkt zijn aan een doelwit kunnen nu inactief maar nog steeds zichtbaar zijn

Let op: gebruik binnen de juiste juridische en ethische context blijft essentieel. IntelX biedt toegang tot gevoelige informatie, maar het raadplegen is geen overtreding zolang de data openbaar beschikbaar is gemaakt.

Een persoon in een hoodie zit achter een bureau, omringd door meerdere computerschermen waarop verschillende websites en software-interfaces worden weergegeven, waaronder hun YouTube-kanaal.

5. Searchcode.com (Codes Search)

Searchcode code search is een gespecialiseerde zoekmachine die miljoenen regels openbare broncode indexeert. Voor pentesters biedt dit platform een krachtige manier om gevoelige informatie zoals hardcoded wachtwoorden, API keys, tokens en interne URLs terug te vinden in repositories van ontwikkelaars wereldwijd.

In tegenstelling tot GitHub’s eigen zoekfunctie, focust Searchcode zich puur op doorzoekbaarheid van codefragmenten en werkt het vaak sneller en specifieker. Het ondersteunt ook reguliere expressies, wat het ideaal maakt voor het opsporen van patronen in code.

Waarom code search belangrijk is

Publiek gedeelde broncode is een onderschatte bron van informatie bij pentesting. Developers plaatsen regelmatig code op platforms als GitHub, Bitbucket of SourceForge zonder gevoelige info te verwijderen. Denk aan:

  • API keys of tokens in .env-bestanden
  • Database credentials in testcode
  • S3 buckets met verkeerde rechten
  • Debug endpoints die live staan
  • Exposed secrets in logging-bestanden

Searchcode maakt het mogelijk om gericht te zoeken op deze kwetsbaarheden over duizenden repositories, verspreid over meerdere hostingplatforms.

Zoeken naar secrets en API keys

Pentesters gebruiken vaak specifieke regex-opdrachten binnen Searchcode om secrets op te sporen. Voorbeelden van zoekpatronen:

  • apikey OR "api_key" AND "secret"
  • "AWS_SECRET_ACCESS_KEY"
  • file:.env AND password
  • github_token OR slack_token

Deze zoekopdrachten leiden regelmatig naar:

  • Geheime sleutels voor third-party services
    Zoals Stripe, Twilio, Slack of AWS
  • Toegangstokens voor CI/CD-tools
    Bijvoorbeeld Jenkins of GitLab runners
  • Productiegegevens in testcode
    Developers gebruiken soms echte data voor debuggen

Zodra deze data eenmaal openbaar is geworden via een repository, is het via Searchcode vindbaar — zelfs als het bestand later is verwijderd, zolang het gecrawld is.

Vergelijking met grep.app

Hoewel grep.app ook een krachtige code search engine is, verschillen beide tools in benadering:

AspectSearchcodeGrep.app
Regex ondersteuningJaJa
FocusMulti-repo searchVooral GitHub code
SnelheidIets trager bij veel hitsSneller
IndexeringsdiepteGroter bereik buiten GitHubFocus op GitHub
GebruiksgemakEenvoudige UI, filtersMinimalistische UI

Searchcode is dus interessanter voor bredere OSINT-analyses, terwijl grep.app sneller werkt voor GitHub-specifieke doelwitten.

Best practices

Bij het gebruik van Searchcode als pentester gelden er een paar slimme werkwijzen:

  • Beperk je zoekopdracht tot relevante domeinen of projectnamen
    Gebruik filters zoals inurl:companyname of project_name:.
  • Gebruik brede zoektermen en werk terug naar specifieke doelen
    Begin met password, ga daarna verfijnen op password=" en bestandsnamen.
  • Combineer gevonden data met andere OSINT-tools
    Gebruik gevonden tokens bijvoorbeeld in combinatie met Hunter.io of IntelX voor meer context.
  • Bewaar bewijs zorgvuldig (screenshots, timestamp, URL)
    Code die vandaag zichtbaar is, kan morgen verwijderd zijn.

Searchcode biedt ook een API voor integratie in eigen tools of pipelines. Voor geautomatiseerde OSINT-processen of grotere pentests is dit een groot voordeel.

Illustratie van laptops met waarschuwingssymbolen op schermen, die duiden op digitale beveiligingswaarschuwingen of mogelijke hackproblemen.

6. Leakix.net (Threat Intelligence)

Leakix leaked data search is een krachtige zoekmachine die zich richt op het detecteren van misconfiguraties en openstaande systemen die per ongeluk data lekken. Waar tools als Shodan vooral infrastructuur tonen, gaat Leakix een stap verder: het toont direct de inhoud van gelekte data, inclusief configuratiebestanden, logfiles en volledige database-inhoud. Voor pentesters is dit een goudmijn aan informatie.

Leakix combineert actieve scans met passieve detectie en monitort continue miljoenen hosts wereldwijd op publieke data-exposure. De focus ligt niet alleen op het vinden van systemen, maar op wat ze prijsgeven — van credentials tot interne documentatie.

Hoe Leakix werkt

Leakix scant op bekende poorten en services die vaak verkeerd zijn geconfigureerd. Denk aan:

  • Elasticsearch
    Veel organisaties laten Elasticsearch-instances draaien zonder authenticatie. Leakix detecteert en indexeert de inhoud direct.
  • MongoDB
    Open databases die onbedoeld publiek staan, inclusief volledige datacollecties.
  • Git-repositories
    .git-mappen op webservers die downloadbaar zijn, inclusief commitgeschiedenis.
  • SMB shares
    Netwerkshares die toegankelijk zijn zonder wachtwoord.
  • FTP en rsync-servers
    Met directory listing of anonieme toegang.

Zodra een systeem gevoelige inhoud prijsgeeft, wordt het door Leakix toegevoegd aan de zoekdatabase. Resultaten bevatten naast IP en poortinformatie ook een preview van de gelekte content.

Voorbeelden van gevonden data

De inhoud die Leakix toont is vaak schokkend door z’n gevoeligheid. Veelvoorkomende lekken:

  • .env-bestanden met API keys, mailconfiguratie en wachtwoorden
  • Database dumps in SQL-formaat
  • Backup-bestanden zoals .tar.gz of .bak
  • Configuratiebestanden van VPN’s, reverse proxies of Docker
  • PDF’s of tekstbestanden met interne instructies of credentials

Voor pentesters levert dit directe ingangen op, of waardevolle context die elders via brute force of exploitatie verzameld moet worden.

Integratie met pentests

Leakix wordt door pentesters vaak gebruikt in de reconnaissance-fase. Het biedt snel inzicht in zwakke plekken binnen een organisatie, zoals vergeten testomgevingen of fout geconfigureerde cloudservices.

Praktische toepassingen:

  • Verificatie van exposure
    Toont of bepaalde IP-ranges daadwerkelijk gevoelige info lekken.
  • Asset discovery
    Identificeert systemen die niet in het assetregister staan.
  • Validatie van gevonden credentials
    Combineer gevonden API keys met gevonden domeinen voor chaining-aanvallen.
  • Bewijs voor rapportage
    Screenshots van gelekte bestanden ondersteunen de impactanalyse.

Leakix kan via zoekfilters zoals IP-range, port, hostname of country worden gebruikt om gericht te zoeken binnen een specifieke scope.

Voorkomen van datalekken

Hoewel pentesters Leakix gebruiken om lekken aan te tonen, is het voor bedrijven ook een tool om zichzelf te monitoren. Wie regelmatig z’n eigen IP-ranges checkt in Leakix, kan voorkomen dat een misconfiguratie leidt tot reputatieschade of incidenten.

Aandachtspunten voor organisaties:

  • Beperk publieke toegang tot database-services
  • Gebruik firewalls en IP-whitelisting
  • Zet authenticatie aan op elk extern toegankelijke systeem
  • Scan regelmatig je eigen infrastructuur met tools als Leakix, Censys of Shodan
Een computerscherm geeft een rode waarschuwing weer over een kwaadaardig bestand, waarbij gebruikers worden gewaarschuwd voor mogelijke malware die apparaatschade of gegevensverlies kan veroorzaken, met opties om meer informatie te krijgen of het bestand niet uit te voeren.

7. Fullhunt.io (Attack Surface)

FullHunt attack surface is een platform dat zich richt op het volledig in kaart brengen van externe systemen, subdomeinen en kwetsbare assets van organisaties. Deze tool is ontworpen voor pentesters, Red Teams en bug bounty hunters die hun doelwit grondig willen analyseren voordat actieve exploitatie plaatsvindt.

Waar traditionele scanners focussen op individuele hosts, analyseert FullHunt de volledige digitale voetafdruk van een domein of organisatie. Het platform combineert OSINT, passieve analyse en live monitoring tot één interface.

Hoe FullHunt werkt

FullHunt verzamelt data uit verschillende bronnen en combineert deze met eigen scans. De focus ligt op:

  • Subdomain enumeration
    Het vinden van bekende én minder bekende subdomeinen met technieken zoals DNS brute forcing, certificate transparency logs en ASN-scans.
  • Asset fingerprinting
    Herkennen van gebruikte technologieën, versienummers en softwarestacks.
  • Vulnerability detection
    Matching van gevonden systemen tegen bekende kwetsbaarheden, zoals CVE’s en misconfiguraties.
  • Change monitoring
    Detecteren wanneer nieuwe assets worden toegevoegd of bestaande configuraties veranderen.

FullHunt is volledig passief, tenzij de gebruiker actief scans uitvoert via de ingebouwde modules. Voor pentesting is dit ideaal tijdens het stealth reconnaissance stadium.

Belang voor bug bounty hunters

Bug bounty researchers gebruiken FullHunt om kwetsbaarheden te vinden die buiten het formele scoperegister vallen, maar wel onderdeel zijn van het ecosysteem van het doelwit.

Veelvoorkomende vondsten:

  • Subdomeinen die vergeten zijn, maar nog live staan
  • Testomgevingen met minder beveiliging
  • Exposed dashboards zoals Kibana, Jenkins of Grafana
  • Verouderde CMS-installaties of bibliotheken
  • Assets met standaardwachtwoorden of misconfiguraties

FullHunt’s kracht zit in het automatiseren van deze discovery, waardoor pentesters niet alles handmatig hoeven te mappen.

Vulnerabilities in scope brengen

Door de attack surface goed in kaart te brengen, kunnen pentesters:

  • Systematisch alle blootgestelde assets testen
  • Shadow IT signaleren: systemen buiten beheer die toch live zijn
  • Herkennen welke assets binnen scope vallen van een test of bounty-programma
  • Externe risico’s koppelen aan interne processen of supply chain

Pentesters gebruiken FullHunt bijvoorbeeld als volgt:

  • Start met een root domein van het doelwit
  • Genereer de subdomeinenlijst
  • Filter op systemen met bekende kwetsbare software
  • Combineer deze info met een tool als Vulners of Shodan voor verdieping

Pentest voorbeelden

Typische scenario’s waarbij FullHunt waardevol is:

  • Subdomain takeover
    Niet-geclaimde subdomeinen gekoppeld aan derde partijen zoals GitHub Pages of Heroku.
  • Exposure van staging-omgevingen
    Subdomeinen zoals staging.domain.com met verouderde code of debug modes aan.
  • Outdated software
    Webapplicaties draaien op kwetsbare versies van WordPress, Drupal of Apache.
  • Identificatie van shadow-assets
    Domeinen die door een externe partij zijn geregistreerd maar naar de infrastructuur van het doel verwijzen.
Een smartphone met opstijgende rook geeft een tekstbericht weer. Een hangslotpictogram in een tekstballon duidt op een beveiligingsprobleem, wat de noodzaak van 2FA benadrukt. Digitale circuitbeelden omringen de telefoon, wat de kwetsbaarheid ervan benadrukt, ondanks dat deze veilig is tegen veelvoorkomende bedreigingen.

8. Urlscan.io (Threat Intelligence)

Urlscan threat analysis is een platform waarmee pentesters en beveiligingsonderzoekers websites en URL’s kunnen analyseren op verdacht gedrag, verborgen redirects, malafide scripts en connecties naar andere domeinen. De tool simuleert een bezoek aan een website, slaat de volledige interactie op, en geeft inzicht in de technische kenmerken van de pagina.

Pentesters gebruiken Urlscan.io voornamelijk voor het detecteren van phishingpagina’s, analyse van malafide domeinen of het onderzoeken van client-side kwetsbaarheden. De kracht ligt in de combinatie van statische en dynamische analyse van URL’s — zonder dat je zelf een verdachte site hoeft te bezoeken.

Hoe urlscan.io werkt

Wanneer een URL wordt gescand via Urlscan, voert het systeem de volgende acties uit:

  • Bezoekt de pagina via een sandboxed browser
  • Neemt screenshots van de interface
  • Analyseert alle netwerkverzoeken en third-party scripts
  • Bepaalt de domeinhistorie en DNS-resolutie
  • Detecteert JavaScript-libraries, trackingtools, externe links en meer

De output bevat gedetailleerde gegevens zoals:

  • HTTP headers
  • Geplaatste cookies
  • Aanroepen van API’s of command & control servers
  • Redirects naar andere domeinen
  • SSL-certificaatinformatie
  • Relaties met andere bekende scans of IOC’s

Detectie van phishing en malware

Pentesters en threat analysts zetten Urlscan.io vaak in om domeinen te controleren op phishing-indicatoren, zoals:

  • Domeinen met typofouten in merknamen (bijv. paypa1.com)
  • Loginpagina’s met identieke HTML-structuur als echte sites
  • SSL-certificaten van gratis aanbieders zoals Let’s Encrypt
  • Scripts die informatie wegschrijven naar verdachte externe adressen
  • Obfuscated JavaScript dat user input steelt

Dankzij het publieke karakter van veel scans, kan ook gezocht worden op termen zoals inurl:login of inbody:"Enter your password" om bestaande phishingpogingen te ontdekken.

Urlscan bevat bovendien een live feed van recente scans, handig voor real-time detectie.

Belang in incident response

In pentesting wordt Urlscan.io vaak gebruikt als onderdeel van post-exploitatie of als controletool binnen incident response. Denk aan scenario’s zoals:

  • Valideren of een link in een phishingmail actief is
  • Analyseren van command & control communicatie
  • Controleren of een gelekte URL nog live is
  • Onderzoeken welke externe domeinen of CDNs bij een site betrokken zijn

Bovendien kan het platform helpen bij threat attribution. Via de “relaties”-functie kun je zien of dezelfde infrastructuur wordt hergebruikt op meerdere verdachte sites.

Pentester scenario’s

Concrete toepassingen van Urlscan.io in pentests:

  • Controleren van uitgaande links op klantwebsites
    Externe JavaScript-hosts kunnen lekken of injecties veroorzaken.
  • Monitoren van phishing kits
    Domeinen met identieke HTML-structuren of hostingpatronen kunnen gelinkt worden aan phishing-kits.
  • In kaart brengen van supply chain risico’s
    Denk aan third-party scripts die vanaf externe domeinen worden geladen.
  • Validatie van scope en asset discovery
    Domeinen van een doelwit kunnen via historische scans en redirect chains teruggevonden worden, ook als ze niet meer in DNS zichtbaar zijn.
Illustratie van een laptop met een e-mailinterface, omringd door pictogrammen die beveiliging, SEO en zakelijke tools symboliseren.

9. Censys.io (Server)

Censys server search is een zoekmachine die de volledige openbare internetinfrastructuur in kaart brengt. Voor pentesters is dit een waardevol platform om inzicht te krijgen in open poorten, services, certificaten en kwetsbare softwareversies. Net als Shodan maakt Censys gebruik van internet-wide scanning, maar legt de nadruk op diepgang, consistentie en data-integriteit.

Censys combineert geavanceerde scanresultaten met slimme zoekfilters, waardoor kwetsbare servers, misconfiguraties en ongeautoriseerde systemen snel gevonden kunnen worden. De tool wordt veel gebruikt in red teaming, OSINT, threat intelligence en bug bounty werk.

Wat je met Censys kunt vinden

De kracht van Censys ligt in de combinatie van infrastructuurdata en beveiligingsinformatie. Pentesters kunnen onder andere zoeken naar:

  • Open poorten en services
    Zoals RDP, FTP, SSH, HTTP(S), SMTP
  • SSL-certificaten en metadata
    Domeinnamen, uitgevende CA, verloopdatum, wildcardgebruik
  • Besturingssystemen en bannerinformatie
    Versienummers van Apache, NGINX, OpenSSH, Exim enz.
  • DNS-data
    Reverse lookups, subdomeinen en PTR-records
  • Device fingerprinting
    Herkennen van systemen zoals firewalls, load balancers, IoT-apparaten

Met zoekopdrachten als services.service_name: "http" AND location.country: "NL" kun je direct alle webservers in Nederland opvragen.

Verschillen met Shodan

Hoewel Shodan en Censys beide server search engines zijn, verschillen ze op belangrijke punten:

AspectCensysShodan
FocusSecurity & certificatenBreed (ook IoT, camera’s)
API toegangMeer gericht op data-analyseMeer gericht op dashboardgebruik
ZoekprecisieFijnmazige query-structuurSnelle filtering
SSL-informatieDiepgaand & gestructureerdBeperkter
Academische oorsprongUniversiteit van MichiganCommercieel

Censys is bij uitstek geschikt voor pentesters die gericht willen zoeken naar kwetsbare systemen op basis van security-data en certificaten.

Certificaten en misconfiguraties

Een van de sterkste functies van Censys is het inzicht in SSL/TLS-certificaten en het opsporen van gerelateerde kwetsbaarheden:

  • Expired certificates
    Kunnen wijzen op verwaarloosde servers of testomgevingen
  • Self-signed certificates
    Onveilig voor productiegebruik en vaak niet goed geconfigureerd
  • Wildcard-certificaten
    Potentieel risico als ze op meerdere omgevingen tegelijk worden gebruikt
  • Certificaten die nog SHA-1 gebruiken
    Een zwakke hashfunctie die inmiddels als onveilig wordt beschouwd

Via certificate transparency logs worden ook subdomeinen zichtbaar die nergens anders vermeld staan. Zo vinden pentesters domeinen zoals dev.api.klantnaam.nl of vpn.klantnaam.nl — waardevolle ingangen voor verdere analyse.

Praktisch in pentesting

Censys past perfect in de OSINT- en discovery-fase van een pentest. Typische toepassingen:

  • Subdomeinen ontdekken via certificaten
    Door te zoeken op parsed.names: "*.doelwit.nl"
  • Verouderde softwareversies opsporen
    Zoals Apache 2.2 of Exim 4.89 die kwetsbaar zijn voor bekende exploits
  • Cross-referencing met andere tools
    Combineer Censys-data met Shodan, Leakix of FullHunt voor een completer beeld
  • Validatie van patchbeleid
    Controleer of servers recent gepatcht zijn of nog kwetsbare software draaien
  • Toewijzing van IP’s aan domeinen
    Handig bij multi-tenant hostingomgevingen

Censys biedt ook een krachtige API waarmee scans en analyses kunnen worden geautomatiseerd binnen CI/CD of pentest pipelines.

Een laptop op een rommelig bureau toont "Online Search", wat wijst op een hackpoging. Papieren zweven in de lucht eromheen, verlicht door een bureaulamp.

10. Onyphe.io (Server)

Onyphe server scanning is een veelzijdig platform voor passieve en actieve infrastructuurdata. De tool biedt inzicht in miljoenen apparaten, services en systemen die direct bereikbaar zijn via het internet. Voor pentesters is Onyphe vooral interessant door de combinatie van zoekfunctionaliteit, API-toegang en een rijke dataset aan server- en threat intelligence-informatie.

Waar Shodan en Censys vaak worden gezien als de standaard, positioneert Onyphe zich als een aanvulling met een bredere focus op cyberdefensie, passive reconnaissance en kwetsbare infrastructuurdetectie.

Functies van Onyphe

Onyphe werkt met een combinatie van:

  • Passieve sensordata (zoals honeypots en threat feeds)
  • Actieve scans van services, poorten en IP’s
  • Open data scraping (zoals pastebin, dark web, leaks)

Voor pentesters zijn vooral de volgende datatypes interessant:

  • Inet: resultaten van internet-wide scans (zoals banners en headers)
  • Pastries: geparse JSON-resultaten van services
  • Attacks: threat intel afkomstig van honeypots
  • Datascan: openbare bronnen met gelekte gegevens
  • Certificates: TLS-data vergelijkbaar met crt.sh
  • Geolocatie en ASN: contextuele informatie over infrastructuur

Via de webinterface of API kunnen zoekopdrachten worden opgebouwd met filters zoals:

  • ip:185.20.56.1
  • domain:klantnaam.nl
  • category:ssh
  • port:443 AND tls:true
  • geoloc:NL AND tag:webserver

Dit maakt het mogelijk om gericht op infrastructuur, kwetsbare services of metadata te zoeken.

Server data en API’s

De kracht van Onyphe zit in de manier waarop het data presenteert. De inet-categorie bijvoorbeeld toont direct:

  • Open poorten
  • Service banners
  • Hostnamen
  • Tijdstempels van laatste detectie
  • TLS-informatie (certificaat, issuer, SAN’s)
  • Geolocatie van de server

Daarnaast biedt Onyphe een RESTful API waarmee pentesters de gegevens kunnen automatiseren in hun recon workflows. Enkele praktische endpoints:

  • api.onyphe.io/summary/ip/<ip> – samenvatting per IP-adres
  • api.onyphe.io/search/data/<query> – uitgebreide query’s op datasets
  • api.onyphe.io/scan/port/<ip> – portscanresultaten van targets
  • api.onyphe.io/export/... – bulk exports voor analyse in eigen SIEM

De API is stabiel, goed gedocumenteerd en ideaal voor automatisering in grotere pentestprojecten.

Praktische scenario’s

Pentesters gebruiken Onyphe in meerdere contexten:

  • Verzamelen van contextinformatie over doel-IP’s
    Bijvoorbeeld: welk besturingssysteem draait er, welke services zijn actief?
  • Validatie van cloudconfiguraties
    Zijn er systemen met open poorten die in AWS, Azure of GCP draaien?
  • Opsporen van vergeten of verouderde servers
    Door te filteren op specifieke versies of servertypes
  • TLS-certificaatanalyse
    Wat zijn de uitgiftepatronen, zijn er wildcardcertificaten actief?
  • Correlatie van IP’s en domeinen
    Zijn er onbekende subdomeinen die aan dezelfde infrastructuur gekoppeld zijn?
  • Threat hunting
    Detectie van IP’s die in aanvalscampagnes voorkomen (via de attacks-feed)

Voor een pentester is dit een goudmijn aan contextuele data, zonder dat het doelwit direct wordt benaderd.

Integratie met andere tools

Onyphe werkt uitstekend in combinatie met andere search engines:

  • Combineer met crt.sh of Censys om via certificaten servers te koppelen
  • Gebruik samen met Shodan om te valideren welke poorten recent zijn gedetecteerd
  • Voer een reverse DNS-koppeling uit om domeinen te herleiden uit IP’s
  • Link threat data aan OSINT-tools zoals Pulsedive of GreyNoise

Ook tools als Maltego en Recon-ng ondersteunen integratie met Onyphe via modules of custom scripts, wat het inzetbaar maakt in grotere security workflows.

Voorbeeld uit een pentest

Tijdens een pentest op een fintech-platform werd via Onyphe een IP gevonden dat volgens DNS niet meer actief was. Toch bleek uit de inet-feed dat het IP recent op poort 8080 een open Tomcat-service toonde, inclusief serverheader. De pastries-output toonde zelfs een foutpagina met versienummer en een configuratiepad. Via een simpele GET-request werd toegang verkregen tot de Tomcat Manager — zonder inlog. Deze toegang leidde tot remote code execution. Geen directe aanval nodig: de volledige route begon met passieve data uit Onyphe.

Dit toont aan hoe effectief passieve serverinformatie kan zijn in hacking-scenario’s waarbij stealth en informatievoorsprong cruciaal zijn.

Voordelen voor pentesters

  • Volledig stealth – geen directe interactie met doelwit
  • Rijke metadata – combineerbare velden voor diepgaande analyse
  • Real-time feeds – recente scanresultaten en aanvalsinformatie
  • API-koppeling – schaalbaar voor automation en Red Team workflows
  • Veelzijdigheid – infrastructuur, leaks, threats, en certificates in één platform

Waarom kiezen voor Onyphe

In tegenstelling tot Shodan en Censys, biedt Onyphe:

  • Meer focus op dreigingsdata (honeypots, malware-IP’s)
  • Diepere API-mogelijkheden met specifieke datasets
  • Betere tijdslijnen van detecties per IP of domein
  • Directe JSON-resultaten met context per observatie

Het is dus geen vervanging, maar een aanvulling — vooral wanneer scope, stealth en integratie centraal staan.

Close-up van een computermonitor met een keuzemenu met opties voor videoresoluties, gericht op "1080p full hd", potentieel kwetsbaar voor cyberbedreigingen.

11. Socradar.io (Threat Intelligence)

Socradar threat intelligence is een geïntegreerd platform dat organisaties helpt bij het monitoren van cyberdreigingen, externe risico’s en datalekken. Voor pentesters is SocRadar een waardevolle bron van informatie, vooral in de voorbereidende fase van een test waarbij het draait om inzicht in wat er al over het doelwit bekend is op internet, het dark web en andere dreigingsbronnen.

Socradar combineert data uit open bronnen, commerciële feeds, domeindata, social media en dark web-monitoring. De interface is ontworpen om snel verbanden te leggen tussen gelekte data, aanvalsvectoren en kwetsbare assets. Voor hacking-simulaties is het een efficiënte manier om risico’s te visualiseren.

Wat SocRadar biedt

Socradar is opgebouwd uit meerdere modules, waarvan de belangrijkste voor pentesters zijn:

  • Threat Intelligence
    Realtime dreigingsinformatie over malwarecampagnes, phishingdomeinen, command & control infrastructuur en kwetsbaarheden.
  • Digital Risk Protection (DRP)
    Detectie van domeinimitaties, credential leaks, brand abuse en illegale marktplaatsactiviteit.
  • Attack Surface Management (ASM)
    Inzicht in exposed IT-assets, zoals subdomeinen, API-endpoints, cloudservices en open poorten.
  • Dark Web Monitoring
    Doorzoekbare database van posts op dark web forums, marktplaatsen en leaksites.
  • Threat Feed Integratie
    Mogelijkheid om threat data automatisch door te sturen naar SIEM- of SoC-platforms via API’s.

De kracht van SocRadar zit in het combineren van externe informatiebronnen met inzichten die specifiek toepasbaar zijn op een organisatie of domein.

Data categorieën en dashboards

Binnen SocRadar worden gegevens gestructureerd in duidelijke categorieën. Voor pentesters biedt dit overzicht in risico’s per type data:

  • Credential Leaks – Gebruikersnamen en wachtwoorden uit breaches, vaak inclusief bron en datum
  • Leaked Documents – Interne handleidingen, contracten of spreadsheets op paste-sites of cloudopslag
  • Brand Monitoring – Misbruik van merknamen in phishing, apps of valse social media accounts
  • Domain Intelligence – Nieuw geregistreerde domeinen die lijken op het hoofddomein (bijv. klantnamm.nl)
  • Infrastructure Exposure – Gevonden IP’s, poorten, services en softwareversies van externe assets

De dashboards zijn interactief en filterbaar per impactscore, detectiedatum of dreigingscategorie.

Threat feeds integreren

Socradar biedt directe koppelingen met veelgebruikte securityplatforms zoals:

  • Splunk
  • QRadar
  • Azure Sentinel
  • Elastic SIEM
  • MISP

Voor pentesters met geautomatiseerde pipelines of integraties in hun eigen tooling, is dit handig om real-time alerts te koppelen aan specifieke scenario’s of scopelijsten. Denk aan:

  • Automatisch detecteren van subdomeinen die zijn toegevoegd
  • Notificaties bij gelekte credentials gekoppeld aan testdomeinen
  • Alerts wanneer phishingdomeinen live gaan die lijken op het doelwit

Deze real-time integraties versnellen de workflow en maken het eenvoudiger om directe actie te ondernemen.

Pentester toepassingen

Socradar kan op verschillende manieren worden ingezet tijdens een pentest:

  • Pre-scan risicoanalyse
    Voordat technische scans worden uitgevoerd, kan SocRadar inzicht geven in bestaande lekken, exposed assets en bekende kwetsbaarheden.
  • Social engineering voorbereiding
    Door gelekte e-mailadressen, documenten of persoonlijke info te analyseren.
  • Validatie van shadow IT
    Assets of domeinen die buiten het beheer van de organisatie vallen, maar wel zichtbaar zijn in SocRadar.
  • Opsporen van merkimitatie
    Domeinen als klant-support.com kunnen gebruikt worden in phishing en worden via SocRadar snel geïdentificeerd.
  • Dark web bevestiging
    Als tijdens de pentest credentials worden gevonden, kan SocRadar helpen te achterhalen of deze al eerder op het dark web zijn gedeeld.

Waarom SocRadar anders is dan traditionele threat intel feeds

In tegenstelling tot platte IOC-lijsten, biedt SocRadar context, visuele inzichten en gekoppelde relaties. Je ziet bijvoorbeeld:

  • Welke gelekte credentials bij welke service hoorden
  • Of een gelekte e-mail ook voorkomt in phishingcampagnes
  • Wanneer een asset voor het eerst werd ontdekt én wanneer die live ging
  • Of meerdere threats onderdeel zijn van één georganiseerde aanvalscampagne

Deze koppeling maakt het verschil tussen simpelweg iets “vinden” en het volledig kunnen onderbouwen van de impact tijdens een pentest.

Database

12. Grep.app (Codes Search)

grep.app code search is een gespecialiseerde zoekmachine waarmee pentesters razendsnel door miljoenen regels openbare broncode kunnen zoeken. De tool is geoptimaliseerd voor snelheid, precisie en ondersteuning van reguliere expressies (regex), wat het een krachtig wapen maakt voor iedereen die op zoek is naar kwetsbaarheden of gelekte gegevens in code.

Waar platformen als GitHub zoeken beperken of rate limits hanteren, biedt grep.app een directe en ongefilterde manier om kwetsbare patronen, configuratiebestanden of hardcoded credentials te vinden. Deze vorm van OSINT is stil, effectief en vaak verrassend productief.

Zoeken in miljoenen codebases

grep.app indexeert een enorme hoeveelheid open source code van platforms zoals:

  • GitHub (public repositories)
  • GitLab (public)
  • Bitbucket
  • SourceForge
  • Andere codehostingsites met publieke toegang

De index wordt continu bijgewerkt en bevat tientallen miljoenen bestanden in tientallen programmeertalen, waaronder Python, JavaScript, Java, Go, PHP, Ruby, Bash en meer.

De interface laat je zoeken met:

  • Simpele keywords (password, apiKey, jwt)
  • Bestandsfilters (filename:.env)
  • Regex-patterns ((?i)password\s*=\s*['"].+['"])
  • Path- of folderfilters (path:config/)

De zoekresultaten zijn gesorteerd per repository, bestand en regelnummer — met highlight van de match.

Hoe grep.app helpt bij vulnerability hunting

grep.app wordt in pentesting vooral gebruikt voor:

  • Secrets detection
    API-sleutels, toegangstokens, databasewachtwoorden en andere gevoelige waarden die hardcoded zijn
  • Misconfiguraties
    .env-bestanden in verkeerde paden, debugmodus aan, logging naar externe domeinen
  • Outdated of kwetsbare codepatronen
    Gebruik van verouderde hashing (MD5), SQL-injectiegevoelige queries, onbeveiligde auth-mechanismen
  • Tokenleaks via logging
    console.log(jwt) of print(password)-statements in productiecode
  • Zoek naar kwetsbare third-party libraries
    In combinatie met package-bestanden zoals package.json of requirements.txt

Pentesters combineren deze inzichten vaak met gevonden subdomeinen of repositories die gelinkt zijn aan het doelwit.

Voorbeelden van misconfiguraties

grep.app levert regelmatig gevoelige bestanden op zoals:

  • .env met AWS credentials
    Vaak met AWS_ACCESS_KEY_ID en AWS_SECRET_ACCESS_KEY
  • config.php met hardcoded databasewachtwoorden
    Bijvoorbeeld: $db_password = "root123"
  • firebase.json met open toegang tot database
    Geen regels voor toegangsbeheer aanwezig
  • settings.py in Django-projecten met DEBUG = True
    In combinatie met productie-URL’s: een potentieel aanvalspunt
  • .npmrc of .pypirc met tokens voor private repositories
    Hiermee kan een aanvaller packages downloaden of zelfs pushen

Alternatieven en combinaties

grep.app wordt vaak naast andere codezoektools gebruikt voor maximale dekking:

ToolFocusSnelheidGitHub-only?
grep.appRegex en brede dekkingHoogNee
SearchcodeMulti-platform, metadataGemiddeldNee
PublicWWWWebsite source code & JS libsSnelNee
GitHub Code SearchNative in GitHubBeperktJa

Combinaties maken het mogelijk om zowel in live websites als in ontwikkelomgevingen te zoeken naar kwetsbare code.

Best practices voor pentesters

Om grep.app effectief in te zetten, hanteren ervaren pentesters deze aanpak:

  • Start met algemene patterns
    Zoek op password, api_key, secret, en refineer op context
  • Gebruik regex voor precisie
    Bijvoorbeeld: (?i)token\s*[:=]\s*['"].+['"]
  • Beperk op bestandsnamen of paths
    filename:.env of path:secrets/
  • Koppel gevonden data aan doelwitdomeinen
    Check of de eigenaar van de repository overeenkomt met de organisatie
  • Gebruik gevonden credentials in chaining
    Combineer met Hunter.io of IntelX om accounts en toegangspunten te testen

grep.app is volledig passief in gebruik: er worden geen aanvragen gedaan naar de originele systemen of repositories, wat het zeer geschikt maakt voor stealth reconnaissance.

Pentestvoorbeeld: van code naar toegang

Tijdens een pentest op een SaaS-leverancier werd via grep.app een .env-bestand gevonden in een oude GitHub-repository. De variabelen bevatten AWS-sleutels die nog steeds actief waren. Door deze sleutels te combineren met permissies in AWS IAM, kreeg de pentester toegang tot een S3-bucket met klantgegevens en interne documentatie. De volledige aanval vond plaats zonder enige actieve scan — puur op basis van OSINT en code search.

Dit soort scenario’s komt vaak voor bij organisaties die geen goed beleid voeren op source code hygiene. Hacking begint vaak niet met een exploit, maar met een stukje vergeten code op het openbare web.

Close-up van een computerscherm met een gedetailleerde spreadsheetinterface met verschillende gegevensvelden en numerieke invoer, waarmee cybersecuritytools naadloos zijn geïntegreerd voor verbeterde gegevensbescherming.

13. BinaryEdge.io (Attack Surface)

BinaryEdge attack surface is een platform dat de externe IT-infrastructuur van organisaties in kaart brengt. Door wereldwijde internet-scans te combineren met threat intelligence en asset discovery, geeft BinaryEdge pentesters gedetailleerd inzicht in welke systemen publiekelijk bereikbaar zijn — en mogelijk kwetsbaar.

In tegenstelling tot tools die zich beperken tot IP-informatie of domeinanalyses, focust BinaryEdge op het totaalplaatje: services, poorten, versies, SSL-informatie, banners en kwetsbaarheden. Het is bij uitstek geschikt voor de reconnaissance-fase van een pentest of Red Team-operatie, waarbij zichtbaarheid en bereikbaarheid centraal staan.

BinaryEdge als attack surface tool

BinaryEdge scant actief het hele IPv4-adresbereik van het internet. Dit gebeurt continu, met behulp van eigen scaninfrastructuur. De resultaten worden verwerkt in een doorzoekbare database en visueel gepresenteerd op dashboards.

Pentesters kunnen zoeken op:

  • IP-adres of range
  • Domeinnaam of subdomeinen
  • Organisatienaam (op basis van ASN of certificaten)
  • Exposed services (zoals RDP, FTP, Elasticsearch, SMB)
  • Open poorten en servicebanners
  • CVE-koppelingen op basis van versiedetectie

De tool biedt context bij elke gevonden asset, inclusief timestamp van de scan, locatie, en potentiële kwetsbaarheden.

Verschillen met threat intel functie

BinaryEdge heeft zowel een attack surface functie als een threat intelligence functie. Voor pentesters ligt de focus vooral op de eerste.

FunctieDoel
Attack SurfaceWat is er extern bereikbaar?
Threat IntelligenceIs een asset betrokken bij malafide activiteit?

Binnen een pentest is vooral de exposure-analyse waardevol. Threat intel kan aanvullend gebruikt worden om te bepalen of een asset al geassocieerd is met verdachte netwerken of botnets.

Use cases in pentesting

Pentesters gebruiken BinaryEdge voor uiteenlopende scenario’s:

  • Identificatie van shadow IT
    IP’s en servers die buiten het bekende assetregister vallen, maar nog wel live zijn.
  • Detectie van test- of stagingservers
    Vaak minder goed beveiligd en draaien op verouderde software.
  • Exposed services zonder authenticatie
    Denk aan open MongoDB’s, Elasticsearch-instances, Jenkins-servers of VNC zonder wachtwoord.
  • Kwetsbare versies van software herkennen
    Zoals oude Exchange-servers, verouderde webserverversies of open proxies.
  • Informatie voor social engineering
    Banners met bedrijfsnamen, e-mailadressen of medewerkersinformatie die zichtbaar zijn via metadata.

BinaryEdge helpt om snel een volledig overzicht te krijgen van alle aanvalsoppervlakken. Dit bespaart tijd en voorkomt dat assets over het hoofd worden gezien.

Voorbeelden van kwetsbare assets

Tijdens een pentest is het niet ongebruikelijk om de volgende blootgestelde systemen via BinaryEdge te ontdekken:

  • Webservers met verouderde PHP-versies
    Kwetsbaar voor remote code execution
  • VPN’s zonder MFA
    Potentieel toegangspunt bij credential reuse
  • Onbeveiligde Redis- of Memcached-servers
    Direct misbruikbaar voor data-exfiltratie of DDoS-aanvallen
  • Routers met standaardwachtwoorden
    Vooral bij kleine vestigingen of thuiskantoren
  • Cloud storage buckets met foute permissies
    Zoals open S3-buckets of Azure blob containers

BinaryEdge laat ook zien wanneer een asset voor het laatst gescand is en of deze nog steeds online is. Hierdoor kunnen pentesters bepalen of een kwetsbaarheid actueel is.

Integratie met andere tools

BinaryEdge wordt vaak gecombineerd met andere tools voor verdieping of validatie:

  • FullHunt – voor subdomein discovery en attack surface mapping
  • Shodan – vergelijkbare data, maar met meer focus op devices
  • Censys – voor SSL-certificaatanalyse en subdomeinen
  • Leakix – om te controleren of exposed services ook daadwerkelijk data lekken

Daarnaast biedt BinaryEdge een krachtige API die makkelijk integreert in scripts of dashboards. Pentesters kunnen hiermee eigen tooling ontwikkelen voor automatische asset monitoring.

Voorbeeld: van scan naar impact

Tijdens een pentest voor een softwarebedrijf werd via BinaryEdge een vergeten stagingserver ontdekt onder een subdomein dat niet meer in DNS zichtbaar was. De server draaide een oude versie van WordPress met bekende kwetsbaarheden en gaf toegang tot een interne testomgeving. Via deze toegang werd een plugin geüpload met reverse shell-functionaliteit, waarmee laterale beweging naar het interne netwerk mogelijk werd. Dit scenario begon met passieve analyse — geen directe interactie — en leidde tot volledige toegang tot gevoelige systemen.

Dit soort hacking-scenario’s toont het belang van goede asset discovery, iets waar BinaryEdge in uitblinkt.

Image 11

14. Fofa.info (Threat Intelligence)

Fofa.info search engine is een Chinese threat intelligence- en infrastructuurzoekmachine die veel overeenkomsten vertoont met Shodan en Censys, maar vaak andere datasets en methodes gebruikt. Voor pentesters is het een waardevolle aanvulling op bekende tools, juist omdat Fofa regelmatig apparaten, IP-ranges en kwetsbaarheden indexeert die elders niet (of later) zichtbaar zijn.

Fofa scant net als Shodan het hele publieke internet en verzamelt metadata van servers, apparaten en services. De interface biedt krachtige zoekmogelijkheden en ondersteunt geavanceerde filters. De tool is vooral populair bij onderzoekers, Red Teams en hackers die dieper willen graven in infrastructuur- en exposuregegevens — inclusief assets binnen Chinese netwerken of buiten het bereik van westerse scanplatforms.

Wat Fofa uniek maakt

Wat Fofa onderscheidt van andere tools:

  • Andere scanfrequentie en methodologie
    Fofa gebruikt alternatieve detectieprotocollen en poorten, waardoor soms andere resultaten verschijnen dan bij Shodan of Censys.
  • Chinese focus en datadekking
    Meer zicht op Aziatische infrastructuur en netwerken die slecht vertegenwoordigd zijn in westerse tools.
  • Interface met Chinese zoektermen
    Hoewel dit een drempel vormt, biedt het juist waardevolle inzichten voor pentesters die wereldwijd opereren.
  • Relatieanalyse
    Mogelijkheid om verbanden te leggen tussen IP’s, domeinen, certificaten en services binnen infrastructuren.
  • Groot volume aan indexed data
    Met meer dan 100 miljard records is het een van de grootste datasets wereldwijd voor infrastructuur-OSINT.

Data die beschikbaar is

Via Fofa kunnen pentesters de volgende informatie achterhalen:

  • IP-adressen met geopende poorten en services
  • Bannerinformatie van webservers, FTP, SSH, RDP en IoT-apparaten
  • SSL-certificaatdata (issuer, CN, domeinen)
  • HTTP-response headers en statuscodes
  • Lokalisatie van systemen (land, stad, ASN)
  • Domeinassociaties via TLS en HTTP-hostnamen
  • Exposed devices: SCADA-systemen, camera’s, NAS, routers

Net als bij Shodan kan een simpele zoekopdracht zoals port="21" && country="US" duizenden FTP-servers opleveren, inclusief versienummer en bannerdata.

Pentesting use cases

Fofa is bijzonder waardevol voor specifieke scenario’s:

  • Shadow IT detecteren buiten bekende regio’s
    Organisaties die actief zijn in Azië, Afrika of Zuid-Amerika kunnen assets hebben die wél door Fofa, maar niet door andere tools zijn geïndexeerd.
  • Validatie van kwetsbare services
    Denk aan open MongoDB-instances, verouderde SMB-services of onveilige webinterfaces.
  • Subdomeinen en certificaten vinden via CN/subject-alt-names
    Hiermee kunnen nieuwe ingangen gevonden worden in de infrastructuur.
  • Vergelijken met Shodan-resultaten
    Door dezelfde zoekopdracht in meerdere tools te doen, ontstaat een vollediger attack surface beeld.
  • Hunting op specifieke softwareversies
    Bijvoorbeeld: app="Apache Tomcat" && version="7.0.65" voor gericht zoeken naar kwetsbare installaties.

Verschillen met Shodan & Censys

KenmerkFofaShodanCensys
FocusGlobaal, met nadruk op AziëBreed wereldwijdSecurity & certificaten
InterfaceChinees/EngelsEngelsEngels
API-mogelijkhedenUitgebreidUitgebreidUitgebreid
ZoekprecisieHoog, met filteroperatorsSnel met intuïtieve UIZeer specifiek
Extra functiesRelatieanalyse, trendsExposed device focusCertificaatkoppelingen

Fofa is dus geen vervanger, maar een aanvulling — vooral als je een compleet beeld wilt van de internet-exposure van een organisatie.

Toepassing in realistische pentest-scenario’s

In een Red Team-operatie gericht op een internationaal retailbedrijf ontdekte een onderzoeker via Fofa een vergeten subdomein (beta.api.klantnaam.asia) dat nergens anders naar voren kwam. De server draaide een verouderde API-service met debug-functionaliteit aan. Via deze toegang kon een chain-aanval worden opgezet naar interne backends. Shodan en Censys gaven geen resultaat — alleen Fofa had de server geïndexeerd op basis van een TLS-certificaat en open poort op een atypisch IP-blok.

Zulke scenario’s onderstrepen hoe belangrijk het is om meerdere tools te gebruiken binnen de reconnaissance-fase van pentesting en hacking-simulaties.

Fkogkwmfqr Hdjtmcq Vzw

15. PublicWWW.com (Codes Search)

PublicWWW code search is een unieke zoekmachine waarmee pentesters direct kunnen zoeken in de HTML- en JavaScript-code van miljoenen live websites. In tegenstelling tot tools die repositories doorzoeken, richt PublicWWW zich op live, publiek toegankelijke webpagina’s. Hiermee wordt zichtbaar welke scripts, API-keys, tracking-tools en bibliotheken zijn ingeladen — en waar deze worden gebruikt.

Voor pentesters is PublicWWW bijzonder handig bij fingerprinting, bug bounty recon en het opsporen van kwetsbaarheden die ontstaan door hergebruik van onveilige scripts of misconfiguraties in front-end code.

Wat je met PublicWWW vindt

PublicWWW indexeert de broncode van websites en stelt je in staat om direct te zoeken naar:

  • Analytics-ID’s zoals Google Analytics (UA-XXXXXX)
  • Tracking scripts en third-party JS libraries
  • Mailadressen en contactformulieren
  • Codefragmenten zoals apikey=, token, auth
  • Verwijzingen naar backend-API’s
  • SaaS-integraties zoals Stripe, Intercom, Mailchimp, enz.
  • Verouderde of kwetsbare bibliotheken zoals oude versies van jQuery

Elke zoekopdracht levert de exacte locatie, URL en context waarin de zoekterm is gevonden. Het is een passieve techniek: er is geen interactie met de server zelf.

Voorbeelden van tracking codes

Een veelgebruikte toepassing van PublicWWW is het opsporen van trackingcodes:

  • Google Analytics: via UA-12345678 kan je achterhalen welke sites met elkaar verbonden zijn
  • Facebook Pixel ID: laat zien welke domeinen door dezelfde advertentiecampagnes worden gebruikt
  • Hotjar, Mixpanel, Segment: tools voor gedragstracking en analytics

Deze informatie is waardevol voor:

  • Asset correlation
    Sites die dezelfde tracking-ID gebruiken, horen vaak bij dezelfde organisatie
  • Scope-uitbreiding in bug bounty
    Domeinen buiten de opgegeven scope kunnen alsnog eigendom blijken via gedeelde trackingcode
  • Shadow IT detectie
    Bijvoorbeeld vergeten microsites die nog actief zijn, maar dezelfde UA-ID gebruiken

SEO en security overlap

PublicWWW maakt het ook mogelijk om SEO-gerelateerde fingerprints te koppelen aan security-insights:

  • Onveilige canonical-tags
    Dieperliggende pagina’s met verkeerde redirects
  • Openlijke verwijzingen naar staging-omgevingen
    Bijvoorbeeld: staging.domain.com of test-api.domain.com
  • SEO-tools en CDN’s
    Externe scripts die pagina’s aanpassen of injecties mogelijk maken

SEO-fragmenten kunnen een ingang vormen voor pentesters om technische misconfiguraties te vinden in ogenschijnlijk onschuldige metadata.

Gebruik in pentests

PublicWWW is bij uitstek geschikt in de OSINT- en reconnaissancefase. Typische toepassingen zijn:

  • Detectie van exposed JavaScript-files
    Denk aan config.js met hardcoded API-sleutels
  • Vergelijking van domeinen op basis van shared code
    Achterhaal of meerdere domeinen van dezelfde eigenaar zijn
  • Zoek naar API-endpoints en parameters
    Denk aan /api/v1/login of fetch("https://api.domain.com/auth")
  • Detectie van hergebruikte scripts in phishing-domeinen
    Kwaadwillende actoren kopiëren vaak legitieme code — wat via fingerprinting opvalt
  • Subdomeinen ontdekken via in-code verwijzingen
    Zoals cdn.domain.com, files.domain.com, auth.domain.com

Deze informatie geeft een breder beeld van de infrastructuur en biedt vaak nieuwe ingangen voor verdere analyse of exploitatie.

Praktisch voorbeeld

Tijdens een pentest op een e-commerceplatform werd via PublicWWW een shared analytics-ID gevonden op een domein dat buiten de opgegeven scopelijst viel. Het domein bevatte echter een adminpanel met een loginpagina — via brute-force werd toegang verkregen met hergebruikte credentials. De volledige aanval begon met passieve code-analyse, zonder scanning of directe interactie met systemen.

Dergelijke hacking-technieken tonen aan hoe kleine stukjes metadata uiteindelijk leiden tot serieuze kwetsbaarheden.

Best practices bij gebruik

Pentesters gebruiken PublicWWW effectief door:

  • Te zoeken op specifieke identifiers zoals UA-, fbq( of gtag(
  • Gebruik van wildcards en substrings in trackingcodes of URLs
  • Combineren met grep.app of Searchcode voor intern gebruik van dezelfde fragmenten
  • Cross-referencing met tools als Hunter.io of Shodan om e-mailadressen of IP’s te koppelen aan gevonden domeinen
  • Rapporteren van impact via chain-of-exploitation in pentestverslagen

PublicWWW biedt ook een API waarmee je grootschalige analyses kunt uitvoeren of integraties kunt bouwen in reconnaissance scripts.

Xmugg8w4ttmiyrztcj0qhg

16. Crt.sh (Certificate Search)

crt.sh certificate search is een openbare zoekmachine waarmee je SSL/TLS-certificaten kunt doorzoeken die zijn vastgelegd in zogenaamde Certificate Transparency (CT) logs. Voor pentesters is crt.sh een van de krachtigste bronnen voor het ontdekken van subdomeinen, stagingomgevingen en verborgen systemen, zonder enige vorm van actieve interactie met het doelwit.

Informatie die in SSL-certificaten staat, wordt vaak onderschat, maar kan leiden tot kwetsbare ingangen en ongepatchte omgevingen — en dat alles volledig passief. Crt.sh is gratis, snel en betrouwbaar en vormt een vast onderdeel van moderne OSINT- en reconstrategieën.

Hoe crt.sh werkt

Elke keer dat een organisatie een nieuw SSL/TLS-certificaat aanvraagt, wordt dit automatisch gelogd in een Certificate Transparency log. Deze logs zijn openbaar toegankelijk en bevatten onder andere:

  • De Common Name (CN) van het certificaat
  • Alle Subject Alternative Names (SANs), waaronder subdomeinen
  • De uitgevende certificaatautoriteit (CA)
  • De timestamp van aanvraag
  • Eventuele metadata zoals key usage, serial number, etc.

Crt.sh indexeert deze logs en maakt ze doorzoekbaar via:

  • Domeinnaam (%.bedrijf.nl)
  • Substring-zoekopdrachten
  • Certificaat-id of SHA1/SHA256 fingerprint
  • Datum of CA-filter

Subdomeinen vinden via certificaten

Een van de belangrijkste toepassingen van crt.sh is het vinden van subdomeinen. Bijvoorbeeld:

Zoekopdracht: %.targetbedrijf.nl
Resultaten:

  • vpn.targetbedrijf.nl
  • test-api.targetbedrijf.nl
  • admin-panel.targetbedrijf.nl
  • dev-internal.targetbedrijf.nl

Veel van deze subdomeinen zijn niet terug te vinden via DNS-brute forcing of Google Dorks, maar wél via certificaten die ooit zijn aangemaakt — zelfs als ze inmiddels verlopen zijn.

Deze subdomeinen kunnen toegang geven tot:

  • Test- of stagingservers
  • Adminportalen
  • API-endpoints
  • Developeromgevingen
  • VPN-ingangen

Voor pentesters is dit waardevolle informatie die verder onderzocht kan worden met tools zoals Shodan, Censys of FullHunt.

Pentesting toepassingen

Crt.sh wordt breed ingezet in de recon-fase van pentests, met toepassingen zoals:

  • Subdomain enumeration
    Beter en dieper dan traditionele brute-force
  • Opsporen van shadow IT
    Systemen buiten het zicht van het IT-team, maar wél publiek beschikbaar
  • Controle op wildcardcertificaten
    *.bedrijf.nl kan wijzen op slechte segmentatie en verhoogd risico bij compromise
  • Historische analyse van infrastructuur
    Domeinen of servers die ooit bestonden, maar vergeten zijn op te schonen
  • Chain-building van aanvalspaden
    Van subdomein naar stagingserver naar interne credentials

Crt.sh laat ook certificaten zien van onderliggende diensten zoals CDN’s of derde partijen, wat weer leidt tot nieuwe aanvalsvectoren.

Voorbeeld van misconfiguraties

Een pentestteam ontdekte via crt.sh een subdomein admin-old.klantnaam.nl dat nooit verwijderd was uit de DNS. De server bleek nog live en draaide op een kwetsbare versie van phpMyAdmin zonder tweefactorauthenticatie. Door het gebruik van hergebruikte credentials uit een eerdere breach werd toegang verkregen tot de volledige databaseomgeving. Alles begon met een simpele zoekopdracht in crt.sh.

Best practices voor gebruik

Voor pentesters zijn dit effectieve tactieken:

  • Zoek met wildcards: Gebruik %.doelwit.nl om álle bekende subdomeinen te zien
  • Controleer op oudere certificaten: Zelfs verlopen domeinen kunnen nog live zijn
  • Koppel met andere tools: Combineer resultaten met scans van BinaryEdge, Shodan of Leakix
  • Let op staging/testwoorden in subdomeinen: staging., dev., test. en old. zijn vaak vergeten of minder goed beveiligd
  • Check op wildcardcertificaten: Onbedoeld gebruik van *.bedrijf.nl vergroot het risico bij key leakage

Crt.sh biedt ook een eenvoudige en snelle webinterface zonder registratie. Voor grotere projecten kan het gecombineerd worden met tools zoals CertSpotter, Subfinder of Amass, die crt.sh-gegevens automatisch ophalen en structureren.

Sax3xy7qshw88d6fnqsgbw

17. Vulners.com (Vulnerabilities)

Vulners vulnerability database is een geavanceerd platform waarmee pentesters snel en gericht bekende kwetsbaarheden kunnen opsporen. Het biedt toegang tot een gecentraliseerde zoekmachine voor CVE’s, exploits, advisories, scannerresultaten en patchinformatie. Wat Vulners onderscheidt, is de focus op snelheid, integratie en bruikbaarheid tijdens actieve en passieve pentesting workflows.

Voor ethical hacking is het vinden van kwetsbare softwareversies pas het begin — het koppelen van die versies aan bekende exploits maakt het verschil tussen een bevinding en een directe toegang. Vulners automatiseert dat proces.

Wat Vulners uniek maakt

Vulners indexeert kwetsbaarheidsinformatie uit tientallen bronnen:

  • CVE-database van MITRE
  • ExploitDB, Metasploit en Packet Storm
  • Security advisories van vendors zoals Cisco, Microsoft, Apache, Red Hat
  • Patch notes en changelogs
  • Security mailinglists en RSS-feeds
  • NVD scoring en contextuele risico-indicatie

De kracht van Vulners zit in de snelle zoekmachine die alle data doorzoekbaar maakt op:

  • Softwarenaam + versienummer
  • CVE-code
  • Poort/service/protocol
  • Platform of besturingssysteem
  • Zoekwoorden binnen advisories

Het platform werkt ook met zogenaamde bulletins die direct samenvattingen geven van kwetsbaarheden en bijbehorende patches of exploits.

Zoeken naar kwetsbaarheden

Pentesters gebruiken Vulners op verschillende manieren tijdens een pentest:

  • Na bannergrabbing of fingerprinting
    Gebruik gevonden versies van Apache, PHP, Tomcat of MySQL om direct te zoeken naar CVE’s
  • Via toolintegratie
    Vulners is geïntegreerd in tools zoals Nmap (via NSE scripts), Burp Suite, Nessus en OpenVAS
  • Als standalone search engine
    Via de website of API direct zoeken naar kwetsbaarheden op basis van software + versienummer

Voorbeeld: je vindt tijdens een scan Apache HTTP Server 2.4.49
Zoekopdracht: apache 2.4.49
Resultaat: CVE-2021-41773 – Path traversal + RCE mogelijk bij verkeerde configuratie

De koppeling met ExploitDB laat direct zien of er een proof-of-concept exploit beschikbaar is.

Exploits koppelen aan systemen

Vulners maakt het mogelijk om direct te zien:

  • Of er publiek beschikbare exploits zijn
  • Welk type exploit het is (remote, local, web, privilege escalation)
  • In welke taal het geschreven is (Python, C, Metasploit module)
  • Wat de impact is (CVSS-score, impact op CIA-triad)
  • Of de kwetsbaarheid al actief wordt misbruikt

Deze informatie helpt pentesters om prioriteit te geven aan kwetsbaarheden die daadwerkelijk inzetbaar zijn in hun test. Dat verhoogt de effectiviteit van de simulatie.

Pentesting met Vulners

Binnen een pentest gebruiken onderzoekers Vulners bijvoorbeeld voor:

  • Validatie van bevindingen uit scans
    Scanresultaten van tools zoals Nmap, Nessus of Burp koppelen aan Vulners-data
  • Snelle CVE-matching tijdens exploitatie
    Bij detectie van een oude versie direct checken of daar een werkende exploit voor beschikbaar is
  • Documentatie in rapportages
    CVE’s en bijbehorende info kunnen direct worden opgenomen in het pentestrapport, inclusief risicoanalyse
  • Live enrichment van testdata
    Tijdens handmatige tests snel opzoeken wat bekende issues zijn van een gevonden component

Voorbeeld: impact van kwetsbare software

Tijdens een pentest op een educatief platform werd Tomcat 9.0.30 aangetroffen. Via Vulners bleek deze versie kwetsbaar voor CVE-2020-1938 — ook bekend als “Ghostcat”. De exploit was publiek beschikbaar en stelde de pentester in staat om configbestanden te lezen via het AJP-protocol. Hierdoor werden credentials gevonden waarmee toegang tot een beheerpaneel kon worden verkregen. De keten van aanval begon met een eenvoudige versiedetectie en werd direct versterkt met informatie uit Vulners.

Dit scenario laat zien hoe effectief pentesters kunnen werken als ze real-time toegang hebben tot gekoppelde CVE’s en exploitinformatie — zonder tijdverlies.

Integratie met pentest workflows

Vulners biedt een API die makkelijk in scripts of tools verwerkt kan worden. Voorbeelden van gebruik:

  • Automatisch aanvullen van scanresultaten met CVE’s
  • Vulnerability-as-a-Service via interne portals
  • Triage van bevindingen o.b.v. CVSS-score en exploitbeschikbaarheid
  • Security automation in CI/CD pipelines

In combinatie met tools als BinaryEdge, FullHunt of Shodan kunnen exposed assets direct worden gematched met kwetsbaarheden die via Vulners zijn geïdentificeerd.

004023

18. Pulsedive.com (Threat Intelligence)

Pulsedive threat intelligence is een platform dat zich richt op het verzamelen, analyseren en verrijken van Indicators of Compromise (IoCs), zoals domeinen, IP-adressen, URLs en hashes. Voor pentesters en threat researchers is het een handige tool om snel te bepalen of een bepaalde indicator verdacht is, waar deze mee geassocieerd wordt en hoe die past in bredere aanvalscampagnes.

Waar veel threat intel-platformen overweldigend of commercieel zijn opgezet, biedt Pulsedive een laagdrempelige interface met zowel gratis als uitgebreide betaalopties. Pentesters gebruiken de tool om verdachte signalen te valideren, OSINT-analyses te verrijken en phishingdomeinen te beoordelen — zonder actieve scans uit te voeren.

Wat Pulsedive biedt

Pulsedive verzamelt gegevens uit tientallen bronnen:

  • Open threat feeds (zoals Abuse.ch, PhishTank, URLhaus)
  • Malware analysis-platforms
  • Certificaatlogs en domeinregistratie-informatie
  • Community input en threat hunting-projecten

Elke IOC die je invoert (IP, URL, domein of hash), wordt direct geanalyseerd op:

  • Risiconiveau (benign, suspicious, malicious)
  • Geassocieerde threat actors of malwarefamilies
  • Tijdsframe en eerste detectie
  • Links met andere IoCs
  • Geografische locatie en ASN-data

Daarnaast geeft Pulsedive context over exploit attempts, phishingactiviteiten en herkomst van de IOC in eerdere incidenten.

Indicatoren van Compromis (IoCs)

Pentesters en analisten gebruiken Pulsedive voor verschillende soorten IoCs:

  • Domeinen – phishingdomeinen, typo-squatting, rogue mailservers
  • IP-adressen – command & control, brute-force hosts, spam
  • URLs – links in phishingmails, redirect chains, malafide scripts
  • Hashes – van bestanden of payloads die bij een aanval horen

Door één IOC in te voeren, toont Pulsedive vaak een heel netwerk aan gerelateerde entiteiten. Dit maakt het mogelijk om aanvalscampagnes en infrastructuur van aanvallers te reconstrueren.

Hoe pentesters Pulsedive gebruiken

Pulsedive is bij uitstek geschikt voor:

  • Controle van phishing- of malwaredomeinen
    Ontvangen via OSINT, gevonden met tools als Urlscan.io of PublicWWW
  • Valideren van bevindingen in social engineering tests
    Controleren of links die in phishingmails zijn gebruikt reeds bekend zijn in threat feeds
  • Detectie van C2-infrastructuur
    IP’s gevonden via netwerkverkeer analyseren op connecties met bekende botnets of APT-groepen
  • Threat enrichment in rapportages
    Toevoegen van context over IOC’s om de impact van bevindingen te onderbouwen
  • Hunting op campagnebasis
    Door zoeken op keywords of malwarefamilies om verwante domeinen en hosts te vinden

Pentesters gebruiken Pulsedive niet alleen voor validatie, maar ook om inzicht te krijgen in hoe doelwitten al in andere aanvallen zijn betrokken — of hoe hun infrastructuur hergebruikt wordt.

Integratie met SIEM/SoC

Hoewel Pulsedive een lichte interface heeft, is het ook goed te integreren met professionele securitysystemen. De API biedt:

  • Realtime threat feed access
  • IOC enrichment binnen Splunk, Elastic, QRadar
  • Automatische alerts bij nieuwe matches op IOC-profielen
  • Exportmogelijkheden naar STIX, JSON of CSV-formaat

Voor pentesters met toegang tot het SIEM van de klant (bij Red Team-opdrachten) is Pulsedive waardevol bij het correleren van interne logs met externe dreigingsinformatie.

Praktische pentestscenario’s

  • Scenario 1: Een pentester ontvangt een subdomein login-klantnaam-support.com via OSINT. Pulsedive toont dat dit domein gelinkt is aan een bekende phishingcampagne gericht op financiële instellingen.
  • Scenario 2: Tijdens netwerkmonitoring komt een onbekend IP naar voren. Pulsedive koppelt het IP aan een C2-server van de Emotet-malware uit een eerdere campagne.
  • Scenario 3: Een geüploade executable tijdens een phishingtest levert een SHA256-hash op. Pulsedive herkent deze hash en koppelt het bestand aan een bekende remote access tool (RAT).

Dergelijke bevindingen geven direct extra impact aan het pentestverslag, en tonen aan dat systemen daadwerkelijk misbruikt kunnen worden.

Waarom Pulsedive nuttig is in hacking workflows

In hacking- en pentestprocessen draait alles om verbanden leggen. Tools zoals Pulsedive versnellen dat proces door ruwe IOC’s te verrijken met context, historie en technische details. Dit maakt de tool niet alleen bruikbaar voor dreigingsanalyses, maar ook voor:

  • OSINT-gedreven recon
  • Social engineering validatie
  • Incident response simulatie
  • Infrastructurele mapping van dreigingen

Omdat het platform deels open is, kan elke pentester laagdrempelig beginnen zonder direct in complexe enterprise-platforms te duiken.

004039

19. Zoomeye.org (Threat Intelligence)

Zoomeye threat intelligence is een geavanceerde zoekmachine die internetbrede scans uitvoert en kwetsbare systemen en apparaten indexeert. Het platform is ontwikkeld door het Chinese cybersecuritybedrijf Knownsec en staat bekend als het “Chinese Shodan”. Voor pentesters is Zoomeye een waardevolle bron van alternatieve scanresultaten, vooral voor infrastructuur in Azië en omgevingen die onder de radar blijven bij westerse tools.

De tool richt zich op blootgestelde services, apparaten, servers en ICS-systemen, met een interface die geoptimaliseerd is voor technische zoekopdrachten. De combinatie van device-fingerprinting en threat intelligence maakt het geschikt voor zowel infrastructuurreconnaissance als risicoanalyse.

Geschiedenis van Zoomeye

Zoomeye werd gelanceerd als een academisch project en groeide snel uit tot een volwaardig intelligence-platform. Waar Shodan bekendstaat om zijn device focus en Censys om certificaatdata, richt Zoomeye zich op een combinatie van:

  • Internet of Things (IoT)
  • Servers en services
  • Webapplicaties
  • SCADA en industriële netwerken
  • Threat activity monitoring

Met name bij Red Team-operaties in Aziatische regio’s biedt Zoomeye unieke inzichten die elders niet beschikbaar zijn.

Vergelijking met FOFA en Shodan

KenmerkZoomeyeFOFAShodan
TaalinterfaceChinees/EngelsChinees/EngelsEngels
FocusgebiedAzië, wereldwijdChina, open servicesWereldwijd, breed
ZoekmogelijkhedenTCP/UDP, service, bannerCertificaten, hostnamesService, org, port
Threat dataJa, inclusief malware feedsJa, via FOFA threat centerBeperkt (via addons)

Zoomeye biedt met name meer zicht op Aziatische IP-blokken, IoT-exposure en industriële controleomgevingen dan de meeste westerse tools.

Welke data pentesters vinden

Pentesters kunnen in Zoomeye zoeken op basis van:

  • IP of IP-range
  • Poortnummers (bijv. port:21)
  • Service- of bannerspecifieke info (bijv. app:nginx)
  • Geolocatie of ASN
  • Softwarenaam + versienummer
  • Device-type (bijv. camera, NAS, router)

Veelvoorkomende vondsten via Zoomeye:

  • NAS- of CCTV-systemen met standaardwachtwoorden
  • SCADA-interfaces die publiek toegankelijk zijn
  • Open RDP- of VNC-servers zonder versleuteling
  • Legacy Windows-servers met SMBv1 actief
  • Exposed Elasticsearch- en Redis-databases

Voor pentesters die infrastructuur in China, Singapore, Zuid-Korea of Japan onderzoeken, levert Zoomeye vaak meer en andere resultaten dan Shodan of BinaryEdge.

Risico’s en ethiek

Hoewel Zoomeye net als andere tools publieke data toont, is het belangrijk om de gegevens ethisch te gebruiken:

  • Geen exploitatie zonder toestemming
  • Gebruik alleen binnen scope van een pentest of bug bounty
  • Geen misbruik maken van exposed credentials of testservers
  • Combineer met responsible disclosure waar mogelijk

Net als bij andere search engines geldt: Zoomeye laat zien wat publiek zichtbaar is, maar dat betekent niet automatisch dat je het mag of moet gebruiken zonder toestemming.

Toepassingen in pentests

Zoomeye wordt in pentests ingezet voor:

  • Extern asset discovery
    Achterhalen welke systemen of services buiten controle van IT staan
  • Validatie van patchbeheer
    Servers met verouderde versies van software identificeren
  • Opbouw van attack surface
    Combineren van subdomeinen, IP’s en services tot één logisch geheel
  • Detectie van zwakke segmentatie
    Systemen die uit andere netwerken bereikbaar zijn, maar dat niet zouden mogen zijn
  • Controle op industriële apparaten
    Denk aan HMI’s, PLC’s of SCADA-panelen met onbeveiligde toegang

Ethical hacking voorbeeld

Tijdens een internationale pentest werd via Zoomeye een subdomein gevonden (vpn.old-doelwit.cn) dat niet in DNS zichtbaar was, maar nog wel actief luisterde op poort 443. De SSL-banner onthulde dat het ging om een oude Pulse Secure VPN, kwetsbaar voor CVE-2019-11510. De ontdekking leidde tot toegang tot interne documentatie en gebruikersdata. Deze server was in Shodan en Censys niet zichtbaar — alleen Zoomeye had de exposure gelogd.

Dit soort bevindingen maken duidelijk hoe krachtig Zoomeye kan zijn in reconfases van hacking-simulaties.

004141

20. Iv.re (Server)

Iv.re server search is een krachtige, minimalistische zoekmachine die gespecialiseerd is in het analyseren van publieke servers en hun netwerkexposure. Voor pentesters biedt Iv.re een snelle manier om IP-adressen, domeinen en services te koppelen aan hun bijbehorende infrastructuur — volledig passief en zonder actieve scans.

In tegenstelling tot platforms zoals Shodan of Censys, die uitgebreide interfaces en metadata bieden, richt Iv.re zich op snelheid en eenvoud. Het toont precies wat nodig is: welke servers bestaan, hoe ze bereikbaar zijn, welke poorten openstaan en wat de bijbehorende hostnamen en SSL-informatie zijn.

Wat Iv.re biedt

Iv.re scant continu het internet en indexeert technische informatie van servers en hosts. De zoekmachine geeft inzicht in:

  • Actieve IP-adressen en poorten
  • Serverbanner-informatie (bijv. Apache, NGINX, SSH)
  • SSL-certificaten en SAN-gegevens
  • Hostnamen en subdomeinen
  • ASN en locatiegegevens
  • Reverse DNS-records

De interface is gericht op eenvoud: één zoekbalk, directe resultaten, zonder poespas. Dit maakt het bij uitstek geschikt voor snelle pentest-reconnaissance of asset discovery.

Server identificatie en mapping

Een typische workflow met Iv.re:

  1. Zoek op IP of subnet
    Bijvoorbeeld: 185.23.56.0/24
    Direct zicht op alle actieve IP’s binnen het blok
  2. Analyseer open poorten en banners
    Ontdek services zoals SSH, FTP, SMTP, HTTP(S) of custom services
  3. Controleer op SSL-certificaten
    Welke domeinen horen bij dit IP? Welke certificaatautoriteit is gebruikt?
  4. Hostnamen en subdomeinen
    Ook niet-resolveerbare subdomeinen kunnen worden herleid via certificaatdata
  5. ASN- en netwerkinformatie
    Beoordeel de herkomst en scope van een infrastructuur

Deze gegevens kunnen direct worden gebruikt om doelgerichte pentest-aanpakken te ontwerpen — zonder ruis.

Praktische pentest scenario’s

Iv.re komt van pas in de volgende situaties:

  • Stealth-reconnaissance zonder interactie
    Informatie ophalen zonder connecties met het doelwit
  • Validatie van shadow IT
    Servers buiten het beheer van de organisatie die toch live staan
  • Identificatie van oude of ongepatchte systemen
    Denk aan FTP-servers, oude OpenSSH-versies of verouderde webservers
  • Vaststellen van shared hosting
    Meerdere domeinen op één IP-adres kunnen wijzen op shared infrastructuur
  • Bevestiging van asset ownership
    Als e-mail of certificaatgegevens terugverwijzen naar de organisatie

Vergelijking met Shodan

KenmerkIv.reShodan
InterfaceMinimalistisch & snelVisueel en uitgebreid
ScanmethodeActief + passiefActief
SSL-informatieJaJa
PortdataJa, overzichtelijkJa, zeer gedetailleerd
FiltersIP, poort, ASN, bannerVeelzijdiger, maar complexer
GebruikersdoelSnelle OSINT & reconBrede infrastructuuranalyse

Iv.re is geen vervanging van Shodan, maar een aanvulling — vooral als je snelheid en eenvoud nodig hebt tijdens OSINT en initiële reconnaissance.

Praktische bevinding tijdens pentest

Bij een pentest op een leverancier in de zorgsector gebruikte het team Iv.re om een ASN-blok te doorzoeken dat volgens Whois-data gelinkt was aan het bedrijf. Daarbij werd een vergeten server aangetroffen op vpn-old.klantnaam.net, met een verouderde SSL-certificaatketen en een webinterface op poort 8443. De banner onthulde een legacy VPN-oplossing die kwetsbaar was voor CVE-2019-1579. De combinatie van certificaatdata en bannerinformatie — zonder actieve scan — leidde tot een directe en effectieve exploitkans.

Dergelijke hacking-scenario’s tonen aan hoe krachtig passieve serverinformatie kan zijn.

004365

21. Netlas.io (Attack Surface)

Netlas attack surface is een krachtige zoek- en analyse-engine die organisaties helpt bij het ontdekken, monitoren en evalueren van hun externe IT-assets. Voor pentesters is het een alles-in-één OSINT-tool die subdomeinen, services, DNS-records, TLS-certificaten en netwerkconnecties samenbrengt in één interface. De kracht van Netlas zit in de snelheid, de diepte van de data en de flexibiliteit van het zoekplatform.

Netlas.io combineert functies van tools zoals Shodan, Censys, crt.sh en SecurityTrails — maar dan met een moderne interface en slimme filtering. Pentesters gebruiken het in reconfases om het volledige aanvalsoppervlak van een doelwit bloot te leggen zonder actieve scans uit te voeren.

Wat Netlas uniek maakt

Netlas indexeert en correleert data van:

  • DNS-records (A, AAAA, MX, TXT, CNAME)
  • SSL-certificaten en TLS-handshakes
  • HTTP(s)-banners en headers
  • Subdomeinen uit certificaatlogs
  • ASN- en IP-informatie
  • Portscans en versiedetectie

Alles is toegankelijk via een krachtige zoektaal die vergelijkbaar is met die van Elasticsearch of Splunk. Voorbeeld:
domain:bedrijf.nl AND service:http AND header:"X-Powered-By"

Zoekopdrachten kunnen tot op poortniveau worden gefilterd en gecombineerd met geolocatie, hostnames, softwareversies en meer.

Attack surface management in pentests

Pentesters gebruiken Netlas.io voor:

  • Volledige asset discovery
    Subdomeinen, IP-adressen, cloudservices en derde partijen in kaart brengen
  • Identificatie van vergeten of shadow IT
    Externe servers, testomgevingen of tools die buiten beheer vallen
  • Detectie van kwetsbare softwareversies
    Zoals Apache 2.4.49, Exim 4.91 of VPN-servers met bekende CVE’s
  • Segmentatieanalyse
    Systemen die via het internet bereikbaar zijn, maar dat niet zouden moeten zijn
  • Onderbouwing van risico’s
    Met direct bewijs van exposed services, headers, SSL-certificaten of response-banners

Voorbeelden van kwetsbaarheden

Via Netlas.io vinden pentesters regelmatig:

  • Subdomeinen zoals dev-api.klantnaam.nl of admin.test.klantnaam.com
  • Public-facing admin panels (Jenkins, Kibana, phpMyAdmin)
  • Configuratiefouten in headers zoals Access-Control-Allow-Origin: *
  • Certificaten die verlopen of wildcard-certificaten met te brede scope
  • CDN- en cloud misconfiguraties met open toegang tot assets

De tool maakt het mogelijk om deze assets snel te filteren en prioriteren, zonder het risico van opgemerkt te worden tijdens actieve scans.

Voorbeelden van kwetsbaarheden in context

Tijdens een pentest voor een logistiek bedrijf ontdekte een analist via Netlas het subdomein track-beta.klantnaam.nl. Dit domein werd niet gevonden via Google of DNS-brute forcing, maar wel via certificaatdata. De server draaide een verouderde versie van Laravel met debug-modus aan. Via een foutmelding in de HTTP-header werd de locatie van een .env-bestand zichtbaar, dat vol stond met credentials voor de stagingdatabase. Deze toegang leidde tot gevoelige klantinformatie en bewijst hoe hacking vaak begint bij slechte exposure-analyse.

Integratie met security workflows

Netlas biedt een API waarmee pentesters de tool eenvoudig kunnen integreren in eigen scripts of recon-tools. Mogelijke toepassingen:

  • Automatische discovery van nieuwe subdomeinen
  • Alerting bij nieuwe open poorten of services op bekende IP’s
  • Koppeling met SIEM of assetmanagementtools
  • Asset monitoring in langdurige Red Team trajecten

De API maakt het mogelijk om Netlas in te zetten als OSINT-datalake, gevoed met actuele infrastructuurinformatie.

Kantoorpersoneel in een chaotische omgeving, omringd door rondvliegende papieren en een kapot scherm, terwijl collega's op de achtergrond haastig werken vanwege vermoedens van hacking.

22. App.binaryedge.com (Threat Intelligence)

BinaryEdge threat intelligence biedt een compleet beeld van de wereldwijde internetblootstelling van systemen, netwerken en applicaties. De tool verzamelt continu data via grootschalige internet-wide scans en verrijkt die met threat intelligence, service-informatie en assetdetails. Voor pentesters betekent dit directe toegang tot blootgestelde infrastructuur en kwetsbare systemen, zonder eerst te hoeven scannen.

BinaryEdge richt zich op asset discovery en threat exposure vanuit een technisch perspectief. De focus ligt op snelheid, schaal en de combinatie van service fingerprinting met risico-informatie.

Wat is BinaryEdge?

BinaryEdge bestaat uit verschillende modules die samen een breed platform vormen:

  • Internet Scanning: alle IPv4-adressen worden continu gescand op open poorten, services en headers
  • Certificate Scans: TLS-certificaten worden geanalyseerd op inhoud, geldigheid en herkomst
  • Vulnerability Exposure: detectie van bekende kwetsbaarheden op IP’s of domeinen
  • Threat Intel Feeds: integratie van IOC’s, botnets en malware-gerelateerde IP’s
  • API & Exports: directe koppeling van data met je pentesttools of dashboards

De webinterface biedt snelle zoekfunctionaliteit, terwijl de API meer geschikt is voor geautomatiseerde workflows.

Voorbeeldzoekopdrachten:

  • domain:doelwit.nl
  • port:445 country:NL
  • product:Apache AND version:2.4.49
  • tag:vulnerable
  • ssl.subject:"CN=*.klantnaam.com"

Belang voor threat intelligence

BinaryEdge is vooral krachtig in het signaleren van:

  • Kwetsbare services met bekende versies (zoals SMB, RDP, Elasticsearch)
  • Vergeten of ongedocumenteerde assets via TLS-certificaten of hostnames
  • IP’s die in botnetactiviteiten voorkomen of malware hosten
  • Servers die actief worden aangevallen, op basis van honeypot-koppeling

De tool combineert threat intelligence met live infrastructuurdata. Dat maakt het bijzonder geschikt voor Red Team-operaties, incident response én preventieve pentests.

Use cases in pentesting

Pentesters gebruiken BinaryEdge voor:

  • Reconnaissance zonder direct scannen
    Ontdek welke assets online staan en welke services open zijn.
  • Scope-analyse voorafgaand aan pentests
    Wat is er echt blootgesteld — en valt het binnen of buiten scope?
  • Detectie van kwetsbare versies
    Zoek bijvoorbeeld naar Apache 2.4.49, Fortinet SSL VPN of Exchange-servers met bekende CVE’s.
  • Validatie van cloudconfiguraties
    Zijn er S3 buckets of VPS-servers met foutieve poortinstellingen?
  • Vergelijken van resultaten met Shodan en Onyphe
    Voor meer volledigheid en cross-validatie van bevindingen

Vergelijking met Shodan

FeatureBinaryEdgeShodan
Snelheid van scansZeer snelGemiddeld
Data-verrijkingZeer uitgebreidGoed, maar minder contextueel
Threat FeedsIngebouwdBeperkt
Certificate scanningGeavanceerdBeschikbaar, maar minder filteropties
UI & usabilityMeer technischToegankelijker voor beginners

BinaryEdge is technisch sterker op gebied van data-extractie en -filtering, terwijl Shodan makkelijker navigeert. In combinatie zijn ze bijzonder krachtig.

Pentesting voorbeeldscenario

Een pentest op een SaaS-platform begon met een BinaryEdge-zoekopdracht op domain:klantnaam.com. De resultaten toonden een exposed Elasticsearch-service op poort 9200 met versie 6.0.1. Via de product en version filters werd een kwetsbare configuratie gevonden die ongeauthenticeerde toegang toestond. De index bevatte gebruikerslogdata inclusief e-mailadressen. Door de koppeling met threat feeds bleek het IP eerder te zijn misbruikt door een botnet — extra bewijs dat het asset écht risico liep. Deze vorm van hacking begon volledig passief, zonder directe interactie met het systeem.

Voordelen van BinaryEdge

  • Volledig internetdekkend – alle IPv4-ranges worden continu gescand
  • Gedetailleerde scans – met headers, versies en certificaatdata
  • Threat correlation – inzicht in of een asset al doelwit is geweest
  • API-klaar – gemakkelijk te integreren in pentesttools of SIEM
  • Realtime zoekresultaten – ontdek kwetsbaarheden terwijl ze live staan

Koppeling met andere tools

Gebruik BinaryEdge samen met:

  • Netlas of Onyphe – voor bredere context en subdomeinkoppelingen
  • crt.sh en Censys – voor certificaatanalyse
  • Amass / Subfinder – voor subdomain enumeration, gecombineerd met BinaryEdge voor validatie
  • Burp Suite / Nuclei – scan assets die je via BinaryEdge ontdekt hebt

Deze combinatie zorgt voor snelheid, stealth en schaalbaarheid in je pentestworkflow.

2024 04 28 10 56 59 Person Using Laptop Computer Photo – Free Business Image On Unsplash

23. Viz.greynoise.io (Threat Intelligence)

GreyNoise threat intelligence biedt pentesters en security professionals inzicht in achtergrondverkeer op het internet. Waar traditionele tools focussen op wat er op een specifiek IP of domein draait, kijkt GreyNoise naar wie er probeert te scannen, waar vandaan, en met welk gedrag.

De tool helpt onderscheid te maken tussen normale internetactiviteit en gerichte aanvalspogingen. Voor pentesters is het vooral waardevol in de OSINT- en detectiefase: het geeft direct zicht op of een IP-adres bekendstaat als bron van scanning, botnets of ongewenste activiteit.

Wat GreyNoise uniek maakt

GreyNoise verzamelt data via duizenden sensoren verspreid over het internet. Deze sensoren luisteren passief naar inkomende verbindingen en registreren:

  • IP-adressen die actief scannen
  • Ports en protocollen die worden aangeroepen
  • Tools of payloads die gebruikt worden (zoals masscan, zgrab, Mirai)
  • Frequentie en patroon van het gedrag
  • Tijd van activiteit en geolocatie van het IP

Deze data wordt vervolgens gecategoriseerd in:

  • Benign: scanners zoals zoekmachines of researchers
  • Malicious: bots, wormen, brute-forcers
  • Unknown: nog niet geklasseerde activiteit

Elke zoekopdracht naar een IP levert direct status, gedrag, locatie en classificatie op.

Detecteren van scanning activity

Pentesters gebruiken GreyNoise onder andere om:

  • Na te gaan of een target-IP al wordt gescand door anderen
  • Controleren of eigen scan-IP’s opvallen bij defensieve tooling
  • Gedragspatronen van scanners te analyseren voor verdediging of mimicry
  • Begrijpen welke poorten, protocollen en services het vaakst worden aangevallen

Dit inzicht is waardevol voor stealth-operaties. Als je zelf niet zichtbaar wilt zijn, is het nuttig om te weten wat wél opvalt.

GreyNoise biedt ook een tagging-systeem dat IP’s groepeert onder categorieën zoals:

  • Mirai, Masscan, zmap, OpenSSH scanner
  • RDP brute force, IoT vuln scan, Webshell scanner
  • Tor exit node, Proxy/VPN, Known malware C2

Hoe pentesters GreyNoise gebruiken

  • Verifiëren of een IP actief is als scanner
    Bijvoorbeeld vóór je een red team-operatie start, om te bepalen of je infrastructuur al verdacht is.
  • Aantonen van achtergrondruis tijdens een pentest
    Bij false positives kun je bewijzen dat een asset breed wordt gescand, ongeacht jouw acties.
  • Validatie van client-IP’s bij logging tests
    Als een organisatie logt, helpt GreyNoise bij het onderscheiden van normale ruis en doelgerichte actie.
  • Threat attribution bij incident response simulaties
    Is een aanval onderdeel van een gerichte campagne of slechts onderdeel van een massa-scan?

Case study voorbeelden

Voorbeeld 1:
Tijdens een pentest werd vastgesteld dat het externe IP van de klant binnen 24 uur 200 keer gescand werd op poort 445. Via GreyNoise bleek dat 80% van de activiteit afkomstig was van bots met het label smb-worm uit verschillende landen. De pentester kon aantonen dat de open poort niet alleen een kwetsbaarheid was, maar ook daadwerkelijk opgemerkt werd in de hacking ecosystemen.

Voorbeeld 2:
Een pentester gebruikte een eigen VPS voor scanning. Na enkele dagen meldde het team dat hun IP gelogd werd door defensieve tooling. GreyNoise bevestigde dat het IP inmiddels was gelabeld als Masscan scanner, zichtbaar voor iedereen. Het team roteerde de scaninfrastructuur en paste het tempo aan om detectie te vermijden.

Pentester scenario’s in de praktijk

  • Opbouw van stealth scanning strategieën
    Door gedrag van botnets te analyseren, kunnen pentesters soortgelijke patronen volgen en camouflage gebruiken.
  • Beoordelen van risico’s voor specifieke poorten of services
    Een asset op poort 8080 trekt meer aandacht dan gedacht? GreyNoise laat zien hoeveel traffic daar terechtkomt.
  • Controle van eigen IP footprint
    Red Teams die langdurige operaties uitvoeren, gebruiken GreyNoise om hun IP-reputatie te monitoren.
  • Onderbouwing van prioriteit in rapportage
    Assets die regelmatig worden gescand hebben een hoger exploitatie-risico. Dit kan prioritering beïnvloeden.

Hoe Viz.greynoise.io integreert in workflows

  • GreyNoise CLI: voor snelle command line queries in scripts
  • API access: voor geautomatiseerde checks tijdens OSINT-fase
  • SIEM-integratie: bij SOC-operaties of detection engineering
  • Maltego transform: visualiseer scanactiviteit en IP-relaties
  • Tag-based queries: snel filteren op type scanner of gedrag

GreyNoise werkt uitstekend naast tools als Shodan, Censys, BinaryEdge en Onyphe. Waar die tools laten zien wat er online staat, toont GreyNoise wie er kijkt en waar ze naar zoeken.

Voordelen voor pentesters

  • Realtime inzicht in IP-gedrag wereldwijd
  • Beter risicobegrip van blootgestelde systemen
  • Efficiëntie in logging en detectievalidatie
  • Ondersteuning van stealth-operaties
  • Gedragsanalyse van bots en scanners

GreyNoise voegt context toe die andere tools missen. Het kijkt niet naar de infrastructuur zelf, maar naar het gedrag van het internet daartegenover.

004251

24. Hunter.io (Email Addresses)

Hunter.io email search is een krachtige OSINT-tool waarmee pentesters eenvoudig zakelijke e-mailadressen kunnen verzamelen die openbaar gelinkt zijn aan een domeinnaam. Waar traditionele reconnaissance zich vaak richt op technische infrastructuur, maakt Hunter.io het mogelijk om aan de menselijke kant van security te beginnen — de gebruiker zelf.

E-mailadressen zijn vaak het startpunt van gerichte aanvallen zoals phishing, credential stuffing of social engineering. Deze tool biedt inzicht in welke contactinformatie voor iedereen zichtbaar is, inclusief de onderliggende patronen die je kunt misbruiken of benutten binnen een pentest.

Hoe Hunter.io werkt

Hunter.io verzamelt en indexeert e-mailadressen van openbare webbronnen. Dit zijn onder andere:

  • Webpagina’s
  • PDF’s en andere documenten
  • Social media-profielen
  • WHOIS-informatie
  • Persberichten, blogartikelen en nieuwsfeeds

Je voert simpelweg een domeinnaam in, zoals bedrijf.nl, en Hunter.io toont:

  • Alle gevonden e-mailadressen
  • De pagina waarop het adres is gevonden
  • Datum van ontdekking
  • Het patroon waarin de e-mails zijn opgebouwd

Voorbeeldpatronen:

  • voornaam@bedrijf.nl
  • voorletter.achternaam@bedrijf.nl
  • voornaam.achternaam@bedrijf.nl

Door dit patroon te herkennen kun je onbekende adressen voorspellen, bijvoorbeeld op basis van een LinkedIn-profiel of organigram.

Emailadressen in OSINT en pentests

Hunter.io is bijzonder waardevol in de inlichtingenfase van een pentest. De informatie is passief verzameld, dus je veroorzaakt geen verkeer naar het doelwit. Typische toepassingen:

  • Phishingcampagnes voorbereiden
    Verzamel echte adressen voor simulaties of awareness-tests.
  • Spear phishing op management
    Identificeer namen, functies en gerichte targets voor meer impact.
  • Validatie van e-mailstructuur
    Predictive modelling: welke andere adressen zijn waarschijnlijk bruikbaar?
  • Credential stuffing-aanvallen
    Combineer gevonden adressen met eerder gelekte wachtwoorden of bekende patronen.
  • Shadow IT ontdekken
    Adressen zoals test@, dev@, of backup@ kunnen leiden naar vergeten systemen.

Risico’s van openbaar e-mailgebruik

Organisaties zijn zich vaak niet bewust van de hoeveelheid e-mails die online vindbaar zijn. De risico’s zijn reëel:

  • Spear phishing op basis van functietitels
    Bijvoorbeeld hr@, finance@, of ceo@bedrijf.nl
  • Misbruik van B2B-relaties
    Leveranciers of integratiepartners gebruiken e-mails die zichtbaar zijn op meerdere domeinen.
  • Gerecyclede of niet-verwijderde accounts
    E-mailadressen van ex-medewerkers kunnen nog toegang geven tot systemen.
  • Bots die automatisch e-mails verzamelen
    Niet alleen pentesters gebruiken Hunter.io; ook aanvallers doen dat.

Toepassing in social engineering

Een praktijkvoorbeeld: een pentester wilde testen of medewerkers vatbaar waren voor een interne spear phishing-aanval. Via Hunter.io werden 20 adressen gevonden, waaronder:

  • support@bedrijf.nl
  • afdeling-ict@bedrijf.nl
  • robin.techniek@bedrijf.nl

Het patroon voornaam.afdeling@ werd herkend. De pentester vulde dit aan met LinkedIn-informatie en bouwde een lijst van 80 potentieel werkende e-mails. Eén phishingmail met een nep Office365-inlogpagina leidde tot vijf succesvolle loginpogingen. Alles begon bij de zichtbare gegevens in Hunter.io — zonder scanning, zonder toegang, puur via hacking op basis van gedrag en zichtbaarheid.

Praktische tips voor gebruik

  • Zoek ook op verwante domeinen zoals klantnaam-support.nl of klantnaamgroup.com
  • Gebruik wildcardtools om patronen te voorspellen: voorletter.achternaam@
  • Koppel aan tools zoals HaveIBeenPwned om te zien of adressen in datalekken voorkomen
  • Controleer ook PDF’s en whitepapers die op de website staan — Hunter.io indexeert ze vaak
  • Combineer met MailTester of Verify-email.org om live te testen of een e-mailadres nog actief is

Waarom pentesters Hunter.io inzetten

  • Eenvoudige interface, krachtige output
  • Laagdrempelig beginpunt van social engineering
  • Waardevolle input voor phishingcampagnes of Red Teaming
  • Snelle validatie van gebruikersstructuren
  • Uitstekende API voor automatisering in OSINT-workflows

Hunter.io is niet bedoeld als hackingtool, maar in de handen van een ethisch hacker wordt het een scherp mes. Het laat zien dat de zwakste schakel vaak geen technologie is, maar een mens — en dat die mens vaak eenvoudiger te benaderen is dan het netwerk.

003954

25. SecurityTrails (Asset & Domain Intelligence)

SecurityTrails OSINT search is een krachtige bron voor pentesters die willen achterhalen wat er aan domeinen, subdomeinen, IP-adressen en infrastructuur zichtbaar is van een organisatie. Waar veel tools zich richten op live scanning of open poorten, blinkt SecurityTrails uit in historische data, domeinkoppelingen en asset mapping. De tool is passief, snel en breed inzetbaar voor reconnaissance, Red Teaming en externe risicoanalyses.

SecurityTrails staat bekend om de nauwkeurigheid van zijn DNS- en infrastructuurdata. Het platform wordt veel gebruikt door zowel pentesters als threat hunters, vanwege de combinatie van historische DNS-informatie, IP-relaties, subdomein discovery en bedrijfsmatige asset-inventarisatie.

Wat maakt SecurityTrails waardevol voor pentesters

SecurityTrails verzamelt en indexeert informatie over:

  • Domeinen en subdomeinen
  • DNS-records (A, MX, TXT, NS, CNAME)
  • Historische DNS-data (tot jaren terug)
  • IP-adressen en hostinglocaties
  • AS-gegevens en netwerkstructuren
  • SSL-certificaten en reverse WHOIS-data

Je kunt zoeken op een domein, IP-adres, ASN of organisatie en snel een overzicht krijgen van alle online verbonden assets. Alles zonder actieve interactie met het doelwit.

Toepassingen in pentesting en hacking scenario’s

SecurityTrails is met name krachtig in de voorbereidende fase van een pentest, zoals:

  • Subdomain enumeration
    Zoek naar subdomeinen die niet meer in gebruik zijn, maar wel nog bestaan in DNS.
  • Asset discovery
    Krijg inzicht in andere domeinen, IP’s of infrastructuur die bij hetzelfde bedrijf horen.
  • Shadow IT detectie
    Vind oude of vergeten assets via historische DNS-data of SSL-certificaten.
  • Correlatie van IP en domeinen
    Koppel publieke IP’s aan interne systemen of cloudresources.
  • Passieve OSINT
    Verzamel waardevolle info zonder iets te scannen of op te vallen.

Voorbeeldgebruik: subdomeinlekkage

Tijdens een pentest voor een groot consultancybedrijf werd via SecurityTrails gezocht op het hoofddomein consultco.nl. Naast verwachte subdomeinen als mail. en vpn., werden ook oude staging-omgevingen gevonden zoals:

  • dev-v2.consultco.nl
  • clientportal-old.consultco.nl
  • sharepoint2010.consultco.nl

Door deze subdomeinen in een browser te openen, bleek dat enkele van deze legacy-systemen nog online waren. Eén SharePoint-instantie had geen authenticatie en bevatte honderden PDF-bestanden met klantgegevens. Alles werd gevonden zonder enige actieve hacking, puur door het analyseren van oude DNS-records en hostnames via SecurityTrails.

Belangrijkste functies voor pentesters

  • Subdomain Discovery
    Inclusief oude records die nergens anders meer zichtbaar zijn.
  • Reverse DNS / Reverse WHOIS
    Ontdek domeinen die bij dezelfde organisatie horen.
  • Certificate Search
    Zie welke domeinen certificaten delen, vergelijkbaar met crt.sh.
  • Historical Data View
    Bekijk wat er jaren geleden online stond en of het nu echt weg is.
  • ASN Lookup
    Koppel infrastructuur aan specifieke hostingbedrijven of cloudaanbieders.

SecurityTrails maakt het eenvoudig om overlooked infrastructure boven tafel te halen — vaak net de systemen die kwetsbaar zijn omdat ze vergeten zijn.

Integratie en API-gebruik

SecurityTrails biedt een krachtige REST API voor geautomatiseerd gebruik in pentest-workflows:

  • Query’s op domein, IP of ASN
  • Bulkzoekopdrachten en exports
  • Integratie met tools als Recon-ng, SpiderFoot, Maltego

Ook populair bij Red Teams die asset inventories opbouwen voorafgaand aan deep engagements.

Waarom SecurityTrails toevoegen aan je toolkit

  • Dieper dan standaard subdomain tools zoals Subfinder of Amass
  • Zeer geschikt voor stealth OSINT zonder scanverkeer
  • Detecteert infrastructuurrelaties tussen domeinen, IP’s en certificaten
  • Altijd toegang tot historische DNS-informatie
  • Snel overzicht van complete attack surface

SecurityTrails is niet gratis in uitgebreide vorm, maar de gratis versie geeft al veel waardevolle inzichten. Voor professionele pentesters is het een waardevolle aanvulling op tools als crt.sh, Netlas, Shodan en Censys.

003828

26. DNSDumpster (DNS Reconnaissance)

DNSDumpster DNS reconnaissance is een gratis, webgebaseerde zoekmachine die zich richt op het in kaart brengen van DNS-infrastructuur. Voor pentesters is het een snelle en effectieve manier om zicht te krijgen op subdomeinen, IP-adressen, hostnamen, en netwerkstructuren van een organisatie — zonder enige actieve interactie met het doelwit.

Waar tools als Shodan en Censys zoeken naar wat er draait op internet, kijkt DNSDumpster naar de naamgeving, structuur en koppelingen binnen domeinen. Die informatie vormt vaak het fundament van elke goede hacking-voorbereiding.

Waarom DNSDumpster interessant is voor pentesters

DNSDumpster verzamelt publiek beschikbare DNS-informatie uit meerdere bronnen, waaronder:

  • Open DNS-servers
  • Certificate transparency logs
  • Public webcrawlers
  • Zone transfers (indien mogelijk)
  • Subdomain bruteforcing (passief)

Het resultaat is een gedetailleerd overzicht van:

  • Subdomeinen
  • A-, MX-, TXT-, en NS-records
  • Hostingproviders en ASN’s
  • Reverse DNS-data
  • IP-geolocatie en visualisatie in netwerkkaart

Typische toepassingen in pentests

Pentesters zetten DNSDumpster vaak in tijdens de verkenningsfase:

  • Subdomein discovery
    Snel alle bekende subdomeinen van een doelwitdomein ophalen.
  • Detectie van e-mailservers
    MX-records tonen de mailstructuur van een organisatie.
  • Begrip van hosting- en netwerkstructuur
    Wie host wat? Zijn er afhankelijkheden van derde partijen?
  • Analyse van configuratiefouten
    Onverwachte A-records of TXT-records kunnen wijzen op testomgevingen, oude API’s of configuratieresten.
  • Opbouw van aanvalspaden
    Subdomeinen leiden vaak naar vergeten applicaties of interne tooling (zoals vpn., jira., dev., of old.)

Voorbeeldscenario uit de praktijk

Een Red Team-opdracht begon met een scope van bedrijfxyz.com. Via DNSDumpster werden binnen enkele seconden deze subdomeinen gevonden:

  • intranet.bedrijfxyz.com
  • api-legacy.bedrijfxyz.com
  • vpn01.bedrijfxyz.com

De DNS-kaart toonde dat de vpn01-subdomein resolveerde naar een IP in een legacy-datacenter. Door dit te combineren met een poortscan werd een verouderde SSL VPN gedetecteerd — met een bekende kwetsbaarheid. De toegang tot het interne netwerk begon dus met een simpele DNS-lookup.

Sterke punten van DNSDumpster

  • Geen registratie vereist — volledig toegankelijk via browser
  • Zeer snel en direct overzicht
  • Goede visuele weergave van relaties tussen subdomeinen, IP’s en netwerken
  • Passieve aanpak — géén verkeer naar het doelwit, dus stealth
  • Gratis beschikbaar — waardevol in fast recon of ad-hoc engagements

Vergelijking met andere subdomain tools

ToolTypeActief/passiefGeschikt voor stealth?Visualisatie
DNSDumpsterWeb-basedPassief✅ Ja✅ Ja
SubfinderCLI toolActief❌ Nee❌ Nee
AmassHybridHalf passief⚠️ Beperkt❌ Nee
crt.shCert logsPassief✅ Ja❌ Nee
SecurityTrailsAPI/webPassief✅ Ja⚠️ Beperkt

DNSDumpster is geen vervanging voor grotere frameworks, maar een snelle en visuele aanvulling op tools als crt.sh, Amass of Subfinder.

Tips voor gebruik in pentests

  • Combineer met crt.sh en SecurityTrails voor vollediger subdomeinbeeld
  • Zoek op alternatieve domeinen zoals bedrijfgroep.com, bedrijfcloud.net, etc.
  • Check op directe IP-koppelingen — sommige subdomeinen wijzen naar cloudinstances of legacyservers
  • Let op exposed TXT-records — bevatten soms API-sleutels, verificatiegegevens of SPF-instellingen die je verder helpen
  • Verzamel data vóór actieve scans — DNSDumpster biedt een perfecte basis voor scopevalidatie

Waarom DNSDumpster in je toolkit hoort

  • Laagdrempelig, snel en effectief
  • Ideaal voor de eerste OSINT-stap
  • 100% passief: geen verkeer naar doelwit
  • Handig voor presentaties of rapportages (visuele weergave)
  • Sterke combinatie met tools als Amass, crt.sh en Hunter.io

DNSDumpster is misschien niet het meest geavanceerde platform, maar zijn eenvoud maakt het juist zo krachtig. Het biedt in seconden een compleet DNS-profiel van het doelwit — en vaak is dat al genoeg om het eerste ingangspunt te vinden.

Lt4 3vhhri6ahmqp00x Xw

27. CertSpotter (Certificate Transparency Search)

CertSpotter certificate search is een krachtige, minder bekende tool waarmee pentesters certificaattransparantiegegevens kunnen doorzoeken om subdomeinen, infrastructuurveranderingen en onverwachte domeinkoppelingen te ontdekken. Deze zoekmachine, ontwikkeld door SSLMate, biedt toegang tot de wereldwijde Certificate Transparency (CT) logs die worden gebruikt om SSL/TLS-certificaten publiekelijk zichtbaar en controleerbaar te maken.

Voor een pentester is CertSpotter waardevol als passieve, niet-detecteerbare manier om nieuwe subdomeinen of services van een doelwit te identificeren — nog vóórdat DNS-records of traditionele tools ze kunnen detecteren.

Wat is CertSpotter precies

CertSpotter monitort Certificate Transparency logs op SSL-certificaten die worden uitgegeven voor een specifiek domein. Elke keer dat een certificaat wordt aangemaakt (zelfs als het voor een testomgeving is), wordt dit gelogd.

Een eenvoudige zoekopdracht zoals:

klantnaam.nl

Levert dan resultaten als:

  • vpn.klantnaam.nl
  • test-api.klantnaam.nl
  • fileshare.klantnaam.nl
  • *.internal.klantnaam.nl

Zelfs wildcard-certificaten en tijdelijke testcertificaten komen in de logs terecht. Vaak nog voordat subdomeinen publiekelijk in DNS staan of actief zijn.

Waarom dit nuttig is voor pentesters

Certificaattransparantie is een goudmijn voor OSINT. Pentesters gebruiken CertSpotter voor:

  • Subdomein reconnaissance — op basis van uitgegeven certificaten
  • Shadow IT-detectie — ontdek systemen die los zijn opgetuigd, zoals tijdelijke omgevingen
  • Validatie van infrastructuurveranderingen — wanneer een organisatie overstapt naar een andere CA of hostingprovider
  • Up-to-date zicht op attack surface — CT logs zijn realtime; je mist zelden iets nieuws
  • Detectie van onverwachte externe koppelingen — zoals derden die certificaten uitgeven voor jouw domein (potentieel misbruik)

Gebruiksscenario: subdomeinvondst via CertSpotter

Bij een pentest voor een overheidsinstantie zocht een Red Team naar verborgen systemen. Via CertSpotter kwamen wildcardcertificaten boven water voor:

  • *.dev.infra.overheid123.nl
  • *.internal-mgmt.overheid123.nl

Deze subdomeinen bestonden nog niet in DNS, maar waren wel al zichtbaar door de uitgifte van Let’s Encrypt certificaten. Een week later werden ze actief in DNS en bleken testversies van de productieomgeving te bevatten. Zonder een scan of actieve interactie had het team een voorsprong van dagen.

Voordelen van CertSpotter t.o.v. crt.sh

EigenschapCertSpottercrt.sh
Snelheid van updates✅ Zeer snel⚠️ Iets trager
Duplicaten gefilterd✅ Ja❌ Nee (veel noise)
API beschikbaar✅ Ja✅ Ja
Schone interface✅ Ja❌ Basis
Gebruik voor automation✅ Zeer geschikt⚠️ Minder overzichtelijk

CertSpotter levert minder ruis, snellere resultaten en betere filtering dan crt.sh, waardoor het beter integreerbaar is in pentest- of bug bounty workflows.

Integratie in workflows

CertSpotter kan worden geïntegreerd in tools zoals:

  • Recon-ng of custom OSINT scripts
  • Amass (CT log integration)
  • Nuclei templates voor subdomain monitoring
  • Bug bounty automation pipelines
  • Maltego transforms voor visualisatie

Het platform ondersteunt ook alerting via webhook-integratie, waardoor je als pentester notificaties krijgt bij nieuwe certificaten die aan een domein gekoppeld zijn.

Tips voor effectief gebruik

  • Zoek op hoofddomein én subdomeincombinaties: bedrijf.nl, infra.bedrijf.nl
  • Let op vreemde of niet-officiële issuers — kunnen wijzen op misbruik
  • Kijk naar oude certificaten met korte geldigheid — vaak voor tijdelijke testomgevingen
  • Combineer met SecurityTrails of DNSDumpster om te controleren of de subdomeinen resolven
  • Gebruik wildcardmatches om patronen te herkennen (*.vpn.bedrijf.nl, *.dev.bedrijf.nl)

Waarom CertSpotter in je toolkit thuishoort

  • Snelle detectie van nieuwe subdomeinen
  • Minimale ruis t.o.v. andere CT-tools
  • Volledig passieve en stealthy informatiebron
  • API geschikt voor automation
  • Nuttig voor Red Teams, OSINT-specialisten en bug bounty hunters

CertSpotter is de stille kracht in moderne reconnaissance. Het kijkt vooruit, waar andere tools slechts het heden kennen. Door gebruik te maken van deze transparante bron kom je vaak eerder op kwetsbare systemen dan de beheerder zelf.

Close-up van de hand van een persoon die op een toetsenbord typt met een computermonitor op de achtergrond met een beveiligde poort.

28. SpiderFoot HX (Geautomatiseerde OSINT)

SpiderFoot HX OSINT automation is een alles-in-één platform voor geautomatiseerde informatieverzameling. Pentesters gebruiken het om binnen enkele minuten een diepgaand profiel van een doelwit op te bouwen. Het platform doorzoekt honderden bronnen tegelijk — van domeingegevens tot data leaks — en doet dat volledig passief of met beperkte interactie.

Waar veel tools gespecialiseerd zijn in één databron (zoals DNS, WHOIS of IP-informatie), combineert SpiderFoot al die bronnen in één workflow. Ideaal voor Red Teams, bug bounty hunters en securityanalisten die snel zicht willen op de aanvalsvectoren van een organisatie.

Wat maakt SpiderFoot uniek

SpiderFoot verzamelt data via meer dan 200 modules die automatisch informatie ophalen uit o.a.:

  • DNS-records en subdomeinen
  • WHOIS-informatie
  • Leaked credentials en data leaks
  • Shodan, Censys, VirusTotal, HaveIBeenPwned
  • Geolocatie en netwerkdata
  • Social media en meta-informatie
  • Dark web monitoring (Tor, Onion-sites)

Je voert één zoekterm in, zoals een domein, IP, e-mailadres of naam, en SpiderFoot genereert een volledig rapport van alle gevonden relaties en risico’s.

Typische toepassingen voor pentesters

SpiderFoot HX wordt vaak ingezet in de verkenningsfase van een pentest, met als doel om snel een breed overzicht te krijgen van:

  • Externe attack surface
  • Subdomeinen, exposed IP’s en oude infrastructuur
  • Persoonsgegevens gekoppeld aan e-mails of gebruikersnamen
  • Credential leaks gekoppeld aan domeinen
  • Organisatorische structuren op basis van metadata en social links

De tool geeft je als pentester de kans om dieper te graven dan de meeste manuele OSINT-methodes, zonder dat je daar veel scripting of plugins voor nodig hebt.

Voorbeeldscenario: automatische asset mapping

Een pentester kreeg als opdracht: “breng in kaart welke externe systemen we hebben.” Met SpiderFoot werd een scan gedaan op het hoofddomein bedrijfxyz.nl. Binnen 10 minuten identificeerde het platform:

  • 58 subdomeinen (waarvan 12 niet in DNS zichtbaar waren)
  • 3 gelekte credentials in bekende breaches
  • 2 e-mailadressen van ex-medewerkers
  • 4 systemen met kwetsbare services (gevonden via Shodan-integratie)
  • Eén AWS S3-bucket met publieke toegang

De output was direct bruikbaar voor verdere analyse, zonder handmatige zoekacties of scripting.

Voordelen van SpiderFoot voor pentesting

  • Automatisering van OSINT-processen
  • Breed scala aan databronnen in één scan
  • Volledig browser-based (via HX platform) of zelf gehost
  • Resultaten visueel gepresenteerd met relatiegrafen
  • Mogelijkheid tot volledig passieve scans

De tool ondersteunt zowel actieve als passieve reconnaissance, afhankelijk van je aanpak. Voor stealth-operaties kun je modules uitschakelen die verkeer naar het doelwit genereren.

Integratiemogelijkheden

SpiderFoot kan gebruikt worden met:

  • Command line (voor scripting en automatisering)
  • Webinterface (HX) met dashboards en grafieken
  • Integratie met Maltego voor visualisatie
  • API voor export en verdere verwerking van data

De kracht ligt in de snelheid waarmee je van één datapunt (zoals een e-mailadres of domein) naar tientallen andere gerelateerde assets springt.

Tips voor gebruik in pentests

  • Scan eerst passief om detectie te voorkomen
  • Combineer met Shodan- en HaveIBeenPwned-modules voor diepgang
  • Gebruik ‘Use Case Templates’ zoals ‘Footprinting’, ‘Leak Discovery’ of ‘External Threat Mapping’
  • Exporteer naar CSV of JSON voor rapportages of verdere analyse
  • Check op tijd gefilterde resultaten — SpiderFoot toont ook indirecte associaties

Waarom SpiderFoot in je toolkit thuishoort

  • Automatiseert vervelend OSINT-handwerk
  • Geschikt voor startende én gevorderde pentesters
  • Toont direct verbanden tussen assets, personen en netwerken
  • Passieve en actieve scanopties geven flexibiliteit
  • API en CLI maken integratie eenvoudig in workflows

SpiderFoot HX is geen vervanger van handmatige analyse, maar een enorme versneller. Het is als een OSINT-turbomachine: één input, honderden resultaten. Voor pentesters die snel en slim willen werken, hoort deze tool standaard in de toolkit.

003898

29. Maltego Transform Hub (Relationele OSINT)

Maltego Transform Hub OSINT analysis is een krachtige visualisatietool waarmee pentesters complexe netwerken van relaties kunnen blootleggen. Waar veel zoekmachines werken met lijsten en tabellen, toont Maltego data als verbonden entiteiten — personen, domeinen, IP’s, e-mailadressen, infrastructuur en nog veel meer.

De kracht van Maltego zit in de Transform Hub: een bibliotheek van dataconnectors waarmee je met één klik informatie ophaalt uit tientallen bronnen zoals Shodan, HaveIBeenPwned, Hunter.io, VirusTotal, GreyNoise, en vele andere. Hierdoor is Maltego vooral geschikt voor diepgaande OSINT-analyses, persoonsgerichte aanvallen of Red Team-operaties waarbij inzicht in de samenhang tussen data cruciaal is.

Wat Maltego anders maakt dan andere tools

  • Visualisatie van verbanden tussen entiteiten, automatisch gegenereerd
  • Real-time pivoting op datapunten zoals IP’s, domeinen of personen
  • Modulaire opbouw met meer dan 60 geïntegreerde dataservices
  • Geschikt voor cross-analyse van technische, menselijke en contextuele data
  • Gebruik van publieke én commerciële bronnen via API-integraties

Voorbeelden van transforms

In de Transform Hub kunnen pentesters modules activeren voor onder andere:

  • Shodan (infrastructurele data)
  • Hunter.io (e-mailstructuur en domeingebonden e-mails)
  • WHOISXML (registratiegegevens)
  • VirusTotal (malware en URL reputatie)
  • GreyNoise (IP-beweging en scannerdetectie)
  • HaveIBeenPwned (leaked credentials)
  • DNSDB, Censys, crt.sh, ThreatMiner en meer

Elke transform levert directe data die als knooppunt aan de grafiek wordt toegevoegd.

Typische pentestscenario’s met Maltego

  • Targeted reconnaissance op basis van een naam of e-mailadres
  • Mapping van externe infrastructuur via DNS, subdomeinen, IP’s en certificaten
  • Opsporing van relaties tussen verschillende organisaties via gedeelde IP-blokken of infrastructuur
  • Samenstellen van context voor spear phishing of social engineering
  • Koppeling van leaks aan specifieke medewerkers of interne systemen

Praktisch voorbeeld: persoonsgerichte OSINT

Een pentester voert een scan uit op het e-mailadres j.delaat@bedrijfx.nl. Maltego toont binnen seconden:

  • Gekoppelde domeinen
  • Bijbehorende WHOIS-gegevens
  • Een LinkedIn-profiel met functietitel en vestigingsplaats
  • Github-projecten die een API-key bevatten
  • Een subdomein dat alleen vanuit DNS terug te vinden is
  • VirusTotal-hits op bijlagen die door dit e-mailadres zijn verzonden

De grafiek toont niet alleen de losse gegevens, maar ook hoe ze met elkaar verbonden zijn. Dit maakt het mogelijk om aanvalsvectoren in kaart te brengen die met traditionele tools over het hoofd worden gezien.

Voordelen van Maltego voor pentesters

  • Diepgang in relationele analyse, vooral bij menselijke doelen
  • Geen scripting nodig, maar wel krachtige automatisering
  • Geschikt voor multi-source OSINT in één interface
  • Ondersteunt export naar rapportageformaten
  • Beschikbaar als desktopapplicatie, ook zonder actieve scanactiviteit

Tips voor effectief gebruik

  • Werk van breed naar smal: begin met algemene entiteiten (zoals domein of organisatie) en zoom in
  • Combineer technische en sociale data voor effectievere aanvalsscenario’s
  • Gebruik de filters en visualisatieopties om grote grafieken beheersbaar te houden
  • Sla tussenstappen op om je OSINT flow later opnieuw te kunnen gebruiken of rapporteren
  • Activeer alleen relevante transforms om overbelasting of onnodige ruis te voorkomen

Waarom Maltego onmisbaar is in je toolkit

  • Ideaal voor Red Teaming en social engineering
  • Visualiseert verbanden die andere tools verbergen
  • Schaalbaar van kleine OSINT-onderzoeken tot complexe bedrijfsanalyses
  • Transformeerbare data, direct bruikbaar in rapportages
  • Sterk in combinatie met andere tools zoals Shodan, GreyNoise, crt.sh en Hunter.io

Maltego laat zien dat hacking niet altijd over techniek gaat — soms is het de combinatie van mensen, metadata en infrastructuur die de deur opent. Wie dat wil doorgronden, heeft met Maltego een krachtig wapen in handen.

Een close-up van een metalen sleutel met geëtste cijfers, gebruikt voor wachtwoordbeveiliging, liggend op een reflecterend donker oppervlak met een onscherpe achtergrond.

30. FOCA (Metadata & Document Reconnaissance)

FOCA metadata reconnaissance is een populaire OSINT-tool die zich richt op het analyseren van metadata in documenten die door organisaties online worden gepubliceerd. Denk aan PDF’s, Word-bestanden, Excel-sheets en PowerPoints — vaak onschuldig ogend, maar in werkelijkheid goudmijnen voor pentesters.

FOCA (Fingerprinting Organizations with Collected Archives) is vooral geliefd bij pentesters die zich richten op social engineering, interne netwerkinformatie, of het verkrijgen van contextuele data over een doelwitorganisatie, zonder dat er enige directe interactie met systemen nodig is.

Wat FOCA doet

FOCA downloadt en analyseert bestanden die via zoekmachines (zoals Google of Bing) gevonden kunnen worden op domeinen van het doelwit. De tool haalt vervolgens de metadata uit deze documenten, waaronder:

  • Gebruikersnamen van medewerkers
  • Gebruikte softwareversies en systeemnamen
  • Netwerkpaden en printers
  • Interne servernamen (zoals filesrv01.intern.local)
  • Tijdstempels, auteurs, titels en revisies

Deze informatie geeft inzicht in:

  • Interne structuur
  • Gebruikte technologieën
  • Mogelijke kwetsbaarheden
  • Persoonsinformatie bruikbaar voor phishing of impersonatie

Typische toepassingen voor pentesters

FOCA is vooral effectief in:

  • Voorbereiding van social engineering-aanvallen
    Achterhaal wie welke documenten aanmaakt en gebruik echte namen of afdelingen in pretexts.
  • Identificeren van interne systemen
    Ontdek domeinnamen, shares of servernamen zoals \\finance-fs01\, die later bruikbaar zijn in phishing of bij fysieke toegang.
  • Versies van software vinden
    Zie dat documenten zijn gemaakt met bijv. “Word 2007” op “Windows 7” — mogelijk kwetsbaar.
  • Opbouw van interne netwerkkaart
    Metadata bevat vaak verwijzingen naar interne netwerken die normaal onzichtbaar zijn voor externe scanners.

Voorbeeld uit de praktijk

Een pentester onderzocht de website van een grote gemeente. Via FOCA werden meer dan 200 documenten gevonden (zoals beleidsstukken en PDF-formulieren). De metadata onthulde:

  • 17 unieke gebruikersnamen van ambtenaren
  • Een netwerkprinter met naam GEMEENTE-MFP-01
  • Referentie naar \\gemeente-intra\projecten\WMO\
  • Dat een deel van de documenten met verouderde software was gemaakt (Office 2010)

Met deze info kon het Red Team zeer gerichte phishingmails sturen die verwezen naar projecten die écht bestonden — de klikratio was 70%.

Voordelen van FOCA

  • Volledig passieve informatieverzameling
  • Zoekt via zoekmachines (Google, Bing, DuckDuckGo)
  • Snelle analyse van honderden documenten tegelijk
  • Geeft diep inzicht in interne netwerkinrichting en gebruikers
  • Exportmogelijkheden voor rapportage en cross-verwijzingen

De tool is ideaal voor gebruik aan het begin van een pentest, zeker wanneer je geen actieve scans mag uitvoeren, of wanneer context nodig is voor Red Teaming of phishingcampagnes.

Integratie en aanvullingen

  • Combineer met Google Dorks om zelf documenten te vinden (site:bedrijf.nl filetype:pdf)
  • Gebruik samen met Maltego voor het koppelen van gebruikers aan online profielen
  • Combineer metadata met Hunter.io om te achterhalen welke e-mailstructuren in gebruik zijn
  • Cross-check interne netwerknamen met externe resolvability via DNS-tools

Waarom FOCA in je toolkit hoort

  • Unieke focus op document metadata, iets wat andere tools nauwelijks bieden
  • Zeer nuttig voor social engineering en interne netwerkanalyse
  • Gratis beschikbaar, veel gebruikt in Red Teaming
  • Perfect voor stealth reconnaissance in gevoelige omgevingen

FOCA laat zien dat informatielekkage niet alleen via systemen loopt, maar ook via Word- en PDF-bestanden. Wie die data weet te lezen, hoeft vaak niet eens een scan uit te voeren om zijn weg naar binnen te vinden.

Hackin 1

Hoe kies je de juiste search engine als pentester?

Beste search engine voor pentesters is geen absolute keuze, maar hangt af van je doel, doelgroep, en de fase waarin je je bevindt tijdens een pentest. Er zijn tientallen krachtige tools beschikbaar — van subdomain hunters tot threat intelligence-platformen. De kunst zit in het combineren, filteren en strategisch inzetten van de juiste zoekmachine, op het juiste moment.

Een effectieve pentester weet niet alleen wat een tool doet, maar ook wanneer je welke tool inzet voor maximaal resultaat.

Verschillen per categorie

Een overzicht van de hoofdcategorieën:

1. Server Search Tools

Tools zoals Shodan, Censys, Onyphe en Iv.re scannen het hele internet op open poorten, services en kwetsbare apparaten.

Gebruik bij:

  • Het in kaart brengen van extern blootgestelde systemen
  • Detecteren van verouderde services of softwareversies
  • Valideren van cloudexposure

Topkeuzes:

  • Shodan: snel, uitgebreid, veel filters
  • Censys: sterk in certificaten en internet-wide scanning
  • Onyphe: API-vriendelijk en goede integratie met threat feeds

2. OSINT & Email Reconnaissance

Tools als Hunter.io, IntelX en SecurityTrails brengen personen en infrastructuur samen.

Gebruik bij:

  • Voorbereiding van phishing of social engineering
  • Domeinanalyse en shadow IT-detectie
  • Subdomeinen vinden via transparantie en e-mailstructuren

Topkeuzes:

  • Hunter.io: direct inzicht in zakelijke e-mails
  • IntelX: zoekt ook in dark web en pastebins
  • SecurityTrails: uitstekend voor historische DNS-data en assetmapping

3. Threat Intelligence Platforms

Hier draait het om gedrag van scanners, bots, malware-IP’s en indicatoren van compromis.

Gebruik bij:

  • Detecteren of doelwit al onder vuur ligt
  • Beoordelen van risico’s per IP of domein
  • Valideren van pentestresultaten tegen live threat feeds

Topkeuzes:

  • GreyNoise: laat zien wie er aan het scannen is
  • BinaryEdge (App): threat intel gecombineerd met scanresultaten
  • Socradar / Pulsedive: IOC’s en cybercrime-monitoring

4. Code Search Engines

Tools als Grep.app, Searchcode en PublicWWW scannen miljoenen repositories en websites op gevoelige informatie.

Gebruik bij:

  • Vinden van API keys, credentials of private data in openbare code
  • Analyseren van veelgebruikte libraries of scripts
  • Detectie van codelekkages of verkeerde configuraties

Topkeuzes:

  • Grep.app: regex search in open source code
  • Searchcode: meer gefocust op specifieke talen of repo’s
  • PublicWWW: combineert code en marketingdata (zoals analytics IDs)

5. Attack Surface Mapping Tools

Hiermee breng je de volledige externe infrastructuur in kaart, vaak op schaal.

Gebruik bij:

  • Bug bounty reconnaissance
  • Red Team preparation
  • Validatie van scope in complexe cloudomgevingen

Topkeuzes:

  • FullHunt: gericht op bug bounty en scope mapping
  • Netlas.io: zeer breed en geschikt voor asset correlation
  • BinaryEdge.io: naast threat intel ook krachtig in attack surface
Pictogram met een versnelling omringd door circuitlijnen, die technologie of industriële processen symboliseren.

Wanneer gebruik je welke tool?

Doel van je onderzoekBeste eerste keuze
Subdomeinen vindenSecurityTrails, crt.sh, CertSpotter
Kwetsbare servers identificerenShodan, Censys, BinaryEdge
Emailadressen verzamelenHunter.io, IntelX
Gegevenslekken ontdekkenLeakix, Pulsedive, Vulners
Gedrag van scanners analyserenGreyNoise, Onyphe
Code analyseren op secretsGrep.app, Searchcode, PublicWWW
Realtime threat data raadplegenSocradar, Pulsedive, Fofa
Shadow IT of oude assets detecterenDNSDumpster, SecurityTrails, Netlas

Toekomst van pentesting search engines

De grenzen tussen OSINT, threat intelligence en asset discovery vervagen. Moderne tools integreren meerdere databronnen, combineren context met snelheid en richten zich op automation via API’s.

Verwacht:

  • Meer AI-gedreven correlatie tussen databronnen
  • Stealth OSINT-platformen die zelf niet traceerbaar zijn
  • Realtime alerts voor nieuwe assets of dreigingen
  • Gecombineerde dashboards met scoring, risico en bruikbaarheid
Vergrootglaspictogram over een lijngrafiek heen gelegd, dat data-analyse of financiële beoordeling symboliseert.

Praktische tips voor beginners

  • Begin met passieve tools (DNSDumpster, Hunter.io, crt.sh) om op te warmen zonder detectie
  • Gebruik tags en filters slim — veel tools bieden dorking of geavanceerde query’s
  • Automatiseer met API’s als je repetitieve taken uitvoert
  • Vergelijk resultaten altijd met minstens twee bronnen voor betrouwbaarheid
  • Log je queries en findings zodat je OSINT-sessie herhaalbaar en onderbouwd is

De beste search engine voor pentesters is degene die past bij je opdracht, scope en strategie. Combineer bronnen, werk gefaseerd en benut het volledige spectrum: van domeinniveau tot aan dreigingsniveau. Goede hacking begint bij slimme verkenning — en die start altijd met de juiste zoekmachine.

003870

Belangrijkste Inzichten uit de 30 Search Engines voor Pentesters

Een effectieve pentester combineert snelheid, precisie en informatie. Deze inzichten geven richting aan hoe je tooling strategisch inzet tijdens verkenning, analyse en rapportage.

  • Elke sterke pentest begint met passieve verkenning
    Zonder direct contact met het doelwit kun je via OSINT-tools al kritieke informatie verzamelen over infrastructuur, gebruikers en kwetsbaarheden. Dit biedt een stealthy voorsprong.
  • Koppeling van databronnen levert meer op dan losse feiten
    Het vermogen om data uit meerdere tools te combineren, zoals domeininformatie met certificaatdata of metadata, leidt tot diepere inzichten en betere aanvalskansen.
  • De juiste tool kies je op basis van doel en scenario
    Reconnaissance vóór phishing vraagt om andere tools dan netwerkverkenning. Denk vanuit je aanvalspad en pas je tooling daarop aan.
  • Alles wat zichtbaar is, kan worden benut in een aanval
    Search engines maken zichtbaar wat vaak buiten scope valt: oude subdomeinen, testservers of vergeten API’s. Wat online staat, ligt binnen bereik van een pentester.
  • Shadow IT is geen uitzondering maar een patroon
    Tools als SecurityTrails en Leakix tonen keer op keer dat bedrijven assets online hebben staan zonder dat ze het weten. Juist daar liggen de kansen.
  • Metadata verraadt vaak meer dan kwetsbare poorten
    Analyse van documenten, certificaten en profielen levert gevoelige informatie op over systemen, medewerkers en interne processen — zonder één scan.
  • Automatisering maakt massale verkenning haalbaar
    Tools zoals SpiderFoot HX en Maltego Transform Hub geven toegang tot honderden datapunten in minuten, en zijn onmisbaar bij bredere engagements of Red Teaming.
  • Threat intelligence maakt zichtbaar wie al op je doelwit jaagt
    GreyNoise, Pulsedive en BinaryEdge geven context aan je ontdekking: is dit systeem al onder vuur? Dat maakt het verschil tussen ruis en risico.
  • Veel tools zijn ook verdedigend inzetbaar
    Hoewel ontwikkeld voor offensieve doeleinden, kunnen search engines ook gebruikt worden om te zien wat een aanvaller ziet — en daarmee je eigen verdedigingspositie verbeteren.
  • Externe attack surfaces zijn dynamisch — monitoring moet dat ook zijn
    De zichtbaarheid van assets verandert constant. Tools die continu scannen en rapporteren zijn niet optioneel maar noodzakelijk voor elke moderne penteststrategie.