{"id":333502,"date":"2026-06-29T09:53:02","date_gmt":"2026-06-29T09:53:02","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/kinetichub-page-loader\/"},"modified":"2026-09-06T09:36:31","modified_gmt":"2026-09-06T09:36:31","slug":"kinetichub-page-loader","status":"publish","type":"plugin","link":"https:\/\/de.wordpress.org\/plugins\/kinetichub-page-loader\/","author":23473886,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.4.0","stable_tag":"1.4.0","tested":"7.0.5","requires":"5.8","requires_php":"7.4","requires_plugins":null,"header_name":"KineticHub Page Loader","header_author":"KineticHub","header_description":"A lightweight brand preloader and site intro for WordPress. Show a polished loading screen with your logo before your site appears.","assets_banners_color":"010f2b","last_updated":"2026-09-06 09:36:31","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/getkinetichub.com\/","rating":0,"author_block_rating":0,"active_installs":30,"downloads":580,"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":"kinetichub","date":"2026-06-29 10:03:36","revision":3589838},"1.1.0":{"tag":"1.1.0","author":"kinetichub","date":"2026-06-29 18:58:49","revision":3590521},"1.1.1":{"tag":"1.1.1","author":"kinetichub","date":"2026-06-30 23:46:58","revision":3592025},"1.2.0":{"tag":"1.2.0","author":"kinetichub","date":"2026-07-12 21:24:01","revision":3605210},"1.3.0":{"tag":"1.3.0","author":"kinetichub","date":"2026-07-17 20:03:29","revision":3611976},"1.4.0":{"tag":"1.4.0","author":"kinetichub","date":"2026-09-06 09:36:31","revision":3683238}},"upgrade_notice":{"1.4.0":"<p>Adds Smart Anti-Flash, KineticPower motion profiles, new progress styles, exit transitions, page reveal and cover modes, plus a redesigned settings experience. Existing settings are preserved and the loader looks unchanged until you opt in.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3589870,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3589870,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3683302,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3683302,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{"blueprint.json":{"filename":"blueprint.json","revision":3683323,"resolution":false,"location":"assets","locale":"","contents":"{\"$schema\":\"https:\\\/\\\/playground.wordpress.net\\\/blueprint-schema.json\",\"landingPage\":\"\\\/\",\"preferredVersions\":{\"php\":\"8.2\",\"wp\":\"latest\"},\"features\":{\"networking\":false},\"steps\":[{\"step\":\"login\",\"username\":\"admin\",\"password\":\"password\"},{\"step\":\"installPlugin\",\"pluginData\":{\"resource\":\"wordpress.org\\\/plugins\",\"slug\":\"kinetichub-page-loader\"},\"options\":{\"activate\":true}},{\"step\":\"setSiteOptions\",\"options\":{\"blogname\":\"KineticHub Page Loader\",\"blogdescription\":\"Make the first second memorable\"}},{\"step\":\"writeFile\",\"path\":\"\\\/tmp\\\/khpl-demo-logo.png\",\"data\":{\"resource\":\"url\",\"url\":\"https:\\\/\\\/ps.w.org\\\/kinetichub-page-loader\\\/assets\\\/icon-256x256.png\"}},{\"step\":\"writeFile\",\"path\":\"\\\/wordpress\\\/wp-content\\\/mu-plugins\\\/khpl-demo.php\",\"data\":\"<?php\\n\\\/**\\n * Plugin Name: KineticHub Page Loader - Demo Showcase\\n * Description: Renders the Playground showcase page for KineticHub Page Loader. Written by the plugin's blueprint; not part of the distributed plugin.\\n * Version:     1.0.0\\n * Author:      KineticHub\\n *\\n * This file exists only inside the WordPress Playground preview that the\\n * blueprint boots. It is never shipped in the plugin ZIP and never runs on a\\n * real site.\\n *\\n * Scope rules it follows:\\n *   - It only ever touches the one demo page (by slug). Every other request is\\n *     left completely alone.\\n *   - All markup is namespaced .khpld- so it cannot collide with the plugin's\\n *     own .khpl- frontend classes.\\n *   - Feature lists are read from KHPL_Settings::get_choices(), so the demo can\\n *     never advertise a value the plugin does not actually accept.\\n *\\n * @package KineticHub_Page_Loader_Demo\\n *\\\/\\n\\nif ( ! defined( 'ABSPATH' ) ) {\\n\\texit;\\n}\\n\\nconst KHPLD_SLUG = 'khpl-demo';\\n\\n\\\/**\\n * Is this request the demo page?\\n *\\\/\\nfunction khpld_is_demo(): bool {\\n\\treturn is_page( KHPLD_SLUG );\\n}\\n\\n\\\/**\\n * The vocabulary the plugin actually supports, or an empty array if the plugin\\n * is not active. Everything the demo renders is filtered through this.\\n *\\\/\\nfunction khpld_choices(): array {\\n\\t\\\/*\\n\\t * method_exists as well as class_exists.\\n\\t *\\n\\t * The blueprint installs the plugin from wordpress.org, so the demo can land\\n\\t * on a build older than the one it was written against - get_choices() and\\n\\t * the smart-visual settings only exist from the 1.4.0 smart-visuals release\\n\\t * onward. Missing vocabulary has to degrade to \\\"unfiltered\\\", never to a\\n\\t * fatal: calling a method that is not there white-screens the entire Live\\n\\t * Preview, which is exactly what happened before this guard existed.\\n\\t *\\\/\\n\\tif ( ! class_exists( 'KHPL_Settings' ) || ! method_exists( 'KHPL_Settings', 'get_choices' ) ) {\\n\\t\\treturn array();\\n\\t}\\n\\n\\treturn KHPL_Settings::get_choices();\\n}\\n\\n\\\/**\\n * Keeps only the options the plugin really accepts for a given setting.\\n *\\n * The demo is written against the plugin's own list, so if a value is ever\\n * renamed or dropped upstream it silently disappears from the demo instead of\\n * advertising something that no longer exists.\\n *\\n * @param string $key     Settings key, e.g. 'kinetic_mode'.\\n * @param array  $labeled Map of value => array( label, desc ).\\n *\\\/\\nfunction khpld_filter_options( string $key, array $labeled ): array {\\n\\t$choices = khpld_choices();\\n\\tif ( empty( $choices[ $key ] ) ) {\\n\\t\\treturn $labeled;\\n\\t}\\n\\treturn array_intersect_key( $labeled, array_flip( $choices[ $key ] ) );\\n}\\n\\n\\\/**\\n * URL of the logo the blueprint installed, or '' when none resolved.\\n *\\\/\\nfunction khpld_logo_url(): string {\\n\\t$settings = (array) get_option( 'khpl_settings', array() );\\n\\t$id       = isset( $settings['logo_attachment_id'] ) ? (int) $settings['logo_attachment_id'] : 0;\\n\\tif ( ! $id ) {\\n\\t\\treturn '';\\n\\t}\\n\\t$url = wp_get_attachment_image_url( $id, 'medium' );\\n\\treturn $url ? $url : '';\\n}\\n\\n\\\/\\\/ -----------------------------------------------------------------------------\\n\\\/\\\/ Assets\\n\\\/\\\/ -----------------------------------------------------------------------------\\n\\nadd_action(\\n\\t'wp_enqueue_scripts',\\n\\tfunction () {\\n\\t\\tif ( ! khpld_is_demo() ) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\n\\t\\t$base = WPMU_PLUGIN_URL . '\\\/khpl-demo';\\n\\n\\t\\twp_enqueue_style( 'khpld-demo', $base . '\\\/demo.css', array(), '1.0.0' );\\n\\t\\twp_enqueue_script( 'khpld-demo', $base . '\\\/demo.js', array(), '1.0.0', true );\\n\\n\\t\\twp_localize_script(\\n\\t\\t\\t'khpld-demo',\\n\\t\\t\\t'khpldDemo',\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'ajaxUrl' => admin_url( 'admin-ajax.php' ),\\n\\t\\t\\t\\t'nonce'   => wp_create_nonce( 'khpld_apply' ),\\n\\t\\t\\t)\\n\\t\\t);\\n\\t}\\n);\\n\\n\\\/\\\/ -----------------------------------------------------------------------------\\n\\\/\\\/ Template\\n\\\/\\\/ -----------------------------------------------------------------------------\\n\\nadd_filter(\\n\\t'template_include',\\n\\tfunction ( $template ) {\\n\\t\\tif ( ! khpld_is_demo() ) {\\n\\t\\t\\treturn $template;\\n\\t\\t}\\n\\t\\treturn __DIR__ . '\\\/khpl-demo\\\/template.php';\\n\\t}\\n);\\n\\n\\\/\\\/ -----------------------------------------------------------------------------\\n\\\/\\\/ \\\"Apply to this site\\\" - the one live control on the page\\n\\\/\\\/ -----------------------------------------------------------------------------\\n\\nadd_action(\\n\\t'wp_ajax_khpld_apply',\\n\\tfunction () {\\n\\t\\tcheck_ajax_referer( 'khpld_apply', 'nonce' );\\n\\n\\t\\tif ( ! current_user_can( 'manage_options' ) || ! class_exists( 'KHPL_Settings' ) ) {\\n\\t\\t\\twp_send_json_error();\\n\\t\\t}\\n\\n\\t\\t$settings = new KHPL_Settings();\\n\\t\\t$current  = $settings->get_settings();\\n\\n\\t\\t\\\/\\\/ Only the six keys the demo exposes are taken from the request; every\\n\\t\\t\\\/\\\/ other stored setting is carried through untouched. The plugin's own\\n\\t\\t\\\/\\\/ sanitiser then validates the whole array, so an unexpected value can\\n\\t\\t\\\/\\\/ only ever fall back to that setting's default.\\n\\t\\t$keys = array( 'kinetic_mode', 'progress_style', 'exit_transition', 'page_reveal', 'cover_mode', 'logo_effect' );\\n\\n\\t\\tforeach ( $keys as $key ) {\\n\\t\\t\\tif ( isset( $_POST[ $key ] ) ) {\\n\\t\\t\\t\\t$current[ $key ] = sanitize_text_field( wp_unslash( $_POST[ $key ] ) );\\n\\t\\t\\t}\\n\\t\\t}\\n\\n\\t\\t\\\/\\\/ sanitize_settings() accepts stored arrays as readily as form strings for\\n\\t\\t\\\/\\\/ the list fields, so the whole array round-trips without conversion.\\n\\t\\tupdate_option( 'khpl_settings', $settings->sanitize_settings( $current ) );\\n\\n\\t\\twp_send_json_success();\\n\\t}\\n);\\n\\n\\\/\\\/ -----------------------------------------------------------------------------\\n\\\/\\\/ Rendering helpers\\n\\\/\\\/ -----------------------------------------------------------------------------\\n\\n\\\/**\\n * Renders one demo stage: a small viewport with the loader over it.\\n *\\n * @param array $args id, class, power, progress, exit, reveal, cover, effect, status.\\n *\\\/\\nfunction khpld_stage( array $args ): void {\\n\\t$a = wp_parse_args(\\n\\t\\t$args,\\n\\t\\tarray(\\n\\t\\t\\t'id'       => '',\\n\\t\\t\\t'class'    => '',\\n\\t\\t\\t'power'    => 'balanced',\\n\\t\\t\\t'progress' => 'none',\\n\\t\\t\\t'exit'     => 'fade',\\n\\t\\t\\t'reveal'   => 'soft-fade',\\n\\t\\t\\t'cover'    => 'solid',\\n\\t\\t\\t'effect'   => 'fade',\\n\\t\\t\\t'status'   => '',\\n\\t\\t\\t'tagline'  => 'Branded loading screens for WordPress',\\n\\t\\t)\\n\\t);\\n\\n\\t$logo = khpld_logo_url();\\n\\t?>\\n\\t<div class=\\\"khpld-stage <?php echo esc_attr( $a['class'] ); ?>\\\"\\n\\t\\t<?php echo $a['id'] ? 'id=\\\"' . esc_attr( $a['id'] ) . '\\\"' : ''; ?>\\n\\t\\tdata-power=\\\"<?php echo esc_attr( $a['power'] ); ?>\\\"\\n\\t\\tdata-progress=\\\"<?php echo esc_attr( $a['progress'] ); ?>\\\"\\n\\t\\tdata-exit=\\\"<?php echo esc_attr( $a['exit'] ); ?>\\\"\\n\\t\\tdata-reveal=\\\"<?php echo esc_attr( $a['reveal'] ); ?>\\\"\\n\\t\\tdata-cover=\\\"<?php echo esc_attr( $a['cover'] ); ?>\\\"\\n\\t\\tdata-effect=\\\"<?php echo esc_attr( $a['effect'] ); ?>\\\"\\n\\t\\t<?php echo $a['status'] ? 'data-status=\\\"' . esc_attr( $a['status'] ) . '\\\"' : ''; ?>\\n\\t\\taria-hidden=\\\"true\\\">\\n\\n\\t\\t<div class=\\\"khpld-stage__page\\\">\\n\\t\\t\\t<span class=\\\"khpld-stage__page-bar\\\"><\\\/span>\\n\\t\\t\\t<span class=\\\"khpld-stage__page-line\\\"><\\\/span>\\n\\t\\t\\t<span class=\\\"khpld-stage__page-line khpld-stage__page-line--short\\\"><\\\/span>\\n\\t\\t\\t<span class=\\\"khpld-stage__page-block\\\"><\\\/span>\\n\\t\\t<\\\/div>\\n\\n\\t\\t<div class=\\\"khpld-stage__loader\\\">\\n\\t\\t\\t<span class=\\\"khpld-stage__curtain khpld-stage__curtain--start\\\"><\\\/span>\\n\\t\\t\\t<span class=\\\"khpld-stage__curtain khpld-stage__curtain--end\\\"><\\\/span>\\n\\n\\t\\t\\t<div class=\\\"khpld-stage__track\\\"><span class=\\\"khpld-stage__bar\\\"><\\\/span><\\\/div>\\n\\n\\t\\t\\t<div class=\\\"khpld-stage__inner\\\">\\n\\t\\t\\t\\t<div class=\\\"khpld-stage__media\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-stage__ring\\\"><\\\/span>\\n\\t\\t\\t\\t\\t<svg class=\\\"khpld-stage__ringbar\\\" viewBox=\\\"0 0 100 100\\\" focusable=\\\"false\\\" aria-hidden=\\\"true\\\">\\n\\t\\t\\t\\t\\t\\t<circle class=\\\"khpld-stage__ringbar-track\\\" cx=\\\"50\\\" cy=\\\"50\\\" r=\\\"46\\\" \\\/>\\n\\t\\t\\t\\t\\t\\t<circle class=\\\"khpld-stage__ringbar-bar\\\" cx=\\\"50\\\" cy=\\\"50\\\" r=\\\"46\\\" \\\/>\\n\\t\\t\\t\\t\\t<\\\/svg>\\n\\t\\t\\t\\t\\t<?php if ( $logo ) : ?>\\n\\t\\t\\t\\t\\t<img class=\\\"khpld-stage__logo\\\" src=\\\"<?php echo esc_url( $logo ); ?>\\\" alt=\\\"\\\" \\\/>\\n\\t\\t\\t\\t\\t<?php endif; ?>\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-stage__shine\\\"><\\\/span>\\n\\t\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t\\t<span class=\\\"khpld-stage__tagline\\\"><?php echo esc_html( $a['tagline'] ); ?><\\\/span>\\n\\n\\t\\t\\t\\t<div class=\\\"khpld-stage__glow\\\"><span class=\\\"khpld-stage__bar\\\"><\\\/span><\\\/div>\\n\\t\\t\\t\\t<span class=\\\"khpld-stage__percent\\\" data-khpld-percent>0%<\\\/span>\\n\\t\\t\\t<\\\/div>\\n\\t\\t<\\\/div>\\n\\t<\\\/div>\\n\\t<?php\\n}\\n\\n\\\/**\\n * Renders a radio-card selector.\\n *\\n * Native radios keep arrow-key navigation, grouping and announcement for free;\\n * the card is the label, so the whole tile is clickable without any custom key\\n * handling. Selection is marked with a tick as well as colour.\\n *\\n * @param array $args legend, name, key, target, options, selected, class.\\n *\\\/\\nfunction khpld_seg( array $args ): void {\\n\\t$a = wp_parse_args(\\n\\t\\t$args,\\n\\t\\tarray(\\n\\t\\t\\t'legend'   => '',\\n\\t\\t\\t'name'     => '',\\n\\t\\t\\t'key'      => '',\\n\\t\\t\\t'target'   => '',\\n\\t\\t\\t'options'  => array(),\\n\\t\\t\\t'selected' => '',\\n\\t\\t\\t'class'    => '',\\n\\t\\t)\\n\\t);\\n\\n\\tif ( empty( $a['options'] ) ) {\\n\\t\\treturn;\\n\\t}\\n\\t?>\\n\\t<fieldset class=\\\"khpld-seg <?php echo esc_attr( $a['class'] ); ?>\\\">\\n\\t\\t<legend class=\\\"khpld-seg__legend\\\"><?php echo esc_html( $a['legend'] ); ?><\\\/legend>\\n\\t\\t<?php foreach ( $a['options'] as $value => $opt ) : ?>\\n\\t\\t<label class=\\\"khpld-opt\\\">\\n\\t\\t\\t<input type=\\\"radio\\\"\\n\\t\\t\\t\\tname=\\\"<?php echo esc_attr( $a['name'] ); ?>\\\"\\n\\t\\t\\t\\tvalue=\\\"<?php echo esc_attr( $value ); ?>\\\"\\n\\t\\t\\t\\tdata-khpld-control=\\\"<?php echo esc_attr( $a['key'] ); ?>\\\"\\n\\t\\t\\t\\tdata-target=\\\"<?php echo esc_attr( $a['target'] ); ?>\\\"\\n\\t\\t\\t\\t<?php checked( $a['selected'], $value ); ?> \\\/>\\n\\t\\t\\t<span class=\\\"khpld-opt__card\\\">\\n\\t\\t\\t\\t<span class=\\\"khpld-opt__name\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-opt__tick\\\" aria-hidden=\\\"true\\\">\\n\\t\\t\\t\\t\\t\\t<svg viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"3.4\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"><path d=\\\"m5 12.5 4.5 4.5L19 7.5\\\"\\\/><\\\/svg>\\n\\t\\t\\t\\t\\t<\\\/span>\\n\\t\\t\\t\\t\\t<?php echo esc_html( $opt['label'] ); ?>\\n\\t\\t\\t\\t<\\\/span>\\n\\t\\t\\t\\t<?php if ( ! empty( $opt['desc'] ) ) : ?>\\n\\t\\t\\t\\t<span class=\\\"khpld-opt__desc\\\"><?php echo esc_html( $opt['desc'] ); ?><\\\/span>\\n\\t\\t\\t\\t<?php endif; ?>\\n\\t\\t\\t<\\\/span>\\n\\t\\t<\\\/label>\\n\\t\\t<?php endforeach; ?>\\n\\t<\\\/fieldset>\\n\\t<?php\\n}\\n\\n\\\/**\\n * Prints one inline icon. Every icon is a static literal - no request, no font.\\n *\\n * @param string $name Icon slug.\\n *\\\/\\nfunction khpld_icon( string $name ): void {\\n\\t$open = '<svg viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"1.8\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\" focusable=\\\"false\\\" aria-hidden=\\\"true\\\">';\\n\\n\\tswitch ( $name ) {\\n\\t\\tcase 'feather':\\n\\t\\t\\techo $open . '<path d=\\\"M20.2 3.8a5.5 5.5 0 0 0-7.8 0L4 12.2V20h7.8l8.4-8.4a5.5 5.5 0 0 0 0-7.8Z\\\"\\\/><path d=\\\"M16 8 4.5 19.5\\\"\\\/><\\\/svg>'; \\\/\\\/ phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal.\\n\\t\\t\\tbreak;\\n\\t\\tcase 'brand':\\n\\t\\t\\techo $open . '<circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"8.6\\\"\\\/><circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"3\\\"\\\/><\\\/svg>'; \\\/\\\/ phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal.\\n\\t\\t\\tbreak;\\n\\t\\tcase 'motion':\\n\\t\\t\\techo $open . '<path d=\\\"M3 12h4l2.5-7 5 14L17 12h4\\\"\\\/><\\\/svg>'; \\\/\\\/ phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal.\\n\\t\\t\\tbreak;\\n\\t\\tcase 'flash':\\n\\t\\t\\techo $open . '<path d=\\\"M13.3 2.6 4.9 13.3h5.5l-.7 8.1 8.4-10.9h-5.5z\\\"\\\/><\\\/svg>'; \\\/\\\/ phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal.\\n\\t\\t\\tbreak;\\n\\t\\tcase 'clock':\\n\\t\\t\\techo $open . '<circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"9\\\"\\\/><path d=\\\"M12 7v5.3l3.4 2\\\"\\\/><\\\/svg>'; \\\/\\\/ phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal.\\n\\t\\t\\tbreak;\\n\\t\\tcase 'eye':\\n\\t\\t\\techo $open . '<path d=\\\"M2.6 12S6.1 5.6 12 5.6 21.4 12 21.4 12 17.9 18.4 12 18.4 2.6 12 2.6 12Z\\\"\\\/><circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"2.9\\\"\\\/><\\\/svg>'; \\\/\\\/ phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal.\\n\\t\\t\\tbreak;\\n\\t\\tcase 'devices':\\n\\t\\t\\techo $open . '<rect x=\\\"2.6\\\" y=\\\"4.6\\\" width=\\\"13\\\" height=\\\"10\\\" rx=\\\"1.8\\\"\\\/><rect x=\\\"17\\\" y=\\\"9\\\" width=\\\"4.6\\\" height=\\\"10.4\\\" rx=\\\"1.4\\\"\\\/><path d=\\\"M6.6 18.4h5\\\"\\\/><\\\/svg>'; \\\/\\\/ phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal.\\n\\t\\t\\tbreak;\\n\\t\\tcase 'cart':\\n\\t\\t\\techo $open . '<circle cx=\\\"9.5\\\" cy=\\\"19.5\\\" r=\\\"1.4\\\"\\\/><circle cx=\\\"17.5\\\" cy=\\\"19.5\\\" r=\\\"1.4\\\"\\\/><path d=\\\"M2.6 3.6h2.6l2.4 11.2h11l2.2-8.2H6\\\"\\\/><\\\/svg>'; \\\/\\\/ phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal.\\n\\t\\t\\tbreak;\\n\\t\\tcase 'shield':\\n\\t\\t\\techo $open . '<path d=\\\"M12 2.8 4.8 5.8v5.6c0 4.4 3 8.2 7.2 9.8 4.2-1.6 7.2-5.4 7.2-9.8V5.8z\\\"\\\/><path d=\\\"m8.8 12 2.2 2.2 4.2-4.4\\\"\\\/><\\\/svg>'; \\\/\\\/ phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal.\\n\\t\\t\\tbreak;\\n\\t\\tcase 'accessible':\\n\\t\\t\\techo $open . '<circle cx=\\\"12\\\" cy=\\\"12\\\" r=\\\"9\\\"\\\/><path d=\\\"M8.5 9.5h7M12 9.5V15m-2 2.5L12 15l2 2.5\\\"\\\/><\\\/svg>'; \\\/\\\/ phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal.\\n\\t\\t\\tbreak;\\n\\t\\tcase 'play':\\n\\t\\t\\techo $open . '<path d=\\\"M7.5 4.8 19 12 7.5 19.2z\\\"\\\/><\\\/svg>'; \\\/\\\/ phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal.\\n\\t\\t\\tbreak;\\n\\t\\tcase 'sliders':\\n\\t\\t\\techo $open . '<path d=\\\"M6 3v5.2M6 12.8V21M12 3v9.2M12 16.8V21M18 3v2.2M18 9.8V21\\\"\\\/><circle cx=\\\"6\\\" cy=\\\"10.5\\\" r=\\\"2.3\\\"\\\/><circle cx=\\\"12\\\" cy=\\\"15\\\" r=\\\"2.3\\\"\\\/><circle cx=\\\"18\\\" cy=\\\"7.5\\\" r=\\\"2.3\\\"\\\/><\\\/svg>'; \\\/\\\/ phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal.\\n\\t\\t\\tbreak;\\n\\t\\tcase 'message':\\n\\t\\t\\techo $open . '<path d=\\\"M20.4 15.2a2 2 0 0 1-2 2H7.6L3.6 21V5.4a2 2 0 0 1 2-2h12.8a2 2 0 0 1 2 2z\\\"\\\/><\\\/svg>'; \\\/\\\/ phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- static literal.\\n\\t\\t\\tbreak;\\n\\t}\\n}\\n\\n\\\/**\\n * Renders a replay button plus its live status line for one stage.\\n *\\n * @param string $stage_id Stage element id.\\n * @param string $label    Button label.\\n *\\\/\\nfunction khpld_replay( string $stage_id, string $label = 'Replay' ): void {\\n\\t$status_id = $stage_id . '-status';\\n\\t?>\\n\\t<div class=\\\"khpld-stage-bar\\\">\\n\\t\\t<button type=\\\"button\\\" class=\\\"khpld-btn\\\" data-khpld-replay=\\\"<?php echo esc_attr( $stage_id ); ?>\\\">\\n\\t\\t\\t<?php khpld_icon( 'play' ); ?>\\n\\t\\t\\t<?php echo esc_html( $label ); ?>\\n\\t\\t<\\\/button>\\n\\t\\t<span class=\\\"khpld-stage-status\\\" id=\\\"<?php echo esc_attr( $status_id ); ?>\\\" role=\\\"status\\\" aria-live=\\\"polite\\\"><\\\/span>\\n\\t<\\\/div>\\n\\t<?php\\n}\\n\"},{\"step\":\"mkdir\",\"path\":\"\\\/wordpress\\\/wp-content\\\/mu-plugins\\\/khpl-demo\"},{\"step\":\"writeFile\",\"path\":\"\\\/wordpress\\\/wp-content\\\/mu-plugins\\\/khpl-demo\\\/template.php\",\"data\":\"<?php\\n\\\/**\\n * KineticHub Page Loader - Playground showcase template.\\n *\\n * A standalone dark page: the demo deliberately owns the whole viewport rather\\n * than sitting inside theme chrome, because it is the product showcase. It\\n * still calls wp_head() \\\/ wp_body_open() \\\/ wp_footer(), so the real Page Loader\\n * runs over it exactly as it would on any site, and the admin bar keeps\\n * working.\\n *\\n * Every option list is filtered through KHPL_Settings::get_choices() before it\\n * is rendered, so nothing here can advertise a value the plugin does not have.\\n *\\n * @package KineticHub_Page_Loader_Demo\\n *\\\/\\n\\nif ( ! defined( 'ABSPATH' ) ) {\\n\\texit;\\n}\\n\\n$khpld_logo = khpld_logo_url();\\n\\n$khpld_modes = khpld_filter_options(\\n\\t'kinetic_mode',\\n\\tarray(\\n\\t\\t'ultra-minimal'  => array( 'label' => 'Ultra Minimal',  'desc' => 'Almost still. Clean and restrained.' ),\\n\\t\\t'calm'           => array( 'label' => 'Calm',           'desc' => 'Soft movement and gentle pacing.' ),\\n\\t\\t'balanced'       => array( 'label' => 'Balanced',       'desc' => 'Polished motion without distraction.' ),\\n\\t\\t'dynamic'        => array( 'label' => 'Dynamic',        'desc' => 'Sharper movement and stronger presence.' ),\\n\\t\\t'signature-glow' => array( 'label' => 'Signature Glow', 'desc' => 'The most expressive KineticHub treatment.' ),\\n\\t\\t'classic'        => array( 'label' => 'Classic',        'desc' => 'The original baseline pacing.' ),\\n\\t)\\n);\\n\\n$khpld_progress = khpld_filter_options(\\n\\t'progress_style',\\n\\tarray(\\n\\t\\t'none'            => array( 'label' => 'None',        'desc' => 'No progress indicator at all.' ),\\n\\t\\t'top-bar'         => array( 'label' => 'Top Bar',     'desc' => 'A thin bar across the top edge.' ),\\n\\t\\t'bottom-line'     => array( 'label' => 'Bottom Line', 'desc' => 'The same bar, anchored low.' ),\\n\\t\\t'logo-ring'       => array( 'label' => 'Logo Ring',   'desc' => 'Progress traced around the logo.' ),\\n\\t\\t'center-glow'     => array( 'label' => 'Center Glow', 'desc' => 'A soft lit line beneath the mark.' ),\\n\\t\\t'minimal-percent' => array( 'label' => 'Percentage',  'desc' => 'A quiet numeric readout.' ),\\n\\t)\\n);\\n\\n$khpld_exits = khpld_filter_options(\\n\\t'exit_transition',\\n\\tarray(\\n\\t\\t'fade'          => array( 'label' => 'Fade',          'desc' => 'Simply dissolves away.' ),\\n\\t\\t'slide-up'      => array( 'label' => 'Slide Up',      'desc' => 'Lifts off the top of the screen.' ),\\n\\t\\t'blur-lift'     => array( 'label' => 'Blur Lift',     'desc' => 'Softens and floats upward.' ),\\n\\t\\t'split-curtain' => array( 'label' => 'Split Curtain', 'desc' => 'Parts from the middle outward.' ),\\n\\t\\t'circle-reveal' => array( 'label' => 'Circle Reveal', 'desc' => 'Irises open from the centre.' ),\\n\\t)\\n);\\n\\n$khpld_reveals = khpld_filter_options(\\n\\t'page_reveal',\\n\\tarray(\\n\\t\\t'none'         => array( 'label' => 'None',          'desc' => 'The page is simply there.' ),\\n\\t\\t'soft-fade'    => array( 'label' => 'Soft Fade',     'desc' => 'The page fades up into place.' ),\\n\\t\\t'blur-sharp'   => array( 'label' => 'Blur to Sharp', 'desc' => 'Focus resolves as it arrives.' ),\\n\\t\\t'lift-in'      => array( 'label' => 'Lift In',       'desc' => 'Rises gently into position.' ),\\n\\t\\t'gentle-scale' => array( 'label' => 'Gentle Scale',  'desc' => 'Settles out from slightly small.' ),\\n\\t)\\n);\\n\\n$khpld_covers = khpld_filter_options(\\n\\t'cover_mode',\\n\\tarray(\\n\\t\\t'solid'        => array( 'label' => 'Solid',        'desc' => 'Fully hides the page while it renders.' ),\\n\\t\\t'soft-overlay' => array( 'label' => 'Soft Overlay', 'desc' => 'A translucent veil over the layout.' ),\\n\\t\\t'blur-page'    => array( 'label' => 'Blur Page',    'desc' => 'The page shows through, softened.' ),\\n\\t\\t'glass'        => array( 'label' => 'Glass',        'desc' => 'Frosted glass with a little saturation.' ),\\n\\t)\\n);\\n\\n$khpld_effects = khpld_filter_options(\\n\\t'logo_effect',\\n\\tarray(\\n\\t\\t'fade'              => array( 'label' => 'Fade',              'desc' => 'Quietly appears.' ),\\n\\t\\t'grayscale-reveal'  => array( 'label' => 'Grayscale to Color', 'desc' => 'Colour washes in.' ),\\n\\t\\t'soft-scale'        => array( 'label' => 'Soft Scale',        'desc' => 'Eases up to full size.' ),\\n\\t\\t'shine-sweep'       => array( 'label' => 'Soft Shine Sweep',  'desc' => 'A light passes across.' ),\\n\\t\\t'zoom-bloom'        => array( 'label' => 'Zoom Bloom',        'desc' => 'Opens with a gentle overshoot.' ),\\n\\t\\t'mask-reveal'       => array( 'label' => 'Mask Reveal',       'desc' => 'Wipes upward into view.' ),\\n\\t)\\n);\\n\\n\\\/*\\n * The logo effect the closing composition starts on, and therefore the tile\\n * that starts marked as selected. Derived rather than written twice: if\\n * 'zoom-bloom' were ever dropped from the plugin, khpld_filter_options() would\\n * remove that tile and the CTA stage would still claim it, so the gallery and\\n * the CTA would disagree about what \\\"Apply\\\" is about to write.\\n *\\\/\\n$khpld_default_effect = isset( $khpld_effects['zoom-bloom'] )\\n\\t? 'zoom-bloom'\\n\\t: ( $khpld_effects ? (string) array_key_first( $khpld_effects ) : 'fade' );\\n\\n?><!DOCTYPE html>\\n<html <?php language_attributes(); ?>>\\n<head>\\n\\t<meta charset=\\\"<?php bloginfo( 'charset' ); ?>\\\" \\\/>\\n\\t<meta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1\\\" \\\/>\\n\\t<?php wp_head(); ?>\\n<\\\/head>\\n<body <?php body_class( 'khpld' ); ?>>\\n<?php wp_body_open(); ?>\\n\\n<main class=\\\"khpld-main\\\">\\n\\n\\t<!-- ===================================================== 1. HERO -->\\n\\t<section class=\\\"khpld-hero\\\">\\n\\t\\t<div class=\\\"khpld-shell\\\">\\n\\t\\t\\t<div class=\\\"khpld-hero__grid\\\">\\n\\t\\t\\t\\t<div>\\n\\t\\t\\t\\t\\t<?php if ( $khpld_logo ) : ?>\\n\\t\\t\\t\\t\\t<div class=\\\"khpld-hero__brand\\\">\\n\\t\\t\\t\\t\\t\\t<img src=\\\"<?php echo esc_url( $khpld_logo ); ?>\\\" alt=\\\"\\\" width=\\\"42\\\" height=\\\"42\\\" \\\/>\\n\\t\\t\\t\\t\\t\\t<span class=\\\"khpld-hero__brand-name\\\">KineticHub Page Loader<\\\/span>\\n\\t\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t\\t\\t<?php endif; ?>\\n\\n\\t\\t\\t\\t\\t<h1 class=\\\"khpld-hero__title\\\">\\n\\t\\t\\t\\t\\t\\tMake the <span class=\\\"khpld-hero__accent\\\">first second<\\\/span> memorable.\\n\\t\\t\\t\\t\\t<\\\/h1>\\n\\n\\t\\t\\t\\t\\t<p class=\\\"khpld-hero__lede\\\">\\n\\t\\t\\t\\t\\t\\tCreate a branded loading experience with refined motion, smart timing,\\n\\t\\t\\t\\t\\t\\tprogress styles, and polished page reveals &mdash; without turning your\\n\\t\\t\\t\\t\\t\\tsite into a heavy animation project.\\n\\t\\t\\t\\t\\t<\\\/p>\\n\\n\\t\\t\\t\\t\\t<ul class=\\\"khpld-chips\\\">\\n\\t\\t\\t\\t\\t\\t<li class=\\\"khpld-chip\\\"><?php khpld_icon( 'feather' ); ?>Lightweight<\\\/li>\\n\\t\\t\\t\\t\\t\\t<li class=\\\"khpld-chip\\\"><?php khpld_icon( 'brand' ); ?>Brand-first<\\\/li>\\n\\t\\t\\t\\t\\t\\t<li class=\\\"khpld-chip\\\"><?php khpld_icon( 'accessible' ); ?>Reduced-motion aware<\\\/li>\\n\\t\\t\\t\\t\\t\\t<li class=\\\"khpld-chip\\\"><?php khpld_icon( 'flash' ); ?>Smart anti-flash<\\\/li>\\n\\t\\t\\t\\t\\t<\\\/ul>\\n\\t\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t\\t<div class=\\\"khpld-stage-wrap\\\">\\n\\t\\t\\t\\t\\t<?php\\n\\t\\t\\t\\t\\tkhpld_stage(\\n\\t\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t\\t'id'       => 'khpld-stage-hero',\\n\\t\\t\\t\\t\\t\\t\\t'class'    => 'khpld-stage--tall',\\n\\t\\t\\t\\t\\t\\t\\t'power'    => 'signature-glow',\\n\\t\\t\\t\\t\\t\\t\\t'progress' => 'logo-ring',\\n\\t\\t\\t\\t\\t\\t\\t'exit'     => 'circle-reveal',\\n\\t\\t\\t\\t\\t\\t\\t'reveal'   => 'soft-fade',\\n\\t\\t\\t\\t\\t\\t\\t'cover'    => 'solid',\\n\\t\\t\\t\\t\\t\\t\\t'effect'   => 'zoom-bloom',\\n\\t\\t\\t\\t\\t\\t\\t'status'   => 'khpld-stage-hero-status',\\n\\t\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\tkhpld_replay( 'khpld-stage-hero', 'Play the intro' );\\n\\t\\t\\t\\t\\t?>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t<\\\/div>\\n\\t\\t<\\\/div>\\n\\t<\\\/section>\\n\\n\\t<!-- ============================================ 2. KINETICPOWER -->\\n\\t<section class=\\\"khpld-section\\\">\\n\\t\\t<div class=\\\"khpld-shell\\\">\\n\\t\\t\\t<div class=\\\"khpld-section__head\\\">\\n\\t\\t\\t\\t<p class=\\\"khpld-eyebrow\\\">KineticPower<\\\/p>\\n\\t\\t\\t\\t<h2 class=\\\"khpld-h2\\\">Choose the mood.<\\\/h2>\\n\\t\\t\\t\\t<p class=\\\"khpld-lede\\\">\\n\\t\\t\\t\\t\\tOne motion profile retunes pacing, glow and entrance across whichever\\n\\t\\t\\t\\t\\tpreset and effects you already chose &mdash; it never replaces them.\\n\\t\\t\\t\\t\\tSame brand, different personality.\\n\\t\\t\\t\\t<\\\/p>\\n\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t<div class=\\\"khpld-split\\\">\\n\\t\\t\\t\\t<div class=\\\"khpld-split__visual khpld-stage-wrap\\\">\\n\\t\\t\\t\\t\\t<?php\\n\\t\\t\\t\\t\\tkhpld_stage(\\n\\t\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t\\t'id'       => 'khpld-stage-mood',\\n\\t\\t\\t\\t\\t\\t\\t'power'    => 'balanced',\\n\\t\\t\\t\\t\\t\\t\\t'progress' => 'center-glow',\\n\\t\\t\\t\\t\\t\\t\\t'exit'     => 'fade',\\n\\t\\t\\t\\t\\t\\t\\t'reveal'   => 'soft-fade',\\n\\t\\t\\t\\t\\t\\t\\t'effect'   => 'soft-scale',\\n\\t\\t\\t\\t\\t\\t\\t'status'   => 'khpld-stage-mood-status',\\n\\t\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\tkhpld_replay( 'khpld-stage-mood' );\\n\\t\\t\\t\\t\\t?>\\n\\t\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t\\t<div>\\n\\t\\t\\t\\t\\t<?php\\n\\t\\t\\t\\t\\tkhpld_seg(\\n\\t\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t\\t'legend'   => 'Motion profile',\\n\\t\\t\\t\\t\\t\\t\\t'name'     => 'khpld-mood',\\n\\t\\t\\t\\t\\t\\t\\t'key'      => 'power',\\n\\t\\t\\t\\t\\t\\t\\t'target'   => 'khpld-stage-mood',\\n\\t\\t\\t\\t\\t\\t\\t'options'  => $khpld_modes,\\n\\t\\t\\t\\t\\t\\t\\t'selected' => 'balanced',\\n\\t\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t?>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t<\\\/div>\\n\\t\\t<\\\/div>\\n\\t<\\\/section>\\n\\n\\t<!-- ============================================ 3. LOGO REVEALS -->\\n\\t<section class=\\\"khpld-section\\\">\\n\\t\\t<div class=\\\"khpld-shell\\\">\\n\\t\\t\\t<div class=\\\"khpld-section__head\\\">\\n\\t\\t\\t\\t<p class=\\\"khpld-eyebrow\\\">Logo reveals<\\\/p>\\n\\t\\t\\t\\t<h2 class=\\\"khpld-h2\\\">One logo. Several refined entrances.<\\\/h2>\\n\\t\\t\\t\\t<p class=\\\"khpld-lede\\\">\\n\\t\\t\\t\\t\\tThe mark you already use can arrive in a way that suits the brand.\\n\\t\\t\\t\\t\\tSelect any tile to play it again.\\n\\t\\t\\t\\t<\\\/p>\\n\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t<div class=\\\"khpld-gallery\\\" role=\\\"group\\\" aria-label=\\\"Logo reveal effect\\\">\\n\\t\\t\\t\\t<?php\\n\\t\\t\\t\\t$khpld_i = 0;\\n\\t\\t\\t\\tforeach ( $khpld_effects as $khpld_value => $khpld_effect ) :\\n\\t\\t\\t\\t\\t$khpld_i++;\\n\\t\\t\\t\\t\\t$khpld_id       = 'khpld-stage-fx-' . $khpld_i;\\n\\t\\t\\t\\t\\t$khpld_selected = ( $khpld_value === $khpld_default_effect );\\n\\t\\t\\t\\t\\t?>\\n\\t\\t\\t\\t<button type=\\\"button\\\"\\n\\t\\t\\t\\t\\tclass=\\\"khpld-tile\\\"\\n\\t\\t\\t\\t\\tdata-khpld-effect=\\\"<?php echo esc_attr( $khpld_value ); ?>\\\"\\n\\t\\t\\t\\t\\taria-pressed=\\\"<?php echo $khpld_selected ? 'true' : 'false'; ?>\\\">\\n\\t\\t\\t\\t\\t<?php\\n\\t\\t\\t\\t\\tkhpld_stage(\\n\\t\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t\\t'id'       => $khpld_id,\\n\\t\\t\\t\\t\\t\\t\\t'power'    => 'balanced',\\n\\t\\t\\t\\t\\t\\t\\t'progress' => 'none',\\n\\t\\t\\t\\t\\t\\t\\t'exit'     => 'fade',\\n\\t\\t\\t\\t\\t\\t\\t'reveal'   => 'none',\\n\\t\\t\\t\\t\\t\\t\\t'effect'   => $khpld_value,\\n\\t\\t\\t\\t\\t\\t\\t'tagline'  => $khpld_effect['label'],\\n\\t\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t?>\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-tile__meta\\\">\\n\\t\\t\\t\\t\\t\\t<span class=\\\"khpld-tile__name\\\">\\n\\t\\t\\t\\t\\t\\t\\t<?php\\n\\t\\t\\t\\t\\t\\t\\t\\\/*\\n\\t\\t\\t\\t\\t\\t\\t * The tick is a shape and a word, not just a colour: the\\n\\t\\t\\t\\t\\t\\t\\t * selected tile stays identifiable to anyone who cannot\\n\\t\\t\\t\\t\\t\\t\\t * separate the cyan border from the default one, and\\n\\t\\t\\t\\t\\t\\t\\t * aria-pressed carries the same state to assistive tech.\\n\\t\\t\\t\\t\\t\\t\\t *\\\/\\n\\t\\t\\t\\t\\t\\t\\t?>\\n\\t\\t\\t\\t\\t\\t\\t<span class=\\\"khpld-tile__tick\\\" aria-hidden=\\\"true\\\">\\n\\t\\t\\t\\t\\t\\t\\t\\t<svg viewBox=\\\"0 0 24 24\\\" fill=\\\"none\\\" stroke=\\\"currentColor\\\" stroke-width=\\\"3.4\\\" stroke-linecap=\\\"round\\\" stroke-linejoin=\\\"round\\\"><path d=\\\"m5 12.5 4.5 4.5L19 7.5\\\"\\\/><\\\/svg>\\n\\t\\t\\t\\t\\t\\t\\t<\\\/span>\\n\\t\\t\\t\\t\\t\\t\\t<?php echo esc_html( $khpld_effect['label'] ); ?>\\n\\t\\t\\t\\t\\t\\t<\\\/span>\\n\\t\\t\\t\\t\\t\\t<span class=\\\"khpld-tile__hint\\\"><?php echo esc_html( $khpld_effect['desc'] ); ?><\\\/span>\\n\\t\\t\\t\\t\\t<\\\/span>\\n\\t\\t\\t\\t<\\\/button>\\n\\t\\t\\t\\t<?php endforeach; ?>\\n\\t\\t\\t<\\\/div>\\n\\t\\t<\\\/div>\\n\\t<\\\/section>\\n\\n\\t<!-- ================================================ 4. PROGRESS -->\\n\\t<section class=\\\"khpld-section\\\">\\n\\t\\t<div class=\\\"khpld-shell\\\">\\n\\t\\t\\t<div class=\\\"khpld-section__head khpld-section__head--center\\\">\\n\\t\\t\\t\\t<p class=\\\"khpld-eyebrow\\\">Progress<\\\/p>\\n\\t\\t\\t\\t<h2 class=\\\"khpld-h2\\\">Choose how progress feels.<\\\/h2>\\n\\t\\t\\t\\t<p class=\\\"khpld-lede\\\">\\n\\t\\t\\t\\t\\tProgress is a pacing device, not a network measurement. It eases toward\\n\\t\\t\\t\\t\\tcompletion and finishes cleanly when the page is ready.\\n\\t\\t\\t\\t<\\\/p>\\n\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t<div class=\\\"khpld-stage-wrap khpld-stage-wrap--centered\\\">\\n\\t\\t\\t\\t<?php\\n\\t\\t\\t\\tkhpld_stage(\\n\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t'id'       => 'khpld-stage-progress',\\n\\t\\t\\t\\t\\t\\t'class'    => 'khpld-stage--wide',\\n\\t\\t\\t\\t\\t\\t'power'    => 'balanced',\\n\\t\\t\\t\\t\\t\\t'progress' => 'logo-ring',\\n\\t\\t\\t\\t\\t\\t'exit'     => 'fade',\\n\\t\\t\\t\\t\\t\\t'reveal'   => 'soft-fade',\\n\\t\\t\\t\\t\\t\\t'effect'   => 'fade',\\n\\t\\t\\t\\t\\t\\t'status'   => 'khpld-stage-progress-status',\\n\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t);\\n\\t\\t\\t\\tkhpld_replay( 'khpld-stage-progress' );\\n\\t\\t\\t\\t?>\\n\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t<div style=\\\"margin-top:26px\\\">\\n\\t\\t\\t\\t<?php\\n\\t\\t\\t\\tkhpld_seg(\\n\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t'legend'   => 'Progress style',\\n\\t\\t\\t\\t\\t\\t'name'     => 'khpld-progress',\\n\\t\\t\\t\\t\\t\\t'key'      => 'progress',\\n\\t\\t\\t\\t\\t\\t'target'   => 'khpld-stage-progress',\\n\\t\\t\\t\\t\\t\\t'options'  => $khpld_progress,\\n\\t\\t\\t\\t\\t\\t'selected' => 'logo-ring',\\n\\t\\t\\t\\t\\t\\t'class'    => 'khpld-seg--tight',\\n\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t);\\n\\t\\t\\t\\t?>\\n\\t\\t\\t<\\\/div>\\n\\t\\t<\\\/div>\\n\\t<\\\/section>\\n\\n\\t<!-- =================================================== 5. EXITS -->\\n\\t<section class=\\\"khpld-section\\\">\\n\\t\\t<div class=\\\"khpld-shell\\\">\\n\\t\\t\\t<div class=\\\"khpld-section__head\\\">\\n\\t\\t\\t\\t<p class=\\\"khpld-eyebrow\\\">Exit transitions<\\\/p>\\n\\t\\t\\t\\t<h2 class=\\\"khpld-h2\\\">The loader should leave as gracefully as it arrived.<\\\/h2>\\n\\t\\t\\t\\t<p class=\\\"khpld-lede\\\">\\n\\t\\t\\t\\t\\tRemoval is driven by a timer rather than by the animation finishing, so\\n\\t\\t\\t\\t\\tthe loader is always cleared even if the transition is interrupted.\\n\\t\\t\\t\\t<\\\/p>\\n\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t<div class=\\\"khpld-split khpld-split--stage-first\\\">\\n\\t\\t\\t\\t<div>\\n\\t\\t\\t\\t\\t<?php\\n\\t\\t\\t\\t\\tkhpld_seg(\\n\\t\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t\\t'legend'   => 'Exit style',\\n\\t\\t\\t\\t\\t\\t\\t'name'     => 'khpld-exit',\\n\\t\\t\\t\\t\\t\\t\\t'key'      => 'exit',\\n\\t\\t\\t\\t\\t\\t\\t'target'   => 'khpld-stage-exit',\\n\\t\\t\\t\\t\\t\\t\\t'options'  => $khpld_exits,\\n\\t\\t\\t\\t\\t\\t\\t'selected' => 'circle-reveal',\\n\\t\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t?>\\n\\t\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t\\t<div class=\\\"khpld-split__visual khpld-stage-wrap\\\">\\n\\t\\t\\t\\t\\t<?php\\n\\t\\t\\t\\t\\tkhpld_stage(\\n\\t\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t\\t'id'       => 'khpld-stage-exit',\\n\\t\\t\\t\\t\\t\\t\\t'power'    => 'balanced',\\n\\t\\t\\t\\t\\t\\t\\t'progress' => 'top-bar',\\n\\t\\t\\t\\t\\t\\t\\t'exit'     => 'circle-reveal',\\n\\t\\t\\t\\t\\t\\t\\t'reveal'   => 'none',\\n\\t\\t\\t\\t\\t\\t\\t'effect'   => 'fade',\\n\\t\\t\\t\\t\\t\\t\\t'status'   => 'khpld-stage-exit-status',\\n\\t\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\tkhpld_replay( 'khpld-stage-exit' );\\n\\t\\t\\t\\t\\t?>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t<\\\/div>\\n\\t\\t<\\\/div>\\n\\t<\\\/section>\\n\\n\\t<!-- ============================================= 6. PAGE REVEAL -->\\n\\t<section class=\\\"khpld-section\\\">\\n\\t\\t<div class=\\\"khpld-shell\\\">\\n\\t\\t\\t<div class=\\\"khpld-section__head\\\">\\n\\t\\t\\t\\t<p class=\\\"khpld-eyebrow\\\">Page reveal<\\\/p>\\n\\t\\t\\t\\t<h2 class=\\\"khpld-h2\\\">Two different moments, deliberately.<\\\/h2>\\n\\t\\t\\t\\t<p class=\\\"khpld-lede\\\">\\n\\t\\t\\t\\t\\tThe exit is how the loader leaves. The page reveal is how your content\\n\\t\\t\\t\\t\\tarrives underneath it. Setting both is what makes the handover feel\\n\\t\\t\\t\\t\\tconsidered rather than abrupt.\\n\\t\\t\\t\\t<\\\/p>\\n\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t<div class=\\\"khpld-split\\\">\\n\\t\\t\\t\\t<div class=\\\"khpld-split__visual khpld-stage-wrap\\\">\\n\\t\\t\\t\\t\\t<?php\\n\\t\\t\\t\\t\\tkhpld_stage(\\n\\t\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t\\t'id'       => 'khpld-stage-reveal',\\n\\t\\t\\t\\t\\t\\t\\t'power'    => 'calm',\\n\\t\\t\\t\\t\\t\\t\\t'progress' => 'none',\\n\\t\\t\\t\\t\\t\\t\\t'exit'     => 'fade',\\n\\t\\t\\t\\t\\t\\t\\t'reveal'   => 'blur-sharp',\\n\\t\\t\\t\\t\\t\\t\\t'effect'   => 'fade',\\n\\t\\t\\t\\t\\t\\t\\t'status'   => 'khpld-stage-reveal-status',\\n\\t\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\tkhpld_replay( 'khpld-stage-reveal' );\\n\\t\\t\\t\\t\\t?>\\n\\t\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t\\t<div>\\n\\t\\t\\t\\t\\t<?php\\n\\t\\t\\t\\t\\tkhpld_seg(\\n\\t\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t\\t'legend'   => 'Page reveal',\\n\\t\\t\\t\\t\\t\\t\\t'name'     => 'khpld-reveal',\\n\\t\\t\\t\\t\\t\\t\\t'key'      => 'reveal',\\n\\t\\t\\t\\t\\t\\t\\t'target'   => 'khpld-stage-reveal',\\n\\t\\t\\t\\t\\t\\t\\t'options'  => $khpld_reveals,\\n\\t\\t\\t\\t\\t\\t\\t'selected' => 'blur-sharp',\\n\\t\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t?>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t<\\\/div>\\n\\t\\t<\\\/div>\\n\\t<\\\/section>\\n\\n\\t<!-- ============================================= 7. COVER MODES -->\\n\\t<section class=\\\"khpld-section\\\">\\n\\t\\t<div class=\\\"khpld-shell\\\">\\n\\t\\t\\t<div class=\\\"khpld-section__head khpld-section__head--center\\\">\\n\\t\\t\\t\\t<p class=\\\"khpld-eyebrow\\\">Cover modes<\\\/p>\\n\\t\\t\\t\\t<h2 class=\\\"khpld-h2\\\">Hide the page, or let it breathe through.<\\\/h2>\\n\\t\\t\\t\\t<p class=\\\"khpld-lede\\\">\\n\\t\\t\\t\\t\\tSolid fully hides the layout while it renders. The other modes let it\\n\\t\\t\\t\\t\\tshow through, softened. Browsers without backdrop-filter fall back to a\\n\\t\\t\\t\\t\\tsolid cover.\\n\\t\\t\\t\\t<\\\/p>\\n\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t<div class=\\\"khpld-split\\\">\\n\\t\\t\\t\\t<div class=\\\"khpld-split__visual khpld-stage-wrap\\\">\\n\\t\\t\\t\\t\\t<?php\\n\\t\\t\\t\\t\\tkhpld_stage(\\n\\t\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t\\t'id'       => 'khpld-stage-cover',\\n\\t\\t\\t\\t\\t\\t\\t'power'    => 'balanced',\\n\\t\\t\\t\\t\\t\\t\\t'progress' => 'none',\\n\\t\\t\\t\\t\\t\\t\\t'exit'     => 'fade',\\n\\t\\t\\t\\t\\t\\t\\t'reveal'   => 'none',\\n\\t\\t\\t\\t\\t\\t\\t'cover'    => 'glass',\\n\\t\\t\\t\\t\\t\\t\\t'effect'   => 'fade',\\n\\t\\t\\t\\t\\t\\t\\t'status'   => 'khpld-stage-cover-status',\\n\\t\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\tkhpld_replay( 'khpld-stage-cover' );\\n\\t\\t\\t\\t\\t?>\\n\\t\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t\\t<div>\\n\\t\\t\\t\\t\\t<?php\\n\\t\\t\\t\\t\\tkhpld_seg(\\n\\t\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t\\t'legend'   => 'Cover style',\\n\\t\\t\\t\\t\\t\\t\\t'name'     => 'khpld-cover',\\n\\t\\t\\t\\t\\t\\t\\t'key'      => 'cover',\\n\\t\\t\\t\\t\\t\\t\\t'target'   => 'khpld-stage-cover',\\n\\t\\t\\t\\t\\t\\t\\t'options'  => $khpld_covers,\\n\\t\\t\\t\\t\\t\\t\\t'selected' => 'glass',\\n\\t\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t?>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t<\\\/div>\\n\\t\\t<\\\/div>\\n\\t<\\\/section>\\n\\n\\t<!-- ==================================================== 8. SMART -->\\n\\t<section class=\\\"khpld-section\\\">\\n\\t\\t<div class=\\\"khpld-shell\\\">\\n\\t\\t\\t<div class=\\\"khpld-section__head\\\">\\n\\t\\t\\t\\t<p class=\\\"khpld-eyebrow\\\">Practical<\\\/p>\\n\\t\\t\\t\\t<h2 class=\\\"khpld-h2\\\">Smart enough to stay out of the way.<\\\/h2>\\n\\t\\t\\t\\t<p class=\\\"khpld-lede\\\">\\n\\t\\t\\t\\t\\tA loading screen earns its place by knowing when not to appear.\\n\\t\\t\\t\\t<\\\/p>\\n\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t<div class=\\\"khpld-cards\\\">\\n\\t\\t\\t\\t<div class=\\\"khpld-card\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-card__icon\\\"><?php khpld_icon( 'flash' ); ?><\\\/span>\\n\\t\\t\\t\\t\\t<h3 class=\\\"khpld-card__title\\\">Smart Anti-Flash<\\\/h3>\\n\\t\\t\\t\\t\\t<p class=\\\"khpld-card__text\\\">Hold the loader back for a moment so pages that finish immediately never flash one up at all.<\\\/p>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t\\t<div class=\\\"khpld-card\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-card__icon\\\"><?php khpld_icon( 'clock' ); ?><\\\/span>\\n\\t\\t\\t\\t\\t<h3 class=\\\"khpld-card__title\\\">Frequency Control<\\\/h3>\\n\\t\\t\\t\\t\\t<p class=\\\"khpld-card__text\\\">Show it on every load, once per session, or once per day.<\\\/p>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t\\t<div class=\\\"khpld-card\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-card__icon\\\"><?php khpld_icon( 'eye' ); ?><\\\/span>\\n\\t\\t\\t\\t\\t<h3 class=\\\"khpld-card__title\\\">Display Rules<\\\/h3>\\n\\t\\t\\t\\t\\t<p class=\\\"khpld-card__text\\\">Run it across the whole site or on the homepage only, and exclude specific posts or URL paths.<\\\/p>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t\\t<div class=\\\"khpld-card\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-card__icon\\\"><?php khpld_icon( 'devices' ); ?><\\\/span>\\n\\t\\t\\t\\t\\t<h3 class=\\\"khpld-card__title\\\">Device Visibility<\\\/h3>\\n\\t\\t\\t\\t\\t<p class=\\\"khpld-card__text\\\">Independent desktop and mobile switches, plus a visitors-only option that hides it from logged-in users.<\\\/p>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t\\t<div class=\\\"khpld-card\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-card__icon\\\"><?php khpld_icon( 'cart' ); ?><\\\/span>\\n\\t\\t\\t\\t\\t<h3 class=\\\"khpld-card__title\\\">WooCommerce Exclusions<\\\/h3>\\n\\t\\t\\t\\t\\t<p class=\\\"khpld-card__text\\\">Keep cart and checkout flows clear of the loader when that suits the store.<\\\/p>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t\\t<div class=\\\"khpld-card\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-card__icon\\\"><?php khpld_icon( 'shield' ); ?><\\\/span>\\n\\t\\t\\t\\t\\t<h3 class=\\\"khpld-card__title\\\">Maximum Timeout<\\\/h3>\\n\\t\\t\\t\\t\\t<p class=\\\"khpld-card__text\\\">A failsafe timer removes the loader no matter what, so a visitor is never trapped behind it.<\\\/p>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t\\t<div class=\\\"khpld-card\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-card__icon\\\"><?php khpld_icon( 'accessible' ); ?><\\\/span>\\n\\t\\t\\t\\t\\t<h3 class=\\\"khpld-card__title\\\">Reduced Motion<\\\/h3>\\n\\t\\t\\t\\t\\t<p class=\\\"khpld-card__text\\\">When a visitor asks their system for less motion, the looping animation collapses to a still frame.<\\\/p>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t\\t<div class=\\\"khpld-card\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-card__icon\\\"><?php khpld_icon( 'sliders' ); ?><\\\/span>\\n\\t\\t\\t\\t\\t<h3 class=\\\"khpld-card__title\\\">Timing You Control<\\\/h3>\\n\\t\\t\\t\\t\\t<p class=\\\"khpld-card__text\\\">Minimum display time, maximum timeout and fade-out duration are all yours to set.<\\\/p>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t<\\\/div>\\n\\t\\t<\\\/div>\\n\\t<\\\/section>\\n\\n\\t<!-- ================================================== 9. DETAILS -->\\n\\t<section class=\\\"khpld-section\\\">\\n\\t\\t<div class=\\\"khpld-shell\\\">\\n\\t\\t\\t<div class=\\\"khpld-section__head\\\">\\n\\t\\t\\t\\t<p class=\\\"khpld-eyebrow\\\">Finishing touches<\\\/p>\\n\\t\\t\\t\\t<h2 class=\\\"khpld-h2\\\">Small details. Better polish.<\\\/h2>\\n\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t<div class=\\\"khpld-cards\\\">\\n\\t\\t\\t\\t<div class=\\\"khpld-card\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-card__icon\\\"><?php khpld_icon( 'message' ); ?><\\\/span>\\n\\t\\t\\t\\t\\t<h3 class=\\\"khpld-card__title\\\">Loading Message Rotator<\\\/h3>\\n\\t\\t\\t\\t\\t<p class=\\\"khpld-card__text\\\">Up to six short messages fade through in place of a single fixed tagline.<\\\/p>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t\\t<div class=\\\"khpld-card\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-card__icon\\\"><?php khpld_icon( 'brand' ); ?><\\\/span>\\n\\t\\t\\t\\t\\t<h3 class=\\\"khpld-card__title\\\">Completion Pulse<\\\/h3>\\n\\t\\t\\t\\t\\t<p class=\\\"khpld-card__text\\\">An optional beat on the logo the moment loading finishes, just before the exit begins.<\\\/p>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t\\t<div class=\\\"khpld-card\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-card__icon\\\"><?php khpld_icon( 'sliders' ); ?><\\\/span>\\n\\t\\t\\t\\t\\t<h3 class=\\\"khpld-card__title\\\">Timing Presets<\\\/h3>\\n\\t\\t\\t\\t\\t<p class=\\\"khpld-card__text\\\">Sensible starting points for minimum display and fade-out, adjustable afterwards.<\\\/p>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t\\t<div class=\\\"khpld-card\\\">\\n\\t\\t\\t\\t\\t<span class=\\\"khpld-card__icon\\\"><?php khpld_icon( 'motion' ); ?><\\\/span>\\n\\t\\t\\t\\t\\t<h3 class=\\\"khpld-card__title\\\">Logo &amp; Tagline Treatment<\\\/h3>\\n\\t\\t\\t\\t\\t<p class=\\\"khpld-card__text\\\">Shape the mark as original, rounded or a circle, add a brand ring, and space the tagline to taste.<\\\/p>\\n\\t\\t\\t\\t<\\\/div>\\n\\t\\t\\t<\\\/div>\\n\\t\\t<\\\/div>\\n\\t<\\\/section>\\n\\n\\t<!-- ====================================================== 10. CTA -->\\n\\t<section class=\\\"khpld-section\\\" style=\\\"border-top:0\\\">\\n\\t\\t<div class=\\\"khpld-shell\\\">\\n\\t\\t\\t<div class=\\\"khpld-cta\\\">\\n\\t\\t\\t\\t<p class=\\\"khpld-eyebrow\\\" style=\\\"justify-content:center\\\">Put it together<\\\/p>\\n\\t\\t\\t\\t<h2 class=\\\"khpld-h2\\\">Ready before the page even begins.<\\\/h2>\\n\\t\\t\\t\\t<p class=\\\"khpld-lede\\\" style=\\\"margin:0 auto;max-width:60ch\\\">\\n\\t\\t\\t\\t\\tThis is the combination you picked above. Apply it and the page will\\n\\t\\t\\t\\t\\treload with the real Page Loader running your settings &mdash; not a\\n\\t\\t\\t\\t\\tpreview of them.\\n\\t\\t\\t\\t<\\\/p>\\n\\n\\t\\t\\t\\t<div class=\\\"khpld-stage-wrap\\\" style=\\\"max-width:660px;margin:38px auto 0\\\">\\n\\t\\t\\t\\t\\t<?php\\n\\t\\t\\t\\t\\tkhpld_stage(\\n\\t\\t\\t\\t\\t\\tarray(\\n\\t\\t\\t\\t\\t\\t\\t'id'       => 'khpld-stage-final',\\n\\t\\t\\t\\t\\t\\t\\t'class'    => 'khpld-stage--wide',\\n\\t\\t\\t\\t\\t\\t\\t'power'    => 'balanced',\\n\\t\\t\\t\\t\\t\\t\\t'progress' => 'logo-ring',\\n\\t\\t\\t\\t\\t\\t\\t'exit'     => 'circle-reveal',\\n\\t\\t\\t\\t\\t\\t\\t'reveal'   => 'blur-sharp',\\n\\t\\t\\t\\t\\t\\t\\t\\\/\\\/ Solid by default: this is the closing hero shot, and a\\n\\t\\t\\t\\t\\t\\t\\t\\\/\\\/ translucent cover over the pale faux page reads muddy\\n\\t\\t\\t\\t\\t\\t\\t\\\/\\\/ rather than premium. Choosing a cover above still\\n\\t\\t\\t\\t\\t\\t\\t\\\/\\\/ mirrors onto this stage.\\n\\t\\t\\t\\t\\t\\t\\t'cover'    => 'solid',\\n\\t\\t\\t\\t\\t\\t\\t'effect'   => $khpld_default_effect,\\n\\t\\t\\t\\t\\t\\t\\t'status'   => 'khpld-stage-final-status',\\n\\t\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\tkhpld_replay( 'khpld-stage-final' );\\n\\t\\t\\t\\t\\t?>\\n\\t\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t\\t<div class=\\\"khpld-actions\\\">\\n\\t\\t\\t\\t\\t<?php if ( current_user_can( 'manage_options' ) ) : ?>\\n\\t\\t\\t\\t\\t<button type=\\\"button\\\" class=\\\"khpld-btn khpld-btn--primary\\\" id=\\\"khpld-apply\\\">\\n\\t\\t\\t\\t\\t\\t<?php khpld_icon( 'flash' ); ?>\\n\\t\\t\\t\\t\\t\\tApply this to the site\\n\\t\\t\\t\\t\\t<\\\/button>\\n\\t\\t\\t\\t\\t<a class=\\\"khpld-btn\\\" href=\\\"<?php echo esc_url( admin_url( 'options-general.php?page=kinetichub-page-loader' ) ); ?>\\\">\\n\\t\\t\\t\\t\\t\\t<?php khpld_icon( 'sliders' ); ?>\\n\\t\\t\\t\\t\\t\\tOpen the settings\\n\\t\\t\\t\\t\\t<\\\/a>\\n\\t\\t\\t\\t\\t<?php endif; ?>\\n\\t\\t\\t\\t\\t<a class=\\\"khpld-btn\\\" href=\\\"<?php echo esc_url( 'https:\\\/\\\/wordpress.org\\\/plugins\\\/kinetichub-page-loader\\\/' ); ?>\\\" target=\\\"_blank\\\" rel=\\\"noopener noreferrer\\\">\\n\\t\\t\\t\\t\\t\\tView on WordPress.org\\n\\t\\t\\t\\t\\t<\\\/a>\\n\\t\\t\\t\\t<\\\/div>\\n\\n\\t\\t\\t\\t<p class=\\\"khpld-apply-status\\\" id=\\\"khpld-apply-status\\\" role=\\\"status\\\" aria-live=\\\"polite\\\"><\\\/p>\\n\\t\\t\\t<\\\/div>\\n\\t\\t<\\\/div>\\n\\t<\\\/section>\\n\\n\\t<footer class=\\\"khpld-foot\\\">\\n\\t\\t<div class=\\\"khpld-shell\\\">\\n\\t\\t\\tKineticHub Page Loader &mdash; a free WordPress plugin.\\n\\t\\t\\tEvery stage on this page is a scaled preview; the loader you saw on arrival is the real one.\\n\\t\\t<\\\/div>\\n\\t<\\\/footer>\\n\\n<\\\/main>\\n\\n<?php wp_footer(); ?>\\n<\\\/body>\\n<\\\/html>\\n\"},{\"step\":\"writeFile\",\"path\":\"\\\/wordpress\\\/wp-content\\\/mu-plugins\\\/khpl-demo\\\/demo.css\",\"data\":\"\\\/* =============================================================================\\n   KineticHub Page Loader - Playground demo styles\\n\\n   Loaded only on the demo landing page, by the khpl-demo mu-plugin that the\\n   Playground blueprint writes. Every selector is namespaced .khpld- so nothing\\n   here can reach the plugin's own frontend loader (.khpl-), the admin screen,\\n   or the theme. This file never ships inside the plugin.\\n   ============================================================================= *\\\/\\n\\n.khpld {\\n\\t--khpld-bg: #050b14;\\n\\t--khpld-bg-2: #07111f;\\n\\t--khpld-panel: #081827;\\n\\t--khpld-panel-soft: #0b1f34;\\n\\n\\t--khpld-cyan: #00d5ff;\\n\\t--khpld-blue: #2f7dff;\\n\\t--khpld-purple: #8b5cf6;\\n\\t--khpld-violet: #a855f7;\\n\\t--khpld-green: #28d77b;\\n\\n\\t--khpld-text: #f8fbff;\\n\\t--khpld-text-2: #d8e6f7;\\n\\t--khpld-muted: #8fa6bf;\\n\\n\\t--khpld-border: rgba(130, 190, 255, .16);\\n\\t--khpld-border-strong: rgba(0, 213, 255, .34);\\n\\n\\t--khpld-r-lg: 22px;\\n\\t--khpld-r-md: 16px;\\n\\t--khpld-r-sm: 11px;\\n\\n\\t\\\/* Written by demo.js per stage. Defaults keep the stage sane with no JS. *\\\/\\n\\t--khpld-motion: 1;\\n\\t--khpld-glow: 0;\\n\\t--khpld-progress: 0;\\n\\n\\tbox-sizing: border-box;\\n\\tmargin: 0;\\n\\tpadding: 0;\\n\\tcolor: var(--khpld-text);\\n\\tbackground:\\n\\t\\tradial-gradient(circle at 15% 5%, rgba(0, 213, 255, .12), transparent 30%),\\n\\t\\tradial-gradient(circle at 85% 15%, rgba(139, 92, 246, .14), transparent 34%),\\n\\t\\tlinear-gradient(145deg, #050b14, #07111f 48%, #050b14);\\n\\tfont-family: -apple-system, BlinkMacSystemFont, \\\"Segoe UI\\\", Roboto, Oxygen-Sans, Ubuntu, Cantarell, \\\"Helvetica Neue\\\", sans-serif;\\n\\tfont-size: 16px;\\n\\tline-height: 1.6;\\n\\t-webkit-font-smoothing: antialiased;\\n\\toverflow-x: hidden;\\n}\\n\\n.khpld *,\\n.khpld *::before,\\n.khpld *::after {\\n\\tbox-sizing: border-box;\\n}\\n\\n.khpld img {\\n\\tmax-width: 100%;\\n\\theight: auto;\\n}\\n\\n\\\/* ---------- Layout primitives ---------- *\\\/\\n\\n.khpld-shell {\\n\\twidth: 100%;\\n\\tmax-width: 1180px;\\n\\tmargin: 0 auto;\\n\\tpadding: 0 28px;\\n}\\n\\n.khpld-section {\\n\\tposition: relative;\\n\\tpadding: 92px 0;\\n\\tborder-top: 1px solid var(--khpld-border);\\n}\\n\\n.khpld-section:first-of-type {\\n\\tborder-top: 0;\\n}\\n\\n.khpld-section__head {\\n\\tmax-width: 720px;\\n\\tmargin: 0 0 44px;\\n}\\n\\n.khpld-section__head--center {\\n\\tmargin-left: auto;\\n\\tmargin-right: auto;\\n\\ttext-align: center;\\n}\\n\\n.khpld-eyebrow {\\n\\tdisplay: inline-flex;\\n\\talign-items: center;\\n\\tgap: 9px;\\n\\tmargin: 0 0 16px;\\n\\tfont-size: 12px;\\n\\tfont-weight: 700;\\n\\tletter-spacing: .16em;\\n\\ttext-transform: uppercase;\\n\\tcolor: var(--khpld-cyan);\\n}\\n\\n.khpld-eyebrow::before {\\n\\tcontent: '';\\n\\twidth: 22px;\\n\\theight: 1px;\\n\\tbackground: linear-gradient(90deg, transparent, var(--khpld-cyan));\\n}\\n\\n.khpld-section__head--center .khpld-eyebrow::before {\\n\\tdisplay: none;\\n}\\n\\n.khpld-h2 {\\n\\tmargin: 0 0 16px;\\n\\tfont-size: clamp(28px, 3.4vw, 42px);\\n\\tfont-weight: 800;\\n\\tline-height: 1.14;\\n\\tletter-spacing: -.02em;\\n\\tcolor: var(--khpld-text);\\n}\\n\\n.khpld-lede {\\n\\tmargin: 0;\\n\\tfont-size: 17px;\\n\\tline-height: 1.65;\\n\\tcolor: var(--khpld-muted);\\n}\\n\\n.khpld-note {\\n\\tmargin: 18px 0 0;\\n\\tfont-size: 13.5px;\\n\\tline-height: 1.6;\\n\\tcolor: var(--khpld-muted);\\n}\\n\\n\\\/* ---------- Hero ---------- *\\\/\\n\\n.khpld-hero {\\n\\tposition: relative;\\n\\toverflow: hidden;\\n\\tpadding: 104px 0 96px;\\n}\\n\\n.khpld-hero::before {\\n\\tcontent: '';\\n\\tposition: absolute;\\n\\ttop: -260px;\\n\\tright: -180px;\\n\\twidth: 620px;\\n\\theight: 620px;\\n\\tborder: 1px solid rgba(0, 213, 255, .10);\\n\\tborder-radius: 50%;\\n\\tbox-shadow: 0 0 0 60px rgba(0, 213, 255, .022);\\n\\tpointer-events: none;\\n}\\n\\n.khpld-hero__grid {\\n\\tdisplay: grid;\\n\\tgrid-template-columns: minmax(0, 1fr) minmax(0, 500px);\\n\\tgap: 56px;\\n\\talign-items: center;\\n}\\n\\n.khpld-hero__title {\\n\\tmargin: 0 0 20px;\\n\\tfont-size: clamp(36px, 5.2vw, 62px);\\n\\tfont-weight: 800;\\n\\tline-height: 1.06;\\n\\tletter-spacing: -.03em;\\n\\tcolor: var(--khpld-text);\\n}\\n\\n\\\/* \\\"first second\\\" carries the brand gradient. Flat cyan is declared first so an\\n   engine without background-clip painting shows colour rather than nothing. *\\\/\\n.khpld-hero__accent {\\n\\tcolor: var(--khpld-cyan);\\n}\\n\\n@supports ((-webkit-background-clip: text) or (background-clip: text)) {\\n\\t.khpld-hero__accent {\\n\\t\\tbackground-image: linear-gradient(112deg, #00d5ff 0%, #2f7dff 52%, #a855f7 100%);\\n\\t\\t-webkit-background-clip: text;\\n\\t\\tbackground-clip: text;\\n\\t\\t-webkit-text-fill-color: transparent;\\n\\t}\\n}\\n\\n.khpld-hero__lede {\\n\\tmax-width: 56ch;\\n\\tmargin: 0 0 30px;\\n\\tfont-size: 18px;\\n\\tline-height: 1.62;\\n\\tcolor: var(--khpld-text-2);\\n}\\n\\n.khpld-hero__brand {\\n\\tdisplay: inline-flex;\\n\\talign-items: center;\\n\\tgap: 13px;\\n\\tmargin: 0 0 26px;\\n}\\n\\n.khpld-hero__brand img {\\n\\twidth: 42px;\\n\\theight: 42px;\\n\\tborder-radius: 12px;\\n}\\n\\n.khpld-hero__brand-name {\\n\\tfont-size: 13px;\\n\\tfont-weight: 700;\\n\\tletter-spacing: .14em;\\n\\ttext-transform: uppercase;\\n\\tcolor: var(--khpld-muted);\\n}\\n\\n\\\/* ---------- Chips ---------- *\\\/\\n\\n.khpld-chips {\\n\\tdisplay: flex;\\n\\tflex-wrap: wrap;\\n\\tgap: 10px;\\n\\tmargin: 0;\\n\\tpadding: 0;\\n\\tlist-style: none;\\n}\\n\\n.khpld-chip {\\n\\tdisplay: inline-flex;\\n\\talign-items: center;\\n\\tgap: 8px;\\n\\tpadding: 8px 14px;\\n\\tfont-size: 13px;\\n\\tfont-weight: 600;\\n\\tcolor: var(--khpld-text-2);\\n\\tbackground: rgba(5, 11, 20, .6);\\n\\tborder: 1px solid var(--khpld-border);\\n\\tborder-radius: 999px;\\n}\\n\\n.khpld-chip svg {\\n\\twidth: 15px;\\n\\theight: 15px;\\n\\tcolor: var(--khpld-cyan);\\n\\tflex-shrink: 0;\\n}\\n\\n\\\/* ---------- Buttons ---------- *\\\/\\n\\n.khpld-btn {\\n\\tdisplay: inline-flex;\\n\\talign-items: center;\\n\\tjustify-content: center;\\n\\tgap: 9px;\\n\\tpadding: 13px 22px;\\n\\tfont: inherit;\\n\\tfont-size: 15px;\\n\\tfont-weight: 700;\\n\\tline-height: 1.2;\\n\\ttext-decoration: none;\\n\\tcolor: var(--khpld-text);\\n\\tbackground: rgba(5, 11, 20, .62);\\n\\tborder: 1px solid rgba(130, 190, 255, .24);\\n\\tborder-radius: 12px;\\n\\tcursor: pointer;\\n\\ttransition: color .18s ease, background-color .18s ease, border-color .18s ease, transform .18s ease;\\n}\\n\\n.khpld-btn:hover {\\n\\tcolor: #fff;\\n\\tbackground: rgba(0, 213, 255, .08);\\n\\tborder-color: var(--khpld-cyan);\\n}\\n\\n.khpld-btn:focus-visible {\\n\\toutline: 2px solid var(--khpld-cyan);\\n\\toutline-offset: 3px;\\n}\\n\\n.khpld-btn svg {\\n\\twidth: 17px;\\n\\theight: 17px;\\n\\tflex-shrink: 0;\\n}\\n\\n.khpld-btn--primary {\\n\\tcolor: #fff;\\n\\tbackground: linear-gradient(135deg, #00d5ff 0%, #2f7dff 55%, #8b5cf6 100%);\\n\\tborder-color: rgba(255, 255, 255, .18);\\n\\tbox-shadow: 0 12px 30px rgba(47, 125, 255, .26);\\n}\\n\\n.khpld-btn--primary:hover {\\n\\tcolor: #fff;\\n\\tbackground: linear-gradient(135deg, #00d5ff 0%, #2f7dff 55%, #8b5cf6 100%);\\n\\tborder-color: rgba(255, 255, 255, .3);\\n\\tfilter: brightness(1.08);\\n\\ttransform: translateY(-1px);\\n}\\n\\n.khpld-actions {\\n\\tdisplay: flex;\\n\\tflex-wrap: wrap;\\n\\tgap: 12px;\\n\\talign-items: center;\\n}\\n\\n\\\/* ---------- Stage: a mini viewport with the loader over it ----------\\n\\n   Mirrors the real loader's structure and class model at small scale. Class\\n   names are .khpld-stage__* so the plugin's own .khpl- rules cannot reach in,\\n   and nothing here is ever position:fixed - a stage can never cover the page.\\n   -------------------------------------------------------------------------- *\\\/\\n\\n.khpld-stage {\\n\\tposition: relative;\\n\\twidth: 100%;\\n\\taspect-ratio: 16 \\\/ 11;\\n\\toverflow: hidden;\\n\\tcontain: paint;\\n\\tbackground: #0a1626;\\n\\tborder: 1px solid rgba(130, 190, 255, .2);\\n\\tborder-radius: var(--khpld-r-md);\\n\\tbox-shadow:\\n\\t\\t0 0 0 1px rgba(0, 213, 255, .07),\\n\\t\\t0 26px 60px rgba(0, 0, 0, .5);\\n}\\n\\n.khpld-stage--tall {\\n\\taspect-ratio: 16 \\\/ 12;\\n}\\n\\n.khpld-stage--wide {\\n\\taspect-ratio: 16 \\\/ 9;\\n}\\n\\n\\\/* --- the faux page behind the loader --- *\\\/\\n\\n.khpld-stage__page {\\n\\tposition: absolute;\\n\\tinset: 0;\\n\\tdisplay: flex;\\n\\tflex-direction: column;\\n\\tgap: 10px;\\n\\tpadding: 16px;\\n\\tbackground: linear-gradient(180deg, #ffffff, #eef2f7);\\n\\ttransition:\\n\\t\\topacity calc(560ms * var(--khpld-motion)) ease,\\n\\t\\tfilter calc(560ms * var(--khpld-motion)) ease,\\n\\t\\ttransform calc(560ms * var(--khpld-motion)) cubic-bezier(.22, 1, .36, 1);\\n}\\n\\n.khpld-stage__page-bar {\\n\\theight: 15px;\\n\\tborder-radius: 4px;\\n\\tbackground: #cfd6de;\\n}\\n\\n.khpld-stage__page-line {\\n\\theight: 7px;\\n\\tborder-radius: 4px;\\n\\tbackground: #dfe4ea;\\n}\\n\\n.khpld-stage__page-line--short {\\n\\twidth: 58%;\\n}\\n\\n.khpld-stage__page-block {\\n\\tflex: 1 1 auto;\\n\\tmin-height: 34px;\\n\\tborder-radius: 8px;\\n\\tbackground: linear-gradient(135deg, #dbe3ec, #e9edf3);\\n}\\n\\n\\\/* Page-reveal pre-states, held only while the loader is covering. *\\\/\\n.khpld-stage.is-covering.khpld-reveal-soft-fade .khpld-stage__page { opacity: 0; }\\n.khpld-stage.is-covering.khpld-reveal-blur-sharp .khpld-stage__page { opacity: .5; filter: blur(7px); }\\n.khpld-stage.is-covering.khpld-reveal-lift-in .khpld-stage__page { opacity: 0; transform: translateY(18px); }\\n.khpld-stage.is-covering.khpld-reveal-gentle-scale .khpld-stage__page { opacity: 0; transform: scale(.95); }\\n\\n\\\/* --- the loader --- *\\\/\\n\\n.khpld-stage__loader {\\n\\tposition: absolute;\\n\\tinset: 0;\\n\\tdisplay: flex;\\n\\talign-items: center;\\n\\tjustify-content: center;\\n\\tbackground: #0f172a;\\n\\topacity: 1;\\n\\ttransition:\\n\\t\\topacity calc(600ms * var(--khpld-motion)) ease,\\n\\t\\ttransform calc(600ms * var(--khpld-motion)) cubic-bezier(.65, 0, .35, 1),\\n\\t\\tfilter calc(600ms * var(--khpld-motion)) ease,\\n\\t\\tclip-path calc(600ms * var(--khpld-motion)) cubic-bezier(.65, 0, .35, 1);\\n}\\n\\n\\\/* Cover modes. The alpha comes from a single token so one rule serves all. *\\\/\\n.khpld-cover-soft-overlay .khpld-stage__loader,\\n.khpld-cover-blur-page .khpld-stage__loader,\\n.khpld-cover-glass .khpld-stage__loader {\\n\\tbackground: rgba(15, 23, 42, .82);\\n}\\n\\n.khpld-cover-blur-page .khpld-stage__loader {\\n\\t-webkit-backdrop-filter: blur(6px);\\n\\tbackdrop-filter: blur(6px);\\n}\\n\\n.khpld-cover-glass .khpld-stage__loader {\\n\\tbackground: rgba(15, 23, 42, .62);\\n\\t-webkit-backdrop-filter: blur(11px) saturate(1.4);\\n\\tbackdrop-filter: blur(11px) saturate(1.4);\\n}\\n\\n.khpld-stage__inner {\\n\\tposition: relative;\\n\\tdisplay: flex;\\n\\tflex-direction: column;\\n\\talign-items: center;\\n\\tgap: 12px;\\n\\twidth: 100%;\\n\\tpadding: 0 24px;\\n}\\n\\n.khpld-stage__media {\\n\\tposition: relative;\\n\\tdisplay: flex;\\n\\talign-items: center;\\n\\tjustify-content: center;\\n\\twidth: 84px;\\n\\theight: 84px;\\n}\\n\\n.khpld-stage__logo {\\n\\tdisplay: block;\\n\\twidth: 60px;\\n\\theight: 60px;\\n\\tborder-radius: 50%;\\n}\\n\\n.khpld-stage__tagline {\\n\\tfont-size: 12.5px;\\n\\tfont-weight: 600;\\n\\tletter-spacing: .02em;\\n\\tcolor: #cbd5e1;\\n\\ttext-align: center;\\n}\\n\\n\\\/* --- decorative ring --- *\\\/\\n\\n.khpld-stage__ring {\\n\\tposition: absolute;\\n\\tinset: 0;\\n\\tborder-radius: 50%;\\n\\tborder: 2px solid rgba(0, 213, 255, .22);\\n\\tborder-top-color: var(--khpld-cyan);\\n\\tanimation: khpld-spin calc(1.5s * var(--khpld-motion)) linear infinite;\\n}\\n\\n@keyframes khpld-spin {\\n\\tto { transform: rotate(360deg); }\\n}\\n\\n\\\/* --- accent bloom, scaled by the KineticPower profile --- *\\\/\\n\\n.khpld-stage__inner::after {\\n\\tcontent: '';\\n\\tposition: absolute;\\n\\tleft: 50%;\\n\\ttop: 34%;\\n\\twidth: 190px;\\n\\theight: 190px;\\n\\ttransform: translate(-50%, -50%);\\n\\tborder-radius: 50%;\\n\\tbackground: radial-gradient(circle, rgba(0, 213, 255, .5), transparent 62%);\\n\\topacity: var(--khpld-glow);\\n\\tpointer-events: none;\\n\\ttransition: opacity calc(500ms * var(--khpld-motion)) ease;\\n}\\n\\n\\\/* --- KineticPower profiles ---\\n   Each profile only retunes pacing and bloom; it never swaps the visual. *\\\/\\n\\n.khpld-power-ultra-minimal .khpld-stage__ring {\\n\\tanimation: none;\\n\\tborder-top-color: rgba(0, 213, 255, .22);\\n}\\n\\n.khpld-power-signature-glow .khpld-stage__tagline {\\n\\ttext-shadow: 0 0 16px rgba(0, 213, 255, .55);\\n}\\n\\n\\\/* --- logo effects --- *\\\/\\n\\n.khpld-stage.is-covering.khpld-effect-fade .khpld-stage__media {\\n\\tanimation: khpld-fade calc(.85s * var(--khpld-motion)) ease both;\\n}\\n\\n.khpld-stage.is-covering.khpld-effect-soft-scale .khpld-stage__media {\\n\\tanimation: khpld-scale calc(.75s * var(--khpld-motion)) cubic-bezier(.22, 1, .36, 1) both;\\n}\\n\\n.khpld-stage.is-covering.khpld-effect-zoom-bloom .khpld-stage__media {\\n\\tanimation: khpld-bloom calc(1.05s * var(--khpld-motion)) cubic-bezier(.22, 1, .36, 1) both;\\n}\\n\\n.khpld-stage.is-covering.khpld-effect-grayscale-reveal .khpld-stage__logo {\\n\\tanimation: khpld-gray calc(1.9s * var(--khpld-motion)) ease both;\\n}\\n\\n.khpld-stage.is-covering.khpld-effect-mask-reveal .khpld-stage__media {\\n\\tanimation: khpld-mask calc(1.1s * var(--khpld-motion)) cubic-bezier(.22, 1, .36, 1) both;\\n}\\n\\n.khpld-stage.is-covering.khpld-effect-shine-sweep .khpld-stage__media {\\n\\tanimation: khpld-fade calc(.85s * var(--khpld-motion)) ease both;\\n}\\n\\n.khpld-stage__shine {\\n\\tposition: absolute;\\n\\tinset: 0;\\n\\tdisplay: none;\\n\\toverflow: hidden;\\n\\tborder-radius: 50%;\\n\\tpointer-events: none;\\n}\\n\\n.khpld-effect-shine-sweep .khpld-stage__shine {\\n\\tdisplay: block;\\n}\\n\\n.khpld-stage.is-covering.khpld-effect-shine-sweep .khpld-stage__shine::before {\\n\\tcontent: '';\\n\\tposition: absolute;\\n\\ttop: 0;\\n\\tbottom: 0;\\n\\twidth: 46%;\\n\\tbackground: linear-gradient(100deg, transparent, rgba(255, 255, 255, .55), transparent);\\n\\tanimation: khpld-sweep calc(1.5s * var(--khpld-motion)) ease both;\\n}\\n\\n@keyframes khpld-fade  { from { opacity: 0; } to { opacity: 1; } }\\n@keyframes khpld-scale { from { opacity: 0; transform: scale(.86); } to { opacity: 1; transform: none; } }\\n@keyframes khpld-bloom { 0% { opacity: 0; transform: scale(.62); } 60% { opacity: 1; transform: scale(1.06); } 100% { opacity: 1; transform: none; } }\\n@keyframes khpld-gray  { 0% { filter: grayscale(1); opacity: .55; } 100% { filter: none; opacity: 1; } }\\n@keyframes khpld-mask  { from { opacity: 0; clip-path: inset(0 0 100% 0); } to { opacity: 1; clip-path: inset(0 0 0 0); } }\\n@keyframes khpld-sweep { from { transform: translateX(-160%); } to { transform: translateX(320%); } }\\n\\n\\\/* --- progress --- *\\\/\\n\\n.khpld-stage__track,\\n.khpld-stage__glow,\\n.khpld-stage__percent,\\n.khpld-stage__ringbar {\\n\\tdisplay: none;\\n}\\n\\n.khpld-stage__track {\\n\\tposition: absolute;\\n\\tleft: 0;\\n\\tright: 0;\\n\\theight: 3px;\\n\\tbackground: rgba(255, 255, 255, .12);\\n\\tz-index: 2;\\n}\\n\\n.khpld-progress-top-bar .khpld-stage__track { display: block; top: 0; }\\n.khpld-progress-bottom-line .khpld-stage__track { display: block; bottom: 0; }\\n\\n.khpld-stage__bar {\\n\\tdisplay: block;\\n\\twidth: 100%;\\n\\theight: 100%;\\n\\ttransform: scaleX(var(--khpld-progress));\\n\\ttransform-origin: 0 50%;\\n\\tbackground: linear-gradient(90deg, var(--khpld-cyan), var(--khpld-blue));\\n\\ttransition: transform .22s ease;\\n}\\n\\n.khpld-stage__glow {\\n\\tposition: relative;\\n\\twidth: 168px;\\n\\theight: 2px;\\n\\toverflow: hidden;\\n\\tborder-radius: 2px;\\n\\tbackground: rgba(255, 255, 255, .1);\\n}\\n\\n.khpld-progress-center-glow .khpld-stage__glow { display: block; }\\n\\n.khpld-stage__glow .khpld-stage__bar {\\n\\tbox-shadow: 0 0 16px rgba(0, 213, 255, .75);\\n}\\n\\n.khpld-stage__percent {\\n\\tfont-size: 12px;\\n\\tfont-weight: 700;\\n\\tfont-variant-numeric: tabular-nums;\\n\\tcolor: var(--khpld-cyan);\\n}\\n\\n.khpld-progress-minimal-percent .khpld-stage__percent { display: block; }\\n\\n.khpld-stage__ringbar {\\n\\tposition: absolute;\\n\\tinset: 0;\\n\\ttransform: rotate(-90deg);\\n}\\n\\n.khpld-progress-logo-ring .khpld-stage__ringbar { display: block; }\\n\\n.khpld-stage__ringbar circle {\\n\\tfill: none;\\n\\tstroke-width: 5;\\n\\tcx: 50;\\n\\tcy: 50;\\n\\tr: 46;\\n}\\n\\n.khpld-stage__ringbar-track {\\n\\tstroke: rgba(0, 213, 255, .16);\\n}\\n\\n.khpld-stage__ringbar-bar {\\n\\tstroke: var(--khpld-cyan);\\n\\tstroke-linecap: round;\\n\\tstroke-dasharray: 289;\\n\\tstroke-dashoffset: calc(289 - (289 * var(--khpld-progress)));\\n\\ttransition: stroke-dashoffset .22s ease;\\n}\\n\\n\\\/* The logo ring replaces the decorative spinner, exactly as it does live. *\\\/\\n.khpld-progress-logo-ring .khpld-stage__ring {\\n\\tdisplay: none;\\n}\\n\\n\\\/* --- completion pulse --- *\\\/\\n\\n.khpld-stage.is-complete .khpld-stage__media {\\n\\tanimation: khpld-pulse calc(.5s * var(--khpld-motion)) ease;\\n}\\n\\n@keyframes khpld-pulse {\\n\\t50% { transform: scale(1.07); }\\n}\\n\\n\\\/* --- exits --- *\\\/\\n\\n.khpld-stage__curtain {\\n\\tposition: absolute;\\n\\ttop: 0;\\n\\tbottom: 0;\\n\\twidth: 50.5%;\\n\\tbackground: #0f172a;\\n\\topacity: 0;\\n\\tpointer-events: none;\\n\\ttransition: transform calc(620ms * var(--khpld-motion)) cubic-bezier(.65, 0, .35, 1);\\n}\\n\\n.khpld-stage__curtain--start { left: 0; }\\n.khpld-stage__curtain--end { right: 0; }\\n\\n.khpld-stage.is-exiting .khpld-stage__loader { opacity: 0; }\\n.khpld-stage.is-exiting.khpld-exit-slide-up .khpld-stage__loader { opacity: 1; transform: translateY(-100%); }\\n.khpld-stage.is-exiting.khpld-exit-blur-lift .khpld-stage__loader { filter: blur(9px); transform: translateY(-12px) scale(1.03); }\\n\\n.khpld-exit-circle-reveal .khpld-stage__loader { clip-path: circle(150% at 50% 50%); }\\n.khpld-stage.is-exiting.khpld-exit-circle-reveal .khpld-stage__loader { opacity: 1; clip-path: circle(0% at 50% 50%); }\\n\\n.khpld-stage.is-exiting.khpld-exit-split-curtain .khpld-stage__loader { opacity: 1; background: transparent; }\\n.khpld-stage.is-exiting.khpld-exit-split-curtain .khpld-stage__inner { opacity: 0; transition: opacity calc(320ms * var(--khpld-motion)) ease; }\\n.khpld-stage.is-exiting.khpld-exit-split-curtain .khpld-stage__curtain { opacity: 1; }\\n.khpld-stage.is-exiting.khpld-exit-split-curtain .khpld-stage__curtain--start { transform: translateX(-100%); }\\n.khpld-stage.is-exiting.khpld-exit-split-curtain .khpld-stage__curtain--end { transform: translateX(100%); }\\n\\n\\\/* Settled state once the cycle has finished. *\\\/\\n.khpld-stage.is-done .khpld-stage__loader {\\n\\topacity: 0;\\n\\tpointer-events: none;\\n}\\n\\n\\\/* ---------- Stage caption \\\/ replay ---------- *\\\/\\n\\n.khpld-stage-wrap {\\n\\tposition: relative;\\n}\\n\\n\\\/* A full-width stage on a 1440px screen leaves the loader marooned in a lot of\\n   empty space. The showcase stages are capped and centred so they read as a\\n   device rather than as a large empty panel. *\\\/\\n.khpld-stage-wrap--centered {\\n\\tmax-width: 860px;\\n\\tmargin-left: auto;\\n\\tmargin-right: auto;\\n}\\n\\n.khpld-stage-wrap--centered .khpld-stage-bar {\\n\\tjustify-content: center;\\n}\\n\\n.khpld-stage-bar {\\n\\tdisplay: flex;\\n\\talign-items: center;\\n\\tjustify-content: space-between;\\n\\tgap: 14px;\\n\\tflex-wrap: wrap;\\n\\tmargin-top: 16px;\\n}\\n\\n.khpld-stage-status {\\n\\tfont-size: 13px;\\n\\tfont-weight: 600;\\n\\tcolor: var(--khpld-muted);\\n}\\n\\n\\\/* ---------- Segmented radio selector ---------- *\\\/\\n\\n.khpld-seg {\\n\\tdisplay: grid;\\n\\tgrid-template-columns: repeat(auto-fit, minmax(178px, 1fr));\\n\\tgap: 12px;\\n\\tmargin: 0;\\n\\tpadding: 0;\\n\\tborder: 0;\\n}\\n\\n.khpld-seg--tight {\\n\\tgrid-template-columns: repeat(auto-fit, minmax(146px, 1fr));\\n}\\n\\n.khpld-seg__legend {\\n\\tpadding: 0;\\n\\tmargin: 0 0 14px;\\n\\tfont-size: 13px;\\n\\tfont-weight: 700;\\n\\tletter-spacing: .1em;\\n\\ttext-transform: uppercase;\\n\\tcolor: var(--khpld-muted);\\n}\\n\\n.khpld-opt {\\n\\tposition: relative;\\n\\tdisplay: block;\\n}\\n\\n.khpld-opt input {\\n\\tposition: absolute;\\n\\twidth: 1px;\\n\\theight: 1px;\\n\\tmargin: -1px;\\n\\tpadding: 0;\\n\\toverflow: hidden;\\n\\tclip: rect(0 0 0 0);\\n\\tclip-path: inset(50%);\\n\\twhite-space: nowrap;\\n\\tborder: 0;\\n}\\n\\n.khpld-opt__card {\\n\\tdisplay: flex;\\n\\tflex-direction: column;\\n\\tgap: 5px;\\n\\theight: 100%;\\n\\tpadding: 15px 16px 16px;\\n\\tbackground: rgba(5, 11, 20, .66);\\n\\tborder: 1px solid var(--khpld-border);\\n\\tborder-radius: var(--khpld-r-sm);\\n\\tcursor: pointer;\\n\\ttransition: border-color .18s ease, background-color .18s ease, box-shadow .18s ease;\\n}\\n\\n.khpld-opt__card:hover {\\n\\tborder-color: rgba(0, 213, 255, .32);\\n}\\n\\n.khpld-opt__name {\\n\\tdisplay: flex;\\n\\talign-items: center;\\n\\tgap: 8px;\\n\\tfont-size: 14.5px;\\n\\tfont-weight: 700;\\n\\tcolor: var(--khpld-text-2);\\n}\\n\\n\\\/* The tick is a shape, not a colour: selection stays legible to anyone who\\n   cannot separate the cyan border from the default one. *\\\/\\n.khpld-opt__tick {\\n\\tdisplay: flex;\\n\\talign-items: center;\\n\\tjustify-content: center;\\n\\twidth: 17px;\\n\\theight: 17px;\\n\\tflex-shrink: 0;\\n\\tborder: 1px solid rgba(130, 190, 255, .35);\\n\\tborder-radius: 50%;\\n}\\n\\n.khpld-opt__tick svg {\\n\\twidth: 11px;\\n\\theight: 11px;\\n\\topacity: 0;\\n\\tcolor: #050b14;\\n}\\n\\n.khpld-opt__desc {\\n\\tfont-size: 13px;\\n\\tline-height: 1.5;\\n\\tcolor: var(--khpld-muted);\\n}\\n\\n.khpld-opt input:checked + .khpld-opt__card {\\n\\tbackground: linear-gradient(180deg, rgba(0, 213, 255, .1), rgba(47, 125, 255, .05));\\n\\tborder-color: rgba(0, 213, 255, .7);\\n\\tbox-shadow:\\n\\t\\t0 0 0 1px rgba(0, 213, 255, .25),\\n\\t\\t0 0 30px rgba(0, 213, 255, .1);\\n}\\n\\n.khpld-opt input:checked + .khpld-opt__card .khpld-opt__name {\\n\\tcolor: #fff;\\n}\\n\\n.khpld-opt input:checked + .khpld-opt__card .khpld-opt__tick {\\n\\tbackground: var(--khpld-cyan);\\n\\tborder-color: var(--khpld-cyan);\\n}\\n\\n.khpld-opt input:checked + .khpld-opt__card .khpld-opt__tick svg {\\n\\topacity: 1;\\n}\\n\\n.khpld-opt input:focus-visible + .khpld-opt__card {\\n\\toutline: 2px solid var(--khpld-cyan);\\n\\toutline-offset: 3px;\\n}\\n\\n\\\/* ---------- Two-column feature layout ---------- *\\\/\\n\\n.khpld-split {\\n\\tdisplay: grid;\\n\\tgrid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\\n\\tgap: 48px;\\n\\talign-items: center;\\n}\\n\\n.khpld-split--stage-first .khpld-split__visual {\\n\\torder: -1;\\n}\\n\\n.khpld-cards {\\n\\tdisplay: grid;\\n\\tgrid-template-columns: repeat(auto-fit, minmax(268px, 1fr));\\n\\tgap: 16px;\\n}\\n\\n.khpld-card {\\n\\tpadding: 22px 22px 24px;\\n\\tbackground: linear-gradient(180deg, rgba(11, 31, 52, .8), rgba(7, 17, 31, .8));\\n\\tborder: 1px solid var(--khpld-border);\\n\\tborder-radius: var(--khpld-r-md);\\n}\\n\\n.khpld-card__icon {\\n\\tdisplay: flex;\\n\\talign-items: center;\\n\\tjustify-content: center;\\n\\twidth: 38px;\\n\\theight: 38px;\\n\\tmargin-bottom: 15px;\\n\\tcolor: var(--khpld-cyan);\\n\\tbackground: rgba(0, 213, 255, .1);\\n\\tborder: 1px solid rgba(0, 213, 255, .2);\\n\\tborder-radius: 11px;\\n}\\n\\n.khpld-card__icon svg {\\n\\twidth: 19px;\\n\\theight: 19px;\\n}\\n\\n.khpld-card__title {\\n\\tmargin: 0 0 8px;\\n\\tfont-size: 16px;\\n\\tfont-weight: 700;\\n\\tcolor: var(--khpld-text);\\n}\\n\\n.khpld-card__text {\\n\\tmargin: 0;\\n\\tfont-size: 14px;\\n\\tline-height: 1.6;\\n\\tcolor: var(--khpld-muted);\\n}\\n\\n\\\/* ---------- Reveal gallery (logo effects) ---------- *\\\/\\n\\n.khpld-gallery {\\n\\tdisplay: grid;\\n\\tgrid-template-columns: repeat(auto-fit, minmax(228px, 1fr));\\n\\tgap: 18px;\\n}\\n\\n.khpld-tile {\\n\\tdisplay: flex;\\n\\tflex-direction: column;\\n\\tgap: 0;\\n\\tpadding: 0;\\n\\toverflow: hidden;\\n\\tbackground: rgba(5, 11, 20, .6);\\n\\tborder: 1px solid var(--khpld-border);\\n\\tborder-radius: var(--khpld-r-md);\\n\\tcursor: pointer;\\n\\ttext-align: left;\\n\\tfont: inherit;\\n\\tcolor: inherit;\\n\\ttransition: border-color .18s ease, box-shadow .18s ease;\\n}\\n\\n.khpld-tile:hover {\\n\\tborder-color: rgba(0, 213, 255, .34);\\n}\\n\\n.khpld-tile:focus-visible {\\n\\toutline: 2px solid var(--khpld-cyan);\\n\\toutline-offset: 3px;\\n}\\n\\n.khpld-tile .khpld-stage {\\n\\tborder: 0;\\n\\tborder-radius: 0;\\n\\tbox-shadow: none;\\n\\taspect-ratio: 16 \\\/ 10;\\n}\\n\\n.khpld-tile__meta {\\n\\tpadding: 14px 16px 16px;\\n\\tborder-top: 1px solid var(--khpld-border);\\n}\\n\\n.khpld-tile__name {\\n\\tdisplay: flex;\\n\\talign-items: center;\\n\\tgap: 8px;\\n\\tfont-size: 14.5px;\\n\\tfont-weight: 700;\\n\\tcolor: var(--khpld-text);\\n}\\n\\n\\\/* Selected tile. Borrows the segmented selector's treatment rather than\\n   inventing a second one, so \\\"chosen\\\" reads the same everywhere on the page:\\n   a tick badge, a cyan edge, and aria-pressed underneath. *\\\/\\n.khpld-tile__tick {\\n\\tdisplay: flex;\\n\\talign-items: center;\\n\\tjustify-content: center;\\n\\twidth: 17px;\\n\\theight: 17px;\\n\\tflex-shrink: 0;\\n\\tborder: 1px solid rgba(130, 190, 255, .35);\\n\\tborder-radius: 50%;\\n}\\n\\n.khpld-tile__tick svg {\\n\\twidth: 11px;\\n\\theight: 11px;\\n\\topacity: 0;\\n\\tcolor: #050b14;\\n}\\n\\n.khpld-tile[aria-pressed=\\\"true\\\"] {\\n\\tborder-color: rgba(0, 213, 255, .7);\\n\\tbox-shadow:\\n\\t\\t0 0 0 1px rgba(0, 213, 255, .25),\\n\\t\\t0 0 30px rgba(0, 213, 255, .1);\\n}\\n\\n.khpld-tile[aria-pressed=\\\"true\\\"] .khpld-tile__tick {\\n\\tbackground: var(--khpld-cyan);\\n\\tborder-color: var(--khpld-cyan);\\n}\\n\\n.khpld-tile[aria-pressed=\\\"true\\\"] .khpld-tile__tick svg {\\n\\topacity: 1;\\n}\\n\\n.khpld-tile[aria-pressed=\\\"true\\\"] .khpld-tile__meta {\\n\\tbackground: linear-gradient(180deg, rgba(0, 213, 255, .08), rgba(47, 125, 255, .03));\\n}\\n\\n.khpld-tile__hint {\\n\\tdisplay: block;\\n\\tmargin-top: 3px;\\n\\tfont-size: 12.5px;\\n\\tcolor: var(--khpld-muted);\\n}\\n\\n\\\/* ---------- Final CTA ---------- *\\\/\\n\\n.khpld-cta {\\n\\tposition: relative;\\n\\toverflow: hidden;\\n\\tpadding: 76px 32px 80px;\\n\\tmargin: 0 0 96px;\\n\\ttext-align: center;\\n\\tbackground:\\n\\t\\tradial-gradient(circle at 50% 0%, rgba(0, 213, 255, .14), transparent 55%),\\n\\t\\tlinear-gradient(160deg, rgba(11, 31, 52, .9), rgba(5, 11, 20, .95));\\n\\tborder: 1px solid rgba(0, 213, 255, .2);\\n\\tborder-radius: var(--khpld-r-lg);\\n}\\n\\n.khpld-cta .khpld-actions {\\n\\tjustify-content: center;\\n\\tmargin-top: 30px;\\n}\\n\\n.khpld-apply-status {\\n\\tmargin: 18px 0 0;\\n\\tmin-height: 1.4em;\\n\\tfont-size: 13.5px;\\n\\tfont-weight: 600;\\n\\tcolor: var(--khpld-cyan);\\n}\\n\\n\\\/* ---------- Footer ---------- *\\\/\\n\\n.khpld-foot {\\n\\tpadding: 30px 0 56px;\\n\\tfont-size: 13px;\\n\\tcolor: var(--khpld-muted);\\n\\ttext-align: center;\\n\\tborder-top: 1px solid var(--khpld-border);\\n}\\n\\n.khpld-foot a {\\n\\tcolor: var(--khpld-cyan);\\n}\\n\\n\\\/* ---------- Responsive ---------- *\\\/\\n\\n@media (max-width: 1024px) {\\n\\t.khpld-hero__grid,\\n\\t.khpld-split {\\n\\t\\tgrid-template-columns: minmax(0, 1fr);\\n\\t\\tgap: 40px;\\n\\t}\\n\\n\\t.khpld-split--stage-first .khpld-split__visual {\\n\\t\\torder: 0;\\n\\t}\\n\\n\\t.khpld-hero {\\n\\t\\tpadding: 76px 0 68px;\\n\\t}\\n\\n\\t.khpld-section {\\n\\t\\tpadding: 72px 0;\\n\\t}\\n}\\n\\n@media (max-width: 768px) {\\n\\t.khpld-shell {\\n\\t\\tpadding: 0 20px;\\n\\t}\\n\\n\\t.khpld-section {\\n\\t\\tpadding: 58px 0;\\n\\t}\\n\\n\\t.khpld-hero {\\n\\t\\tpadding: 60px 0 56px;\\n\\t}\\n\\n\\t.khpld-hero::before {\\n\\t\\tdisplay: none;\\n\\t}\\n\\n\\t.khpld-cta {\\n\\t\\tpadding: 56px 22px 60px;\\n\\t}\\n}\\n\\n@media (max-width: 480px) {\\n\\t.khpld-shell {\\n\\t\\tpadding: 0 15px;\\n\\t}\\n\\n\\t.khpld-seg,\\n\\t.khpld-seg--tight {\\n\\t\\tgrid-template-columns: minmax(0, 1fr);\\n\\t}\\n\\n\\t.khpld-gallery,\\n\\t.khpld-cards {\\n\\t\\tgrid-template-columns: minmax(0, 1fr);\\n\\t}\\n\\n\\t.khpld-btn {\\n\\t\\twidth: 100%;\\n\\t}\\n\\n\\t.khpld-stage {\\n\\t\\taspect-ratio: 4 \\\/ 3;\\n\\t}\\n}\\n\\n\\\/* ---------- Reduced motion ----------\\n   Every animation on this page is decorative: it illustrates a setting that is\\n   also stated in text. Under a reduced-motion preference the stages hold their\\n   finished frame instead, and the replay buttons simply re-state it. *\\\/\\n@media (prefers-reduced-motion: reduce) {\\n\\t.khpld *,\\n\\t.khpld *::before,\\n\\t.khpld *::after {\\n\\t\\tanimation-duration: .01ms !important;\\n\\t\\tanimation-iteration-count: 1 !important;\\n\\t\\ttransition-duration: .01ms !important;\\n\\t\\tscroll-behavior: auto !important;\\n\\t}\\n\\n\\t.khpld-stage__ring {\\n\\t\\tanimation: none;\\n\\t\\tborder-top-color: rgba(0, 213, 255, .22);\\n\\t}\\n\\n\\t.khpld-btn--primary:hover {\\n\\t\\ttransform: none;\\n\\t}\\n}\\n\"},{\"step\":\"writeFile\",\"path\":\"\\\/wordpress\\\/wp-content\\\/mu-plugins\\\/khpl-demo\\\/demo.js\",\"data\":\"\\\/**\\n * KineticHub Page Loader - Playground demo controller.\\n *\\n * Drives the demo stages: each one plays a bounded cover -> progress -> exit ->\\n * page-reveal cycle and then stops. Nothing here loops forever, nothing is\\n * position:fixed, and no library is used - plain ES5-compatible DOM work,\\n * CSS classes, and three custom properties.\\n *\\n * This file is written by the Playground blueprint into an mu-plugin and never\\n * ships inside the plugin.\\n *\\\/\\n( function () {\\n\\t'use strict';\\n\\n\\tvar reduced = window.matchMedia && window.matchMedia( '(prefers-reduced-motion: reduce)' ).matches;\\n\\n\\t\\\/* KineticPower profiles. These mirror the pacing and bloom the real plugin\\n\\t   applies for each mode; they retune an existing look rather than replace\\n\\t   it, which is exactly what the setting does live. *\\\/\\n\\tvar POWER = {\\n\\t\\t'classic':        { motion: 1,    glow: 0,   hold: 2200 },\\n\\t\\t'ultra-minimal':  { motion: .55,  glow: 0,   hold: 1500 },\\n\\t\\t'calm':           { motion: 1.35, glow: .18, hold: 2800 },\\n\\t\\t'balanced':       { motion: 1,    glow: .26, hold: 2200 },\\n\\t\\t'dynamic':        { motion: .72,  glow: .34, hold: 1800 },\\n\\t\\t'signature-glow': { motion: 1.1,  glow: .6,  hold: 2600 }\\n\\t};\\n\\n\\tfunction classPrefixClear( el, prefix ) {\\n\\t\\tvar out = [];\\n\\t\\tvar list = el.className.split( \\\/\\\\s+\\\/ );\\n\\t\\tfor ( var i = 0; i < list.length; i++ ) {\\n\\t\\t\\tif ( list[ i ] && list[ i ].indexOf( prefix ) !== 0 ) {\\n\\t\\t\\t\\tout.push( list[ i ] );\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tel.className = out.join( ' ' );\\n\\t}\\n\\n\\t\\\/**\\n\\t * One demo stage.\\n\\t *\\n\\t * @param {HTMLElement} root Element carrying .khpld-stage.\\n\\t *\\\/\\n\\tfunction Stage( root ) {\\n\\t\\tthis.root = root;\\n\\t\\tthis.timers = [];\\n\\t\\tthis.raf = null;\\n\\t\\tthis.state = {\\n\\t\\t\\tpower:    root.getAttribute( 'data-power' )    || 'balanced',\\n\\t\\t\\tprogress: root.getAttribute( 'data-progress' ) || 'none',\\n\\t\\t\\texit:     root.getAttribute( 'data-exit' )     || 'fade',\\n\\t\\t\\treveal:   root.getAttribute( 'data-reveal' )   || 'soft-fade',\\n\\t\\t\\tcover:    root.getAttribute( 'data-cover' )    || 'solid',\\n\\t\\t\\teffect:   root.getAttribute( 'data-effect' )   || 'fade'\\n\\t\\t};\\n\\t\\tthis.percentEl = root.querySelector( '[data-khpld-percent]' );\\n\\t\\tthis.apply();\\n\\t\\tthis.reset();\\n\\n\\t\\t\\\/\\\/ Rest as a composed poster until this stage is actually played. A stage\\n\\t\\t\\\/\\\/ below the fold would otherwise sit at 0% - an empty ring and a blank\\n\\t\\t\\\/\\\/ readout - which reads as broken rather than as waiting. play() zeroes\\n\\t\\t\\\/\\\/ it again before animating.\\n\\t\\tthis.setProgress( 1 );\\n\\t}\\n\\n\\t\\\/** Writes the current state onto the element as classes and tokens. *\\\/\\n\\tStage.prototype.apply = function () {\\n\\t\\tvar s = this.state;\\n\\t\\tvar root = this.root;\\n\\n\\t\\t[ 'khpld-power-', 'khpld-progress-', 'khpld-exit-', 'khpld-reveal-', 'khpld-cover-', 'khpld-effect-' ]\\n\\t\\t\\t.forEach( function ( p ) { classPrefixClear( root, p ); } );\\n\\n\\t\\troot.classList.add( 'khpld-power-' + s.power );\\n\\t\\troot.classList.add( 'khpld-progress-' + s.progress );\\n\\t\\troot.classList.add( 'khpld-exit-' + s.exit );\\n\\t\\troot.classList.add( 'khpld-reveal-' + s.reveal );\\n\\t\\troot.classList.add( 'khpld-cover-' + s.cover );\\n\\t\\troot.classList.add( 'khpld-effect-' + s.effect );\\n\\n\\t\\tvar p = POWER[ s.power ] || POWER.balanced;\\n\\t\\troot.style.setProperty( '--khpld-motion', String( p.motion ) );\\n\\t\\troot.style.setProperty( '--khpld-glow', String( p.glow ) );\\n\\t};\\n\\n\\tStage.prototype.set = function ( key, value ) {\\n\\t\\tthis.state[ key ] = value;\\n\\t\\tthis.apply();\\n\\t\\tthis.play();\\n\\t};\\n\\n\\t\\\/** Same, but without replaying - used to mirror choices onto the CTA stage. *\\\/\\n\\tStage.prototype.setQuiet = function ( key, value ) {\\n\\t\\tthis.state[ key ] = value;\\n\\t\\tthis.apply();\\n\\t};\\n\\n\\tStage.prototype.clearTimers = function () {\\n\\t\\tfor ( var i = 0; i < this.timers.length; i++ ) {\\n\\t\\t\\tclearTimeout( this.timers[ i ] );\\n\\t\\t}\\n\\t\\tthis.timers = [];\\n\\t\\tif ( this.raf ) {\\n\\t\\t\\tcancelAnimationFrame( this.raf );\\n\\t\\t\\tthis.raf = null;\\n\\t\\t}\\n\\t};\\n\\n\\tStage.prototype.after = function ( ms, fn ) {\\n\\t\\tthis.timers.push( setTimeout( fn, ms ) );\\n\\t};\\n\\n\\tStage.prototype.setProgress = function ( value ) {\\n\\t\\tthis.root.style.setProperty( '--khpld-progress', String( value ) );\\n\\t\\tif ( this.percentEl ) {\\n\\t\\t\\tthis.percentEl.textContent = Math.round( value * 100 ) + '%';\\n\\t\\t}\\n\\t};\\n\\n\\tStage.prototype.reset = function () {\\n\\t\\tthis.clearTimers();\\n\\t\\tthis.root.classList.remove( 'is-exiting', 'is-complete', 'is-done' );\\n\\t\\tthis.root.classList.add( 'is-covering' );\\n\\t\\tthis.setProgress( 0 );\\n\\t};\\n\\n\\t\\\/**\\n\\t * Plays one bounded cycle.\\n\\t *\\n\\t * Progress is simulated - it eases toward roughly 94% and only completes\\n\\t * when the loader is ready to leave. That is how the plugin behaves too:\\n\\t * it is a pacing device, not a measurement of network transfer.\\n\\t *\\\/\\n\\tStage.prototype.play = function () {\\n\\t\\tvar self = this;\\n\\t\\tvar p = POWER[ this.state.power ] || POWER.balanced;\\n\\n\\t\\tthis.reset();\\n\\n\\t\\tif ( reduced ) {\\n\\t\\t\\t\\\/\\\/ Hold a composed still frame instead of animating - the same thing\\n\\t\\t\\t\\\/\\\/ the plugin itself does under a reduced-motion preference. Every\\n\\t\\t\\t\\\/\\\/ setting this page demonstrates is also stated in text, so nothing\\n\\t\\t\\t\\\/\\\/ is lost by not playing it.\\n\\t\\t\\tthis.setProgress( 1 );\\n\\t\\t\\tthis.signal( 'Still frame (reduced motion)' );\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\n\\t\\tvar hold = p.hold;\\n\\t\\tvar start = Date.now();\\n\\t\\tvar ceiling = 0.94;\\n\\n\\t\\tthis.signal( 'Loading' );\\n\\n\\t\\tfunction tick() {\\n\\t\\t\\tvar elapsed = Date.now() - start;\\n\\t\\t\\tvar t = Math.min( 1, elapsed \\\/ hold );\\n\\t\\t\\t\\\/\\\/ Ease-out so it slows as it approaches the ceiling.\\n\\t\\t\\tvar eased = 1 - Math.pow( 1 - t, 2.4 );\\n\\t\\t\\tself.setProgress( eased * ceiling );\\n\\t\\t\\tif ( t < 1 ) {\\n\\t\\t\\t\\tself.raf = requestAnimationFrame( tick );\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.raf = requestAnimationFrame( tick );\\n\\n\\t\\tthis.after( hold, function () {\\n\\t\\t\\tself.setProgress( 1 );\\n\\t\\t\\tself.root.classList.add( 'is-complete' );\\n\\t\\t\\tself.signal( 'Ready' );\\n\\n\\t\\t\\tself.after( 260 * p.motion, function () {\\n\\t\\t\\t\\tself.root.classList.remove( 'is-covering' );\\n\\t\\t\\t\\tself.root.classList.add( 'is-exiting' );\\n\\t\\t\\t\\tself.signal( 'Revealing the page' );\\n\\n\\t\\t\\t\\tself.after( 700 * p.motion, function () {\\n\\t\\t\\t\\t\\tself.root.classList.add( 'is-done' );\\n\\t\\t\\t\\t\\tself.signal( 'Page revealed' );\\n\\n\\t\\t\\t\\t\\t\\\/\\\/ Settle back to a poster frame rather than resting on an\\n\\t\\t\\t\\t\\t\\\/\\\/ empty faux page. This is a single settle, not a loop: the\\n\\t\\t\\t\\t\\t\\\/\\\/ stage shows the finished loader and then stops until the\\n\\t\\t\\t\\t\\t\\\/\\\/ visitor replays it or changes a setting. It also means a\\n\\t\\t\\t\\t\\t\\\/\\\/ screenshot taken at any idle moment shows the product.\\n\\t\\t\\t\\t\\tself.after( 1500, function () {\\n\\t\\t\\t\\t\\t\\tself.root.classList.remove( 'is-exiting', 'is-complete', 'is-done' );\\n\\t\\t\\t\\t\\t\\tself.root.classList.add( 'is-covering' );\\n\\t\\t\\t\\t\\t\\tself.setProgress( 1 );\\n\\t\\t\\t\\t\\t\\tself.signal( '' );\\n\\t\\t\\t\\t\\t} );\\n\\t\\t\\t\\t} );\\n\\t\\t\\t} );\\n\\t\\t} );\\n\\t};\\n\\n\\t\\\/** Reports stage state into an optional adjacent status element. *\\\/\\n\\tStage.prototype.signal = function ( text ) {\\n\\t\\tvar id = this.root.getAttribute( 'data-status' );\\n\\t\\tif ( ! id ) { return; }\\n\\t\\tvar el = document.getElementById( id );\\n\\t\\tif ( el ) { el.textContent = text; }\\n\\t};\\n\\n\\t\\\/\\\/ -------------------------------------------------------------------------\\n\\t\\\/\\\/ Wiring\\n\\t\\\/\\\/ -------------------------------------------------------------------------\\n\\n\\tfunction init() {\\n\\t\\tvar stages = {};\\n\\n\\t\\t\\\/\\\/ Build every stage on the page.\\n\\t\\tArray.prototype.forEach.call( document.querySelectorAll( '.khpld-stage' ), function ( el ) {\\n\\t\\t\\tvar stage = new Stage( el );\\n\\t\\t\\tvar id = el.getAttribute( 'id' );\\n\\t\\t\\tif ( id ) { stages[ id ] = stage; }\\n\\t\\t\\tel.__khpldStage = stage;\\n\\t\\t} );\\n\\n\\t\\t\\\/\\\/ Radio selectors: each group names the stage it drives and the key it\\n\\t\\t\\\/\\\/ sets, so one handler covers every section on the page.\\n\\t\\tArray.prototype.forEach.call( document.querySelectorAll( '[data-khpld-control]' ), function ( input ) {\\n\\t\\t\\tinput.addEventListener( 'change', function () {\\n\\t\\t\\t\\tif ( ! input.checked ) { return; }\\n\\t\\t\\t\\tvar targetId = input.getAttribute( 'data-target' );\\n\\t\\t\\t\\tvar key = input.getAttribute( 'data-khpld-control' );\\n\\t\\t\\t\\tvar stage = stages[ targetId ];\\n\\t\\t\\t\\tif ( stage ) { stage.set( key, input.value ); }\\n\\n\\t\\t\\t\\t\\\/\\\/ The closing composition mirrors every choice made further up,\\n\\t\\t\\t\\t\\\/\\\/ so what the CTA stage shows is exactly what \\\"Apply\\\" writes.\\n\\t\\t\\t\\tvar finalStage = stages[ 'khpld-stage-final' ];\\n\\t\\t\\t\\tif ( finalStage && finalStage !== stage ) { finalStage.setQuiet( key, input.value ); }\\n\\t\\t\\t} );\\n\\t\\t} );\\n\\n\\t\\t\\\/\\\/ Replay buttons.\\n\\t\\tArray.prototype.forEach.call( document.querySelectorAll( '[data-khpld-replay]' ), function ( btn ) {\\n\\t\\t\\tbtn.addEventListener( 'click', function () {\\n\\t\\t\\t\\tvar stage = stages[ btn.getAttribute( 'data-khpld-replay' ) ];\\n\\t\\t\\t\\tif ( stage ) { stage.play(); }\\n\\t\\t\\t} );\\n\\t\\t} );\\n\\n\\t\\t\\\/\\\/ Effect tiles. Clicking one replays that tile and also selects its logo\\n\\t\\t\\\/\\\/ effect for the closing composition - the gallery is a chooser, not just\\n\\t\\t\\\/\\\/ a set of previews, so \\\"Apply\\\" writes the effect the visitor picked\\n\\t\\t\\\/\\\/ rather than whatever the CTA stage happened to start on.\\n\\t\\tvar tiles = document.querySelectorAll( '.khpld-tile' );\\n\\n\\t\\tArray.prototype.forEach.call( tiles, function ( tile ) {\\n\\t\\t\\ttile.addEventListener( 'click', function () {\\n\\t\\t\\t\\tvar el = tile.querySelector( '.khpld-stage' );\\n\\t\\t\\t\\tif ( el && el.__khpldStage ) { el.__khpldStage.play(); }\\n\\n\\t\\t\\t\\tvar effect = tile.getAttribute( 'data-khpld-effect' );\\n\\t\\t\\t\\tif ( ! effect ) { return; }\\n\\n\\t\\t\\t\\t\\\/\\\/ aria-pressed is derived from the CTA stage's state, so the\\n\\t\\t\\t\\t\\\/\\\/ selection has exactly one owner: Stage.state.effect.\\n\\t\\t\\t\\tvar finalStage = stages[ 'khpld-stage-final' ];\\n\\t\\t\\t\\tif ( finalStage ) {\\n\\t\\t\\t\\t\\t\\\/\\\/ setQuiet, not set: the CTA stage is rested as a poster with\\n\\t\\t\\t\\t\\t\\\/\\\/ is-covering applied, so swapping the khpld-effect- class\\n\\t\\t\\t\\t\\t\\\/\\\/ re-runs just that entrance animation. Replaying the whole\\n\\t\\t\\t\\t\\t\\\/\\\/ cover -> progress -> exit cycle would be noise for what is\\n\\t\\t\\t\\t\\t\\\/\\\/ only a change of entrance.\\n\\t\\t\\t\\t\\tfinalStage.setQuiet( 'effect', effect );\\n\\t\\t\\t\\t}\\n\\n\\t\\t\\t\\tArray.prototype.forEach.call( tiles, function ( other ) {\\n\\t\\t\\t\\t\\tother.setAttribute(\\n\\t\\t\\t\\t\\t\\t'aria-pressed',\\n\\t\\t\\t\\t\\t\\tother.getAttribute( 'data-khpld-effect' ) === effect ? 'true' : 'false'\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t} );\\n\\t\\t\\t} );\\n\\t\\t} );\\n\\n\\t\\t\\\/\\\/ Play each stage once when it first scrolls into view, then stop\\n\\t\\t\\\/\\\/ observing it. Nothing replays on its own after that.\\n\\t\\tif ( 'IntersectionObserver' in window ) {\\n\\t\\t\\tvar io = new IntersectionObserver( function ( entries ) {\\n\\t\\t\\t\\tentries.forEach( function ( entry ) {\\n\\t\\t\\t\\t\\tif ( ! entry.isIntersecting ) { return; }\\n\\t\\t\\t\\t\\tio.unobserve( entry.target );\\n\\t\\t\\t\\t\\tif ( entry.target.__khpldStage ) {\\n\\t\\t\\t\\t\\t\\tentry.target.__khpldStage.play();\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} );\\n\\t\\t\\t}, { threshold: 0.35 } );\\n\\n\\t\\t\\tArray.prototype.forEach.call( document.querySelectorAll( '.khpld-stage' ), function ( el ) {\\n\\t\\t\\t\\tio.observe( el );\\n\\t\\t\\t} );\\n\\t\\t} else {\\n\\t\\t\\tArray.prototype.forEach.call( document.querySelectorAll( '.khpld-stage' ), function ( el ) {\\n\\t\\t\\t\\tif ( el.__khpldStage ) { el.__khpldStage.play(); }\\n\\t\\t\\t} );\\n\\t\\t}\\n\\n\\t\\twireApply( stages );\\n\\t}\\n\\n\\t\\\/**\\n\\t * \\\"Apply to this site\\\" - the one genuinely live control on the page.\\n\\t *\\n\\t * It posts the combination the visitor assembled to admin-ajax, where the\\n\\t * plugin's own sanitiser validates it and it is stored as real settings.\\n\\t * The page then reloads so the actual Page Loader runs with them. Nothing\\n\\t * about it is simulated.\\n\\t *\\\/\\n\\tfunction wireApply( stages ) {\\n\\t\\tvar btn = document.getElementById( 'khpld-apply' );\\n\\t\\tif ( ! btn || ! window.khpldDemo ) { return; }\\n\\n\\t\\tvar status = document.getElementById( 'khpld-apply-status' );\\n\\n\\t\\tbtn.addEventListener( 'click', function () {\\n\\t\\t\\tvar main = stages[ 'khpld-stage-final' ];\\n\\t\\t\\tif ( ! main ) { return; }\\n\\n\\t\\t\\tbtn.disabled = true;\\n\\t\\t\\tif ( status ) { status.textContent = 'Applying to this site...'; }\\n\\n\\t\\t\\tvar body = new URLSearchParams();\\n\\t\\t\\tbody.append( 'action', 'khpld_apply' );\\n\\t\\t\\tbody.append( 'nonce', window.khpldDemo.nonce );\\n\\t\\t\\tbody.append( 'kinetic_mode', main.state.power );\\n\\t\\t\\tbody.append( 'progress_style', main.state.progress );\\n\\t\\t\\tbody.append( 'exit_transition', main.state.exit );\\n\\t\\t\\tbody.append( 'page_reveal', main.state.reveal );\\n\\t\\t\\tbody.append( 'cover_mode', main.state.cover );\\n\\t\\t\\tbody.append( 'logo_effect', main.state.effect );\\n\\n\\t\\t\\tfetch( window.khpldDemo.ajaxUrl, {\\n\\t\\t\\t\\tmethod: 'POST',\\n\\t\\t\\t\\tcredentials: 'same-origin',\\n\\t\\t\\t\\theaders: { 'Content-Type': 'application\\\/x-www-form-urlencoded' },\\n\\t\\t\\t\\tbody: body.toString()\\n\\t\\t\\t} )\\n\\t\\t\\t\\t.then( function ( r ) { return r.json(); } )\\n\\t\\t\\t\\t.then( function ( data ) {\\n\\t\\t\\t\\t\\tif ( data && data.success ) {\\n\\t\\t\\t\\t\\t\\tif ( status ) { status.textContent = 'Saved. Reloading so the real loader runs...'; }\\n\\t\\t\\t\\t\\t\\twindow.location.reload();\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tbtn.disabled = false;\\n\\t\\t\\t\\t\\t\\tif ( status ) { status.textContent = 'Could not apply those settings.'; }\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} )\\n\\t\\t\\t\\t.catch( function () {\\n\\t\\t\\t\\t\\tbtn.disabled = false;\\n\\t\\t\\t\\t\\tif ( status ) { status.textContent = 'Could not reach the site.'; }\\n\\t\\t\\t\\t} );\\n\\t\\t} );\\n\\t}\\n\\n\\tif ( document.readyState === 'loading' ) {\\n\\t\\tdocument.addEventListener( 'DOMContentLoaded', init );\\n\\t} else {\\n\\t\\tinit();\\n\\t}\\n} )();\\n\"},{\"step\":\"runPHP\",\"code\":\"<?php\\n\\\/**\\n * Playground setup step for the KineticHub Page Loader demo.\\n *\\n * Inlined into blueprint.json as the runPHP step by build.js. It runs once,\\n * inside the Playground instance, after the plugin and the demo mu-plugin have\\n * been written.\\n *\\n * Three jobs: register the official plugin icon as the demo logo, write the\\n * loader settings, and create the showcase page as the site's front page.\\n *\\n * @package KineticHub_Page_Loader_Demo\\n *\\\/\\n\\nrequire_once '\\\/wordpress\\\/wp-load.php';\\nrequire_once ABSPATH . 'wp-admin\\\/includes\\\/image.php';\\nrequire_once ABSPATH . 'wp-admin\\\/includes\\\/file.php';\\nrequire_once ABSPATH . 'wp-admin\\\/includes\\\/media.php';\\n\\n\\\/\\\/ -----------------------------------------------------------------------------\\n\\\/\\\/ 1. Demo logo\\n\\\/\\\/\\n\\\/\\\/ This is the official published plugin icon, downloaded by the preceding\\n\\\/\\\/ writeFile step. It is used exactly as shipped - the demo never substitutes or\\n\\\/\\\/ redraws the product mark.\\n\\\/\\\/ -----------------------------------------------------------------------------\\n\\n$khpld_attachment_id = 0;\\n$khpld_logo_file     = '\\\/tmp\\\/khpl-demo-logo.png';\\n\\nif ( file_exists( $khpld_logo_file ) ) {\\n\\t$khpld_upload = wp_upload_bits( 'kinetichub-logo.png', null, file_get_contents( $khpld_logo_file ) );\\n\\n\\tif ( empty( $khpld_upload['error'] ) ) {\\n\\t\\t$khpld_attachment_id = wp_insert_attachment(\\n\\t\\t\\tarray(\\n\\t\\t\\t\\t'post_mime_type' => 'image\\\/png',\\n\\t\\t\\t\\t'post_title'     => 'KineticHub Logo',\\n\\t\\t\\t\\t'post_status'    => 'inherit',\\n\\t\\t\\t),\\n\\t\\t\\t$khpld_upload['file']\\n\\t\\t);\\n\\n\\t\\tif ( ! is_wp_error( $khpld_attachment_id ) && $khpld_attachment_id ) {\\n\\t\\t\\twp_update_attachment_metadata(\\n\\t\\t\\t\\t$khpld_attachment_id,\\n\\t\\t\\t\\twp_generate_attachment_metadata( $khpld_attachment_id, $khpld_upload['file'] )\\n\\t\\t\\t);\\n\\t\\t} else {\\n\\t\\t\\t$khpld_attachment_id = 0;\\n\\t\\t}\\n\\t}\\n}\\n\\n\\\/\\\/ -----------------------------------------------------------------------------\\n\\\/\\\/ 2. Loader settings\\n\\\/\\\/\\n\\\/\\\/ Every value below is one the plugin actually accepts, and the whole array is\\n\\\/\\\/ pushed through KHPL_Settings::sanitize_settings() rather than written raw.\\n\\\/\\\/\\n\\\/\\\/ That is deliberate. An earlier revision of this blueprint wrote four values\\n\\\/\\\/ for display_mode, audience, show_frequency and min_display_ms that are not in\\n\\\/\\\/ the plugin's vocabulary at all; each only appeared to work because it fell\\n\\\/\\\/ through a !== check, and the timing value silently snapped to the clamp\\n\\\/\\\/ ceiling the first time anyone saved the settings screen. Routing through the\\n\\\/\\\/ sanitiser means the demo cannot drift out of step with the plugin again.\\n\\\/\\\/\\n\\\/\\\/ The offending literals are deliberately not repeated here, so that grepping\\n\\\/\\\/ the generated blueprint for them stays a meaningful release check.\\n\\\/\\\/ -----------------------------------------------------------------------------\\n\\n$khpld_settings = array(\\n\\t\\\/\\\/ Core\\n\\t'enabled'             => true,\\n\\t'display_mode'        => 'all',\\n\\t'show_frequency'      => 'always',\\n\\t'audience'            => 'all',\\n\\n\\t\\\/\\\/ Branding - the official icon, circular, with the dual brand ring.\\n\\t'logo_attachment_id'  => $khpld_attachment_id,\\n\\t'logo_max_width'      => 160,\\n\\t'logo_shape'          => 'circle',\\n\\t'logo_ring_enabled'   => true,\\n\\t'logo_ring_style'     => 'dual',\\n\\t'logo_ring_color_1'   => '#00d5ff',\\n\\t'logo_ring_color_2'   => '#8b5cf6',\\n\\t'logo_ring_thickness' => 3,\\n\\t'logo_ring_speed'     => 9,\\n\\t'text_fallback'       => 'KineticHub',\\n\\t'tagline'             => 'Branded loading screens for WordPress',\\n\\t'tagline_spacing'     => 12,\\n\\n\\t\\\/\\\/ Rotating messages, so the rotator is visible on arrival.\\n\\t'loading_messages'    => array(\\n\\t\\t'Preparing your first second',\\n\\t\\t'Shaping the entrance',\\n\\t\\t'Almost ready',\\n\\t),\\n\\n\\t\\\/\\\/ Style - the KineticHub palette.\\n\\t'preset'              => 'circular-brand-ring',\\n\\t'bg_color'            => '#050b14',\\n\\t'accent_color'        => '#00d5ff',\\n\\t'text_color'          => '#f8fbff',\\n\\t'use_gradient'        => true,\\n\\t'gradient_color'      => '#8b5cf6',\\n\\t'logo_effect'         => 'zoom-bloom',\\n\\n\\t\\\/\\\/ The 1.4.0 smart visuals - the whole point of the refreshed demo.\\n\\t'kinetic_mode'        => 'signature-glow',\\n\\t'progress_style'      => 'logo-ring',\\n\\t'exit_transition'     => 'circle-reveal',\\n\\t'page_reveal'         => 'soft-fade',\\n\\t'cover_mode'          => 'solid',\\n\\t'completion_pulse'    => true,\\n\\t'reveal_delay_ms'     => 0,\\n\\n\\t\\\/\\\/ Timing. min_display_ms stays inside the plugin's own 0-3000 range.\\n\\t'min_display_ms'      => 2200,\\n\\t'max_timeout_ms'      => 8000,\\n\\t'fade_out_ms'         => 600,\\n\\t'show_on_desktop'     => true,\\n\\t'show_on_mobile'      => true,\\n);\\n\\nif ( class_exists( 'KHPL_Settings' ) ) {\\n\\t$khpld_sanitizer = new KHPL_Settings();\\n\\tupdate_option( 'khpl_settings', $khpld_sanitizer->sanitize_settings( $khpld_settings ) );\\n} else {\\n\\tupdate_option( 'khpl_settings', $khpld_settings );\\n}\\n\\n\\\/\\\/ -----------------------------------------------------------------------------\\n\\\/\\\/ 3. Showcase page\\n\\\/\\\/\\n\\\/\\\/ The mu-plugin takes the page over by slug and renders the showcase, so the\\n\\\/\\\/ stored content is only a human-readable fallback for anyone who opens it in\\n\\\/\\\/ the editor.\\n\\\/\\\/ -----------------------------------------------------------------------------\\n\\n$khpld_existing = get_page_by_path( 'khpl-demo' );\\n$khpld_page_id  = $khpld_existing ? (int) $khpld_existing->ID : 0;\\n\\nif ( ! $khpld_page_id ) {\\n\\t$khpld_page_id = wp_insert_post(\\n\\t\\tarray(\\n\\t\\t\\t'post_type'    => 'page',\\n\\t\\t\\t'post_status'  => 'publish',\\n\\t\\t\\t'post_title'   => 'Make the first second memorable',\\n\\t\\t\\t'post_name'    => 'khpl-demo',\\n\\t\\t\\t'post_content' => '<!-- wp:paragraph --><p>This page is rendered by the KineticHub Page Loader demo showcase.<\\\/p><!-- \\\/wp:paragraph -->',\\n\\t\\t)\\n\\t);\\n}\\n\\nif ( $khpld_page_id && ! is_wp_error( $khpld_page_id ) ) {\\n\\tupdate_option( 'show_on_front', 'page' );\\n\\tupdate_option( 'page_on_front', (int) $khpld_page_id );\\n}\\n\\n\\\/\\\/ Tidy permalinks so \\\/khpl-demo\\\/ resolves as well as \\\/.\\nupdate_option( 'permalink_structure', '\\\/%postname%\\\/' );\\nflush_rewrite_rules( false );\\n\"}]}"}},"all_blocks":[],"tagged_versions":["1.0.0","1.1.0","1.1.1","1.2.0","1.3.0","1.4.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3683246,"resolution":"1","location":"assets","locale":"","width":1180,"height":577},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3683246,"resolution":"2","location":"assets","locale":"","width":1177,"height":574},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3683246,"resolution":"3","location":"assets","locale":"","width":1177,"height":575},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3683246,"resolution":"4","location":"assets","locale":"","width":1180,"height":572},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3683246,"resolution":"5","location":"assets","locale":"","width":1170,"height":570},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3683246,"resolution":"6","location":"assets","locale":"","width":1201,"height":564},"screenshot-7.png":{"filename":"screenshot-7.png","revision":3683246,"resolution":"7","location":"assets","locale":"","width":1299,"height":550}},"screenshots":{"1":"KineticHub Page Loader dashboard with real-time Live Preview and simple site-wide controls.","2":"Choose from polished animation presets and customize the visual style with instant preview.","3":"Smart Anti-Flash, progress styles, transitions, cover modes, and page reveal controls.","4":"KineticPower motion profiles range from Ultra Minimal to the expressive Signature Glow.","5":"Flexible display rules control when, where, and for whom the page loader appears.","6":"A polished branded loader with logo treatment, simulated progress, and modern visual effects.","7":"Another frontend example showing how KineticHub Page Loader can adapt to different brand styles and visual treatments."}},"plugin_section":[],"plugin_tags":[4470,41009,154083,32564,791],"plugin_category":[],"plugin_contributors":[264673],"plugin_business_model":[],"class_list":["post-333502","plugin","type-plugin","status-publish","hentry","plugin_tags-loader","plugin_tags-loading-animation","plugin_tags-loading-screen","plugin_tags-page-loader","plugin_tags-preloader","plugin_contributors-kinetichub","plugin_committers-kinetichub","plugin_support_reps-caddylac00"],"banners":{"banner":"https:\/\/ps.w.org\/kinetichub-page-loader\/assets\/banner-772x250.png?rev=3683302","banner_2x":"https:\/\/ps.w.org\/kinetichub-page-loader\/assets\/banner-1544x500.png?rev=3683302","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/kinetichub-page-loader\/assets\/icon-128x128.png?rev=3589870","icon_2x":"https:\/\/ps.w.org\/kinetichub-page-loader\/assets\/icon-256x256.png?rev=3589870","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/kinetichub-page-loader\/assets\/screenshot-1.png?rev=3683246","caption":"KineticHub Page Loader dashboard with real-time Live Preview and simple site-wide controls."},{"src":"https:\/\/ps.w.org\/kinetichub-page-loader\/assets\/screenshot-2.png?rev=3683246","caption":"Choose from polished animation presets and customize the visual style with instant preview."},{"src":"https:\/\/ps.w.org\/kinetichub-page-loader\/assets\/screenshot-3.png?rev=3683246","caption":"Smart Anti-Flash, progress styles, transitions, cover modes, and page reveal controls."},{"src":"https:\/\/ps.w.org\/kinetichub-page-loader\/assets\/screenshot-4.png?rev=3683246","caption":"KineticPower motion profiles range from Ultra Minimal to the expressive Signature Glow."},{"src":"https:\/\/ps.w.org\/kinetichub-page-loader\/assets\/screenshot-5.png?rev=3683246","caption":"Flexible display rules control when, where, and for whom the page loader appears."},{"src":"https:\/\/ps.w.org\/kinetichub-page-loader\/assets\/screenshot-6.png?rev=3683246","caption":"A polished branded loader with logo treatment, simulated progress, and modern visual effects."},{"src":"https:\/\/ps.w.org\/kinetichub-page-loader\/assets\/screenshot-7.png?rev=3683246","caption":"Another frontend example showing how KineticHub Page Loader can adapt to different brand styles and visual treatments."}],"raw_content":"<!--section=description-->\n<p>KineticHub Page Loader is a customizable WordPress preloader and page loader for creating branded loading screens while a page finishes rendering. Add your logo, choose a loading animation, configure progress and transitions, and preview the result directly from the WordPress admin.<\/p>\n\n<p>It is designed for branding and perceived presentation, not for pretending to make a website load faster. The plugin does not improve server response time or actual page speed; it gives visitors a polished visual experience while the page becomes ready.<\/p>\n\n<p>KineticHub Page Loader is built with CSS-first animations and vanilla JavaScript, with no jQuery, external fonts, CDN assets, or frontend remote requests.<\/p>\n\n<h4>Smart loading experiences<\/h4>\n\n<ul>\n<li><strong>Smart Anti-Flash<\/strong> - an optional reveal delay so the loader does not flash on very fast page loads.<\/li>\n<li><strong>KineticPower motion profiles<\/strong> - Ultra Minimal, Calm, Balanced, Dynamic, and Signature Glow, layered over the preset you choose.<\/li>\n<li><strong>Seven visual presets<\/strong> - Minimal Pulse, Logo Fade, Gradient Sweep, Soft Orb, Progress Bar Minimal, Circular Brand Ring, and Logo Color Reveal.<\/li>\n<li><strong>Live Preview<\/strong> - the settings screen renders your loading screen in real time as you change options.<\/li>\n<\/ul>\n\n<h4>Branding and logo effects<\/h4>\n\n<p>Upload a custom logo from the WordPress Media Library, or fall back to short text that defaults to your site name. An optional tagline sits below, with its own spacing control.<\/p>\n\n<ul>\n<li>Logo shapes: original, rounded, or circle<\/li>\n<li>Loading rings around the logo: solid, dashed, dual, or glow, with color, thickness and speed<\/li>\n<li>Logo reveal effects: Fade, Grayscale to Color, Soft Scale, Soft Shine Sweep, Zoom Bloom, and Mask Reveal<\/li>\n<li>Background, accent, text, and optional gradient colors<\/li>\n<\/ul>\n\n<h4>Progress, transitions and page reveal<\/h4>\n\n<p>Smart Progress adds a progress indicator in one of six styles: None, Top Bar, Bottom Line, Logo Ring, Center Glow Line, or Minimal Percentage.<\/p>\n\n<p><strong>Progress is simulated visual progress<\/strong> - a timed animation that conveys activity, not a measurement of actual network or download progress.<\/p>\n\n<ul>\n<li>Exit transitions: Fade, Slide Up, Blur Lift, Split Curtain, Circle Reveal<\/li>\n<li>Page Reveal for the handoff into your page: None, Soft Fade, Blur to Sharp, Lift In, Gentle Scale<\/li>\n<li>Cover modes: Solid, Soft Overlay, Blur Page, Glass<\/li>\n<li>An optional completion pulse, rotating loading messages, and one-click timing presets<\/li>\n<\/ul>\n\n<h4>Display rules and compatibility<\/h4>\n\n<p>Show the page loader site-wide or on the homepage only, to everyone or to visitors only, on every load, once per session, or once per day. Exclude specific post\/page IDs and URL paths, optionally exclude the WooCommerce cart, checkout and account pages, and toggle desktop and mobile visibility independently.<\/p>\n\n<p>The loader is output through standard WordPress frontend hooks (<code>wp_body_open<\/code>, with a <code>wp_footer<\/code> fallback), so it works with classic themes, block themes, and page builders that render normal frontend pages. Session and daily frequency are tracked in the browser, so pages stay cacheable alongside caching and performance plugins, and the loader includes failsafe handling for setups that delay frontend JavaScript.<\/p>\n\n<h4>Lightweight and accessible<\/h4>\n\n<ul>\n<li>Vanilla JavaScript, no jQuery, no frontend remote requests<\/li>\n<li>Minified production CSS and JavaScript<\/li>\n<li>Respects <code>prefers-reduced-motion<\/code> by collapsing animations to an instant transition<\/li>\n<li>An <code>aria-hidden<\/code> visual overlay with no focus trap, so keyboard focus stays on the page below<\/li>\n<li>The loader element is removed from the DOM once it has hidden<\/li>\n<li>A <code>noscript<\/code> fallback hides the loader for visitors with JavaScript disabled<\/li>\n<li>A bounded maximum timeout ensures the loading screen goes away even if a resource never loads<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Install KineticHub Page Loader from the WordPress Plugin Directory, or upload the plugin ZIP.<\/li>\n<li>Activate the plugin.<\/li>\n<li>Go to Settings -&gt; Page Loader.<\/li>\n<li>Enable the loader, add your logo or text, choose the visual options you want, and save.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"how%20do%20i%20add%20a%20preloader%20to%20wordpress%3F\"><h3>How do I add a preloader to WordPress?<\/h3><\/dt>\n<dd><p>Install and activate KineticHub Page Loader, then go to <strong>Settings -&gt; Page Loader<\/strong>. Enable the loader, add your logo or text, pick a preset and the options you want, and save. The loading screen appears on the next frontend page load.<\/p><\/dd>\n<dt id=\"can%20i%20use%20my%20own%20logo%20in%20the%20loading%20screen%3F\"><h3>Can I use my own logo in the loading screen?<\/h3><\/dt>\n<dd><p>Yes. Upload any image from the WordPress Media Library. If no logo is set, a text fallback is shown instead, defaulting to your site name. You can add logo reveal effects (fade, grayscale to color, soft scale, shine sweep, zoom bloom, mask reveal), logo shapes (original, rounded, circle), and an animated loading ring.<\/p><\/dd>\n<dt id=\"can%20i%20add%20a%20progress%20bar%20or%20loading%20percentage%3F\"><h3>Can I add a progress bar or loading percentage?<\/h3><\/dt>\n<dd><p>Yes. Smart Progress offers Top Bar, Bottom Line, Logo Ring, Center Glow Line, and Minimal Percentage styles, or None. This is simulated visual progress: a timed animation, not a measurement of the actual network loading percentage.<\/p><\/dd>\n<dt id=\"can%20i%20control%20where%20the%20page%20loader%20appears%3F\"><h3>Can I control where the page loader appears?<\/h3><\/dt>\n<dd><p>Yes. Show it site-wide or on the homepage only, to everyone or to visitors only, and exclude specific post\/page IDs, URL paths, or WooCommerce cart, checkout and account pages. Desktop and mobile visibility are independent.<\/p><\/dd>\n<dt id=\"can%20the%20preloader%20show%20only%20once%20per%20session%20or%20once%20per%20day%3F\"><h3>Can the preloader show only once per session or once per day?<\/h3><\/dt>\n<dd><p>Yes. Show frequency can be every page load, once per session, or once per day. On repeat views within that window the loader is suppressed before it can paint, so there is no flash of a loading screen.<\/p><\/dd>\n<dt id=\"does%20kinetichub%20page%20loader%20work%20with%20woocommerce%2C%20page%20builders%2C%20and%20caching%20plugins%3F\"><h3>Does KineticHub Page Loader work with WooCommerce, page builders, and caching plugins?<\/h3><\/dt>\n<dd><p>It is designed to. WooCommerce cart, checkout, and account pages can be excluded with one toggle, and the loader is theme- and builder-agnostic because it renders through normal WordPress frontend hooks. Frequency tracking happens in the browser, so pages stay cacheable, and failsafe handling covers setups that delay frontend JavaScript. Third-party configurations vary, so compatibility with every possible combination cannot be guaranteed.<\/p><\/dd>\n<dt id=\"does%20a%20preloader%20make%20my%20wordpress%20site%20faster%3F\"><h3>Does a preloader make my WordPress site faster?<\/h3><\/dt>\n<dd><p>No. It changes the visual loading experience and perceived presentation. It does not reduce server response time or optimize your assets.<\/p><\/dd>\n<dt id=\"does%20the%20loader%20respect%20reduced%20motion%20and%20accessibility%20preferences%3F\"><h3>Does the loader respect reduced motion and accessibility preferences?<\/h3><\/dt>\n<dd><p>Yes. When <code>prefers-reduced-motion: reduce<\/code> is set, animations collapse to an instant transition. The overlay is marked <code>aria-hidden<\/code> so screen readers skip it, there is no focus trap, and the loader is removed from the DOM after hiding. With JavaScript disabled, a <code>noscript<\/code> block hides the loader so the page is never blocked.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.4.0<\/h4>\n\n<ul>\n<li>Added: Smart Anti-Flash reveal delay, so the loader does not flash on very fast page loads.<\/li>\n<li>Added: KineticPower motion profiles - Classic, Ultra Minimal, Calm, Balanced, Dynamic, and Signature Glow.<\/li>\n<li>Added: logo reveal effects - Soft Shine Sweep, Zoom Bloom, and Mask Reveal, alongside the existing fade, grayscale reveal, and soft scale.<\/li>\n<li>Added: Smart Progress styles - Top Bar, Bottom Line, Logo Ring, Center Glow Line, and Minimal Percentage. Progress is simulated, not a measurement of actual load progress.<\/li>\n<li>Added: exit transitions - Slide Up, Blur Lift, Split Curtain, and Circle Reveal - plus optional page reveal effects for a smoother handoff into the page.<\/li>\n<li>Added: cover modes - Solid, Soft Overlay, Blur Page, and Glass.<\/li>\n<li>Added: rotating loading messages, an optional completion pulse, and one-click timing presets.<\/li>\n<li>Improved: redesigned settings screen with a modern KineticHub dashboard layout and an expanded Live Preview.<\/li>\n<li>Improved: scroll-lock handling on iOS and Safari, and general loader lifecycle robustness.<\/li>\n<li>Note: all new visual options default to the previous behavior, so existing sites render exactly as before until you opt in.<\/li>\n<\/ul>\n\n<h4>1.3.0<\/h4>\n\n<ul>\n<li>Added: Tagline Spacing setting (0-50 px) in the Content section, controlling the space between the logo\/text and the tagline. Default 0 preserves the existing look.<\/li>\n<li>Added: a one-time, permanently dismissible review request, shown only on the plugin's own settings page at least 10 days after installation.<\/li>\n<li>Added: a small card on the settings page introducing KineticHub - Animated Blocks, shown only when it is not already installed.<\/li>\n<li>Fixed: with no logo set, the circle shape and the Circular Brand Ring preset reserved empty space the size of the configured logo width above the tagline.<\/li>\n<li>Fixed: ring decorations are no longer rendered around the text fallback when no logo is set, where they appeared as stretched ellipses.<\/li>\n<li>Improved: ring options are visually disabled, with an explanatory note, while the Circular Brand Ring preset is selected, since that preset draws its own rings. Saved ring settings are preserved.<\/li>\n<li>Improved: the settings sidebar (preview and info card) sticks as one block and scrolls internally on short screens.<\/li>\n<\/ul>","raw_excerpt":"Customizable WordPress preloader and page loader with branded loading screens, logo effects, progress styles, transitions, and live preview.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/333502","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=333502"}],"author":[{"embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/kinetichub"}],"wp:attachment":[{"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=333502"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=333502"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=333502"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=333502"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=333502"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=333502"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}