/* update variables when header is on dark background*/
.on-dark-bg {
   --header-bg: var(--current-header-bg);
   --chevron-clr: white;
   --menu-item-clr: white;
   --menu-item-hover-bg: #172235;
   --menu-item-hover-clr: #bc92e6;
   --menu-toggle-clr: var(--menu-item-clr);
   --dropdown-content-border: solid 1px rgb(220 220 220 / 20%);
   --mobile-menu-bg: var(--header-bg);
 }

 .on-light-bg {
   --menu-item-clr: black;
   /* update variables when header is on light background*/
 }


 /* update variable when on dark or light background */
 .on-dark-bg,
 .on-light-bg {
   --overlay-header-bg-active: var(--current-header-bg);
   --dropdown-content-bg: var(--current-header-bg);
 }

 .on-video-section {
   /* update variables when header is on video section*/
   --menu-item-clr: white;
   --chevron-clr: white;
   --menu-item-hover-bg: rgb(0 0 0 / 30%);
   --menu-item-hover-clr: #bc92e6;
   --dropdown-content-bg: rgb(0 0 0 / 70%);
   --overlay-header-bg: rgb(0 0 0 / 25%);
   --overlay-header-bg-active: var(--dropdown-content-bg);
   --dropdown-content-border: solid 1px rgb(220 220 220 / 20%);
   --current-header-bg: rgb(0 0 0 / 14%) !important;
   --header-bg: rgb(0 0 0 / 70%);
   --menu-toggle-clr: white;
   --mobile-menu-bg: rgb(0 0 0 / 95%);
   --menu-cta-border: var(--dropdown-content-border)
 }


 .on-hero-section {
   /* update variables when header is on hero section*/
 }

 /* header bg blure when on video section */
 html:not(.dwc-mobile) .dwc-nest-header.on-video-section {
   backdrop-filter: blur(var(--overlay-header-blur));
 }

 /* overlay header border when on video section or dark background*/
 .dwc-nest-header:is(.on-dark-bg, .on-video-section)[data-overlay-header="true"] {
   border: 1px solid rgba(255, 255, 255, 0.2);
 }

 /* header bottom border when on dark background or video section*/
 .dwc-nest-header:is(.on-dark-bg, .on-video-section) {
   border-bottom: 1px solid rgba(255, 255, 255, 0.2);
 }


 /* logo color when on dark background*/
 .on-dark-bg .dwc-nest-menu__logo path {
   fill: white;
 }

 /* logo color when on light background*/
 .on-dark-bg .dwc-nest-menu__logo path {
   /*define svg fill when logo is on light background */
 }

 /* logo color when on video background*/
 .on-video-section .dwc-nest-menu__logo path {
   fill: white;
 }

/*custom */

.on-dark-bg .mega-menu-magic__menu-icon-large{
   background-color: var(--current-header-bg);
    fill: #bc92e6;
    color: #bc92e6;
}

.on-video-section .mega-menu-magic__menu-icon-large{
   background-color: var(--current-header-bg);
    fill: #bc92e6;
    color: #bc92e6;
}

.on-video-section .mega-menu-magic__dropdown-title,
.on-dark-bg .mega-menu-magic__dropdown-title{
    color: rgb(210 210 210);   
}
// Constants
const BREAKPOINT_DESKTOP = 0;
const DEBOUNCE_DELAY = 50;

// Configuration object for all header-related selectors
const HEADER_CONFIG = {
  // Main header element
  headerElement: '.dwc-nest-header',
  // Wrapper element selectors (can be classes, IDs, or data attributes)
  wrapperSelectors: [
    // '.dwc-nest-header__container'
  ],
  // Elements to monitor for header styling (can include any CSS selector)
  // Default monitors sections, but you can add footer, divs, or any element
  monitoredElements: 'section, [data-header-zone]',
  // Store original header background color
  originalHeaderBgColor: null
};

// Unified section type configuration
// Add new data attributes here - they will be automatically mapped to header classes
const SECTION_TYPES = {
  'data-hero': 'on-hero-section',
  'data-video': 'on-video-section',
  'data-custom': 'on-custom-section',
  'data-sticky': 'on-media-section'
  // Add new: 'data-feature': 'on-feature-section'
};

