{"id":357934,"date":"2026-08-28T05:51:48","date_gmt":"2026-08-28T05:51:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/arts-sticky-header-for-elementor\/"},"modified":"2026-08-28T05:51:36","modified_gmt":"2026-08-28T05:51:36","slug":"artem-semkin-header-engine-for-elementor","status":"publish","type":"plugin","link":"https:\/\/szl.wordpress.org\/plugins\/artem-semkin-header-engine-for-elementor\/","author":23271239,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.0","stable_tag":"1.0.0","tested":"7.1","requires":"6.5","requires_php":"8.0","requires_plugins":null,"header_name":"Artem Semkin Header Engine for Elementor","header_author":"Artem Semkin","header_description":"Sticky and auto-hide header for Elementor containers. Hide on scroll down, reveal on scroll up, logo swap, sticky styling. Free, zero dependencies.","assets_banners_color":"484848","last_updated":"2026-08-28 05:51:36","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/artemsemkin.com\/plugins\/header-engine-for-elementor\/","header_author_uri":"https:\/\/artemsemkin.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":65,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"artemsemkin","date":"2026-08-28 05:51:36","revision":3669856}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3669856,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3669856,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon.svg":{"filename":"icon.svg","revision":3669856,"resolution":false,"location":"assets","locale":false}},"assets_banners":{"banner-1544x500.jpg":{"filename":"banner-1544x500.jpg","revision":3669856,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.jpg":{"filename":"banner-772x250.jpg","revision":3669856,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{"blueprint.json":{"filename":"blueprint.json","revision":3669856,"resolution":false,"location":"assets","locale":"","contents":"{\"$schema\":\"https:\\\/\\\/playground.wordpress.net\\\/blueprint-schema.json\",\"landingPage\":\"\\\/?page_id=9941\",\"preferredVersions\":{\"php\":\"8.1\",\"wp\":\"latest\"},\"features\":{\"networking\":true},\"login\":true,\"steps\":[{\"step\":\"installPlugin\",\"pluginData\":{\"resource\":\"wordpress.org\\\/plugins\",\"slug\":\"elementor\"},\"options\":{\"activate\":true}},{\"step\":\"installTheme\",\"themeData\":{\"resource\":\"wordpress.org\\\/themes\",\"slug\":\"hello-elementor\"},\"options\":{\"activate\":true}},{\"step\":\"writeFile\",\"path\":\"\\\/wordpress\\\/wp-content\\\/artem-semkin-header-engine-for-elementor-demo-seed.php\",\"data\":\"<?php\\n\\\/**\\n * Seeds the \\\"Artem Semkin Header Engine \\u2014 Demo\\\" page: the Live Preview landing page on\\n * WordPress.org and the page this plugin is judged by.\\n *\\n * Run against the Local dev site:\\n *   dev\\\/wp eval-file dev\\\/seed\\\/demo-page.php --user=1\\n *\\n * Also inlined into .wordpress-org\\\/blueprints\\\/blueprint.json as a writeFile\\n * step by `arts-wp blueprint build`, then required from the runPHP step that\\n * follows it (no wp-cli context there \\u2014 the WP_CLI:: calls below are guarded\\n * for that reason). Idempotent: finds the page by slug and rewrites it\\n * wholesale; the two logo attachments are keyed on a meta value and reused.\\n *\\n * Styling is hard-coded except the three \\\"Header *\\\" kit Global Colors the seed\\n * installs itself \\u2014 the sticky recolor showcase binds the header content to\\n * them via __globals__. The header\\\/dock\\\/zone behavior is entirely this\\n * plugin's panel controls \\u2014 the seed writes the same settings the panel would\\n * save, nothing hand-wired.\\n *\\\/\\n\\nif ( ! defined( 'ABSPATH' ) ) {\\n\\texit;\\n}\\n\\n\\\/**\\n * Pinned so the blueprint's landingPage can address the page without guessing.\\n * The blueprint generator regexes this constant out of the file \\u2014 keep the\\n * literal on one line.\\n *\\\/\\ndefine( 'AHE_DEMO_PAGE_ID', 9941 );\\n\\n\\\/\\\/ Elementor otherwise hijacks the first admin request with its onboarding\\n\\\/\\\/ wizard. Harmless on an already-onboarded dev site.\\nupdate_option( 'elementor_onboarded', true );\\ndelete_transient( 'elementor_activation_redirect' );\\n\\n\\\/\\\/ The set_theme_mod() calls below forward-sync into the Elementor kit through\\n\\\/\\\/ the plugin's pre_set_theme_mod filters, and the kit save runs a capability\\n\\\/\\\/ check (\\\"Access denied\\\" in the blueprint's userless runPHP context otherwise).\\nwp_set_current_user( 1 );\\n\\nconst AHE_TEXT      = '#111111';\\nconst AHE_MUTED     = '#6b6b6b';\\nconst AHE_BORDER    = '#e4e4e2';\\nconst AHE_SOFT      = '#f6f6f4';\\nconst AHE_DOCK_BG   = '#161616';\\nconst AHE_DOCK_TEXT = '#d6d6d6';\\n\\n\\\/\\\/ The stuck header goes dark and re-inks its content via the sticky\\n\\\/\\\/ global-color remap. Light values the remap (and the light logo SVG,\\n\\\/\\\/ which duplicates the ink hex \\u2014 nowdoc can't interpolate) flips to.\\nconst AHE_INK_STICKY   = '#f5f5f5';\\nconst AHE_MUTED_STICKY = '#a3a3a3';\\n\\nfunction ahe_seed_id(): string {\\n\\treturn substr( bin2hex( random_bytes( 4 ) ), 0, 7 );\\n}\\n\\nfunction ahe_zero_gap(): array {\\n\\treturn array(\\n\\t\\t'unit'     => 'px',\\n\\t\\t'column'   => '0',\\n\\t\\t'row'      => '0',\\n\\t\\t'isLinked' => true,\\n\\t);\\n}\\n\\nfunction ahe_gap( int $px ): array {\\n\\treturn array(\\n\\t\\t'unit'     => 'px',\\n\\t\\t'column'   => (string) $px,\\n\\t\\t'row'      => (string) $px,\\n\\t\\t'isLinked' => true,\\n\\t);\\n}\\n\\n\\\/** Heading widget with explicit typography (the blueprint boots a bare kit). *\\\/\\nfunction ahe_heading( string $title, string $tag, string $font_size, array $extra = array() ): array {\\n\\treturn array(\\n\\t\\t'id'         => ahe_seed_id(),\\n\\t\\t'elType'     => 'widget',\\n\\t\\t'widgetType' => 'heading',\\n\\t\\t'settings'   => array_merge(\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'title'                     => $title,\\n\\t\\t\\t\\t'header_size'               => $tag,\\n\\t\\t\\t\\t'title_color'               => AHE_TEXT,\\n\\t\\t\\t\\t'typography_typography'     => 'custom',\\n\\t\\t\\t\\t'typography_font_weight'    => '600',\\n\\t\\t\\t\\t'typography_font_size'      => array(\\n\\t\\t\\t\\t\\t'unit' => 'custom',\\n\\t\\t\\t\\t\\t'size' => $font_size,\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'typography_line_height'    => array(\\n\\t\\t\\t\\t\\t'unit' => 'custom',\\n\\t\\t\\t\\t\\t'size' => '1.2',\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'typography_letter_spacing' => array(\\n\\t\\t\\t\\t\\t'unit'  => 'em',\\n\\t\\t\\t\\t\\t'size'  => -0.01,\\n\\t\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t\\t),\\n\\t\\t\\t),\\n\\t\\t\\t$extra\\n\\t\\t),\\n\\t\\t'elements'   => array(),\\n\\t);\\n}\\n\\n\\\/** Muted body paragraph, capped at a readable measure. *\\\/\\nfunction ahe_body( string $title, array $extra = array() ): array {\\n\\treturn array(\\n\\t\\t'id'         => ahe_seed_id(),\\n\\t\\t'elType'     => 'widget',\\n\\t\\t'widgetType' => 'heading',\\n\\t\\t'settings'   => array_merge(\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'title'                  => $title,\\n\\t\\t\\t\\t'header_size'            => 'p',\\n\\t\\t\\t\\t'title_color'            => AHE_MUTED,\\n\\t\\t\\t\\t'typography_typography'  => 'custom',\\n\\t\\t\\t\\t'typography_font_size'   => array(\\n\\t\\t\\t\\t\\t'unit'  => 'px',\\n\\t\\t\\t\\t\\t'size'  => 17,\\n\\t\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'typography_line_height' => array(\\n\\t\\t\\t\\t\\t'unit' => 'custom',\\n\\t\\t\\t\\t\\t'size' => '1.65',\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'_element_width'         => 'initial',\\n\\t\\t\\t\\t'_element_custom_width'  => array(\\n\\t\\t\\t\\t\\t'unit' => 'custom',\\n\\t\\t\\t\\t\\t'size' => 'min(54ch, 100%)',\\n\\t\\t\\t\\t),\\n\\t\\t\\t),\\n\\t\\t\\t$extra\\n\\t\\t),\\n\\t\\t'elements'   => array(),\\n\\t);\\n}\\n\\n\\\/**\\n * Plain-text nav link (heading widget \\u2014 free Elementor has no nav widget).\\n * Colors bind to the header's Global Color tokens (__globals__ wins over the\\n * hardcoded fallbacks), so the sticky recolor re-inks the whole menu.\\n *\\\/\\nfunction ahe_nav_link( string $title, string $url ): array {\\n\\treturn array(\\n\\t\\t'id'         => ahe_seed_id(),\\n\\t\\t'elType'     => 'widget',\\n\\t\\t'widgetType' => 'heading',\\n\\t\\t'settings'   => array(\\n\\t\\t\\t'title'                 => $title,\\n\\t\\t\\t'header_size'           => 'p',\\n\\t\\t\\t'link'                  => array(\\n\\t\\t\\t\\t'url'         => $url,\\n\\t\\t\\t\\t'is_external' => '',\\n\\t\\t\\t\\t'nofollow'    => '',\\n\\t\\t\\t),\\n\\t\\t\\t'title_color'           => AHE_MUTED,\\n\\t\\t\\t'title_hover_color'     => AHE_TEXT,\\n\\t\\t\\t'__globals__'           => array(\\n\\t\\t\\t\\t'title_color'       => 'globals\\\/colors?id=ahemute01',\\n\\t\\t\\t\\t'title_hover_color' => 'globals\\\/colors?id=aheink01',\\n\\t\\t\\t),\\n\\t\\t\\t'typography_typography' => 'custom',\\n\\t\\t\\t'typography_font_size'  => array(\\n\\t\\t\\t\\t'unit'  => 'px',\\n\\t\\t\\t\\t'size'  => 15,\\n\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t),\\n\\t\\t\\t'_element_width'        => 'auto',\\n\\t\\t),\\n\\t\\t'elements'   => array(),\\n\\t);\\n}\\n\\n\\\/** Pill button: hairline border, fully rounded, inverts on hover. *\\\/\\nfunction ahe_pill( string $text, string $url, array $extra = array() ): array {\\n\\treturn array(\\n\\t\\t'id'         => ahe_seed_id(),\\n\\t\\t'elType'     => 'widget',\\n\\t\\t'widgetType' => 'button',\\n\\t\\t'settings'   => array_merge(\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'text'                    => $text,\\n\\t\\t\\t\\t'link'                    => array(\\n\\t\\t\\t\\t\\t'url'         => $url,\\n\\t\\t\\t\\t\\t'is_external' => '',\\n\\t\\t\\t\\t\\t'nofollow'    => '',\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'button_text_color'       => AHE_TEXT,\\n\\t\\t\\t\\t\\\/\\\/ Group_Control_Background defaults to the kit's global accent\\n\\t\\t\\t\\t\\\/\\\/ color when unset \\u2014 explicit so the pill stays transparent.\\n\\t\\t\\t\\t'background_background'   => 'classic',\\n\\t\\t\\t\\t'background_color'        => 'transparent',\\n\\t\\t\\t\\t'border_border'           => 'solid',\\n\\t\\t\\t\\t'border_width'            => array(\\n\\t\\t\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t\\t\\t'top'      => '1',\\n\\t\\t\\t\\t\\t'right'    => '1',\\n\\t\\t\\t\\t\\t'bottom'   => '1',\\n\\t\\t\\t\\t\\t'left'     => '1',\\n\\t\\t\\t\\t\\t'isLinked' => true,\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'border_color'            => AHE_TEXT,\\n\\t\\t\\t\\t'border_radius'           => array(\\n\\t\\t\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t\\t\\t'top'      => '999',\\n\\t\\t\\t\\t\\t'right'    => '999',\\n\\t\\t\\t\\t\\t'bottom'   => '999',\\n\\t\\t\\t\\t\\t'left'     => '999',\\n\\t\\t\\t\\t\\t'isLinked' => true,\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'text_padding'            => array(\\n\\t\\t\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t\\t\\t'top'      => '8',\\n\\t\\t\\t\\t\\t'right'    => '18',\\n\\t\\t\\t\\t\\t'bottom'   => '8',\\n\\t\\t\\t\\t\\t'left'     => '18',\\n\\t\\t\\t\\t\\t'isLinked' => false,\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'typography_typography'   => 'custom',\\n\\t\\t\\t\\t'typography_font_size'    => array(\\n\\t\\t\\t\\t\\t'unit'  => 'px',\\n\\t\\t\\t\\t\\t'size'  => 15,\\n\\t\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'typography_font_weight'  => '500',\\n\\t\\t\\t\\t'hover_color'             => '#ffffff',\\n\\t\\t\\t\\t'button_background_hover_background' => 'classic',\\n\\t\\t\\t\\t'button_background_hover_color'      => AHE_TEXT,\\n\\t\\t\\t\\t'button_hover_border_color'          => AHE_TEXT,\\n\\t\\t\\t\\t\\\/\\\/ Token-bound (globals win over the hardcoded fallbacks): the\\n\\t\\t\\t\\t\\\/\\\/ sticky recolor inverts the pill, hover included \\u2014 hover text\\n\\t\\t\\t\\t\\\/\\\/ takes the Surface token, which goes dark while the bar does.\\n\\t\\t\\t\\t'__globals__'             => array(\\n\\t\\t\\t\\t\\t'button_text_color'             => 'globals\\\/colors?id=aheink01',\\n\\t\\t\\t\\t\\t'border_color'                  => 'globals\\\/colors?id=aheink01',\\n\\t\\t\\t\\t\\t'hover_color'                   => 'globals\\\/colors?id=ahesurf01',\\n\\t\\t\\t\\t\\t'button_background_hover_color' => 'globals\\\/colors?id=aheink01',\\n\\t\\t\\t\\t\\t'button_hover_border_color'     => 'globals\\\/colors?id=aheink01',\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'_element_width'          => 'auto',\\n\\t\\t\\t),\\n\\t\\t\\t$extra\\n\\t\\t),\\n\\t\\t'elements'   => array(),\\n\\t);\\n}\\n\\n\\\/**\\n * Inner structural container. Explicit zero padding + gap: the kit's default\\n * container padding and --widgets-spacing (20px) would leak in otherwise.\\n *\\\/\\nfunction ahe_row( array $settings, array $children ): array {\\n\\treturn array(\\n\\t\\t'id'       => ahe_seed_id(),\\n\\t\\t'elType'   => 'container',\\n\\t\\t'settings' => array_merge(\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'content_width' => 'full',\\n\\t\\t\\t\\t'padding'       => array(\\n\\t\\t\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t\\t\\t'top'      => '0',\\n\\t\\t\\t\\t\\t'right'    => '0',\\n\\t\\t\\t\\t\\t'bottom'   => '0',\\n\\t\\t\\t\\t\\t'left'     => '0',\\n\\t\\t\\t\\t\\t'isLinked' => true,\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'flex_gap'      => ahe_zero_gap(),\\n\\t\\t\\t),\\n\\t\\t\\t$settings\\n\\t\\t),\\n\\t\\t'elements' => $children,\\n\\t);\\n}\\n\\n\\\/** Content section: single column, generous vertical padding, anchor id. *\\\/\\nfunction ahe_section( string $anchor, array $children, array $extra = array() ): array {\\n\\treturn ahe_row(\\n\\t\\tarray_merge(\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'_element_id'    => $anchor,\\n\\t\\t\\t\\t'flex_direction' => 'column',\\n\\t\\t\\t\\t'flex_gap'       => ahe_gap( 12 ),\\n\\t\\t\\t\\t'padding'        => array(\\n\\t\\t\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t\\t\\t'top'      => '120',\\n\\t\\t\\t\\t\\t'right'    => '0',\\n\\t\\t\\t\\t\\t'bottom'   => '120',\\n\\t\\t\\t\\t\\t'left'     => '0',\\n\\t\\t\\t\\t\\t'isLinked' => false,\\n\\t\\t\\t\\t),\\n\\t\\t\\t),\\n\\t\\t\\t$extra\\n\\t\\t),\\n\\t\\t$children\\n\\t);\\n}\\n\\n\\\/**\\n * Header Zone block: a NON-header container carrying the zone controls the\\n * plugin adds to every regular container ($type: 'hide' or 'lock').\\n *\\\/\\nfunction ahe_zone( string $type, array $children ): array {\\n\\treturn ahe_row(\\n\\t\\tarray(\\n\\t\\t\\t'arts_header_zone'          => $type,\\n\\t\\t\\t'arts_header_zone_geometry' => 'overlap',\\n\\t\\t\\t'min_height'                => array(\\n\\t\\t\\t\\t'unit'  => 'vh',\\n\\t\\t\\t\\t'size'  => 78,\\n\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t),\\n\\t\\t\\t'flex_direction'            => 'column',\\n\\t\\t\\t'flex_justify_content'      => 'center',\\n\\t\\t\\t'flex_gap'                  => ahe_gap( 8 ),\\n\\t\\t\\t'background_background'     => 'classic',\\n\\t\\t\\t'background_color'          => AHE_SOFT,\\n\\t\\t\\t'border_radius'             => array(\\n\\t\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t\\t'top'      => '4',\\n\\t\\t\\t\\t'right'    => '4',\\n\\t\\t\\t\\t'bottom'   => '4',\\n\\t\\t\\t\\t'left'     => '4',\\n\\t\\t\\t\\t'isLinked' => true,\\n\\t\\t\\t),\\n\\t\\t\\t'padding'                   => array(\\n\\t\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t\\t'top'      => '48',\\n\\t\\t\\t\\t'right'    => '32',\\n\\t\\t\\t\\t'bottom'   => '48',\\n\\t\\t\\t\\t'left'     => '32',\\n\\t\\t\\t\\t'isLinked' => false,\\n\\t\\t\\t),\\n\\t\\t\\t'_margin'                   => array(\\n\\t\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t\\t'top'      => '24',\\n\\t\\t\\t\\t'right'    => '0',\\n\\t\\t\\t\\t'bottom'   => '0',\\n\\t\\t\\t\\t'left'     => '0',\\n\\t\\t\\t\\t'isLinked' => false,\\n\\t\\t\\t),\\n\\t\\t),\\n\\t\\t$children\\n\\t);\\n}\\n\\n\\\/\\\/ --- Logo attachments (dual-logo demo) ----------------------------------------\\n\\n$ahe_fail = static function ( string $message ): void {\\n\\tif ( defined( 'WP_CLI' ) && WP_CLI ) {\\n\\t\\tWP_CLI::error( $message );\\n\\t}\\n\\tthrow new RuntimeException( $message );\\n};\\n\\n$upload = wp_upload_dir();\\n\\nif ( ! empty( $upload['error'] ) ) {\\n\\t$ahe_fail( $upload['error'] );\\n}\\n\\n\\\/**\\n * Writes a file into uploads and registers it as an attachment, reusing one\\n * previously created under the same key.\\n *\\n * SVG is not on WordPress's mime whitelist, so the media uploader is bypassed:\\n * inserting the attachment directly skips the whitelist (it only guards\\n * uploads). Metadata is hand-written because generate_attachment_metadata()\\n * would hand the file to the image editor, which cannot measure an SVG and\\n * would record zeros.\\n *\\\/\\n$ahe_attach = static function (\\n\\tstring $key,\\n\\tstring $filename,\\n\\tstring $bytes,\\n\\tstring $title\\n) use ( $upload, $ahe_fail ): int {\\n\\t$existing = get_posts(\\n\\t\\tarray(\\n\\t\\t\\t'post_type'      => 'attachment',\\n\\t\\t\\t'post_status'    => 'inherit',\\n\\t\\t\\t'posts_per_page' => 1,\\n\\t\\t\\t'meta_key'       => '_arts_he_asset',\\n\\t\\t\\t'meta_value'     => $key,\\n\\t\\t\\t'fields'         => 'ids',\\n\\t\\t)\\n\\t);\\n\\n\\t$target = \\\"{$upload['path']}\\\/{$filename}\\\";\\n\\n\\tif ( false === file_put_contents( $target, $bytes ) ) {\\n\\t\\t$ahe_fail( \\\"Could not write {$target}\\\" );\\n\\t}\\n\\n\\t$relative = ltrim( str_replace( $upload['basedir'], '', $target ), '\\\/' );\\n\\t$id       = $existing ? (int) $existing[0] : 0;\\n\\n\\tif ( $id ) {\\n\\t\\twp_update_post(\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'ID'             => $id,\\n\\t\\t\\t\\t'post_title'     => $title,\\n\\t\\t\\t\\t'post_mime_type' => 'image\\\/svg+xml',\\n\\t\\t\\t)\\n\\t\\t);\\n\\t\\tupdate_post_meta( $id, '_wp_attached_file', $relative );\\n\\t} else {\\n\\t\\t$id = wp_insert_attachment(\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'post_mime_type' => 'image\\\/svg+xml',\\n\\t\\t\\t\\t'post_title'     => $title,\\n\\t\\t\\t\\t'post_content'   => '',\\n\\t\\t\\t\\t'post_status'    => 'inherit',\\n\\t\\t\\t),\\n\\t\\t\\t$target,\\n\\t\\t\\t0,\\n\\t\\t\\ttrue\\n\\t\\t);\\n\\n\\t\\tif ( is_wp_error( $id ) ) {\\n\\t\\t\\t$ahe_fail( $id->get_error_message() );\\n\\t\\t}\\n\\n\\t\\tupdate_post_meta( $id, '_arts_he_asset', $key );\\n\\t}\\n\\n\\twp_update_attachment_metadata(\\n\\t\\t$id,\\n\\t\\tarray(\\n\\t\\t\\t'width'  => 40,\\n\\t\\t\\t'height' => 40,\\n\\t\\t\\t'file'   => $relative,\\n\\t\\t\\t'sizes'  => array(),\\n\\t\\t)\\n\\t);\\n\\n\\treturn (int) $id;\\n};\\n\\n$ahe_svg_outline = <<<'SVG'\\n<svg xmlns=\\\"http:\\\/\\\/www.w3.org\\\/2000\\\/svg\\\" width=\\\"40\\\" height=\\\"40\\\" viewBox=\\\"0 0 40 40\\\"><rect x=\\\"5\\\" y=\\\"5\\\" width=\\\"30\\\" height=\\\"30\\\" fill=\\\"none\\\" stroke=\\\"#111111\\\" stroke-width=\\\"5\\\"\\\/><\\\/svg>\\nSVG;\\n\\n$ahe_svg_filled = <<<'SVG'\\n<svg xmlns=\\\"http:\\\/\\\/www.w3.org\\\/2000\\\/svg\\\" width=\\\"40\\\" height=\\\"40\\\" viewBox=\\\"0 0 40 40\\\"><rect x=\\\"5\\\" y=\\\"5\\\" width=\\\"30\\\" height=\\\"30\\\" fill=\\\"#f5f5f5\\\"\\\/><\\\/svg>\\nSVG;\\n\\n$outline_id = $ahe_attach( 'logo-outline', 'ahe-logo-outline.svg', $ahe_svg_outline, 'Header Engine \\u2014 Logo (outline)' );\\n$filled_id  = $ahe_attach( 'logo-filled', 'ahe-logo-filled.svg', $ahe_svg_filled, 'Header Engine \\u2014 Logo (filled)' );\\n\\n\\\/\\\/ The dual-logo widget reads these theme mods directly; setting them also\\n\\\/\\\/ forward-syncs into the Elementor kit via the plugin's pre_set_theme_mod\\n\\\/\\\/ filters. header_text gates the site-title text next to the mark.\\nset_theme_mod( 'custom_logo', $outline_id );\\nset_theme_mod( 'arts_header_custom_logo_secondary', $filled_id );\\nset_theme_mod( 'header_text', 1 );\\nupdate_option( 'blogname', 'Header Engine' );\\n\\\/\\\/ Blank, or \\\"Just another WordPress site\\\" renders as a tagline line.\\nupdate_option( 'blogdescription', '' );\\n\\n\\\/\\\/ --- Kit tokens: explicit header Global Colors -----------------------------------\\n\\\/\\\/ The recolor workflow the demo showcases: header content binds to these three\\n\\\/\\\/ tokens, and the header's Sticky Colors rows remap them while stuck. Merged\\n\\\/\\\/ into the kit's custom_colors keyed on _id \\u2014 idempotent, other colors kept.\\n\\n$kit_id = 0;\\nif ( class_exists( '\\\\Elementor\\\\Plugin' ) && \\\\Elementor\\\\Plugin::$instance && \\\\Elementor\\\\Plugin::$instance->kits_manager ) {\\n\\t$kit_id = (int) \\\\Elementor\\\\Plugin::$instance->kits_manager->get_active_id();\\n}\\n\\nif ( $kit_id ) {\\n\\t$kit_settings = get_post_meta( $kit_id, '_elementor_page_settings', true );\\n\\t$kit_settings = is_array( $kit_settings ) ? $kit_settings : array();\\n\\t$kit_custom   = isset( $kit_settings['custom_colors'] ) && is_array( $kit_settings['custom_colors'] ) ? $kit_settings['custom_colors'] : array();\\n\\n\\t$ahe_tokens = array(\\n\\t\\tarray(\\n\\t\\t\\t'_id'   => 'aheink01',\\n\\t\\t\\t'title' => 'Header Ink',\\n\\t\\t\\t'color' => AHE_TEXT,\\n\\t\\t),\\n\\t\\tarray(\\n\\t\\t\\t'_id'   => 'ahemute01',\\n\\t\\t\\t'title' => 'Header Muted',\\n\\t\\t\\t'color' => AHE_MUTED,\\n\\t\\t),\\n\\t\\tarray(\\n\\t\\t\\t'_id'   => 'ahesurf01',\\n\\t\\t\\t'title' => 'Header Surface',\\n\\t\\t\\t'color' => '#ffffff',\\n\\t\\t),\\n\\t);\\n\\n\\tforeach ( $ahe_tokens as $ahe_token ) {\\n\\t\\t$replaced = false;\\n\\t\\tforeach ( $kit_custom as $i => $row ) {\\n\\t\\t\\tif ( is_array( $row ) && isset( $row['_id'] ) && $row['_id'] === $ahe_token['_id'] ) {\\n\\t\\t\\t\\t$kit_custom[ $i ] = $ahe_token;\\n\\t\\t\\t\\t$replaced         = true;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif ( ! $replaced ) {\\n\\t\\t\\t$kit_custom[] = $ahe_token;\\n\\t\\t}\\n\\t}\\n\\n\\t$kit_settings['custom_colors'] = $kit_custom;\\n\\tupdate_post_meta( $kit_id, '_elementor_page_settings', wp_slash( $kit_settings ) );\\n\\n\\tif ( class_exists( '\\\\Elementor\\\\Core\\\\Files\\\\CSS\\\\Post' ) ) {\\n\\t\\t\\\\Elementor\\\\Core\\\\Files\\\\CSS\\\\Post::create( $kit_id )->delete();\\n\\t}\\n}\\n\\n\\\/\\\/ --- Primary header (top overlay, sticky + auto-hide) ---------------------------\\n\\n$header = array(\\n\\t'id'       => ahe_seed_id(),\\n\\t'elType'   => 'container',\\n\\t'isInner'  => false,\\n\\t'settings' => array(\\n\\t\\t'_title'                     => 'Header',\\n\\t\\t'content_width'              => 'full',\\n\\t\\t'flex_direction'             => 'row',\\n\\t\\t'flex_justify_content'       => 'space-between',\\n\\t\\t'flex_align_items'           => 'center',\\n\\t\\t'flex_gap'                   => ahe_gap( 24 ),\\n\\n\\t\\t\\\/\\\/ The plugin's panel controls \\u2014 everything the demo shows.\\n\\t\\t'arts_header_enabled'        => 'yes',\\n\\t\\t'arts_header_position'       => '',\\n\\t\\t'arts_header_on_scroll'      => 'auto-hide',\\n\\t\\t'arts_header_sticky_reveal_offset_preset'       => 'viewport',\\n\\t\\t'arts_header_state_non_sticky_logo_version'     => 'primary',\\n\\t\\t'arts_header_state_sticky_logo_version'         => 'secondary',\\n\\n\\t\\t\\\/\\\/ The recolor showcase: the stuck bar goes dark, and the three kit\\n\\t\\t\\\/\\\/ tokens the header content binds to flip light-on-dark with it.\\n\\t\\t'arts_header_sticky_global_colors'              => array(\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'_id'          => 'ahegc001',\\n\\t\\t\\t\\t'global_id'    => 'aheink01',\\n\\t\\t\\t\\t'sticky_color' => AHE_INK_STICKY,\\n\\t\\t\\t),\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'_id'          => 'ahegc002',\\n\\t\\t\\t\\t'global_id'    => 'ahemute01',\\n\\t\\t\\t\\t'sticky_color' => AHE_MUTED_STICKY,\\n\\t\\t\\t),\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'_id'          => 'ahegc003',\\n\\t\\t\\t\\t'global_id'    => 'ahesurf01',\\n\\t\\t\\t\\t'sticky_color' => AHE_DOCK_BG,\\n\\t\\t\\t),\\n\\t\\t),\\n\\t\\t'background_sticky_background' => 'classic',\\n\\t\\t'background_sticky_color'      => AHE_DOCK_BG,\\n\\t\\t\\\/\\\/ Explicit zero-width rest border: the bar transitions border-width, and\\n\\t\\t\\\/\\\/ without a rest value the unstick leg animates toward the browser\\n\\t\\t\\\/\\\/ default `medium` (3px, all sides) while the discrete border-style\\n\\t\\t\\\/\\\/ flips mid-transition \\u2014 a visible border flash.\\n\\t\\t'border_border'                => 'solid',\\n\\t\\t'border_width'                 => array(\\n\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t'top'      => '0',\\n\\t\\t\\t'right'    => '0',\\n\\t\\t\\t'bottom'   => '0',\\n\\t\\t\\t'left'     => '0',\\n\\t\\t\\t'isLinked' => false,\\n\\t\\t),\\n\\t\\t'border_color'                 => AHE_BORDER,\\n\\t\\t'border_sticky_border'         => 'solid',\\n\\t\\t'border_sticky_width'          => array(\\n\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t'top'      => '0',\\n\\t\\t\\t'right'    => '0',\\n\\t\\t\\t'bottom'   => '1',\\n\\t\\t\\t'left'     => '0',\\n\\t\\t\\t'isLinked' => false,\\n\\t\\t),\\n\\t\\t'border_sticky_color'          => '#2a2a2a',\\n\\n\\t\\t\\\/\\\/ Rest padding = the native control; the stuck state overrides it via\\n\\t\\t\\\/\\\/ padding_sticky (all four sides filled on both \\u2014 a blank side makes\\n\\t\\t\\\/\\\/ Elementor skip the whole rule). No native position\\\/z-index:\\n\\t\\t\\\/\\\/ _modes.scss owns positioning via the bar modifier class.\\n\\t\\t'padding'                    => array(\\n\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t'isLinked' => false,\\n\\t\\t\\t'top'      => '28',\\n\\t\\t\\t'bottom'   => '28',\\n\\t\\t\\t'left'     => '32',\\n\\t\\t\\t'right'    => '32',\\n\\t\\t),\\n\\t\\t'padding_sticky'             => array(\\n\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t'isLinked' => false,\\n\\t\\t\\t'top'      => '14',\\n\\t\\t\\t'bottom'   => '14',\\n\\t\\t\\t'left'     => '32',\\n\\t\\t\\t'right'    => '32',\\n\\t\\t),\\n\\t),\\n\\t'elements' => array(\\n\\t\\tarray(\\n\\t\\t\\t'id'         => ahe_seed_id(),\\n\\t\\t\\t'elType'     => 'widget',\\n\\t\\t\\t'widgetType' => 'arts-header-dual-site-logo',\\n\\t\\t\\t'settings'   => array(\\n\\t\\t\\t\\t'logo_link_type'   => 'custom',\\n\\t\\t\\t\\t'logo_custom_link' => array(\\n\\t\\t\\t\\t\\t'url'         => '#top',\\n\\t\\t\\t\\t\\t'is_external' => '',\\n\\t\\t\\t\\t\\t'nofollow'    => '',\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'logo_max_height'  => array(\\n\\t\\t\\t\\t\\t'size' => 18,\\n\\t\\t\\t\\t\\t'unit' => 'px',\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'gap_logo_text'    => array(\\n\\t\\t\\t\\t\\t'size' => 9,\\n\\t\\t\\t\\t\\t'unit' => 'px',\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'typography_title_control_typography'  => 'custom',\\n\\t\\t\\t\\t'typography_title_control_font_size'   => array(\\n\\t\\t\\t\\t\\t'unit'  => 'px',\\n\\t\\t\\t\\t\\t'size'  => 16,\\n\\t\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'typography_title_control_font_weight' => '600',\\n\\t\\t\\t\\t'color_title_control' => AHE_TEXT,\\n\\t\\t\\t\\t'__globals__'         => array(\\n\\t\\t\\t\\t\\t'color_title_control' => 'globals\\\/colors?id=aheink01',\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'_element_width'      => 'auto',\\n\\t\\t\\t),\\n\\t\\t\\t'elements'   => array(),\\n\\t\\t),\\n\\t\\tahe_row(\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'width'            => array(\\n\\t\\t\\t\\t\\t'unit' => 'custom',\\n\\t\\t\\t\\t\\t'size' => 'auto',\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'flex_direction'   => 'row',\\n\\t\\t\\t\\t'flex_align_items' => 'center',\\n\\t\\t\\t\\t'flex_gap'         => ahe_gap( 26 ),\\n\\t\\t\\t),\\n\\t\\t\\tarray(\\n\\t\\t\\t\\tahe_nav_link( 'Sticky', '#sticky' ),\\n\\t\\t\\t\\tahe_nav_link( 'Zones', '#zones' ),\\n\\t\\t\\t\\tahe_nav_link( 'Dock', '#dock' ),\\n\\t\\t\\t\\tahe_pill( 'Open editor', '#outro' ),\\n\\t\\t\\t)\\n\\t\\t),\\n\\t),\\n);\\n\\n\\\/\\\/ --- Page content ---------------------------------------------------------------\\n\\n$hero = ahe_row(\\n\\tarray(\\n\\t\\t'_element_id'          => 'top',\\n\\t\\t'flex_direction'       => 'column',\\n\\t\\t'flex_justify_content' => 'center',\\n\\t\\t'flex_gap'             => ahe_gap( 18 ),\\n\\t\\t'min_height'           => array(\\n\\t\\t\\t'unit'  => 'vh',\\n\\t\\t\\t'size'  => 92,\\n\\t\\t\\t'sizes' => array(),\\n\\t\\t),\\n\\t),\\n\\tarray(\\n\\t\\t\\\/\\\/ Anchor smoothness + landing clear of the fixed bar. Baked into page\\n\\t\\t\\\/\\\/ content because the seed runs once at provisioning \\u2014 a wp_head hook\\n\\t\\t\\\/\\\/ registered here would not survive past that request.\\n\\t\\tarray(\\n\\t\\t\\t'id'         => ahe_seed_id(),\\n\\t\\t\\t'elType'     => 'widget',\\n\\t\\t\\t'widgetType' => 'html',\\n\\t\\t\\t'settings'   => array(\\n\\t\\t\\t\\t'html' => '<style>html{scroll-behavior:smooth;scroll-padding-top:84px}<\\\/style>',\\n\\t\\t\\t),\\n\\t\\t\\t'elements'   => array(),\\n\\t\\t),\\n\\t\\tahe_heading(\\n\\t\\t\\t'A header that stays out of the way.',\\n\\t\\t\\t'h1',\\n\\t\\t\\t'clamp(32px, 5vw, 44px)',\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'typography_line_height'    => array(\\n\\t\\t\\t\\t\\t'unit' => 'custom',\\n\\t\\t\\t\\t\\t'size' => '1.15',\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'typography_letter_spacing' => array(\\n\\t\\t\\t\\t\\t'unit'  => 'em',\\n\\t\\t\\t\\t\\t'size'  => -0.02,\\n\\t\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t\\t),\\n\\t\\t\\t)\\n\\t\\t),\\n\\t\\tahe_body(\\n\\t\\t\\t'Sticky, auto-hide, and zone-aware \\u2014 animated entirely in CSS, configured entirely in the Elementor panel.',\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'_element_custom_width' => array(\\n\\t\\t\\t\\t\\t'unit' => 'custom',\\n\\t\\t\\t\\t\\t'size' => 'min(44ch, 100%)',\\n\\t\\t\\t\\t),\\n\\t\\t\\t)\\n\\t\\t),\\n\\t\\tahe_body(\\n\\t\\t\\t'Scroll \\u2014 the bar above is live.',\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'typography_font_size' => array(\\n\\t\\t\\t\\t\\t'unit'  => 'px',\\n\\t\\t\\t\\t\\t'size'  => 14,\\n\\t\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'_margin'              => array(\\n\\t\\t\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t\\t\\t'top'      => '30',\\n\\t\\t\\t\\t\\t'right'    => '0',\\n\\t\\t\\t\\t\\t'bottom'   => '0',\\n\\t\\t\\t\\t\\t'left'     => '0',\\n\\t\\t\\t\\t\\t'isLinked' => false,\\n\\t\\t\\t\\t),\\n\\t\\t\\t)\\n\\t\\t),\\n\\t)\\n);\\n\\n$sticky_section = ahe_section(\\n\\t'sticky',\\n\\tarray(\\n\\t\\tahe_heading( 'The sticky flip', 'h2', '22px' ),\\n\\t\\tahe_body( 'Past the first screen the bar turns dark \\u2014 and everything in it re-inks itself. The header remaps Global Colors while sticky, so the menu, the button and the site title follow with no per-widget wiring; the logo swaps to its light version.' ),\\n\\t\\tahe_body( 'Auto-hide waits out the first full screen \\u2014 the reveal offset, set to one viewport height in the panel. From here on, scrolling down sends the bar away; scrolling up brings it back.' ),\\n\\t)\\n);\\n\\n$zones_section = ahe_section(\\n\\t'zones',\\n\\tarray(\\n\\t\\tahe_heading( 'Zones', 'h2', '22px' ),\\n\\t\\tahe_body( 'Any section can tell the header what to do while they overlap. This one asks it to stay hidden:' ),\\n\\t\\tahe_zone(\\n\\t\\t\\t'hide',\\n\\t\\t\\tarray(\\n\\t\\t\\t\\tahe_heading( 'Hide zone', 'h3', '17px' ),\\n\\t\\t\\t\\tahe_body(\\n\\t\\t\\t\\t\\t\\\"Think fullscreen slider or video. Scrolling up in here won't bring the header back \\u2014 it returns when you leave.\\\",\\n\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t'typography_font_size'  => array(\\n\\t\\t\\t\\t\\t\\t\\t'unit'  => 'px',\\n\\t\\t\\t\\t\\t\\t\\t'size'  => 15,\\n\\t\\t\\t\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t\\t\\t\\t),\\n\\t\\t\\t\\t\\t\\t'_element_custom_width' => array(\\n\\t\\t\\t\\t\\t\\t\\t'unit' => 'custom',\\n\\t\\t\\t\\t\\t\\t\\t'size' => 'min(46ch, 100%)',\\n\\t\\t\\t\\t\\t\\t),\\n\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\tahe_body(\\n\\t\\t\\t\\t\\t'Try it: scroll up \\u2014 the bar waits outside.',\\n\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t'typography_font_size' => array(\\n\\t\\t\\t\\t\\t\\t\\t'unit'  => 'px',\\n\\t\\t\\t\\t\\t\\t\\t'size'  => 13,\\n\\t\\t\\t\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t\\t\\t\\t),\\n\\t\\t\\t\\t\\t\\t'_margin'              => array(\\n\\t\\t\\t\\t\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t\\t\\t\\t\\t'top'      => '16',\\n\\t\\t\\t\\t\\t\\t\\t'right'    => '0',\\n\\t\\t\\t\\t\\t\\t\\t'bottom'   => '0',\\n\\t\\t\\t\\t\\t\\t\\t'left'     => '0',\\n\\t\\t\\t\\t\\t\\t\\t'isLinked' => false,\\n\\t\\t\\t\\t\\t\\t),\\n\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t),\\n\\t\\t\\t)\\n\\t\\t),\\n\\t\\tahe_body(\\n\\t\\t\\t'Between zones normal auto-hide applies. The next one does the opposite:',\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'typography_font_size' => array(\\n\\t\\t\\t\\t\\t'unit'  => 'px',\\n\\t\\t\\t\\t\\t'size'  => 15,\\n\\t\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'_margin'              => array(\\n\\t\\t\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t\\t\\t'top'      => '32',\\n\\t\\t\\t\\t\\t'right'    => '0',\\n\\t\\t\\t\\t\\t'bottom'   => '0',\\n\\t\\t\\t\\t\\t'left'     => '0',\\n\\t\\t\\t\\t\\t'isLinked' => false,\\n\\t\\t\\t\\t),\\n\\t\\t\\t)\\n\\t\\t),\\n\\t\\tahe_zone(\\n\\t\\t\\t'lock',\\n\\t\\t\\tarray(\\n\\t\\t\\t\\tahe_heading( 'Lock zone', 'h3', '17px' ),\\n\\t\\t\\t\\tahe_body(\\n\\t\\t\\t\\t\\t\\\"This one pins the bar on screen: while you're over it the header shows and stays, whatever the scroll direction \\u2014 useful over forms and checkout steps.\\\",\\n\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t'typography_font_size'  => array(\\n\\t\\t\\t\\t\\t\\t\\t'unit'  => 'px',\\n\\t\\t\\t\\t\\t\\t\\t'size'  => 15,\\n\\t\\t\\t\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t\\t\\t\\t),\\n\\t\\t\\t\\t\\t\\t'_element_custom_width' => array(\\n\\t\\t\\t\\t\\t\\t\\t'unit' => 'custom',\\n\\t\\t\\t\\t\\t\\t\\t'size' => 'min(46ch, 100%)',\\n\\t\\t\\t\\t\\t\\t),\\n\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\tahe_body(\\n\\t\\t\\t\\t\\t'Try it: keep scrolling down \\u2014 the bar refuses to leave.',\\n\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t'typography_font_size' => array(\\n\\t\\t\\t\\t\\t\\t\\t'unit'  => 'px',\\n\\t\\t\\t\\t\\t\\t\\t'size'  => 13,\\n\\t\\t\\t\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t\\t\\t\\t),\\n\\t\\t\\t\\t\\t\\t'_margin'              => array(\\n\\t\\t\\t\\t\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t\\t\\t\\t\\t'top'      => '16',\\n\\t\\t\\t\\t\\t\\t\\t'right'    => '0',\\n\\t\\t\\t\\t\\t\\t\\t'bottom'   => '0',\\n\\t\\t\\t\\t\\t\\t\\t'left'     => '0',\\n\\t\\t\\t\\t\\t\\t\\t'isLinked' => false,\\n\\t\\t\\t\\t\\t\\t),\\n\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t),\\n\\t\\t\\t)\\n\\t\\t),\\n\\t)\\n);\\n\\n$dock_section = ahe_section(\\n\\t'dock',\\n\\tarray(\\n\\t\\tahe_heading( 'More than one', 'h2', '22px' ),\\n\\t\\tahe_body( \\\"The dark rail along the bottom edge is a second header instance, docked low and hiding downward \\u2014 it's been there since the page loaded, leaving whenever you scroll down. Instances run independently on the same page.\\\" ),\\n\\t)\\n);\\n\\n$outro_section = ahe_section(\\n\\t'outro',\\n\\tarray(\\n\\t\\tahe_heading( 'See the panel', 'h2', '22px' ),\\n\\t\\tahe_body( 'Everything on this page is a panel setting. The preview logs you in \\u2014 open the page in Elementor and click the header container.' ),\\n\\t\\tahe_pill(\\n\\t\\t\\t'Open in Elementor',\\n\\t\\t\\tadmin_url( 'post.php?post=' . AHE_DEMO_PAGE_ID . '&action=elementor' ),\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'_margin' => array(\\n\\t\\t\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t\\t\\t'top'      => '14',\\n\\t\\t\\t\\t\\t'right'    => '0',\\n\\t\\t\\t\\t\\t'bottom'   => '0',\\n\\t\\t\\t\\t\\t'left'     => '0',\\n\\t\\t\\t\\t\\t'isLinked' => false,\\n\\t\\t\\t\\t),\\n\\t\\t\\t)\\n\\t\\t),\\n\\t),\\n\\tarray(\\n\\t\\t'padding' => array(\\n\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t'top'      => '120',\\n\\t\\t\\t'right'    => '0',\\n\\t\\t\\t'bottom'   => '200',\\n\\t\\t\\t'left'     => '0',\\n\\t\\t\\t'isLinked' => false,\\n\\t\\t),\\n\\t)\\n);\\n\\n$page_wrapper = array(\\n\\t'id'       => ahe_seed_id(),\\n\\t'elType'   => 'container',\\n\\t'isInner'  => false,\\n\\t'settings' => array(\\n\\t\\t'_title'        => 'Content',\\n\\t\\t'content_width' => 'boxed',\\n\\t\\t'boxed_width'   => array(\\n\\t\\t\\t'unit'  => 'px',\\n\\t\\t\\t'size'  => 640,\\n\\t\\t\\t'sizes' => array(),\\n\\t\\t),\\n\\t\\t'flex_gap'      => ahe_zero_gap(),\\n\\t\\t'padding'       => array(\\n\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t'top'      => '0',\\n\\t\\t\\t'right'    => '24',\\n\\t\\t\\t'bottom'   => '0',\\n\\t\\t\\t'left'     => '24',\\n\\t\\t\\t'isLinked' => false,\\n\\t\\t),\\n\\t),\\n\\t'elements' => array( $hero, $sticky_section, $zones_section, $dock_section, $outro_section ),\\n);\\n\\n\\\/\\\/ --- Secondary header (bottom dock) ---------------------------------------------\\n\\\/\\\/ Rendered after the primary in the element tree \\u2014 the first-rendered header\\n\\\/\\\/ container becomes the primary (page globals owner); this one runs with\\n\\\/\\\/ heightObserver and zones off automatically. It must also come BEFORE the tall\\n\\\/\\\/ page content: a fixed wrapper's natural position is estimated from its\\n\\\/\\\/ previous sibling (estimateNaturalTop), and a document-end estimate would keep\\n\\\/\\\/ the bottom dock un-stuck \\u2014 auto-hide machinery never engages.\\n\\n$dock = array(\\n\\t'id'       => ahe_seed_id(),\\n\\t'elType'   => 'container',\\n\\t'isInner'  => false,\\n\\t'settings' => array(\\n\\t\\t'_title'                => 'Bottom Dock',\\n\\t\\t'content_width'         => 'full',\\n\\t\\t'flex_direction'        => 'row',\\n\\t\\t'flex_justify_content'  => 'space-between',\\n\\t\\t'flex_align_items'      => 'center',\\n\\t\\t'flex_gap'              => ahe_gap( 16 ),\\n\\n\\t\\t'arts_header_enabled'   => 'yes',\\n\\t\\t'arts_header_position'  => 'bottom',\\n\\t\\t'arts_header_on_scroll' => 'auto-hide',\\n\\t\\t'arts_header_sticky_reveal_offset_preset' => 'viewport',\\n\\n\\t\\t'background_background' => 'classic',\\n\\t\\t'background_color'      => AHE_DOCK_BG,\\n\\t\\t'padding'               => array(\\n\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t'top'      => '13',\\n\\t\\t\\t'right'    => '32',\\n\\t\\t\\t'bottom'   => '13',\\n\\t\\t\\t'left'     => '32',\\n\\t\\t\\t'isLinked' => false,\\n\\t\\t),\\n\\t),\\n\\t'elements' => array(\\n\\t\\tahe_body(\\n\\t\\t\\t'Second instance \\u2014 bottom dock',\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'title_color'          => AHE_DOCK_TEXT,\\n\\t\\t\\t\\t'typography_font_size' => array(\\n\\t\\t\\t\\t\\t'unit'  => 'px',\\n\\t\\t\\t\\t\\t'size'  => 13,\\n\\t\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'_element_width'       => 'auto',\\n\\t\\t\\t\\t'_element_custom_width' => array(),\\n\\t\\t\\t)\\n\\t\\t),\\n\\t\\tahe_body(\\n\\t\\t\\t'hides on scroll down',\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'title_color'          => AHE_DOCK_TEXT,\\n\\t\\t\\t\\t'typography_font_size' => array(\\n\\t\\t\\t\\t\\t'unit'  => 'px',\\n\\t\\t\\t\\t\\t'size'  => 13,\\n\\t\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t\\t),\\n\\t\\t\\t\\t'_element_width'       => 'auto',\\n\\t\\t\\t\\t'_element_custom_width' => array(),\\n\\t\\t\\t)\\n\\t\\t),\\n\\t),\\n);\\n\\n\\\/\\\/ --- Persist --------------------------------------------------------------------\\n\\n$slug     = 'ahe-demo';\\n$existing = get_page_by_path( $slug );\\n\\n$post_id = $existing ? $existing->ID : wp_insert_post(\\n\\tarray(\\n\\t\\t'import_id'   => AHE_DEMO_PAGE_ID,\\n\\t\\t'post_type'   => 'page',\\n\\t\\t'post_status' => 'publish',\\n\\t\\t'post_title'  => 'Artem Semkin Header Engine \\u2014 Demo',\\n\\t\\t'post_name'   => $slug,\\n\\t),\\n\\ttrue\\n);\\n\\nif ( is_wp_error( $post_id ) ) {\\n\\tif ( defined( 'WP_CLI' ) && WP_CLI ) {\\n\\t\\tWP_CLI::error( $post_id->get_error_message() );\\n\\t}\\n\\treturn;\\n}\\n\\n$elements = array( $header, $dock, $page_wrapper );\\n\\n$page_settings = array(\\n\\t'template'              => 'elementor_canvas',\\n\\t'hide_title'            => 'yes',\\n\\t'background_background' => 'classic',\\n\\t'background_color'      => '#ffffff',\\n);\\n\\n\\\/\\\/ Mirrors Document::save()'s sequence (elementor\\\/core\\\/base\\\/document.php).\\nupdate_post_meta( $post_id, '_elementor_page_settings', wp_slash( $page_settings ) );\\nupdate_post_meta( $post_id, '_elementor_data', wp_slash( wp_json_encode( $elements, JSON_UNESCAPED_UNICODE ) ) );\\nupdate_post_meta( $post_id, '_elementor_edit_mode', 'builder' );\\nupdate_post_meta( $post_id, '_elementor_template_type', 'wp-page' );\\nupdate_post_meta( $post_id, '_wp_page_template', 'elementor_canvas' );\\n\\nif ( defined( 'ELEMENTOR_VERSION' ) ) {\\n\\tupdate_post_meta( $post_id, '_elementor_version', ELEMENTOR_VERSION );\\n}\\n\\n\\\/\\\/ Post CSS never diffs (is_update_required() is hard-coded false) \\u2014 delete to regen.\\nif ( class_exists( '\\\\Elementor\\\\Core\\\\Files\\\\CSS\\\\Post' ) ) {\\n\\t\\\\Elementor\\\\Core\\\\Files\\\\CSS\\\\Post::create( $post_id )->delete();\\n}\\ndelete_post_meta( $post_id, '_elementor_element_cache' );\\n\\n\\\/\\\/ The editor prefers newer autosave revisions over raw meta \\u2014 remove them all.\\nforeach ( wp_get_post_revisions( $post_id, array( 'fields' => 'ids' ) ) as $revision_id ) {\\n\\twp_delete_post_revision( $revision_id );\\n}\\n\\nif ( defined( 'WP_CLI' ) && WP_CLI ) {\\n\\tWP_CLI::success( sprintf( 'Demo page seeded: post_id=%d %s', $post_id, get_permalink( $post_id ) ) );\\n}\\n\"},{\"step\":\"runPHP\",\"code\":\"<?php require_once '\\\/wordpress\\\/wp-load.php'; require '\\\/wordpress\\\/wp-content\\\/artem-semkin-header-engine-for-elementor-demo-seed.php';\"},{\"step\":\"installPlugin\",\"pluginData\":{\"resource\":\"wordpress.org\\\/plugins\",\"slug\":\"artem-semkin-header-engine-for-elementor\"},\"options\":{\"activate\":true}}]}"}},"all_blocks":[],"tagged_versions":["1.0.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3669856,"resolution":"1","location":"assets","locale":"","width":1520,"height":1520},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3669856,"resolution":"2","location":"assets","locale":"","width":1520,"height":1520},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3669856,"resolution":"3","location":"assets","locale":"","width":1520,"height":1520},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3669856,"resolution":"4","location":"assets","locale":"","width":1520,"height":1520},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3669856,"resolution":"5","location":"assets","locale":"","width":1520,"height":1520}},"screenshots":{"1":"The Create Header section in the Layout tab of an Elementor Container \u2014 turn any container into a site header right in its own settings panel.","2":"Header scroll behavior settings: position, Sticky &amp; Auto-Hide mode, pin and reveal offsets, the dual logo per state, and the Global Color overrides that recolor the stuck header.","3":"Sticky Header Styles in the Style tab \u2014 a separate background for the stuck header, set with Elementor's native controls.","4":"The bundled Dual Site Logo widget in the Elementor elements panel.","5":"Primary and secondary logos in the Dual Site Logo widget \u2014 the header swaps them automatically when it sticks."}},"plugin_section":[],"plugin_tags":[76538,177797,217390,10213,179681],"plugin_category":[],"plugin_contributors":[241532],"plugin_business_model":[],"class_list":["post-357934","plugin","type-plugin","status-publish","hentry","plugin_tags-elementor","plugin_tags-elementor-header","plugin_tags-hide-header","plugin_tags-sticky-header","plugin_tags-transparent-header","plugin_contributors-artemsemkin","plugin_committers-artemsemkin"],"banners":{"banner":"https:\/\/ps.w.org\/artem-semkin-header-engine-for-elementor\/assets\/banner-772x250.jpg?rev=3669856","banner_2x":"https:\/\/ps.w.org\/artem-semkin-header-engine-for-elementor\/assets\/banner-1544x500.jpg?rev=3669856","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":"https:\/\/ps.w.org\/artem-semkin-header-engine-for-elementor\/assets\/icon.svg?rev=3669856","icon":"https:\/\/ps.w.org\/artem-semkin-header-engine-for-elementor\/assets\/icon.svg?rev=3669856","icon_2x":false,"generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/artem-semkin-header-engine-for-elementor\/assets\/screenshot-1.png?rev=3669856","caption":"The Create Header section in the Layout tab of an Elementor Container \u2014 turn any container into a site header right in its own settings panel."},{"src":"https:\/\/ps.w.org\/artem-semkin-header-engine-for-elementor\/assets\/screenshot-2.png?rev=3669856","caption":"Header scroll behavior settings: position, Sticky &amp; Auto-Hide mode, pin and reveal offsets, the dual logo per state, and the Global Color overrides that recolor the stuck header."},{"src":"https:\/\/ps.w.org\/artem-semkin-header-engine-for-elementor\/assets\/screenshot-3.png?rev=3669856","caption":"Sticky Header Styles in the Style tab \u2014 a separate background for the stuck header, set with Elementor's native controls."},{"src":"https:\/\/ps.w.org\/artem-semkin-header-engine-for-elementor\/assets\/screenshot-4.png?rev=3669856","caption":"The bundled Dual Site Logo widget in the Elementor elements panel."},{"src":"https:\/\/ps.w.org\/artem-semkin-header-engine-for-elementor\/assets\/screenshot-5.png?rev=3669856","caption":"Primary and secondary logos in the Dual Site Logo widget \u2014 the header swaps them automatically when it sticks."}],"raw_content":"<!--section=description-->\n<p>Turn any Elementor Container into a site header that knows what to do on scroll: pin it to the top, tuck it away while readers scroll down, bring it back the moment they scroll up, and restyle it while it is stuck. You set it all up in the Container's own settings panel. There is no separate builder to learn, and the free version of Elementor is enough.<\/p>\n\n<h4>What you get<\/h4>\n\n<ul>\n<li><strong>Sticky header<\/strong> \u2014 the container pins to the viewport once the page would scroll it away.<\/li>\n<li><strong>Auto-hide and reveal<\/strong> \u2014 the header slides out of view on scroll down and returns the moment the reader scrolls up, from anywhere on the page.<\/li>\n<li><strong>Transparent overlay headers<\/strong> \u2014 lay the header over your hero section, then give the sticky state a solid background so it fills in as it pins.<\/li>\n<li><strong>Sticky-state styling<\/strong> \u2014 separate background, border, box-shadow and padding for the stuck header, set with Elementor's native style controls.<\/li>\n<li><strong>Recolor while sticky<\/strong> \u2014 remap any Elementor Global Color for the stuck header: every widget inside that uses it \u2014 menus, buttons, icons, from any addon \u2014 switches with it. No per-widget color settings to hunt down.<\/li>\n<li><strong>Logo swap<\/strong> \u2014 the bundled Dual Site Logo widget switches between a primary and a secondary logo when the header sticks, so a light logo over the hero can become a dark one on a solid sticky bar.<\/li>\n<li><strong>Header zones<\/strong> \u2014 mark any other container on the page to hide the header while visitors scroll over it, or to reveal and lock it there. Handy over full-screen galleries and embedded maps.<\/li>\n<li><strong>Reveal offset<\/strong> \u2014 start auto-hiding only after a chosen scroll distance: a custom value, the viewport height, or the header's own height.<\/li>\n<li><strong>Pin offset<\/strong> \u2014 stick the header below a custom line. Negative offsets work too, which lets a tall header stick in a compact form.<\/li>\n<li><strong>Bottom dock<\/strong> \u2014 fix the header to the bottom edge instead; auto-hide slides it down and out of the way.<\/li>\n<li><strong>In-page sticky bars<\/strong> \u2014 the Default position keeps the container in the page flow and pins it within its parent: mid-page filter bars, sub-menus, section navigation.<\/li>\n<li><strong>Multiple headers per page<\/strong> \u2014 every container you mark runs as its own independent instance.<\/li>\n<\/ul>\n\n<h4>Built to stay out of your way<\/h4>\n\n<ul>\n<li>Zero runtime dependencies. The engine ships without jQuery or animation libraries, so there is nothing for other plugins to conflict with.<\/li>\n<li>The engine only toggles CSS classes and custom properties; every visible animation runs in CSS. There is no per-frame JavaScript styling.<\/li>\n<li>No layout jumps. Overlay headers never affect page flow, and in-flow headers reserve a constant slot, so the page does not shift when the header sticks or shrinks.<\/li>\n<li>No external services. Nothing loads from third-party servers and nothing phones home.<\/li>\n<li>There is no Pro tier. Every feature is included, and your dashboard stays free of ads.<\/li>\n<\/ul>\n\n<h4>Works with<\/h4>\n\n<ul>\n<li>Elementor Free. The header is a regular Container, styled with the controls you already use.<\/li>\n<li>Any theme. The plugin ships its styles in a dedicated CSS cascade layer, so your theme's CSS wins any conflict.<\/li>\n<li>Elementor Pro Theme Builder header templates, for the Top and Bottom positions.<\/li>\n<\/ul>\n\n<h4>For developers<\/h4>\n\n<p>The engine publishes its state as CSS classes and custom properties on the header wrapper and fires CustomEvents on <code>document<\/code>: <code>arts\/header\/sticky<\/code>, <code>arts\/header\/hidden<\/code>, <code>arts\/header\/locked<\/code>, <code>arts\/header\/released<\/code>, <code>arts\/header\/displaced<\/code>. The TypeScript and SCSS source lives on GitHub: https:\/\/github.com\/artkrsk\/header-engine-for-elementor<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Install and activate the plugin. Elementor must be active.<\/li>\n<li>Edit a page with Elementor and select the top-level Container you want as your header.<\/li>\n<li>In the Layout tab, open the Create Header section and switch on \"Use this Container as Page Header\".<\/li>\n<li>Pick a Position (Top, Bottom or Default) and an On Scroll behavior (Sticky, or Sticky &amp; Auto-Hide), then style the Sticky State to taste.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20it%20require%20elementor%20pro%3F\"><h3>Does it require Elementor Pro?<\/h3><\/dt>\n<dd><p>No. It works with the free Elementor plugin \u2014 any Container can become a header. If you use Elementor Pro, header templates built with the Theme Builder work too, in the Top and Bottom positions.<\/p><\/dd>\n<dt id=\"where%20are%20the%20settings%3F\"><h3>Where are the settings?<\/h3><\/dt>\n<dd><p>On the Container itself. Select the container in the Elementor editor and open Layout \u2192 Create Header. There is no separate admin page.<\/p><\/dd>\n<dt id=\"will%20my%20content%20jump%20when%20the%20header%20becomes%20sticky%3F\"><h3>Will my content jump when the header becomes sticky?<\/h3><\/dt>\n<dd><p>No. Headers in the Top and Bottom positions overlay the page and never affect its layout. Headers in the Default position reserve a constant slot in the page, so even a header that shrinks while sticky does not shift the content below it.<\/p><\/dd>\n<dt id=\"can%20the%20header%20look%20different%20while%20it%20is%20sticky%3F\"><h3>Can the header look different while it is sticky?<\/h3><\/dt>\n<dd><p>Yes. The Sticky State section has its own background, border, box-shadow and padding controls, the Sticky Colors rows can remap your Global Colors for everything inside, and the Dual Site Logo widget can swap to a second logo. The transition between the two states is animated in CSS.<\/p><\/dd>\n<dt id=\"how%20do%20i%20change%20my%20menu%20and%20text%20colors%20when%20the%20header%20sticks%3F\"><h3>How do I change my menu and text colors when the header sticks?<\/h3><\/dt>\n<dd><p>Use Elementor Global Colors in the widgets inside your header, then add rows under Create Header \u2192 Sticky Colors: each row maps one Global Color to the value it should take while the header is sticky. Every widget that uses that color follows automatically, third-party widgets included. Plain hex colors are left alone, and a widget's own sticky-specific color control, if it has one, still wins.<\/p><\/dd>\n<dt id=\"how%20do%20i%20make%20a%20transparent%20header%20that%20turns%20solid%20on%20scroll%3F\"><h3>How do I make a transparent header that turns solid on scroll?<\/h3><\/dt>\n<dd><p>Set Position to Top, leave the container's background empty, and give the Sticky State a solid background. The header overlays your hero, then fills in as it pins.<\/p><\/dd>\n<dt id=\"can%20i%20hide%20the%20header%20over%20one%20specific%20section%3F\"><h3>Can I hide the header over one specific section?<\/h3><\/dt>\n<dd><p>Yes. Select any other container on the page and open its Header Zone section: choose Hide Header or Reveal &amp; Lock Header, and pick when the zone counts: when it reaches the top, overlaps the header, or is in view.<\/p><\/dd>\n<dt id=\"why%20doesn%27t%20the%20default%20position%20stick%20inside%20my%20theme%20builder%20header%3F\"><h3>Why doesn't the Default position stick inside my Theme Builder header?<\/h3><\/dt>\n<dd><p>The Default position pins the header within its parent container, and a Theme Builder header location is only as tall as the header itself, so there is nowhere to pin. Use the Top position for site headers; Default is meant for bars inside tall page content.<\/p><\/dd>\n<dt id=\"does%20it%20slow%20down%20my%20site%3F\"><h3>Does it slow down my site?<\/h3><\/dt>\n<dd><p>No. The script and stylesheet together weigh about 25 KB, and the engine does its work on a single shared scroll listener with cached geometry; the animations themselves run in CSS.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.0<\/h4>\n\n<p>Initial release.<\/p>","raw_excerpt":"Sticky and auto-hide header for Elementor containers. Hide on scroll down, reveal on scroll up, logo swap, sticky styling. Free, zero dependencies.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/szl.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/357934","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/szl.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/szl.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/szl.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=357934"}],"author":[{"embeddable":true,"href":"https:\/\/szl.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/artemsemkin"}],"wp:attachment":[{"href":"https:\/\/szl.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=357934"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/szl.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=357934"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/szl.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=357934"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/szl.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=357934"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/szl.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=357934"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/szl.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=357934"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}