More Global’s Cyber and Data Security experts are ready to help you protect and leverage your Cyber and Data Security.
"*" indicates required fields
"*" indicates required fields
"*" indicates required fields
				
			@import "../../resources/scss/util/variables";
@import "../../resources/scss/util/mixins";
.block-contact {
  position: relative;
	padding: rem-calc(60px) 0;
	/** Removed Temp for sync
	&.block-contact--no-tabs {
		.block-contact__content>div:nth-of-type(2) {
			grid-row: 1;
		}
		.tab-content {
			padding-top: 30px;
			@include bp($xl) {
				padding-top: 0;
			}
		}
	}
		**/
  .gform_wrapper.gravity-theme {
    input::placeholder,
    textarea::placeholder,
    select::placeholder {
      color: rgba(255, 255, 255, 0.4);
      opacity: 1; /* Firefox requires this to customize placeholders */
    }
  }
  &.has-secondary-background-color {
    .gform_wrapper.gravity-theme {
      input[type=submit].gform_button {
        background-color: $primary-blue;
        border-color: $primary-blue;
        &:hover {
          background-color: $primary;
          border-color: $primary;
        }
      }
    }
  }
  &.has-background:not(.has-light-blue-background-color) {
    color: $white;
    p {
      color: $white;
    }
    .block-contact__sidebar {
      &:after {
        background-color: rgba(255, 255, 255, .2);
      }
    }
    .gform_wrapper.gravity-theme {
      .gfield_required {
        color: $white;
      }
      .gform_body {
        .gfield {
          input,
          textarea,
          select {
            border-color: rgba(255, 255, 255, .2);
          }
          select {
            background-image: url('/wp-content/themes/moore-global/assets/icons/select-dropdown-light.svg');
          }
        }
        .gfield_error .gfield_label,
        .gfield_error label {
          color: $white;
        }
        .gfield_radio {
          input[type=radio]:after {
            background-color: $white;
          }
        }
        .gfield_checkbox input[type=checkbox]:checked {
          background: url('/wp-content/themes/moore-global/assets/icons/checked-light.svg') center/40% no-repeat transparent;
        }
        .gfield_html {
          a {
            color: $white;
          }
        }
        .ginput_container_consent input[type=checkbox]:checked {
          background: url('/wp-content/themes/moore-global/assets/icons/checked-light.svg') center/40% no-repeat transparent;
        }
        // .gfield_description.gfield_validation_message {
        //   padding: 8px 12px;
        //   background: #fff9f9;
        //   border-radius: 5px;
        // }
      }
    }
  }
  &__sidebar {
		@include section-sidebar;
    background-color: transparent;
	}
  &__content {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    padding: 0 16px;
    column-gap: $grid-gutter-width;
    position: relative;
    z-index: 2;
    @include bp($lg) {
      padding: 0 80px;
    }
    & > div {
      &:nth-of-type(1) {
        grid-row: 1;
        grid-column: 1 / 13;
        margin-bottom: 30px;
        @include bp($xl) {
          margin-bottom: 0;
          grid-column: 2 / 6;
        }
      }
      &:nth-of-type(2) {
        grid-row: 2;
        grid-column: 1 / 13;
        @include bp($xl) {
          grid-row: 1;
          grid-column: 7 / 13;
        }
      }
    }
    h1, h2, h3, h4, h5, h6 {
      @include fluid-type(24, 40, 375, $max-container-size);
      font-weight: 400;
    }
    p {
      line-height: 1.5;
    }
  }
  &__tabs {
    @include list-unstyled;
    margin: 0 0 35px;
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    column-gap: clamp(20px, 2vw, 40px);
    row-gap: 16px;
    overflow-x: auto;
    width: calc(100% + 32px);
    position: relative;
    left: -16px;
    padding: 0 16px;
    -ms-overflow-style: none;
    scrollbar-width: none;
    @include bp($md) {
      flex-wrap: wrap;
      overflow: hidden;
      width: auto;
      left: auto;
      padding: 0;
    }
    &::-webkit-scrollbar {
      display: none;
    }
    li {
      text-transform: uppercase;
      letter-spacing: 0.05em;
      line-height: 1;
      position: relative;
      cursor: pointer;
      padding-bottom: 5px;
      white-space: nowrap;
      &:after {
        content: "";
        width: 100%;
        height: 2px;
        display: block;
        background-color: $primary-blue;
        position: absolute;
        left: 0;
        bottom: 0;
        max-width: 0;
        transition: max-width .2s;
      }
      &.current {
        font-weight: 600;
        &:after {
          max-width: 100%;
        }
      }
      &:hover:after {
        max-width: 100%;
      }
    }
  }
  .tab-content {
    display: none;
    &.current {
      display: block;
    }
  }
  picture {
    z-index: 1;
  }
  // Single form styles
  &--single-form {
    .block-contact__content {
      & > div {
        &:nth-of-type(1) {
          margin-bottom: 30px;
          @include bp($xl) {
            margin-bottom: 0;
          }
        }
        &:nth-of-type(2) {
          grid-row: 2;
          grid-column: 1 / 13;
          margin: 0;
          padding: 0;
          @include bp($xl) {
            grid-row: 1;
            grid-column: 7 / 13;
          }
          > div {
            margin: 0;
            padding: 0;
          }
        }
      }
      .gform_wrapper {
        .gform_description,
        .gfield_description {
          margin: 0;
          padding: 0;
        }
      }
    }
    .block-contact__tabs {
      display: none;
      margin: 0;
      padding: 0;
    }
    .tab-content {
      display: block !important;
      opacity: 1 !important;
      margin: 0;
      padding: 0;
    }
    .tab-content-wrapper {
      margin: 0;
      padding: 0;
    }
  }
  // Tab content wrapper styles
  .tab-content-wrapper {
    // Add any specific tab content wrapper styles here if needed
  }
}
				
			class ContactBlock {
	constructor() {
		this.init();
	}
	init() {
		// Find all contact blocks on the page
		this.blocks = document.querySelectorAll('.block-contact');
		if (!this.blocks.length) return;
		// Set up tab click handlers
		this.setupTabClickHandlers();
		// Check URL parameters on page load
		this.handleUrlParameters();
		// Expose global navigation function
		window.navigateToContactTab = this.navigateToContactTab.bind(this);
		// Set up special link interceptor
		this.setupLinkInterceptor();
		//console.log('ContactBlock initialized with', this.blocks.length, 'blocks found');
	}
	setupLinkInterceptor() {
		// Add a global click handler for all links on the page
		document.addEventListener('click', (event) => {
			// Check if the click was on an anchor or its child
			const link = event.target.closest('a');
			if (!link) return;
			// Get the href attribute
			const href = link.getAttribute('href');
			if (!href) return;
			// Check if it matches our special pattern: #fragment?tab=number
			if (href.includes('#') && href.includes('?tab=')) {
				// Prevent the default navigation
				event.preventDefault();
				//console.log('Intercepted link click with URL:', href);
				// Parse the URL
				let hashPart = '';
				let tabParam = null;
				// Case 1: Full URL with hash and parameters
				if (href.includes('://' && href.includes('#'))) {
					const urlParts = href.split('#');
					if (urlParts.length > 1) {
						const hashAndQuery = urlParts[1];
						if (hashAndQuery.includes('?')) {
							const fragmentParts = hashAndQuery.split('?');
							hashPart = '#' + fragmentParts[0];
							const queryPart = new URLSearchParams(fragmentParts[1]);
							tabParam = queryPart.get('tab');
						}
					}
				}
				// Case 2: Just hash and parameters
				else if (href.startsWith('#') && href.includes('?')) {
					const fragmentParts = href.split('?');
					hashPart = fragmentParts[0];
					const queryPart = new URLSearchParams(fragmentParts[1]);
					tabParam = queryPart.get('tab');
				}
				//console.log('Parsed link parts:', { hashPart, tabParam });
				// If we have the hash and tab parameter, handle the navigation
				if (hashPart && tabParam !== null) {
					// Get the target element
					const targetId = hashPart.startsWith('#') ? hashPart : `#${hashPart}`;
					let targetElement = document.querySelector(targetId);
					// Try alternative methods to find the element
					if (!targetElement && targetId.startsWith('#')) {
						const idWithoutHash = targetId.substring(1);
						targetElement = document.getElementById(idWithoutHash);
					}
					// If still not found and it's contact-section, try the contact block
					if (!targetElement && (targetId === '#contact-section' || targetId === 'contact-section')) {
						targetElement = document.querySelector('.block-contact');
					}
					// If still not found, just use any contact block
					if (!targetElement) {
						targetElement = document.querySelector('.block-contact');
					}
					if (targetElement) {
						// Process the tab parameter
						const tabIndex = parseInt(tabParam) - 1;
						// Select the tab first
						this.blocks.forEach(block => {
							const tabs = block.querySelectorAll('.tab-link');
							if (tabIndex >= 0 && tabIndex < tabs.length) {
								tabs[tabIndex].click();
							}
						});
						// Then scroll to the target
						setTimeout(() => {
							const headerHeight = document.querySelector('header')?.offsetHeight || 0;
							const additionalOffset = 60;
							const scrollPosition = targetElement.getBoundingClientRect().top +
								window.pageYOffset - headerHeight - additionalOffset;
							window.scrollTo({
								top: scrollPosition,
								behavior: 'smooth'
							});
							// Update the URL hash without page reload
							history.pushState(null, null, hashPart);
						}, 100);
					}
				}
			}
		});
	}
	setupTabClickHandlers() {
		this.blocks.forEach(block => {
			const tabs = block.querySelectorAll('.tab-link');
			const tabContents = block.querySelectorAll('.tab-content');
			//console.log('Setting up tab handlers for', tabs.length, 'tabs');
			tabs.forEach(tab => {
				tab.addEventListener('click', () => {
					// Remove current class from all tabs and contents
					tabs.forEach(t => t.classList.remove('current'));
					tabContents.forEach(c => c.classList.remove('current'));
					// Add current class to clicked tab
					tab.classList.add('current');
					// Show the corresponding tab content
					const tabId = tab.getAttribute('data-tab');
					const tabContent = block.querySelector(`#${tabId}`);
					//console.log('Tab clicked:', tabId, tabContent ? 'found' : 'not found');
					if (tabContent) {
						tabContent.classList.add('current');
					}
				});
			});
		});
	}
	handleUrlParameters() {
		// Check for regular tab parameter in query string
		const urlParams = new URLSearchParams(window.location.search);
		let tabParam = urlParams.get('tab');
		// Check for the special case where #section?tab=1 format is used
		// This happens when the hash is followed by query parameters
		if (!tabParam && window.location.hash && window.location.hash.includes('?')) {
			const hashParts = window.location.hash.split('?');
			const hashFragment = hashParts[0];
			const hashQuery = new URLSearchParams(hashParts[1]);
			tabParam = hashQuery.get('tab');
			// Store the clean hash for later use
			this.cleanHash = hashFragment;
			//console.log('Special URL format detected:', window.location.hash, 'cleaned to', this.cleanHash, 'with tab param', tabParam);
		} else {
			this.cleanHash = window.location.hash;
			//console.log('Standard URL format:', window.location.hash, 'with search params', window.location.search, 'tab param:', tabParam);
		}
		// If we have a tab parameter, select the tab
		if (tabParam !== null) {
			// Find the corresponding tab (tab indexes are 0-based in code but 1-based in URL)
			const tabIndex = parseInt(tabParam) - 1;
			//console.log('Setting active tab to index', tabIndex);
			this.blocks.forEach(block => {
				const tabs = block.querySelectorAll('.tab-link');
				// If the tab index is valid
				if (tabIndex >= 0 && tabIndex < tabs.length) {
					// Click the tab to activate it
					setTimeout(() => {
						//console.log('Clicking tab at index', tabIndex);
						tabs[tabIndex].click();
					}, 100);
				} else {
					//console.log('Tab index out of range:', tabIndex, 'max is', tabs.length - 1);
				}
			});
		}
		// Check for fragment identifier (anchor)
		if (this.cleanHash) {
			// Allow the page to first render and tabs to be set
			setTimeout(() => {
				//console.log('Looking for element with ID:', this.cleanHash);
				// Try multiple selector methods
				let targetElement = null;
				// Method 1: Direct querySelector
				targetElement = document.querySelector(this.cleanHash);
				// Method 2: Try without the # if it starts with one
				if (!targetElement && this.cleanHash.startsWith('#')) {
					const idWithoutHash = this.cleanHash.substring(1);
					targetElement = document.getElementById(idWithoutHash);
					//console.log('Trying getElementById with:', idWithoutHash, targetElement ? 'found' : 'not found');
				}
				// Method 3: If we're looking for contact-section, get the contact block directly
				if (!targetElement && (this.cleanHash === '#contact-section' || this.cleanHash === 'contact-section')) {
					targetElement = document.querySelector('.block-contact');
					//console.log('Falling back to .block-contact selector:', targetElement ? 'found' : 'not found');
				}
				// Method 4: Last resort - find any contact block with an ID
				if (!targetElement) {
					targetElement = document.querySelector('.block-contact[id]');
					//console.log('Last resort - any contact block with ID:', targetElement ? 'found' : 'not found');
				}
				if (targetElement) {
					//console.log('Target element found:', targetElement);
					// Get header height for proper offset
					const headerHeight = document.querySelector('header')?.offsetHeight || 0;
					const additionalOffset = 60;
					// Calculate scroll position
					const scrollPosition = targetElement.getBoundingClientRect().top +
						window.pageYOffset - headerHeight - additionalOffset;
					//console.log('Scrolling to position:', scrollPosition, 'with offset adjustments:',
					//	'headerHeight=', headerHeight, 'additionalOffset=', additionalOffset);
					// Scroll to element
					window.scrollTo({
						top: scrollPosition,
						behavior: 'smooth'
					});
				} else {
					console.error('Target element not found for selector:', this.cleanHash);
					// List all IDs on the page to help debug
					const allElements = document.querySelectorAll('[id]');
					//console.log('Available IDs on page:', Array.from(allElements).map(el => el.id));
					// Last resort: Find the contact block and scroll to it anyway
					const contactBlock = document.querySelector('.block-contact');
					if (contactBlock) {
						//console.log('Falling back to scrolling to contact block without ID');
						const headerHeight = document.querySelector('header')?.offsetHeight || 0;
						const additionalOffset = 60;
						const scrollPosition = contactBlock.getBoundingClientRect().top +
							window.pageYOffset - headerHeight - additionalOffset;
						window.scrollTo({
							top: scrollPosition,
							behavior: 'smooth'
						});
					}
				}
			}, 300); // Increased timeout to ensure page is fully rendered
		}
	}
	// Function to be called from buttons/links to navigate to a specific tab and section
	navigateToContactTab(tabIndex, sectionId) {
		//console.log('navigateToContactTab called with:', tabIndex, sectionId);
		// Find the correct tab and click it
		this.blocks.forEach(block => {
			const tabs = block.querySelectorAll('.tab-link');
			// Convert to 0-based index if needed (tab indexes are 0-based in code but may be 1-based in parameters)
			const adjustedIndex = tabIndex > 0 ? tabIndex - 1 : tabIndex;
			// If the tab index is valid
			if (adjustedIndex >= 0 && adjustedIndex < tabs.length) {
				// Click the tab to activate it
				tabs[adjustedIndex].click();
			}
		});
		// Then scroll to the section
		if (sectionId) {
			// Add # if not already present
			const fullSectionId = sectionId.startsWith('#') ? sectionId : `#${sectionId}`;
			// Wait a moment for any DOM updates to complete
			setTimeout(() => {
				const targetElement = document.querySelector(fullSectionId);
				if (targetElement) {
					// Get header height for proper offset
					const headerHeight = document.querySelector('header')?.offsetHeight || 0;
					const additionalOffset = 60;
					// Calculate scroll position
					const scrollPosition = targetElement.getBoundingClientRect().top +
						window.pageYOffset - headerHeight - additionalOffset;
					// Scroll to element
					window.scrollTo({
						top: scrollPosition,
						behavior: 'smooth'
					});
					// Update URL without reload
					history.pushState(null, null, fullSectionId);
				} else {
					console.error('Target element not found:', fullSectionId);
				}
			}, 100);
		}
	}
}
// Initialize on document ready
document.addEventListener('DOMContentLoaded', () => {
	//console.log('DOM loaded, initializing ContactBlock');
	new ContactBlock();
});
// Also add a direct link handler for special format URLs
window.addEventListener('load', function() {
	// Check if we have a URL in the format /#contact-section?tab=1
	if (window.location.hash && window.location.hash.includes('?')) {
		const hashParts = window.location.hash.split('?');
		const hashFragment = hashParts[0];
		const hashQuery = new URLSearchParams(hashParts[1]);
		const tabParam = hashQuery.get('tab');
		if (tabParam !== null) {
			//console.log('Direct hash handler: Found tab param', tabParam, 'and fragment', hashFragment);
			// Find the contact block and scroll to it
			setTimeout(() => {
				let targetElement = null;
				// Try to find by hash fragment
				if (hashFragment) {
					targetElement = document.querySelector(hashFragment);
					if (!targetElement && hashFragment.startsWith('#')) {
						targetElement = document.getElementById(hashFragment.substring(1));
					}
				}
				// If not found, try to find any contact block
				if (!targetElement) {
					targetElement = document.querySelector('.block-contact');
				}
				if (targetElement) {
					//console.log('Direct hash handler: Found target element', targetElement);
					// Get header height for proper offset
					const headerHeight = document.querySelector('header')?.offsetHeight || 0;
					const additionalOffset = 60;
					// Calculate scroll position
					const scrollPosition = targetElement.getBoundingClientRect().top +
						window.pageYOffset - headerHeight - additionalOffset;
					// Scroll to the element
					window.scrollTo({
						top: scrollPosition,
						behavior: 'smooth'
					});
					// Now handle the tab parameter
					const tabIndex = parseInt(tabParam) - 1;
					const contactBlocks = document.querySelectorAll('.block-contact');
					contactBlocks.forEach(block => {
						const tabs = block.querySelectorAll('.tab-link');
						if (tabIndex >= 0 && tabIndex < tabs.length) {
							setTimeout(() => {
								tabs[tabIndex].click();
							}, 100);
						}
					});
				} else {
					console.error('Direct hash handler: Could not find target element');
				}
			}, 500);
		}
	}
});
				
			{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 2,
  "name": "strategiq/contact",
  "title": "Contact Forms",
  "description": "Example block to be used as a template",
  "category": "strategiq",
  "icon": "strategiq",
  "acf": {
      "mode": "preview",
      "renderTemplate": "block-contact.php"
  },
  "supports": {
      "anchor": true,
      "align": false,
      "color": {
          "background": true,
          "text": false,
          "gradients": true
      },
      "spacing": {
          "margin": [
              "top",
              "bottom"
          ],
          "padding": [
              "top",
              "bottom"
          ]
      }
  },
  "example": {
      "attributes": {
          "mode": "preview",
          "data": {
              "heading_type": "h2",
              "heading_text": "Example - Contact Forms",
              "content": "This is some example content to represent what the content will look like"
          }
      }
  },
  "style": "file:../../assets/css/contact/block-contact.css",
  "viewScript": ["contact"]
}