// Configuration for excluded sections
const EXCLUSION_CONFIG = {
  // Data attribute that identifies sections to exclude from header styling
  sectionAttribute: 'data-exclude-header'
};

// Text color classes
const TEXT_CLASSES = {
  light: 'on-dark-bg',
  dark: 'on-light-bg'
};

// Generate classes to remove dynamically from SECTION_TYPES and text classes
const ALL_CLASSES_TO_REMOVE = [
  // Add all header classes from section types
  ...Object.values(SECTION_TYPES),
  // Add text color classes
  TEXT_CLASSES.light,
  TEXT_CLASSES.dark
];

// Performance optimization: Cache DOM elements and computed values
const CACHE = {
  headerElement: null,
  wrapperElement: null,
  sections: [],
  sectionsData: new Map(),
  colorCache: new Map(),
  tempColorElement: null,
  lastKnownSection: null,
  isUpdating: false,
  pendingColorUpdate: false
};

// Initialize cache
function initializeCache() {
  // Cache header elements
  CACHE.headerElement = document.querySelector(HEADER_CONFIG.headerElement);
  
  // Try each wrapper selector until one is found
  for (const selector of HEADER_CONFIG.wrapperSelectors) {
    CACHE.wrapperElement = document.querySelector(selector);
    if (CACHE.wrapperElement) break;
  }
  
  // Cache sections and their positions
  CACHE.sections = Array.from(document.querySelectorAll(HEADER_CONFIG.monitoredElements));
  
  // Create reusable element for color calculations
  CACHE.tempColorElement = document.createElement('div');
  CACHE.tempColorElement.style.position = 'absolute';
  CACHE.tempColorElement.style.visibility = 'hidden';
  CACHE.tempColorElement.style.pointerEvents = 'none';
  document.body.appendChild(CACHE.tempColorElement);
  
  // Cache section metadata
  updateSectionsCache();
}

// Update sections cache (call when DOM changes)
function updateSectionsCache() {
  CACHE.sections = Array.from(document.querySelectorAll(HEADER_CONFIG.monitoredElements));
  CACHE.sectionsData.clear();
  
  CACHE.sections.forEach((section, index) => {
    const sectionData = {
      index,
      isExcluded: section.hasAttribute(EXCLUSION_CONFIG.sectionAttribute)
    };
    
    // Dynamically check for all section types defined in SECTION_TYPES
    Object.keys(SECTION_TYPES).forEach(attribute => {
      sectionData[attribute] = section.hasAttribute(attribute);
    });
    
    CACHE.sectionsData.set(section, sectionData);
  });
}

// Function to remove all section classes from :root only
function removeAllSectionClasses() {
  const rootElement = document.documentElement;
  
  // Remove classes from :root only
  rootElement.classList.remove(...ALL_CLASSES_TO_REMOVE);
}

// Function to update the CSS variable on :root
function updateRootBackgroundVariable(color) {
  document.documentElement.style.setProperty('--current-header-bg', color);
}

// Function to apply classes to :root only
function applyClassesToRoot(headerClass, textClass) {
  const rootElement = document.documentElement;
  
  // Apply header class to :root only
  if (headerClass) {
    rootElement.classList.add(headerClass);
  }
  
  // Apply text class to :root only
  if (textClass) {
    rootElement.classList.add(textClass);
  }
}

// Optimized color conversion using cached temp element
function getRGBValues(color) {
  const cacheKey = color;
  if (CACHE.colorCache.has(cacheKey)) {
    return CACHE.colorCache.get(cacheKey);
  }
  
  CACHE.tempColorElement.style.color = color;
  const computedColor = window.getComputedStyle(CACHE.tempColorElement).color;
  
  // Extract RGB values
  const match = computedColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
  const result = match ? {
    r: parseInt(match[1]),
    g: parseInt(match[2]),
    b: parseInt(match[3])
  } : { r: 255, g: 255, b: 255 };
  
  // Cache the result
  CACHE.colorCache.set(cacheKey, result);
  return result;
}

