{"id":361337,"date":"2026-08-31T09:20:49","date_gmt":"2026-08-31T09:20:49","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/arts-immersive-lightbox-for-elementor\/"},"modified":"2026-08-31T09:20:20","modified_gmt":"2026-08-31T09:20:20","slug":"immersive-lightbox-for-elementor","status":"publish","type":"plugin","link":"https:\/\/tzm.wordpress.org\/plugins\/immersive-lightbox-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.2","requires_php":"8.0","requires_plugins":null,"header_name":"Arts Immersive Lightbox for Elementor","header_author":"Artem Semkin","header_description":"A PhotoSwipe lightbox that replaces Elementor's native one: cinematic transitions, mousemove explore pan, video galleries, any link as a trigger.","assets_banners_color":"191919","last_updated":"2026-08-31 09:20:20","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/artemsemkin.com\/plugins\/immersive-lightbox-for-elementor\/","header_author_uri":"https:\/\/artemsemkin.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":39,"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-31 09:20:20","revision":3673742}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3673742,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3673742,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon.svg":{"filename":"icon.svg","revision":3673742,"resolution":false,"location":"assets","locale":false}},"assets_banners":{"banner-1544x500.jpg":{"filename":"banner-1544x500.jpg","revision":3673742,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.jpg":{"filename":"banner-772x250.jpg","revision":3673742,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{"blueprint.json":{"filename":"blueprint.json","revision":3673743,"resolution":false,"location":"assets","locale":"","contents":"{\"$schema\":\"https:\\\/\\\/playground.wordpress.net\\\/blueprint-schema.json\",\"landingPage\":\"\\\/?page_id=9942\",\"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\\\/immersive-lightbox-for-elementor-demo-seed.php\",\"data\":\"<?php\\n\\\/**\\n * Seeds the \\\"Arts Immersive Lightbox \\u2014 Demo\\\" page: the Live Preview landing\\n * page on 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 slide attachments are keyed on a meta value and reused.\\n *\\n * The slides are SVG compositions embedded below. The blueprint cannot fetch\\n * assets (wp.org's SVN serves no CORS headers), and vector stays crisp at any\\n * explore-pan zoom. WordPress does not count .svg as an image\\n * (wp_attachment_is_image), so each attachment's metadata carries a\\n * `sizes.full` entry \\u2014 the one branch of image_downsize() that lets a\\n * non-image through \\u2014 which is what makes [gallery] and the Image widget\\n * render them at all.\\n *\\n * The lightbox runs on kit defaults plus one flipped switch (thumbnails). The\\n * widgets carry the same settings the panel would 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( 'AIL_DEMO_PAGE_ID', 9942 );\\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\\\/\\\/ update_option( 'blogname' ) below forward-syncs into the Elementor kit\\n\\\/\\\/ through Elementor's own update_option_blogname hook, and that kit save\\n\\\/\\\/ runs a capability check (\\\"Access denied\\\" in the blueprint's userless\\n\\\/\\\/ runPHP context otherwise).\\nwp_set_current_user( 1 );\\n\\nconst AIL_TEXT  = '#111111';\\nconst AIL_MUTED = '#6b6b6b';\\n\\nfunction ail_seed_id(): string {\\n\\treturn substr( bin2hex( random_bytes( 4 ) ), 0, 7 );\\n}\\n\\nfunction ail_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 ail_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 ail_heading( string $title, string $tag, string $font_size, array $extra = array() ): array {\\n\\treturn array(\\n\\t\\t'id'         => ail_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'               => AIL_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 ail_body( string $title, array $extra = array() ): array {\\n\\treturn array(\\n\\t\\t'id'         => ail_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'            => AIL_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\\\/** Small hint line under a showcase: 14px, a little air above. *\\\/\\nfunction ail_hint( string $title ): array {\\n\\treturn ail_body(\\n\\t\\t$title,\\n\\t\\tarray(\\n\\t\\t\\t'typography_font_size' => array(\\n\\t\\t\\t\\t'unit'  => 'px',\\n\\t\\t\\t\\t'size'  => 14,\\n\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t),\\n\\t\\t\\t'_margin'              => array(\\n\\t\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t\\t'top'      => '8',\\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);\\n}\\n\\n\\\/**\\n * Pill button: hairline border, fully rounded, inverts on hover. $link is the\\n * URL control's value verbatim \\u2014 pass 'arts_lightbox' => 'yes' in it and the\\n * plugin's render filter stamps data-arts-lightbox on the anchor, exactly as\\n * ticking \\\"Open in lightbox\\\" in the panel would.\\n *\\\/\\nfunction ail_pill( string $text, array $link, array $extra = array() ): array {\\n\\treturn array(\\n\\t\\t'id'         => ail_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'                               => $link,\\n\\t\\t\\t\\t'button_text_color'                  => AIL_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'                       => AIL_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'      => '10',\\n\\t\\t\\t\\t\\t'right'    => '22',\\n\\t\\t\\t\\t\\t'bottom'   => '10',\\n\\t\\t\\t\\t\\t'left'     => '22',\\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'      => AIL_TEXT,\\n\\t\\t\\t\\t'button_hover_border_color'          => AIL_TEXT,\\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 ail_row( array $settings, array $children ): array {\\n\\treturn array(\\n\\t\\t'id'       => ail_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'      => ail_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 ail_section( string $anchor, array $children, array $extra = array() ): array {\\n\\treturn ail_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'       => ail_gap( 12 ),\\n\\t\\t\\t\\t'padding'        => array(\\n\\t\\t\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t\\t\\t'top'      => '96',\\n\\t\\t\\t\\t\\t'right'    => '0',\\n\\t\\t\\t\\t\\t'bottom'   => '96',\\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 * Basic Gallery widget \\u2014 the stock Elementor gallery, linking to the media\\n * files with the lightbox on. Elementor groups its items into one slideshow\\n * and stamps title\\\/description on every link; the plugin reads both.\\n *\\\/\\nfunction ail_gallery( array $ids ): array {\\n\\t$items = array();\\n\\tforeach ( $ids as $id ) {\\n\\t\\t$items[] = array(\\n\\t\\t\\t'id'  => $id,\\n\\t\\t\\t'url' => wp_get_attachment_url( $id ),\\n\\t\\t);\\n\\t}\\n\\n\\treturn array(\\n\\t\\t'id'         => ail_seed_id(),\\n\\t\\t'elType'     => 'widget',\\n\\t\\t'widgetType' => 'image-gallery',\\n\\t\\t'settings'   => array(\\n\\t\\t\\t'wp_gallery'           => $items,\\n\\t\\t\\t'thumbnail_size'       => 'medium',\\n\\t\\t\\t'gallery_columns'      => '3',\\n\\t\\t\\t'gallery_link'         => 'file',\\n\\t\\t\\t'open_lightbox'        => 'yes',\\n\\t\\t\\t'image_spacing'        => 'custom',\\n\\t\\t\\t'image_spacing_custom' => array(\\n\\t\\t\\t\\t'unit'  => 'px',\\n\\t\\t\\t\\t'size'  => 12,\\n\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t),\\n\\t\\t),\\n\\t\\t'elements'   => array(),\\n\\t);\\n}\\n\\n\\\/** Image widget linking to its own media file with the lightbox on. *\\\/\\nfunction ail_image( int $id ): array {\\n\\treturn array(\\n\\t\\t'id'         => ail_seed_id(),\\n\\t\\t'elType'     => 'widget',\\n\\t\\t'widgetType' => 'image',\\n\\t\\t'settings'   => array(\\n\\t\\t\\t'image'         => array(\\n\\t\\t\\t\\t'id'  => $id,\\n\\t\\t\\t\\t'url' => wp_get_attachment_url( $id ),\\n\\t\\t\\t),\\n\\t\\t\\t'image_size'    => 'full',\\n\\t\\t\\t\\\/\\\/ Elementor sizes an SVG inside an image-widget link to 48px\\n\\t\\t\\t\\\/\\\/ (widget-image.css: a img[src$=\\\".svg\\\"]); the width control's\\n\\t\\t\\t\\\/\\\/ wrapper-scoped selector outranks that rule.\\n\\t\\t\\t'width'         => array(\\n\\t\\t\\t\\t'unit'  => '%',\\n\\t\\t\\t\\t'size'  => 100,\\n\\t\\t\\t\\t'sizes' => array(),\\n\\t\\t\\t),\\n\\t\\t\\t'link_to'       => 'file',\\n\\t\\t\\t'open_lightbox' => 'yes',\\n\\t\\t),\\n\\t\\t'elements'   => array(),\\n\\t);\\n}\\n\\n\\\/\\\/ --- Slide attachments ----------------------------------------------------------\\n\\n$ail_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$ail_fail( $upload['error'] );\\n}\\n\\n\\\/**\\n * Writes an SVG 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. The\\n * `sizes.full` entry is load-bearing: wp_attachment_is_image() is false for\\n * .svg, and image_downsize() serves a non-image only through that entry \\u2014\\n * without it [gallery] and wp_get_attachment_image() print nothing.\\n *\\n * Title and description become the lightbox caption lines: Elementor resolves\\n * its lightbox_title_src \\\/ lightbox_description_src kit settings (defaults:\\n * title, description) into data attributes on the link, and the plugin reads\\n * those.\\n *\\\/\\n$ail_attach = static function (\\n\\tstring $key,\\n\\tstring $filename,\\n\\tstring $bytes,\\n\\tstring $title,\\n\\tstring $description,\\n\\tint $width,\\n\\tint $height\\n) use (\\n\\t$upload,\\n\\t$ail_fail\\n): 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_il_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$ail_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_content'   => $description,\\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'   => $description,\\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$ail_fail( $id->get_error_message() );\\n\\t\\t}\\n\\n\\t\\tupdate_post_meta( $id, '_arts_il_asset', $key );\\n\\t}\\n\\n\\twp_update_attachment_metadata(\\n\\t\\t$id,\\n\\t\\tarray(\\n\\t\\t\\t'width'  => $width,\\n\\t\\t\\t'height' => $height,\\n\\t\\t\\t'file'   => $relative,\\n\\t\\t\\t'sizes'  => array(\\n\\t\\t\\t\\t'full' => array(\\n\\t\\t\\t\\t\\t'file'      => $filename,\\n\\t\\t\\t\\t\\t'width'     => $width,\\n\\t\\t\\t\\t\\t'height'    => $height,\\n\\t\\t\\t\\t\\t'mime-type' => 'image\\\/svg+xml',\\n\\t\\t\\t\\t),\\n\\t\\t\\t),\\n\\t\\t)\\n\\t);\\n\\n\\treturn (int) $id;\\n};\\n\\n\\n\\\/\\\/ Swiss poster set: paper #efece5, ink #141414, vermilion #e3311a. Type is\\n\\\/\\\/ Helvetica\\\/Arial \\u2014 an <img>-embedded SVG can only reach installed fonts.\\n\\n$ail_svg_bars = <<<'SVG'\\n<svg xmlns=\\\"http:\\\/\\\/www.w3.org\\\/2000\\\/svg\\\" width=\\\"2400\\\" height=\\\"1600\\\" viewBox=\\\"0 0 2400 1600\\\">\\n<rect width=\\\"2400\\\" height=\\\"1600\\\" fill=\\\"#efece5\\\"\\\/>\\n<path d=\\\"M300 0V1600M1200 0V1600M2100 0V1600M0 400H2400M0 1200H2400\\\" fill=\\\"none\\\" stroke=\\\"#141414\\\" stroke-opacity=\\\"0.2\\\" stroke-width=\\\"2\\\"\\\/>\\n<rect x=\\\"300\\\" y=\\\"400\\\" width=\\\"1500\\\" height=\\\"120\\\" fill=\\\"#141414\\\"\\\/>\\n<rect x=\\\"300\\\" y=\\\"600\\\" width=\\\"900\\\" height=\\\"120\\\" fill=\\\"#141414\\\"\\\/>\\n<rect x=\\\"300\\\" y=\\\"800\\\" width=\\\"1800\\\" height=\\\"120\\\" fill=\\\"#141414\\\"\\\/>\\n<rect x=\\\"1800\\\" y=\\\"1200\\\" width=\\\"300\\\" height=\\\"300\\\" fill=\\\"#e3311a\\\"\\\/>\\n<text x=\\\"300\\\" y=\\\"1450\\\" font-family=\\\"Helvetica Neue, Helvetica, Arial, sans-serif\\\" font-size=\\\"44\\\" font-weight=\\\"700\\\" fill=\\\"#141414\\\">01 \\u2014 BARS<\\\/text>\\n<\\\/svg>\\nSVG;\\n\\n$ail_svg_diagonal = <<<'SVG'\\n<svg xmlns=\\\"http:\\\/\\\/www.w3.org\\\/2000\\\/svg\\\" width=\\\"2400\\\" height=\\\"1600\\\" viewBox=\\\"0 0 2400 1600\\\">\\n<rect width=\\\"2400\\\" height=\\\"1600\\\" fill=\\\"#efece5\\\"\\\/>\\n<polygon points=\\\"0,1600 0,1180 2400,0 2400,420\\\" fill=\\\"#141414\\\"\\\/>\\n<circle cx=\\\"1620\\\" cy=\\\"1100\\\" r=\\\"300\\\" fill=\\\"#e3311a\\\"\\\/>\\n<path d=\\\"M0 1390L2400 210\\\" stroke=\\\"#efece5\\\" stroke-width=\\\"3\\\"\\\/>\\n<text x=\\\"120\\\" y=\\\"200\\\" font-family=\\\"Helvetica Neue, Helvetica, Arial, sans-serif\\\" font-size=\\\"44\\\" font-weight=\\\"700\\\" fill=\\\"#141414\\\">02 \\u2014 DIAGONAL<\\\/text>\\n<\\\/svg>\\nSVG;\\n\\n$ail_svg_seven = <<<'SVG'\\n<svg xmlns=\\\"http:\\\/\\\/www.w3.org\\\/2000\\\/svg\\\" width=\\\"2400\\\" height=\\\"1600\\\" viewBox=\\\"0 0 2400 1600\\\">\\n<rect width=\\\"2400\\\" height=\\\"1600\\\" fill=\\\"#efece5\\\"\\\/>\\n<text x=\\\"-40\\\" y=\\\"1560\\\" font-family=\\\"Helvetica Neue, Helvetica, Arial, sans-serif\\\" font-size=\\\"2300\\\" font-weight=\\\"700\\\" fill=\\\"#141414\\\" letter-spacing=\\\"-0.06em\\\">7<\\\/text>\\n<rect x=\\\"1700\\\" width=\\\"60\\\" height=\\\"1600\\\" fill=\\\"#e3311a\\\"\\\/>\\n<text x=\\\"1820\\\" y=\\\"1520\\\" font-family=\\\"Helvetica Neue, Helvetica, Arial, sans-serif\\\" font-size=\\\"44\\\" font-weight=\\\"700\\\" fill=\\\"#141414\\\">03 \\u2014 SEVEN<\\\/text>\\n<\\\/svg>\\nSVG;\\n\\n$ail_svg_arcs = <<<'SVG'\\n<svg xmlns=\\\"http:\\\/\\\/www.w3.org\\\/2000\\\/svg\\\" width=\\\"2400\\\" height=\\\"1600\\\" viewBox=\\\"0 0 2400 1600\\\">\\n<rect width=\\\"2400\\\" height=\\\"1600\\\" fill=\\\"#efece5\\\"\\\/>\\n<g fill=\\\"none\\\" stroke=\\\"#141414\\\">\\n<circle cx=\\\"2500\\\" cy=\\\"1750\\\" r=\\\"480\\\" stroke-width=\\\"36\\\"\\\/>\\n<circle cx=\\\"2500\\\" cy=\\\"1750\\\" r=\\\"640\\\" stroke-width=\\\"52\\\"\\\/>\\n<circle cx=\\\"2500\\\" cy=\\\"1750\\\" r=\\\"840\\\" stroke-width=\\\"76\\\"\\\/>\\n<circle cx=\\\"2500\\\" cy=\\\"1750\\\" r=\\\"1090\\\" stroke-width=\\\"110\\\" stroke=\\\"#e3311a\\\"\\\/>\\n<circle cx=\\\"2500\\\" cy=\\\"1750\\\" r=\\\"1400\\\" stroke-width=\\\"160\\\"\\\/>\\n<circle cx=\\\"2500\\\" cy=\\\"1750\\\" r=\\\"1790\\\" stroke-width=\\\"230\\\"\\\/>\\n<circle cx=\\\"2500\\\" cy=\\\"1750\\\" r=\\\"2270\\\" stroke-width=\\\"330\\\"\\\/>\\n<\\\/g>\\n<text x=\\\"120\\\" y=\\\"200\\\" font-family=\\\"Helvetica Neue, Helvetica, Arial, sans-serif\\\" font-size=\\\"44\\\" font-weight=\\\"700\\\" fill=\\\"#141414\\\">04 \\u2014 ARCS<\\\/text>\\n<\\\/svg>\\nSVG;\\n\\n$ail_svg_rhythm = <<<'SVG'\\n<svg xmlns=\\\"http:\\\/\\\/www.w3.org\\\/2000\\\/svg\\\" width=\\\"2400\\\" height=\\\"1600\\\" viewBox=\\\"0 0 2400 1600\\\">\\n<rect width=\\\"2400\\\" height=\\\"1600\\\" fill=\\\"#efece5\\\"\\\/>\\n<g fill=\\\"#141414\\\">\\n<rect x=\\\"80\\\" y=\\\"1180\\\" width=\\\"80\\\" height=\\\"300\\\"\\\/><rect x=\\\"220\\\" y=\\\"780\\\" width=\\\"80\\\" height=\\\"700\\\"\\\/><rect x=\\\"360\\\" y=\\\"980\\\" width=\\\"80\\\" height=\\\"500\\\"\\\/>\\n<rect x=\\\"500\\\" y=\\\"380\\\" width=\\\"80\\\" height=\\\"1100\\\"\\\/><rect x=\\\"640\\\" y=\\\"580\\\" width=\\\"80\\\" height=\\\"900\\\"\\\/><rect x=\\\"780\\\" y=\\\"1080\\\" width=\\\"80\\\" height=\\\"400\\\"\\\/>\\n<rect x=\\\"920\\\" y=\\\"180\\\" width=\\\"80\\\" height=\\\"1300\\\" fill=\\\"#e3311a\\\"\\\/><rect x=\\\"1060\\\" y=\\\"880\\\" width=\\\"80\\\" height=\\\"600\\\"\\\/><rect x=\\\"1200\\\" y=\\\"480\\\" width=\\\"80\\\" height=\\\"1000\\\"\\\/>\\n<rect x=\\\"1340\\\" y=\\\"1130\\\" width=\\\"80\\\" height=\\\"350\\\"\\\/><rect x=\\\"1480\\\" y=\\\"680\\\" width=\\\"80\\\" height=\\\"800\\\"\\\/><rect x=\\\"1620\\\" y=\\\"280\\\" width=\\\"80\\\" height=\\\"1200\\\"\\\/>\\n<rect x=\\\"1760\\\" y=\\\"1030\\\" width=\\\"80\\\" height=\\\"450\\\"\\\/><rect x=\\\"1900\\\" y=\\\"530\\\" width=\\\"80\\\" height=\\\"950\\\"\\\/><rect x=\\\"2040\\\" y=\\\"830\\\" width=\\\"80\\\" height=\\\"650\\\"\\\/><rect x=\\\"2180\\\" y=\\\"80\\\" width=\\\"80\\\" height=\\\"1400\\\"\\\/>\\n<\\\/g>\\n<path d=\\\"M80 1480H2260\\\" stroke=\\\"#141414\\\" stroke-width=\\\"6\\\"\\\/>\\n<text x=\\\"80\\\" y=\\\"1560\\\" font-family=\\\"Helvetica Neue, Helvetica, Arial, sans-serif\\\" font-size=\\\"44\\\" font-weight=\\\"700\\\" fill=\\\"#141414\\\">05 \\u2014 RHYTHM<\\\/text>\\n<\\\/svg>\\nSVG;\\n\\n$ail_svg_discs = <<<'SVG'\\n<svg xmlns=\\\"http:\\\/\\\/www.w3.org\\\/2000\\\/svg\\\" width=\\\"2400\\\" height=\\\"1600\\\" viewBox=\\\"0 0 2400 1600\\\">\\n<rect width=\\\"2400\\\" height=\\\"1600\\\" fill=\\\"#efece5\\\"\\\/>\\n<path d=\\\"M0 1600L2400 0\\\" stroke=\\\"#141414\\\" stroke-opacity=\\\"0.35\\\" stroke-width=\\\"3\\\"\\\/>\\n<circle cx=\\\"900\\\" cy=\\\"800\\\" r=\\\"620\\\" fill=\\\"#141414\\\"\\\/>\\n<circle cx=\\\"1900\\\" cy=\\\"1150\\\" r=\\\"330\\\" fill=\\\"none\\\" stroke=\\\"#141414\\\" stroke-width=\\\"16\\\"\\\/>\\n<circle cx=\\\"1560\\\" cy=\\\"560\\\" r=\\\"260\\\" fill=\\\"#e3311a\\\"\\\/>\\n<text x=\\\"120\\\" y=\\\"1520\\\" font-family=\\\"Helvetica Neue, Helvetica, Arial, sans-serif\\\" font-size=\\\"44\\\" font-weight=\\\"700\\\" fill=\\\"#141414\\\">06 \\u2014 DISCS<\\\/text>\\n<\\\/svg>\\nSVG;\\n\\n\\\/\\\/ The explore piece: a programme sheet. A masthead, a cropped numeral, and\\n\\\/\\\/ forty rows of small tabular type \\u2014 the kind of detail that only reads once\\n\\\/\\\/ the sheet fills the screen and glides under the mouse. Rows come from a\\n\\\/\\\/ fixed-seed LCG so every run prints the same sheet.\\n$ail_rows = '';\\n$ail_seed = 20260831;\\n$ail_next = static function () use ( &$ail_seed ): int {\\n\\t$ail_seed = ( $ail_seed * 1103515245 + 12345 ) % 2147483648;\\n\\treturn $ail_seed;\\n};\\nfor ( $i = 0; $i < 40; $i++ ) {\\n\\t$y         = 760 + $i * 64;\\n\\t$time      = sprintf( '%02d.%02d', 8 + intdiv( $i, 3 ), ( $i % 3 ) * 20 );\\n\\t$ref       = sprintf( 'A-%04d', 1200 + $ail_next() % 800 );\\n\\t$key       = sprintf( '%d.%d', $ail_next() % 90 + 10, $ail_next() % 10 );\\n\\t$val       = sprintf( '%d', 100 + $ail_next() % 900 );\\n\\t$delta     = sprintf( '%s%d.%02d', ( $ail_next() % 2 ) ? '+' : '-', $ail_next() % 9, $ail_next() % 100 );\\n\\t$ail_rows .= sprintf(\\n\\t\\t'<text y=\\\"%d\\\"><tspan x=\\\"120\\\">%02d<\\\/tspan><tspan x=\\\"360\\\">%s<\\\/tspan><tspan x=\\\"760\\\">%s<\\\/tspan><tspan x=\\\"1200\\\">%s<\\\/tspan><tspan x=\\\"1640\\\">%s<\\\/tspan><tspan x=\\\"2080\\\">%s<\\\/tspan><\\\/text>' . \\\"\\\\n\\\",\\n\\t\\t$y,\\n\\t\\t$i + 1,\\n\\t\\t$time,\\n\\t\\t$ref,\\n\\t\\t$key,\\n\\t\\t$val,\\n\\t\\t$delta\\n\\t);\\n\\t$ail_rows .= sprintf(\\n\\t\\t'<path d=\\\"M120 %dH2280\\\" stroke=\\\"#141414\\\" stroke-opacity=\\\"%s\\\" stroke-width=\\\"%s\\\"\\\/>' . \\\"\\\\n\\\",\\n\\t\\t$y + 20,\\n\\t\\t( 9 === $i % 10 ) ? '0.8' : '0.2',\\n\\t\\t( 9 === $i % 10 ) ? '3' : '1.5'\\n\\t);\\n}\\n\\n$ail_svg_sheet  = <<<'SVG'\\n<svg xmlns=\\\"http:\\\/\\\/www.w3.org\\\/2000\\\/svg\\\" width=\\\"2400\\\" height=\\\"3600\\\" viewBox=\\\"0 0 2400 3600\\\">\\n<rect width=\\\"2400\\\" height=\\\"3600\\\" fill=\\\"#efece5\\\"\\\/>\\n<rect x=\\\"120\\\" y=\\\"120\\\" width=\\\"2160\\\" height=\\\"360\\\" fill=\\\"#e3311a\\\"\\\/>\\n<g font-family=\\\"Helvetica Neue, Helvetica, Arial, sans-serif\\\" font-weight=\\\"700\\\" fill=\\\"#efece5\\\">\\n<text x=\\\"160\\\" y=\\\"400\\\" font-size=\\\"230\\\" letter-spacing=\\\"-0.04em\\\">PROGRAMME<\\\/text>\\n<text x=\\\"2240\\\" y=\\\"200\\\" font-size=\\\"36\\\" text-anchor=\\\"end\\\">SHEET 04<\\\/text>\\n<text x=\\\"2240\\\" y=\\\"250\\\" font-size=\\\"36\\\" text-anchor=\\\"end\\\">40 ROWS<\\\/text>\\n<\\\/g>\\n<g font-family=\\\"Helvetica Neue, Helvetica, Arial, sans-serif\\\" font-size=\\\"30\\\" font-weight=\\\"700\\\" fill=\\\"#141414\\\">\\n<text y=\\\"690\\\"><tspan x=\\\"120\\\">NR<\\\/tspan><tspan x=\\\"360\\\">TIME<\\\/tspan><tspan x=\\\"760\\\">REF<\\\/tspan><tspan x=\\\"1200\\\">KEY<\\\/tspan><tspan x=\\\"1640\\\">VALUE<\\\/tspan><tspan x=\\\"2080\\\">DELTA<\\\/tspan><\\\/text>\\n<\\\/g>\\n<path d=\\\"M120 712H2280\\\" stroke=\\\"#141414\\\" stroke-width=\\\"4\\\"\\\/>\\n<g font-family=\\\"Helvetica Neue, Helvetica, Arial, sans-serif\\\" font-size=\\\"30\\\" fill=\\\"#141414\\\">\\nSVG;\\n$ail_svg_sheet .= $ail_rows;\\n$ail_svg_sheet .= <<<'SVG'\\n<\\\/g>\\n<text x=\\\"2320\\\" y=\\\"3560\\\" font-family=\\\"Helvetica Neue, Helvetica, Arial, sans-serif\\\" font-size=\\\"900\\\" font-weight=\\\"700\\\" fill=\\\"#141414\\\" letter-spacing=\\\"-0.06em\\\" text-anchor=\\\"end\\\" fill-opacity=\\\"0.92\\\">04<\\\/text>\\n<path d=\\\"M120 3400H1300\\\" stroke=\\\"#141414\\\" stroke-width=\\\"4\\\"\\\/>\\n<text x=\\\"120\\\" y=\\\"3470\\\" font-family=\\\"Helvetica Neue, Helvetica, Arial, sans-serif\\\" font-size=\\\"36\\\" font-weight=\\\"700\\\" fill=\\\"#141414\\\">ARTS IMMERSIVE LIGHTBOX \\u2014 LIVE PREVIEW<\\\/text>\\n<\\\/svg>\\nSVG;\\n\\n$slide_ids = array(\\n\\t$ail_attach( 'slide-bars', 'ail-bars.svg', $ail_svg_bars, 'Bars', 'Three weights on one grid.', 2400, 1600 ),\\n\\t$ail_attach( 'slide-diagonal', 'ail-diagonal.svg', $ail_svg_diagonal, 'Diagonal', 'One band, one disc.', 2400, 1600 ),\\n\\t$ail_attach( 'slide-seven', 'ail-seven.svg', $ail_svg_seven, 'Seven', 'A numeral cropped by the frame.', 2400, 1600 ),\\n\\t$ail_attach( 'slide-arcs', 'ail-arcs.svg', $ail_svg_arcs, 'Arcs', 'Rings that grow as they leave.', 2400, 1600 ),\\n\\t$ail_attach( 'slide-rhythm', 'ail-rhythm.svg', $ail_svg_rhythm, 'Rhythm', 'Sixteen bars, one in red.', 2400, 1600 ),\\n\\t$ail_attach( 'slide-discs', 'ail-discs.svg', $ail_svg_discs, 'Discs', 'Two discs and a ring.', 2400, 1600 ),\\n);\\n\\n$survey_id = $ail_attach( 'sheet', 'ail-sheet.svg', $ail_svg_sheet, 'Programme 04', 'Forty rows of small type. Move the mouse to read them.', 2400, 3600 );\\n\\nupdate_option( 'blogname', 'Immersive Lightbox' );\\n\\\/\\\/ Blank, or \\\"Just another WordPress site\\\" renders as a tagline line.\\nupdate_option( 'blogdescription', '' );\\n\\n\\\/\\\/ --- Kit: thumbnails on ------------------------------------------------------------\\n\\\/\\\/ The one behavior default the demo changes. Behavior settings are read\\n\\\/\\\/ server-side by Options::build() on every front-end load, so the meta write\\n\\\/\\\/ is all it takes \\u2014 no kit CSS to regenerate.\\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\\n\\t$kit_settings['arts_lightbox_thumbnails'] = 'yes';\\n\\n\\tupdate_post_meta( $kit_id, '_elementor_page_settings', wp_slash( $kit_settings ) );\\n}\\n\\n\\\/\\\/ --- Page content ---------------------------------------------------------------\\n\\n$hero = ail_row(\\n\\tarray(\\n\\t\\t'_element_id'    => 'top',\\n\\t\\t'flex_direction' => 'column',\\n\\t\\t'flex_gap'       => ail_gap( 18 ),\\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'   => '48',\\n\\t\\t\\t'left'     => '0',\\n\\t\\t\\t'isLinked' => false,\\n\\t\\t),\\n\\t),\\n\\tarray(\\n\\t\\t\\\/\\\/ Anchor smoothness, baked into page content because the seed runs once\\n\\t\\t\\\/\\\/ at provisioning \\u2014 a wp_head hook registered here would not survive\\n\\t\\t\\\/\\\/ past that request.\\n\\t\\tarray(\\n\\t\\t\\t'id'         => ail_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}<\\\/style>',\\n\\t\\t\\t),\\n\\t\\t\\t'elements'   => array(),\\n\\t\\t),\\n\\t\\tail_heading(\\n\\t\\t\\t'The image you click is the one that opens.',\\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\\tail_body(\\n\\t\\t\\t'It lifts off the page, and when you close it, it settles back exactly where it came from \\u2014 however far you have scrolled. Click any image below.',\\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(46ch, 100%)',\\n\\t\\t\\t\\t),\\n\\t\\t\\t)\\n\\t\\t),\\n\\t)\\n);\\n\\n$gallery_section = ail_section(\\n\\t'gallery',\\n\\tarray(\\n\\t\\tail_heading( 'Six slides, one gallery', 'h2', '22px' ),\\n\\t\\tail_body( 'A stock Elementor Basic Gallery. Pull a slide across with the mouse \\u2014 it moves with the same physics as a swipe on a phone. The rail along the bottom jumps straight to any slide, and the scroll wheel steps through them.' ),\\n\\t\\tail_gallery( $slide_ids ),\\n\\t\\tail_hint( 'Esc, or a click on the backdrop, sends the image home.' ),\\n\\t),\\n\\tarray(\\n\\t\\t'padding' => array(\\n\\t\\t\\t'unit'     => 'px',\\n\\t\\t\\t'top'      => '48',\\n\\t\\t\\t'right'    => '0',\\n\\t\\t\\t'bottom'   => '96',\\n\\t\\t\\t'left'     => '0',\\n\\t\\t\\t'isLinked' => false,\\n\\t\\t),\\n\\t)\\n);\\n\\n$explore_section = ail_section(\\n\\t'explore',\\n\\tarray(\\n\\t\\tail_heading( 'Explore pan', 'h2', '22px' ),\\n\\t\\tail_body( 'Made for photographers. Open the sheet and just move the mouse: it fills the screen and glides under the cursor, the way you would lean closer to a print, and every line of small type stays sharp. Click to see the whole frame; click again to fill it.' ),\\n\\t\\tail_image( $survey_id ),\\n\\t)\\n);\\n\\n$link_section = ail_section(\\n\\t'link',\\n\\tarray(\\n\\t\\tail_heading( 'Any link opens it', 'h2', '22px' ),\\n\\t\\tail_body( 'Every URL field in Elementor gains an \\u201cOpen in lightbox\\u201d checkbox \\u2014 buttons, icons, text links, widgets from any addon. Paste a YouTube or Vimeo link and it plays as a video slide. This is a stock Elementor button with the box ticked:' ),\\n\\t\\tail_pill(\\n\\t\\t\\t'Play the film',\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'url'           => 'https:\\\/\\\/www.youtube.com\\\/watch?v=aqz-KE-bpKQ',\\n\\t\\t\\t\\t'is_external'   => '',\\n\\t\\t\\t\\t'nofollow'      => '',\\n\\t\\t\\t\\t'arts_lightbox' => 'yes',\\n\\t\\t\\t),\\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'      => '8',\\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$outro_section = ail_section(\\n\\t'outro',\\n\\tarray(\\n\\t\\tail_heading( 'Make it yours', 'h2', '22px' ),\\n\\t\\tail_body( 'Colors, typography and the counter live in Site Settings \\u2192 Lightbox and preview live in the editor; transitions, zoom, explore pan and the thumbnail rail sit right beside them. The preview logs you in \\u2014 open the page in Elementor and look around.' ),\\n\\t\\tail_pill(\\n\\t\\t\\t'Open in Elementor',\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'url'         => admin_url( 'post.php?post=' . AIL_DEMO_PAGE_ID . '&action=elementor' ),\\n\\t\\t\\t\\t'is_external' => '',\\n\\t\\t\\t\\t'nofollow'    => '',\\n\\t\\t\\t),\\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'      => '8',\\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'      => '96',\\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'       => ail_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'      => ail_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, $gallery_section, $explore_section, $link_section, $outro_section ),\\n);\\n\\n\\\/\\\/ --- Persist --------------------------------------------------------------------\\n\\n$slug     = 'ail-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'   => AIL_DEMO_PAGE_ID,\\n\\t\\t'post_type'   => 'page',\\n\\t\\t'post_status' => 'publish',\\n\\t\\t'post_title'  => 'Arts Immersive Lightbox \\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( $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\\\/immersive-lightbox-for-elementor-demo-seed.php';\"},{\"step\":\"installPlugin\",\"pluginData\":{\"resource\":\"wordpress.org\\\/plugins\",\"slug\":\"immersive-lightbox-for-elementor\"},\"options\":{\"activate\":true}}]}"}},"all_blocks":[],"tagged_versions":["1.0.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3673742,"resolution":"1","location":"assets","locale":"","width":1520,"height":1520},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3673742,"resolution":"2","location":"assets","locale":"","width":1520,"height":1520},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3673742,"resolution":"3","location":"assets","locale":"","width":1520,"height":1520},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3673742,"resolution":"4","location":"assets","locale":"","width":1520,"height":1520},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3673742,"resolution":"5","location":"assets","locale":"","width":1520,"height":1520},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3673742,"resolution":"6","location":"assets","locale":"","width":1520,"height":1520}},"screenshots":{"1":"The lightbox open on a gallery: thumbnail rail, slide counter and arrows, with video slides sitting in the same strip as the images.","2":"Site Settings \u2192 Lightbox in the Elementor editor \u2014 every setting for this plugin lives inside Elementor's own panel.","3":"Lightbox Transitions: a Curtain or Fade opening style, the curtain's edge shape, and how long the transition runs.","4":"Lightbox Interface: the thumbnail rail and its position, captions, counter typography, backdrop opacity and slide corner radius.","5":"Lightbox Behavior: gallery looping, uniting galleries on a page, zoom mode, mouse-wheel zoom, explore pan and video autoplay.","6":"Every Elementor URL field gains an \"Open in lightbox\" checkbox \u2014 buttons, icons and text links, including YouTube and Vimeo URLs."}},"plugin_section":[],"plugin_tags":[76538,210,237,13896,21858],"plugin_category":[50],"plugin_contributors":[241532],"plugin_business_model":[],"class_list":["post-361337","plugin","type-plugin","status-publish","hentry","plugin_tags-elementor","plugin_tags-gallery","plugin_tags-lightbox","plugin_tags-photoswipe","plugin_tags-video-lightbox","plugin_category-media","plugin_contributors-artemsemkin","plugin_committers-artemsemkin"],"banners":{"banner":"https:\/\/ps.w.org\/immersive-lightbox-for-elementor\/assets\/banner-772x250.jpg?rev=3673742","banner_2x":"https:\/\/ps.w.org\/immersive-lightbox-for-elementor\/assets\/banner-1544x500.jpg?rev=3673742","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":"https:\/\/ps.w.org\/immersive-lightbox-for-elementor\/assets\/icon.svg?rev=3673742","icon":"https:\/\/ps.w.org\/immersive-lightbox-for-elementor\/assets\/icon.svg?rev=3673742","icon_2x":false,"generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/immersive-lightbox-for-elementor\/assets\/screenshot-1.png?rev=3673742","caption":"The lightbox open on a gallery: thumbnail rail, slide counter and arrows, with video slides sitting in the same strip as the images."},{"src":"https:\/\/ps.w.org\/immersive-lightbox-for-elementor\/assets\/screenshot-2.png?rev=3673742","caption":"Site Settings \u2192 Lightbox in the Elementor editor \u2014 every setting for this plugin lives inside Elementor's own panel."},{"src":"https:\/\/ps.w.org\/immersive-lightbox-for-elementor\/assets\/screenshot-3.png?rev=3673742","caption":"Lightbox Transitions: a Curtain or Fade opening style, the curtain's edge shape, and how long the transition runs."},{"src":"https:\/\/ps.w.org\/immersive-lightbox-for-elementor\/assets\/screenshot-4.png?rev=3673742","caption":"Lightbox Interface: the thumbnail rail and its position, captions, counter typography, backdrop opacity and slide corner radius."},{"src":"https:\/\/ps.w.org\/immersive-lightbox-for-elementor\/assets\/screenshot-5.png?rev=3673742","caption":"Lightbox Behavior: gallery looping, uniting galleries on a page, zoom mode, mouse-wheel zoom, explore pan and video autoplay."},{"src":"https:\/\/ps.w.org\/immersive-lightbox-for-elementor\/assets\/screenshot-6.png?rev=3673742","caption":"Every Elementor URL field gains an \"Open in lightbox\" checkbox \u2014 buttons, icons and text links, including YouTube and Vimeo URLs."}],"raw_content":"<!--section=description-->\n<p>Your Elementor images, galleries and videos already open in a lightbox. This plugin makes that moment the best part of the page. Activate it and the native lightbox is replaced with an immersive, PhotoSwipe-powered one: the kind of cinematic, premium feel that usually stays locked inside high-end portfolio themes, now on any Elementor site with zero setup.<\/p>\n\n<h4>What you get<\/h4>\n\n<ul>\n<li><strong>Cinematic open and close<\/strong> \u2014 the image you click travels into the lightbox and settles back exactly where it came from, however far the visitor has scrolled. The kind of detail people notice before they can say why.<\/li>\n<li><strong>Explore pan<\/strong> \u2014 zoom into a high-resolution photo and it glides with the mouse: visitors wander across every detail just by moving the cursor, the way they'd lean closer to a print. A gift for photographers. Your work gets studied, not skimmed.<\/li>\n<li><strong>Any link opens the lightbox<\/strong> \u2014 every Elementor URL field gains an \"Open in lightbox\" checkbox: buttons, icons, text links, widgets from any addon. Paste a YouTube or Vimeo link and it opens as video.<\/li>\n<li><strong>Drag navigation on desktop<\/strong> \u2014 pull slides across with the mouse, with the same physics as a touch swipe.<\/li>\n<li><strong>Thumbnail navigation<\/strong> \u2014 a rail of thumbnails for jumping straight to any slide.<\/li>\n<li><strong>Video slides<\/strong> \u2014 YouTube, Vimeo and self-hosted video files, detected straight from the link. No setup.<\/li>\n<li><strong>Grouped galleries<\/strong> \u2014 images from different widgets and sections can join one gallery.<\/li>\n<li><strong>Captions and counter<\/strong> \u2014 the caption reads the same title and description fields as the native lightbox, so nothing needs re-entering.<\/li>\n<li><strong>Styled in Site Settings<\/strong> \u2014 Elementor's existing Lightbox settings (colors, typography, counter) drive this lightbox, editable live in the editor.<\/li>\n<li><strong>Touch gestures and keyboard<\/strong> \u2014 swipe, pinch zoom, arrow keys, Esc, looping galleries.<\/li>\n<\/ul>\n\n<h4>Light by design<\/h4>\n\n<ul>\n<li>The engine loads only when a visitor opens the lightbox; until that first click the page carries just a tiny loader script.<\/li>\n<li>Zero dependencies \u2014 the engine bundles its own tuned PhotoSwipe fork and needs nothing else, not even jQuery.<\/li>\n<li>Everything ships in the free plugin. There is no Pro tier, your dashboard stays free of ads and nag screens, and nothing ever calls an external server.<\/li>\n<\/ul>\n\n<h4>Works with<\/h4>\n\n<ul>\n<li>Elementor Free \u2014 Image, Basic Gallery, Image Carousel and every widget that opens the native lightbox. Elementor Pro widgets, including the Media Carousel's video slides, work too.<\/li>\n<li>Any theme.<\/li>\n<li>Arts Cursor Follower for Elementor \u2014 adds a hover hint (magnifier, plus, or a text pill) over lightbox links.<\/li>\n<\/ul>\n\n<h4>For developers<\/h4>\n\n<p>The plugin fires CustomEvents (<code>arts-lightbox:open<\/code>, <code>arts-lightbox:change<\/code>, <code>arts-lightbox:destroy<\/code>), exposes CSS custom properties for sizing and theming, and understands a small <code>data-arts-lightbox-*<\/code> attribute vocabulary for captions, groups, HTML slides and opt-outs. The TypeScript source and the full contract live on GitHub: https:\/\/github.com\/artkrsk\/immersive-lightbox-for-elementor<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Install and activate the plugin. Elementor must be active.<\/li>\n<li>There is no step 2 \u2014 links Elementor would open in its lightbox now open in this one, following the same rules (including the Image Lightbox switch in Site Settings).<\/li>\n<li>To restyle it, open Site Settings \u2192 Lightbox in the Elementor editor.<\/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. The free Elementor plugin is enough. If you have Pro, its gallery and carousel widgets work as well.<\/p><\/dd>\n<dt id=\"do%20i%20need%20to%20configure%20anything%3F\"><h3>Do I need to configure anything?<\/h3><\/dt>\n<dd><p>No. The plugin follows Elementor's own lightbox rules: whatever would open in the native lightbox opens here instead. Widgets with \"Lightbox: No\" stay excluded, and the kit's Image Lightbox switch still governs plain image links.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20youtube%20and%20vimeo%3F\"><h3>Does it work with YouTube and Vimeo?<\/h3><\/dt>\n<dd><p>Yes. YouTube and Vimeo URLs and video files open as video slides automatically \u2014 the plugin detects them from the link itself.<\/p><\/dd>\n<dt id=\"can%20a%20button%20or%20an%20icon%20open%20the%20lightbox%3F\"><h3>Can a button or an icon open the lightbox?<\/h3><\/dt>\n<dd><p>Yes \u2014 any element with a link. Every Elementor URL control has an \"Open in lightbox\" checkbox: tick it and the link opens in the lightbox instead of a new page. That covers image links as well as YouTube, Vimeo and video file URLs.<\/p><\/dd>\n<dt id=\"how%20do%20i%20change%20the%20lightbox%20colors%20and%20fonts%3F\"><h3>How do I change the lightbox colors and fonts?<\/h3><\/dt>\n<dd><p>In the Elementor editor, open Site Settings \u2192 Lightbox. Background, UI and text colors plus caption and counter typography apply to this lightbox, with a live preview.<\/p><\/dd>\n<dt id=\"can%20images%20from%20different%20sections%20join%20one%20gallery%3F\"><h3>Can images from different sections join one gallery?<\/h3><\/dt>\n<dd><p>Yes. Widgets already grouped by Elementor's slideshow setting stay grouped, and a <code>data-arts-lightbox-group<\/code> attribute joins anything else across containers.<\/p><\/dd>\n<dt id=\"will%20it%20slow%20down%20my%20site%3F\"><h3>Will it slow down my site?<\/h3><\/dt>\n<dd><p>No. Nothing heavy loads up front \u2014 the engine and its styles are fetched the first time a visitor opens the lightbox, and the plugin has zero dependencies.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20i%20deactivate%20the%20plugin%3F\"><h3>What happens if I deactivate the plugin?<\/h3><\/dt>\n<dd><p>Elementor's native lightbox returns exactly as it was. The plugin claims clicks in the browser and never rewrites your content.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.0<\/h4>\n\n<p>Initial release.<\/p>","raw_excerpt":"A PhotoSwipe lightbox that replaces Elementor&#039;s native one: cinematic transitions, mousemove explore pan, video galleries, any link as a trigger.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/tzm.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/361337","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tzm.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/tzm.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/tzm.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=361337"}],"author":[{"embeddable":true,"href":"https:\/\/tzm.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/artemsemkin"}],"wp:attachment":[{"href":"https:\/\/tzm.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=361337"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/tzm.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=361337"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/tzm.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=361337"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/tzm.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=361337"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/tzm.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=361337"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/tzm.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=361337"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}