<?php

/**
 * Plugin Name: A360 Panorama Hero
 * Plugin URI: https://a360.pl/a360-panorama-hero/
 * Description: Add an interactive 360° panorama behind a Hero section while editing its content with native WordPress blocks.
 * Version: 1.3.14
 * Requires at least: 6.0
 * Requires PHP: 7.4
 * Author: Igor Rubas
 * Text Domain: a360-panorama-hero
 * License: GPL-2.0-or-later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 */

if (! defined('ABSPATH')) {
	exit;
}

define('A360_PANORAMA_VERSION', '1.3.14');
define('A360_PANORAMA_FILE', __FILE__);
define('A360_PANORAMA_URL', plugin_dir_url(__FILE__));
define('A360_PANORAMA_PATH', plugin_dir_path(__FILE__));

/**
 * Registers viewer assets. They are enqueued only on pages containing the shortcode.
 */
function a360_panorama_register_assets()
{
	load_plugin_textdomain("a360-panorama-hero", false, dirname(plugin_basename(__FILE__)) . "/languages");
	wp_register_style(
		'a360-panorama',
		A360_PANORAMA_URL . 'assets/css/a360-panorama.css',
		array(),
		A360_PANORAMA_VERSION
	);

	wp_register_script(
		'a360-panorama-viewer',
		A360_PANORAMA_URL . 'assets/js/a360-panorama.js',
		array(),
		A360_PANORAMA_VERSION,
		true
	);
}
add_action('init', 'a360_panorama_register_assets');

/**
 * Loads assets early for shortcodes placed directly in post content.
 */
function a360_panorama_maybe_enqueue_assets()
{
	global $post;

	$has_panorama = $post instanceof WP_Post && (
		has_shortcode($post->post_content, 'a360_panorama')
		|| has_block('a360/panorama-hero', $post->post_content)
	);
	if (! $has_panorama && is_front_page() && function_exists('get_block_template')) {
		$template = get_block_template(get_stylesheet() . '//front-page', 'wp_template');
		$has_panorama = $template && has_block('a360/panorama-hero', (string) $template->content);
	}
	if ($has_panorama) {
		wp_enqueue_style('a360-panorama');
		wp_enqueue_script('a360-panorama-viewer');
	}
}
add_action('wp_enqueue_scripts', 'a360_panorama_maybe_enqueue_assets', 20);

/**
 * Prints a late-enqueued stylesheet when a page builder renders the shortcode
 * after wp_head has already run.
 */
function a360_panorama_print_late_styles()
{
	if (wp_style_is('a360-panorama', 'enqueued') && ! wp_style_is('a360-panorama', 'done')) {
		wp_print_styles('a360-panorama');
	}
}
add_action('wp_footer', 'a360_panorama_print_late_styles', 1);

/**
 * Resolves a shortcode image value.
 *
 * Supported values:
 * - attachment ID,
 * - absolute http(s) URL,
 * - root-relative URL,
 * - filename stored in the plugin's panoramas directory.
 *
 * @param string $image Shortcode image value.
 * @return string
 */
function a360_panorama_resolve_image_url($image)
{
	$image = trim((string) $image);

	if ('' === $image) {
		return '';
	}

	if (ctype_digit($image)) {
		$attachment_url = wp_get_attachment_url((int) $image);
		return $attachment_url ? $attachment_url : '';
	}

	if (preg_match('#^https?://#i', $image)) {
		return esc_url_raw($image);
	}

	if (0 === strpos($image, '/')) {
		return esc_url_raw(home_url($image));
	}

	$filename = wp_basename($image);
	return esc_url_raw(A360_PANORAMA_URL . 'panoramas/' . rawurlencode($filename));
}

/**
 * Renders a single, automatically rotating panorama.
 *
 * @param array $atts Shortcode attributes.
 * @return string
 */