// Function to check if a background color is transparent or empty
function isBackgroundTransparent(color) {
  if (!color) return true;
  
  const transparentValues = [
    'transparent',
    'rgba(0, 0, 0, 0)',
    'rgba(0,0,0,0)',
    'initial',
    'inherit',
    ''
  ];
  
  return transparentValues.includes(color.toLowerCase().replace(/\s/g, ''));
}

// Function to determine if a color is dark or light
function isColorDark(color) {
  if (color === 'transparent' || color === 'rgba(0, 0, 0, 0)') {
    return false;
  }
  
  const rgb = getRGBValues(color);
  const luminance = (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255;
  return luminance < 0.5;
}

// Optimized section detection using cached data
function getCurrentSection() {
  if (!CACHE.headerElement || CACHE.sections.length === 0) return null;
  
  const headerHeight = CACHE.headerElement.offsetHeight;
  
  // Quick check if we're still in the same section
  if (CACHE.lastKnownSection) {
    const rect = CACHE.lastKnownSection.getBoundingClientRect();
    if (rect.top <= headerHeight && rect.bottom > headerHeight) {
      return CACHE.lastKnownSection;
    }
  }
  
  // Binary search would be ideal here, but simple loop is sufficient for most cases
  for (const section of CACHE.sections) {
    const rect = section.getBoundingClientRect();
    if (rect.top <= headerHeight && rect.bottom > headerHeight) {
      CACHE.lastKnownSection = section;
      return section;
    }
  }
  
  const firstSection = CACHE.sections[0] || null;
  CACHE.lastKnownSection = firstSection;
  return firstSection;
}

// Function to get computed background color with caching
function getComputedBackgroundColor(element) {
  const cacheKey = element;
  if (CACHE.colorCache.has(cacheKey)) {
    return CACHE.colorCache.get(cacheKey);
  }
  
  const bgColor = window.getComputedStyle(element).backgroundColor;
  CACHE.colorCache.set(cacheKey, bgColor);
  return bgColor;
}

// Function to initialize original header background color
function initializeOriginalHeaderBgColor() {
  if (CACHE.headerElement) {
    HEADER_CONFIG.originalHeaderBgColor = window.getComputedStyle(CACHE.headerElement).backgroundColor;
  }
}

// Function to determine header style configuration based on section
function determineHeaderConfig(section) {
  if (!section) return null;
  
  const sectionData = CACHE.sectionsData.get(section);
  if (!sectionData) return null;
  
  // If section is excluded, return null to skip styling
  if (sectionData.isExcluded) {
    return null;
  }
  
  // Dynamically check for any section type defined in SECTION_TYPES
  for (const [attribute, headerClass] of Object.entries(SECTION_TYPES)) {
    if (sectionData[attribute]) {
      return {
        backgroundColor: null,
        headerClass: headerClass,
        needsWhiteText: null,
        isSpecialSection: true
      };
    }
  }
  
  // Get the actual background color of the section
  const sectionBgColor = getComputedBackgroundColor(section);
  
  if (isBackgroundTransparent(sectionBgColor)) {
    return {
      backgroundColor: HEADER_CONFIG.originalHeaderBgColor || 'rgb(255, 255, 255)',
      headerClass: null,
      needsWhiteText: isColorDark(HEADER_CONFIG.originalHeaderBgColor || 'rgb(255, 255, 255)'),
      isSpecialSection: false
    };
  }
  
  const needsWhiteText = isColorDark(sectionBgColor);
  
  return {
    backgroundColor: sectionBgColor,
    headerClass: null,
    needsWhiteText: needsWhiteText,
    isSpecialSection: false
  };
}

// Function to apply styles (background color to header, classes to :root only)
function applyHeaderStyles(config) {
  if (!CACHE.headerElement || !config) return;
  
  const elementsToStyle = [CACHE.headerElement, CACHE.wrapperElement].filter(Boolean);
  
  // Use requestAnimationFrame for smooth visual updates
  requestAnimationFrame(() => {
    // First, remove all section classes and text classes from :root only
    removeAllSectionClasses();
    
    // Update the root CSS variable with background color
    if (config.backgroundColor !== null) {
      const appliedBgColor = config.backgroundColor || '';
      updateRootBackgroundVariable(appliedBgColor);
    } else {
      updateRootBackgroundVariable('');
    }
    
    // Determine text class to apply
    const textClass = config.needsWhiteText !== null 
      ? (config.needsWhiteText ? TEXT_CLASSES.light : TEXT_CLASSES.dark)
      : null;
    
    // Apply classes to :root only
    applyClassesToRoot(config.headerClass, textClass);
    
    // Handle background color on header elements only
    elementsToStyle.forEach(element => {
      if (config.backgroundColor !== null) {
        const appliedBgColor = config.backgroundColor || '';
        element.style.backgroundColor = appliedBgColor;
      } else {
        element.style.backgroundColor = '';
      }
    });
    
    // For special sections, allow CSS to apply first, then get computed background color
    if (config.isSpecialSection && config.headerClass) {
      // Use setTimeout(0) to ensure CSS has been applied, but batch multiple calls
      if (!CACHE.pendingColorUpdate) {
        CACHE.pendingColorUpdate = true;
        setTimeout(() => {
          // Process all elements that need color updates in this batch
          elementsToStyle.forEach(el => {
            // Check if element has any of the section classes (though they're not applied anymore)
            const hasSectionClass = Object.values(SECTION_TYPES).some(className => 
              el.classList.contains(className)
            );
            
            if (hasSectionClass) {
              const computedBgColor = getComputedBackgroundColor(el);
              updateRootBackgroundVariable(computedBgColor);
            }
          });
          CACHE.pendingColorUpdate = false;
        }, 50);
      }
    }
    
    CACHE.isUpdating = false;
  });
}

// Throttled update function using requestAnimationFrame
function updateHeaderStyles() {
  // Prevent multiple updates in the same frame
  if (CACHE.isUpdating) return;
  
  // Apply only on screens larger than the breakpoint
  if (window.innerWidth <= BREAKPOINT_DESKTOP) {
    return;
  }
  
  CACHE.isUpdating = true;
  
  const currentSection = getCurrentSection();
  if (!currentSection) {
    CACHE.isUpdating = false;
    return;
  }
  
  const headerConfig = determineHeaderConfig(currentSection);
  if (!headerConfig) {
    CACHE.isUpdating = false;
    return;
  }
  
  applyHeaderStyles(headerConfig);
}

// Debounce function for resize events (less frequent)
function debounce(func, wait) {
  let timeout;
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout);
      func(...args);
    };
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
}

