diff --git a/.stylelintignore b/.stylelintignore
new file mode 100644
index 00000000..28f249ae
--- /dev/null
+++ b/.stylelintignore
@@ -0,0 +1,2 @@
+node_modules/
+tribe-events/
diff --git a/.stylelintrc.json b/.stylelintrc.json
index 2c501105..244450b8 100644
--- a/.stylelintrc.json
+++ b/.stylelintrc.json
@@ -1,3 +1,3 @@
{
- "extends": "stylelint-config-recommended"
+ "extends": "@wordpress/stylelint-config"
}
diff --git a/assets/js/header.js b/assets/js/header.js
new file mode 100644
index 00000000..bdf9bd88
--- /dev/null
+++ b/assets/js/header.js
@@ -0,0 +1,96 @@
+(function () {
+ 'use strict';
+
+ const header = document.querySelector( 'header.wp-block-template-part' );
+ if ( ! header ) return;
+
+ const findHero = () => document.querySelector(
+ '.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child'
+ );
+
+ new ResizeObserver( function ( entries ) {
+ document.documentElement.style.setProperty(
+ '--ext-header-height',
+ entries[ 0 ].borderBoxSize[ 0 ].blockSize + 'px'
+ );
+ } ).observe( header, { box: 'border-box' } );
+
+ // Normal mode: IntersectionObservers against the viewport.
+ // Original behavior, preserved for real frontend pages.
+ const setupNormal = () => {
+ const hero = findHero();
+ let heroObs;
+ if ( hero ) {
+ heroObs = new IntersectionObserver( function ( entries ) {
+ header.classList.toggle( 'is-past-hero', ! entries[ 0 ].isIntersecting );
+ }, { rootMargin: '-50% 0px 0px 0px' } );
+ heroObs.observe( hero );
+ }
+
+ const sentinel = document.createElement( 'div' );
+ sentinel.style.cssText = 'position:absolute;top:0;left:0;height:16px;width:1px;pointer-events:none;';
+ document.body.prepend( sentinel );
+
+ const scrollObs = new IntersectionObserver( function ( entries ) {
+ header.classList.toggle( 'is-scrolled', ! entries[ 0 ].isIntersecting );
+ } );
+ scrollObs.observe( sentinel );
+
+ return () => {
+ heroObs?.disconnect();
+ scrollObs.disconnect();
+ sentinel.remove();
+ };
+ };
+
+ // Agent mode: rAF-throttled scroll/resize listener with CSS-pixel math.
+ // The agent's transform: scale() on .wp-site-blocks breaks
+ // IntersectionObserver geometry, but offsetTop / offsetHeight / scrollTop
+ // are unaffected by transforms — stable at any scale.
+ const setupAgent = ( root ) => {
+ let rafId = 0;
+ const update = () => {
+ rafId = 0;
+ header.classList.toggle( 'is-scrolled', root.scrollTop > 0 );
+ const hero = findHero();
+ if ( ! hero ) return;
+ const heroBottom = hero.offsetTop + hero.offsetHeight;
+ header.classList.toggle( 'is-past-hero', root.scrollTop > heroBottom );
+ };
+ const schedule = () => {
+ if ( rafId ) return;
+ rafId = requestAnimationFrame( update );
+ };
+
+ root.addEventListener( 'scroll', schedule, { passive: true } );
+ window.addEventListener( 'resize', schedule, { passive: true } );
+ update();
+
+ return () => {
+ if ( rafId ) cancelAnimationFrame( rafId );
+ root.removeEventListener( 'scroll', schedule );
+ window.removeEventListener( 'resize', schedule );
+ };
+ };
+
+ let teardown;
+ const setup = ( root ) => {
+ teardown?.();
+ teardown = root ? setupAgent( root ) : setupNormal();
+ };
+
+ setup( null );
+
+ // Optional integration: if the Extendify Agent is active it dispatches
+ // extendify-agent:layout-shift on open/close (see useLayoutShift in
+ // SidebarLayout.jsx). When the agent isn't installed this listener is
+ // simply never invoked — the file works standalone with normal-mode
+ // IntersectionObservers, identical to its original behavior.
+ window.addEventListener( 'extendify-agent:layout-shift', function ( event ) {
+ const open = event?.detail?.open;
+ const root = open ? document.querySelector( '.wp-site-blocks' ) : null;
+ // Wait one frame so the agent's transform / overflow changes commit
+ // before we attach handlers and read geometry.
+ requestAnimationFrame( () => setup( root ) );
+ } );
+} )();
diff --git a/assets/js/navigation-customization.js b/assets/js/navigation-customization.js
index 6d3b49ba..ac5262c8 100644
--- a/assets/js/navigation-customization.js
+++ b/assets/js/navigation-customization.js
@@ -13,7 +13,7 @@
const hasSiteTitle = !!document.querySelector('header.wp-block-template-part .wp-block-site-title');
const wrapper = document.createElement('div');
- wrapper.className = 'site-logo-title wp-block-site-logo';
+ wrapper.className = 'site-logo-title wp-block-site-logo cloned-for-mobile';
wrapper.innerHTML = `
${logoUrl ? `
` : ''}
${hasSiteTitle ? `${siteTitle || ''}` : ''}
@@ -21,9 +21,62 @@
container.prepend(wrapper);
}
+ function injectNavExtras() {
+ const dialog = document.querySelector('.wp-block-navigation__responsive-dialog');
+ if (!dialog) return;
+ if (dialog.querySelector('.ext-nav-extras-mobile')) return;
+
+ const header = document.querySelector('header.wp-block-template-part');
+ if (!header) return;
+
+ // Only clone the specific extras (phone / CTA / social). Avoid cloning
+ // .ext-nav-extras as a wrapper because some header parts use that class
+ // around the navigation block itself — cloning it would duplicate the
+ // entire nav.
+ const extras = header.querySelectorAll(
+ '.ext-nav-extras-phone, .ext-nav-extras-btn, .ext-nav-extras-social'
+ );
+ if (extras.length === 0) return;
+
+ const container = document.createElement('div');
+ container.className = 'ext-nav-extras-mobile cloned-for-mobile';
+
+ extras.forEach((el) => {
+ const clone = el.cloneNode(true);
+ // Strip identifiers that should be unique per document so the clone
+ // doesn't collide with the original (id targets, agent-tracked blocks).
+ clone
+ .querySelectorAll('[id], [data-extendify-part-block-id], [data-extendify-part-slug], [data-extendify-part]')
+ .forEach((node) => {
+ node.removeAttribute('id');
+ node.removeAttribute('data-extendify-part-block-id');
+ node.removeAttribute('data-extendify-part-slug');
+ node.removeAttribute('data-extendify-part');
+ });
+ // Force left alignment via inline style: WP generates a
+ // wp-container-* class for each layout block with its own
+ // justify-content rule, which has higher specificity than
+ // swapping .is-content-justification-right/left classes can fight.
+ [clone, ...clone.querySelectorAll('*')]
+ .filter((node) => node.classList?.contains('is-content-justification-right')
+ || node.classList?.contains('is-content-justification-center'))
+ .forEach((node) => {
+ node.style.justifyContent = 'flex-start';
+ });
+ container.appendChild(clone);
+ });
+
+ dialog.appendChild(container);
+ }
+
+ function init() {
+ injectSiteLogoTitle();
+ injectNavExtras();
+ }
+
if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', injectSiteLogoTitle);
+ document.addEventListener('DOMContentLoaded', init);
} else {
- injectSiteLogoTitle();
+ init();
}
})();
diff --git a/functions.php b/functions.php
index 41f2a795..55253484 100644
--- a/functions.php
+++ b/functions.php
@@ -228,6 +228,23 @@ function extendable_exclude_wc_block_templates( $templates, $query ) {
}
add_filter( 'get_block_templates', 'extendable_exclude_wc_block_templates', 10, 2 );
+/**
+ * Header helper.
+ *
+ * @package Extendable
+ * @since Extendable 2.1.5
+ */
+function extendable_enqueue_header_scripts() {
+ wp_enqueue_script(
+ 'extendable-header',
+ get_template_directory_uri() . '/assets/js/header.js',
+ array(),
+ EXTENDABLE_THEME_VERSION,
+ true
+ );
+}
+add_action( 'wp_enqueue_scripts', 'extendable_enqueue_header_scripts' );
+
/**
* Navigation customizations
*
@@ -253,11 +270,11 @@ function extendable_enqueue_navigation_customizations() {
true // load in footer
);
- wp_localize_script( 'extendable-navigation_customizations', 'ExtendableNavData',
+ wp_localize_script( 'extendable-navigation_customizations', 'ExtendableNavData',
array(
'logoUrl' => $logo_url,
'siteTitle' => $site_title,
- )
+ )
);
}
endif;
diff --git a/parts/header-atlas-beacon.html b/parts/header-atlas-beacon.html
new file mode 100644
index 00000000..fab9834e
--- /dev/null
+++ b/parts/header-atlas-beacon.html
@@ -0,0 +1,35 @@
+
+
+
diff --git a/parts/header-catalina-skyline.html b/parts/header-catalina-skyline.html
new file mode 100644
index 00000000..b69b8a94
--- /dev/null
+++ b/parts/header-catalina-skyline.html
@@ -0,0 +1,52 @@
+
+
+
+
\ No newline at end of file
diff --git a/parts/header-ceadar-peak.html b/parts/header-ceadar-peak.html
new file mode 100644
index 00000000..33be1389
--- /dev/null
+++ b/parts/header-ceadar-peak.html
@@ -0,0 +1,35 @@
+
+
+
diff --git a/style.css b/style.css
index 5bf5fd38..ad70e7eb 100644
--- a/style.css
+++ b/style.css
@@ -28,16 +28,16 @@ Extendable therefore is also distributed under the terms of the GNU GPL.
--wp--custom--spacing--medium: var(--wp--preset--spacing--50, clamp(2.5rem, 8vw, 4rem));
--wp--custom--spacing--large: var(--wp--preset--spacing--60, clamp(2.5rem, 8vw, 6rem));
--wp--custom--spacing--outer: max(1.25rem, 4vw);
- --wp--preset--spacing--80: min(8rem, 12vw);
+ --wp--preset--spacing--80: min(8rem, 12vw);
}
/*
* Smooth scrolling
*/
- html {
+html {
scroll-behavior: smooth;
- }
+}
/*
* Font smoothing.
@@ -68,8 +68,8 @@ a:focus {
}
:where(.wp-site-blocks *:focus) {
- outline-width:1px;
- outline-style:solid
+ outline-width: 1px;
+ outline-style: solid;
}
a:active {
@@ -80,45 +80,47 @@ a:active {
* Navigation Block
*/
- @media (min-width: 600px) {
- .site-logo-title {
- display:none
- }
+@media (min-width: 600px) {
+
+ .site-logo-title {
+ display: none;
+ }
- .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation-item,
- .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__container,
+ .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation-item,
+ .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__container,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-page-list {
align-items: flex-start !important;
}
}
- @media (max-width: 600px) {
- .has-modal-open .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation-item,
- .has-modal-open .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__container,
+@media (max-width: 600px) {
+
+ .has-modal-open .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation-item,
+ .has-modal-open .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__container,
.has-modal-open .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-page-list {
align-items: flex-start !important;
}
}
.wp-block-navigation__responsive-container.has-modal-open.is-menu-open .site-logo-title {
- display: flex;
+ display: flex;
flex-wrap: nowrap;
max-width: 100%;
- align-items: center;
- gap: 0.5rem;
- padding-bottom: var(--wp--preset--spacing--30);
- position: relative;
+ align-items: center;
+ gap: 0.5rem;
+ padding-bottom: var(--wp--preset--spacing--30);
+ position: relative;
padding-inline-end: 52px;
}
.wp-block-navigation__responsive-container.has-modal-open.is-menu-open .site-logo-title::after {
- content: "";
- position: absolute;
- left: calc(-1 * var(--wp--preset--spacing--30));
- right: calc(-1 * var(--wp--preset--spacing--30));
- bottom: 0;
- height: 1px;
- background: #8080801d;
+ content: "";
+ position: absolute;
+ left: calc(-1 * var(--wp--preset--spacing--30));
+ right: calc(-1 * var(--wp--preset--spacing--30));
+ bottom: 0;
+ height: 1px;
+ background: #8080801d;
}
.wp-block-navigation__responsive-container.has-modal-open.is-menu-open .site-logo-title img {
@@ -133,9 +135,9 @@ a:active {
font-weight: 700;
color: var(--wp--preset--color--foreground);
text-transform: uppercase;
- letter-spacing: -0.02em;
- box-sizing: border-box;
- line-height: 1.15;
+ letter-spacing: -0.02em;
+ box-sizing: border-box;
+ line-height: 1.15;
}
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
@@ -143,10 +145,10 @@ a:active {
}
.has-modal-open .wp-block-navigation__responsive-container-close {
- background-color:var(--wp--preset--color--tertiary);
+ background-color: var(--wp--preset--color--tertiary);
padding: 0.625rem;
border-radius: 100%;
- top: -2.5px !important;
+ top: -2.5px !important;
}
.has-modal-open .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__container {
@@ -154,10 +156,11 @@ a:active {
width: 100%;
}
-.has-modal-open .wp-block-navrigation__containe, .has-modal-open .wp-block-navigation__container ul {
- row-gap: 0.75rem !important;
- width: -webkit-fill-available;
- max-width: 100%;
+.has-modal-open .wp-block-navrigation__containe,
+.has-modal-open .wp-block-navigation__container ul {
+ row-gap: 0.75rem !important;
+ width: -webkit-fill-available;
+ max-width: 100%;
}
.has-modal-open .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content > ul.wp-block-navigation__container > li.wp-block-navigation-item:not(.wp-block-navigation__submenu-container) {
@@ -170,20 +173,122 @@ a:active {
.has-modal-open .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .has-child .wp-block-navigation__submenu-container {
padding: 0.75rem 0.75rem 0 0.75rem !important;
- gap: 0.75rem !important;
- }
+ gap: 0.75rem !important;
+}
.has-modal-open .wp-block-navigation__responsive-dialog ul.wp-block-navigation__container > li:not(.wp-block-navigation__submenu-container) > a.wp-block-navigation-item__content {
- font-size: 1.25rem;
+ font-size: 1.25rem;
font-weight: 600;
}
.has-modal-open .wp-block-navigation__submenu-container {
- padding-top: 0.75rem !important;
+ padding-top: 0.75rem !important;
}
.has-modal-open .wp-block-navigation__responsive-dialog ul.wp-block-navigation__container .wp-block-navigation-submenu .wp-block-navigation-item a {
- font-size: 1rem !important;
+ font-size: 1rem !important;
+}
+
+/*
+ * When the responsive navigation modal opens (WordPress sets .has-modal-open
+ * on ), suppress every property on the modal's ancestor chain that
+ * creates a containing block for position:fixed descendants — otherwise
+ * the modal is trapped inside the header instead of overlaying the viewport.
+ *
+ * Two rules here:
+ *
+ * 1) Broad ancestor coverage — the header itself plus any element inside
+ * it that contains the responsive dialog. Handles transform/filter on
+ * any header variant (overlay, glass, floating-pill, future ones).
+ *
+ * 2) Animation override — mirrors the selectors used by the floating-pill
+ * scroll animations so we can match their specificity. Those animations
+ * use !important + a deep selector to apply translate/backdrop-filter
+ * via keyframes; without a same-or-higher-specificity override our broad
+ * rule loses the cascade and the animation keeps trapping the modal.
+ */
+html.has-modal-open header.wp-block-template-part,
+html.has-modal-open header.wp-block-template-part :has(.wp-block-navigation__responsive-dialog) {
+ backdrop-filter: none !important;
+ transform: none !important;
+ translate: none !important;
+ filter: none !important;
+ animation: none !important;
+}
+
+html.has-modal-open body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-sticky.ext-header-sticky--floating-pill.ext-header-glass) .ext-header-sticky.ext-header-sticky--floating-pill.ext-header-glass,
+html.has-modal-open body:not(:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child)) header.wp-block-template-part:has(.ext-header-sticky.ext-header-sticky--floating-pill.ext-header-glass) .ext-header-sticky.ext-header-sticky--floating-pill.ext-header-glass {
+ animation: none !important;
+ backdrop-filter: none !important;
+ translate: none !important;
+}
+
+/*
+ * Mobile nav-extras: cloned by navigation-customization.js into the
+ * responsive menu dialog so phone / CTA / social aren't visible in the
+ * cramped top bar on small screens. We target the specific modifier
+ * classes (.ext-nav-extras-phone, -btn, -social) rather than the
+ * .ext-nav-extras wrapper, because some header parts use the wrapper
+ * class around the nav block itself.
+ *
+ * On desktop the dialog is rendered inline (it's only "modal-shaped"
+ * when the hamburger opens it), so the cloned extras must stay hidden
+ * until WordPress sets .has-modal-open on .
+ */
+@media (max-width: 781px) {
+
+ header.wp-block-template-part :is(.ext-nav-extras-phone, .ext-nav-extras-btn, .ext-nav-extras-social):not(.ext-nav-extras-mobile *) {
+ display: none;
+ }
+
+ /* Collapse the .ext-nav-extras wrapper too when its only children are the
+ extras (no nav inside) — otherwise the empty wrapper holds a flex slot
+ and the hamburger stays stuck in the middle instead of moving to the
+ end of the row. */
+ header.wp-block-template-part .ext-nav-extras:not(:has(nav, .wp-block-navigation)) {
+ display: none;
+ }
+}
+
+.ext-nav-extras-mobile {
+ display: none;
+}
+
+.has-modal-open .wp-block-navigation__responsive-dialog .ext-nav-extras-mobile {
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ gap: var(--wp--preset--spacing--20);
+ margin-top: var(--wp--preset--spacing--30);
+}
+
+.has-modal-open .wp-block-navigation__responsive-dialog .ext-nav-extras-mobile .wp-block-button {
+ width: 100%;
+}
+
+.has-modal-open .wp-block-navigation__responsive-dialog .ext-nav-extras-mobile .wp-block-button__link {
+ display: block;
+ text-align: center;
+ width: 100%;
+}
+
+/* Match the nav-link typography (see rule above) on the cloned phone CTA. */
+.has-modal-open .wp-block-navigation__responsive-dialog .ext-nav-extras-mobile .ext-nav-extras-phone,
+.has-modal-open .wp-block-navigation__responsive-dialog .ext-nav-extras-mobile .ext-nav-extras-phone a,
+.has-modal-open .wp-block-navigation__responsive-dialog .ext-nav-extras-mobile .ext-nav-extras-phone p {
+ font-size: 1.25rem !important;
+ font-weight: 600 !important;
+}
+
+/* Bigger, more tappable social icons in the menu. */
+.has-modal-open .wp-block-navigation__responsive-dialog .ext-nav-extras-mobile .wp-block-social-link {
+ width: 32px;
+ height: 32px;
+}
+
+.has-modal-open .wp-block-navigation__responsive-dialog .ext-nav-extras-mobile .wp-social-link svg {
+ width: 28px;
+ height: 28px;
}
.wp-block-navigation .wp-block-navigation-item a:hover,
@@ -211,25 +316,35 @@ nav .wp-block-pages-list__item.wp-block-navigation-item.menu-item-home {
padding-left: var(--wp--preset--spacing--30);
}
+/* Temporary: WP core ships this padding as a 4-value clamp() shorthand
+ that some browsers fail to parse — re-declare as individual props. */
+.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
+ padding-top: clamp(1rem, var(--wp--style--root--padding-top), 20rem);
+ padding-right: clamp(1rem, var(--wp--style--root--padding-right), 20rem);
+ padding-bottom: clamp(1rem, var(--wp--style--root--padding-bottom), 20rem);
+ padding-left: clamp(1rem, var(--wp--style--root--padding-left), 20rem);
+}
+
/*
* --------------------------------------------------------
* Custom - blocks
* --------------------------------------------------------
*/
- /* Button
+/* Button
----------------------------------------------------------*/
.wp-element-button {
transition: background-color 0.15s ease;
}
+
.wp-block-button .wp-block-button__link.is-style-outline:not(.has-background):hover,
-.wp-block-button.is-style-outline>.wp-block-button__link:not(.has-background):hover {
+.wp-block-button.is-style-outline > .wp-block-button__link:not(.has-background):hover {
background-color: rgba(159, 159, 159, 0.2);
}
/* Table
----------------------------------------------------------*/
-.wp-block-table.is-style-stripes tbody tr:nth-child(odd){
+.wp-block-table.is-style-stripes tbody tr:nth-child(odd) {
background-color: var(--wp--custom--blocks--core-table--variant-stripes--color--background, var(--wp--preset--color--tertiary));
}
@@ -256,16 +371,20 @@ blockquote:is(.is-style-plain) {
border-radius: var(--wp--custom--elements--button--border--radius);
border-width: var(--wp--custom--elements--input--border--width);
}
+
:where(.wp-block-search__button-inside .wp-block-search__inside-wrapper) .wp-block-search__input {
border-color: transparent;
}
+
.wp-block-search .wp-block-search__input {
border-radius: var(--wp--custom--elements--button--border--radius);
}
/* Image
----------------------------------------------------------*/
-.wp-block-image[style*="-radius"]:not([style*="overflow"]) { overflow: hidden }
+.wp-block-image[style*="-radius"]:not([style*="overflow"]) {
+ overflow: hidden;
+}
/*
* --------------------------------------------------------
@@ -275,9 +394,9 @@ blockquote:is(.is-style-plain) {
.block-editor-block-list__block.wp-block.is-default-size.wp-block-site-logo .components-resizable-box__container,
.wp-block-site-logo.is-default-size img {
- max-height: 42px !important;
- height: auto !important;
- width: auto !important;
+ max-height: 42px !important;
+ height: auto !important;
+ width: auto !important;
}
/* Ensure default logo works well on light and dark backgrounds
@@ -285,6 +404,7 @@ blockquote:is(.is-style-plain) {
.wp-block-site-logo img[src*="extendify-demo-"],
.wp-block-site-logo img[src*="ext-custom-logo-"] {
filter: var(--wp--preset--duotone--primary-foreground);
+ min-width: 40px;
}
@@ -293,6 +413,7 @@ blockquote:is(.is-style-plain) {
* for people that prefer not to see them.
*/
@media (prefers-reduced-motion: reduce) {
+
html:focus-within {
scroll-behavior: auto;
}
@@ -310,7 +431,8 @@ blockquote:is(.is-style-plain) {
/*
* Matching caret and focus outline colors.
*/
-input, textarea {
+input,
+textarea {
caret-color: inherit;
outline-color: inherit;
}
@@ -318,7 +440,7 @@ input, textarea {
/*
* Matching input with outline button style.
*/
-:where(.wp-block-post-comments-form) input:not([type=submit]),
+:where(.wp-block-post-comments-form) input:not([type="submit"]),
:where(.wp-block-post-comments-form) textarea {
background-color: var(--wp--preset--color--background);
color: var(--wp--preset--color--foreground);
@@ -330,16 +452,18 @@ input, textarea {
* Woocommerce temporarily customization until the woo blocks offer support
*/
-.woocommerce-Tabs-panel--description h2, .woocommerce-Reviews-title {
+.woocommerce-Tabs-panel--description h2,
+.woocommerce-Reviews-title {
font-size: var(--wp--preset--font-size--medium);
}
.wp-block-button.wc-block-components-product-button {
flex-direction: row;
- flex-wrap: wrap;
- justify-content: start;
+ flex-wrap: wrap;
+ justify-content: start;
gap: 1rem;
}
+
.wp-block-button.wc-block-components-product-button a.added_to_cart {
margin-top: 0;
}
@@ -350,19 +474,22 @@ input, textarea {
.wp-site-blocks .wp-block-group.woocommerce.product {
margin-top: 0;
- margin-bottom: 0;
+ margin-bottom: 0;
}
+
.wc-block-product-template__responsive {
grid-row-gap: 2rem;
}
+
.wc-block-components-product-button__button {
z-index: 1;
}
+
/*
* Adds offset for sticky header overlap
*/
- .sticky-header-offset-container .entry-content > .wp-block-group {
+.sticky-header-offset-container .entry-content > .wp-block-group {
scroll-margin-top: var(--wp--preset--spacing--60);
}
@@ -371,35 +498,35 @@ input, textarea {
*/
:not(.block-editor-block-preview__content-iframe)
-.has-tertiary-background-color.has-background
-[class*='is-style-ext-preset--group--'][class*='item-card-1']:not(.has-background)
-{
- background-color: var(--wp--preset--color--background);
+.has-tertiary-background-color.has-background
+[class*="is-style-ext-preset--group--"][class*="item-card-1"]:not(.has-background) {
+ background-color: var(--wp--preset--color--background);
}
:not(.block-editor-block-preview__content-iframe)
-.has-tertiary-background-color.has-background
-[class*='is-style-ext-preset--group--'][class*='item-card-1']:not(.has-background)::before {
- background-color: var(--wp--preset--color--background) !important;
+.has-tertiary-background-color.has-background
+[class*="is-style-ext-preset--group--"][class*="item-card-1"]:not(.has-background)::before {
+ background-color: var(--wp--preset--color--background) !important;
}
:not(.block-editor-block-preview__content-iframe)
-.has-tertiary-background-color.has-background
-[class*='is-style-ext-preset--image--']:not(.has-background)::before {
- background-color: var(--wp--preset--color--tertiary) !important;
+.has-tertiary-background-color.has-background
+[class*="is-style-ext-preset--image--"]:not(.has-background)::before {
+ background-color: var(--wp--preset--color--tertiary) !important;
}
:not(.block-editor-block-preview__content-iframe)
-.has-tertiary-background-color.has-background
-[class*='is-style-ext-preset--group--'][class*='item-card-1']::before,:not(.block-editor-block-preview__content-iframe)
-.has-tertiary-background-color.has-background
-[class*='is-style-ext-preset--media-text--']:before {
- background-color: var(--wp--preset--color--background) !important;
+.has-tertiary-background-color.has-background
+[class*="is-style-ext-preset--group--"][class*="item-card-1"]::before,
+:not(.block-editor-block-preview__content-iframe)
+.has-tertiary-background-color.has-background
+[class*="is-style-ext-preset--media-text--"]::before {
+ background-color: var(--wp--preset--color--background) !important;
}
-.block-editor-block-preview__content-iframe
-[class*='is-style-ext-preset--group--natural-1'][class*='item-card-1'] {
- background-color: transparent !important;
+.block-editor-block-preview__content-iframe
+[class*="is-style-ext-preset--group--natural-1"][class*="item-card-1"] {
+ background-color: transparent !important;
}
:root {
@@ -415,32 +542,30 @@ input, textarea {
*/
[class*="is-style-ext-preset--group--"][class*="--section"].has-tertiary-background-color:has(
- + .has-background-background-color > .wp-block-cover.alignfull
++ .has-background-background-color > .wp-block-cover.alignfull
)::after {
- content: none !important;
+ content: none !important;
}
[class*="is-style-ext-preset--group--"][class*="--section"].has-tertiary-background-color:has(
- + .has-background-background-color > .wp-block-cover.alignfull
++ .has-background-background-color > .wp-block-cover.alignfull
) {
- margin-bottom: 0 !important;
+ margin-bottom: 0 !important;
}
-[class*="is-style-ext-preset--group--"][class*="--section"].has-background-background-color:has(.wp-block-cover.alignfull)
-+ .has-tertiary-background-color::before {
- content: none !important;
+[class*="is-style-ext-preset--group--"][class*="--section"].has-background-background-color:has(.wp-block-cover.alignfull) + .has-tertiary-background-color::before {
+ content: none !important;
}
-[class*="is-style-ext-preset--group--"][class*="--section"].has-background-background-color:has(.wp-block-cover.alignfull)
-+ .has-tertiary-background-color {
- margin-top: 0 !important;
+[class*="is-style-ext-preset--group--"][class*="--section"].has-background-background-color:has(.wp-block-cover.alignfull) + .has-tertiary-background-color {
+ margin-top: 0 !important;
}
/*
* utilities
*/
- .m-0 {
+.m-0 {
margin: 0 !important;
}
@@ -451,106 +576,516 @@ input, textarea {
.z-10 {
z-index: 10 !important;
}
+
.z-20 {
z-index: 20 !important;
}
+
.z-30 {
z-index: 30 !important;
}
.d-none {
- display: none;
+ display: none;
}
.d-block {
- display: block;
+ display: block;
}
@media (min-width: 640px) {
- .sm-d-none {
- display: none;
- }
- .sm-d-block {
- display: block;
- }
+ .sm-d-none {
+ display: none;
+ }
+
+ .sm-d-block {
+ display: block;
+ }
}
@media (min-width: 768px) {
- .md-d-none {
- display: none;
- }
- .md-d-block {
- display: block;
- }
+ .md-d-none {
+ display: none;
+ }
+
+ .md-d-block {
+ display: block;
+ }
}
@media (min-width: 1024px) {
- .lg-d-none {
- display: none;
- }
- .lg-d-block {
- display: block;
- }
+ .lg-d-none {
+ display: none;
+ }
+
+ .lg-d-block {
+ display: block;
+ }
}
/* RTL-only fix for Gutenberg Group left justification */
-[dir="rtl"] [class*="wp-container-core-group-is-layout-"].ext-is-logical-start.is-content-justification-left
- > :where(:not(.alignleft):not(.alignright):not(.alignfull)) {
+[dir="rtl"] [class*="wp-container-core-group-is-layout-"].ext-is-logical-start.is-content-justification-left > :where(:not(.alignleft):not(.alignright):not(.alignfull)) {
margin-inline-start: 0 !important;
margin-inline-end: auto !important;
}
-.no-underline, .no-underline a {
- text-decoration: none;
+.no-underline,
+.no-underline a {
+ text-decoration: none;
}
/* CSS for extendify-agent vibe previews */
.extendify-agent .preview-is-style-ext-preset--group--matrix-1--section .preview-is-style-ext-preset--group--matrix-1--item-card-1--align-center {
- border: solid 6px color-mix(in oklab, var(--wp--preset--color--foreground) 10%, transparent) !important;
+ border: solid 6px color-mix(in oklab, var(--wp--preset--color--foreground) 10%, transparent) !important;
}
.extendify-agent .preview-is-style-ext-preset--group--wave-1--section {
- --wave-ratio: 1440 / 80;
- overflow: visible;
+ --wave-ratio: 1440 / 80;
+ overflow: visible;
}
.extendify-agent .preview-is-style-ext-preset--group--wave-1--section .preview-is-style-ext-preset--group--wave-1--item-card-1--align-center {
- position: relative;
- overflow: visible;
+ position: relative;
+ overflow: visible;
}
.extendify-agent .preview-is-style-ext-preset--group--wave-1--section .preview-is-style-ext-preset--group--wave-1--item-card-1--align-center::after {
- content: "";
- position: absolute;
- width: 150%;
- left: 50%;
- transform: translateX(-35%);
- aspect-ratio: var(--wave-ratio);
- background-color: var(--wp--preset--color--background);
- -webkit-mask: var(--wave-mask) no-repeat center / 100% 100%;
- mask: var(--wave-mask) no-repeat center / 100% 100%;
- bottom: -1px;
- pointer-events: none;
- z-index: 1;
+ content: "";
+ position: absolute;
+ width: 150%;
+ left: 50%;
+ transform: translateX(-35%);
+ aspect-ratio: var(--wave-ratio);
+ background-color: var(--wp--preset--color--background);
+ -webkit-mask: var(--wave-mask) no-repeat center / 100% 100%;
+ mask: var(--wave-mask) no-repeat center / 100% 100%;
+ bottom: -1px;
+ pointer-events: none;
+ z-index: 1;
}
+
.extendify-agent .preview-is-style-ext-preset--group--wave-1--section .preview-is-style-ext-preset--group--wave-1--item-card-1--align-center::before {
- content: "";
- position: absolute;
- width: 150%;
- left: 50%;
- transform: translateX(-65%) scale(-1, -1);
- aspect-ratio: var(--wave-ratio);
- background-color: var(--wp--preset--color--background);
- -webkit-mask: var(--wave-mask) no-repeat center / 100% 100%;
- mask: var(--wave-mask) no-repeat center / 100% 100%;
- top: -1px;
- pointer-events: none;
- z-index: 1;
-}
\ No newline at end of file
+ content: "";
+ position: absolute;
+ width: 150%;
+ left: 50%;
+ transform: translateX(-65%) scale(-1, -1);
+ aspect-ratio: var(--wave-ratio);
+ background-color: var(--wp--preset--color--background);
+ -webkit-mask: var(--wave-mask) no-repeat center / 100% 100%;
+ mask: var(--wave-mask) no-repeat center / 100% 100%;
+ top: -1px;
+ pointer-events: none;
+ z-index: 1;
+}
+
+/*
+ * --------------------------------------------------------
+ * Modular Header System
+ * --------------------------------------------------------
+ *
+ * Layout (positioning):
+ * - .ext-header-sticky → position: sticky + admin-bar handling
+ * - .ext-header-overlay → hero section overlap (negative margin)
+ *
+ * Appearance:
+ * - .ext-header-glass → static glassmorphism (bg + blur + radius)
+ * - .ext-header--dark → dark color scheme: white text + dark scrim/glass tint
+ *
+ * Behavior:
+ * - .ext-header-sticky--floating-pill → scroll-driven intensification of glass + layout shift
+ *
+ * Compositions:
+ * - ext-header-sticky → just sticky, theme bg
+ * - ext-header-overlay → overlay, transparent
+ * - ext-header-overlay ext-header--dark → overlay + dark scrim + white text
+ * - ext-header-sticky ext-header-glass → static glass header
+ * - ext-header-sticky ext-header-glass ext-header--dark → static dark glass
+ * - ext-header-sticky ext-header-overlay ext-header-glass ext-header-sticky--floating-pill → animated glass over hero
+ * - + ext-header--dark on the above → animated DARK glass over hero
+ */
+
+:root {
+ --ext-header-height: 96px;
+ --ext-header-offset: 1rem;
+ --ext-header-blur-start: 4px;
+ --ext-header-blur-end: 12px;
+ --ext-header-bg-opacity-start: 0.75;
+ --ext-header-bg-opacity-end: 0.95;
+ --ext-header-padding: 1.5rem;
+ --ext-header-animation-distance: 100px;
+ --ext-header-glass-tint-dark: #ffffff;
+ --ext-header-dark-logo-filter: brightness(0) invert(1);
+}
+
+body {
+ timeline-scope: --ext-hero-timeline;
+}
+
+/* ===========================================================
+ Layout: ext-header-sticky
+ =========================================================== */
+header.wp-block-template-part:has(.ext-header-sticky) {
+ position: sticky;
+ top: 0;
+ z-index: 12;
+}
+
+/* Default bg for sticky headers without glass.
+ Glass headers leave the wrapper transparent so the inner glass element shows through. */
+header.wp-block-template-part:has(.ext-header-sticky):not(:has(.ext-header-glass)):not(.has-background) {
+ background-color: var(--wp--preset--color--background);
+}
+
+body.admin-bar header.wp-block-template-part:has(.ext-header-sticky) {
+ top: var(--wp-admin--admin-bar--position-offset, var(--wp-admin--admin-bar--height, 32px));
+}
+
+@media (max-width: 782px) {
+
+ body.admin-bar header.wp-block-template-part:has(.ext-header-sticky) {
+ top:0;
+ }
+}
+
+html:has(.ext-header-sticky) {
+ scroll-padding-top: var(--ext-header-height);
+}
+
+/* ===========================================================
+ Layout: ext-header-overlay (hero overlap)
+ =========================================================== */
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-overlay):not(:has(.ext-header-sticky)) {
+ position: relative;
+ top: 0;
+ z-index: 12;
+}
+
+body:has(.ext-header-overlay) .entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child {
+ margin-top: calc(-1 * var(--ext-header-height)) !important;
+ position: relative;
+ z-index: 0;
+}
+
+/* Overlay over hero: wrapper goes transparent so the hero shows through.
+ Reverts to default theme bg once .is-past-hero is added or on subpages without a hero. */
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-overlay):not(.is-past-hero):not(:has(.ext-header-glass)) {
+ background-color: transparent;
+}
+
+/* ===========================================================
+ Appearance: ext-header-glass (static glassmorphism)
+ - --ext-header-glass-color-start: tint during the frosted/initial state
+ - --ext-header-glass-color-end: tint at the solid/scrolled state
+ - Static glass shows the end state (most readable)
+ =========================================================== */
+.ext-header-glass {
+ --ext-header-glass-color-start: var(--wp--preset--color--background);
+ --ext-header-glass-color-end: var(--wp--preset--color--background);
+}
+
+header.wp-block-template-part:has(.ext-header-glass) .ext-header-glass {
+ background-color: oklch(from var(--ext-header-glass-color-end) l c h / var(--ext-header-bg-opacity-end));
+ backdrop-filter: blur(var(--ext-header-blur-end));
+ border-radius: 1rem;
+ overflow: hidden;
+}
+
+/* ===========================================================
+ Color: ext-header--dark
+ - Sets shared scrim/glass color variable
+ - Wrapper gets white text when used with overlay or glass
+ - Inner blocks reset their colors to inherit
+ =========================================================== */
+/* Dark variant only takes effect on pages with a fullscreen hero.
+ On subpages, dark+glass falls back to the light glass defaults. */
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) .ext-header-glass.ext-header--dark {
+ --ext-header-glass-color-start: var(--ext-header-glass-tint-dark);
+ --ext-header-glass-color-end: var(--wp--preset--color--foreground);
+ --ext-header-bg-opacity-start: 0.06;
+ --ext-header-bg-opacity-end: 0.85;
+ --ext-header-blur-start: 16px;
+ --ext-header-blur-end: 24px;
+}
+
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-glass.ext-header--dark) .ext-header-glass {
+ border: 1px solid rgb(255 255 255 / 0.12);
+}
+
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:not(.is-past-hero):has(.ext-header-overlay.ext-header--dark) {
+ color: #fff;
+}
+
+/* Top-fade scrim on the hero's cover block — softer falloff than a header-bound gradient.
+ Flat (non-nested) :has() check on body so the rule reliably matches on hero pages
+ that use an overlay+dark header.
+ Fades out via opacity once the smart-sticky JS adds .is-past-hero on the header,
+ in sync with the header reverting to its default theme appearance. */
+body:has(.ext-header-overlay.ext-header--dark) .ext-hero-section--full-screen .wp-block-cover::after {
+ content: "";
+ position: absolute;
+ inset: 0 0 auto 0;
+ height: calc(var(--ext-header-height) * 3);
+ transition: opacity 300ms ease;
+ background: linear-gradient(
+ to bottom,
+ rgb(0 0 0 / 0.50) 0%,
+ rgb(0 0 0 / 0.25) 50%,
+ rgb(0 0 0 / 0.05) 80%,
+ rgb(0 0 0 / 0) 100%
+ );
+ pointer-events: none;
+ z-index: 1;
+}
+
+/* Past-hero: fade the scrim out so the hero image returns to its natural look,
+ matching the header reverting to default theme bg + colors. */
+body:has(header.wp-block-template-part.is-past-hero) .ext-hero-section--full-screen .wp-block-cover::after {
+ opacity: 0;
+}
+
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-glass.ext-header--dark) {
+ color: #fff;
+}
+
+/* Inner-block dark overrides — fire only on hero pages with a dark backdrop.
+ Overlay+dark drops out at .is-past-hero (header has reverted to default theme).
+ Glass+dark keeps firing past-hero because the glass stays dark via its own animation. */
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:not(.is-past-hero):has(.ext-header-overlay.ext-header--dark) :where(a, button, .wp-block-site-title):not(.has-background, .wp-block-button__link, .cloned-for-mobile, .cloned-for-mobile *),
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-glass.ext-header--dark) :where(a, button, .wp-block-site-title):not(.has-background, .wp-block-button__link, .cloned-for-mobile, .cloned-for-mobile *) {
+ color: inherit;
+}
+
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:not(.is-past-hero):has(.ext-header-overlay.ext-header--dark) .wp-social-link:not(.cloned-for-mobile, .cloned-for-mobile *),
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-glass.ext-header--dark) .wp-social-link:not(.cloned-for-mobile, .cloned-for-mobile *) {
+ color: #fff !important;
+}
+
+/* Phone CTA: force white over the dark hero. Needed because the paragraph carries
+ WP's wp-elements-* link-color rule (preset primary), which beats .has-text-color
+ inheritance on the inner . Drops out at .is-past-hero so the phone reverts to theme. */
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:not(.is-past-hero):has(.ext-header-overlay.ext-header--dark) :is(.ext-nav-extras-phone, .ext-nav-extras-phone a):not(.cloned-for-mobile, .cloned-for-mobile *),
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-glass.ext-header--dark) :is(.ext-nav-extras-phone, .ext-nav-extras-phone a):not(.cloned-for-mobile, .cloned-for-mobile *) {
+ color: #fff !important;
+}
+
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:not(.is-past-hero):has(.ext-header-overlay.ext-header--dark) svg:not(.cloned-for-mobile *),
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-glass.ext-header--dark) svg:not(.cloned-for-mobile *) {
+ fill: currentColor;
+}
+
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:not(.is-past-hero):has(.ext-header-overlay.ext-header--dark) :is(.wp-block-site-logo, .wp-duotone-primary-foreground):not(.cloned-for-mobile, .cloned-for-mobile *),
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-glass.ext-header--dark) :is(.wp-block-site-logo, .wp-duotone-primary-foreground):not(.cloned-for-mobile, .cloned-for-mobile *) {
+ filter: var(--ext-header-dark-logo-filter);
+}
+
+/* Nav-extras CTA: white pill + dark text for contrast against the dark hero scrim.
+ Drops out at .is-past-hero so the button returns to its preset styling. */
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:not(.is-past-hero):has(.ext-header-overlay.ext-header--dark) .ext-nav-extras-btn:not(.cloned-for-mobile, .cloned-for-mobile *) .wp-block-button__link,
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-glass.ext-header--dark) .ext-nav-extras-btn:not(.cloned-for-mobile, .cloned-for-mobile *) .wp-block-button__link {
+ background-color: #fefefe !important;
+ color: #060606 !important;
+}
+
+/* Sticky non-glass headers: smooth shadow/bg transitions (toggle on .is-scrolled / .is-past-hero) */
+header.wp-block-template-part:has(.ext-header-sticky):not(:has(.ext-header-glass)) {
+ transition: background-color 300ms ease, box-shadow 300ms ease;
+}
+
+/* Floating-pill: smooth the top change when .is-scrolled toggles, so the
+ header doesn't snap up when scrolling past the admin bar. */
+header.wp-block-template-part:has(.ext-header-sticky.ext-header-sticky--floating-pill) {
+ transition: top 300ms ease;
+}
+
+/* Subpage elevation shadow: appears when user scrolls (no hero on the page) */
+body:not(:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child)) header.wp-block-template-part.is-scrolled:has(.ext-header-sticky):not(:has(.ext-header-glass)) {
+ box-shadow: 0 4px 24px -8px oklch(from var(--wp--preset--color--foreground) l c h / 0.08);
+}
+
+/* Smart sticky transitions: smooth color/filter changes when toggling .is-past-hero */
+header.wp-block-template-part:has(.ext-header--dark) {
+ transition: background-color 300ms ease, color 300ms ease, box-shadow 300ms ease, border-color 300ms ease;
+}
+
+header.wp-block-template-part:has(.ext-header--dark) :where(a, button, .wp-block-site-title, .wp-social-link) {
+ transition: color 300ms ease;
+}
+
+header.wp-block-template-part:has(.ext-header--dark) .wp-block-site-logo {
+ transition: filter 300ms ease;
+}
+
+/* Past-hero: any sticky+overlay gets solid theme bg + elevation shadow.
+ Glass headers are excluded — they manage their own scroll visuals. */
+header.wp-block-template-part.is-past-hero:has(.ext-header-sticky.ext-header-overlay):not(:has(.ext-header-glass)) {
+ background-color: var(--wp--preset--color--background);
+ box-shadow: 0 4px 24px -8px oklch(from var(--wp--preset--color--foreground) l c h / 0.08);
+}
+
+/* Past-hero on dark variant: also revert white text / inverted logo / forced social color */
+header.wp-block-template-part.is-past-hero:has(.ext-header-overlay.ext-header--dark):not(:has(.ext-header-glass)) {
+ color: var(--wp--preset--color--foreground);
+}
+
+header.wp-block-template-part.is-past-hero:has(.ext-header-overlay.ext-header--dark):not(:has(.ext-header-glass)) :where(a, button, .wp-block-site-title):not(.has-background, .wp-block-button__link) {
+ color: inherit;
+}
+
+header.wp-block-template-part.is-past-hero:has(.ext-header-overlay.ext-header--dark):not(:has(.ext-header-glass)) .wp-social-link {
+ color: var(--wp--preset--color--foreground) !important;
+}
+
+header.wp-block-template-part.is-past-hero:has(.ext-header-overlay.ext-header--dark):not(:has(.ext-header-glass)) .wp-block-site-logo {
+ filter: brightness(1) invert(0);
+}
+
+/* ===========================================================
+ Hero timeline (for scroll-driven animations)
+ =========================================================== */
+@supports (animation-timeline: scroll()) {
+
+ .entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child {
+ view-timeline: --ext-hero-timeline block;
+ }
+}
+
+/* ===========================================================
+ Behavior: ext-header-sticky--floating-pill
+ - Layout shift: header wrapper goes transparent + constrained width
+ - When combined with .ext-header-glass, animates glass intensity
+ =========================================================== */
+header.wp-block-template-part .ext-header-sticky--floating-pill.ext-animate {
+ opacity: 1 !important;
+}
+
+header.wp-block-template-part:has(.ext-header-sticky.ext-header-sticky--floating-pill) {
+ position: sticky;
+ top: 0;
+ z-index: 12;
+ border-bottom: none;
+}
+
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-sticky.ext-header-sticky--floating-pill) {
+ position: sticky;
+ top: var(--ext-header-offset);
+ max-width: var(--wp--style--global--wide-size);
+ margin-left: auto;
+ margin-right: auto;
+ background-color: transparent;
+ padding-inline: var(--wp--style--root--padding-right) var(--wp--style--root--padding-left);
+}
+
+/* Initial glass state (over hero): override static glass-end with start values */
+body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-sticky.ext-header-sticky--floating-pill.ext-header-glass) .ext-header-sticky.ext-header-sticky--floating-pill.ext-header-glass {
+ background-color: oklch(from var(--ext-header-glass-color-start) l c h / var(--ext-header-bg-opacity-start));
+ backdrop-filter: blur(var(--ext-header-blur-start));
+}
+
+body.admin-bar:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-sticky.ext-header-sticky--floating-pill) {
+ top:
+ calc(var(--ext-header-offset) +
+ var(--wp-admin--admin-bar--position-offset, var(--wp-admin--admin-bar--height, 32px)));
+ background-color: transparent;
+}
+
+@media (max-width: 782px) {
+ body.admin-bar:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-sticky.ext-header-sticky--floating-pill) {
+ top:
+ calc(var(--ext-header-offset) +
+ var(--wp-admin--admin-bar--position-offset, var(--wp-admin--admin-bar--height, 46px)));
+ }
+
+ body.admin-bar:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part.is-scrolled:has(.ext-header-sticky.ext-header-sticky--floating-pill) {
+ top:var(--ext-header-offset);
+ }
+}
+
+
+@supports (animation-timeline: scroll()) {
+
+ body:not(:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child)) header.wp-block-template-part:has(.ext-header-sticky.ext-header-sticky--floating-pill) {
+ max-width: calc(var(--wp--style--global--wide-size) + var(--wp--style--root--padding-right) + var(--wp--style--root--padding-left));
+ margin-left: auto;
+ margin-right: auto;
+ }
+
+ @media (prefers-reduced-motion: no-preference) {
+
+ body:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child) header.wp-block-template-part:has(.ext-header-sticky.ext-header-sticky--floating-pill.ext-header-glass) .ext-header-sticky.ext-header-sticky--floating-pill.ext-header-glass {
+ animation: ext-header-glass-intensify linear both !important;
+ animation-timeline: --ext-hero-timeline !important;
+ animation-range: exit 0% exit 80% !important;
+ }
+
+ body:not(:has(.entry-content > .ext-hero-section.ext-hero-section--full-screen:first-child)) header.wp-block-template-part:has(.ext-header-sticky.ext-header-sticky--floating-pill.ext-header-glass) .ext-header-sticky.ext-header-sticky--floating-pill.ext-header-glass {
+ animation: ext-header-glass-intensify-no-hero linear forwards !important;
+ animation-timeline: scroll() !important;
+ animation-range: 0 var(--ext-header-animation-distance) !important;
+ }
+ }
+}
+
+@keyframes ext-header-glass-intensify {
+
+ from {
+ background-color: oklch(from var(--ext-header-glass-color-start) l c h / var(--ext-header-bg-opacity-start));
+ backdrop-filter: blur(var(--ext-header-blur-start));
+ }
+
+ to {
+ background-color: oklch(from var(--ext-header-glass-color-end) l c h / var(--ext-header-bg-opacity-end));
+ backdrop-filter: blur(var(--ext-header-blur-end));
+ box-shadow: 0 14px 28px -10px oklch(from var(--wp--preset--color--foreground) l c h / 0.14), 0 -14px 28px -10px oklch(from var(--wp--preset--color--foreground) l c h / 0.14);
+ }
+}
+
+@keyframes ext-header-glass-intensify-no-hero {
+
+ from {
+ background-color: oklch(from var(--ext-header-glass-color-start) l c h / var(--ext-header-bg-opacity-start));
+ backdrop-filter: blur(var(--ext-header-blur-start));
+ box-shadow: none;
+ translate: 0 0;
+ max-width: 100%;
+ margin-inline: auto;
+ }
+
+ to {
+ background-color: oklch(from var(--ext-header-glass-color-end) l c h / var(--ext-header-bg-opacity-end));
+ backdrop-filter: blur(var(--ext-header-blur-end));
+ box-shadow: 0 14px 28px -10px oklch(from var(--wp--preset--color--foreground) l c h / 0.14), 0 -14px 28px -10px oklch(from var(--wp--preset--color--foreground) l c h / 0.14);
+
+ translate: 0 var(--ext-header-offset);
+ max-width: var(--wp--style--global--wide-size);
+ margin-inline: var(--wp--style--root--padding-right) var(--wp--style--root--padding-left);
+ border-radius: 1rem;
+ }
+}
+
+/* ===========================================================
+ Vibe/gradient fix
+ -----------------------------------------------------------
+ Vibe block-style variations (e.g. is-style-ext-preset--group--*--header-1--N)
+ paint a background gradient on the header. That gradient fights every
+ over-hero / glass-tint / dark-scrim treatment we apply to overlay or glass
+ headers, because the glass and overlay rules set background-COLOR while the
+ variation sets a background-IMAGE that paints on top.
+ Override the variation's background-image specifically (not the whole
+ `background:` shorthand). That lets each header keep working in its
+ natural design:
+ - overlay non-glass: gets transparent bg over hero, theme bg past hero
+ - glass: gets the glass tint (light by default, dark when --dark is set)
+ On non-overlay / non-glass headers the variation gradient stays as-is.
+ =========================================================== */
+.ext-header-overlay[class*="is-style-ext-preset--"],
+.ext-header-glass[class*="is-style-ext-preset--"] {
+ background-image: none !important;
+}
diff --git a/theme.json b/theme.json
index 4389360d..8afb5b55 100644
--- a/theme.json
+++ b/theme.json
@@ -1087,6 +1087,26 @@
"title": "Header",
"area": "header"
},
+ {
+ "name": "header-ember-harbor",
+ "title": "Header Ember Harbor",
+ "area": "header"
+ },
+ {
+ "name": "header-atlas-beacon",
+ "title": "Header Atlas Beacon",
+ "area": "header"
+ },
+ {
+ "name": "header-catalina-skyline",
+ "title": "Header Catalina Skyline",
+ "area": "header"
+ },
+ {
+ "name": "header-ceadar-peak",
+ "title": "Header Ceadar Peak",
+ "area": "header"
+ },
{
"name": "header-title-nav-button",
"title": "Header with Button",