function a360_panorama_shortcode($atts)
{
	$atts = shortcode_atts(
		array(
			'image' => '',
			'images' => '',
			'interval' => '8',
			'poster' => '',
			'height' => '600',
			'speed' => '2',
			'fov' => '75',
			'resume' => '4',
			'autoplay' => 'always',
			'label' => __('Interactive 360-degree panorama', 'a360-panorama-hero'),
		), $atts, 'a360_panorama'
	);

	$image_values = array_filter(array_map('trim', explode(',', (string) $atts['images'])));
	if (empty($image_values) && '' !== trim((string) $atts['image'])) $image_values[] = $atts['image'];
	$image_urls = array_values(array_unique(array_filter(array_map('a360_panorama_resolve_image_url', $image_values))));
	if (empty($image_urls)) {
		return current_user_can('edit_posts') ? '<p class="a360-panorama-message">' . esc_html__('A360 Panorama: provide an image using the image or images parameter.', 'a360-panorama-hero') . '</p>' : '';
	}

	$image_url = $image_urls[0];
	$poster_url = a360_panorama_resolve_image_url($atts['poster']) ?: $image_url;
	$height = max(240, min(1200, absint($atts['height'])));
	$speed = max(0.1, min(12, (float) $atts['speed']));
	$fov = max(35, min(110, (float) $atts['fov']));
	$resume = max(0, min(30, (float) $atts['resume']));
	$interval = max(1, min(300, absint($atts['interval'])));
	$autoplay = in_array($atts['autoplay'], array('respect', 'always', 'off'), true) ? $atts['autoplay'] : 'always';
	$id = wp_unique_id('a360-panorama-');
	$scenes = array_map(static function ($url) { return array('url' => $url, 'hotspots' => array()); }, $image_urls);

	wp_enqueue_style('a360-panorama');
	wp_enqueue_script('a360-panorama-viewer');

	return sprintf(
		'<div id="%1$s" class="a360-panorama" role="region" aria-label="%2$s" tabindex="0" style="--a360-panorama-height:%3$dpx" data-image="%4$s" data-images="%14$s" data-scenes="%15$s" data-panorama-interval="%16$s" data-speed="%5$s" data-fov="%6$s" data-resume="%7$s" data-autoplay="%8$s" data-pause-label="%12$s" data-resume-label="%13$s"><img class="a360-panorama__poster" src="%11$s" alt="" decoding="async"><div class="a360-panorama__viewport"></div><div class="a360-panorama__loader" role="status">%9$s</div><div class="a360-panorama__error" role="alert" hidden>%10$s</div><button class="a360-panorama__toggle" type="button" aria-pressed="false" aria-label="%12$s"><span aria-hidden="true">Ⅱ</span></button></div>',
		esc_attr($id), esc_attr($atts['label']), $height, esc_url($image_url), esc_attr($speed), esc_attr($fov), esc_attr($resume), esc_attr($autoplay),
		esc_html__('Loading panorama…', 'a360-panorama-hero'), esc_html__('The panorama could not be loaded.', 'a360-panorama-hero'), esc_url($poster_url),
		esc_attr__('Pause panorama rotation', 'a360-panorama-hero'), esc_attr__('Resume panorama rotation', 'a360-panorama-hero'),
		esc_attr(wp_json_encode($image_urls)), esc_attr(wp_json_encode($scenes)), esc_attr($interval)
	);
}
add_shortcode('a360_panorama', 'a360_panorama_shortcode');

/** Sanitizes hotspot data stored for an individual panorama. */
function a360_panorama_sanitize_hotspots($source)
{
	$result = array();
	if (! is_array($source)) {
		return $result;
	}
	foreach ($source as $hotspot) {
		if (! is_array($hotspot)) continue;
		$type_value = $hotspot['type'] ?? 'info';
		$type = in_array($type_value, array('info', 'product', 'link'), true) ? $type_value : 'info';
		$destination_type_value = $hotspot['destinationTypee'] ?? 'url';
		$destination_type = in_array($destination_type_value, array('url', 'panorama'), true) ? $destination_type_value : 'url';
		$gallery = array();
		foreach ((array) ($hotspot['gallery'] ?? array()) as $image) {
			if (! is_array($image)) continue;
			$gallery[] = array('id' => absint($image['id'] ?? 0), 'url' => esc_url_raw($image['url'] ?? ''), 'alt' => sanitize_text_field($image['alt'] ?? ''));
		}
		$result[] = array(
			'id' => sanitize_key($hotspot['id'] ?? wp_unique_id('hotspot-')),
			'yaw' => max(-180, min(180, (float) ($hotspot['yaw'] ?? 0))),
			'pitch' => max(-89, min(89, (float) ($hotspot['pitch'] ?? 0))),
			'type' => $type,
			'title' => sanitize_text_field($hotspot['title'] ?? ''),
			'visible' => ! array_key_exists('visible', $hotspot) || ! empty($hotspot['visible']),
			'description' => sanitize_textarea_field($hotspot['description'] ?? ''),
			'gallery' => $gallery,
			'youtube' => esc_url_raw($hotspot['youtube'] ?? ''),
			'productId' => absint($hotspot['productId'] ?? 0),
			'destinationTypee' => $destination_type,
			'url' => esc_url_raw($hotspot['url'] ?? ''),
			'targetBlank' => ! empty($hotspot['targetBlank']),
			'targetImageId' => absint($hotspot['targetImageId'] ?? 0),
			'targetImageUrl' => esc_url_raw($hotspot['targetImageUrl'] ?? ''),
		);
	}
	return $result;
}