// RAF-based throttle for scroll events
let rafId = null;
function throttleWithRAF(func) {
  return function(...args) {
    if (rafId) return;
    
    rafId = requestAnimationFrame(() => {
      func.apply(this, args);
      rafId = null;
    });
  };
}

// Initialize everything
function initialize() {
  initializeCache();
  initializeOriginalHeaderBgColor();
  updateHeaderStyles();
}

// Cleanup function
function cleanup() {
  if (CACHE.tempColorElement && CACHE.tempColorElement.parentNode) {
    CACHE.tempColorElement.parentNode.removeChild(CACHE.tempColorElement);
  }
  if (rafId) {
    cancelAnimationFrame(rafId);
  }
}

// Initialize on page load
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', initialize);
} else {
  initialize();
}

// Create optimized event handlers
const throttledUpdateHeaderStyles = throttleWithRAF(updateHeaderStyles);
const debouncedUpdateHeaderStyles = debounce(() => {
  updateSectionsCache(); // Refresh cache on resize
  updateHeaderStyles();
}, DEBOUNCE_DELAY);

// Add event listeners with passive option for better performance
window.addEventListener('scroll', throttledUpdateHeaderStyles, { passive: true });
window.addEventListener('resize', debouncedUpdateHeaderStyles, { passive: true });

// Cleanup on page unload
window.addEventListener('beforeunload', cleanup);

Hofstra University

The Strength and Conditioning Facility at David S. Mack Sports and Exhibition Complex