/** Renderuje blok Hero, zachowując jego zawartość jako natywne bloki WP. */
function a360_panorama_render_hero_block($attributes, $content)
{
	$image_id  = absint($attributes['imageId'] ?? 0);
	$image_url = esc_url_raw($attributes['imageUrl'] ?? '');
	$image_url = $image_url ?: ($image_id ? wp_get_attachment_image_url($image_id, 'full') : '');
	$panoramas = array();
	if (! empty($attributes['panoramas']) && is_array($attributes['panoramas'])) {
		foreach ($attributes['panoramas'] as $panorama) {
			if (! is_array($panorama)) {
				continue;
			}
			$panorama_id = absint($panorama['id'] ?? 0);
			$panorama_url = esc_url_raw($panorama['url'] ?? '');
			$panorama_url = $panorama_url ?: ($panorama_id ? wp_get_attachment_image_url($panorama_id, 'full') : '');
			if ($panorama_url) {
				$panoramas[] = array('id' => $panorama_id, 'url' => $panorama_url);
			}
		}
	}
	if (empty($panoramas) && $image_url) {
		$panoramas[] = array('id' => $image_id, 'url' => $image_url);
	}
	if (! empty($panoramas)) {
		$image_id = $panoramas[0]['id'];
		$image_url = $panoramas[0]['url'];
	}
	if (! $image_url) {
		return current_user_can('edit_posts') ? '<p class="a360-panorama-message">' . esc_html__('A360 Panorama Hero: select a spherical image.', 'a360-panorama-hero') . '</p>' : '';
	}
	$poster_id = absint($attributes['posterId'] ?? 0);
	$poster_url = esc_url_raw($attributes['posterUrl'] ?? '');
	$poster_url = $poster_url ?: ($poster_id ? wp_get_attachment_image_url($poster_id, 'full') : '');
	$poster_url = $poster_url ?: $image_url;
	$nadir_logo_id = absint($attributes['nadirLogoId'] ?? 0);
	$nadir_logo_url = esc_url_raw($attributes['nadirLogoUrl'] ?? '');
	$nadir_logo_url = $nadir_logo_url ?: ($nadir_logo_id ? wp_get_attachment_image_url($nadir_logo_id, 'full') : '');
	$nadir_rotation = max(-180, min(180, (float) ($attributes['nadirRotation'] ?? 0)));
	$nadir_size = max(10, min(100, (float) ($attributes['nadirSize'] ?? 50)));
	$interaction_hint_enabled = ! array_key_exists('interactionHint', $attributes) || ! empty($attributes['interactionHint']);
	$interaction_hint_text = sanitize_text_field($attributes['interactionHintText'] ?? 'Click and drag mouse to explore');
	$interaction_hint = '';
	if ($interaction_hint_enabled && '' !== $interaction_hint_text) {
		$interaction_hint = sprintf(
			'<div class="a360-panorama__interaction-hint" aria-hidden="true"><svg viewBox="0 0 112 72" role="img" focusable="false"><path d="M40 36H14m0 0 8-8m-8 8 8 8M72 36h26m0 0-8-8m8 8-8 8"/><rect x="42" y="8" width="28" height="54" rx="14"/><path d="M56 9v17"/></svg><span>%s</span></div>',
			esc_html($interaction_hint_text)
		);
	}
	$height = max(200, min(1200, absint($attributes['height'] ?? 720)));
	$speed = max(.1, min(12, (float) ($attributes['speed'] ?? 2)));
	$fov = max(35, min(110, (float) ($attributes['fov'] ?? 75)));
	$yaw = max(-180, min(180, (float) ($attributes['yaw'] ?? 0)));
	$resume = max(0, min(30, (float) ($attributes['resume'] ?? 4)));
	$panorama_interval = max(1, min(300, absint($attributes['panoramaInterval'] ?? 8)));
	$overlay = max(0, min(90, absint($attributes['overlayOpacity'] ?? 45)));
	$content_padding = max(0, min(160, absint($attributes['contentPadding'] ?? 50)));
	$horizontal = in_array($attributes['contentHorizontalAlign'] ?? 'left', array('left', 'center', 'right'), true) ? $attributes['contentHorizontalAlign'] : 'left';
	$vertical = in_array($attributes['contentVerticalAlign'] ?? 'top', array('top', 'center', 'bottom'), true) ? $attributes['contentVerticalAlign'] : 'top';
	$align_items = array('left' => 'flex-start', 'center' => 'center', 'right' => 'flex-end')[$horizontal];
	$justify_content = array('top' => 'flex-start', 'center' => 'center', 'bottom' => 'flex-end')[$vertical];
	$autoplay = in_array($attributes['autoplay'] ?? 'always', array('respect', 'always', 'off'), true) ? $attributes['autoplay'] : 'always';
	$hotspots = array();
	$hotspot_image_id = absint($attributes['hotspotImageId'] ?? 0);
	$hotspots_match_image = 0 === $hotspot_image_id || $hotspot_image_id === $image_id;

	if ($hotspots_match_image && ! empty($attributes['hotspots']) && is_array($attributes['hotspots'])) {
		foreach ($attributes['hotspots'] as $hotspot) {
			if (! is_array($hotspot)) {
				continue;
			}

			$type_value = $hotspot['type'] ?? 'info';
			$type = in_array($type_value, array('info', 'product', 'link'), true) ? $type_value : 'info';

			$destination_type_value = $hotspot['destinationTypee'] ?? 'url';
			$destination_type = in_array($destination_type_value, array('url', 'panorama'), true) ? $destination_type_value : 'url';
			$gallery = array();

			if (! empty($hotspot['gallery']) && is_array($hotspot['gallery'])) {
				foreach ($hotspot['gallery'] as $image) {
					if (! is_array($image)) {
						continue;
					}
					$gallery[] = array(
						'id'  => absint($image['id'] ?? 0),
						'url' => esc_url_raw($image['url'] ?? ''),
						'alt' => sanitize_text_field($image['alt'] ?? ''),
					);
				}
			}

			$hotspots[] = array(
				'id'              => sanitize_key($hotspot['id'] ?? wp_unique_id('hotspot-')),
				'yaw'             => max(-180, min(180, (float) ($hotspot['yaw'] ?? 0))),
				'pitch'           => max(-89, min(89, (float) ($hotspot['pitch'] ?? 0))),
				'type'            => $type,
				'title'           => sanitize_text_field($hotspot['title'] ?? ''),
				'visible'         => ! array_key_exists('visible', $hotspot) || ! empty($hotspot['visible']),
				'description'     => sanitize_textarea_field($hotspot['description'] ?? ''),
				'gallery'         => $gallery,
				'youtube'         => esc_url_raw($hotspot['youtube'] ?? ''),
				'productId'       => absint($hotspot['productId'] ?? 0),
				'destinationTypee' => $destination_type,
				'url'             => esc_url_raw($hotspot['url'] ?? ''),
				'targetBlank'     => ! empty($hotspot['targetBlank']),
				'targetImageId'   => absint($hotspot['targetImageId'] ?? 0),
				'targetImageUrl'  => esc_url_raw($hotspot['targetImageUrl'] ?? ''),
			);
		}
	}

	$hotspots_json = wp_json_encode($hotspots);
	$hotspot_map = ! empty($attributes['hotspotsByPanorama']) && is_array($attributes['hotspotsByPanorama']) ? $attributes['hotspotsByPanorama'] : array();
	$scenes = array();
	foreach ($panoramas as $index => $panorama) {
		$key = $panorama['id'] ? 'id:' . $panorama['id'] : 'url:' . $panorama['url'];
		$scene_hotspots = isset($hotspot_map[$key]) ? a360_panorama_sanitize_hotspots($hotspot_map[$key]) : (0 === $index ? $hotspots : array());
		$scenes[] = array('url' => $panorama['url'], 'hotspots' => $scene_hotspots);
	}
	$scenes_json = wp_json_encode($scenes);
	$panoramas_json = wp_json_encode(array_values(array_map(static function ($panorama) {
		return $panorama['url'];
	}, $panoramas)));
	$height_class = $height < 400 ? ' is-short-height is-micro-height' : ($height < 560 ? ' is-short-height' : '');
	$wrapper_class = 'a360-panorama-hero' . $height_class;
	$wrapper = get_block_wrapper_attributes(array('class' => $wrapper_class, 'style' => sprintf('--a360-hero-height:%dpx;--a360-hero-overlay:%.2f;--a360-hero-content-padding:%dpx;--a360-hero-content-x:%s;--a360-hero-content-y:%s;--a360-hero-text-align:%s', $height, $overlay / 100, $content_padding, $align_items, $justify_content, $horizontal)));
	$poster = $poster_url ? sprintf('<img class="a360-panorama-hero__poster" src="%s" alt="" fetchpriority="high" decoding="async">', esc_url($poster_url)) : '';
	wp_enqueue_style('a360-panorama');
	wp_enqueue_style('a360-panorama-hero');
	wp_enqueue_script('a360-panorama-viewer');
	return sprintf(
		'<section %1$s><div class="a360-panorama-hero__media" aria-busy="true">%2$s<div class="a360-panorama" role="region" aria-label="%3$s" tabindex="0" data-image="%4$s" data-images="%20$s" data-scenes="%22$s" data-panorama-interval="%21$s" data-speed="%5$s" data-fov="%6$s" data-resume="%7$s" data-autoplay="%8$s" data-yaw="%14$s" data-hotspots="%15$s" data-nadir-logo="%16$s" data-nadir-rotation="%17$s" data-nadir-size="%18$s" data-pause-label="%12$s" data-resume-label="%13$s"><div class="a360-panorama__viewport"></div>%19$s<div class="a360-panorama__loader" role="status">%9$s</div><div class="a360-panorama__error" role="alert" hidden>%10$s</div><button class="a360-panorama__toggle" type="button" aria-pressed="false" aria-label="%12$s"><span aria-hidden="true">Ⅱ</span></button></div></div><div class="a360-panorama-hero__overlay"></div><div class="a360-panorama-hero__content">%11$s</div></section>',
		$wrapper,
		$poster,
		esc_attr($attributes['label'] ?? __('Interactive 360-degree panorama', 'a360-panorama-hero')),
		esc_url($image_url),
		esc_attr($speed),
		esc_attr($fov),
		esc_attr($resume),
		esc_attr($autoplay),
		esc_html__('Loading panorama…', 'a360-panorama-hero'),
		esc_html__('The panorama could not be loaded.', 'a360-panorama-hero'),
		$content,
		esc_attr__('Pause panorama rotation', 'a360-panorama-hero'),
		esc_attr__('Resume panorama rotation', 'a360-panorama-hero'),
		esc_attr($yaw),
		esc_attr($hotspots_json),
		esc_url($nadir_logo_url),
		esc_attr($nadir_rotation),
		esc_attr($nadir_size),
		$interaction_hint,
		esc_attr($panoramas_json),
		esc_attr($panorama_interval),
		esc_attr($scenes_json)
	);
}