Hempstead, NY

Hofstra + Advantage: The Perfect Equation

When preparing to renovate their strength and conditioning facility at the David S. Mack Sports and Exhibition Complex, the athletic department staff at Hofstra University realized that giving student athletes access to the right tools at this point in their careers would have a lifelong impact on them. The same way they take every opportunity to improve academics, they take pride in improving all aspects of student life. The new weight room at the David S. Mack Sports and Exhibition Complex is absolutely incredible, and Advantage was delighted to contribute to the project.

Kelly Shaver, Associate Director of Athletics for Sports Performance at Hofstra University had previously worked with Advantage Sport & Fitness on weight room projects. He wanted to work with a company and an expert who he could rely on to deliver the right layout, recommend durable top-of-the-line equipment, and be available and present for the duration of the project. Based on those needs and his past experience, Kelly knew the clear choice was Territory Sales Manager Rob Anspach and the Advantage Team.

Branded fitness equipment at Hofstra University

Hofstra University Showcase

Behind the Hofstra University project

Maximizing space

Kelly notes that at the start of the project, the most important aspect was maximizing the space they had to work with. They needed a layout and an assortment of equipment that could easily handle team rosters of between 8 and 38 within the same room.

Another element that was very important to Hofstra was branding. They wanted to integrate their colors logo, and slogans prominently on equipment and throughout the space so it oozed Hofstra spirit.

The effort

When it came to securing optimal equipment, Kelly wanted his selections to last and knew premium pieces were an investment worth making. Knowing that Power Lift has a reputation for durability, an array of accessories, and lots of customization options, Rob and Kelly landed on 10 Power Lift Half Racks with Rhino Hook Bar Catches and upgraded bumper storage, all with the complete branding details Hofstra sought to achieve. 10 9’ Power-Lift half racks with custom laser engraved uprights, chin handles, bar catches, custom power block storage and kettlebell storage.

Branded fitness equipment at Hofstra University

Customization and branding

The room also includes benches with custom logos on the frame and embossed upholstery, which is a really nice, elevated touch.

Additional strength pieces include Power-Lift Pro Select 2x Free Standing Pulley, Leg Extension and Prone Leg Curl, well rounded workouts suitable for all sports.

Custom Bumper plates from Ferus Prime are seen donning the words “Hofstra Pride”, as well a Custom Bar end caps, featuring the Hofstra “H.”

Last but certainly not least, the flooring is the ultimate game-changer. With Ecore Beast Rubber flooring specially designed for strength training and engineered to last. With the custom Hofstra “H” custom branded inlaid lifting platforms, the floor combines functionality with aesthetics for big win!

Branded fitness equipment at Hofstra University

The reward

It’s been fulfilling to hear all positive feedback from Kelly regarding the new facility. The Hofstra community has expressed gratitude and the weight room has become more than a place for athletes to train, but also a standout feature that enhances the school’s appeal.

Interested in seeing more spaces like this? Click here.

The athletes at Hofstra University now have the space and tools they need to succeed, bring home wins and make their school proud. Through our partnership with Hofstra, we were able to help bring their vision to life and provide a competitive edge that will serve them for years to come.

We love sharing our expertise and design ideas with clients in collegiate athletics and beyond. If you are ready to explore options for your fitness space, get in touch with our team.

Hofstra University Testimonial

Branded fitness equipment at Hofstra University

"A space that coaches love showing off to parents, recruits, and alumni"

“Rob was outstanding and made the whole renovation process from concept to installation very easy. Rob was always a quick phone call or email away to help us navigate and manage all the moving pieces that comes with a large project like a weight room renovation. The reaction has been overwhelmingly positive from administration, coaches, student-athletes, and staff. It’s a space that the student-athletes love coming to and a space that the coaches love showing off to parents, recruits, and alumni.”

Kelly Shaver,
Associate Director of Athletics for Sports Performance, Hofstra University

Ready to start your next project?

As the largest and most experienced gym equipment provider on the east coast, our team will pull out all the stops to provide the top-of-the-line fitness solutions you are looking for. Contact us to start a conversation.