function a360_panorama_register_hero_block()
{
	wp_register_style('a360-panorama-hero', A360_PANORAMA_URL . 'assets/css/a360-panorama-hero.css', array('a360-panorama'), A360_PANORAMA_VERSION);
	wp_register_style('a360-panorama-hero-editor', A360_PANORAMA_URL . 'assets/css/a360-panorama-hero-editor.css', array('a360-panorama-hero'), A360_PANORAMA_VERSION);
	wp_register_script('a360-panorama-hero-editor', A360_PANORAMA_URL . 'assets/js/a360-panorama-hero-editor.js', array('a360-panorama-viewer', 'wp-blocks', 'wp-block-editor', 'wp-components', 'wp-element', 'wp-i18n'), A360_PANORAMA_VERSION, true);
	wp_set_script_translations("a360-panorama-hero-editor", "a360-panorama-hero", A360_PANORAMA_PATH . "languages");
	register_block_type(A360_PANORAMA_PATH . 'blocks/panorama-hero', array('render_callback' => 'a360_panorama_render_hero_block'));
}
add_action('init', 'a360_panorama_register_hero_block');

/**
 * Adds the standard plugin details link to the Plugins screen.
 *
 * @param string[] $plugin_meta Plugin metadata links.
 * @param string   $plugin_file Plugin basename.
 * @return string[]
 */
function a360_panorama_plugin_row_meta($plugin_meta, $plugin_file)
{
	if (plugin_basename(A360_PANORAMA_FILE) !== $plugin_file) {
		return $plugin_meta;
	}

	$details_url = add_query_arg(
		array(
			'tab'       => 'plugin-information',
			'plugin'    => 'a360-panorama-hero',
			'TB_iframe' => 'true',
			'width'     => '600',
			'height'    => '550',
		),
		self_admin_url('plugin-install.php')
	);

	$plugin_meta[] = sprintf(
		'<a href="%1$s" class="thickbox open-plugin-details-modal" aria-label="%2$s">%3$s</a>',
		esc_url($details_url),
		esc_attr__('View details for A360 Panorama Hero', 'a360-panorama-hero'),
		esc_html__('View details', 'a360-panorama-hero')
	);

	return $plugin_meta;
}
add_filter('plugin_row_meta', 'a360_panorama_plugin_row_meta', 10, 2);

/**
 * Supplies plugin information before the WordPress.org listing is available.
 * WordPress.org data takes precedence once the plugin is published there.
 *
 * @param false|object|array $result Plugin information result.
 * @param string             $action Requested API action.
 * @param object             $args   API request arguments.
 * @return false|object|array
 */
function a360_panorama_plugin_information($result, $action, $args)
{
	if ('plugin_information' !== $action || empty($args->slug) || 'a360-panorama-hero' !== $args->slug) {
		return $result;
	}

	$host = (string) wp_parse_url(home_url(), PHP_URL_HOST);
	$is_ddev = strlen($host) >= 10 && 0 === substr_compare($host, '.ddev.site', -10);
	if (! in_array(wp_get_environment_type(), array('local', 'development'), true) && ! $is_ddev) {
		return $result;
	}

	$asset_url = A360_PANORAMA_URL . 'wporg-assets/';

	return (object) array(
		'name'          => 'A360 Panorama Hero',
		'slug'          => 'a360-panorama-hero',
		'version'       => A360_PANORAMA_VERSION,
		'author'        => 'Igor Rubas',
		'author_profile' => 'https://github.com/IgorRubas',
		'homepage'      => 'https://a360.pl/a360-panorama-hero/',
		'requires'      => '6.0',
		'tested'        => '7.1',
		'requires_php'  => '7.4',
		'last_updated'  => gmdate('Y-m-d'),
		'short_description' => __('Turn any WordPress Hero into an immersive, interactive 360° experience.', 'a360-panorama-hero'),
		'sections'      => array(
			'description' => '<h2>Make the first screen unforgettable</h2><p>A360 Panorama Hero replaces a flat Hero background with an interactive 360° world—without taking away the WordPress editing experience you already know.</p><p>Add headings, paragraphs, buttons, groups, or columns as native blocks. Then place the content exactly where it belongs with compact alignment and padding controls.</p><h3>Lightweight by design</h3><p>The plugin keeps its footprint focused and loads panorama assets only on pages where the block or shortcode is actually used. There is no tracking, no remote platform, and no unnecessary site-wide script payload.</p><h3>Built for attention. Designed for WordPress.</h3><ul><li>Native dynamic Gutenberg block with InnerBlocks.</li><li>Focused, lightweight assets loaded only where needed.</li><li>Smooth WebGL panorama with mouse, touch, and keyboard interaction.</li><li>Automatic rotation, pause control, and configurable restart delay.</li><li>Responsive height, field of view, overlay, alignment, and padding.</li><li>Optional loading poster for a polished first impression.</li><li>No tracking and no external service dependency.</li></ul>',
			'installation' => '<ol><li>Activate A360 Panorama Hero.</li><li>Add the block in the WordPress editor.</li><li>Select a 2:1 equirectangular image from the Media Library.</li><li>Edit the foreground with native blocks and publish.</li></ol>',
			'faq' => '<h4>Do I need a special panorama format?</h4><p>Use a standard 2:1 equirectangular JPEG or WebP image.</p><h4>Can I use normal WordPress buttons and headings?</h4><p>Yes. Foreground content is made from native WordPress blocks.</p><h4>Does it connect to an external platform?</h4><p>No. Rendering happens directly in the visitor’s browser.</p>',
			'changelog' => '<h4>1.0</h4><ul><li>Initial public release.</li><li>Native panorama Hero block and standalone shortcode.</li><li>Responsive content alignment and padding controls.</li></ul>',
		),
		'banners'       => array(
			'low'  => $asset_url . 'banner-772x250.png',
			'high' => $asset_url . 'banner-1544x500.png',
		),
		'icons'         => array(
			'1x' => $asset_url . 'icon-128x128.png',
			'2x' => $asset_url . 'icon-256x256.png',
		),
	);
}
add_filter('plugins_api', 'a360_panorama_plugin_information', 20, 3);
