diff --git a/Minecraft-Modern-Theme/clear-cache.php b/Minecraft-Modern-Theme/clear-cache.php index af7c614..c9fcafb 100644 --- a/Minecraft-Modern-Theme/clear-cache.php +++ b/Minecraft-Modern-Theme/clear-cache.php @@ -2,6 +2,11 @@ define('WP_USE_THEMES', false); require('../../../wp-load.php'); +if ( php_sapi_name() !== 'cli' && ! current_user_can( 'manage_options' ) ) { + http_response_code( 403 ); + exit( 'Forbidden: Admin-Login erforderlich.' ); +} + global $wpdb; $deleted1 = $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_mm_yt_live%'"); $deleted2 = $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_mm_yt_live%'"); diff --git a/Minecraft-Modern-Theme/clear-livestream-cache.php b/Minecraft-Modern-Theme/clear-livestream-cache.php index e393a08..3e19d10 100644 --- a/Minecraft-Modern-Theme/clear-livestream-cache.php +++ b/Minecraft-Modern-Theme/clear-livestream-cache.php @@ -6,6 +6,11 @@ define('WP_USE_THEMES', false); require('../../../wp-load.php'); +if ( php_sapi_name() !== 'cli' && ! current_user_can( 'manage_options' ) ) { + http_response_code( 403 ); + exit( 'Forbidden: Admin-Login erforderlich.' ); +} + echo "=== Cache löschen ===\n\n"; // Zähler diff --git a/Minecraft-Modern-Theme/functions.php b/Minecraft-Modern-Theme/functions.php index bbbd3f8..37f8325 100644 --- a/Minecraft-Modern-Theme/functions.php +++ b/Minecraft-Modern-Theme/functions.php @@ -1,3939 +1,34 @@ 9999, - 'width' => 9999, - 'flex-height' => true, - 'flex-width' => true, - 'header_text' => array( 'site-title', 'site-description' ), - ) ); - - add_theme_support( 'custom-background' ); - - register_nav_menus( array( - 'primary' => __( 'Hauptmenü', 'minecraft-modern-theme' ), - 'footer' => __( 'Footer-Menü', 'minecraft-modern-theme' ), - ) ); - - // FIX: 'script' und 'style' ergänzt für sauberes HTML5-Output-Format - add_theme_support( 'html5', array( - 'search-form', 'comment-form', 'comment-list', - 'gallery', 'caption', 'script', 'style', - ) ); -} -add_action( 'after_setup_theme', 'minecraft_modern_setup' ); - - -// === Styles & Scripts laden === -function minecraft_modern_scripts() { - // Haupt-Stylesheet - wp_enqueue_style( 'minecraft-modern-style', get_stylesheet_uri(), array(), filemtime( get_stylesheet_directory() . '/style.css' ) ); - - // Swiper.js CSS - wp_enqueue_style( 'swiper-css', 'https://cdn.jsdelivr.net/npm/swiper@8/swiper-bundle.min.css' ); - - // Header-Scroll + Suche Toggle - wp_enqueue_script( - 'minecraft-modern-header-script', - get_template_directory_uri() . '/js/header-scroll.js', - array(), - filemtime( get_template_directory() . '/js/header-scroll.js' ), - true - ); - - // Navigation (Dropdown + Außenklick-Schließen) - wp_enqueue_script( - 'minecraft-navigation', - get_template_directory_uri() . '/js/navigation.js', - array(), - '1.1', - true - ); - - // Swiper.js - wp_enqueue_script( - 'swiper-js', - 'https://cdn.jsdelivr.net/npm/swiper@8/swiper-bundle.min.js', - array(), - '8.0.0', - true - ); - - // Slider-Init - wp_enqueue_script( - 'minecraft-modern-slider-script', - get_template_directory_uri() . '/js/slider-init.js', - array( 'swiper-js' ), - '1.1', - true - ); - - // Theme Toggle - wp_enqueue_script( - 'theme-toggle-script', - get_template_directory_uri() . '/js/theme-toggle.js', - array(), - '1.1', - true - ); - - // BUG-FIX: post_type_exists('faq') prüft nur ob der CPT registriert ist, nicht ob wir - // auf einer FAQ-Seite sind – das Script wurde damit seitenübergreifend geladen. - // Jetzt: nur auf FAQ-Archiv-, Einzel- und Seiten mit FAQ-Template laden. - if ( post_type_exists( 'faq' ) && ( is_post_type_archive( 'faq' ) || is_singular( 'faq' ) || is_page( 'FAQ' ) || is_page( 'faq' ) ) ) { - wp_enqueue_script( - 'faq-accordion-script', - get_template_directory_uri() . '/js/faq-accordion.js', - array(), - '1.0', - true - ); - } - - // FIX: 'loop' ergänzt – war in slider-init.js als sliderSettings.loop referenziert, aber nie übergeben - wp_localize_script( - 'minecraft-modern-slider-script', - 'sliderSettings', - array( - 'hideArrows' => get_theme_mod( 'slider_hide_arrows', false ) ? '1' : '0', - 'hidePagination' => get_theme_mod( 'slider_hide_pagination', false ) ? '1' : '0', - 'effect' => get_theme_mod( 'slider_effect', 'fade' ), - 'direction' => get_theme_mod( 'slider_direction', 'horizontal' ), - 'defaultMode' => get_theme_mod( 'default_theme_mode', 'dark' ), - 'loop' => get_theme_mod( 'slider_loop', true ) ? '1' : '0', - 'ajax_url' => admin_url( 'admin-ajax.php' ), - ) - ); - - wp_localize_script( - 'minecraft-modern-header-script', - 'headerSettings', - array( - 'isCustomizer' => is_customize_preview(), - ) - ); -} -add_action( 'wp_enqueue_scripts', 'minecraft_modern_scripts' ); - - -// FIX: Scroll-to-Top via Customizer ein-/ausblendbar -function minecraft_modern_scroll_to_top_css() { - if ( ! get_theme_mod( 'show_scroll_to_top', true ) ) { - wp_add_inline_style( 'minecraft-modern-style', '#scroll-to-top { display: none !important; }' ); - } -} -add_action( 'wp_enqueue_scripts', 'minecraft_modern_scroll_to_top_css', 25 ); - - -// === Customizer-Datei laden === +require get_template_directory() . '/inc/theme-setup.php'; require get_template_directory() . '/inc/customizer.php'; - - - - - -// ========================================================================= -// INTELLIGENTER SUPPORT-ASSISTENT -// ========================================================================= -// Ausgelagert in /inc/assistant-widget.php require get_template_directory() . '/inc/assistant-widget.php'; - - -// === Theme-Updater-Datei laden === require get_template_directory() . '/inc/theme-updater.php'; - - -// === Footer-Widgets registrieren === -function minecraft_modern_footer_widgets() { - register_sidebar( array( - 'name' => __( 'Footer Links', 'minecraft-modern-theme' ), - 'id' => 'footer-left', - 'description' => __( 'Widget-Bereich links im Footer.', 'minecraft-modern-theme' ), - 'before_widget' => '
', - 'after_widget' => '
', - 'before_title' => '

', - 'after_title' => '

', - ) ); - for ( $i = 1; $i <= 3; $i++ ) { - register_sidebar( array( - 'name' => sprintf( __( 'Footer Spalte %d', 'minecraft-modern-theme' ), $i ), - 'id' => 'footer-' . $i, - 'description' => sprintf( __( 'Widget für die %d. Spalte im Footer.', 'minecraft-modern-theme' ), $i ), - 'before_widget' => '
', - 'after_widget' => '
', - 'before_title' => '

', - 'after_title' => '

', - ) ); - } - register_sidebar( array( - 'name' => __( 'Footer Rechts', 'minecraft-modern-theme' ), - 'id' => 'footer-right', - 'description' => __( 'Widget-Bereich rechts im Footer.', 'minecraft-modern-theme' ), - 'before_widget' => '
', - 'after_widget' => '
', - 'before_title' => '

', - 'after_title' => '

', - ) ); -} -add_action( 'widgets_init', 'minecraft_modern_footer_widgets' ); - - -// === Homepage Sidebar registrieren === -function minecraft_modern_homepage_sidebar() { - register_sidebar( array( - 'name' => __( 'Startseiten Sidebar - Oben', 'minecraft-modern-theme' ), - 'id' => 'homepage-sidebar-top', - 'description' => __( 'Widget-Bereich oben in der Sidebar (z.B. für wichtige Infos).', 'minecraft-modern-theme' ), - 'before_widget' => '
', - 'after_widget' => '
', - 'before_title' => '

', - 'after_title' => '

', - ) ); - register_sidebar( array( - 'name' => __( 'Startseiten Sidebar - Mitte 1', 'minecraft-modern-theme' ), - 'id' => 'homepage-sidebar-middle-1', - 'description' => __( 'Widget-Bereich in der Mitte der Sidebar.', 'minecraft-modern-theme' ), - 'before_widget' => '
', - 'after_widget' => '
', - 'before_title' => '

', - 'after_title' => '

', - ) ); - register_sidebar( array( - 'name' => __( 'Startseiten Sidebar - Mitte 2', 'minecraft-modern-theme' ), - 'id' => 'homepage-sidebar-middle-2', - 'description' => __( 'Zweiter Widget-Bereich in der Mitte der Sidebar.', 'minecraft-modern-theme' ), - 'before_widget' => '
', - 'after_widget' => '
', - 'before_title' => '

', - 'after_title' => '

', - ) ); - register_sidebar( array( - 'name' => __( 'Startseiten Sidebar - Unten', 'minecraft-modern-theme' ), - 'id' => 'homepage-sidebar-bottom', - 'description' => __( 'Widget-Bereich unten in der Sidebar.', 'minecraft-modern-theme' ), - 'before_widget' => '
', - 'after_widget' => '
', - 'before_title' => '

', - 'after_title' => '

', - ) ); - register_sidebar( array( - 'name' => __( 'Startseiten Sidebar - Extra', 'minecraft-modern-theme' ), - 'id' => 'homepage-sidebar-extra', - 'description' => __( 'Zusätzlicher Widget-Bereich für spezielle Inhalte.', 'minecraft-modern-theme' ), - 'before_widget' => '
', - 'after_widget' => '
', - 'before_title' => '

', - 'after_title' => '

', - ) ); -} -add_action( 'widgets_init', 'minecraft_modern_homepage_sidebar' ); - - -/** - * Rendert alle Sidebar-Sections der Homepage. - * Ersetzt den doppelten Sidebar-Code in front-page.php. - */ -function minecraft_modern_render_sidebar_sections() { - $sections = array( - 'homepage-sidebar-top', - 'homepage-sidebar-middle-1', - 'homepage-sidebar-middle-2', - 'homepage-sidebar-bottom', - 'homepage-sidebar-extra', - ); - $classes = array( - 'homepage-sidebar-top' => 'sidebar-top', - 'homepage-sidebar-middle-1' => 'sidebar-middle-1', - 'homepage-sidebar-middle-2' => 'sidebar-middle-2', - 'homepage-sidebar-bottom' => 'sidebar-bottom', - 'homepage-sidebar-extra' => 'sidebar-extra', - ); - foreach ( $sections as $sidebar_id ) { - if ( is_active_sidebar( $sidebar_id ) ) { - $class = isset( $classes[ $sidebar_id ] ) ? ' ' . $classes[ $sidebar_id ] : ''; - echo ''; - } - } -} - - -// === FAQ Custom Post Type & Taxonomy === -function create_faq_post_type() { - if ( get_theme_mod( 'faq_enabled', true ) ) { - register_post_type( 'faq', array( - 'labels' => array( - 'name' => __( 'FAQs', 'minecraft-modern-theme' ), - 'singular_name' => __( 'FAQ', 'minecraft-modern-theme' ), - 'add_new' => __( 'Neue FAQ hinzufügen', 'minecraft-modern-theme' ), - 'add_new_item' => __( 'Neue FAQ hinzufügen', 'minecraft-modern-theme' ), - 'edit_item' => __( 'FAQ bearbeiten', 'minecraft-modern-theme' ), - 'new_item' => __( 'Neue FAQ', 'minecraft-modern-theme' ), - 'view_item' => __( 'FAQ ansehen', 'minecraft-modern-theme' ), - 'search_items' => __( 'FAQs durchsuchen', 'minecraft-modern-theme' ), - 'not_found' => __( 'Keine FAQs gefunden', 'minecraft-modern-theme' ), - 'not_found_in_trash' => __( 'Keine FAQs im Papierkorb gefunden', 'minecraft-modern-theme' ), - 'all_items' => __( 'Alle FAQs', 'minecraft-modern-theme' ), - ), - 'public' => true, - 'has_archive' => true, - 'menu_icon' => 'dashicons-format-chat', - 'supports' => array( 'title', 'editor', 'page-attributes' ), - 'rewrite' => array( 'slug' => 'faq' ), - 'show_in_rest' => true, - ) ); - register_taxonomy( 'faq_category', 'faq', array( - 'label' => __( 'FAQ Kategorien', 'minecraft-modern-theme' ), - 'rewrite' => array( 'slug' => 'faq-kategorie' ), - 'hierarchical' => true, - 'show_in_rest' => true, - ) ); - } -} -add_action( 'init', 'create_faq_post_type' ); - - -// ============================================================================= -// Automatische "Home" Seitenerstellung -// ============================================================================= - -function set_static_front_page_automatically() { - if ( 'page' !== get_option( 'show_on_front' ) ) { - // BUG-FIX: get_page_by_title() ist seit WP 6.2 deprecated. Ersetzt durch WP_Query. - $home_query = new WP_Query( array( - 'post_type' => 'page', - 'title' => 'Home', - 'post_status' => 'publish', - 'posts_per_page' => 1, - 'no_found_rows' => true, - 'update_post_meta_cache' => false, - 'update_post_term_cache' => false, - ) ); - $home_page = $home_query->have_posts() ? $home_query->posts[0] : null; - if ( ! $home_page ) { - $home_page_id = wp_insert_post( array( - 'post_title' => 'Home', - 'post_content' => 'Diese Seite dient als statische Startseite.', - 'post_status' => 'publish', - 'post_type' => 'page', - 'post_author' => 1, - ) ); - } else { - $home_page_id = $home_page->ID; - } - if ( $home_page_id ) { - update_option( 'show_on_front', 'page' ); - update_option( 'page_on_front', $home_page_id ); - } - } -} -add_action( 'after_switch_theme', 'set_static_front_page_automatically' ); - - -function add_home_body_class( $classes ) { - if ( is_front_page() && ! get_theme_mod( 'show_home_title', true ) ) { - $classes[] = 'home-title-hidden'; - } - return $classes; -} -add_filter( 'body_class', 'add_home_body_class' ); - - -// ============================================================================= -// FAQ-Seitenerstellung -// ============================================================================= - -function create_faq_page_automatically() { - if ( ! get_theme_mod( 'faq_enabled', true ) ) return; - - // BUG-FIX: get_page_by_title() ist seit WP 6.2 deprecated. Ersetzt durch WP_Query. - $faq_query = new WP_Query( array( - 'post_type' => 'page', - 'title' => 'FAQ', - 'post_status' => 'publish', - 'posts_per_page' => 1, - 'no_found_rows' => true, - 'update_post_meta_cache' => false, - 'update_post_term_cache' => false, - ) ); - if ( $faq_query->have_posts() ) return; - - wp_insert_post( array( - 'post_title' => 'FAQ', - 'post_content' => 'Diese Seite zeigt alle FAQs an. Der Inhalt wird automatisch generiert.', - 'post_status' => 'publish', - 'post_type' => 'page', - 'post_author' => 1, - ) ); -} -add_action( 'customize_save_after', 'create_faq_page_automatically' ); - - -function load_faq_page_template( $template ) { - if ( get_theme_mod( 'faq_enabled', true ) && is_page() ) { - global $post; - if ( $post && $post->post_title === 'FAQ' ) { - return get_template_directory() . '/archive-faq.php'; - } - } - return $template; -} -add_filter( 'template_include', 'load_faq_page_template' ); - - -// ========================================================================= -// CUSTOM LOGIN FUNCTIONS -// ========================================================================= - -function minecraft_modern_login_assets() { - wp_enqueue_style( 'minecraft-modern-login-style', get_template_directory_uri() . '/css/login-style.css' ); - wp_enqueue_style( 'font-awesome', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css' ); - - // FIX: login-slider.js – erster Slide sofort sichtbar (fixiert) - wp_enqueue_script( 'minecraft-avatar-slider-script', get_template_directory_uri() . '/js/login-slider.js', array( 'jquery' ), '1.1', true ); - wp_enqueue_script( 'minecraft-modern-login-script', get_template_directory_uri() . '/js/login-script.js', array( 'jquery' ), '1.0', true ); - - wp_add_inline_script( 'minecraft-modern-login-script', " - jQuery(document).ready(function($) { - $('.forgetmenot, #nav').wrapAll('
'); - }); - " ); - - $slider_speed = get_theme_mod( 'login_avatar_slider_speed', 4 ); - wp_localize_script( 'minecraft-avatar-slider-script', 'avatarSliderSettings', array( - 'speed' => $slider_speed * 1000, - ) ); - - $login_bg_image = get_theme_mod( 'login_background_image' ); - if ( $login_bg_image ) { - wp_add_inline_style( 'minecraft-modern-login-style', "body.login { background-image: url('" . esc_url( $login_bg_image ) . "') !important; }" ); - } - $logo_url = get_theme_mod( 'login_logo' ); - if ( $logo_url ) { - wp_add_inline_style( 'minecraft-modern-login-style', ".login h1 a { background-image: url('" . esc_url( $logo_url ) . "') !important; }" ); - } -} -add_action( 'login_enqueue_scripts', 'minecraft_modern_login_assets' ); - - -function add_minecraft_avatar_slider_to_login() { - $avatar_html = '
'; - $has_avatars = false; - - for ( $i = 1; $i <= 5; $i++ ) { - $uuid = get_theme_mod( 'login_avatar_uuid_' . $i ); - if ( ! empty( $uuid ) ) { - $has_avatars = true; - $avatar_url = 'https://visage.surgeplay.com/full/' . $uuid . '.png'; - // FIX: Klasse wird hier gesetzt, JS überschreibt sie trotzdem (kompatibel) - $active_class = ( $i === 1 ) ? 'avatar-slide avatar-slide-active' : 'avatar-slide'; - $avatar_html .= 'Minecraft Avatar ' . $i . ''; - } - } - $avatar_html .= '
'; - - if ( $has_avatars ) { - echo $avatar_html; - } -} -add_action( 'login_form', 'add_minecraft_avatar_slider_to_login' ); - - -function add_post_login_links() { - ?> -
- ← Zu -
- - - - - '3.0', - '_exported' => date( 'Y-m-d H:i:s' ), - '_theme' => $theme_slug, - ); - - // 1. Alle Customizer-Einstellungen (Theme Mods) - // Enthält: Farben, Slider, Hero, Social Links, Menü-Design, Login-Einstellungen, Sidebar-Einstellungen usw. - $data['theme_mods'] = get_theme_mods(); - - // 2. Announcement-Bar (gespeichert als wp_options, nicht als Theme Mod) - $announcement_keys = array( - 'mm_announcement_enabled', 'mm_announcement_text', 'mm_announcement_bg', - 'mm_announcement_color', 'mm_announcement_font_size', 'mm_announcement_font_family', - 'mm_announcement_position', 'mm_announcement_countdown_enabled', - 'mm_announcement_countdown_label', 'mm_announcement_countdown_date', - 'mm_announcement_countdown_expired_msg', - ); - foreach ( $announcement_keys as $key ) { - $data['announcement'][ $key ] = get_option( $key ); - } - - // 3. Widget-Konfigurationen aller Theme-Sidebars - $theme_sidebars = array( - 'single-post-sidebar', - 'homepage-sidebar-top', 'homepage-sidebar-middle-1', - 'homepage-sidebar-middle-2', 'homepage-sidebar-bottom', - 'homepage-sidebar-extra', 'footer-1', 'footer-2', 'footer-3', - ); - $all_sidebars = wp_get_sidebars_widgets(); - $widget_data = array(); - foreach ( $theme_sidebars as $sidebar_id ) { - $widget_data[ $sidebar_id ] = array(); - if ( empty( $all_sidebars[ $sidebar_id ] ) ) continue; - foreach ( $all_sidebars[ $sidebar_id ] as $widget_id ) { - if ( ! preg_match( '/^(.+)-(\d+)$/', $widget_id, $m ) ) continue; - $type = $m[1]; - $index = intval( $m[2] ); - $all = get_option( 'widget_' . $type, array() ); - $widget_data[ $sidebar_id ][] = array( - 'type' => $type, - 'index' => $index, - 'settings' => isset( $all[ $index ] ) ? $all[ $index ] : array(), - ); - } - } - $data['widgets'] = $widget_data; - - // 4. Team-Mitglieder (mit UUID, Banner, Thumbnail) - $team_data = array(); - $team_query = new WP_Query( array( - 'post_type' => 'team_member', - 'posts_per_page' => -1, - 'orderby' => 'menu_order', - 'order' => 'ASC', - ) ); - if ( $team_query->have_posts() ) { - while ( $team_query->have_posts() ) { - $team_query->the_post(); - $post_id = get_the_ID(); - $team_data[] = array( - 'title' => get_the_title(), - 'content' => get_the_content(), - 'rank' => get_post_meta( $post_id, '_team_member_rank', true ), - 'uuid' => get_post_meta( $post_id, '_team_member_uuid', true ), - 'banner_id' => get_post_meta( $post_id, '_team_member_banner', true ), - 'thumbnail_id' => get_post_thumbnail_id( $post_id ), - 'menu_order' => get_post_field( 'menu_order', $post_id ), - ); - } - wp_reset_postdata(); - } - $data['team'] = $team_data; - - // 5. FAQ-Einträge (theme-eigener Custom Post Type) - $faq_data = array(); - $faq_query = new WP_Query( array( - 'post_type' => 'faq', - 'posts_per_page' => -1, - 'orderby' => 'menu_order', - 'order' => 'ASC', - ) ); - if ( $faq_query->have_posts() ) { - while ( $faq_query->have_posts() ) { - $faq_query->the_post(); - $terms = wp_get_post_terms( get_the_ID(), 'faq_category', array( 'fields' => 'names' ) ); - $faq_data[] = array( - 'title' => get_the_title(), - 'content' => get_the_content(), - 'menu_order' => get_post_field( 'menu_order', get_the_ID() ), - 'categories' => is_wp_error( $terms ) ? array() : $terms, - ); - } - wp_reset_postdata(); - } - $data['faqs'] = $faq_data; - - // 6. Custom CSS (Customizer → Zusätzliches CSS) - $data['custom_css'] = wp_get_custom_css(); - - // 7. Homepage-Seite (falls eingestellt) - $homepage_id = get_option( 'page_on_front' ); - if ( $homepage_id ) { - $homepage = get_post( $homepage_id ); - if ( $homepage ) { - $data['homepage'] = array( - 'title' => $homepage->post_title, - 'content' => $homepage->post_content, - 'excerpt' => $homepage->post_excerpt, - 'featured_img' => get_post_thumbnail_id( $homepage_id ), - ); - } - } - - // 8. Navigation Menüs mit Items - $nav_menus = array(); - $all_nav_menus = wp_get_nav_menus(); - foreach ( $all_nav_menus as $menu ) { - $nav_menus[ $menu->slug ] = array( - 'name' => $menu->name, - 'description' => $menu->description, - 'items' => array(), - ); - $menu_items = wp_get_nav_menu_items( $menu->term_id ); - if ( $menu_items ) { - foreach ( $menu_items as $item ) { - $nav_menus[ $menu->slug ]['items'][] = array( - 'title' => $item->title, - 'url' => $item->url, - 'description' => $item->description, - 'type' => $item->type, - 'type_label' => $item->type_label, - 'object' => $item->object, - 'object_id' => $item->object_id, - 'parent' => $item->menu_item_parent, - 'menu_order' => $item->menu_order, - 'target' => get_post_meta( $item->ID, '_menu_item_target', true ), - 'classes' => implode( ' ', (array) $item->classes ), - 'xfn' => get_post_meta( $item->ID, '_menu_item_xfn', true ), - ); - } - } - } - $data['nav_menus'] = $nav_menus; - - // 9. Menü-Positionen (welches Menü ist welchem Theme-Location zugewiesen) - $data['nav_menu_locations'] = get_theme_mod( 'nav_menu_locations', array() ); - - $json = json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ); - header( 'Content-Type: application/json; charset=utf-8' ); - header( 'Content-Disposition: attachment; filename=' . $theme_slug . '-theme-backup-' . date( 'Y-m-d' ) . '.json' ); - header( 'Pragma: no-cache' ); - header( 'Expires: 0' ); - echo $json; - exit; -} - - -add_action( 'wp_ajax_import_theme_settings', 'handle_theme_settings_import' ); - -function handle_theme_settings_import() { - if ( ! current_user_can( 'edit_theme_options' ) ) { - wp_send_json_error( __( 'Keine Berechtigung.', 'minecraft-modern-theme' ) ); - } - check_ajax_referer( 'theme-import-nonce', 'nonce' ); - - if ( empty( $_FILES['import_file']['tmp_name'] ) ) { - wp_send_json_error( __( 'Keine Datei hochgeladen.', 'minecraft-modern-theme' ) ); - } - - $json_content = file_get_contents( $_FILES['import_file']['tmp_name'] ); - $data = json_decode( $json_content, true ); - - if ( json_last_error() !== JSON_ERROR_NONE || ! is_array( $data ) ) { - wp_send_json_error( __( 'Ungültige JSON-Datei.', 'minecraft-modern-theme' ) ); - } - - $imported = array(); - $version = isset( $data['_version'] ) ? $data['_version'] : '1.0'; - - // ------------------------------------------------------------------------- - // 1. Customizer / Theme Mods - // ------------------------------------------------------------------------- - $mods = array(); - if ( $version === '3.0' && isset( $data['theme_mods'] ) ) { - $mods = $data['theme_mods']; - } elseif ( $version === '2.0' && isset( $data['theme_mods'] ) ) { - $mods = $data['theme_mods']; - } else { - // Altes v1-Format: alles auf oberster Ebene - $skip = array( '_version', '_exported', '_theme', 'announcement', 'widgets', 'team', 'faqs', 'menus', 'wp_options', 'custom_css', 'team_data' ); - foreach ( $data as $k => $v ) { - if ( ! in_array( $k, $skip ) ) $mods[ $k ] = $v; - } - } - foreach ( $mods as $key => $value ) { - set_theme_mod( $key, $value ); - } - $imported[] = 'Customizer-Einstellungen'; - - // ------------------------------------------------------------------------- - // 2. Announcement-Bar - // ------------------------------------------------------------------------- - $announcement_keys = array( - 'mm_announcement_enabled', 'mm_announcement_text', 'mm_announcement_bg', - 'mm_announcement_color', 'mm_announcement_font_size', 'mm_announcement_font_family', - 'mm_announcement_position', 'mm_announcement_countdown_enabled', - 'mm_announcement_countdown_label', 'mm_announcement_countdown_date', - 'mm_announcement_countdown_expired_msg', - ); - $ann = isset( $data['announcement'] ) ? $data['announcement'] : $data; - foreach ( $announcement_keys as $key ) { - if ( array_key_exists( $key, $ann ) ) { - update_option( $key, $ann[ $key ] ); - } - } - $imported[] = 'Ankündigung'; - - // ------------------------------------------------------------------------- - // 3. Widgets - // ------------------------------------------------------------------------- - if ( ! empty( $data['widgets'] ) ) { - $current_sidebars = get_option( 'sidebars_widgets', array() ); - foreach ( $data['widgets'] as $sidebar_id => $widgets ) { - $current_sidebars[ $sidebar_id ] = array(); - foreach ( $widgets as $widget ) { - $type = sanitize_key( $widget['type'] ); - $index = intval( $widget['index'] ); - $all = get_option( 'widget_' . $type, array() ); - $all[ $index ] = $widget['settings']; - update_option( 'widget_' . $type, $all ); - $current_sidebars[ $sidebar_id ][] = $type . '-' . $index; - } - } - update_option( 'sidebars_widgets', $current_sidebars ); - $imported[] = 'Widgets'; - } - - // ------------------------------------------------------------------------- - // 4. Team-Mitglieder - // ------------------------------------------------------------------------- - $team_data = isset( $data['team'] ) ? $data['team'] : ( isset( $data['team_data'] ) ? $data['team_data'] : array() ); - if ( ! empty( $team_data ) ) { - $existing = new WP_Query( array( 'post_type' => 'team_member', 'posts_per_page' => -1, 'fields' => 'ids' ) ); - if ( $existing->have_posts() ) { - foreach ( $existing->posts as $pid ) wp_delete_post( $pid, true ); - } - wp_reset_postdata(); - foreach ( $team_data as $member ) { - $id = wp_insert_post( array( - 'post_title' => sanitize_text_field( $member['title'] ), - 'post_content' => wp_kses_post( $member['content'] ), - 'post_type' => 'team_member', - 'post_status' => 'publish', - 'menu_order' => intval( isset( $member['menu_order'] ) ? $member['menu_order'] : 0 ), - ) ); - if ( $id && ! is_wp_error( $id ) ) { - // Rank - if ( ! empty( $member['rank'] ) ) { - update_post_meta( $id, '_team_member_rank', sanitize_text_field( $member['rank'] ) ); - } - // UUID - if ( ! empty( $member['uuid'] ) ) { - update_post_meta( $id, '_team_member_uuid', sanitize_text_field( $member['uuid'] ) ); - } - // Thumbnail - if ( ! empty( $member['thumbnail_id'] ) ) { - set_post_thumbnail( $id, intval( $member['thumbnail_id'] ) ); - } - // Banner - if ( ! empty( $member['banner_id'] ) ) { - update_post_meta( $id, '_team_member_banner', intval( $member['banner_id'] ) ); - } - } - } - $imported[] = count( $team_data ) . ' Team-Mitglieder'; - } - - // ------------------------------------------------------------------------- - // 5. FAQs - // ------------------------------------------------------------------------- - if ( ! empty( $data['faqs'] ) ) { - $existing = new WP_Query( array( 'post_type' => 'faq', 'posts_per_page' => -1, 'fields' => 'ids' ) ); - if ( $existing->have_posts() ) { - foreach ( $existing->posts as $pid ) wp_delete_post( $pid, true ); - } - wp_reset_postdata(); - foreach ( $data['faqs'] as $faq ) { - $id = wp_insert_post( array( - 'post_title' => sanitize_text_field( $faq['title'] ), - 'post_content' => wp_kses_post( $faq['content'] ), - 'post_type' => 'faq', - 'post_status' => 'publish', - 'menu_order' => intval( isset( $faq['menu_order'] ) ? $faq['menu_order'] : 0 ), - ) ); - if ( $id && ! is_wp_error( $id ) && ! empty( $faq['categories'] ) ) { - foreach ( (array) $faq['categories'] as $cat_name ) { - $term = term_exists( sanitize_text_field( $cat_name ), 'faq_category' ); - if ( ! $term ) { - $term = wp_insert_term( sanitize_text_field( $cat_name ), 'faq_category' ); - } - if ( ! is_wp_error( $term ) ) { - wp_set_post_terms( $id, array( intval( $term['term_id'] ) ), 'faq_category', true ); - } - } - } - } - $imported[] = count( $data['faqs'] ) . ' FAQs'; - } - - // ------------------------------------------------------------------------- - // 6. Custom CSS - // ------------------------------------------------------------------------- - if ( isset( $data['custom_css'] ) && $data['custom_css'] !== '' ) { - wp_update_custom_css_post( $data['custom_css'] ); - $imported[] = 'Custom CSS'; - } - - // ------------------------------------------------------------------------- - // 7. Homepage-Seite - // ------------------------------------------------------------------------- - if ( ! empty( $data['homepage'] ) ) { - $homepage_id = get_option( 'page_on_front' ); - if ( $homepage_id ) { - wp_update_post( array( - 'ID' => $homepage_id, - 'post_title' => sanitize_text_field( $data['homepage']['title'] ), - 'post_content' => wp_kses_post( $data['homepage']['content'] ), - 'post_excerpt' => sanitize_textarea_field( $data['homepage']['excerpt'] ), - ) ); - if ( ! empty( $data['homepage']['featured_img'] ) ) { - set_post_thumbnail( $homepage_id, intval( $data['homepage']['featured_img'] ) ); - } - $imported[] = 'Homepage-Seite'; - } - } - - // ------------------------------------------------------------------------- - // 8. Navigation Menüs mit Items - // ------------------------------------------------------------------------- - if ( ! empty( $data['nav_menus'] ) ) { - $menu_id_map = array(); // slug => term_id Mapping für Item-Parent-Zuordnung - - // Alle existierenden Menüs löschen - $existing_menus = wp_get_nav_menus(); - foreach ( $existing_menus as $menu ) { - wp_delete_nav_menu( $menu->term_id ); - } - - // Neue Menüs und Items importieren - foreach ( $data['nav_menus'] as $menu_slug => $menu_data ) { - $new_menu = wp_create_nav_menu( $menu_data['name'] ); - if ( ! is_wp_error( $new_menu ) ) { - $menu_id_map[ $menu_slug ] = $new_menu; - - // Items hinzufügen - if ( ! empty( $menu_data['items'] ) ) { - $item_id_map = array(); // Altes Item ID => Neues Item ID Mapping - - // Erste Runde: Root-Items (parent = 0) - foreach ( $menu_data['items'] as $idx => $item ) { - if ( empty( $item['parent'] ) || $item['parent'] == 0 ) { - $item_id = wp_update_nav_menu_item( $new_menu, 0, array( - 'menu-item-title' => sanitize_text_field( $item['title'] ), - 'menu-item-url' => esc_url_raw( $item['url'] ), - 'menu-item-description' => sanitize_text_field( $item['description'] ), - 'menu-item-type' => sanitize_key( $item['type'] ), - 'menu-item-object' => sanitize_key( $item['object'] ), - 'menu-item-object-id' => intval( $item['object_id'] ), - 'menu-item-target' => sanitize_text_field( $item['target'] ), - 'menu-item-classes' => sanitize_text_field( $item['classes'] ), - 'menu-item-xfn' => sanitize_text_field( $item['xfn'] ), - 'menu-item-status' => 'publish', - ) ); - if ( $item_id && ! is_wp_error( $item_id ) ) { - $item_id_map[ $idx ] = $item_id; - } - } - } - - // Zweite Runde: Sub-Items (parent > 0) - foreach ( $menu_data['items'] as $idx => $item ) { - if ( ! empty( $item['parent'] ) && $item['parent'] > 0 ) { - $parent_item_id = isset( $item_id_map[ $item['parent'] - 1 ] ) ? $item_id_map[ $item['parent'] - 1 ] : 0; - $item_id = wp_update_nav_menu_item( $new_menu, 0, array( - 'menu-item-title' => sanitize_text_field( $item['title'] ), - 'menu-item-url' => esc_url_raw( $item['url'] ), - 'menu-item-description' => sanitize_text_field( $item['description'] ), - 'menu-item-type' => sanitize_key( $item['type'] ), - 'menu-item-object' => sanitize_key( $item['object'] ), - 'menu-item-object-id' => intval( $item['object_id'] ), - 'menu-item-parent-id' => $parent_item_id, - 'menu-item-target' => sanitize_text_field( $item['target'] ), - 'menu-item-classes' => sanitize_text_field( $item['classes'] ), - 'menu-item-xfn' => sanitize_text_field( $item['xfn'] ), - 'menu-item-status' => 'publish', - ) ); - if ( $item_id && ! is_wp_error( $item_id ) ) { - $item_id_map[ $idx ] = $item_id; - } - } - } - } - } - } - $imported[] = 'Navigation Menüs (' . count( $data['nav_menus'] ) . ')'; - } - - // ------------------------------------------------------------------------- - // 9. Menü-Positionen - // ------------------------------------------------------------------------- - if ( ! empty( $data['nav_menu_locations'] ) ) { - set_theme_mod( 'nav_menu_locations', $data['nav_menu_locations'] ); - $imported[] = 'Menü-Positionen'; - } - - wp_send_json_success( sprintf( - __( 'Erfolgreich wiederhergestellt: %s', 'minecraft-modern-theme' ), - implode( ', ', $imported ) - ) ); -} - - -// ========================================================================= -// ANNOUNCEMENT BAR -// ========================================================================= - -function mm_announcement_get_font_list() { - return array( - 'inherit' => array( 'label' => 'Theme-Standard', 'css' => 'inherit', 'google' => false, 'google_name' => '' ), - 'Arial' => array( 'label' => 'Arial', 'css' => 'Arial, Helvetica, sans-serif', 'google' => false, 'google_name' => '' ), - 'Roboto' => array( 'label' => 'Roboto', 'css' => "'Roboto', sans-serif", 'google' => true, 'google_name' => 'Roboto' ), - 'Montserrat' => array( 'label' => 'Montserrat', 'css' => "'Montserrat', sans-serif", 'google' => true, 'google_name' => 'Montserrat' ), - 'Open Sans' => array( 'label' => 'Open Sans', 'css' => "'Open Sans', sans-serif", 'google' => true, 'google_name' => 'Open+Sans' ), - 'Lato' => array( 'label' => 'Lato', 'css' => "'Lato', sans-serif", 'google' => true, 'google_name' => 'Lato' ), - 'Poppins' => array( 'label' => 'Poppins', 'css' => "'Poppins', sans-serif", 'google' => true, 'google_name' => 'Poppins' ), - 'Source Sans Pro' => array( 'label' => 'Source Sans Pro', 'css' => "'Source Sans Pro', sans-serif", 'google' => true, 'google_name' => 'Source+Sans+Pro' ), - 'Noto Sans' => array( 'label' => 'Noto Sans', 'css' => "'Noto Sans', sans-serif", 'google' => true, 'google_name' => 'Noto+Sans' ), - 'Raleway' => array( 'label' => 'Raleway', 'css' => "'Raleway', sans-serif", 'google' => true, 'google_name' => 'Raleway' ), - 'Merriweather' => array( 'label' => 'Merriweather', 'css' => "'Merriweather', serif", 'google' => true, 'google_name' => 'Merriweather' ), - 'Playfair Display' => array( 'label' => 'Playfair Display', 'css' => "'Playfair Display', serif", 'google' => true, 'google_name' => 'Playfair+Display' ), - 'Oswald' => array( 'label' => 'Oswald', 'css' => "'Oswald', sans-serif", 'google' => true, 'google_name' => 'Oswald' ), - 'Rubik' => array( 'label' => 'Rubik', 'css' => "'Rubik', sans-serif", 'google' => true, 'google_name' => 'Rubik' ), - 'Inter' => array( 'label' => 'Inter', 'css' => "'Inter', sans-serif", 'google' => true, 'google_name' => 'Inter' ), - 'Nunito' => array( 'label' => 'Nunito', 'css' => "'Nunito', sans-serif", 'google' => true, 'google_name' => 'Nunito' ), - 'Ubuntu' => array( 'label' => 'Ubuntu', 'css' => "'Ubuntu', sans-serif", 'google' => true, 'google_name' => 'Ubuntu' ), - 'PT Sans' => array( 'label' => 'PT Sans', 'css' => "'PT Sans', sans-serif", 'google' => true, 'google_name' => 'PT+Sans' ), - 'Archivo' => array( 'label' => 'Archivo', 'css' => "'Archivo', sans-serif", 'google' => true, 'google_name' => 'Archivo' ), - 'Fira Sans' => array( 'label' => 'Fira Sans', 'css' => "'Fira Sans', sans-serif", 'google' => true, 'google_name' => 'Fira+Sans' ), - 'Work Sans' => array( 'label' => 'Work Sans', 'css' => "'Work Sans', sans-serif", 'google' => true, 'google_name' => 'Work+Sans' ), - 'Quicksand' => array( 'label' => 'Quicksand', 'css' => "'Quicksand', sans-serif", 'google' => true, 'google_name' => 'Quicksand' ), - 'Karla' => array( 'label' => 'Karla', 'css' => "'Karla', sans-serif", 'google' => true, 'google_name' => 'Karla' ), - 'Dancing Script' => array( 'label' => 'Dancing Script', 'css' => "'Dancing Script', cursive", 'google' => true, 'google_name' => 'Dancing+Script' ), - 'Pacifico' => array( 'label' => 'Pacifico', 'css' => "'Pacifico', cursive", 'google' => true, 'google_name' => 'Pacifico' ), - 'Great Vibes' => array( 'label' => 'Great Vibes', 'css' => "'Great Vibes', cursive", 'google' => true, 'google_name' => 'Great+Vibes' ), - 'Satisfy' => array( 'label' => 'Satisfy', 'css' => "'Satisfy', cursive", 'google' => true, 'google_name' => 'Satisfy' ), - 'Allura' => array( 'label' => 'Allura', 'css' => "'Allura', cursive", 'google' => true, 'google_name' => 'Allura' ), - 'Alex Brush' => array( 'label' => 'Alex Brush', 'css' => "'Alex Brush', cursive", 'google' => true, 'google_name' => 'Alex+Brush' ), - 'Cookie' => array( 'label' => 'Cookie', 'css' => "'Cookie', cursive", 'google' => true, 'google_name' => 'Cookie' ), - ); -} - - -function mm_announcement_admin_init() { - add_menu_page( 'Ankündigung', 'Ankündigung', 'manage_options', 'mm-announcement', 'mm_announcement_admin_page', 'dashicons-megaphone', 61 ); - - register_setting( 'mm_announcement_group', 'mm_announcement_enabled' ); - register_setting( 'mm_announcement_group', 'mm_announcement_text' ); - register_setting( 'mm_announcement_group', 'mm_announcement_bg' ); - register_setting( 'mm_announcement_group', 'mm_announcement_color' ); - register_setting( 'mm_announcement_group', 'mm_announcement_font_size' ); - register_setting( 'mm_announcement_group', 'mm_announcement_font_family' ); - register_setting( 'mm_announcement_group', 'mm_announcement_position' ); - register_setting( 'mm_announcement_group', 'mm_announcement_countdown_enabled' ); - register_setting( 'mm_announcement_group', 'mm_announcement_countdown_label' ); - register_setting( 'mm_announcement_group', 'mm_announcement_countdown_date' ); - register_setting( 'mm_announcement_group', 'mm_announcement_countdown_expired_msg' ); -} -add_action( 'admin_menu', 'mm_announcement_admin_init' ); - - -function mm_announcement_admin_page() { - if ( ! current_user_can( 'manage_options' ) ) return; - - $fonts = mm_announcement_get_font_list(); - $selected_font = get_option( 'mm_announcement_font_family', 'inherit' ); - $selected_size = (int) get_option( 'mm_announcement_font_size', 16 ); - $bg = esc_attr( get_option( 'mm_announcement_bg', '#1e1e1e' ) ); - $color = esc_attr( get_option( 'mm_announcement_color', '#ffffff' ) ); - $text_sample = wp_strip_all_tags( get_option( 'mm_announcement_text' ) ) ?: 'Das ist eine Vorschau: Wie sieht die Schrift aus?'; - ?> -
-

Header-Ankündigung

-

Diese Leiste wird auf allen Seiten angezeigt. Die Vorschau unten zeigt sofort, wie die Ankündigung aussieht — Änderungen wirken direkt in der Vorschau, erst nach Änderungen speichern werden sie im Frontend übernommen.

- -
- - -

Allgemein

- - - - - -
Aktivieren - -
- -

Inhalt

- - - - - -
Text - 6, 'media_buttons' => false, 'tinymce' => true, 'quicktags' => true ) ); ?> - -

Verfügbare Icons

-

Klicke auf ein Icon, um es in den Editor einzufügen.

-
- ' . $icon . ''; - } - ?> -
- - -

HTML erlaubt (z. B. <a>-Links).

- -
-
- -
-

Live Vorschau

-
-
- -

Position

- - - - - -
Anzeigeort - -
- -

Design

- - - - - - - - - - - - - - - - - -
Hintergrundfarbe
Textfarbe
Schriftgröße (px)
Schriftfamilie - -
- -

Countdown Timer

- - - - - - - - - - - - - - - - - -
Countdown aktivieren
Label (Text vor Timer)
Zieldatum & Uhrzeit
Nachricht nach Ablauf
- - -
-
- - ' . $countdown_label . ' - Laden... - '; - } - ?> -
-
-
- - -
- -
-
- get_option( 'mm_announcement_font_family', 'inherit' ), - 'size' => (int) get_option( 'mm_announcement_font_size', 16 ), - 'bg' => get_option( 'mm_announcement_bg', '#1e1e1e' ), - 'color' => get_option( 'mm_announcement_color', '#ffffff' ), - 'text' => wp_kses_post( get_option( 'mm_announcement_text' ) ), - ) ); -} -add_action( 'admin_enqueue_scripts', 'mm_announcement_admin_assets' ); - - -// ========================================================================= -// TEAM MODUL -// ========================================================================= - -function create_team_post_type() { - if ( get_theme_mod( 'team_enabled', true ) ) { - register_post_type( 'team_member', array( - 'labels' => array( - 'name' => __( 'Team', 'minecraft-modern-theme' ), - 'singular_name' => __( 'Teammitglied', 'minecraft-modern-theme' ), - 'add_new' => __( 'Neues Mitglied', 'minecraft-modern-theme' ), - 'menu_name' => __( 'Team', 'minecraft-modern-theme' ), - ), - 'public' => true, - 'has_archive' => true, - 'menu_icon' => 'dashicons-groups', - 'supports' => array( 'title', 'thumbnail', 'page-attributes' ), - 'rewrite' => array( 'slug' => 'team' ), - 'show_in_rest' => true, - 'show_in_menu' => false, - ) ); - } -} -add_action( 'init', 'create_team_post_type' ); - - -function add_team_meta_boxes() { - add_meta_box( 'team_member_rank_box', __( 'Rang & Position', 'minecraft-modern-theme' ), 'team_member_rank_callback', 'team_member', 'side', 'default' ); -} -add_action( 'add_meta_boxes', 'add_team_meta_boxes' ); - -function team_member_rank_callback( $post ) { - wp_nonce_field( 'team_member_rank_save', 'team_member_rank_nonce' ); - $value = get_post_meta( $post->ID, '_team_member_rank', true ); - ?> -

- - -

- id !== 'toplevel_page_mm-team-manager' ) return; - echo ''; -} -add_action( 'admin_head', 'mm_team_manager_admin_css' ); - -function mm_team_manager_page_html() { - ?> -
-

Team Verwaltung

-

Hier kannst du Teammitglieder hinzufügen, sortieren und bearbeiten.

- -
-

Neues Mitglied hinzufügen

-
-
-
- -
-
-
- -
-
-
- -
- -
- -
-
- -

UUID eingeben → Avatar wird automatisch geladen

-
- -
-
-
- - - Kein Bild gewählt -
-

Wird ignoriert wenn UUID gesetzt ist

-
- -
-
-
- - - Kein Banner gewählt -
-

Hintergrundbild der Card (optional)

-
-
- -
-
-
- -
-
-
- -
- -
-
- - -
-
- -
- - - - - - - - - - - - - - 'team_member', 'posts_per_page' => -1, 'orderby' => 'menu_order', 'order' => 'ASC' ) ); - if ( $team_query->have_posts() ) : - while ( $team_query->have_posts() ) : $team_query->the_post(); - $id = get_the_ID(); - $name = get_the_title(); - $rank = get_post_meta( $id, '_team_member_rank', true ); - $bio = get_the_content(); - $uuid = get_post_meta( $id, '_team_member_uuid', true ); - $img_id = get_post_thumbnail_id( $id ); - $banner_id = get_post_meta( $id, '_team_member_banner', true ); - $banner_url = $banner_id ? wp_get_attachment_image_url( $banner_id, 'medium' ) : false; - - // Avatar anzeigen: UUID > Bild > Placeholder - if ( $uuid ) { - $avatar_src = 'https://visage.surgeplay.com/bust/' . esc_attr($uuid) . '.png'; - } elseif ( $img_id ) { - $avatar_src = wp_get_attachment_image_url( $img_id, array(40,40) ); - } else { - $avatar_src = false; - } - ?> - - - - - - - - - - '; - endif; - ?> - -
BildNameRangBioUUID / BildSort.Aktionen
-
- - - - 👤 - -
-
- -
- - - -
- -
-
- - - - - -
Noch keine Mitglieder vorhanden.
-
-
- - - $id, 'menu_order' => $pos ) ); - $pos++; - } - wp_send_json_success(); -} - - -add_action( 'wp_ajax_mm_add_team_member', 'handle_mm_add_member' ); -function handle_mm_add_member() { - check_ajax_referer( 'mm_team_nonce', 'nonce' ); - if ( ! current_user_can( 'publish_posts' ) ) wp_send_json_error( 'Keine Berechtigung' ); - - $id = wp_insert_post( array( - 'post_title' => sanitize_text_field( $_POST['name'] ), - 'post_content' => sanitize_textarea_field( $_POST['bio'] ), - 'post_type' => 'team_member', - 'post_status' => 'publish', - 'menu_order' => 999, - ) ); - - if ( ! $id || is_wp_error( $id ) ) { - wp_send_json_error( 'Fehler beim Erstellen' ); - } - - update_post_meta( $id, '_team_member_rank', sanitize_text_field( $_POST['rank'] ) ); - - // UUID speichern (kein externer Request hier – nur als Text speichern) - if ( ! empty( $_POST['uuid'] ) ) { - $uuid = sanitize_text_field( trim( $_POST['uuid'] ) ); - update_post_meta( $id, '_team_member_uuid', $uuid ); - } elseif ( ! empty( $_POST['img_id'] ) ) { - set_post_thumbnail( $id, intval( $_POST['img_id'] ) ); - } - - // Banner-Bild speichern - if ( ! empty( $_POST['banner_id'] ) ) { - update_post_meta( $id, '_team_member_banner', intval( $_POST['banner_id'] ) ); - } - - wp_send_json_success( array( 'id' => $id, 'msg' => 'Hinzugefügt' ) ); -} - -add_action( 'wp_ajax_mm_update_team_member', 'handle_mm_update_team_member' ); -function handle_mm_update_team_member() { - check_ajax_referer( 'mm_team_nonce', 'nonce' ); - if ( ! current_user_can( 'edit_posts' ) ) wp_send_json_error( 'Keine Berechtigung' ); - $id = intval( $_POST['id'] ); - wp_update_post( array( - 'ID' => $id, - 'post_title' => sanitize_text_field( $_POST['title'] ), - 'post_content' => sanitize_textarea_field( $_POST['bio'] ), - ) ); - update_post_meta( $id, '_team_member_rank', sanitize_text_field( $_POST['rank'] ) ); - // UUID speichern oder löschen - if ( isset( $_POST['uuid'] ) ) { - $uuid = sanitize_text_field( trim( $_POST['uuid'] ) ); - if ( $uuid ) { - update_post_meta( $id, '_team_member_uuid', $uuid ); - } else { - delete_post_meta( $id, '_team_member_uuid' ); - } - } - // Bild nur setzen wenn keine UUID - if ( empty( $_POST['uuid'] ) && ! empty( $_POST['img_id'] ) ) { - set_post_thumbnail( $id, intval( $_POST['img_id'] ) ); - } - // Banner speichern - if ( isset( $_POST['banner_id'] ) ) { - if ( ! empty( $_POST['banner_id'] ) ) { - update_post_meta( $id, '_team_member_banner', intval( $_POST['banner_id'] ) ); - } - } - wp_send_json_success( 'Gespeichert' ); -} - -add_action( 'wp_ajax_mm_delete_team_member', 'handle_mm_delete_team_member' ); -function handle_mm_delete_team_member() { - check_ajax_referer( 'mm_team_nonce', 'nonce' ); - if ( ! current_user_can( 'delete_posts' ) ) wp_send_json_error( 'Keine Berechtigung' ); - wp_delete_post( intval( $_POST['id'] ), true ); - wp_send_json_success( 'Gelöscht' ); -} - - -function create_team_page_automatically() { - if ( get_theme_mod( 'team_enabled', true ) && get_page_by_title( 'Team' ) == null ) { - wp_insert_post( array( 'post_title' => 'Team', 'post_status' => 'publish', 'post_type' => 'page', 'post_author' => 1 ) ); - } -} -add_action( 'customize_save_after', 'create_team_page_automatically' ); - - -function load_team_page_template( $template ) { - if ( ! get_theme_mod( 'team_enabled', true ) ) return $template; - if ( is_post_type_archive( 'team_member' ) ) return get_template_directory() . '/archive-team.php'; - if ( is_page() ) { - $obj = get_queried_object(); - if ( $obj && $obj->post_name === 'team' ) return get_template_directory() . '/archive-team.php'; - } - return $template; -} -add_filter( 'template_include', 'load_team_page_template' ); - - -// Doppelte team_customize_register entfernt – ist jetzt in inc/customizer.php - -// ========================================================================= -// MENÜ-LAYOUTS: Hilfsfunktionen für header.php -// ========================================================================= - -if ( ! function_exists('mm_branding') ) : -function mm_branding( $show_title_with_logo = false ) { ?> -
- - - -

- -

- - - -

- -

- - -
- - - 'fab fa-bluesky', 'discord' => 'fab fa-discord', 'youtube' => 'fab fa-youtube', - 'twitter' => 'fab fa-x-twitter', 'facebook' => 'fab fa-facebook-f', - 'instagram' => 'fab fa-instagram', 'tiktok' => 'fab fa-tiktok', - 'twitch' => 'fab fa-twitch', 'steam' => 'fab fa-steam', - 'github' => 'fab fa-github', 'linkedin' => 'fab fa-linkedin-in', - 'pinterest' => 'fab fa-pinterest-p', 'reddit' => 'fab fa-reddit-alien', - 'mastodon' => 'fab fa-mastodon', 'threads' => 'fab fa-threads', - 'kickstarter' => 'fab fa-kickstarter', 'teamspeak' => 'fab fa-teamspeak', 'spotify' => 'fab fa-spotify', - 'stoat' => 'fab fa-diaspora', - ); ?> -
- - -
-add_section( 'header_menu_style_section', array( - 'title' => __( 'Menü-Design', 'minecraft-modern-theme' ), - 'priority' => 30, - ) ); - $wp_customize->add_setting( 'header_menu_style', array( - 'default' => 'classic', - 'sanitize_callback' => 'sanitize_text_field', - 'transport' => 'refresh', - ) ); - $wp_customize->add_control( 'header_menu_style', array( - 'label' => __( 'Menü-Layout wählen', 'minecraft-modern-theme' ), - 'section' => 'header_menu_style_section', - 'type' => 'select', - 'choices' => array( - 'classic' => __( '① Classic – Logo links, Menü Mitte, Icons rechts', 'minecraft-modern-theme' ), - 'centered' => __( '② Zentriert – Logo oben, Menü darunter', 'minecraft-modern-theme' ), - 'sidebar' => __( '③ Sidebar – Menü als vertikale Leiste', 'minecraft-modern-theme' ), - 'mega' => __( '④ Mega-Menü – breite Dropdown-Spalten', 'minecraft-modern-theme' ), - ), - ) ); - - // Branding-Position (gilt für alle Layouts) - $wp_customize->add_setting( 'sidebar_branding_position', array( - 'default' => 'left', - 'sanitize_callback' => 'sanitize_text_field', - 'transport' => 'refresh', - ) ); - $wp_customize->add_control( 'sidebar_branding_position', array( - 'label' => __( 'Logo/Titel Position', 'minecraft-modern-theme' ), - 'description' => __( 'Gilt für alle Menü-Layouts.', 'minecraft-modern-theme' ), - 'section' => 'header_menu_style_section', - 'type' => 'select', - 'choices' => array( - 'left' => __( 'Links', 'minecraft-modern-theme' ), - 'center' => __( 'Mitte', 'minecraft-modern-theme' ), - 'right' => __( 'Rechts', 'minecraft-modern-theme' ), - ), - ) ); -} -add_action( 'customize_register', 'minecraft_modern_menu_style_customizer' ); - - -// === Sidebar-Menü JavaScript (nur wenn Sidebar-Layout aktiv) === -function minecraft_modern_sidebar_menu_script() { - if ( get_theme_mod( 'header_menu_style', 'classic' ) !== 'sidebar' ) return; - ?> - - __( 'Beitrag Sidebar', 'minecraft-modern-theme' ), - 'id' => 'single-post-sidebar', - 'description' => __( 'Widget-Bereich für die Sidebar auf Einzelbeitrags-Seiten.', 'minecraft-modern-theme' ), - 'before_widget' => '', - 'before_title' => '

', - 'after_title' => '

', - ) ); -} -add_action( 'widgets_init', 'minecraft_modern_single_sidebar' ); - - -// === Single-Post Sidebar Render-Funktion === -function minecraft_modern_render_single_sidebar() { - if ( is_active_sidebar( 'single-post-sidebar' ) ) { - dynamic_sidebar( 'single-post-sidebar' ); - } else { - ?> - - - - - - - - add_section( 'single_sidebar_section', array( - 'title' => __( 'Beitrag Sidebar', 'minecraft-modern-theme' ), - 'priority' => 55, - ) ); - $wp_customize->add_setting( 'single_sidebar_enabled', array( - 'default' => true, - 'sanitize_callback' => 'wp_validate_boolean', - ) ); - $wp_customize->add_control( 'single_sidebar_enabled', array( - 'label' => __( 'Sidebar auf Einzelbeiträgen anzeigen', 'minecraft-modern-theme' ), - 'section' => 'single_sidebar_section', - 'type' => 'checkbox', - ) ); - $wp_customize->add_setting( 'single_sidebar_position', array( - 'default' => 'right', - 'sanitize_callback' => 'sanitize_text_field', - ) ); - $wp_customize->add_control( 'single_sidebar_position', array( - 'label' => __( 'Sidebar-Position', 'minecraft-modern-theme' ), - 'section' => 'single_sidebar_section', - 'type' => 'select', - 'choices' => array( - 'right' => __( 'Rechts', 'minecraft-modern-theme' ), - 'left' => __( 'Links', 'minecraft-modern-theme' ), - ), - ) ); -} -add_action( 'customize_register', 'minecraft_modern_single_sidebar_customizer' ); - - -// === Announcement-Bar Höhe als CSS-Variable + Body-Klasse === -function minecraft_modern_announcement_offset_script() { - if ( ! get_option( 'mm_announcement_enabled' ) ) return; - ?> - - -
- -
-

-

-
-
- add_section( 'mm_cookie_banner_section', array( - 'title' => __( 'Cookie-Banner (DSGVO)', 'minecraft-modern-theme' ), - 'priority' => 75, - ) ); - - $wp_customize->add_setting( 'mm_cookie_enabled', array( 'default' => true, 'sanitize_callback' => 'wp_validate_boolean', 'transport' => 'postMessage' ) ); - $wp_customize->add_control( 'mm_cookie_enabled', array( 'label' => __( 'Cookie-Banner aktivieren', 'minecraft-modern-theme' ), 'section' => 'mm_cookie_banner_section', 'type' => 'checkbox' ) ); - - $wp_customize->add_setting( 'mm_cookie_style', array( 'default' => 'bar', 'sanitize_callback' => 'sanitize_text_field', 'transport' => 'postMessage' ) ); - $wp_customize->add_control( 'mm_cookie_style', array( - 'label' => __( 'Design-Variante', 'minecraft-modern-theme' ), - 'section' => 'mm_cookie_banner_section', - 'type' => 'select', - 'choices' => array( - 'bar' => __( 'Variante 1 – Schmale Bar (volle Breite)', 'minecraft-modern-theme' ), - 'split' => __( 'Variante 2 – Zweispaltig (3A)', 'minecraft-modern-theme' ), - 'slide' => __( 'Variante 3 – Slide-In von rechts (3B)', 'minecraft-modern-theme' ), - 'stepper' => __( 'Variante 4 – Kompakt-Center mit Stepper (3C)', 'minecraft-modern-theme' ), - ), - ) ); - - $wp_customize->add_setting( 'mm_cookie_text', array( 'default' => __( 'Wir nutzen Cookies und ähnliche Technologien. Einige sind essenziell, andere helfen uns diese Website zu verbessern. Du kannst deine Auswahl jederzeit anpassen.', 'minecraft-modern-theme' ), 'sanitize_callback' => 'wp_kses_post', 'transport' => 'postMessage' ) ); - $wp_customize->add_control( 'mm_cookie_text', array( 'label' => __( 'Banner-Text', 'minecraft-modern-theme' ), 'section' => 'mm_cookie_banner_section', 'type' => 'textarea' ) ); - - $wp_customize->add_setting( 'mm_cookie_privacy_url', array( 'default' => '', 'sanitize_callback' => 'esc_url_raw' ) ); - $wp_customize->add_control( 'mm_cookie_privacy_url', array( 'label' => __( 'URL Datenschutzerklärung', 'minecraft-modern-theme' ), 'description' => __( 'Leer lassen um den Link auszublenden.', 'minecraft-modern-theme' ), 'section' => 'mm_cookie_banner_section', 'type' => 'url' ) ); - - foreach ( array( - 'necessary' => array( 'label' => __( 'Beschreibung: Notwendige', 'minecraft-modern-theme' ), 'default' => __( 'Grundlegende Funktionen der Website. Können nicht deaktiviert werden.', 'minecraft-modern-theme' ) ), - 'statistics' => array( 'label' => __( 'Beschreibung: Statistik', 'minecraft-modern-theme' ), 'default' => __( 'Helfen uns zu verstehen wie Besucher mit der Website interagieren (z.B. Google Analytics).', 'minecraft-modern-theme' ) ), - 'marketing' => array( 'label' => __( 'Beschreibung: Marketing', 'minecraft-modern-theme' ), 'default' => __( 'Werden genutzt um Werbung relevanter zu gestalten (z.B. YouTube, Facebook).', 'minecraft-modern-theme' ) ), - ) as $key => $opts ) { - $wp_customize->add_setting( 'mm_cookie_desc_' . $key, array( 'default' => $opts['default'], 'sanitize_callback' => 'sanitize_textarea_field' ) ); - $wp_customize->add_control( 'mm_cookie_desc_' . $key, array( 'label' => $opts['label'], 'section' => 'mm_cookie_banner_section', 'type' => 'textarea' ) ); - } - - $wp_customize->add_setting( 'mm_cookie_ga_id', array( 'default' => '', 'sanitize_callback' => 'sanitize_text_field' ) ); - $wp_customize->add_control( 'mm_cookie_ga_id', array( 'label' => __( 'Google Analytics ID (optional)', 'minecraft-modern-theme' ), 'description' => __( 'z.B. G-XXXXXXXXXX', 'minecraft-modern-theme' ), 'section' => 'mm_cookie_banner_section', 'type' => 'text' ) ); - - $wp_customize->add_setting( 'mm_cookie_lifetime', array( 'default' => 365, 'sanitize_callback' => 'absint' ) ); - $wp_customize->add_control( 'mm_cookie_lifetime', array( 'label' => __( 'Cookie-Laufzeit (Tage)', 'minecraft-modern-theme' ), 'section' => 'mm_cookie_banner_section', 'type' => 'number', 'input_attrs' => array( 'min' => 1, 'max' => 730 ) ) ); - - if ( class_exists( 'MM_Cookie_Preview_Control' ) ) { - $wp_customize->add_setting( 'mm_cookie_preview_dummy', array( 'sanitize_callback' => 'sanitize_text_field' ) ); - $wp_customize->add_control( new MM_Cookie_Preview_Control( $wp_customize, 'mm_cookie_preview_dummy', array( 'section' => 'mm_cookie_banner_section', 'priority' => 200 ) ) ); - } -} -add_action( 'customize_register', 'mm_cookie_banner_customizer' ); - - -// --- 2. Banner HTML – ALLE 4 LAYOUTS gleichzeitig ausgeben --- -// Im Customizer wechselt JS nur die Klasse auf #mm-cookie-banner. -// CSS zeigt immer nur das passende .mmc-layout-* div. -function mm_cookie_banner_render() { - $is_preview = is_customize_preview(); - if ( ! $is_preview && ! get_theme_mod( 'mm_cookie_enabled', true ) ) return; - - $style = get_theme_mod( 'mm_cookie_style', 'bar' ); - $text = get_theme_mod( 'mm_cookie_text', __( 'Wir nutzen Cookies und ähnliche Technologien. Einige sind essenziell, andere helfen uns diese Website zu verbessern.', 'minecraft-modern-theme' ) ); - $priv_url = get_theme_mod( 'mm_cookie_privacy_url', '' ); - $lifetime = absint( get_theme_mod( 'mm_cookie_lifetime', 365 ) ); - $ga_id = get_theme_mod( 'mm_cookie_ga_id', '' ); - $desc_n = get_theme_mod( 'mm_cookie_desc_necessary', __( 'Grundlegende Funktionen der Website. Können nicht deaktiviert werden.', 'minecraft-modern-theme' ) ); - $desc_s = get_theme_mod( 'mm_cookie_desc_statistics', __( 'Helfen uns zu verstehen wie Besucher mit der Website interagieren (z.B. Google Analytics).', 'minecraft-modern-theme' ) ); - $desc_m = get_theme_mod( 'mm_cookie_desc_marketing', __( 'Werden genutzt um Werbung relevanter zu gestalten (z.B. YouTube, Facebook).', 'minecraft-modern-theme' ) ); - - $priv_link = $priv_url ? '' . __( 'Datenschutzerklärung', 'minecraft-modern-theme' ) . '' : ''; - $preview_class = $is_preview ? ' mmc-visible mmc-preview-mode' : ''; - $inline_style = $is_preview ? '' : 'display:none;'; - - // Kategorien-Block (identisch in allen Varianten mit Kategorien) - $cats = '
-
' . __('Notwendige','minecraft-modern-theme') . '' . __('Immer aktiv','minecraft-modern-theme') . '

' . esc_html($desc_n) . '

-

' . esc_html($desc_s) . '

-

' . esc_html($desc_m) . '

-
'; - - $btn_accept = ''; - $btn_select = ''; - $btn_neces = ''; - - $text_esc = wp_kses_post($text); - ?> - - - - __('Cookie-Einstellungen','minecraft-modern-theme')),$atts);return ''.esc_html($a['text']).'';} -add_shortcode('cookie_settings','mm_cookie_settings_shortcode'); - - -// --- 4. Live-Vorschau: nur Klasse + Text wechseln, HTML ist bereits vollständig --- -function mm_cookie_banner_preview_js(){ - if(!is_customize_preview())return; ?> - - array( - 'name' => __( 'Videos', 'minecraft-modern-theme' ), - 'singular_name' => __( 'Video', 'minecraft-modern-theme' ), - 'add_new' => __( 'Neues Video', 'minecraft-modern-theme' ), - 'add_new_item' => __( 'Neues Video hinzufügen', 'minecraft-modern-theme' ), - 'edit_item' => __( 'Video bearbeiten', 'minecraft-modern-theme' ), - 'all_items' => __( 'Alle Videos', 'minecraft-modern-theme' ), - 'menu_name' => __( 'Videos', 'minecraft-modern-theme' ), - ), - 'public' => true, - 'has_archive' => true, - 'menu_icon' => 'dashicons-video-alt3', - 'menu_position' => 7, - 'supports' => array( 'title', 'thumbnail', 'excerpt', 'page-attributes' ), - 'rewrite' => array( 'slug' => 'videos' ), - 'show_in_rest' => true, - ) ); - - register_post_type( 'mm_livestream', array( - 'labels' => array( - 'name' => __( 'Livestreams', 'minecraft-modern-theme' ), - 'singular_name' => __( 'Livestream', 'minecraft-modern-theme' ), - 'add_new' => __( 'Neuer Livestream', 'minecraft-modern-theme' ), - 'add_new_item' => __( 'Neuen Livestream hinzufügen', 'minecraft-modern-theme' ), - 'edit_item' => __( 'Livestream bearbeiten', 'minecraft-modern-theme' ), - 'all_items' => __( 'Alle Livestreams', 'minecraft-modern-theme' ), - 'menu_name' => __( 'Livestreams', 'minecraft-modern-theme' ), - ), - 'public' => true, - 'publicly_queryable' => false, - 'exclude_from_search' => true, - 'show_ui' => true, - 'show_in_menu' => 'edit.php?post_type=mm_video', - 'menu_position' => 8, - 'supports' => array( 'title', 'excerpt', 'page-attributes' ), - 'show_in_rest' => true, - ) ); -} -add_action( 'init', 'mm_register_video_post_type' ); - - -// --- 2. Meta-Box: Video URL + Kategorie --- -function mm_video_meta_boxes() { - add_meta_box( - 'mm_video_data', - __( 'Video-Einstellungen', 'minecraft-modern-theme' ), - 'mm_video_meta_box_html', - 'mm_video', 'normal', 'high' - ); - - add_meta_box( - 'mm_livestream_data', - __( 'Livestream-Einstellungen', 'minecraft-modern-theme' ), - 'mm_livestream_meta_box_html', - 'mm_livestream', 'normal', 'high' - ); -} -add_action( 'add_meta_boxes', 'mm_video_meta_boxes' ); - -function mm_video_meta_box_html( $post ) { - wp_nonce_field( 'mm_video_save', 'mm_video_nonce' ); - $url = get_post_meta( $post->ID, '_mm_video_url', true ); - $category = get_post_meta( $post->ID, '_mm_video_category', true ); - $post_id = $post->ID; - ?> - - - - - - - - - - - - - -
- -

- -

-
- -

-
- -
- - -

- -

- -
- ID, '_mm_livestream_url', true ); - $player_url = get_post_meta( $post->ID, '_mm_livestream_player_url', true ); - $owner = get_post_meta( $post->ID, '_mm_livestream_owner', true ); - ?> - - - - - - - - - - - - - - - - - -
- -

- -

-
- -

- -

-
- -

- -

-
-

-
- Tag ausgegeben, nicht iframe - } - - return false; -} - -function mm_video_get_type( $url ) { - if ( preg_match( '/youtube\.com|youtu\.be/', $url ) ) return 'youtube'; - if ( strpos( $url, 'vimeo.com' ) !== false ) return 'vimeo'; - if ( strpos( $url, 'twitch.tv' ) !== false ) return 'twitch'; - if ( preg_match( '/\.(mp4|webm|ogv|ogg)(\?.*)?$/i', $url ) ) return 'mp4'; - return 'unknown'; -} - -function mm_twitch_get_channel_from_url( $url ) { - if ( preg_match( '/twitch\.tv\/([a-zA-Z0-9_]+)(?:\/|\?|$)/', (string) $url, $m ) ) { - return strtolower( $m[1] ); - } - - return ''; -} - -function mm_twitch_get_app_token() { - $client_id = get_theme_mod( 'twitch_client_id', '' ); - $client_secret = get_theme_mod( 'twitch_client_secret', '' ); - - if ( empty( $client_id ) || empty( $client_secret ) ) { - return false; - } - - $cache_key = 'mm_twitch_app_token'; - $cached = get_transient( $cache_key ); - if ( ! empty( $cached ) ) { - return $cached; - } - - $response = wp_remote_post( 'https://id.twitch.tv/oauth2/token', array( - 'timeout' => 8, - 'body' => array( - 'client_id' => $client_id, - 'client_secret' => $client_secret, - 'grant_type' => 'client_credentials', - ), - ) ); - - if ( is_wp_error( $response ) ) { - return false; - } - - $data = json_decode( wp_remote_retrieve_body( $response ), true ); - if ( empty( $data['access_token'] ) || empty( $data['expires_in'] ) ) { - return false; - } - - $ttl = max( 60, (int) $data['expires_in'] - 60 ); - set_transient( $cache_key, $data['access_token'], $ttl ); - - return $data['access_token']; -} - -function mm_twitch_is_live( $channel ) { - $channel = sanitize_text_field( (string) $channel ); - if ( $channel === '' ) { - return false; - } - - $cache_key = 'mm_twitch_live_' . $channel; - $cached = get_transient( $cache_key ); - if ( false !== $cached ) { - return $cached === 'live'; - } - - $client_id = get_theme_mod( 'twitch_client_id', '' ); - $token = mm_twitch_get_app_token(); - if ( empty( $client_id ) || empty( $token ) ) { - return false; - } - - $url = add_query_arg( array( - 'user_login' => $channel, - ), 'https://api.twitch.tv/helix/streams' ); - - $response = wp_remote_get( $url, array( - 'timeout' => 8, - 'headers' => array( - 'Client-ID' => $client_id, - 'Authorization' => 'Bearer ' . $token, - ), - ) ); - - if ( is_wp_error( $response ) ) { - return false; - } - - $data = json_decode( wp_remote_retrieve_body( $response ), true ); - $is_live = ! empty( $data['data'][0] ); - set_transient( $cache_key, $is_live ? 'live' : 'offline', 2 * MINUTE_IN_SECONDS ); - - return $is_live; -} - -function mm_video_get_youtube_player_url( $identifier, $mode = 'video' ) { - $params = 'autoplay=0&rel=0&modestbranding=1'; - - if ( $mode === 'channel' ) { - return 'https://www.youtube.com/embed/live_stream?channel=' . rawurlencode( $identifier ) . '&' . $params; - } - - if ( $mode === 'handle-live' ) { - return 'https://www.youtube.com/embed/' . ltrim( $identifier ) . '/live?' . $params; - } - - return 'https://www.youtube.com/embed/' . rawurlencode( $identifier ) . '?' . $params; -} - -function mm_video_get_youtube_handle_from_url( $url ) { - if ( preg_match( '~youtube\.com/(@[A-Za-z0-9._-]+)(?:/.*)?$~i', (string) $url, $matches ) ) { - return sanitize_text_field( $matches[1] ); - } - - return ''; -} - -function mm_video_extract_youtube_live_video_id( $html ) { - $patterns = array( - '/"canonicalBaseUrl":"\\/watch\?v=([A-Za-z0-9_-]{11})"/i', - '/"watchEndpoint":\{"videoId":"([A-Za-z0-9_-]{11})"/i', - '/\/watch\?v=([A-Za-z0-9_-]{11})\\u0026/i', - '/"videoId":"([A-Za-z0-9_-]{11})".{0,600}?"isLiveNow":true/is', - '/"videoId":"([A-Za-z0-9_-]{11})".{0,600}?"style":"LIVE"/is', - '/"videoId":"([A-Za-z0-9_-]{11})".{0,600}?LIVE_NOW/is', - '/https:\/\/www\.youtube\.com\/watch\?v=([A-Za-z0-9_-]{11})/i', - '/ 5 ) ); - if ( ! is_wp_error( $response ) ) { - $data = json_decode( wp_remote_retrieve_body( $response ), true ); - if ( ! empty( $data['items'][0] ) ) { - $state = $data['items'][0]['snippet']['liveBroadcastContent'] ?? ''; - $is_live = ( $state === 'live' ); - set_transient( $cache_key, $is_live ? 'live' : 'offline', 2 * MINUTE_IN_SECONDS ); - return $is_live; - } - } - } - - // Fallback: Wenn keine API, gehen wir davon aus dass die video_id aktuell ist - // weil sie von mm_video_resolve_youtube_live_video_id() kam - set_transient( $cache_key, 'live', 2 * MINUTE_IN_SECONDS ); - return true; -} - -function mm_video_resolve_youtube_live_video_id( $profile_url = '', $youtube_channel_id = '' ) { - $profile_url = trim( (string) $profile_url ); - $youtube_channel_id = trim( (string) $youtube_channel_id ); - $cache_key = 'mm_yt_live_v2_' . md5( strtolower( $profile_url . '|' . $youtube_channel_id ) ); - $cached = get_transient( $cache_key ); - - if ( is_array( $cached ) && array_key_exists( 'video_id', $cached ) ) { - return $cached['video_id']; - } - - $candidate_urls = array(); - $handle = mm_video_get_youtube_handle_from_url( $profile_url ); - - if ( $youtube_channel_id && preg_match( '/^UC[a-zA-Z0-9_-]+$/', $youtube_channel_id ) ) { - $candidate_urls[] = 'https://www.youtube.com/channel/' . rawurlencode( $youtube_channel_id ) . '/live'; - $candidate_urls[] = 'https://www.youtube.com/channel/' . rawurlencode( $youtube_channel_id ) . '/streams'; - } - - if ( $handle ) { - $candidate_urls[] = 'https://www.youtube.com/' . rawurlencode( ltrim( $handle, '/' ) ) . '/live'; - $candidate_urls[] = 'https://www.youtube.com/' . rawurlencode( ltrim( $handle, '/' ) ) . '/streams'; - } - - if ( $profile_url ) { - $candidate_urls[] = untrailingslashit( $profile_url ) . '/live'; - $candidate_urls[] = untrailingslashit( $profile_url ) . '/streams'; - } - - $candidate_urls = array_values( array_unique( array_filter( $candidate_urls ) ) ); - $request_args = array( - 'timeout' => 10, - 'redirection' => 5, - 'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36', - 'headers' => array( - 'Accept-Language' => 'en-US,en;q=0.9,de;q=0.8', - ), - ); - - foreach ( $candidate_urls as $candidate_url ) { - $response = wp_remote_get( $candidate_url, $request_args ); - - if ( is_wp_error( $response ) ) { - continue; - } - - $body = wp_remote_retrieve_body( $response ); - if ( ! is_string( $body ) || $body === '' ) { - continue; - } - - $video_id = mm_video_extract_youtube_live_video_id( $body ); - if ( $video_id ) { - set_transient( $cache_key, array( 'video_id' => $video_id ), 2 * MINUTE_IN_SECONDS ); - return $video_id; - } - } - - set_transient( $cache_key, array( 'video_id' => '' ), 60 ); - return ''; -} - -function mm_video_get_livestream_data( $profile_url = '', $player_url = '', $youtube_channel_id = '' ) { - if ( empty( $profile_url ) && empty( $player_url ) && empty( $youtube_channel_id ) ) { - return false; - } - - $profile_url = trim( $profile_url ); - $player_url = trim( $player_url ); - $youtube_channel_id = trim( $youtube_channel_id ); - $source_url = $player_url ? $player_url : $profile_url; - $parent_host = parse_url( home_url(), PHP_URL_HOST ); - $data = array( - 'profile_url' => esc_url_raw( $profile_url ? $profile_url : $player_url ), - 'platform' => 'unknown', - 'label' => __( 'Livestream', 'minecraft-modern-theme' ), - 'icon' => 'fas fa-tower-broadcast', - 'color' => '#00d4ff', - 'cta' => __( 'Profil öffnen', 'minecraft-modern-theme' ), - 'embed_url' => '', - 'video_id' => '', - 'channel' => '', - 'channel_display' => '', - ); - - if ( ! empty( $youtube_channel_id ) && preg_match( '/^UC[a-zA-Z0-9_-]+$/', $youtube_channel_id ) ) { - $resolved_video_id = mm_video_resolve_youtube_live_video_id( $profile_url, $youtube_channel_id ); - - $data['platform'] = 'youtube'; - $data['label'] = __( 'YouTube Livestream', 'minecraft-modern-theme' ); - $data['icon'] = 'fab fa-youtube'; - $data['color'] = '#ff0000'; - $data['cta'] = __( 'Zum YouTube-Kanal', 'minecraft-modern-theme' ); - $data['channel'] = $youtube_channel_id; - $data['channel_display'] = $youtube_channel_id; - $data['video_id'] = $resolved_video_id; - $data['embed_url'] = $resolved_video_id ? mm_video_get_youtube_player_url( $resolved_video_id, 'video' ) : ''; - - if ( preg_match( '~youtube\.com/(@[A-Za-z0-9._-]+)(?:/.*)?$~i', $profile_url, $handle_matches ) ) { - $data['channel_display'] = sanitize_text_field( $handle_matches[1] ); - } - - if ( empty( $data['profile_url'] ) ) { - $data['profile_url'] = 'https://www.youtube.com/channel/' . rawurlencode( $youtube_channel_id ); - } - - if ( empty( $player_url ) ) { - return $data; - } - } - - if ( empty( $source_url ) ) { - return false; - } - - if ( preg_match( '/youtube\.com|youtu\.be/', $source_url ) && preg_match( '/(?:youtube\.com\/(?:watch\?v=|shorts\/|embed\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/', $source_url ) ) { - $data['platform'] = 'youtube'; - $data['label'] = __( 'YouTube Livestream', 'minecraft-modern-theme' ); - $data['icon'] = 'fab fa-youtube'; - $data['color'] = '#ff0000'; - $data['cta'] = __( 'Zum YouTube-Kanal', 'minecraft-modern-theme' ); - preg_match( '/(?:youtube\.com\/(?:watch\?v=|shorts\/|embed\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/', $source_url, $video_match ); - $data['video_id'] = ! empty( $video_match[1] ) ? $video_match[1] : ''; - $data['embed_url'] = ! empty( $video_match[1] ) ? mm_video_get_youtube_player_url( $video_match[1], 'video' ) : ''; - return $data; - } - - if ( preg_match( '~twitch\.tv/([A-Za-z0-9_]+)(?:/)?(?:\?.*)?$~i', $source_url, $matches ) && strtolower( $matches[1] ) !== 'videos' ) { - $channel = sanitize_key( $matches[1] ); - $data['platform'] = 'twitch'; - $data['label'] = __( 'Twitch Livestream', 'minecraft-modern-theme' ); - $data['icon'] = 'fab fa-twitch'; - $data['color'] = '#9146ff'; - $data['cta'] = __( 'Zum Twitch-Kanal', 'minecraft-modern-theme' ); - $data['channel'] = $channel; - $data['channel_display'] = '@' . $channel; - $data['embed_url'] = 'https://player.twitch.tv/?channel=' . rawurlencode( $channel ) . '&parent=' . rawurlencode( $parent_host ) . '&autoplay=false'; - return $data; - } - - if ( preg_match( '~kick\.com/([A-Za-z0-9_]+)(?:/)?(?:\?.*)?$~i', $source_url, $matches ) ) { - $channel = sanitize_key( $matches[1] ); - $data['platform'] = 'kick'; - $data['label'] = __( 'Kick Livestream', 'minecraft-modern-theme' ); - $data['icon'] = 'fas fa-satellite-dish'; - $data['color'] = '#53fc18'; - $data['cta'] = __( 'Zum Kick-Kanal', 'minecraft-modern-theme' ); - $data['channel'] = $channel; - $data['channel_display'] = '@' . $channel; - $data['embed_url'] = 'https://player.kick.com/' . rawurlencode( $channel ); - return $data; - } - - if ( preg_match( '~youtube\.com/channel/(UC[a-zA-Z0-9_-]+)~i', $source_url, $matches ) ) { - $channel_id = sanitize_text_field( $matches[1] ); - $resolved_video_id = mm_video_resolve_youtube_live_video_id( $source_url, $channel_id ); - $data['platform'] = 'youtube'; - $data['label'] = __( 'YouTube Livestream', 'minecraft-modern-theme' ); - $data['icon'] = 'fab fa-youtube'; - $data['color'] = '#ff0000'; - $data['cta'] = __( 'Zum YouTube-Kanal', 'minecraft-modern-theme' ); - $data['channel'] = $channel_id; - $data['channel_display'] = $channel_id; - $data['video_id'] = $resolved_video_id; - $data['embed_url'] = $resolved_video_id ? mm_video_get_youtube_player_url( $resolved_video_id, 'video' ) : ''; - return $data; - } - - if ( preg_match( '~youtube\.com/(@[A-Za-z0-9._-]+)(?:/.*)?$~i', $source_url, $matches ) ) { - $handle = sanitize_text_field( $matches[1] ); - $resolved_video_id = mm_video_resolve_youtube_live_video_id( $source_url, '' ); - $data['platform'] = 'youtube'; - $data['label'] = __( 'YouTube Livestream', 'minecraft-modern-theme' ); - $data['icon'] = 'fab fa-youtube'; - $data['color'] = '#ff0000'; - $data['cta'] = __( 'Zum YouTube-Kanal', 'minecraft-modern-theme' ); - $data['channel'] = ltrim( $handle, '@' ); - $data['channel_display'] = $handle; - $data['video_id'] = $resolved_video_id; - $data['embed_url'] = $resolved_video_id ? mm_video_get_youtube_player_url( $resolved_video_id, 'video' ) : ''; - return $data; - } - - if ( preg_match( '~youtube\.com/(?:c|user)/([A-Za-z0-9._-]+)(?:/.*)?$~i', $source_url, $matches ) ) { - $channel_name = sanitize_text_field( $matches[1] ); - $resolved_video_id = mm_video_resolve_youtube_live_video_id( $source_url, '' ); - $data['platform'] = 'youtube'; - $data['label'] = __( 'YouTube Livestream', 'minecraft-modern-theme' ); - $data['icon'] = 'fab fa-youtube'; - $data['color'] = '#ff0000'; - $data['cta'] = __( 'Zum YouTube-Kanal', 'minecraft-modern-theme' ); - $data['channel'] = $channel_name; - $data['channel_display'] = '@' . ltrim( $channel_name, '@' ); - $data['video_id'] = $resolved_video_id; - $data['embed_url'] = $resolved_video_id ? mm_video_get_youtube_player_url( $resolved_video_id, 'video' ) : ''; - return $data; - } - - if ( strpos( $source_url, 'youtube.com' ) !== false || strpos( $source_url, 'youtu.be' ) !== false ) { - $data['platform'] = 'youtube'; - $data['label'] = __( 'YouTube Livestream', 'minecraft-modern-theme' ); - $data['icon'] = 'fab fa-youtube'; - $data['color'] = '#ff0000'; - $data['cta'] = __( 'Zum YouTube-Kanal', 'minecraft-modern-theme' ); - } - - return $data; -} - -function mm_video_get_livestream_item( $post_id ) { - $stream_url = get_post_meta( $post_id, '_mm_livestream_url', true ); - $player_url = get_post_meta( $post_id, '_mm_livestream_player_url', true ); - $owner_meta = trim( get_post_meta( $post_id, '_mm_livestream_owner', true ) ); - $youtube_channel_id = get_post_meta( $post_id, '_mm_livestream_youtube_channel_id', true ); - $stream = mm_video_get_livestream_data( $stream_url, $player_url, $youtube_channel_id ); - - if ( ! $stream || empty( $stream['profile_url'] ) ) { - return false; - } - - $stream_title = trim( get_the_title( $post_id ) ); - if ( empty( $stream_title ) || $stream_title === '(kein Titel)' || stripos( $stream_title, 'Automatisch gespeicherter Entwurf' ) !== false || stripos( $stream_title, 'Auto Draft' ) !== false ) { - $stream_title = ! empty( $stream['channel_display'] ) ? $stream['channel_display'] : $stream['label']; - } - - $stream_excerpt = has_excerpt( $post_id ) ? get_the_excerpt( $post_id ) : ''; - $owner = $owner_meta; - if ( empty( $owner ) ) { - $owner = ! empty( $stream['channel_display'] ) ? $stream['channel_display'] : $stream_title; - } - - return array( - 'post_id' => $post_id, - 'owner' => $owner, - 'title' => $stream_title, - 'description' => $stream_excerpt, - 'profile_url' => $stream['profile_url'], - 'channel' => $stream['channel'], - 'stream' => $stream, - ); -} - -/** - * Automatische YouTube-Live-Erkennung via @Handle (Optimiert) - */ - -/** - * 1. Hilfsfunktion: Wandelt @Handle in eine Channel-ID um - */ -function mm_get_channel_id_by_handle( $handle ) { - $api_key = get_theme_mod( 'youtube_api_key' ); - if ( empty( $api_key ) || empty( $handle ) ) { - return false; - } - - // Handle normalisieren (ohne @) - $handle = ltrim( $handle, '@' ); - - // Cache für die Channel-ID (diese ändert sich nie, daher 30 Tage speichern) - $cache_key = 'mm_id_for_' . $handle; - $channel_id = get_transient( $cache_key ); - if ( false !== $channel_id ) { - return $channel_id; - } - - // Suche Kanal zum Handle - $url = 'https://www.googleapis.com/youtube/v3/search?part=snippet&q=' . urlencode( '@' . $handle ) . '&type=channel&maxResults=1&key=' . $api_key; - - $response = wp_remote_get( $url ); - if ( is_wp_error( $response ) ) { - return false; - } - - $data = json_decode( wp_remote_retrieve_body( $response ) ); - - if ( ! empty( $data->items[0]->snippet->channelId ) ) { - $id = $data->items[0]->snippet->channelId; - set_transient( $cache_key, $id, DAY_IN_SECONDS * 30 ); - return $id; - } - - return false; -} - -/** - * 2. Hauptfunktion: Findet die Video-ID des aktuellen Livestreams - */ -function mm_get_youtube_live_id_from_handle( $handle ) { - $api_key = get_theme_mod( 'youtube_api_key' ); - if ( empty( $api_key ) ) { - return false; - } - - // 1. Kanal-ID zum Handle finden - $channel_id = mm_get_channel_id_by_handle( $handle ); - if ( ! $channel_id ) { - return false; - } - - // 2. Aktuellen Livestream in diesem Kanal suchen - $cache_key_live = 'mm_live_status_' . $channel_id; - $live_id = get_transient( $cache_key_live ); - if ( false !== $live_id ) { - return ( $live_id === 'none' ) ? false : $live_id; - } - - // Wir suchen direkt nach dem Live-Event des Kanals - $url = 'https://www.googleapis.com/youtube/v3/search?part=id&channelId=' . $channel_id . '&eventType=live&type=video&key=' . $api_key; - - $response = wp_remote_get( $url ); - if ( is_wp_error( $response ) ) { - return false; - } - - $data = json_decode( wp_remote_retrieve_body( $response ) ); - - if ( ! empty( $data->items[0]->id->videoId ) ) { - $video_id = $data->items[0]->id->videoId; - set_transient( $cache_key_live, $video_id, 2 * MINUTE_IN_SECONDS ); // Nur 2 Min für schnellere Reaktion - return $video_id; - } - - // Wenn nicht live, 'none' speichern, um API-Anfragen zu drosseln - set_transient( $cache_key_live, 'none', 2 * MINUTE_IN_SECONDS ); - return false; -} - -/** - * 3. Update für mm_video_get_livestream_groups - Hybrid-System - * Zeigt ALLE konfigurierten Livestreams an: - * - Livestream-Posts (Hauptmethode für mehrere Kanäle) - * - Optional: Customizer @Handle (für einzelnen Hauptkanal) - */ -function mm_video_get_livestream_groups() { - $groups = array(); - $api_key = get_theme_mod( 'youtube_api_key', '' ); - - // === METHODE 1: Livestream-Posts (IMMER abfragen) === - $posts = get_posts( array( - 'post_type' => 'mm_livestream', - 'post_status' => 'publish', - 'posts_per_page' => -1, - 'orderby' => 'ID', - 'order' => 'ASC', - ) ); - - if ( ! empty( $posts ) ) { - foreach ( $posts as $post ) { - $profile_url = get_post_meta( $post->ID, '_mm_livestream_url', true ); - $stream_url = get_post_meta( $post->ID, '_mm_livestream_player_url', true ); - $owner = get_post_meta( $post->ID, '_mm_livestream_owner', true ); - $channel_id = ''; - - // Versuche Channel-ID aus Profil-URL zu extrahieren (nur für YouTube) - if ( ! empty( $profile_url ) && strpos( $profile_url, 'youtube.com' ) !== false ) { - // Channel-URL mit UC-ID - if ( preg_match( '~/channel/(UC[a-zA-Z0-9_-]+)~', $profile_url, $m ) ) { - $channel_id = $m[1]; - } - // @Handle -> über API auflösen - elseif ( preg_match( '~/@([a-zA-Z0-9_.-]+)(?:/|$)~', $profile_url, $m ) && ! empty( $api_key ) ) { - $channel_id = mm_get_channel_id_by_handle( $m[1] ); - } - } - - // YouTube-Livestream: Prüfe ob live via API - if ( ! empty( $channel_id ) && ! empty( $api_key ) ) { - $cache_key_live = 'mm_live_status_' . $channel_id; - $live_id = get_transient( $cache_key_live ); - - if ( false === $live_id ) { - $search_url = add_query_arg( array( - 'part' => 'id', - 'channelId' => $channel_id, - 'eventType' => 'live', - 'type' => 'video', - 'key' => $api_key, - ), 'https://www.googleapis.com/youtube/v3/search' ); - - $response = wp_remote_get( $search_url, array( 'timeout' => 10 ) ); - - if ( ! is_wp_error( $response ) ) { - $data = json_decode( wp_remote_retrieve_body( $response ), true ); - - if ( isset( $data['items'][0]['id']['videoId'] ) ) { - $live_id = $data['items'][0]['id']['videoId']; - set_transient( $cache_key_live, $live_id, 2 * MINUTE_IN_SECONDS ); - } else { - set_transient( $cache_key_live, 'none', 2 * MINUTE_IN_SECONDS ); - $live_id = false; - } - } else { - $live_id = false; - } - } elseif ( $live_id === 'none' ) { - $live_id = false; - } - - // Nur hinzufügen wenn live - if ( $live_id && $live_id !== 'none' ) { - $groups[] = array( - 'title' => $post->post_title, - 'platform' => 'youtube', - 'yt_id' => $live_id, - 'handle' => $profile_url, - ); - } - } - // Andere Plattformen (Twitch, etc.): Prüfe zuerst direkte Stream-URL, sonst Profil-URL - elseif ( ! empty( $stream_url ) || ! empty( $profile_url ) ) { - $use_url = ! empty( $stream_url ) ? $stream_url : $profile_url; - $embed_url = mm_video_get_embed_url( $use_url ); - - // Nur Live-Streams anzeigen (Twitch muss live sein) - if ( $embed_url ) { - $platform = mm_video_get_type( $use_url ); - - if ( $platform !== 'twitch' ) { - continue; - } - - $channel = mm_twitch_get_channel_from_url( $use_url ); - if ( ! mm_twitch_is_live( $channel ) ) { - continue; - } - - $groups[] = array( - 'title' => $post->post_title, - 'platform' => $platform, - 'embed_url' => $embed_url, - 'profile_url' => $profile_url, - 'owner' => $owner, - ); - } - } - } - } - - return $groups; -} - -/** - * Debug-Informationen für Livestream-System - */ -function mm_video_get_api_livestream_debug() { - if ( ! is_user_logged_in() || ! current_user_can( 'edit_posts' ) ) { - return array(); - } - - $api_key = get_theme_mod( 'youtube_api_key', '' ); - - // Zähle Livestream-Posts - $posts_count = wp_count_posts( 'mm_livestream' ); - $published_posts = isset( $posts_count->publish ) ? $posts_count->publish : 0; - - // === Fall 1: Keine Konfiguration === - if ( $published_posts === 0 ) { - return array( - 'status' => 'error', - 'message' => 'Keine Livestream-Posts gefunden', - 'hint' => 'Erstelle Livestream-Posts über "Livestreams → Neu"', - ); - } - - // === Fall 2: API Key fehlt (nur Warnung) === - if ( empty( $api_key ) ) { - return array( - 'status' => 'warning', - 'message' => 'Kein YouTube API Key', - 'hint' => 'API Key wird für YouTube Live-Erkennung benötigt. Twitch-Streams funktionieren ohne.', - 'posts_count' => $published_posts, - ); - } - - // === Fall 3: Alles OK === - return array( - 'status' => 'ok', - 'posts_count' => $published_posts, - 'api_key_length' => strlen( $api_key ), - ); -} - -function mm_video_get_hidden_livestream_count() { - // Für API-basiertes System nicht relevant - return 0; -} - -function mm_video_get_livestream_debug_rows() { - // Ersetzt durch mm_video_get_api_livestream_debug() - return array(); -} - -function mm_video_render_livestream_group( $group, $index = 0 ) { - // Format 1: Neues API-YouTube-Format mit yt_id (Customizer oder Posts) - if ( isset( $group['yt_id'] ) && isset( $group['platform'] ) && $group['platform'] === 'youtube' ) { - $video_id = trim( (string) $group['yt_id'] ); - $title = isset( $group['title'] ) ? $group['title'] : __( 'Live', 'minecraft-modern-theme' ); - $handle = isset( $group['handle'] ) ? trim( (string) $group['handle'] ) : ''; - - if ( empty( $video_id ) ) { - return ''; - } - - $embed_url = 'https://www.youtube-nocookie.com/embed/' . rawurlencode( $video_id ) . '?autoplay=0&rel=0&modestbranding=1&playsinline=1'; - - ob_start(); - ?> -
-
- -
-
- - - - - - - - - - - -
-
- array( 'icon' => 'fab fa-twitch', 'color' => '#9146ff' ), - 'vimeo' => array( 'icon' => 'fab fa-vimeo-v', 'color' => '#1ab7ea' ), - 'youtube' => array( 'icon' => 'fab fa-youtube', 'color' => '#ff0000' ), - ); - $icon = isset( $platform_icons[$platform] ) ? $platform_icons[$platform]['icon'] : 'fas fa-play'; - - ob_start(); - ?> -
-
- -
-
- - - - - - - - - - - -
-
- 1 - ? __( 'Mehrere aktive oder gespeicherte Streams dieses Streamers lassen sich hier direkt umschalten.', 'minecraft-modern-theme' ) - : __( 'Der Bereich wird automatisch aus deinem Profil-Link erzeugt und oberhalb der Videos eingebunden.', 'minecraft-modern-theme' ) ); - - ob_start(); - ?> -
-
- - - - -

-

- 1 ) : ?> -
- - 1 / - -
-
- $item ) : ?> - - -
- -
- - - - - - - -
-

-
-
- -
- -
- - - -
- -

-
- -
-
- ' . __('Ungültige Video-URL.', 'minecraft-modern-theme') . '

'; - - $type = mm_video_get_type( $url ); - $title = isset($args['title']) ? esc_attr($args['title']) : __('Video', 'minecraft-modern-theme'); - - if ( $type === 'mp4' ) { - return '
' - . '
'; - } - - return '
' - . '
'; -} - - -// --- 5. Shortcode: [mm_video url="..."] --- -// Beispiele: -// [mm_video url="https://www.youtube.com/watch?v=dQw4w9WgXcQ"] -// [mm_video url="https://vimeo.com/123456789" title="Mein Video"] -function mm_video_shortcode( $atts ) { - $a = shortcode_atts( array( - 'url' => '', - 'title' => __('Video', 'minecraft-modern-theme'), - ), $atts ); - - if ( empty($a['url']) ) return ''; - return mm_video_render_embed( $a['url'], $a ); -} -add_shortcode( 'mm_video', 'mm_video_shortcode' ); - - -// --- 6. Template-Loader für Video-Archiv und Galerie-Seite --- -function mm_video_template_loader( $template ) { - // Archiv (domain.de/videos/) - if ( is_post_type_archive('mm_video') ) { - $t = get_template_directory() . '/archive-video.php'; - if ( file_exists($t) ) return $t; - } - // Seite mit dem Slug "videos" - if ( is_page() ) { - $obj = get_queried_object(); - if ( $obj && $obj->post_name === 'videos' ) { - $t = get_template_directory() . '/archive-video.php'; - if ( file_exists($t) ) return $t; - } - } - return $template; -} -add_filter( 'template_include', 'mm_video_template_loader' ); - - -// --- 7. "Videos"-Seite automatisch anlegen --- -function mm_video_create_page() { - if ( ! get_page_by_path('videos') ) { - wp_insert_post( array( - 'post_title' => __('Videos', 'minecraft-modern-theme'), - 'post_name' => 'videos', - 'post_status' => 'publish', - 'post_type' => 'page', - 'post_author' => 1, - ) ); - } -} -add_action( 'after_switch_theme', 'mm_video_create_page' ); -// Auch beim Speichern im Customizer anlegen -add_action( 'customize_save_after', 'mm_video_create_page' ); - - -// ============================================================================= -// === BEWERBUNGSFORMULAR ====================================================== -// ============================================================================= - -// --- 1. Customizer: Ein/Ausschalten --- -function mm_bewerbung_customizer( $wp_customize ) { - $wp_customize->add_section( 'mm_bewerbung_section', array( - 'title' => __( 'Bewerbungsformular', 'minecraft-modern-theme' ), - 'priority' => 80, - ) ); - - $wp_customize->add_setting( 'mm_bewerbung_enabled', array( - 'default' => false, - 'sanitize_callback' => 'wp_validate_boolean', - ) ); - $wp_customize->add_control( 'mm_bewerbung_enabled', array( - 'label' => __( 'Bewerbungsformular aktivieren', 'minecraft-modern-theme' ), - 'description' => __( 'Schaltet die Bewerbungsseite und das Formular ein.', 'minecraft-modern-theme' ), - 'section' => 'mm_bewerbung_section', - 'type' => 'checkbox', - ) ); - - $wp_customize->add_setting( 'mm_bewerbung_title', array( - 'default' => __( 'Bewirb dich bei uns!', 'minecraft-modern-theme' ), - 'sanitize_callback' => 'sanitize_text_field', - ) ); - $wp_customize->add_control( 'mm_bewerbung_title', array( - 'label' => __( 'Titel der Bewerbungsseite', 'minecraft-modern-theme' ), - 'section' => 'mm_bewerbung_section', - 'type' => 'text', - ) ); - - $wp_customize->add_setting( 'mm_bewerbung_desc', array( - 'default' => __( 'Du möchtest Teil unseres Teams werden? Füll das Formular aus und wir melden uns bei dir.', 'minecraft-modern-theme' ), - 'sanitize_callback' => 'sanitize_textarea_field', - ) ); - $wp_customize->add_control( 'mm_bewerbung_desc', array( - 'label' => __( 'Beschreibungstext', 'minecraft-modern-theme' ), - 'section' => 'mm_bewerbung_section', - 'type' => 'textarea', - ) ); - - $wp_customize->add_setting( 'mm_bewerbung_success_msg', array( - 'default' => __( 'Deine Bewerbung wurde erfolgreich eingereicht! Wir melden uns so bald wie möglich bei dir.', 'minecraft-modern-theme' ), - 'sanitize_callback' => 'sanitize_textarea_field', - ) ); - $wp_customize->add_control( 'mm_bewerbung_success_msg', array( - 'label' => __( 'Erfolgsmeldung nach dem Absenden', 'minecraft-modern-theme' ), - 'section' => 'mm_bewerbung_section', - 'type' => 'textarea', - ) ); - - $wp_customize->add_setting( 'mm_bewerbung_min_alter', array( - 'default' => 14, - 'sanitize_callback' => 'absint', - ) ); - $wp_customize->add_control( 'mm_bewerbung_min_alter', array( - 'label' => __( 'Mindestalter', 'minecraft-modern-theme' ), - 'description' => __( 'Bewerbungen unter diesem Alter werden abgelehnt. 0 = kein Limit.', 'minecraft-modern-theme' ), - 'section' => 'mm_bewerbung_section', - 'type' => 'number', - 'input_attrs' => array( 'min' => 0, 'max' => 99 ), - ) ); - - // ── Positionen ── - $wp_customize->add_setting( 'mm_bewerbung_positionen', array( - 'default' => "Moderator -Supporter -Builder -Developer", - 'sanitize_callback' => 'sanitize_textarea_field', - ) ); - $wp_customize->add_control( 'mm_bewerbung_positionen', array( - 'label' => __( 'Bewerbungs-Positionen', 'minecraft-modern-theme' ), - 'description' => __( 'Eine Position pro Zeile. Der Bewerber wählt genau eine davon aus.', 'minecraft-modern-theme' ), - 'section' => 'mm_bewerbung_section', - 'type' => 'textarea', - ) ); -} -add_action( 'customize_register', 'mm_bewerbung_customizer' ); - -// Hilfsfunktion: Positions-Liste als Array zurückgeben -function mm_bewerbung_get_positionen() { - $raw = get_theme_mod( 'mm_bewerbung_positionen', "Moderator -Supporter -Builder -Developer" ); - $list = array_filter( array_map( 'trim', explode( " -", $raw ) ) ); - return array_values( $list ); -} - - -// --- 2. Custom Post Type: Bewerbung --- -function mm_register_bewerbung_cpt() { - if ( ! get_theme_mod( 'mm_bewerbung_enabled', false ) ) return; - - register_post_type( 'mm_bewerbung', array( - 'labels' => array( - 'name' => __( 'Bewerbungen', 'minecraft-modern-theme' ), - 'singular_name' => __( 'Bewerbung', 'minecraft-modern-theme' ), - 'all_items' => __( 'Alle Bewerbungen', 'minecraft-modern-theme' ), - 'menu_name' => __( 'Bewerbungen', 'minecraft-modern-theme' ), - ), - 'public' => false, - 'show_ui' => true, - 'show_in_menu' => true, - 'menu_icon' => 'dashicons-clipboard', - 'menu_position' => 8, - 'supports' => array( 'title' ), - 'capabilities' => array( - 'create_posts' => 'do_not_allow', // Nur über Frontend erstellbar - ), - 'map_meta_cap' => true, - ) ); -} -add_action( 'init', 'mm_register_bewerbung_cpt' ); - - -// --- 3. Admin: Meta-Box für Bewerbungs-Details --- -function mm_bewerbung_meta_box() { - add_meta_box( - 'mm_bewerbung_details', - __( 'Bewerbungs-Details', 'minecraft-modern-theme' ), - 'mm_bewerbung_meta_box_html', - 'mm_bewerbung', 'normal', 'high' - ); - add_meta_box( - 'mm_bewerbung_status_box', - __( 'Status', 'minecraft-modern-theme' ), - 'mm_bewerbung_status_box_html', - 'mm_bewerbung', 'side', 'high' - ); -} -add_action( 'add_meta_boxes', 'mm_bewerbung_meta_box' ); - -function mm_bewerbung_meta_box_html( $post ) { - $fields = array( - '_mm_bew_mc_name' => __( 'Minecraft Username', 'minecraft-modern-theme' ), - '_mm_bew_discord' => __( 'Discord Username', 'minecraft-modern-theme' ), - '_mm_bew_alter' => __( 'Alter', 'minecraft-modern-theme' ), - '_mm_bew_position' => __( 'Bewirbt sich als', 'minecraft-modern-theme' ), - '_mm_bew_warum' => __( 'Warum möchtest du mitspielen?', 'minecraft-modern-theme' ), - '_mm_bew_erfahrung' => __( 'Erfahrung / Vorstellung', 'minecraft-modern-theme' ), - '_mm_bew_datum' => __( 'Eingereicht am', 'minecraft-modern-theme' ), - '_mm_bew_ip' => __( 'IP-Adresse', 'minecraft-modern-theme' ), - ); - echo ''; - foreach ( $fields as $key => $label ) { - $val = get_post_meta( $post->ID, $key, true ); - if ( ! $val ) continue; - $is_long = in_array( $key, array( '_mm_bew_warum', '_mm_bew_erfahrung' ) ); - echo ''; - echo ''; - echo ''; - } - echo '
' . esc_html($label) . ''; - if ( $is_long ) { - echo '
' . esc_html($val) . '
'; - } else { - echo '' . esc_html($val) . ''; - } - echo '
'; -} - -function mm_bewerbung_status_box_html( $post ) { - $status = get_post_meta( $post->ID, '_mm_bew_status', true ) ?: 'neu'; - wp_nonce_field( 'mm_bew_status_save', 'mm_bew_status_nonce' ); - $options = array( - 'neu' => array( 'label' => __('Neu','minecraft-modern-theme'), 'color' => '#0073aa' ), - 'in_pruef' => array( 'label' => __('In Prüfung','minecraft-modern-theme'), 'color' => '#f0ad4e' ), - 'angenommen' => array( 'label' => __('Angenommen','minecraft-modern-theme'), 'color' => '#46b450' ), - 'abgelehnt' => array( 'label' => __('Abgelehnt','minecraft-modern-theme'), 'color' => '#dc3232' ), - ); - echo ''; - $cur = isset($options[$status]) ? $options[$status] : $options['neu']; - echo '
' . esc_html($cur['label']) . '
'; - - // Admin-Notiz - $notiz = get_post_meta( $post->ID, '_mm_bew_notiz', true ); - echo '
'; - echo ''; - echo ''; -} - -function mm_bewerbung_save_status( $post_id ) { - if ( ! isset($_POST['mm_bew_status_nonce']) || ! wp_verify_nonce($_POST['mm_bew_status_nonce'], 'mm_bew_status_save') ) return; - if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return; - if ( ! current_user_can('edit_post', $post_id) ) return; - if ( isset($_POST['mm_bew_status']) ) { - update_post_meta( $post_id, '_mm_bew_status', sanitize_text_field($_POST['mm_bew_status']) ); - } - if ( isset($_POST['mm_bew_notiz']) ) { - update_post_meta( $post_id, '_mm_bew_notiz', sanitize_textarea_field($_POST['mm_bew_notiz']) ); - } -} -add_action( 'save_post', 'mm_bewerbung_save_status' ); - - -// --- 4. Admin-Spalten in der Bewerbungsliste --- -function mm_bewerbung_columns( $cols ) { - return array( - 'cb' => $cols['cb'], - 'title' => __( 'Name', 'minecraft-modern-theme' ), - 'mc_name' => __( 'Minecraft', 'minecraft-modern-theme' ), - 'discord' => __( 'Discord', 'minecraft-modern-theme' ), - 'alter' => __( 'Alter', 'minecraft-modern-theme' ), - 'position' => __( 'Position', 'minecraft-modern-theme' ), - 'status' => __( 'Status', 'minecraft-modern-theme' ), - 'datum' => __( 'Eingereicht', 'minecraft-modern-theme' ), - ); -} -add_filter( 'manage_mm_bewerbung_posts_columns', 'mm_bewerbung_columns' ); - -function mm_bewerbung_column_content( $col, $post_id ) { - $status_colors = array( - 'neu' => '#0073aa', - 'in_pruef' => '#f0ad4e', - 'angenommen' => '#46b450', - 'abgelehnt' => '#dc3232', - ); - $status_labels = array( - 'neu' => __('Neu','minecraft-modern-theme'), - 'in_pruef' => __('In Prüfung','minecraft-modern-theme'), - 'angenommen' => __('Angenommen','minecraft-modern-theme'), - 'abgelehnt' => __('Abgelehnt','minecraft-modern-theme'), - ); - switch ($col) { - case 'mc_name': - $mc = get_post_meta($post_id, '_mm_bew_mc_name', true); - if ($mc) { - echo '
'; - echo ''; - echo esc_html($mc) . '
'; - } - break; - case 'discord': - echo esc_html( get_post_meta($post_id, '_mm_bew_discord', true) ); - break; - case 'alter': - echo esc_html( get_post_meta($post_id, '_mm_bew_alter', true) ); - break; - case 'position': - $pos = get_post_meta($post_id, '_mm_bew_position', true); - if ( $pos ) { - echo '' - . esc_html($pos) . ''; - } else { - echo ''; - } - break; - case 'status': - $s = get_post_meta($post_id, '_mm_bew_status', true) ?: 'neu'; - $color = isset($status_colors[$s]) ? $status_colors[$s] : '#0073aa'; - $label = isset($status_labels[$s]) ? $status_labels[$s] : $s; - echo '' . esc_html($label) . ''; - break; - case 'datum': - echo esc_html( get_post_meta($post_id, '_mm_bew_datum', true) ); - break; - } -} -add_action( 'manage_mm_bewerbung_posts_custom_column', 'mm_bewerbung_column_content', 10, 2 ); - - -// --- 5. AJAX: Formular absenden --- -add_action( 'wp_ajax_mm_submit_bewerbung', 'mm_submit_bewerbung' ); -add_action( 'wp_ajax_nopriv_mm_submit_bewerbung', 'mm_submit_bewerbung' ); - -function mm_submit_bewerbung() { - // Nonce prüfen - if ( ! isset($_POST['nonce']) || ! wp_verify_nonce($_POST['nonce'], 'mm_bewerbung_nonce') ) { - wp_send_json_error( array('msg' => __('Sicherheitsfehler. Bitte Seite neu laden.', 'minecraft-modern-theme')) ); - } - - // Felder validieren - $mc_name = sanitize_text_field( $_POST['mc_name'] ?? '' ); - $discord = sanitize_text_field( $_POST['discord'] ?? '' ); - $alter_raw = absint( $_POST['alter'] ?? 0 ); - $warum = sanitize_textarea_field( $_POST['warum'] ?? '' ); - $erfahrung = sanitize_textarea_field( $_POST['erfahrung'] ?? '' ); - - $position = sanitize_text_field( $_POST['position'] ?? '' ); - $positionen = mm_bewerbung_get_positionen(); - - $errors = array(); - if ( empty($mc_name) ) $errors[] = __('Minecraft Username ist erforderlich.', 'minecraft-modern-theme'); - if ( empty($discord) ) $errors[] = __('Discord Username ist erforderlich.', 'minecraft-modern-theme'); - if ( $alter_raw < 1 ) $errors[] = __('Bitte gib dein Alter an.', 'minecraft-modern-theme'); - if ( ! empty($positionen) && ! in_array($position, $positionen, true) ) { - $errors[] = __('Bitte wähle eine gültige Position aus.', 'minecraft-modern-theme'); - } - if ( empty($warum) ) $errors[] = __('Bitte erkläre warum du mitspielen möchtest.', 'minecraft-modern-theme'); - if ( empty($erfahrung) ) $errors[] = __('Bitte stell dich kurz vor.', 'minecraft-modern-theme'); - - // Mindestalter prüfen - $min_alter = absint( get_theme_mod('mm_bewerbung_min_alter', 14) ); - if ( $min_alter > 0 && $alter_raw < $min_alter ) { - $errors[] = sprintf( __('Du musst mindestens %d Jahre alt sein.', 'minecraft-modern-theme'), $min_alter ); - } - - // Doppelbewerbung prüfen (gleicher MC-Name in den letzten 30 Tagen) - $existing = get_posts( array( - 'post_type' => 'mm_bewerbung', - 'post_status' => 'publish', - 'meta_query' => array( - array( 'key' => '_mm_bew_mc_name', 'value' => $mc_name, 'compare' => '=' ), - ), - 'date_query' => array( - array( 'after' => '30 days ago' ), - ), - 'numberposts' => 1, - ) ); - if ( $existing ) { - $errors[] = __('Mit diesem Minecraft-Namen wurde in den letzten 30 Tagen bereits eine Bewerbung eingereicht.', 'minecraft-modern-theme'); - } - - if ( ! empty($errors) ) { - wp_send_json_error( array('msg' => implode(' ', $errors)) ); - } - - // Bewerbung als Post speichern - $post_id = wp_insert_post( array( - 'post_type' => 'mm_bewerbung', - 'post_status' => 'publish', - 'post_title' => $mc_name . ' – ' . date_i18n('d.m.Y H:i'), - ) ); - - if ( is_wp_error($post_id) ) { - wp_send_json_error( array('msg' => __('Fehler beim Speichern. Bitte versuche es erneut.', 'minecraft-modern-theme')) ); - } - - update_post_meta( $post_id, '_mm_bew_mc_name', $mc_name ); - update_post_meta( $post_id, '_mm_bew_discord', $discord ); - update_post_meta( $post_id, '_mm_bew_alter', $alter_raw ); - update_post_meta( $post_id, '_mm_bew_position', $position ); - update_post_meta( $post_id, '_mm_bew_warum', $warum ); - update_post_meta( $post_id, '_mm_bew_erfahrung', $erfahrung ); - update_post_meta( $post_id, '_mm_bew_status', 'neu' ); - update_post_meta( $post_id, '_mm_bew_datum', date_i18n('d.m.Y H:i:s') ); - update_post_meta( $post_id, '_mm_bew_ip', sanitize_text_field( $_SERVER['REMOTE_ADDR'] ?? '' ) ); - - $success_msg = get_theme_mod( 'mm_bewerbung_success_msg', __('Deine Bewerbung wurde erfolgreich eingereicht! Wir melden uns so bald wie möglich bei dir.', 'minecraft-modern-theme') ); - wp_send_json_success( array('msg' => $success_msg) ); -} - - -// --- 6. Template-Loader --- -function mm_bewerbung_template_loader( $template ) { - if ( ! get_theme_mod('mm_bewerbung_enabled', false) ) return $template; - if ( is_page('bewerbung') ) { - $t = get_template_directory() . '/page-bewerbung.php'; - if ( file_exists($t) ) return $t; - } - return $template; -} -add_filter( 'template_include', 'mm_bewerbung_template_loader' ); - - -// --- 7. Seite automatisch anlegen --- -function mm_bewerbung_create_page() { - if ( ! get_theme_mod('mm_bewerbung_enabled', false) ) return; - if ( ! get_page_by_path('bewerbung') ) { - wp_insert_post( array( - 'post_title' => __('Bewerbung', 'minecraft-modern-theme'), - 'post_name' => 'bewerbung', - 'post_status' => 'publish', - 'post_type' => 'page', - 'post_author' => 1, - ) ); - } -} -add_action( 'customize_save_after', 'mm_bewerbung_create_page' ); \ No newline at end of file +require get_template_directory() . '/inc/widgets.php'; +require get_template_directory() . '/inc/faq.php'; +require get_template_directory() . '/inc/frontpage.php'; +require get_template_directory() . '/inc/login.php'; +require get_template_directory() . '/inc/scroll-to-top.php'; +require get_template_directory() . '/inc/settings-io.php'; +require get_template_directory() . '/inc/announcement.php'; +require get_template_directory() . '/inc/team.php'; +require get_template_directory() . '/inc/header-nav.php'; +require get_template_directory() . '/inc/cookie-banner.php'; +require get_template_directory() . '/inc/video.php'; +require get_template_directory() . '/inc/bewerbung.php'; +require get_template_directory() . '/inc/login-url.php'; +require get_template_directory() . '/inc/menu-links.php'; diff --git a/Minecraft-Modern-Theme/get-channel-id.php b/Minecraft-Modern-Theme/get-channel-id.php index a7aff63..f0141e2 100644 --- a/Minecraft-Modern-Theme/get-channel-id.php +++ b/Minecraft-Modern-Theme/get-channel-id.php @@ -2,8 +2,16 @@ /** * Hilfsskript: Finde Channel-ID für einen @Handle * Verwendet direkt die YouTube API (ohne WordPress) + * + * SICHERHEIT: Nur per CLI ausführbar (php get-channel-id.php @handle). + * Über den Browser aufgerufen bricht das Skript sofort ab. */ +if ( php_sapi_name() !== 'cli' ) { + http_response_code( 403 ); + exit( 'Forbidden: Dieses Skript darf nur per CLI ausgeführt werden.' ); +} + // API Key aus wp-config.php lesen $wp_config_path = __DIR__ . '/../../../wp-config.php'; $api_key = ''; @@ -16,10 +24,13 @@ if ( file_exists( $wp_config_path ) ) { } } -// Fallback: Direkte Eingabe hier (NUR FÜR TESTS!) +// Fallback: API Key per Umgebungsvariable übergeben (NUR FÜR TESTS!) +// Beispiel: YOUTUBE_API_KEY=dein_key php get-channel-id.php @handle if ( empty( $api_key ) ) { - // TEMPORÄR: Trage hier deinen API Key ein - $api_key = 'AIzaSyD-jSXZO-R4NJBySF0WL6SoFJmBDk2Gdbk'; // ← Dein API Key aus dem Customizer + $env_key = getenv( 'YOUTUBE_API_KEY' ); + if ( $env_key !== false ) { + $api_key = $env_key; + } } if ( ! isset( $argv[1] ) ) { diff --git a/Minecraft-Modern-Theme/header.php b/Minecraft-Modern-Theme/header.php index 01ee639..5cc3a24 100644 --- a/Minecraft-Modern-Theme/header.php +++ b/Minecraft-Modern-Theme/header.php @@ -4,7 +4,7 @@ - + > diff --git a/Minecraft-Modern-Theme/js/mm-announcement-admin.js b/Minecraft-Modern-Theme/js/mm-announcement-admin.js index 2e88e56..dba1d1a 100644 --- a/Minecraft-Modern-Theme/js/mm-announcement-admin.js +++ b/Minecraft-Modern-Theme/js/mm-announcement-admin.js @@ -1,158 +1,161 @@ -(function($){ - $(document).ready(function(){ - - const fonts = window.MM_Announcement_Fonts || {}; - const current = window.MM_Announcement_Current || {}; - const fontSelect = $('#mm-announcement-font'); - const sizeInput = $('#mm-announcement-size'); - const bgInput = $('#mm-announcement-bg'); - const colorInput = $('#mm-announcement-color'); - const previewText = $('#mm-announcement-preview-text'); - const previewWrap = $('#mm-announcement-preview'); - const positionSelect = $('#mm-announcement-position'); - - // Helper: lädt Google-Font-Link oder updatet existing - function ensureGoogleFont(googleName) { - if (!googleName) return; - const id = 'mm-admin-google-font'; - const href = 'https://fonts.googleapis.com/css2?family=' + encodeURIComponent(googleName) + ':wght@400;700&display=swap'; - let link = document.getElementById(id); - if (link) { - if (link.getAttribute('href') !== href) link.setAttribute('href', href); - } else { - link = document.createElement('link'); - link.id = id; - link.rel = 'stylesheet'; - link.href = href; - document.head.appendChild(link); - } - } - - // Update preview appearance based on font key - function updatePreviewForFontKey(key) { - const meta = fonts[key]; - if (!meta) { - previewText.css('font-family', ''); - return; - } - previewText.css('font-family', meta.css); - if (meta.google && meta.google_name) { - ensureGoogleFont(meta.google_name); - } - } - - // Update size/colors/position UI - function updateSizeAndColors() { - const size = parseInt(sizeInput.val(), 10) || 16; - previewText.css('font-size', size + 'px'); - previewWrap.css('background', bgInput.val()); - previewWrap.css('color', colorInput.val()); - } - - // Read content from wp_editor (TinyMCE) or textarea - function getEditorText() { - // Try TinyMCE first - if ( typeof tinymce !== 'undefined' ) { - try { - const ed = tinymce.get('mm_announcement_text'); - if (ed && !ed.isHidden()) { - // getContent then strip tags - const html = ed.getContent({format: 'html'}); - const tmp = document.createElement('div'); - tmp.innerHTML = html; - return tmp.textContent || tmp.innerText || ''; - } - } catch (e) { - // ignore - } - } - // Fallback to textarea - const ta = $('#mm_announcement_text'); - if (ta.length) { - const tmp = document.createElement('div'); - tmp.innerHTML = ta.val(); - return tmp.textContent || tmp.innerText || ''; - } - return ''; - } - - // Update preview text from editor content - function updatePreviewTextFromEditor() { - const text = getEditorText(); - if (text && text.trim().length) { - previewText.text(text.trim()); - } else { - previewText.text(current.text || 'Das ist eine Vorschau: Wie sieht die Schrift aus?'); - } - } - - // Initialize controls with current settings - if (current.font) { - updatePreviewForFontKey(current.font); - fontSelect.val(current.font); - } else { - updatePreviewForFontKey(fontSelect.val()); - } - if (current.size) sizeInput.val(current.size); - if (current.bg) bgInput.val(current.bg); - if (current.color) colorInput.val(current.color); - - updateSizeAndColors(); - updatePreviewTextFromEditor(); - - // Attach events -------------------------------------------------- - - // font change - fontSelect.on('change', function(){ - const key = $(this).val(); - updatePreviewForFontKey(key); - }); - - // size/color/position change - sizeInput.on('input change', updateSizeAndColors ); - bgInput.on('input change', updateSizeAndColors ); - colorInput.on('input change', updateSizeAndColors ); - - // Editor changes: - // - TinyMCE: listen for keyup / change events when editor is ready - // - Textarea: listen for input - function attachEditorListeners() { - // TinyMCE - if ( typeof tinymce !== 'undefined' ) { - const ed = tinymce.get('mm_announcement_text'); - if (ed) { - ed.on('keyup change NodeChange', function(){ - updatePreviewTextFromEditor(); - }); - } - } - - // Textarea fallback - $('#mm_announcement_text').on('input change', function(){ - updatePreviewTextFromEditor(); - }); - } - - // TinyMCE initialisation might be async — poll short time then attach - let tries = 0; - const waitForEditor = setInterval(function(){ - tries++; - if ( (typeof tinymce !== 'undefined' && tinymce.get('mm_announcement_text')) || $('#mm_announcement_text').length ) { - clearInterval(waitForEditor); - attachEditorListeners(); - } else if (tries > 30) { // about 3s - clearInterval(waitForEditor); - // still attach textarea event just in case - $('#mm_announcement_text').on('input change', updatePreviewTextFromEditor); - } - }, 100); - - // Also update preview when the form is programmatically changed (e.g., quicktags) - $(document).on('change', '#mm-announcement-font, #mm-announcement-size, #mm-announcement-bg, #mm-announcement-color', function(){ - updateSizeAndColors(); - updatePreviewForFontKey($('#mm-announcement-font').val()); - updatePreviewTextFromEditor(); - }); - - }); -})(jQuery); +(function($){ + $(document).ready(function(){ + + const fonts = window.MM_Announcement_Fonts || {}; + const current = window.MM_Announcement_Current || {}; + const fontSelect = $('#mm-announcement-font'); + const sizeInput = $('#mm-announcement-size'); + const bgInput = $('#mm-announcement-bg'); + const colorInput = $('#mm-announcement-color'); + const previewText = $('#mm-announcement-preview-text'); + const previewWrap = $('#mm-announcement-preview'); + const positionSelect = $('#mm-announcement-position'); + + // Helper: bindet die lokal gehostete Schrift für die Vorschau ein. + // Kein Aufruf von fonts.googleapis.com – die Dateien liegen im Theme + // unter /fonts//font.css (siehe mm_enqueue_local_font() in PHP). + function ensureLocalFont(fontKey) { + if (!fontKey || !current.fontsBase) return; + const slug = String(fontKey).toLowerCase().replace(/ /g, '-'); + const id = 'mm-admin-local-font'; + const href = current.fontsBase + slug + '/font.css'; + let link = document.getElementById(id); + if (link) { + if (link.getAttribute('href') !== href) link.setAttribute('href', href); + } else { + link = document.createElement('link'); + link.id = id; + link.rel = 'stylesheet'; + link.href = href; + document.head.appendChild(link); + } + } + + // Update preview appearance based on font key + function updatePreviewForFontKey(key) { + const meta = fonts[key]; + if (!meta) { + previewText.css('font-family', ''); + return; + } + previewText.css('font-family', meta.css); + if (meta.google) { + ensureLocalFont(key); + } + } + + // Update size/colors/position UI + function updateSizeAndColors() { + const size = parseInt(sizeInput.val(), 10) || 16; + previewText.css('font-size', size + 'px'); + previewWrap.css('background', bgInput.val()); + previewWrap.css('color', colorInput.val()); + } + + // Read content from wp_editor (TinyMCE) or textarea + function getEditorText() { + // Try TinyMCE first + if ( typeof tinymce !== 'undefined' ) { + try { + const ed = tinymce.get('mm_announcement_text'); + if (ed && !ed.isHidden()) { + // getContent then strip tags + const html = ed.getContent({format: 'html'}); + const tmp = document.createElement('div'); + tmp.innerHTML = html; + return tmp.textContent || tmp.innerText || ''; + } + } catch (e) { + // ignore + } + } + // Fallback to textarea + const ta = $('#mm_announcement_text'); + if (ta.length) { + const tmp = document.createElement('div'); + tmp.innerHTML = ta.val(); + return tmp.textContent || tmp.innerText || ''; + } + return ''; + } + + // Update preview text from editor content + function updatePreviewTextFromEditor() { + const text = getEditorText(); + if (text && text.trim().length) { + previewText.text(text.trim()); + } else { + previewText.text(current.text || 'Das ist eine Vorschau: Wie sieht die Schrift aus?'); + } + } + + // Initialize controls with current settings + if (current.font) { + updatePreviewForFontKey(current.font); + fontSelect.val(current.font); + } else { + updatePreviewForFontKey(fontSelect.val()); + } + if (current.size) sizeInput.val(current.size); + if (current.bg) bgInput.val(current.bg); + if (current.color) colorInput.val(current.color); + + updateSizeAndColors(); + updatePreviewTextFromEditor(); + + // Attach events -------------------------------------------------- + + // font change + fontSelect.on('change', function(){ + const key = $(this).val(); + updatePreviewForFontKey(key); + }); + + // size/color/position change + sizeInput.on('input change', updateSizeAndColors ); + bgInput.on('input change', updateSizeAndColors ); + colorInput.on('input change', updateSizeAndColors ); + + // Editor changes: + // - TinyMCE: listen for keyup / change events when editor is ready + // - Textarea: listen for input + function attachEditorListeners() { + // TinyMCE + if ( typeof tinymce !== 'undefined' ) { + const ed = tinymce.get('mm_announcement_text'); + if (ed) { + ed.on('keyup change NodeChange', function(){ + updatePreviewTextFromEditor(); + }); + } + } + + // Textarea fallback + $('#mm_announcement_text').on('input change', function(){ + updatePreviewTextFromEditor(); + }); + } + + // TinyMCE initialisation might be async — poll short time then attach + let tries = 0; + const waitForEditor = setInterval(function(){ + tries++; + if ( (typeof tinymce !== 'undefined' && tinymce.get('mm_announcement_text')) || $('#mm_announcement_text').length ) { + clearInterval(waitForEditor); + attachEditorListeners(); + } else if (tries > 30) { // about 3s + clearInterval(waitForEditor); + // still attach textarea event just in case + $('#mm_announcement_text').on('input change', updatePreviewTextFromEditor); + } + }, 100); + + // Also update preview when the form is programmatically changed (e.g., quicktags) + $(document).on('change', '#mm-announcement-font, #mm-announcement-size, #mm-announcement-bg, #mm-announcement-color', function(){ + updateSizeAndColors(); + updatePreviewForFontKey($('#mm-announcement-font').val()); + updatePreviewTextFromEditor(); + }); + + }); +})(jQuery); diff --git a/Minecraft-Modern-Theme/js/slider-init.js b/Minecraft-Modern-Theme/js/slider-init.js index 792f039..64b494d 100644 --- a/Minecraft-Modern-Theme/js/slider-init.js +++ b/Minecraft-Modern-Theme/js/slider-init.js @@ -1,50 +1,50 @@ -document.addEventListener('DOMContentLoaded', function() { - - const heroSlider = document.querySelector('.hero-slider'); - if (!heroSlider) return; - - // BUG-FIX: sliderSettings wird via wp_localize_script gesetzt. Fehlt es - // (z.B. wegen Caching oder falschem Enqueue), würde ein ReferenceError - // den gesamten Slider-Init abschießen. - if (typeof sliderSettings === 'undefined') { - console.warn('Minecraft Modern Theme: sliderSettings nicht gefunden. Slider wird nicht initialisiert.'); - heroSlider.classList.add('swiper-initialized'); // Opacity-Fix trotzdem aufheben - return; - } - - const swiperConfig = { - effect: 'fade', - fadeEffect: { - crossFade: true - }, - - loop: sliderSettings.loop === '1', - - autoplay: { - delay: 5000, - disableOnInteraction: false, - }, - - pauseOnMouseEnter: true, - - navigation: sliderSettings.hideArrows !== '1' ? { - nextEl: '.swiper-button-next', - prevEl: '.swiper-button-prev', - } : false, - - pagination: sliderSettings.hidePagination !== '1' ? { - el: '.swiper-pagination', - clickable: true, - } : false, - - on: { - init: function () { - setTimeout(function() { - heroSlider.classList.add('swiper-initialized'); - }, 50); - }, - }, - }; - - new Swiper('.hero-slider', swiperConfig); +document.addEventListener('DOMContentLoaded', function() { + + const heroSlider = document.querySelector('.hero-slider'); + if (!heroSlider) return; + + // BUG-FIX: sliderSettings wird via wp_localize_script gesetzt. Fehlt es + // (z.B. wegen Caching oder falschem Enqueue), würde ein ReferenceError + // den gesamten Slider-Init abschießen. + if (typeof sliderSettings === 'undefined') { + console.warn('Minecraft Modern Theme: sliderSettings nicht gefunden. Slider wird nicht initialisiert.'); + heroSlider.classList.add('swiper-initialized'); // Opacity-Fix trotzdem aufheben + return; + } + + const swiperConfig = { + effect: 'fade', + fadeEffect: { + crossFade: true + }, + + loop: sliderSettings.loop === '1', + + autoplay: { + delay: 5000, + disableOnInteraction: false, + }, + + pauseOnMouseEnter: true, + + navigation: sliderSettings.hideArrows !== '1' ? { + nextEl: '.swiper-button-next', + prevEl: '.swiper-button-prev', + } : false, + + pagination: sliderSettings.hidePagination !== '1' ? { + el: '.swiper-pagination', + clickable: true, + } : false, + + on: { + init: function () { + setTimeout(function() { + heroSlider.classList.add('swiper-initialized'); + }, 50); + }, + }, + }; + + new Swiper('.hero-slider', swiperConfig); }); \ No newline at end of file diff --git a/Minecraft-Modern-Theme/js/swiper-bundle.min.js b/Minecraft-Modern-Theme/js/swiper-bundle.min.js new file mode 100644 index 0000000..9353f8c --- /dev/null +++ b/Minecraft-Modern-Theme/js/swiper-bundle.min.js @@ -0,0 +1,14 @@ +/** + * Swiper 8.4.7 + * Most modern mobile touch slider and framework with hardware accelerated transitions + * https://swiperjs.com + * + * Copyright 2014-2023 Vladimir Kharlampidi + * + * Released under the MIT License + * + * Released on: January 30, 2023 + */ + +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Swiper=t()}(this,(function(){"use strict";function e(e){return null!==e&&"object"==typeof e&&"constructor"in e&&e.constructor===Object}function t(s,a){void 0===s&&(s={}),void 0===a&&(a={}),Object.keys(a).forEach((i=>{void 0===s[i]?s[i]=a[i]:e(a[i])&&e(s[i])&&Object.keys(a[i]).length>0&&t(s[i],a[i])}))}const s={body:{},addEventListener(){},removeEventListener(){},activeElement:{blur(){},nodeName:""},querySelector:()=>null,querySelectorAll:()=>[],getElementById:()=>null,createEvent:()=>({initEvent(){}}),createElement:()=>({children:[],childNodes:[],style:{},setAttribute(){},getElementsByTagName:()=>[]}),createElementNS:()=>({}),importNode:()=>null,location:{hash:"",host:"",hostname:"",href:"",origin:"",pathname:"",protocol:"",search:""}};function a(){const e="undefined"!=typeof document?document:{};return t(e,s),e}const i={document:s,navigator:{userAgent:""},location:{hash:"",host:"",hostname:"",href:"",origin:"",pathname:"",protocol:"",search:""},history:{replaceState(){},pushState(){},go(){},back(){}},CustomEvent:function(){return this},addEventListener(){},removeEventListener(){},getComputedStyle:()=>({getPropertyValue:()=>""}),Image(){},Date(){},screen:{},setTimeout(){},clearTimeout(){},matchMedia:()=>({}),requestAnimationFrame:e=>"undefined"==typeof setTimeout?(e(),null):setTimeout(e,0),cancelAnimationFrame(e){"undefined"!=typeof setTimeout&&clearTimeout(e)}};function r(){const e="undefined"!=typeof window?window:{};return t(e,i),e}class n extends Array{constructor(e){"number"==typeof e?super(e):(super(...e||[]),function(e){const t=e.__proto__;Object.defineProperty(e,"__proto__",{get:()=>t,set(e){t.__proto__=e}})}(this))}}function l(e){void 0===e&&(e=[]);const t=[];return e.forEach((e=>{Array.isArray(e)?t.push(...l(e)):t.push(e)})),t}function o(e,t){return Array.prototype.filter.call(e,t)}function d(e,t){const s=r(),i=a();let l=[];if(!t&&e instanceof n)return e;if(!e)return new n(l);if("string"==typeof e){const s=e.trim();if(s.indexOf("<")>=0&&s.indexOf(">")>=0){let e="div";0===s.indexOf("e.split(" "))));return this.forEach((e=>{e.classList.add(...a)})),this},removeClass:function(){for(var e=arguments.length,t=new Array(e),s=0;se.split(" "))));return this.forEach((e=>{e.classList.remove(...a)})),this},hasClass:function(){for(var e=arguments.length,t=new Array(e),s=0;se.split(" "))));return o(this,(e=>a.filter((t=>e.classList.contains(t))).length>0)).length>0},toggleClass:function(){for(var e=arguments.length,t=new Array(e),s=0;se.split(" "))));this.forEach((e=>{a.forEach((t=>{e.classList.toggle(t)}))}))},attr:function(e,t){if(1===arguments.length&&"string"==typeof e)return this[0]?this[0].getAttribute(e):void 0;for(let s=0;s=0;e-=1){const i=a[e];r&&i.listener===r||r&&i.listener&&i.listener.dom7proxy&&i.listener.dom7proxy===r?(s.removeEventListener(t,i.proxyListener,n),a.splice(e,1)):r||(s.removeEventListener(t,i.proxyListener,n),a.splice(e,1))}}}return this},trigger:function(){const e=r();for(var t=arguments.length,s=new Array(t),a=0;at>0)),i.dispatchEvent(t),i.dom7EventData=[],delete i.dom7EventData}}}return this},transitionEnd:function(e){const t=this;return e&&t.on("transitionend",(function s(a){a.target===this&&(e.call(this,a),t.off("transitionend",s))})),this},outerWidth:function(e){if(this.length>0){if(e){const e=this.styles();return this[0].offsetWidth+parseFloat(e.getPropertyValue("margin-right"))+parseFloat(e.getPropertyValue("margin-left"))}return this[0].offsetWidth}return null},outerHeight:function(e){if(this.length>0){if(e){const e=this.styles();return this[0].offsetHeight+parseFloat(e.getPropertyValue("margin-top"))+parseFloat(e.getPropertyValue("margin-bottom"))}return this[0].offsetHeight}return null},styles:function(){const e=r();return this[0]?e.getComputedStyle(this[0],null):{}},offset:function(){if(this.length>0){const e=r(),t=a(),s=this[0],i=s.getBoundingClientRect(),n=t.body,l=s.clientTop||n.clientTop||0,o=s.clientLeft||n.clientLeft||0,d=s===e?e.scrollY:s.scrollTop,c=s===e?e.scrollX:s.scrollLeft;return{top:i.top+d-l,left:i.left+c-o}}return null},css:function(e,t){const s=r();let a;if(1===arguments.length){if("string"!=typeof e){for(a=0;a{e.apply(t,[t,s])})),this):this},html:function(e){if(void 0===e)return this[0]?this[0].innerHTML:null;for(let t=0;tt-1)return d([]);if(e<0){const s=t+e;return d(s<0?[]:[this[s]])}return d([this[e]])},append:function(){let e;const t=a();for(let s=0;s=0;i-=1)this[s].insertBefore(a.childNodes[i],this[s].childNodes[0])}else if(e instanceof n)for(i=0;i0?e?this[0].nextElementSibling&&d(this[0].nextElementSibling).is(e)?d([this[0].nextElementSibling]):d([]):this[0].nextElementSibling?d([this[0].nextElementSibling]):d([]):d([])},nextAll:function(e){const t=[];let s=this[0];if(!s)return d([]);for(;s.nextElementSibling;){const a=s.nextElementSibling;e?d(a).is(e)&&t.push(a):t.push(a),s=a}return d(t)},prev:function(e){if(this.length>0){const t=this[0];return e?t.previousElementSibling&&d(t.previousElementSibling).is(e)?d([t.previousElementSibling]):d([]):t.previousElementSibling?d([t.previousElementSibling]):d([])}return d([])},prevAll:function(e){const t=[];let s=this[0];if(!s)return d([]);for(;s.previousElementSibling;){const a=s.previousElementSibling;e?d(a).is(e)&&t.push(a):t.push(a),s=a}return d(t)},parent:function(e){const t=[];for(let s=0;s6&&(i=i.split(", ").map((e=>e.replace(",","."))).join(", ")),n=new s.WebKitCSSMatrix("none"===i?"":i)):(n=l.MozTransform||l.OTransform||l.MsTransform||l.msTransform||l.transform||l.getPropertyValue("transform").replace("translate(","matrix(1, 0, 0, 1,"),a=n.toString().split(",")),"x"===t&&(i=s.WebKitCSSMatrix?n.m41:16===a.length?parseFloat(a[12]):parseFloat(a[4])),"y"===t&&(i=s.WebKitCSSMatrix?n.m42:16===a.length?parseFloat(a[13]):parseFloat(a[5])),i||0}function m(e){return"object"==typeof e&&null!==e&&e.constructor&&"Object"===Object.prototype.toString.call(e).slice(8,-1)}function f(e){return"undefined"!=typeof window&&void 0!==window.HTMLElement?e instanceof HTMLElement:e&&(1===e.nodeType||11===e.nodeType)}function g(){const e=Object(arguments.length<=0?void 0:arguments[0]),t=["__proto__","constructor","prototype"];for(let s=1;st.indexOf(e)<0));for(let t=0,i=s.length;tn?"next":"prev",p=(e,t)=>"next"===c&&e>=t||"prev"===c&&e<=t,u=()=>{l=(new Date).getTime(),null===o&&(o=l);const e=Math.max(Math.min((l-o)/d,1),0),r=.5-Math.cos(e*Math.PI)/2;let c=n+r*(s-n);if(p(c,s)&&(c=s),t.wrapperEl.scrollTo({[a]:c}),p(c,s))return t.wrapperEl.style.overflow="hidden",t.wrapperEl.style.scrollSnapType="",setTimeout((()=>{t.wrapperEl.style.overflow="",t.wrapperEl.scrollTo({[a]:c})})),void i.cancelAnimationFrame(t.cssModeFrameID);t.cssModeFrameID=i.requestAnimationFrame(u)};u()}let b,x,y;function E(){return b||(b=function(){const e=r(),t=a();return{smoothScroll:t.documentElement&&"scrollBehavior"in t.documentElement.style,touch:!!("ontouchstart"in e||e.DocumentTouch&&t instanceof e.DocumentTouch),passiveListener:function(){let t=!1;try{const s=Object.defineProperty({},"passive",{get(){t=!0}});e.addEventListener("testPassiveListener",null,s)}catch(e){}return t}(),gestures:"ongesturestart"in e}}()),b}function C(e){return void 0===e&&(e={}),x||(x=function(e){let{userAgent:t}=void 0===e?{}:e;const s=E(),a=r(),i=a.navigator.platform,n=t||a.navigator.userAgent,l={ios:!1,android:!1},o=a.screen.width,d=a.screen.height,c=n.match(/(Android);?[\s\/]+([\d.]+)?/);let p=n.match(/(iPad).*OS\s([\d_]+)/);const u=n.match(/(iPod)(.*OS\s([\d_]+))?/),h=!p&&n.match(/(iPhone\sOS|iOS)\s([\d_]+)/),m="Win32"===i;let f="MacIntel"===i;return!p&&f&&s.touch&&["1024x1366","1366x1024","834x1194","1194x834","834x1112","1112x834","768x1024","1024x768","820x1180","1180x820","810x1080","1080x810"].indexOf(`${o}x${d}`)>=0&&(p=n.match(/(Version)\/([\d.]+)/),p||(p=[0,1,"13_0_0"]),f=!1),c&&!m&&(l.os="android",l.android=!0),(p||h||u)&&(l.os="ios",l.ios=!0),l}(e)),x}function T(){return y||(y=function(){const e=r();return{isSafari:function(){const t=e.navigator.userAgent.toLowerCase();return t.indexOf("safari")>=0&&t.indexOf("chrome")<0&&t.indexOf("android")<0}(),isWebView:/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(e.navigator.userAgent)}}()),y}Object.keys(c).forEach((e=>{Object.defineProperty(d.fn,e,{value:c[e],writable:!0})}));var $={on(e,t,s){const a=this;if(!a.eventsListeners||a.destroyed)return a;if("function"!=typeof t)return a;const i=s?"unshift":"push";return e.split(" ").forEach((e=>{a.eventsListeners[e]||(a.eventsListeners[e]=[]),a.eventsListeners[e][i](t)})),a},once(e,t,s){const a=this;if(!a.eventsListeners||a.destroyed)return a;if("function"!=typeof t)return a;function i(){a.off(e,i),i.__emitterProxy&&delete i.__emitterProxy;for(var s=arguments.length,r=new Array(s),n=0;n=0&&t.eventsAnyListeners.splice(s,1),t},off(e,t){const s=this;return!s.eventsListeners||s.destroyed?s:s.eventsListeners?(e.split(" ").forEach((e=>{void 0===t?s.eventsListeners[e]=[]:s.eventsListeners[e]&&s.eventsListeners[e].forEach(((a,i)=>{(a===t||a.__emitterProxy&&a.__emitterProxy===t)&&s.eventsListeners[e].splice(i,1)}))})),s):s},emit(){const e=this;if(!e.eventsListeners||e.destroyed)return e;if(!e.eventsListeners)return e;let t,s,a;for(var i=arguments.length,r=new Array(i),n=0;n{e.eventsAnyListeners&&e.eventsAnyListeners.length&&e.eventsAnyListeners.forEach((e=>{e.apply(a,[t,...s])})),e.eventsListeners&&e.eventsListeners[t]&&e.eventsListeners[t].forEach((e=>{e.apply(a,s)}))})),e}};var S={updateSize:function(){const e=this;let t,s;const a=e.$el;t=void 0!==e.params.width&&null!==e.params.width?e.params.width:a[0].clientWidth,s=void 0!==e.params.height&&null!==e.params.height?e.params.height:a[0].clientHeight,0===t&&e.isHorizontal()||0===s&&e.isVertical()||(t=t-parseInt(a.css("padding-left")||0,10)-parseInt(a.css("padding-right")||0,10),s=s-parseInt(a.css("padding-top")||0,10)-parseInt(a.css("padding-bottom")||0,10),Number.isNaN(t)&&(t=0),Number.isNaN(s)&&(s=0),Object.assign(e,{width:t,height:s,size:e.isHorizontal()?t:s}))},updateSlides:function(){const e=this;function t(t){return e.isHorizontal()?t:{width:"height","margin-top":"margin-left","margin-bottom ":"margin-right","margin-left":"margin-top","margin-right":"margin-bottom","padding-left":"padding-top","padding-right":"padding-bottom",marginRight:"marginBottom"}[t]}function s(e,s){return parseFloat(e.getPropertyValue(t(s))||0)}const a=e.params,{$wrapperEl:i,size:r,rtlTranslate:n,wrongRTL:l}=e,o=e.virtual&&a.virtual.enabled,d=o?e.virtual.slides.length:e.slides.length,c=i.children(`.${e.params.slideClass}`),p=o?e.virtual.slides.length:c.length;let u=[];const h=[],m=[];let f=a.slidesOffsetBefore;"function"==typeof f&&(f=a.slidesOffsetBefore.call(e));let g=a.slidesOffsetAfter;"function"==typeof g&&(g=a.slidesOffsetAfter.call(e));const w=e.snapGrid.length,b=e.slidesGrid.length;let x=a.spaceBetween,y=-f,E=0,C=0;if(void 0===r)return;"string"==typeof x&&x.indexOf("%")>=0&&(x=parseFloat(x.replace("%",""))/100*r),e.virtualSize=-x,n?c.css({marginLeft:"",marginBottom:"",marginTop:""}):c.css({marginRight:"",marginBottom:"",marginTop:""}),a.centeredSlides&&a.cssMode&&(v(e.wrapperEl,"--swiper-centered-offset-before",""),v(e.wrapperEl,"--swiper-centered-offset-after",""));const T=a.grid&&a.grid.rows>1&&e.grid;let $;T&&e.grid.initSlides(p);const S="auto"===a.slidesPerView&&a.breakpoints&&Object.keys(a.breakpoints).filter((e=>void 0!==a.breakpoints[e].slidesPerView)).length>0;for(let i=0;i1&&u.push(e.virtualSize-r)}if(0===u.length&&(u=[0]),0!==a.spaceBetween){const s=e.isHorizontal()&&n?"marginLeft":t("marginRight");c.filter(((e,t)=>!a.cssMode||t!==c.length-1)).css({[s]:`${x}px`})}if(a.centeredSlides&&a.centeredSlidesBounds){let e=0;m.forEach((t=>{e+=t+(a.spaceBetween?a.spaceBetween:0)})),e-=a.spaceBetween;const t=e-r;u=u.map((e=>e<0?-f:e>t?t+g:e))}if(a.centerInsufficientSlides){let e=0;if(m.forEach((t=>{e+=t+(a.spaceBetween?a.spaceBetween:0)})),e-=a.spaceBetween,e{u[s]=e-t})),h.forEach(((e,s)=>{h[s]=e+t}))}}if(Object.assign(e,{slides:c,snapGrid:u,slidesGrid:h,slidesSizesGrid:m}),a.centeredSlides&&a.cssMode&&!a.centeredSlidesBounds){v(e.wrapperEl,"--swiper-centered-offset-before",-u[0]+"px"),v(e.wrapperEl,"--swiper-centered-offset-after",e.size/2-m[m.length-1]/2+"px");const t=-e.snapGrid[0],s=-e.slidesGrid[0];e.snapGrid=e.snapGrid.map((e=>e+t)),e.slidesGrid=e.slidesGrid.map((e=>e+s))}if(p!==d&&e.emit("slidesLengthChange"),u.length!==w&&(e.params.watchOverflow&&e.checkOverflow(),e.emit("snapGridLengthChange")),h.length!==b&&e.emit("slidesGridLengthChange"),a.watchSlidesProgress&&e.updateSlidesOffset(),!(o||a.cssMode||"slide"!==a.effect&&"fade"!==a.effect)){const t=`${a.containerModifierClass}backface-hidden`,s=e.$el.hasClass(t);p<=a.maxBackfaceHiddenSlides?s||e.$el.addClass(t):s&&e.$el.removeClass(t)}},updateAutoHeight:function(e){const t=this,s=[],a=t.virtual&&t.params.virtual.enabled;let i,r=0;"number"==typeof e?t.setTransition(e):!0===e&&t.setTransition(t.params.speed);const n=e=>a?t.slides.filter((t=>parseInt(t.getAttribute("data-swiper-slide-index"),10)===e))[0]:t.slides.eq(e)[0];if("auto"!==t.params.slidesPerView&&t.params.slidesPerView>1)if(t.params.centeredSlides)(t.visibleSlides||d([])).each((e=>{s.push(e)}));else for(i=0;it.slides.length&&!a)break;s.push(n(e))}else s.push(n(t.activeIndex));for(i=0;ir?e:r}(r||0===r)&&t.$wrapperEl.css("height",`${r}px`)},updateSlidesOffset:function(){const e=this,t=e.slides;for(let s=0;s=0&&p1&&u<=t.size||p<=0&&u>=t.size)&&(t.visibleSlides.push(l),t.visibleSlidesIndexes.push(e),a.eq(e).addClass(s.slideVisibleClass)),l.progress=i?-d:d,l.originalProgress=i?-c:c}t.visibleSlides=d(t.visibleSlides)},updateProgress:function(e){const t=this;if(void 0===e){const s=t.rtlTranslate?-1:1;e=t&&t.translate&&t.translate*s||0}const s=t.params,a=t.maxTranslate()-t.minTranslate();let{progress:i,isBeginning:r,isEnd:n}=t;const l=r,o=n;0===a?(i=0,r=!0,n=!0):(i=(e-t.minTranslate())/a,r=i<=0,n=i>=1),Object.assign(t,{progress:i,isBeginning:r,isEnd:n}),(s.watchSlidesProgress||s.centeredSlides&&s.autoHeight)&&t.updateSlidesProgress(e),r&&!l&&t.emit("reachBeginning toEdge"),n&&!o&&t.emit("reachEnd toEdge"),(l&&!r||o&&!n)&&t.emit("fromEdge"),t.emit("progress",i)},updateSlidesClasses:function(){const e=this,{slides:t,params:s,$wrapperEl:a,activeIndex:i,realIndex:r}=e,n=e.virtual&&s.virtual.enabled;let l;t.removeClass(`${s.slideActiveClass} ${s.slideNextClass} ${s.slidePrevClass} ${s.slideDuplicateActiveClass} ${s.slideDuplicateNextClass} ${s.slideDuplicatePrevClass}`),l=n?e.$wrapperEl.find(`.${s.slideClass}[data-swiper-slide-index="${i}"]`):t.eq(i),l.addClass(s.slideActiveClass),s.loop&&(l.hasClass(s.slideDuplicateClass)?a.children(`.${s.slideClass}:not(.${s.slideDuplicateClass})[data-swiper-slide-index="${r}"]`).addClass(s.slideDuplicateActiveClass):a.children(`.${s.slideClass}.${s.slideDuplicateClass}[data-swiper-slide-index="${r}"]`).addClass(s.slideDuplicateActiveClass));let o=l.nextAll(`.${s.slideClass}`).eq(0).addClass(s.slideNextClass);s.loop&&0===o.length&&(o=t.eq(0),o.addClass(s.slideNextClass));let d=l.prevAll(`.${s.slideClass}`).eq(0).addClass(s.slidePrevClass);s.loop&&0===d.length&&(d=t.eq(-1),d.addClass(s.slidePrevClass)),s.loop&&(o.hasClass(s.slideDuplicateClass)?a.children(`.${s.slideClass}:not(.${s.slideDuplicateClass})[data-swiper-slide-index="${o.attr("data-swiper-slide-index")}"]`).addClass(s.slideDuplicateNextClass):a.children(`.${s.slideClass}.${s.slideDuplicateClass}[data-swiper-slide-index="${o.attr("data-swiper-slide-index")}"]`).addClass(s.slideDuplicateNextClass),d.hasClass(s.slideDuplicateClass)?a.children(`.${s.slideClass}:not(.${s.slideDuplicateClass})[data-swiper-slide-index="${d.attr("data-swiper-slide-index")}"]`).addClass(s.slideDuplicatePrevClass):a.children(`.${s.slideClass}.${s.slideDuplicateClass}[data-swiper-slide-index="${d.attr("data-swiper-slide-index")}"]`).addClass(s.slideDuplicatePrevClass)),e.emitSlidesClasses()},updateActiveIndex:function(e){const t=this,s=t.rtlTranslate?t.translate:-t.translate,{slidesGrid:a,snapGrid:i,params:r,activeIndex:n,realIndex:l,snapIndex:o}=t;let d,c=e;if(void 0===c){for(let e=0;e=a[e]&&s=a[e]&&s=a[e]&&(c=e);r.normalizeSlideIndex&&(c<0||void 0===c)&&(c=0)}if(i.indexOf(s)>=0)d=i.indexOf(s);else{const e=Math.min(r.slidesPerGroupSkip,c);d=e+Math.floor((c-e)/r.slidesPerGroup)}if(d>=i.length&&(d=i.length-1),c===n)return void(d!==o&&(t.snapIndex=d,t.emit("snapIndexChange")));const p=parseInt(t.slides.eq(c).attr("data-swiper-slide-index")||c,10);Object.assign(t,{snapIndex:d,realIndex:p,previousIndex:n,activeIndex:c}),t.emit("activeIndexChange"),t.emit("snapIndexChange"),l!==p&&t.emit("realIndexChange"),(t.initialized||t.params.runCallbacksOnInit)&&t.emit("slideChange")},updateClickedSlide:function(e){const t=this,s=t.params,a=d(e).closest(`.${s.slideClass}`)[0];let i,r=!1;if(a)for(let e=0;eo?o:a&&en?"next":r=o.length&&(g=o.length-1);const v=-o[g];if(l.normalizeSlideIndex)for(let e=0;e=s&&t=s&&t=s&&(n=e)}if(r.initialized&&n!==p){if(!r.allowSlideNext&&vr.translate&&v>r.maxTranslate()&&(p||0)!==n)return!1}let b;if(n!==(c||0)&&s&&r.emit("beforeSlideChangeStart"),r.updateProgress(v),b=n>p?"next":n{r.wrapperEl.style.scrollSnapType="",r._swiperImmediateVirtual=!1}))}else{if(!r.support.smoothScroll)return w({swiper:r,targetPosition:s,side:e?"left":"top"}),!0;h.scrollTo({[e?"left":"top"]:s,behavior:"smooth"})}return!0}return r.setTransition(t),r.setTranslate(v),r.updateActiveIndex(n),r.updateSlidesClasses(),r.emit("beforeTransitionStart",t,a),r.transitionStart(s,b),0===t?r.transitionEnd(s,b):r.animating||(r.animating=!0,r.onSlideToWrapperTransitionEnd||(r.onSlideToWrapperTransitionEnd=function(e){r&&!r.destroyed&&e.target===this&&(r.$wrapperEl[0].removeEventListener("transitionend",r.onSlideToWrapperTransitionEnd),r.$wrapperEl[0].removeEventListener("webkitTransitionEnd",r.onSlideToWrapperTransitionEnd),r.onSlideToWrapperTransitionEnd=null,delete r.onSlideToWrapperTransitionEnd,r.transitionEnd(s,b))}),r.$wrapperEl[0].addEventListener("transitionend",r.onSlideToWrapperTransitionEnd),r.$wrapperEl[0].addEventListener("webkitTransitionEnd",r.onSlideToWrapperTransitionEnd)),!0},slideToLoop:function(e,t,s,a){if(void 0===e&&(e=0),void 0===t&&(t=this.params.speed),void 0===s&&(s=!0),"string"==typeof e){const t=parseInt(e,10);if(!isFinite(t))throw new Error(`The passed-in 'index' (string) couldn't be converted to 'number'. [${e}] given.`);e=t}const i=this;let r=e;return i.params.loop&&(r+=i.loopedSlides),i.slideTo(r,t,s,a)},slideNext:function(e,t,s){void 0===e&&(e=this.params.speed),void 0===t&&(t=!0);const a=this,{animating:i,enabled:r,params:n}=a;if(!r)return a;let l=n.slidesPerGroup;"auto"===n.slidesPerView&&1===n.slidesPerGroup&&n.slidesPerGroupAuto&&(l=Math.max(a.slidesPerViewDynamic("current",!0),1));const o=a.activeIndexc(e)));let h=n[u.indexOf(p)-1];if(void 0===h&&i.cssMode){let e;n.forEach(((t,s)=>{p>=t&&(e=s)})),void 0!==e&&(h=n[e>0?e-1:e])}let m=0;if(void 0!==h&&(m=l.indexOf(h),m<0&&(m=a.activeIndex-1),"auto"===i.slidesPerView&&1===i.slidesPerGroup&&i.slidesPerGroupAuto&&(m=m-a.slidesPerViewDynamic("previous",!0)+1,m=Math.max(m,0))),i.rewind&&a.isBeginning){const i=a.params.virtual&&a.params.virtual.enabled&&a.virtual?a.virtual.slides.length-1:a.slides.length-1;return a.slideTo(i,e,t,s)}return a.slideTo(m,e,t,s)},slideReset:function(e,t,s){return void 0===e&&(e=this.params.speed),void 0===t&&(t=!0),this.slideTo(this.activeIndex,e,t,s)},slideToClosest:function(e,t,s,a){void 0===e&&(e=this.params.speed),void 0===t&&(t=!0),void 0===a&&(a=.5);const i=this;let r=i.activeIndex;const n=Math.min(i.params.slidesPerGroupSkip,r),l=n+Math.floor((r-n)/i.params.slidesPerGroup),o=i.rtlTranslate?i.translate:-i.translate;if(o>=i.snapGrid[l]){const e=i.snapGrid[l];o-e>(i.snapGrid[l+1]-e)*a&&(r+=i.params.slidesPerGroup)}else{const e=i.snapGrid[l-1];o-e<=(i.snapGrid[l]-e)*a&&(r-=i.params.slidesPerGroup)}return r=Math.max(r,0),r=Math.min(r,i.slidesGrid.length-1),i.slideTo(r,e,t,s)},slideToClickedSlide:function(){const e=this,{params:t,$wrapperEl:s}=e,a="auto"===t.slidesPerView?e.slidesPerViewDynamic():t.slidesPerView;let i,r=e.clickedIndex;if(t.loop){if(e.animating)return;i=parseInt(d(e.clickedSlide).attr("data-swiper-slide-index"),10),t.centeredSlides?re.slides.length-e.loopedSlides+a/2?(e.loopFix(),r=s.children(`.${t.slideClass}[data-swiper-slide-index="${i}"]:not(.${t.slideDuplicateClass})`).eq(0).index(),p((()=>{e.slideTo(r)}))):e.slideTo(r):r>e.slides.length-a?(e.loopFix(),r=s.children(`.${t.slideClass}[data-swiper-slide-index="${i}"]:not(.${t.slideDuplicateClass})`).eq(0).index(),p((()=>{e.slideTo(r)}))):e.slideTo(r)}else e.slideTo(r)}};var z={loopCreate:function(){const e=this,t=a(),{params:s,$wrapperEl:i}=e,r=i.children().length>0?d(i.children()[0].parentNode):i;r.children(`.${s.slideClass}.${s.slideDuplicateClass}`).remove();let n=r.children(`.${s.slideClass}`);if(s.loopFillGroupWithBlank){const e=s.slidesPerGroup-n.length%s.slidesPerGroup;if(e!==s.slidesPerGroup){for(let a=0;an.length&&e.params.loopedSlidesLimit&&(e.loopedSlides=n.length);const l=[],o=[];n.each(((e,t)=>{d(e).attr("data-swiper-slide-index",t)}));for(let t=0;t=0;e-=1)r.prepend(d(l[e].cloneNode(!0)).addClass(s.slideDuplicateClass))},loopFix:function(){const e=this;e.emit("beforeLoopFix");const{activeIndex:t,slides:s,loopedSlides:a,allowSlidePrev:i,allowSlideNext:r,snapGrid:n,rtlTranslate:l}=e;let o;e.allowSlidePrev=!0,e.allowSlideNext=!0;const d=-n[t]-e.getTranslate();if(t=s.length-a){o=-s.length+t+a,o+=a;e.slideTo(o,0,!1,!0)&&0!==d&&e.setTranslate((l?-e.translate:e.translate)-d)}e.allowSlidePrev=i,e.allowSlideNext=r,e.emit("loopFix")},loopDestroy:function(){const{$wrapperEl:e,params:t,slides:s}=this;e.children(`.${t.slideClass}.${t.slideDuplicateClass},.${t.slideClass}.${t.slideBlankClass}`).remove(),s.removeAttr("data-swiper-slide-index")}};function L(e){const t=this,s=a(),i=r(),n=t.touchEventsData,{params:l,touches:o,enabled:c}=t;if(!c)return;if(t.animating&&l.preventInteractionOnTransition)return;!t.animating&&l.cssMode&&l.loop&&t.loopFix();let p=e;p.originalEvent&&(p=p.originalEvent);let h=d(p.target);if("wrapper"===l.touchEventsTarget&&!h.closest(t.wrapperEl).length)return;if(n.isTouchEvent="touchstart"===p.type,!n.isTouchEvent&&"which"in p&&3===p.which)return;if(!n.isTouchEvent&&"button"in p&&p.button>0)return;if(n.isTouched&&n.isMoved)return;const m=!!l.noSwipingClass&&""!==l.noSwipingClass,f=e.composedPath?e.composedPath():e.path;m&&p.target&&p.target.shadowRoot&&f&&(h=d(f[0]));const g=l.noSwipingSelector?l.noSwipingSelector:`.${l.noSwipingClass}`,v=!(!p.target||!p.target.shadowRoot);if(l.noSwiping&&(v?function(e,t){return void 0===t&&(t=this),function t(s){if(!s||s===a()||s===r())return null;s.assignedSlot&&(s=s.assignedSlot);const i=s.closest(e);return i||s.getRootNode?i||t(s.getRootNode().host):null}(t)}(g,h[0]):h.closest(g)[0]))return void(t.allowClick=!0);if(l.swipeHandler&&!h.closest(l.swipeHandler)[0])return;o.currentX="touchstart"===p.type?p.targetTouches[0].pageX:p.pageX,o.currentY="touchstart"===p.type?p.targetTouches[0].pageY:p.pageY;const w=o.currentX,b=o.currentY,x=l.edgeSwipeDetection||l.iOSEdgeSwipeDetection,y=l.edgeSwipeThreshold||l.iOSEdgeSwipeThreshold;if(x&&(w<=y||w>=i.innerWidth-y)){if("prevent"!==x)return;e.preventDefault()}if(Object.assign(n,{isTouched:!0,isMoved:!1,allowTouchCallbacks:!0,isScrolling:void 0,startMoving:void 0}),o.startX=w,o.startY=b,n.touchStartTime=u(),t.allowClick=!0,t.updateSize(),t.swipeDirection=void 0,l.threshold>0&&(n.allowThresholdMove=!1),"touchstart"!==p.type){let e=!0;h.is(n.focusableElements)&&(e=!1,"SELECT"===h[0].nodeName&&(n.isTouched=!1)),s.activeElement&&d(s.activeElement).is(n.focusableElements)&&s.activeElement!==h[0]&&s.activeElement.blur();const a=e&&t.allowTouchMove&&l.touchStartPreventDefault;!l.touchStartForcePreventDefault&&!a||h[0].isContentEditable||p.preventDefault()}t.params.freeMode&&t.params.freeMode.enabled&&t.freeMode&&t.animating&&!l.cssMode&&t.freeMode.onTouchStart(),t.emit("touchStart",p)}function O(e){const t=a(),s=this,i=s.touchEventsData,{params:r,touches:n,rtlTranslate:l,enabled:o}=s;if(!o)return;let c=e;if(c.originalEvent&&(c=c.originalEvent),!i.isTouched)return void(i.startMoving&&i.isScrolling&&s.emit("touchMoveOpposite",c));if(i.isTouchEvent&&"touchmove"!==c.type)return;const p="touchmove"===c.type&&c.targetTouches&&(c.targetTouches[0]||c.changedTouches[0]),h="touchmove"===c.type?p.pageX:c.pageX,m="touchmove"===c.type?p.pageY:c.pageY;if(c.preventedByNestedSwiper)return n.startX=h,void(n.startY=m);if(!s.allowTouchMove)return d(c.target).is(i.focusableElements)||(s.allowClick=!1),void(i.isTouched&&(Object.assign(n,{startX:h,startY:m,currentX:h,currentY:m}),i.touchStartTime=u()));if(i.isTouchEvent&&r.touchReleaseOnEdges&&!r.loop)if(s.isVertical()){if(mn.startY&&s.translate>=s.minTranslate())return i.isTouched=!1,void(i.isMoved=!1)}else if(hn.startX&&s.translate>=s.minTranslate())return;if(i.isTouchEvent&&t.activeElement&&c.target===t.activeElement&&d(c.target).is(i.focusableElements))return i.isMoved=!0,void(s.allowClick=!1);if(i.allowTouchCallbacks&&s.emit("touchMove",c),c.targetTouches&&c.targetTouches.length>1)return;n.currentX=h,n.currentY=m;const f=n.currentX-n.startX,g=n.currentY-n.startY;if(s.params.threshold&&Math.sqrt(f**2+g**2)=25&&(e=180*Math.atan2(Math.abs(g),Math.abs(f))/Math.PI,i.isScrolling=s.isHorizontal()?e>r.touchAngle:90-e>r.touchAngle)}if(i.isScrolling&&s.emit("touchMoveOpposite",c),void 0===i.startMoving&&(n.currentX===n.startX&&n.currentY===n.startY||(i.startMoving=!0)),i.isScrolling)return void(i.isTouched=!1);if(!i.startMoving)return;s.allowClick=!1,!r.cssMode&&c.cancelable&&c.preventDefault(),r.touchMoveStopPropagation&&!r.nested&&c.stopPropagation(),i.isMoved||(r.loop&&!r.cssMode&&s.loopFix(),i.startTranslate=s.getTranslate(),s.setTransition(0),s.animating&&s.$wrapperEl.trigger("webkitTransitionEnd transitionend"),i.allowMomentumBounce=!1,!r.grabCursor||!0!==s.allowSlideNext&&!0!==s.allowSlidePrev||s.setGrabCursor(!0),s.emit("sliderFirstMove",c)),s.emit("sliderMove",c),i.isMoved=!0;let v=s.isHorizontal()?f:g;n.diff=v,v*=r.touchRatio,l&&(v=-v),s.swipeDirection=v>0?"prev":"next",i.currentTranslate=v+i.startTranslate;let w=!0,b=r.resistanceRatio;if(r.touchReleaseOnEdges&&(b=0),v>0&&i.currentTranslate>s.minTranslate()?(w=!1,r.resistance&&(i.currentTranslate=s.minTranslate()-1+(-s.minTranslate()+i.startTranslate+v)**b)):v<0&&i.currentTranslatei.startTranslate&&(i.currentTranslate=i.startTranslate),s.allowSlidePrev||s.allowSlideNext||(i.currentTranslate=i.startTranslate),r.threshold>0){if(!(Math.abs(v)>r.threshold||i.allowThresholdMove))return void(i.currentTranslate=i.startTranslate);if(!i.allowThresholdMove)return i.allowThresholdMove=!0,n.startX=n.currentX,n.startY=n.currentY,i.currentTranslate=i.startTranslate,void(n.diff=s.isHorizontal()?n.currentX-n.startX:n.currentY-n.startY)}r.followFinger&&!r.cssMode&&((r.freeMode&&r.freeMode.enabled&&s.freeMode||r.watchSlidesProgress)&&(s.updateActiveIndex(),s.updateSlidesClasses()),s.params.freeMode&&r.freeMode.enabled&&s.freeMode&&s.freeMode.onTouchMove(),s.updateProgress(i.currentTranslate),s.setTranslate(i.currentTranslate))}function I(e){const t=this,s=t.touchEventsData,{params:a,touches:i,rtlTranslate:r,slidesGrid:n,enabled:l}=t;if(!l)return;let o=e;if(o.originalEvent&&(o=o.originalEvent),s.allowTouchCallbacks&&t.emit("touchEnd",o),s.allowTouchCallbacks=!1,!s.isTouched)return s.isMoved&&a.grabCursor&&t.setGrabCursor(!1),s.isMoved=!1,void(s.startMoving=!1);a.grabCursor&&s.isMoved&&s.isTouched&&(!0===t.allowSlideNext||!0===t.allowSlidePrev)&&t.setGrabCursor(!1);const d=u(),c=d-s.touchStartTime;if(t.allowClick){const e=o.path||o.composedPath&&o.composedPath();t.updateClickedSlide(e&&e[0]||o.target),t.emit("tap click",o),c<300&&d-s.lastClickTime<300&&t.emit("doubleTap doubleClick",o)}if(s.lastClickTime=u(),p((()=>{t.destroyed||(t.allowClick=!0)})),!s.isTouched||!s.isMoved||!t.swipeDirection||0===i.diff||s.currentTranslate===s.startTranslate)return s.isTouched=!1,s.isMoved=!1,void(s.startMoving=!1);let h;if(s.isTouched=!1,s.isMoved=!1,s.startMoving=!1,h=a.followFinger?r?t.translate:-t.translate:-s.currentTranslate,a.cssMode)return;if(t.params.freeMode&&a.freeMode.enabled)return void t.freeMode.onTouchEnd({currentPos:h});let m=0,f=t.slidesSizesGrid[0];for(let e=0;e=n[e]&&h=n[e]&&(m=e,f=n[n.length-1]-n[n.length-2])}let g=null,v=null;a.rewind&&(t.isBeginning?v=t.params.virtual&&t.params.virtual.enabled&&t.virtual?t.virtual.slides.length-1:t.slides.length-1:t.isEnd&&(g=0));const w=(h-n[m])/f,b=ma.longSwipesMs){if(!a.longSwipes)return void t.slideTo(t.activeIndex);"next"===t.swipeDirection&&(w>=a.longSwipesRatio?t.slideTo(a.rewind&&t.isEnd?g:m+b):t.slideTo(m)),"prev"===t.swipeDirection&&(w>1-a.longSwipesRatio?t.slideTo(m+b):null!==v&&w<0&&Math.abs(w)>a.longSwipesRatio?t.slideTo(v):t.slideTo(m))}else{if(!a.shortSwipes)return void t.slideTo(t.activeIndex);t.navigation&&(o.target===t.navigation.nextEl||o.target===t.navigation.prevEl)?o.target===t.navigation.nextEl?t.slideTo(m+b):t.slideTo(m):("next"===t.swipeDirection&&t.slideTo(null!==g?g:m+b),"prev"===t.swipeDirection&&t.slideTo(null!==v?v:m))}}function A(){const e=this,{params:t,el:s}=e;if(s&&0===s.offsetWidth)return;t.breakpoints&&e.setBreakpoint();const{allowSlideNext:a,allowSlidePrev:i,snapGrid:r}=e;e.allowSlideNext=!0,e.allowSlidePrev=!0,e.updateSize(),e.updateSlides(),e.updateSlidesClasses(),("auto"===t.slidesPerView||t.slidesPerView>1)&&e.isEnd&&!e.isBeginning&&!e.params.centeredSlides?e.slideTo(e.slides.length-1,0,!1,!0):e.slideTo(e.activeIndex,0,!1,!0),e.autoplay&&e.autoplay.running&&e.autoplay.paused&&e.autoplay.run(),e.allowSlidePrev=i,e.allowSlideNext=a,e.params.watchOverflow&&r!==e.snapGrid&&e.checkOverflow()}function D(e){const t=this;t.enabled&&(t.allowClick||(t.params.preventClicks&&e.preventDefault(),t.params.preventClicksPropagation&&t.animating&&(e.stopPropagation(),e.stopImmediatePropagation())))}function G(){const e=this,{wrapperEl:t,rtlTranslate:s,enabled:a}=e;if(!a)return;let i;e.previousTranslate=e.translate,e.isHorizontal()?e.translate=-t.scrollLeft:e.translate=-t.scrollTop,0===e.translate&&(e.translate=0),e.updateActiveIndex(),e.updateSlidesClasses();const r=e.maxTranslate()-e.minTranslate();i=0===r?0:(e.translate-e.minTranslate())/r,i!==e.progress&&e.updateProgress(s?-e.translate:e.translate),e.emit("setTranslate",e.translate,!1)}let N=!1;function B(){}const H=(e,t)=>{const s=a(),{params:i,touchEvents:r,el:n,wrapperEl:l,device:o,support:d}=e,c=!!i.nested,p="on"===t?"addEventListener":"removeEventListener",u=t;if(d.touch){const t=!("touchstart"!==r.start||!d.passiveListener||!i.passiveListeners)&&{passive:!0,capture:!1};n[p](r.start,e.onTouchStart,t),n[p](r.move,e.onTouchMove,d.passiveListener?{passive:!1,capture:c}:c),n[p](r.end,e.onTouchEnd,t),r.cancel&&n[p](r.cancel,e.onTouchEnd,t)}else n[p](r.start,e.onTouchStart,!1),s[p](r.move,e.onTouchMove,c),s[p](r.end,e.onTouchEnd,!1);(i.preventClicks||i.preventClicksPropagation)&&n[p]("click",e.onClick,!0),i.cssMode&&l[p]("scroll",e.onScroll),i.updateOnWindowResize?e[u](o.ios||o.android?"resize orientationchange observerUpdate":"resize observerUpdate",A,!0):e[u]("observerUpdate",A,!0)};var X={attachEvents:function(){const e=this,t=a(),{params:s,support:i}=e;e.onTouchStart=L.bind(e),e.onTouchMove=O.bind(e),e.onTouchEnd=I.bind(e),s.cssMode&&(e.onScroll=G.bind(e)),e.onClick=D.bind(e),i.touch&&!N&&(t.addEventListener("touchstart",B),N=!0),H(e,"on")},detachEvents:function(){H(this,"off")}};const Y=(e,t)=>e.grid&&t.grid&&t.grid.rows>1;var R={addClasses:function(){const e=this,{classNames:t,params:s,rtl:a,$el:i,device:r,support:n}=e,l=function(e,t){const s=[];return e.forEach((e=>{"object"==typeof e?Object.keys(e).forEach((a=>{e[a]&&s.push(t+a)})):"string"==typeof e&&s.push(t+e)})),s}(["initialized",s.direction,{"pointer-events":!n.touch},{"free-mode":e.params.freeMode&&s.freeMode.enabled},{autoheight:s.autoHeight},{rtl:a},{grid:s.grid&&s.grid.rows>1},{"grid-column":s.grid&&s.grid.rows>1&&"column"===s.grid.fill},{android:r.android},{ios:r.ios},{"css-mode":s.cssMode},{centered:s.cssMode&&s.centeredSlides},{"watch-progress":s.watchSlidesProgress}],s.containerModifierClass);t.push(...l),i.addClass([...t].join(" ")),e.emitContainerClasses()},removeClasses:function(){const{$el:e,classNames:t}=this;e.removeClass(t.join(" ")),this.emitContainerClasses()}};var W={init:!0,direction:"horizontal",touchEventsTarget:"wrapper",initialSlide:0,speed:300,cssMode:!1,updateOnWindowResize:!0,resizeObserver:!0,nested:!1,createElements:!1,enabled:!0,focusableElements:"input, select, option, textarea, button, video, label",width:null,height:null,preventInteractionOnTransition:!1,userAgent:null,url:null,edgeSwipeDetection:!1,edgeSwipeThreshold:20,autoHeight:!1,setWrapperSize:!1,virtualTranslate:!1,effect:"slide",breakpoints:void 0,breakpointsBase:"window",spaceBetween:0,slidesPerView:1,slidesPerGroup:1,slidesPerGroupSkip:0,slidesPerGroupAuto:!1,centeredSlides:!1,centeredSlidesBounds:!1,slidesOffsetBefore:0,slidesOffsetAfter:0,normalizeSlideIndex:!0,centerInsufficientSlides:!1,watchOverflow:!0,roundLengths:!1,touchRatio:1,touchAngle:45,simulateTouch:!0,shortSwipes:!0,longSwipes:!0,longSwipesRatio:.5,longSwipesMs:300,followFinger:!0,allowTouchMove:!0,threshold:0,touchMoveStopPropagation:!1,touchStartPreventDefault:!0,touchStartForcePreventDefault:!1,touchReleaseOnEdges:!1,uniqueNavElements:!0,resistance:!0,resistanceRatio:.85,watchSlidesProgress:!1,grabCursor:!1,preventClicks:!0,preventClicksPropagation:!0,slideToClickedSlide:!1,preloadImages:!0,updateOnImagesReady:!0,loop:!1,loopAdditionalSlides:0,loopedSlides:null,loopedSlidesLimit:!0,loopFillGroupWithBlank:!1,loopPreventsSlide:!0,rewind:!1,allowSlidePrev:!0,allowSlideNext:!0,swipeHandler:null,noSwiping:!0,noSwipingClass:"swiper-no-swiping",noSwipingSelector:null,passiveListeners:!0,maxBackfaceHiddenSlides:10,containerModifierClass:"swiper-",slideClass:"swiper-slide",slideBlankClass:"swiper-slide-invisible-blank",slideActiveClass:"swiper-slide-active",slideDuplicateActiveClass:"swiper-slide-duplicate-active",slideVisibleClass:"swiper-slide-visible",slideDuplicateClass:"swiper-slide-duplicate",slideNextClass:"swiper-slide-next",slideDuplicateNextClass:"swiper-slide-duplicate-next",slidePrevClass:"swiper-slide-prev",slideDuplicatePrevClass:"swiper-slide-duplicate-prev",wrapperClass:"swiper-wrapper",runCallbacksOnInit:!0,_emitClasses:!1};function q(e,t){return function(s){void 0===s&&(s={});const a=Object.keys(s)[0],i=s[a];"object"==typeof i&&null!==i?(["navigation","pagination","scrollbar"].indexOf(a)>=0&&!0===e[a]&&(e[a]={auto:!0}),a in e&&"enabled"in i?(!0===e[a]&&(e[a]={enabled:!0}),"object"!=typeof e[a]||"enabled"in e[a]||(e[a].enabled=!0),e[a]||(e[a]={enabled:!1}),g(t,s)):g(t,s)):g(t,s)}}const j={eventsEmitter:$,update:S,translate:M,transition:{setTransition:function(e,t){const s=this;s.params.cssMode||s.$wrapperEl.transition(e),s.emit("setTransition",e,t)},transitionStart:function(e,t){void 0===e&&(e=!0);const s=this,{params:a}=s;a.cssMode||(a.autoHeight&&s.updateAutoHeight(),P({swiper:s,runCallbacks:e,direction:t,step:"Start"}))},transitionEnd:function(e,t){void 0===e&&(e=!0);const s=this,{params:a}=s;s.animating=!1,a.cssMode||(s.setTransition(0),P({swiper:s,runCallbacks:e,direction:t,step:"End"}))}},slide:k,loop:z,grabCursor:{setGrabCursor:function(e){const t=this;if(t.support.touch||!t.params.simulateTouch||t.params.watchOverflow&&t.isLocked||t.params.cssMode)return;const s="container"===t.params.touchEventsTarget?t.el:t.wrapperEl;s.style.cursor="move",s.style.cursor=e?"grabbing":"grab"},unsetGrabCursor:function(){const e=this;e.support.touch||e.params.watchOverflow&&e.isLocked||e.params.cssMode||(e["container"===e.params.touchEventsTarget?"el":"wrapperEl"].style.cursor="")}},events:X,breakpoints:{setBreakpoint:function(){const e=this,{activeIndex:t,initialized:s,loopedSlides:a=0,params:i,$el:r}=e,n=i.breakpoints;if(!n||n&&0===Object.keys(n).length)return;const l=e.getBreakpoint(n,e.params.breakpointsBase,e.el);if(!l||e.currentBreakpoint===l)return;const o=(l in n?n[l]:void 0)||e.originalParams,d=Y(e,i),c=Y(e,o),p=i.enabled;d&&!c?(r.removeClass(`${i.containerModifierClass}grid ${i.containerModifierClass}grid-column`),e.emitContainerClasses()):!d&&c&&(r.addClass(`${i.containerModifierClass}grid`),(o.grid.fill&&"column"===o.grid.fill||!o.grid.fill&&"column"===i.grid.fill)&&r.addClass(`${i.containerModifierClass}grid-column`),e.emitContainerClasses()),["navigation","pagination","scrollbar"].forEach((t=>{const s=i[t]&&i[t].enabled,a=o[t]&&o[t].enabled;s&&!a&&e[t].disable(),!s&&a&&e[t].enable()}));const u=o.direction&&o.direction!==i.direction,h=i.loop&&(o.slidesPerView!==i.slidesPerView||u);u&&s&&e.changeDirection(),g(e.params,o);const m=e.params.enabled;Object.assign(e,{allowTouchMove:e.params.allowTouchMove,allowSlideNext:e.params.allowSlideNext,allowSlidePrev:e.params.allowSlidePrev}),p&&!m?e.disable():!p&&m&&e.enable(),e.currentBreakpoint=l,e.emit("_beforeBreakpoint",o),h&&s&&(e.loopDestroy(),e.loopCreate(),e.updateSlides(),e.slideTo(t-a+e.loopedSlides,0,!1)),e.emit("breakpoint",o)},getBreakpoint:function(e,t,s){if(void 0===t&&(t="window"),!e||"container"===t&&!s)return;let a=!1;const i=r(),n="window"===t?i.innerHeight:s.clientHeight,l=Object.keys(e).map((e=>{if("string"==typeof e&&0===e.indexOf("@")){const t=parseFloat(e.substr(1));return{value:n*t,point:e}}return{value:e,point:e}}));l.sort(((e,t)=>parseInt(e.value,10)-parseInt(t.value,10)));for(let e=0;es}else e.isLocked=1===e.snapGrid.length;!0===s.allowSlideNext&&(e.allowSlideNext=!e.isLocked),!0===s.allowSlidePrev&&(e.allowSlidePrev=!e.isLocked),t&&t!==e.isLocked&&(e.isEnd=!1),t!==e.isLocked&&e.emit(e.isLocked?"lock":"unlock")}},classes:R,images:{loadImage:function(e,t,s,a,i,n){const l=r();let o;function c(){n&&n()}d(e).parent("picture")[0]||e.complete&&i?c():t?(o=new l.Image,o.onload=c,o.onerror=c,a&&(o.sizes=a),s&&(o.srcset=s),t&&(o.src=t)):c()},preloadImages:function(){const e=this;function t(){null!=e&&e&&!e.destroyed&&(void 0!==e.imagesLoaded&&(e.imagesLoaded+=1),e.imagesLoaded===e.imagesToLoad.length&&(e.params.updateOnImagesReady&&e.update(),e.emit("imagesReady")))}e.imagesToLoad=e.$el.find("img");for(let s=0;s1){const e=[];return d(t.el).each((s=>{const a=g({},t,{el:s});e.push(new V(a))})),e}const r=this;r.__swiper__=!0,r.support=E(),r.device=C({userAgent:t.userAgent}),r.browser=T(),r.eventsListeners={},r.eventsAnyListeners=[],r.modules=[...r.__modules__],t.modules&&Array.isArray(t.modules)&&r.modules.push(...t.modules);const n={};r.modules.forEach((e=>{e({swiper:r,extendParams:q(t,n),on:r.on.bind(r),once:r.once.bind(r),off:r.off.bind(r),emit:r.emit.bind(r)})}));const l=g({},W,n);return r.params=g({},l,_,t),r.originalParams=g({},r.params),r.passedParams=g({},t),r.params&&r.params.on&&Object.keys(r.params.on).forEach((e=>{r.on(e,r.params.on[e])})),r.params&&r.params.onAny&&r.onAny(r.params.onAny),r.$=d,Object.assign(r,{enabled:r.params.enabled,el:e,classNames:[],slides:d(),slidesGrid:[],snapGrid:[],slidesSizesGrid:[],isHorizontal:()=>"horizontal"===r.params.direction,isVertical:()=>"vertical"===r.params.direction,activeIndex:0,realIndex:0,isBeginning:!0,isEnd:!1,translate:0,previousTranslate:0,progress:0,velocity:0,animating:!1,allowSlideNext:r.params.allowSlideNext,allowSlidePrev:r.params.allowSlidePrev,touchEvents:function(){const e=["touchstart","touchmove","touchend","touchcancel"],t=["pointerdown","pointermove","pointerup"];return r.touchEventsTouch={start:e[0],move:e[1],end:e[2],cancel:e[3]},r.touchEventsDesktop={start:t[0],move:t[1],end:t[2]},r.support.touch||!r.params.simulateTouch?r.touchEventsTouch:r.touchEventsDesktop}(),touchEventsData:{isTouched:void 0,isMoved:void 0,allowTouchCallbacks:void 0,touchStartTime:void 0,isScrolling:void 0,currentTranslate:void 0,startTranslate:void 0,allowThresholdMove:void 0,focusableElements:r.params.focusableElements,lastClickTime:u(),clickTimeout:void 0,velocities:[],allowMomentumBounce:void 0,isTouchEvent:void 0,startMoving:void 0},allowClick:!0,allowTouchMove:r.params.allowTouchMove,touches:{startX:0,startY:0,currentX:0,currentY:0,diff:0},imagesToLoad:[],imagesLoaded:0}),r.emit("_swiper"),r.params.init&&r.init(),r}enable(){const e=this;e.enabled||(e.enabled=!0,e.params.grabCursor&&e.setGrabCursor(),e.emit("enable"))}disable(){const e=this;e.enabled&&(e.enabled=!1,e.params.grabCursor&&e.unsetGrabCursor(),e.emit("disable"))}setProgress(e,t){const s=this;e=Math.min(Math.max(e,0),1);const a=s.minTranslate(),i=(s.maxTranslate()-a)*e+a;s.translateTo(i,void 0===t?0:t),s.updateActiveIndex(),s.updateSlidesClasses()}emitContainerClasses(){const e=this;if(!e.params._emitClasses||!e.el)return;const t=e.el.className.split(" ").filter((t=>0===t.indexOf("swiper")||0===t.indexOf(e.params.containerModifierClass)));e.emit("_containerClasses",t.join(" "))}getSlideClasses(e){const t=this;return t.destroyed?"":e.className.split(" ").filter((e=>0===e.indexOf("swiper-slide")||0===e.indexOf(t.params.slideClass))).join(" ")}emitSlidesClasses(){const e=this;if(!e.params._emitClasses||!e.el)return;const t=[];e.slides.each((s=>{const a=e.getSlideClasses(s);t.push({slideEl:s,classNames:a}),e.emit("_slideClass",s,a)})),e.emit("_slideClasses",t)}slidesPerViewDynamic(e,t){void 0===e&&(e="current"),void 0===t&&(t=!1);const{params:s,slides:a,slidesGrid:i,slidesSizesGrid:r,size:n,activeIndex:l}=this;let o=1;if(s.centeredSlides){let e,t=a[l].swiperSlideSize;for(let s=l+1;sn&&(e=!0));for(let s=l-1;s>=0;s-=1)a[s]&&!e&&(t+=a[s].swiperSlideSize,o+=1,t>n&&(e=!0))}else if("current"===e)for(let e=l+1;e=0;e-=1){i[l]-i[e]1)&&e.isEnd&&!e.params.centeredSlides?e.slideTo(e.slides.length-1,0,!1,!0):e.slideTo(e.activeIndex,0,!1,!0),i||a()),s.watchOverflow&&t!==e.snapGrid&&e.checkOverflow(),e.emit("update")}changeDirection(e,t){void 0===t&&(t=!0);const s=this,a=s.params.direction;return e||(e="horizontal"===a?"vertical":"horizontal"),e===a||"horizontal"!==e&&"vertical"!==e||(s.$el.removeClass(`${s.params.containerModifierClass}${a}`).addClass(`${s.params.containerModifierClass}${e}`),s.emitContainerClasses(),s.params.direction=e,s.slides.each((t=>{"vertical"===e?t.style.width="":t.style.height=""})),s.emit("changeDirection"),t&&s.update()),s}changeLanguageDirection(e){const t=this;t.rtl&&"rtl"===e||!t.rtl&&"ltr"===e||(t.rtl="rtl"===e,t.rtlTranslate="horizontal"===t.params.direction&&t.rtl,t.rtl?(t.$el.addClass(`${t.params.containerModifierClass}rtl`),t.el.dir="rtl"):(t.$el.removeClass(`${t.params.containerModifierClass}rtl`),t.el.dir="ltr"),t.update())}mount(e){const t=this;if(t.mounted)return!0;const s=d(e||t.params.el);if(!(e=s[0]))return!1;e.swiper=t;const i=()=>`.${(t.params.wrapperClass||"").trim().split(" ").join(".")}`;let r=(()=>{if(e&&e.shadowRoot&&e.shadowRoot.querySelector){const t=d(e.shadowRoot.querySelector(i()));return t.children=e=>s.children(e),t}return s.children?s.children(i()):d(s).children(i())})();if(0===r.length&&t.params.createElements){const e=a().createElement("div");r=d(e),e.className=t.params.wrapperClass,s.append(e),s.children(`.${t.params.slideClass}`).each((e=>{r.append(e)}))}return Object.assign(t,{$el:s,el:e,$wrapperEl:r,wrapperEl:r[0],mounted:!0,rtl:"rtl"===e.dir.toLowerCase()||"rtl"===s.css("direction"),rtlTranslate:"horizontal"===t.params.direction&&("rtl"===e.dir.toLowerCase()||"rtl"===s.css("direction")),wrongRTL:"-webkit-box"===r.css("display")}),!0}init(e){const t=this;if(t.initialized)return t;return!1===t.mount(e)||(t.emit("beforeInit"),t.params.breakpoints&&t.setBreakpoint(),t.addClasses(),t.params.loop&&t.loopCreate(),t.updateSize(),t.updateSlides(),t.params.watchOverflow&&t.checkOverflow(),t.params.grabCursor&&t.enabled&&t.setGrabCursor(),t.params.preloadImages&&t.preloadImages(),t.params.loop?t.slideTo(t.params.initialSlide+t.loopedSlides,0,t.params.runCallbacksOnInit,!1,!0):t.slideTo(t.params.initialSlide,0,t.params.runCallbacksOnInit,!1,!0),t.attachEvents(),t.initialized=!0,t.emit("init"),t.emit("afterInit")),t}destroy(e,t){void 0===e&&(e=!0),void 0===t&&(t=!0);const s=this,{params:a,$el:i,$wrapperEl:r,slides:n}=s;return void 0===s.params||s.destroyed||(s.emit("beforeDestroy"),s.initialized=!1,s.detachEvents(),a.loop&&s.loopDestroy(),t&&(s.removeClasses(),i.removeAttr("style"),r.removeAttr("style"),n&&n.length&&n.removeClass([a.slideVisibleClass,a.slideActiveClass,a.slideNextClass,a.slidePrevClass].join(" ")).removeAttr("style").removeAttr("data-swiper-slide-index")),s.emit("destroy"),Object.keys(s.eventsListeners).forEach((e=>{s.off(e)})),!1!==e&&(s.$el[0].swiper=null,function(e){const t=e;Object.keys(t).forEach((e=>{try{t[e]=null}catch(e){}try{delete t[e]}catch(e){}}))}(s)),s.destroyed=!0),null}static extendDefaults(e){g(_,e)}static get extendedDefaults(){return _}static get defaults(){return W}static installModule(e){V.prototype.__modules__||(V.prototype.__modules__=[]);const t=V.prototype.__modules__;"function"==typeof e&&t.indexOf(e)<0&&t.push(e)}static use(e){return Array.isArray(e)?(e.forEach((e=>V.installModule(e))),V):(V.installModule(e),V)}}function F(e,t,s,i){const r=a();return e.params.createElements&&Object.keys(i).forEach((a=>{if(!s[a]&&!0===s.auto){let n=e.$el.children(`.${i[a]}`)[0];n||(n=r.createElement("div"),n.className=i[a],e.$el.append(n)),s[a]=n,t[a]=n}})),s}function U(e){return void 0===e&&(e=""),`.${e.trim().replace(/([\.:!\/])/g,"\\$1").replace(/ /g,".")}`}function K(e){const t=this,{$wrapperEl:s,params:a}=t;if(a.loop&&t.loopDestroy(),"object"==typeof e&&"length"in e)for(let t=0;t=l)return void s.appendSlide(t);let o=n>e?n+1:n;const d=[];for(let t=l-1;t>=e;t-=1){const e=s.slides.eq(t);e.remove(),d.unshift(e)}if("object"==typeof t&&"length"in t){for(let e=0;ee?n+t.length:n}else a.append(t);for(let e=0;e{if(s.params.effect!==t)return;s.classNames.push(`${s.params.containerModifierClass}${t}`),l&&l()&&s.classNames.push(`${s.params.containerModifierClass}3d`);const e=n?n():{};Object.assign(s.params,e),Object.assign(s.originalParams,e)})),a("setTranslate",(()=>{s.params.effect===t&&i()})),a("setTransition",((e,a)=>{s.params.effect===t&&r(a)})),a("transitionEnd",(()=>{if(s.params.effect===t&&o){if(!d||!d().slideShadows)return;s.slides.each((e=>{s.$(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").remove()})),o()}})),a("virtualUpdate",(()=>{s.params.effect===t&&(s.slides.length||(c=!0),requestAnimationFrame((()=>{c&&s.slides&&s.slides.length&&(i(),c=!1)})))}))}function se(e,t){return e.transformEl?t.find(e.transformEl).css({"backface-visibility":"hidden","-webkit-backface-visibility":"hidden"}):t}function ae(e){let{swiper:t,duration:s,transformEl:a,allSlides:i}=e;const{slides:r,activeIndex:n,$wrapperEl:l}=t;if(t.params.virtualTranslate&&0!==s){let e,s=!1;e=i?a?r.find(a):r:a?r.eq(n).find(a):r.eq(n),e.transitionEnd((()=>{if(s)return;if(!t||t.destroyed)return;s=!0,t.animating=!1;const e=["webkitTransitionEnd","transitionend"];for(let t=0;t`),i.append(r)),r}Object.keys(j).forEach((e=>{Object.keys(j[e]).forEach((t=>{V.prototype[t]=j[e][t]}))})),V.use([function(e){let{swiper:t,on:s,emit:a}=e;const i=r();let n=null,l=null;const o=()=>{t&&!t.destroyed&&t.initialized&&(a("beforeResize"),a("resize"))},d=()=>{t&&!t.destroyed&&t.initialized&&a("orientationchange")};s("init",(()=>{t.params.resizeObserver&&void 0!==i.ResizeObserver?t&&!t.destroyed&&t.initialized&&(n=new ResizeObserver((e=>{l=i.requestAnimationFrame((()=>{const{width:s,height:a}=t;let i=s,r=a;e.forEach((e=>{let{contentBoxSize:s,contentRect:a,target:n}=e;n&&n!==t.el||(i=a?a.width:(s[0]||s).inlineSize,r=a?a.height:(s[0]||s).blockSize)})),i===s&&r===a||o()}))})),n.observe(t.el)):(i.addEventListener("resize",o),i.addEventListener("orientationchange",d))})),s("destroy",(()=>{l&&i.cancelAnimationFrame(l),n&&n.unobserve&&t.el&&(n.unobserve(t.el),n=null),i.removeEventListener("resize",o),i.removeEventListener("orientationchange",d)}))},function(e){let{swiper:t,extendParams:s,on:a,emit:i}=e;const n=[],l=r(),o=function(e,t){void 0===t&&(t={});const s=new(l.MutationObserver||l.WebkitMutationObserver)((e=>{if(1===e.length)return void i("observerUpdate",e[0]);const t=function(){i("observerUpdate",e[0])};l.requestAnimationFrame?l.requestAnimationFrame(t):l.setTimeout(t,0)}));s.observe(e,{attributes:void 0===t.attributes||t.attributes,childList:void 0===t.childList||t.childList,characterData:void 0===t.characterData||t.characterData}),n.push(s)};s({observer:!1,observeParents:!1,observeSlideChildren:!1}),a("init",(()=>{if(t.params.observer){if(t.params.observeParents){const e=t.$el.parents();for(let t=0;t{n.forEach((e=>{e.disconnect()})),n.splice(0,n.length)}))}]);const re=[function(e){let t,{swiper:s,extendParams:a,on:i,emit:r}=e;function n(e,t){const a=s.params.virtual;if(a.cache&&s.virtual.cache[t])return s.virtual.cache[t];const i=a.renderSlide?d(a.renderSlide.call(s,e,t)):d(`
${e}
`);return i.attr("data-swiper-slide-index")||i.attr("data-swiper-slide-index",t),a.cache&&(s.virtual.cache[t]=i),i}function l(e){const{slidesPerView:t,slidesPerGroup:a,centeredSlides:i}=s.params,{addSlidesBefore:l,addSlidesAfter:o}=s.params.virtual,{from:d,to:c,slides:p,slidesGrid:u,offset:h}=s.virtual;s.params.cssMode||s.updateActiveIndex();const m=s.activeIndex||0;let f,g,v;f=s.rtlTranslate?"right":s.isHorizontal()?"left":"top",i?(g=Math.floor(t/2)+a+o,v=Math.floor(t/2)+a+l):(g=t+(a-1)+o,v=a+l);const w=Math.max((m||0)-v,0),b=Math.min((m||0)+g,p.length-1),x=(s.slidesGrid[w]||0)-(s.slidesGrid[0]||0);function y(){s.updateSlides(),s.updateProgress(),s.updateSlidesClasses(),s.lazy&&s.params.lazy.enabled&&s.lazy.load(),r("virtualUpdate")}if(Object.assign(s.virtual,{from:w,to:b,offset:x,slidesGrid:s.slidesGrid}),d===w&&c===b&&!e)return s.slidesGrid!==u&&x!==h&&s.slides.css(f,`${x}px`),s.updateProgress(),void r("virtualUpdate");if(s.params.virtual.renderExternal)return s.params.virtual.renderExternal.call(s,{offset:x,from:w,to:b,slides:function(){const e=[];for(let t=w;t<=b;t+=1)e.push(p[t]);return e}()}),void(s.params.virtual.renderExternalUpdate?y():r("virtualUpdate"));const E=[],C=[];if(e)s.$wrapperEl.find(`.${s.params.slideClass}`).remove();else for(let e=d;e<=c;e+=1)(eb)&&s.$wrapperEl.find(`.${s.params.slideClass}[data-swiper-slide-index="${e}"]`).remove();for(let t=0;t=w&&t<=b&&(void 0===c||e?C.push(t):(t>c&&C.push(t),t{s.$wrapperEl.append(n(p[e],e))})),E.sort(((e,t)=>t-e)).forEach((e=>{s.$wrapperEl.prepend(n(p[e],e))})),s.$wrapperEl.children(".swiper-slide").css(f,`${x}px`),y()}a({virtual:{enabled:!1,slides:[],cache:!0,renderSlide:null,renderExternal:null,renderExternalUpdate:!0,addSlidesBefore:0,addSlidesAfter:0}}),s.virtual={cache:{},from:void 0,to:void 0,slides:[],offset:0,slidesGrid:[]},i("beforeInit",(()=>{s.params.virtual.enabled&&(s.virtual.slides=s.params.virtual.slides,s.classNames.push(`${s.params.containerModifierClass}virtual`),s.params.watchSlidesProgress=!0,s.originalParams.watchSlidesProgress=!0,s.params.initialSlide||l())})),i("setTranslate",(()=>{s.params.virtual.enabled&&(s.params.cssMode&&!s._immediateVirtual?(clearTimeout(t),t=setTimeout((()=>{l()}),100)):l())})),i("init update resize",(()=>{s.params.virtual.enabled&&s.params.cssMode&&v(s.wrapperEl,"--swiper-virtual-size",`${s.virtualSize}px`)})),Object.assign(s.virtual,{appendSlide:function(e){if("object"==typeof e&&"length"in e)for(let t=0;t{const a=e[s],r=a.attr("data-swiper-slide-index");r&&a.attr("data-swiper-slide-index",parseInt(r,10)+i),t[parseInt(s,10)+i]=a})),s.virtual.cache=t}l(!0),s.slideTo(a,0)},removeSlide:function(e){if(null==e)return;let t=s.activeIndex;if(Array.isArray(e))for(let a=e.length-1;a>=0;a-=1)s.virtual.slides.splice(e[a],1),s.params.virtual.cache&&delete s.virtual.cache[e[a]],e[a]0&&0===t.$el.parents(`.${t.params.slideActiveClass}`).length)return;const a=t.$el,i=a[0].clientWidth,r=a[0].clientHeight,n=o.innerWidth,l=o.innerHeight,d=t.$el.offset();s&&(d.left-=t.$el[0].scrollLeft);const c=[[d.left,d.top],[d.left+i,d.top],[d.left,d.top+r],[d.left+i,d.top+r]];for(let t=0;t=0&&s[0]<=n&&s[1]>=0&&s[1]<=l){if(0===s[0]&&0===s[1])continue;e=!0}}if(!e)return}t.isHorizontal()?((d||c||p||u)&&(a.preventDefault?a.preventDefault():a.returnValue=!1),((c||u)&&!s||(d||p)&&s)&&t.slideNext(),((d||p)&&!s||(c||u)&&s)&&t.slidePrev()):((d||c||h||m)&&(a.preventDefault?a.preventDefault():a.returnValue=!1),(c||m)&&t.slideNext(),(d||h)&&t.slidePrev()),n("keyPress",i)}}function p(){t.keyboard.enabled||(d(l).on("keydown",c),t.keyboard.enabled=!0)}function u(){t.keyboard.enabled&&(d(l).off("keydown",c),t.keyboard.enabled=!1)}t.keyboard={enabled:!1},s({keyboard:{enabled:!1,onlyInViewport:!0,pageUpDown:!0}}),i("init",(()=>{t.params.keyboard.enabled&&p()})),i("destroy",(()=>{t.keyboard.enabled&&u()})),Object.assign(t.keyboard,{enable:p,disable:u})},function(e){let{swiper:t,extendParams:s,on:a,emit:i}=e;const n=r();let l;s({mousewheel:{enabled:!1,releaseOnEdges:!1,invert:!1,forceToAxis:!1,sensitivity:1,eventsTarget:"container",thresholdDelta:null,thresholdTime:null}}),t.mousewheel={enabled:!1};let o,c=u();const h=[];function m(){t.enabled&&(t.mouseEntered=!0)}function f(){t.enabled&&(t.mouseEntered=!1)}function g(e){return!(t.params.mousewheel.thresholdDelta&&e.delta=6&&u()-c<60||(e.direction<0?t.isEnd&&!t.params.loop||t.animating||(t.slideNext(),i("scroll",e.raw)):t.isBeginning&&!t.params.loop||t.animating||(t.slidePrev(),i("scroll",e.raw)),c=(new n.Date).getTime(),!1)))}function v(e){let s=e,a=!0;if(!t.enabled)return;const r=t.params.mousewheel;t.params.cssMode&&s.preventDefault();let n=t.$el;if("container"!==t.params.mousewheel.eventsTarget&&(n=d(t.params.mousewheel.eventsTarget)),!t.mouseEntered&&!n[0].contains(s.target)&&!r.releaseOnEdges)return!0;s.originalEvent&&(s=s.originalEvent);let c=0;const m=t.rtlTranslate?-1:1,f=function(e){let t=0,s=0,a=0,i=0;return"detail"in e&&(s=e.detail),"wheelDelta"in e&&(s=-e.wheelDelta/120),"wheelDeltaY"in e&&(s=-e.wheelDeltaY/120),"wheelDeltaX"in e&&(t=-e.wheelDeltaX/120),"axis"in e&&e.axis===e.HORIZONTAL_AXIS&&(t=s,s=0),a=10*t,i=10*s,"deltaY"in e&&(i=e.deltaY),"deltaX"in e&&(a=e.deltaX),e.shiftKey&&!a&&(a=i,i=0),(a||i)&&e.deltaMode&&(1===e.deltaMode?(a*=40,i*=40):(a*=800,i*=800)),a&&!t&&(t=a<1?-1:1),i&&!s&&(s=i<1?-1:1),{spinX:t,spinY:s,pixelX:a,pixelY:i}}(s);if(r.forceToAxis)if(t.isHorizontal()){if(!(Math.abs(f.pixelX)>Math.abs(f.pixelY)))return!0;c=-f.pixelX*m}else{if(!(Math.abs(f.pixelY)>Math.abs(f.pixelX)))return!0;c=-f.pixelY}else c=Math.abs(f.pixelX)>Math.abs(f.pixelY)?-f.pixelX*m:-f.pixelY;if(0===c)return!0;r.invert&&(c=-c);let v=t.getTranslate()+c*r.sensitivity;if(v>=t.minTranslate()&&(v=t.minTranslate()),v<=t.maxTranslate()&&(v=t.maxTranslate()),a=!!t.params.loop||!(v===t.minTranslate()||v===t.maxTranslate()),a&&t.params.nested&&s.stopPropagation(),t.params.freeMode&&t.params.freeMode.enabled){const e={time:u(),delta:Math.abs(c),direction:Math.sign(c)},a=o&&e.time=t.minTranslate()&&(n=t.minTranslate()),n<=t.maxTranslate()&&(n=t.maxTranslate()),t.setTransition(0),t.setTranslate(n),t.updateProgress(),t.updateActiveIndex(),t.updateSlidesClasses(),(!d&&t.isBeginning||!u&&t.isEnd)&&t.updateSlidesClasses(),t.params.freeMode.sticky){clearTimeout(l),l=void 0,h.length>=15&&h.shift();const s=h.length?h[h.length-1]:void 0,a=h[0];if(h.push(e),s&&(e.delta>s.delta||e.direction!==s.direction))h.splice(0);else if(h.length>=15&&e.time-a.time<500&&a.delta-e.delta>=1&&e.delta<=6){const s=c>0?.8:.2;o=e,h.splice(0),l=p((()=>{t.slideToClosest(t.params.speed,!0,void 0,s)}),0)}l||(l=p((()=>{o=e,h.splice(0),t.slideToClosest(t.params.speed,!0,void 0,.5)}),500))}if(a||i("scroll",s),t.params.autoplay&&t.params.autoplayDisableOnInteraction&&t.autoplay.stop(),n===t.minTranslate()||n===t.maxTranslate())return!0}}else{const s={time:u(),delta:Math.abs(c),direction:Math.sign(c),raw:e};h.length>=2&&h.shift();const a=h.length?h[h.length-1]:void 0;if(h.push(s),a?(s.direction!==a.direction||s.delta>a.delta||s.time>a.time+150)&&g(s):g(s),function(e){const s=t.params.mousewheel;if(e.direction<0){if(t.isEnd&&!t.params.loop&&s.releaseOnEdges)return!0}else if(t.isBeginning&&!t.params.loop&&s.releaseOnEdges)return!0;return!1}(s))return!0}return s.preventDefault?s.preventDefault():s.returnValue=!1,!1}function w(e){let s=t.$el;"container"!==t.params.mousewheel.eventsTarget&&(s=d(t.params.mousewheel.eventsTarget)),s[e]("mouseenter",m),s[e]("mouseleave",f),s[e]("wheel",v)}function b(){return t.params.cssMode?(t.wrapperEl.removeEventListener("wheel",v),!0):!t.mousewheel.enabled&&(w("on"),t.mousewheel.enabled=!0,!0)}function x(){return t.params.cssMode?(t.wrapperEl.addEventListener(event,v),!0):!!t.mousewheel.enabled&&(w("off"),t.mousewheel.enabled=!1,!0)}a("init",(()=>{!t.params.mousewheel.enabled&&t.params.cssMode&&x(),t.params.mousewheel.enabled&&b()})),a("destroy",(()=>{t.params.cssMode&&b(),t.mousewheel.enabled&&x()})),Object.assign(t.mousewheel,{enable:b,disable:x})},function(e){let{swiper:t,extendParams:s,on:a,emit:i}=e;function r(e){let s;return e&&(s=d(e),t.params.uniqueNavElements&&"string"==typeof e&&s.length>1&&1===t.$el.find(e).length&&(s=t.$el.find(e))),s}function n(e,s){const a=t.params.navigation;e&&e.length>0&&(e[s?"addClass":"removeClass"](a.disabledClass),e[0]&&"BUTTON"===e[0].tagName&&(e[0].disabled=s),t.params.watchOverflow&&t.enabled&&e[t.isLocked?"addClass":"removeClass"](a.lockClass))}function l(){if(t.params.loop)return;const{$nextEl:e,$prevEl:s}=t.navigation;n(s,t.isBeginning&&!t.params.rewind),n(e,t.isEnd&&!t.params.rewind)}function o(e){e.preventDefault(),(!t.isBeginning||t.params.loop||t.params.rewind)&&(t.slidePrev(),i("navigationPrev"))}function c(e){e.preventDefault(),(!t.isEnd||t.params.loop||t.params.rewind)&&(t.slideNext(),i("navigationNext"))}function p(){const e=t.params.navigation;if(t.params.navigation=F(t,t.originalParams.navigation,t.params.navigation,{nextEl:"swiper-button-next",prevEl:"swiper-button-prev"}),!e.nextEl&&!e.prevEl)return;const s=r(e.nextEl),a=r(e.prevEl);s&&s.length>0&&s.on("click",c),a&&a.length>0&&a.on("click",o),Object.assign(t.navigation,{$nextEl:s,nextEl:s&&s[0],$prevEl:a,prevEl:a&&a[0]}),t.enabled||(s&&s.addClass(e.lockClass),a&&a.addClass(e.lockClass))}function u(){const{$nextEl:e,$prevEl:s}=t.navigation;e&&e.length&&(e.off("click",c),e.removeClass(t.params.navigation.disabledClass)),s&&s.length&&(s.off("click",o),s.removeClass(t.params.navigation.disabledClass))}s({navigation:{nextEl:null,prevEl:null,hideOnClick:!1,disabledClass:"swiper-button-disabled",hiddenClass:"swiper-button-hidden",lockClass:"swiper-button-lock",navigationDisabledClass:"swiper-navigation-disabled"}}),t.navigation={nextEl:null,$nextEl:null,prevEl:null,$prevEl:null},a("init",(()=>{!1===t.params.navigation.enabled?h():(p(),l())})),a("toEdge fromEdge lock unlock",(()=>{l()})),a("destroy",(()=>{u()})),a("enable disable",(()=>{const{$nextEl:e,$prevEl:s}=t.navigation;e&&e[t.enabled?"removeClass":"addClass"](t.params.navigation.lockClass),s&&s[t.enabled?"removeClass":"addClass"](t.params.navigation.lockClass)})),a("click",((e,s)=>{const{$nextEl:a,$prevEl:r}=t.navigation,n=s.target;if(t.params.navigation.hideOnClick&&!d(n).is(r)&&!d(n).is(a)){if(t.pagination&&t.params.pagination&&t.params.pagination.clickable&&(t.pagination.el===n||t.pagination.el.contains(n)))return;let e;a?e=a.hasClass(t.params.navigation.hiddenClass):r&&(e=r.hasClass(t.params.navigation.hiddenClass)),i(!0===e?"navigationShow":"navigationHide"),a&&a.toggleClass(t.params.navigation.hiddenClass),r&&r.toggleClass(t.params.navigation.hiddenClass)}}));const h=()=>{t.$el.addClass(t.params.navigation.navigationDisabledClass),u()};Object.assign(t.navigation,{enable:()=>{t.$el.removeClass(t.params.navigation.navigationDisabledClass),p(),l()},disable:h,update:l,init:p,destroy:u})},function(e){let{swiper:t,extendParams:s,on:a,emit:i}=e;const r="swiper-pagination";let n;s({pagination:{el:null,bulletElement:"span",clickable:!1,hideOnClick:!1,renderBullet:null,renderProgressbar:null,renderFraction:null,renderCustom:null,progressbarOpposite:!1,type:"bullets",dynamicBullets:!1,dynamicMainBullets:1,formatFractionCurrent:e=>e,formatFractionTotal:e=>e,bulletClass:`${r}-bullet`,bulletActiveClass:`${r}-bullet-active`,modifierClass:`${r}-`,currentClass:`${r}-current`,totalClass:`${r}-total`,hiddenClass:`${r}-hidden`,progressbarFillClass:`${r}-progressbar-fill`,progressbarOppositeClass:`${r}-progressbar-opposite`,clickableClass:`${r}-clickable`,lockClass:`${r}-lock`,horizontalClass:`${r}-horizontal`,verticalClass:`${r}-vertical`,paginationDisabledClass:`${r}-disabled`}}),t.pagination={el:null,$el:null,bullets:[]};let l=0;function o(){return!t.params.pagination.el||!t.pagination.el||!t.pagination.$el||0===t.pagination.$el.length}function c(e,s){const{bulletActiveClass:a}=t.params.pagination;e[s]().addClass(`${a}-${s}`)[s]().addClass(`${a}-${s}-${s}`)}function p(){const e=t.rtl,s=t.params.pagination;if(o())return;const a=t.virtual&&t.params.virtual.enabled?t.virtual.slides.length:t.slides.length,r=t.pagination.$el;let p;const u=t.params.loop?Math.ceil((a-2*t.loopedSlides)/t.params.slidesPerGroup):t.snapGrid.length;if(t.params.loop?(p=Math.ceil((t.activeIndex-t.loopedSlides)/t.params.slidesPerGroup),p>a-1-2*t.loopedSlides&&(p-=a-2*t.loopedSlides),p>u-1&&(p-=u),p<0&&"bullets"!==t.params.paginationType&&(p=u+p)):p=void 0!==t.snapIndex?t.snapIndex:t.activeIndex||0,"bullets"===s.type&&t.pagination.bullets&&t.pagination.bullets.length>0){const a=t.pagination.bullets;let i,o,u;if(s.dynamicBullets&&(n=a.eq(0)[t.isHorizontal()?"outerWidth":"outerHeight"](!0),r.css(t.isHorizontal()?"width":"height",n*(s.dynamicMainBullets+4)+"px"),s.dynamicMainBullets>1&&void 0!==t.previousIndex&&(l+=p-(t.previousIndex-t.loopedSlides||0),l>s.dynamicMainBullets-1?l=s.dynamicMainBullets-1:l<0&&(l=0)),i=Math.max(p-l,0),o=i+(Math.min(a.length,s.dynamicMainBullets)-1),u=(o+i)/2),a.removeClass(["","-next","-next-next","-prev","-prev-prev","-main"].map((e=>`${s.bulletActiveClass}${e}`)).join(" ")),r.length>1)a.each((e=>{const t=d(e),a=t.index();a===p&&t.addClass(s.bulletActiveClass),s.dynamicBullets&&(a>=i&&a<=o&&t.addClass(`${s.bulletActiveClass}-main`),a===i&&c(t,"prev"),a===o&&c(t,"next"))}));else{const e=a.eq(p),r=e.index();if(e.addClass(s.bulletActiveClass),s.dynamicBullets){const e=a.eq(i),n=a.eq(o);for(let e=i;e<=o;e+=1)a.eq(e).addClass(`${s.bulletActiveClass}-main`);if(t.params.loop)if(r>=a.length){for(let e=s.dynamicMainBullets;e>=0;e-=1)a.eq(a.length-e).addClass(`${s.bulletActiveClass}-main`);a.eq(a.length-s.dynamicMainBullets-1).addClass(`${s.bulletActiveClass}-prev`)}else c(e,"prev"),c(n,"next");else c(e,"prev"),c(n,"next")}}if(s.dynamicBullets){const i=Math.min(a.length,s.dynamicMainBullets+4),r=(n*i-n)/2-u*n,l=e?"right":"left";a.css(t.isHorizontal()?l:"top",`${r}px`)}}if("fraction"===s.type&&(r.find(U(s.currentClass)).text(s.formatFractionCurrent(p+1)),r.find(U(s.totalClass)).text(s.formatFractionTotal(u))),"progressbar"===s.type){let e;e=s.progressbarOpposite?t.isHorizontal()?"vertical":"horizontal":t.isHorizontal()?"horizontal":"vertical";const a=(p+1)/u;let i=1,n=1;"horizontal"===e?i=a:n=a,r.find(U(s.progressbarFillClass)).transform(`translate3d(0,0,0) scaleX(${i}) scaleY(${n})`).transition(t.params.speed)}"custom"===s.type&&s.renderCustom?(r.html(s.renderCustom(t,p+1,u)),i("paginationRender",r[0])):i("paginationUpdate",r[0]),t.params.watchOverflow&&t.enabled&&r[t.isLocked?"addClass":"removeClass"](s.lockClass)}function u(){const e=t.params.pagination;if(o())return;const s=t.virtual&&t.params.virtual.enabled?t.virtual.slides.length:t.slides.length,a=t.pagination.$el;let r="";if("bullets"===e.type){let i=t.params.loop?Math.ceil((s-2*t.loopedSlides)/t.params.slidesPerGroup):t.snapGrid.length;t.params.freeMode&&t.params.freeMode.enabled&&!t.params.loop&&i>s&&(i=s);for(let s=0;s`;a.html(r),t.pagination.bullets=a.find(U(e.bulletClass))}"fraction"===e.type&&(r=e.renderFraction?e.renderFraction.call(t,e.currentClass,e.totalClass):` / `,a.html(r)),"progressbar"===e.type&&(r=e.renderProgressbar?e.renderProgressbar.call(t,e.progressbarFillClass):``,a.html(r)),"custom"!==e.type&&i("paginationRender",t.pagination.$el[0])}function h(){t.params.pagination=F(t,t.originalParams.pagination,t.params.pagination,{el:"swiper-pagination"});const e=t.params.pagination;if(!e.el)return;let s=d(e.el);0!==s.length&&(t.params.uniqueNavElements&&"string"==typeof e.el&&s.length>1&&(s=t.$el.find(e.el),s.length>1&&(s=s.filter((e=>d(e).parents(".swiper")[0]===t.el)))),"bullets"===e.type&&e.clickable&&s.addClass(e.clickableClass),s.addClass(e.modifierClass+e.type),s.addClass(t.isHorizontal()?e.horizontalClass:e.verticalClass),"bullets"===e.type&&e.dynamicBullets&&(s.addClass(`${e.modifierClass}${e.type}-dynamic`),l=0,e.dynamicMainBullets<1&&(e.dynamicMainBullets=1)),"progressbar"===e.type&&e.progressbarOpposite&&s.addClass(e.progressbarOppositeClass),e.clickable&&s.on("click",U(e.bulletClass),(function(e){e.preventDefault();let s=d(this).index()*t.params.slidesPerGroup;t.params.loop&&(s+=t.loopedSlides),t.slideTo(s)})),Object.assign(t.pagination,{$el:s,el:s[0]}),t.enabled||s.addClass(e.lockClass))}function m(){const e=t.params.pagination;if(o())return;const s=t.pagination.$el;s.removeClass(e.hiddenClass),s.removeClass(e.modifierClass+e.type),s.removeClass(t.isHorizontal()?e.horizontalClass:e.verticalClass),t.pagination.bullets&&t.pagination.bullets.removeClass&&t.pagination.bullets.removeClass(e.bulletActiveClass),e.clickable&&s.off("click",U(e.bulletClass))}a("init",(()=>{!1===t.params.pagination.enabled?f():(h(),u(),p())})),a("activeIndexChange",(()=>{(t.params.loop||void 0===t.snapIndex)&&p()})),a("snapIndexChange",(()=>{t.params.loop||p()})),a("slidesLengthChange",(()=>{t.params.loop&&(u(),p())})),a("snapGridLengthChange",(()=>{t.params.loop||(u(),p())})),a("destroy",(()=>{m()})),a("enable disable",(()=>{const{$el:e}=t.pagination;e&&e[t.enabled?"removeClass":"addClass"](t.params.pagination.lockClass)})),a("lock unlock",(()=>{p()})),a("click",((e,s)=>{const a=s.target,{$el:r}=t.pagination;if(t.params.pagination.el&&t.params.pagination.hideOnClick&&r&&r.length>0&&!d(a).hasClass(t.params.pagination.bulletClass)){if(t.navigation&&(t.navigation.nextEl&&a===t.navigation.nextEl||t.navigation.prevEl&&a===t.navigation.prevEl))return;const e=r.hasClass(t.params.pagination.hiddenClass);i(!0===e?"paginationShow":"paginationHide"),r.toggleClass(t.params.pagination.hiddenClass)}}));const f=()=>{t.$el.addClass(t.params.pagination.paginationDisabledClass),t.pagination.$el&&t.pagination.$el.addClass(t.params.pagination.paginationDisabledClass),m()};Object.assign(t.pagination,{enable:()=>{t.$el.removeClass(t.params.pagination.paginationDisabledClass),t.pagination.$el&&t.pagination.$el.removeClass(t.params.pagination.paginationDisabledClass),h(),u(),p()},disable:f,render:u,update:p,init:h,destroy:m})},function(e){let{swiper:t,extendParams:s,on:i,emit:r}=e;const n=a();let l,o,c,u,h=!1,m=null,f=null;function g(){if(!t.params.scrollbar.el||!t.scrollbar.el)return;const{scrollbar:e,rtlTranslate:s,progress:a}=t,{$dragEl:i,$el:r}=e,n=t.params.scrollbar;let l=o,d=(c-o)*a;s?(d=-d,d>0?(l=o-d,d=0):-d+o>c&&(l=c+d)):d<0?(l=o+d,d=0):d+o>c&&(l=c-d),t.isHorizontal()?(i.transform(`translate3d(${d}px, 0, 0)`),i[0].style.width=`${l}px`):(i.transform(`translate3d(0px, ${d}px, 0)`),i[0].style.height=`${l}px`),n.hide&&(clearTimeout(m),r[0].style.opacity=1,m=setTimeout((()=>{r[0].style.opacity=0,r.transition(400)}),1e3))}function v(){if(!t.params.scrollbar.el||!t.scrollbar.el)return;const{scrollbar:e}=t,{$dragEl:s,$el:a}=e;s[0].style.width="",s[0].style.height="",c=t.isHorizontal()?a[0].offsetWidth:a[0].offsetHeight,u=t.size/(t.virtualSize+t.params.slidesOffsetBefore-(t.params.centeredSlides?t.snapGrid[0]:0)),o="auto"===t.params.scrollbar.dragSize?c*u:parseInt(t.params.scrollbar.dragSize,10),t.isHorizontal()?s[0].style.width=`${o}px`:s[0].style.height=`${o}px`,a[0].style.display=u>=1?"none":"",t.params.scrollbar.hide&&(a[0].style.opacity=0),t.params.watchOverflow&&t.enabled&&e.$el[t.isLocked?"addClass":"removeClass"](t.params.scrollbar.lockClass)}function w(e){return t.isHorizontal()?"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].clientX:e.clientX:"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].clientY:e.clientY}function b(e){const{scrollbar:s,rtlTranslate:a}=t,{$el:i}=s;let r;r=(w(e)-i.offset()[t.isHorizontal()?"left":"top"]-(null!==l?l:o/2))/(c-o),r=Math.max(Math.min(r,1),0),a&&(r=1-r);const n=t.minTranslate()+(t.maxTranslate()-t.minTranslate())*r;t.updateProgress(n),t.setTranslate(n),t.updateActiveIndex(),t.updateSlidesClasses()}function x(e){const s=t.params.scrollbar,{scrollbar:a,$wrapperEl:i}=t,{$el:n,$dragEl:o}=a;h=!0,l=e.target===o[0]||e.target===o?w(e)-e.target.getBoundingClientRect()[t.isHorizontal()?"left":"top"]:null,e.preventDefault(),e.stopPropagation(),i.transition(100),o.transition(100),b(e),clearTimeout(f),n.transition(0),s.hide&&n.css("opacity",1),t.params.cssMode&&t.$wrapperEl.css("scroll-snap-type","none"),r("scrollbarDragStart",e)}function y(e){const{scrollbar:s,$wrapperEl:a}=t,{$el:i,$dragEl:n}=s;h&&(e.preventDefault?e.preventDefault():e.returnValue=!1,b(e),a.transition(0),i.transition(0),n.transition(0),r("scrollbarDragMove",e))}function E(e){const s=t.params.scrollbar,{scrollbar:a,$wrapperEl:i}=t,{$el:n}=a;h&&(h=!1,t.params.cssMode&&(t.$wrapperEl.css("scroll-snap-type",""),i.transition("")),s.hide&&(clearTimeout(f),f=p((()=>{n.css("opacity",0),n.transition(400)}),1e3)),r("scrollbarDragEnd",e),s.snapOnRelease&&t.slideToClosest())}function C(e){const{scrollbar:s,touchEventsTouch:a,touchEventsDesktop:i,params:r,support:l}=t,o=s.$el;if(!o)return;const d=o[0],c=!(!l.passiveListener||!r.passiveListeners)&&{passive:!1,capture:!1},p=!(!l.passiveListener||!r.passiveListeners)&&{passive:!0,capture:!1};if(!d)return;const u="on"===e?"addEventListener":"removeEventListener";l.touch?(d[u](a.start,x,c),d[u](a.move,y,c),d[u](a.end,E,p)):(d[u](i.start,x,c),n[u](i.move,y,c),n[u](i.end,E,p))}function T(){const{scrollbar:e,$el:s}=t;t.params.scrollbar=F(t,t.originalParams.scrollbar,t.params.scrollbar,{el:"swiper-scrollbar"});const a=t.params.scrollbar;if(!a.el)return;let i=d(a.el);t.params.uniqueNavElements&&"string"==typeof a.el&&i.length>1&&1===s.find(a.el).length&&(i=s.find(a.el)),i.addClass(t.isHorizontal()?a.horizontalClass:a.verticalClass);let r=i.find(`.${t.params.scrollbar.dragClass}`);0===r.length&&(r=d(`
`),i.append(r)),Object.assign(e,{$el:i,el:i[0],$dragEl:r,dragEl:r[0]}),a.draggable&&t.params.scrollbar.el&&t.scrollbar.el&&C("on"),i&&i[t.enabled?"removeClass":"addClass"](t.params.scrollbar.lockClass)}function $(){const e=t.params.scrollbar,s=t.scrollbar.$el;s&&s.removeClass(t.isHorizontal()?e.horizontalClass:e.verticalClass),t.params.scrollbar.el&&t.scrollbar.el&&C("off")}s({scrollbar:{el:null,dragSize:"auto",hide:!1,draggable:!1,snapOnRelease:!0,lockClass:"swiper-scrollbar-lock",dragClass:"swiper-scrollbar-drag",scrollbarDisabledClass:"swiper-scrollbar-disabled",horizontalClass:"swiper-scrollbar-horizontal",verticalClass:"swiper-scrollbar-vertical"}}),t.scrollbar={el:null,dragEl:null,$el:null,$dragEl:null},i("init",(()=>{!1===t.params.scrollbar.enabled?S():(T(),v(),g())})),i("update resize observerUpdate lock unlock",(()=>{v()})),i("setTranslate",(()=>{g()})),i("setTransition",((e,s)=>{!function(e){t.params.scrollbar.el&&t.scrollbar.el&&t.scrollbar.$dragEl.transition(e)}(s)})),i("enable disable",(()=>{const{$el:e}=t.scrollbar;e&&e[t.enabled?"removeClass":"addClass"](t.params.scrollbar.lockClass)})),i("destroy",(()=>{$()}));const S=()=>{t.$el.addClass(t.params.scrollbar.scrollbarDisabledClass),t.scrollbar.$el&&t.scrollbar.$el.addClass(t.params.scrollbar.scrollbarDisabledClass),$()};Object.assign(t.scrollbar,{enable:()=>{t.$el.removeClass(t.params.scrollbar.scrollbarDisabledClass),t.scrollbar.$el&&t.scrollbar.$el.removeClass(t.params.scrollbar.scrollbarDisabledClass),T(),v(),g()},disable:S,updateSize:v,setTranslate:g,init:T,destroy:$})},function(e){let{swiper:t,extendParams:s,on:a}=e;s({parallax:{enabled:!1}});const i=(e,s)=>{const{rtl:a}=t,i=d(e),r=a?-1:1,n=i.attr("data-swiper-parallax")||"0";let l=i.attr("data-swiper-parallax-x"),o=i.attr("data-swiper-parallax-y");const c=i.attr("data-swiper-parallax-scale"),p=i.attr("data-swiper-parallax-opacity");if(l||o?(l=l||"0",o=o||"0"):t.isHorizontal()?(l=n,o="0"):(o=n,l="0"),l=l.indexOf("%")>=0?parseInt(l,10)*s*r+"%":l*s*r+"px",o=o.indexOf("%")>=0?parseInt(o,10)*s+"%":o*s+"px",null!=p){const e=p-(p-1)*(1-Math.abs(s));i[0].style.opacity=e}if(null==c)i.transform(`translate3d(${l}, ${o}, 0px)`);else{const e=c-(c-1)*(1-Math.abs(s));i.transform(`translate3d(${l}, ${o}, 0px) scale(${e})`)}},r=()=>{const{$el:e,slides:s,progress:a,snapGrid:r}=t;e.children("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]").each((e=>{i(e,a)})),s.each(((e,s)=>{let n=e.progress;t.params.slidesPerGroup>1&&"auto"!==t.params.slidesPerView&&(n+=Math.ceil(s/2)-a*(r.length-1)),n=Math.min(Math.max(n,-1),1),d(e).find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]").each((e=>{i(e,n)}))}))};a("beforeInit",(()=>{t.params.parallax.enabled&&(t.params.watchSlidesProgress=!0,t.originalParams.watchSlidesProgress=!0)})),a("init",(()=>{t.params.parallax.enabled&&r()})),a("setTranslate",(()=>{t.params.parallax.enabled&&r()})),a("setTransition",((e,s)=>{t.params.parallax.enabled&&function(e){void 0===e&&(e=t.params.speed);const{$el:s}=t;s.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]").each((t=>{const s=d(t);let a=parseInt(s.attr("data-swiper-parallax-duration"),10)||e;0===e&&(a=0),s.transition(a)}))}(s)}))},function(e){let{swiper:t,extendParams:s,on:a,emit:i}=e;const n=r();s({zoom:{enabled:!1,maxRatio:3,minRatio:1,toggle:!0,containerClass:"swiper-zoom-container",zoomedSlideClass:"swiper-slide-zoomed"}}),t.zoom={enabled:!1};let l,o,c,p=1,u=!1;const m={$slideEl:void 0,slideWidth:void 0,slideHeight:void 0,$imageEl:void 0,$imageWrapEl:void 0,maxRatio:3},f={isTouched:void 0,isMoved:void 0,currentX:void 0,currentY:void 0,minX:void 0,minY:void 0,maxX:void 0,maxY:void 0,width:void 0,height:void 0,startX:void 0,startY:void 0,touchesStart:{},touchesCurrent:{}},g={x:void 0,y:void 0,prevPositionX:void 0,prevPositionY:void 0,prevTime:void 0};let v=1;function w(e){if(e.targetTouches.length<2)return 1;const t=e.targetTouches[0].pageX,s=e.targetTouches[0].pageY,a=e.targetTouches[1].pageX,i=e.targetTouches[1].pageY;return Math.sqrt((a-t)**2+(i-s)**2)}function b(e){const s=t.support,a=t.params.zoom;if(o=!1,c=!1,!s.gestures){if("touchstart"!==e.type||"touchstart"===e.type&&e.targetTouches.length<2)return;o=!0,m.scaleStart=w(e)}m.$slideEl&&m.$slideEl.length||(m.$slideEl=d(e.target).closest(`.${t.params.slideClass}`),0===m.$slideEl.length&&(m.$slideEl=t.slides.eq(t.activeIndex)),m.$imageEl=m.$slideEl.find(`.${a.containerClass}`).eq(0).find("picture, img, svg, canvas, .swiper-zoom-target").eq(0),m.$imageWrapEl=m.$imageEl.parent(`.${a.containerClass}`),m.maxRatio=m.$imageWrapEl.attr("data-swiper-zoom")||a.maxRatio,0!==m.$imageWrapEl.length)?(m.$imageEl&&m.$imageEl.transition(0),u=!0):m.$imageEl=void 0}function x(e){const s=t.support,a=t.params.zoom,i=t.zoom;if(!s.gestures){if("touchmove"!==e.type||"touchmove"===e.type&&e.targetTouches.length<2)return;c=!0,m.scaleMove=w(e)}m.$imageEl&&0!==m.$imageEl.length?(s.gestures?i.scale=e.scale*p:i.scale=m.scaleMove/m.scaleStart*p,i.scale>m.maxRatio&&(i.scale=m.maxRatio-1+(i.scale-m.maxRatio+1)**.5),i.scalef.touchesStart.x))return void(f.isTouched=!1);if(!t.isHorizontal()&&(Math.floor(f.minY)===Math.floor(f.startY)&&f.touchesCurrent.yf.touchesStart.y))return void(f.isTouched=!1)}e.cancelable&&e.preventDefault(),e.stopPropagation(),f.isMoved=!0,f.currentX=f.touchesCurrent.x-f.touchesStart.x+f.startX,f.currentY=f.touchesCurrent.y-f.touchesStart.y+f.startY,f.currentXf.maxX&&(f.currentX=f.maxX-1+(f.currentX-f.maxX+1)**.8),f.currentYf.maxY&&(f.currentY=f.maxY-1+(f.currentY-f.maxY+1)**.8),g.prevPositionX||(g.prevPositionX=f.touchesCurrent.x),g.prevPositionY||(g.prevPositionY=f.touchesCurrent.y),g.prevTime||(g.prevTime=Date.now()),g.x=(f.touchesCurrent.x-g.prevPositionX)/(Date.now()-g.prevTime)/2,g.y=(f.touchesCurrent.y-g.prevPositionY)/(Date.now()-g.prevTime)/2,Math.abs(f.touchesCurrent.x-g.prevPositionX)<2&&(g.x=0),Math.abs(f.touchesCurrent.y-g.prevPositionY)<2&&(g.y=0),g.prevPositionX=f.touchesCurrent.x,g.prevPositionY=f.touchesCurrent.y,g.prevTime=Date.now(),m.$imageWrapEl.transform(`translate3d(${f.currentX}px, ${f.currentY}px,0)`)}}function C(){const e=t.zoom;m.$slideEl&&t.previousIndex!==t.activeIndex&&(m.$imageEl&&m.$imageEl.transform("translate3d(0,0,0) scale(1)"),m.$imageWrapEl&&m.$imageWrapEl.transform("translate3d(0,0,0)"),e.scale=1,p=1,m.$slideEl=void 0,m.$imageEl=void 0,m.$imageWrapEl=void 0)}function T(e){const s=t.zoom,a=t.params.zoom;if(m.$slideEl||(e&&e.target&&(m.$slideEl=d(e.target).closest(`.${t.params.slideClass}`)),m.$slideEl||(t.params.virtual&&t.params.virtual.enabled&&t.virtual?m.$slideEl=t.$wrapperEl.children(`.${t.params.slideActiveClass}`):m.$slideEl=t.slides.eq(t.activeIndex)),m.$imageEl=m.$slideEl.find(`.${a.containerClass}`).eq(0).find("picture, img, svg, canvas, .swiper-zoom-target").eq(0),m.$imageWrapEl=m.$imageEl.parent(`.${a.containerClass}`)),!m.$imageEl||0===m.$imageEl.length||!m.$imageWrapEl||0===m.$imageWrapEl.length)return;let i,r,l,o,c,u,h,g,v,w,b,x,y,E,C,T,$,S;t.params.cssMode&&(t.wrapperEl.style.overflow="hidden",t.wrapperEl.style.touchAction="none"),m.$slideEl.addClass(`${a.zoomedSlideClass}`),void 0===f.touchesStart.x&&e?(i="touchend"===e.type?e.changedTouches[0].pageX:e.pageX,r="touchend"===e.type?e.changedTouches[0].pageY:e.pageY):(i=f.touchesStart.x,r=f.touchesStart.y),s.scale=m.$imageWrapEl.attr("data-swiper-zoom")||a.maxRatio,p=m.$imageWrapEl.attr("data-swiper-zoom")||a.maxRatio,e?($=m.$slideEl[0].offsetWidth,S=m.$slideEl[0].offsetHeight,l=m.$slideEl.offset().left+n.scrollX,o=m.$slideEl.offset().top+n.scrollY,c=l+$/2-i,u=o+S/2-r,v=m.$imageEl[0].offsetWidth,w=m.$imageEl[0].offsetHeight,b=v*s.scale,x=w*s.scale,y=Math.min($/2-b/2,0),E=Math.min(S/2-x/2,0),C=-y,T=-E,h=c*s.scale,g=u*s.scale,hC&&(h=C),gT&&(g=T)):(h=0,g=0),m.$imageWrapEl.transition(300).transform(`translate3d(${h}px, ${g}px,0)`),m.$imageEl.transition(300).transform(`translate3d(0,0,0) scale(${s.scale})`)}function $(){const e=t.zoom,s=t.params.zoom;m.$slideEl||(t.params.virtual&&t.params.virtual.enabled&&t.virtual?m.$slideEl=t.$wrapperEl.children(`.${t.params.slideActiveClass}`):m.$slideEl=t.slides.eq(t.activeIndex),m.$imageEl=m.$slideEl.find(`.${s.containerClass}`).eq(0).find("picture, img, svg, canvas, .swiper-zoom-target").eq(0),m.$imageWrapEl=m.$imageEl.parent(`.${s.containerClass}`)),m.$imageEl&&0!==m.$imageEl.length&&m.$imageWrapEl&&0!==m.$imageWrapEl.length&&(t.params.cssMode&&(t.wrapperEl.style.overflow="",t.wrapperEl.style.touchAction=""),e.scale=1,p=1,m.$imageWrapEl.transition(300).transform("translate3d(0,0,0)"),m.$imageEl.transition(300).transform("translate3d(0,0,0) scale(1)"),m.$slideEl.removeClass(`${s.zoomedSlideClass}`),m.$slideEl=void 0)}function S(e){const s=t.zoom;s.scale&&1!==s.scale?$():T(e)}function M(){const e=t.support;return{passiveListener:!("touchstart"!==t.touchEvents.start||!e.passiveListener||!t.params.passiveListeners)&&{passive:!0,capture:!1},activeListenerWithCapture:!e.passiveListener||{passive:!1,capture:!0}}}function P(){return`.${t.params.slideClass}`}function k(e){const{passiveListener:s}=M(),a=P();t.$wrapperEl[e]("gesturestart",a,b,s),t.$wrapperEl[e]("gesturechange",a,x,s),t.$wrapperEl[e]("gestureend",a,y,s)}function z(){l||(l=!0,k("on"))}function L(){l&&(l=!1,k("off"))}function O(){const e=t.zoom;if(e.enabled)return;e.enabled=!0;const s=t.support,{passiveListener:a,activeListenerWithCapture:i}=M(),r=P();s.gestures?(t.$wrapperEl.on(t.touchEvents.start,z,a),t.$wrapperEl.on(t.touchEvents.end,L,a)):"touchstart"===t.touchEvents.start&&(t.$wrapperEl.on(t.touchEvents.start,r,b,a),t.$wrapperEl.on(t.touchEvents.move,r,x,i),t.$wrapperEl.on(t.touchEvents.end,r,y,a),t.touchEvents.cancel&&t.$wrapperEl.on(t.touchEvents.cancel,r,y,a)),t.$wrapperEl.on(t.touchEvents.move,`.${t.params.zoom.containerClass}`,E,i)}function I(){const e=t.zoom;if(!e.enabled)return;const s=t.support;e.enabled=!1;const{passiveListener:a,activeListenerWithCapture:i}=M(),r=P();s.gestures?(t.$wrapperEl.off(t.touchEvents.start,z,a),t.$wrapperEl.off(t.touchEvents.end,L,a)):"touchstart"===t.touchEvents.start&&(t.$wrapperEl.off(t.touchEvents.start,r,b,a),t.$wrapperEl.off(t.touchEvents.move,r,x,i),t.$wrapperEl.off(t.touchEvents.end,r,y,a),t.touchEvents.cancel&&t.$wrapperEl.off(t.touchEvents.cancel,r,y,a)),t.$wrapperEl.off(t.touchEvents.move,`.${t.params.zoom.containerClass}`,E,i)}Object.defineProperty(t.zoom,"scale",{get:()=>v,set(e){if(v!==e){const t=m.$imageEl?m.$imageEl[0]:void 0,s=m.$slideEl?m.$slideEl[0]:void 0;i("zoomChange",e,t,s)}v=e}}),a("init",(()=>{t.params.zoom.enabled&&O()})),a("destroy",(()=>{I()})),a("touchStart",((e,s)=>{t.zoom.enabled&&function(e){const s=t.device;m.$imageEl&&0!==m.$imageEl.length&&(f.isTouched||(s.android&&e.cancelable&&e.preventDefault(),f.isTouched=!0,f.touchesStart.x="touchstart"===e.type?e.targetTouches[0].pageX:e.pageX,f.touchesStart.y="touchstart"===e.type?e.targetTouches[0].pageY:e.pageY))}(s)})),a("touchEnd",((e,s)=>{t.zoom.enabled&&function(){const e=t.zoom;if(!m.$imageEl||0===m.$imageEl.length)return;if(!f.isTouched||!f.isMoved)return f.isTouched=!1,void(f.isMoved=!1);f.isTouched=!1,f.isMoved=!1;let s=300,a=300;const i=g.x*s,r=f.currentX+i,n=g.y*a,l=f.currentY+n;0!==g.x&&(s=Math.abs((r-f.currentX)/g.x)),0!==g.y&&(a=Math.abs((l-f.currentY)/g.y));const o=Math.max(s,a);f.currentX=r,f.currentY=l;const d=f.width*e.scale,c=f.height*e.scale;f.minX=Math.min(m.slideWidth/2-d/2,0),f.maxX=-f.minX,f.minY=Math.min(m.slideHeight/2-c/2,0),f.maxY=-f.minY,f.currentX=Math.max(Math.min(f.currentX,f.maxX),f.minX),f.currentY=Math.max(Math.min(f.currentY,f.maxY),f.minY),m.$imageWrapEl.transition(o).transform(`translate3d(${f.currentX}px, ${f.currentY}px,0)`)}()})),a("doubleTap",((e,s)=>{!t.animating&&t.params.zoom.enabled&&t.zoom.enabled&&t.params.zoom.toggle&&S(s)})),a("transitionEnd",(()=>{t.zoom.enabled&&t.params.zoom.enabled&&C()})),a("slideChange",(()=>{t.zoom.enabled&&t.params.zoom.enabled&&t.params.cssMode&&C()})),Object.assign(t.zoom,{enable:O,disable:I,in:T,out:$,toggle:S})},function(e){let{swiper:t,extendParams:s,on:a,emit:i}=e;s({lazy:{checkInView:!1,enabled:!1,loadPrevNext:!1,loadPrevNextAmount:1,loadOnTransitionStart:!1,scrollingElement:"",elementClass:"swiper-lazy",loadingClass:"swiper-lazy-loading",loadedClass:"swiper-lazy-loaded",preloaderClass:"swiper-lazy-preloader"}}),t.lazy={};let n=!1,l=!1;function o(e,s){void 0===s&&(s=!0);const a=t.params.lazy;if(void 0===e)return;if(0===t.slides.length)return;const r=t.virtual&&t.params.virtual.enabled?t.$wrapperEl.children(`.${t.params.slideClass}[data-swiper-slide-index="${e}"]`):t.slides.eq(e),n=r.find(`.${a.elementClass}:not(.${a.loadedClass}):not(.${a.loadingClass})`);!r.hasClass(a.elementClass)||r.hasClass(a.loadedClass)||r.hasClass(a.loadingClass)||n.push(r[0]),0!==n.length&&n.each((e=>{const n=d(e);n.addClass(a.loadingClass);const l=n.attr("data-background"),c=n.attr("data-src"),p=n.attr("data-srcset"),u=n.attr("data-sizes"),h=n.parent("picture");t.loadImage(n[0],c||l,p,u,!1,(()=>{if(null!=t&&t&&(!t||t.params)&&!t.destroyed){if(l?(n.css("background-image",`url("${l}")`),n.removeAttr("data-background")):(p&&(n.attr("srcset",p),n.removeAttr("data-srcset")),u&&(n.attr("sizes",u),n.removeAttr("data-sizes")),h.length&&h.children("source").each((e=>{const t=d(e);t.attr("data-srcset")&&(t.attr("srcset",t.attr("data-srcset")),t.removeAttr("data-srcset"))})),c&&(n.attr("src",c),n.removeAttr("data-src"))),n.addClass(a.loadedClass).removeClass(a.loadingClass),r.find(`.${a.preloaderClass}`).remove(),t.params.loop&&s){const e=r.attr("data-swiper-slide-index");if(r.hasClass(t.params.slideDuplicateClass)){o(t.$wrapperEl.children(`[data-swiper-slide-index="${e}"]:not(.${t.params.slideDuplicateClass})`).index(),!1)}else{o(t.$wrapperEl.children(`.${t.params.slideDuplicateClass}[data-swiper-slide-index="${e}"]`).index(),!1)}}i("lazyImageReady",r[0],n[0]),t.params.autoHeight&&t.updateAutoHeight()}})),i("lazyImageLoad",r[0],n[0])}))}function c(){const{$wrapperEl:e,params:s,slides:a,activeIndex:i}=t,r=t.virtual&&s.virtual.enabled,n=s.lazy;let c=s.slidesPerView;function p(t){if(r){if(e.children(`.${s.slideClass}[data-swiper-slide-index="${t}"]`).length)return!0}else if(a[t])return!0;return!1}function u(e){return r?d(e).attr("data-swiper-slide-index"):d(e).index()}if("auto"===c&&(c=0),l||(l=!0),t.params.watchSlidesProgress)e.children(`.${s.slideVisibleClass}`).each((e=>{o(r?d(e).attr("data-swiper-slide-index"):d(e).index())}));else if(c>1)for(let e=i;e1||n.loadPrevNextAmount&&n.loadPrevNextAmount>1){const e=n.loadPrevNextAmount,t=Math.ceil(c),s=Math.min(i+t+Math.max(e,t),a.length),r=Math.max(i-Math.max(t,e),0);for(let e=i+t;e0&&o(u(t));const a=e.children(`.${s.slidePrevClass}`);a.length>0&&o(u(a))}}function p(){const e=r();if(!t||t.destroyed)return;const s=t.params.lazy.scrollingElement?d(t.params.lazy.scrollingElement):d(e),a=s[0]===e,i=a?e.innerWidth:s[0].offsetWidth,l=a?e.innerHeight:s[0].offsetHeight,o=t.$el.offset(),{rtlTranslate:u}=t;let h=!1;u&&(o.left-=t.$el[0].scrollLeft);const m=[[o.left,o.top],[o.left+t.width,o.top],[o.left,o.top+t.height],[o.left+t.width,o.top+t.height]];for(let e=0;e=0&&t[0]<=i&&t[1]>=0&&t[1]<=l){if(0===t[0]&&0===t[1])continue;h=!0}}const f=!("touchstart"!==t.touchEvents.start||!t.support.passiveListener||!t.params.passiveListeners)&&{passive:!0,capture:!1};h?(c(),s.off("scroll",p,f)):n||(n=!0,s.on("scroll",p,f))}a("beforeInit",(()=>{t.params.lazy.enabled&&t.params.preloadImages&&(t.params.preloadImages=!1)})),a("init",(()=>{t.params.lazy.enabled&&(t.params.lazy.checkInView?p():c())})),a("scroll",(()=>{t.params.freeMode&&t.params.freeMode.enabled&&!t.params.freeMode.sticky&&c()})),a("scrollbarDragMove resize _freeModeNoMomentumRelease",(()=>{t.params.lazy.enabled&&(t.params.lazy.checkInView?p():c())})),a("transitionStart",(()=>{t.params.lazy.enabled&&(t.params.lazy.loadOnTransitionStart||!t.params.lazy.loadOnTransitionStart&&!l)&&(t.params.lazy.checkInView?p():c())})),a("transitionEnd",(()=>{t.params.lazy.enabled&&!t.params.lazy.loadOnTransitionStart&&(t.params.lazy.checkInView?p():c())})),a("slideChange",(()=>{const{lazy:e,cssMode:s,watchSlidesProgress:a,touchReleaseOnEdges:i,resistanceRatio:r}=t.params;e.enabled&&(s||a&&(i||0===r))&&c()})),a("destroy",(()=>{t.$el&&t.$el.find(`.${t.params.lazy.loadingClass}`).removeClass(t.params.lazy.loadingClass)})),Object.assign(t.lazy,{load:c,loadInSlide:o})},function(e){let{swiper:t,extendParams:s,on:a}=e;function i(e,t){const s=function(){let e,t,s;return(a,i)=>{for(t=-1,e=a.length;e-t>1;)s=e+t>>1,a[s]<=i?t=s:e=s;return e}}();let a,i;return this.x=e,this.y=t,this.lastIndex=e.length-1,this.interpolate=function(e){return e?(i=s(this.x,e),a=i-1,(e-this.x[a])*(this.y[i]-this.y[a])/(this.x[i]-this.x[a])+this.y[a]):0},this}function r(){t.controller.control&&t.controller.spline&&(t.controller.spline=void 0,delete t.controller.spline)}s({controller:{control:void 0,inverse:!1,by:"slide"}}),t.controller={control:void 0},a("beforeInit",(()=>{t.controller.control=t.params.controller.control})),a("update",(()=>{r()})),a("resize",(()=>{r()})),a("observerUpdate",(()=>{r()})),a("setTranslate",((e,s,a)=>{t.controller.control&&t.controller.setTranslate(s,a)})),a("setTransition",((e,s,a)=>{t.controller.control&&t.controller.setTransition(s,a)})),Object.assign(t.controller,{setTranslate:function(e,s){const a=t.controller.control;let r,n;const l=t.constructor;function o(e){const s=t.rtlTranslate?-t.translate:t.translate;"slide"===t.params.controller.by&&(!function(e){t.controller.spline||(t.controller.spline=t.params.loop?new i(t.slidesGrid,e.slidesGrid):new i(t.snapGrid,e.snapGrid))}(e),n=-t.controller.spline.interpolate(-s)),n&&"container"!==t.params.controller.by||(r=(e.maxTranslate()-e.minTranslate())/(t.maxTranslate()-t.minTranslate()),n=(s-t.minTranslate())*r+e.minTranslate()),t.params.controller.inverse&&(n=e.maxTranslate()-n),e.updateProgress(n),e.setTranslate(n,t),e.updateActiveIndex(),e.updateSlidesClasses()}if(Array.isArray(a))for(let e=0;e{s.updateAutoHeight()})),s.$wrapperEl.transitionEnd((()=>{i&&(s.params.loop&&"slide"===t.params.controller.by&&s.loopFix(),s.transitionEnd())})))}if(Array.isArray(i))for(r=0;r{n(e),"BUTTON"!==e[0].tagName&&(o(e,"button"),e.on("keydown",m)),p(e,s),function(e,t){e.attr("aria-controls",t)}(e,t)},w=()=>{t.a11y.clicked=!0},b=()=>{requestAnimationFrame((()=>{requestAnimationFrame((()=>{t.destroyed||(t.a11y.clicked=!1)}))}))},x=e=>{if(t.a11y.clicked)return;const s=e.target.closest(`.${t.params.slideClass}`);if(!s||!t.slides.includes(s))return;const a=t.slides.indexOf(s)===t.activeIndex,i=t.params.watchSlidesProgress&&t.visibleSlides&&t.visibleSlides.includes(s);a||i||e.sourceCapabilities&&e.sourceCapabilities.firesTouchEvents||(t.isHorizontal()?t.el.scrollLeft=0:t.el.scrollTop=0,t.slideTo(t.slides.indexOf(s),0))},y=()=>{const e=t.params.a11y;e.itemRoleDescriptionMessage&&c(d(t.slides),e.itemRoleDescriptionMessage),e.slideRole&&o(d(t.slides),e.slideRole);const s=t.params.loop?t.slides.filter((e=>!e.classList.contains(t.params.slideDuplicateClass))).length:t.slides.length;e.slideLabelMessage&&t.slides.each(((a,i)=>{const r=d(a),n=t.params.loop?parseInt(r.attr("data-swiper-slide-index"),10):i;p(r,e.slideLabelMessage.replace(/\{\{index\}\}/,n+1).replace(/\{\{slidesLength\}\}/,s))}))},E=()=>{const e=t.params.a11y;t.$el.append(i);const s=t.$el;e.containerRoleDescriptionMessage&&c(s,e.containerRoleDescriptionMessage),e.containerMessage&&p(s,e.containerMessage);const a=t.$wrapperEl,r=e.id||a.attr("id")||`swiper-wrapper-${n=16,void 0===n&&(n=16),"x".repeat(n).replace(/x/g,(()=>Math.round(16*Math.random()).toString(16)))}`;var n;const l=t.params.autoplay&&t.params.autoplay.enabled?"off":"polite";var o;let d,u;o=r,a.attr("id",o),function(e,t){e.attr("aria-live",t)}(a,l),y(),t.navigation&&t.navigation.$nextEl&&(d=t.navigation.$nextEl),t.navigation&&t.navigation.$prevEl&&(u=t.navigation.$prevEl),d&&d.length&&v(d,r,e.nextSlideMessage),u&&u.length&&v(u,r,e.prevSlideMessage),g()&&t.pagination.$el.on("keydown",U(t.params.pagination.bulletClass),m),t.$el.on("focus",x,!0),t.$el.on("pointerdown",w,!0),t.$el.on("pointerup",b,!0)};a("beforeInit",(()=>{i=d(``)})),a("afterInit",(()=>{t.params.a11y.enabled&&E()})),a("slidesLengthChange snapGridLengthChange slidesGridLengthChange",(()=>{t.params.a11y.enabled&&y()})),a("fromEdge toEdge afterInit lock unlock",(()=>{t.params.a11y.enabled&&function(){if(t.params.loop||t.params.rewind||!t.navigation)return;const{$nextEl:e,$prevEl:s}=t.navigation;s&&s.length>0&&(t.isBeginning?(u(s),l(s)):(h(s),n(s))),e&&e.length>0&&(t.isEnd?(u(e),l(e)):(h(e),n(e)))}()})),a("paginationUpdate",(()=>{t.params.a11y.enabled&&function(){const e=t.params.a11y;f()&&t.pagination.bullets.each((s=>{const a=d(s);t.params.pagination.clickable&&(n(a),t.params.pagination.renderBullet||(o(a,"button"),p(a,e.paginationBulletMessage.replace(/\{\{index\}\}/,a.index()+1)))),a.is(`.${t.params.pagination.bulletActiveClass}`)?a.attr("aria-current","true"):a.removeAttr("aria-current")}))}()})),a("destroy",(()=>{t.params.a11y.enabled&&function(){let e,s;i&&i.length>0&&i.remove(),t.navigation&&t.navigation.$nextEl&&(e=t.navigation.$nextEl),t.navigation&&t.navigation.$prevEl&&(s=t.navigation.$prevEl),e&&e.off("keydown",m),s&&s.off("keydown",m),g()&&t.pagination.$el.off("keydown",U(t.params.pagination.bulletClass),m),t.$el.off("focus",x,!0),t.$el.off("pointerdown",w,!0),t.$el.off("pointerup",b,!0)}()}))},function(e){let{swiper:t,extendParams:s,on:a}=e;s({history:{enabled:!1,root:"",replaceState:!1,key:"slides",keepQuery:!1}});let i=!1,n={};const l=e=>e.toString().replace(/\s+/g,"-").replace(/[^\w-]+/g,"").replace(/--+/g,"-").replace(/^-+/,"").replace(/-+$/,""),o=e=>{const t=r();let s;s=e?new URL(e):t.location;const a=s.pathname.slice(1).split("/").filter((e=>""!==e)),i=a.length;return{key:a[i-2],value:a[i-1]}},d=(e,s)=>{const a=r();if(!i||!t.params.history.enabled)return;let n;n=t.params.url?new URL(t.params.url):a.location;const o=t.slides.eq(s);let d=l(o.attr("data-history"));if(t.params.history.root.length>0){let s=t.params.history.root;"/"===s[s.length-1]&&(s=s.slice(0,s.length-1)),d=`${s}/${e}/${d}`}else n.pathname.includes(e)||(d=`${e}/${d}`);t.params.history.keepQuery&&(d+=n.search);const c=a.history.state;c&&c.value===d||(t.params.history.replaceState?a.history.replaceState({value:d},null,d):a.history.pushState({value:d},null,d))},c=(e,s,a)=>{if(s)for(let i=0,r=t.slides.length;i{n=o(t.params.url),c(t.params.speed,n.value,!1)};a("init",(()=>{t.params.history.enabled&&(()=>{const e=r();if(t.params.history){if(!e.history||!e.history.pushState)return t.params.history.enabled=!1,void(t.params.hashNavigation.enabled=!0);i=!0,n=o(t.params.url),(n.key||n.value)&&(c(0,n.value,t.params.runCallbacksOnInit),t.params.history.replaceState||e.addEventListener("popstate",p))}})()})),a("destroy",(()=>{t.params.history.enabled&&(()=>{const e=r();t.params.history.replaceState||e.removeEventListener("popstate",p)})()})),a("transitionEnd _freeModeNoMomentumRelease",(()=>{i&&d(t.params.history.key,t.activeIndex)})),a("slideChange",(()=>{i&&t.params.cssMode&&d(t.params.history.key,t.activeIndex)}))},function(e){let{swiper:t,extendParams:s,emit:i,on:n}=e,l=!1;const o=a(),c=r();s({hashNavigation:{enabled:!1,replaceState:!1,watchState:!1}});const p=()=>{i("hashChange");const e=o.location.hash.replace("#","");if(e!==t.slides.eq(t.activeIndex).attr("data-hash")){const s=t.$wrapperEl.children(`.${t.params.slideClass}[data-hash="${e}"]`).index();if(void 0===s)return;t.slideTo(s)}},u=()=>{if(l&&t.params.hashNavigation.enabled)if(t.params.hashNavigation.replaceState&&c.history&&c.history.replaceState)c.history.replaceState(null,null,`#${t.slides.eq(t.activeIndex).attr("data-hash")}`||""),i("hashSet");else{const e=t.slides.eq(t.activeIndex),s=e.attr("data-hash")||e.attr("data-history");o.location.hash=s||"",i("hashSet")}};n("init",(()=>{t.params.hashNavigation.enabled&&(()=>{if(!t.params.hashNavigation.enabled||t.params.history&&t.params.history.enabled)return;l=!0;const e=o.location.hash.replace("#","");if(e){const s=0;for(let a=0,i=t.slides.length;a{t.params.hashNavigation.enabled&&t.params.hashNavigation.watchState&&d(c).off("hashchange",p)})),n("transitionEnd _freeModeNoMomentumRelease",(()=>{l&&u()})),n("slideChange",(()=>{l&&t.params.cssMode&&u()}))},function(e){let t,{swiper:s,extendParams:i,on:r,emit:n}=e;function l(){if(!s.size)return s.autoplay.running=!1,void(s.autoplay.paused=!1);const e=s.slides.eq(s.activeIndex);let a=s.params.autoplay.delay;e.attr("data-swiper-autoplay")&&(a=e.attr("data-swiper-autoplay")||s.params.autoplay.delay),clearTimeout(t),t=p((()=>{let e;s.params.autoplay.reverseDirection?s.params.loop?(s.loopFix(),e=s.slidePrev(s.params.speed,!0,!0),n("autoplay")):s.isBeginning?s.params.autoplay.stopOnLastSlide?d():(e=s.slideTo(s.slides.length-1,s.params.speed,!0,!0),n("autoplay")):(e=s.slidePrev(s.params.speed,!0,!0),n("autoplay")):s.params.loop?(s.loopFix(),e=s.slideNext(s.params.speed,!0,!0),n("autoplay")):s.isEnd?s.params.autoplay.stopOnLastSlide?d():(e=s.slideTo(0,s.params.speed,!0,!0),n("autoplay")):(e=s.slideNext(s.params.speed,!0,!0),n("autoplay")),(s.params.cssMode&&s.autoplay.running||!1===e)&&l()}),a)}function o(){return void 0===t&&(!s.autoplay.running&&(s.autoplay.running=!0,n("autoplayStart"),l(),!0))}function d(){return!!s.autoplay.running&&(void 0!==t&&(t&&(clearTimeout(t),t=void 0),s.autoplay.running=!1,n("autoplayStop"),!0))}function c(e){s.autoplay.running&&(s.autoplay.paused||(t&&clearTimeout(t),s.autoplay.paused=!0,0!==e&&s.params.autoplay.waitForTransition?["transitionend","webkitTransitionEnd"].forEach((e=>{s.$wrapperEl[0].addEventListener(e,h)})):(s.autoplay.paused=!1,l())))}function u(){const e=a();"hidden"===e.visibilityState&&s.autoplay.running&&c(),"visible"===e.visibilityState&&s.autoplay.paused&&(l(),s.autoplay.paused=!1)}function h(e){s&&!s.destroyed&&s.$wrapperEl&&e.target===s.$wrapperEl[0]&&(["transitionend","webkitTransitionEnd"].forEach((e=>{s.$wrapperEl[0].removeEventListener(e,h)})),s.autoplay.paused=!1,s.autoplay.running?l():d())}function m(){s.params.autoplay.disableOnInteraction?d():(n("autoplayPause"),c()),["transitionend","webkitTransitionEnd"].forEach((e=>{s.$wrapperEl[0].removeEventListener(e,h)}))}function f(){s.params.autoplay.disableOnInteraction||(s.autoplay.paused=!1,n("autoplayResume"),l())}s.autoplay={running:!1,paused:!1},i({autoplay:{enabled:!1,delay:3e3,waitForTransition:!0,disableOnInteraction:!0,stopOnLastSlide:!1,reverseDirection:!1,pauseOnMouseEnter:!1}}),r("init",(()=>{if(s.params.autoplay.enabled){o();a().addEventListener("visibilitychange",u),s.params.autoplay.pauseOnMouseEnter&&(s.$el.on("mouseenter",m),s.$el.on("mouseleave",f))}})),r("beforeTransitionStart",((e,t,a)=>{s.autoplay.running&&(a||!s.params.autoplay.disableOnInteraction?s.autoplay.pause(t):d())})),r("sliderFirstMove",(()=>{s.autoplay.running&&(s.params.autoplay.disableOnInteraction?d():c())})),r("touchEnd",(()=>{s.params.cssMode&&s.autoplay.paused&&!s.params.autoplay.disableOnInteraction&&l()})),r("destroy",(()=>{s.$el.off("mouseenter",m),s.$el.off("mouseleave",f),s.autoplay.running&&d();a().removeEventListener("visibilitychange",u)})),Object.assign(s.autoplay,{pause:c,run:l,start:o,stop:d})},function(e){let{swiper:t,extendParams:s,on:a}=e;s({thumbs:{swiper:null,multipleActiveThumbs:!0,autoScrollOffset:0,slideThumbActiveClass:"swiper-slide-thumb-active",thumbsContainerClass:"swiper-thumbs"}});let i=!1,r=!1;function n(){const e=t.thumbs.swiper;if(!e||e.destroyed)return;const s=e.clickedIndex,a=e.clickedSlide;if(a&&d(a).hasClass(t.params.thumbs.slideThumbActiveClass))return;if(null==s)return;let i;if(i=e.params.loop?parseInt(d(e.clickedSlide).attr("data-swiper-slide-index"),10):s,t.params.loop){let e=t.activeIndex;t.slides.eq(e).hasClass(t.params.slideDuplicateClass)&&(t.loopFix(),t._clientLeft=t.$wrapperEl[0].clientLeft,e=t.activeIndex);const s=t.slides.eq(e).prevAll(`[data-swiper-slide-index="${i}"]`).eq(0).index(),a=t.slides.eq(e).nextAll(`[data-swiper-slide-index="${i}"]`).eq(0).index();i=void 0===s?a:void 0===a?s:a-e1&&!t.params.centeredSlides&&(i=t.params.slidesPerView),t.params.thumbs.multipleActiveThumbs||(i=1),i=Math.floor(i),s.slides.removeClass(r),s.params.loop||s.params.virtual&&s.params.virtual.enabled)for(let e=0;e1?a:o:a-ot.previousIndex?"next":"prev"}else i=t.realIndex,r=i>t.previousIndex?"next":"prev";l&&(i+="next"===r?n:-1*n),s.visibleSlidesIndexes&&s.visibleSlidesIndexes.indexOf(i)<0&&(s.params.centeredSlides?i=i>o?i-Math.floor(a/2)+1:i+Math.floor(a/2)-1:i>o&&s.params.slidesPerGroup,s.slideTo(i,e?0:void 0))}}t.thumbs={swiper:null},a("beforeInit",(()=>{const{thumbs:e}=t.params;e&&e.swiper&&(l(),o(!0))})),a("slideChange update resize observerUpdate",(()=>{o()})),a("setTransition",((e,s)=>{const a=t.thumbs.swiper;a&&!a.destroyed&&a.setTransition(s)})),a("beforeDestroy",(()=>{const e=t.thumbs.swiper;e&&!e.destroyed&&r&&e.destroy()})),Object.assign(t.thumbs,{init:l,update:o})},function(e){let{swiper:t,extendParams:s,emit:a,once:i}=e;s({freeMode:{enabled:!1,momentum:!0,momentumRatio:1,momentumBounce:!0,momentumBounceRatio:1,momentumVelocityRatio:1,sticky:!1,minimumVelocity:.02}}),Object.assign(t,{freeMode:{onTouchStart:function(){const e=t.getTranslate();t.setTranslate(e),t.setTransition(0),t.touchEventsData.velocities.length=0,t.freeMode.onTouchEnd({currentPos:t.rtl?t.translate:-t.translate})},onTouchMove:function(){const{touchEventsData:e,touches:s}=t;0===e.velocities.length&&e.velocities.push({position:s[t.isHorizontal()?"startX":"startY"],time:e.touchStartTime}),e.velocities.push({position:s[t.isHorizontal()?"currentX":"currentY"],time:u()})},onTouchEnd:function(e){let{currentPos:s}=e;const{params:r,$wrapperEl:n,rtlTranslate:l,snapGrid:o,touchEventsData:d}=t,c=u()-d.touchStartTime;if(s<-t.minTranslate())t.slideTo(t.activeIndex);else if(s>-t.maxTranslate())t.slides.length1){const e=d.velocities.pop(),s=d.velocities.pop(),a=e.position-s.position,i=e.time-s.time;t.velocity=a/i,t.velocity/=2,Math.abs(t.velocity)150||u()-e.time>300)&&(t.velocity=0)}else t.velocity=0;t.velocity*=r.freeMode.momentumVelocityRatio,d.velocities.length=0;let e=1e3*r.freeMode.momentumRatio;const s=t.velocity*e;let c=t.translate+s;l&&(c=-c);let p,h=!1;const m=20*Math.abs(t.velocity)*r.freeMode.momentumBounceRatio;let f;if(ct.minTranslate())r.freeMode.momentumBounce?(c-t.minTranslate()>m&&(c=t.minTranslate()+m),p=t.minTranslate(),h=!0,d.allowMomentumBounce=!0):c=t.minTranslate(),r.loop&&r.centeredSlides&&(f=!0);else if(r.freeMode.sticky){let e;for(let t=0;t-c){e=t;break}c=Math.abs(o[e]-c){t.loopFix()})),0!==t.velocity){if(e=l?Math.abs((-c-t.translate)/t.velocity):Math.abs((c-t.translate)/t.velocity),r.freeMode.sticky){const s=Math.abs((l?-c:c)-t.translate),a=t.slidesSizesGrid[t.activeIndex];e=s{t&&!t.destroyed&&d.allowMomentumBounce&&(a("momentumBounce"),t.setTransition(r.speed),setTimeout((()=>{t.setTranslate(p),n.transitionEnd((()=>{t&&!t.destroyed&&t.transitionEnd()}))}),0))}))):t.velocity?(a("_freeModeNoMomentumRelease"),t.updateProgress(c),t.setTransition(e),t.setTranslate(c),t.transitionStart(!0,t.swipeDirection),t.animating||(t.animating=!0,n.transitionEnd((()=>{t&&!t.destroyed&&t.transitionEnd()})))):t.updateProgress(c),t.updateActiveIndex(),t.updateSlidesClasses()}else{if(r.freeMode.sticky)return void t.slideToClosest();r.freeMode&&a("_freeModeNoMomentumRelease")}(!r.freeMode.momentum||c>=r.longSwipesMs)&&(t.updateProgress(),t.updateActiveIndex(),t.updateSlidesClasses())}}}})},function(e){let t,s,a,{swiper:i,extendParams:r}=e;r({grid:{rows:1,fill:"column"}}),i.grid={initSlides:e=>{const{slidesPerView:r}=i.params,{rows:n,fill:l}=i.params.grid;s=t/n,a=Math.floor(e/n),t=Math.floor(e/n)===e/n?e:Math.ceil(e/n)*n,"auto"!==r&&"row"===l&&(t=Math.max(t,r*n))},updateSlide:(e,r,n,l)=>{const{slidesPerGroup:o,spaceBetween:d}=i.params,{rows:c,fill:p}=i.params.grid;let u,h,m;if("row"===p&&o>1){const s=Math.floor(e/(o*c)),a=e-c*o*s,i=0===s?o:Math.min(Math.ceil((n-s*c*o)/c),o);m=Math.floor(a/i),h=a-m*i+s*o,u=h+m*t/c,r.css({"-webkit-order":u,order:u})}else"column"===p?(h=Math.floor(e/c),m=e-h*c,(h>a||h===a&&m===c-1)&&(m+=1,m>=c&&(m=0,h+=1))):(m=Math.floor(e/s),h=e-m*s);r.css(l("margin-top"),0!==m?d&&`${d}px`:"")},updateWrapperSize:(e,s,a)=>{const{spaceBetween:r,centeredSlides:n,roundLengths:l}=i.params,{rows:o}=i.params.grid;if(i.virtualSize=(e+r)*t,i.virtualSize=Math.ceil(i.virtualSize/o)-r,i.$wrapperEl.css({[a("width")]:`${i.virtualSize+r}px`}),n){s.splice(0,s.length);const e=[];for(let t=0;t{const{slides:e}=t,s=t.params.fadeEffect;for(let a=0;a{const{transformEl:s}=t.params.fadeEffect;(s?t.slides.find(s):t.slides).transition(e),ae({swiper:t,duration:e,transformEl:s,allSlides:!0})},overwriteParams:()=>({slidesPerView:1,slidesPerGroup:1,watchSlidesProgress:!0,spaceBetween:0,virtualTranslate:!t.params.cssMode})})},function(e){let{swiper:t,extendParams:s,on:a}=e;s({cubeEffect:{slideShadows:!0,shadow:!0,shadowOffset:20,shadowScale:.94}});const i=(e,t,s)=>{let a=s?e.find(".swiper-slide-shadow-left"):e.find(".swiper-slide-shadow-top"),i=s?e.find(".swiper-slide-shadow-right"):e.find(".swiper-slide-shadow-bottom");0===a.length&&(a=d(`
`),e.append(a)),0===i.length&&(i=d(`
`),e.append(i)),a.length&&(a[0].style.opacity=Math.max(-t,0)),i.length&&(i[0].style.opacity=Math.max(t,0))};te({effect:"cube",swiper:t,on:a,setTranslate:()=>{const{$el:e,$wrapperEl:s,slides:a,width:r,height:n,rtlTranslate:l,size:o,browser:c}=t,p=t.params.cubeEffect,u=t.isHorizontal(),h=t.virtual&&t.params.virtual.enabled;let m,f=0;p.shadow&&(u?(m=s.find(".swiper-cube-shadow"),0===m.length&&(m=d('
'),s.append(m)),m.css({height:`${r}px`})):(m=e.find(".swiper-cube-shadow"),0===m.length&&(m=d('
'),e.append(m))));for(let e=0;e-1&&(f=90*s+90*d,l&&(f=90*-s-90*d)),t.transform(v),p.slideShadows&&i(t,d,u)}if(s.css({"-webkit-transform-origin":`50% 50% -${o/2}px`,"transform-origin":`50% 50% -${o/2}px`}),p.shadow)if(u)m.transform(`translate3d(0px, ${r/2+p.shadowOffset}px, ${-r/2}px) rotateX(90deg) rotateZ(0deg) scale(${p.shadowScale})`);else{const e=Math.abs(f)-90*Math.floor(Math.abs(f)/90),t=1.5-(Math.sin(2*e*Math.PI/360)/2+Math.cos(2*e*Math.PI/360)/2),s=p.shadowScale,a=p.shadowScale/t,i=p.shadowOffset;m.transform(`scale3d(${s}, 1, ${a}) translate3d(0px, ${n/2+i}px, ${-n/2/a}px) rotateX(-90deg)`)}const g=c.isSafari||c.isWebView?-o/2:0;s.transform(`translate3d(0px,0,${g}px) rotateX(${t.isHorizontal()?0:f}deg) rotateY(${t.isHorizontal()?-f:0}deg)`),s[0].style.setProperty("--swiper-cube-translate-z",`${g}px`)},setTransition:e=>{const{$el:s,slides:a}=t;a.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e),t.params.cubeEffect.shadow&&!t.isHorizontal()&&s.find(".swiper-cube-shadow").transition(e)},recreateShadows:()=>{const e=t.isHorizontal();t.slides.each((t=>{const s=Math.max(Math.min(t.progress,1),-1);i(d(t),s,e)}))},getEffectParams:()=>t.params.cubeEffect,perspective:()=>!0,overwriteParams:()=>({slidesPerView:1,slidesPerGroup:1,watchSlidesProgress:!0,resistanceRatio:0,spaceBetween:0,centeredSlides:!1,virtualTranslate:!0})})},function(e){let{swiper:t,extendParams:s,on:a}=e;s({flipEffect:{slideShadows:!0,limitRotation:!0,transformEl:null}});const i=(e,s,a)=>{let i=t.isHorizontal()?e.find(".swiper-slide-shadow-left"):e.find(".swiper-slide-shadow-top"),r=t.isHorizontal()?e.find(".swiper-slide-shadow-right"):e.find(".swiper-slide-shadow-bottom");0===i.length&&(i=ie(a,e,t.isHorizontal()?"left":"top")),0===r.length&&(r=ie(a,e,t.isHorizontal()?"right":"bottom")),i.length&&(i[0].style.opacity=Math.max(-s,0)),r.length&&(r[0].style.opacity=Math.max(s,0))};te({effect:"flip",swiper:t,on:a,setTranslate:()=>{const{slides:e,rtlTranslate:s}=t,a=t.params.flipEffect;for(let r=0;r{const{transformEl:s}=t.params.flipEffect;(s?t.slides.find(s):t.slides).transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e),ae({swiper:t,duration:e,transformEl:s})},recreateShadows:()=>{const e=t.params.flipEffect;t.slides.each((s=>{const a=d(s);let r=a[0].progress;t.params.flipEffect.limitRotation&&(r=Math.max(Math.min(s.progress,1),-1)),i(a,r,e)}))},getEffectParams:()=>t.params.flipEffect,perspective:()=>!0,overwriteParams:()=>({slidesPerView:1,slidesPerGroup:1,watchSlidesProgress:!0,spaceBetween:0,virtualTranslate:!t.params.cssMode})})},function(e){let{swiper:t,extendParams:s,on:a}=e;s({coverflowEffect:{rotate:50,stretch:0,depth:100,scale:1,modifier:1,slideShadows:!0,transformEl:null}}),te({effect:"coverflow",swiper:t,on:a,setTranslate:()=>{const{width:e,height:s,slides:a,slidesSizesGrid:i}=t,r=t.params.coverflowEffect,n=t.isHorizontal(),l=t.translate,o=n?e/2-l:s/2-l,d=n?r.rotate:-r.rotate,c=r.depth;for(let e=0,t=a.length;e0?p:0),s.length&&(s[0].style.opacity=-p>0?-p:0)}}},setTransition:e=>{const{transformEl:s}=t.params.coverflowEffect;(s?t.slides.find(s):t.slides).transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e)},perspective:()=>!0,overwriteParams:()=>({watchSlidesProgress:!0})})},function(e){let{swiper:t,extendParams:s,on:a}=e;s({creativeEffect:{transformEl:null,limitProgress:1,shadowPerProgress:!1,progressMultiplier:1,perspective:!0,prev:{translate:[0,0,0],rotate:[0,0,0],opacity:1,scale:1},next:{translate:[0,0,0],rotate:[0,0,0],opacity:1,scale:1}}});const i=e=>"string"==typeof e?e:`${e}px`;te({effect:"creative",swiper:t,on:a,setTranslate:()=>{const{slides:e,$wrapperEl:s,slidesSizesGrid:a}=t,r=t.params.creativeEffect,{progressMultiplier:n}=r,l=t.params.centeredSlides;if(l){const e=a[0]/2-t.params.slidesOffsetBefore||0;s.transform(`translateX(calc(50% - ${e}px))`)}for(let s=0;s0&&(f=r.prev,m=!0),u.forEach(((e,t)=>{u[t]=`calc(${e}px + (${i(f.translate[t])} * ${Math.abs(d*n)}))`})),h.forEach(((e,t)=>{h[t]=f.rotate[t]*Math.abs(d*n)})),a[0].style.zIndex=-Math.abs(Math.round(o))+e.length;const g=u.join(", "),v=`rotateX(${h[0]}deg) rotateY(${h[1]}deg) rotateZ(${h[2]}deg)`,w=c<0?`scale(${1+(1-f.scale)*c*n})`:`scale(${1-(1-f.scale)*c*n})`,b=c<0?1+(1-f.opacity)*c*n:1-(1-f.opacity)*c*n,x=`translate3d(${g}) ${v} ${w}`;if(m&&f.shadow||!m){let e=a.children(".swiper-slide-shadow");if(0===e.length&&f.shadow&&(e=ie(r,a)),e.length){const t=r.shadowPerProgress?d*(1/r.limitProgress):d;e[0].style.opacity=Math.min(Math.max(Math.abs(t),0),1)}}const y=se(r,a);y.transform(x).css({opacity:b}),f.origin&&y.css("transform-origin",f.origin)}},setTransition:e=>{const{transformEl:s}=t.params.creativeEffect;(s?t.slides.find(s):t.slides).transition(e).find(".swiper-slide-shadow").transition(e),ae({swiper:t,duration:e,transformEl:s,allSlides:!0})},perspective:()=>t.params.creativeEffect.perspective,overwriteParams:()=>({watchSlidesProgress:!0,virtualTranslate:!t.params.cssMode})})},function(e){let{swiper:t,extendParams:s,on:a}=e;s({cardsEffect:{slideShadows:!0,transformEl:null,rotate:!0,perSlideRotate:2,perSlideOffset:8}}),te({effect:"cards",swiper:t,on:a,setTranslate:()=>{const{slides:e,activeIndex:s}=t,a=t.params.cardsEffect,{startTranslate:i,isTouched:r}=t.touchEventsData,n=t.translate;for(let l=0;l0&&c<1&&(r||t.params.cssMode)&&n-1&&(r||t.params.cssMode)&&n>i;if(b||x){const e=(1-Math.abs((Math.abs(c)-.5)/.5))**.5;g+=-28*c*e,f+=-.5*e,v+=96*e,h=-25*e*Math.abs(c)+"%"}if(u=c<0?`calc(${u}px + (${v*Math.abs(c)}%))`:c>0?`calc(${u}px + (-${v*Math.abs(c)}%))`:`${u}px`,!t.isHorizontal()){const e=h;h=u,u=e}const y=c<0?""+(1+(1-f)*c):""+(1-(1-f)*c),E=`\n translate3d(${u}, ${h}, ${m}px)\n rotateZ(${a.rotate?g:0}deg)\n scale(${y})\n `;if(a.slideShadows){let e=o.find(".swiper-slide-shadow");0===e.length&&(e=ie(a,o)),e.length&&(e[0].style.opacity=Math.min(Math.max((Math.abs(c)-.5)/.5,0),1))}o[0].style.zIndex=-Math.abs(Math.round(d))+e.length;se(a,o).transform(E)}},setTransition:e=>{const{transformEl:s}=t.params.cardsEffect;(s?t.slides.find(s):t.slides).transition(e).find(".swiper-slide-shadow").transition(e),ae({swiper:t,duration:e,transformEl:s})},perspective:()=>!0,overwriteParams:()=>({watchSlidesProgress:!0,virtualTranslate:!t.params.cssMode})})}];return V.use(re),V})); +//# sourceMappingURL=swiper-bundle.min.js.map \ No newline at end of file diff --git a/Minecraft-Modern-Theme/list-posts.php b/Minecraft-Modern-Theme/list-posts.php index 4fe68e8..52286c7 100644 --- a/Minecraft-Modern-Theme/list-posts.php +++ b/Minecraft-Modern-Theme/list-posts.php @@ -2,6 +2,11 @@ define('WP_USE_THEMES', false); require('../../../wp-load.php'); +if ( php_sapi_name() !== 'cli' && ! current_user_can( 'manage_options' ) ) { + http_response_code( 403 ); + exit( 'Forbidden: Admin-Login erforderlich.' ); +} + $posts = get_posts(array( 'post_type' => 'mm_livestream', 'posts_per_page' => -1, diff --git a/Minecraft-Modern-Theme/webfonts/fa-brands-400.ttf b/Minecraft-Modern-Theme/webfonts/fa-brands-400.ttf new file mode 100644 index 0000000..5efb1d4 Binary files /dev/null and b/Minecraft-Modern-Theme/webfonts/fa-brands-400.ttf differ diff --git a/Minecraft-Modern-Theme/webfonts/fa-brands-400.woff2 b/Minecraft-Modern-Theme/webfonts/fa-brands-400.woff2 new file mode 100644 index 0000000..36fbda7 Binary files /dev/null and b/Minecraft-Modern-Theme/webfonts/fa-brands-400.woff2 differ diff --git a/Minecraft-Modern-Theme/webfonts/fa-regular-400.ttf b/Minecraft-Modern-Theme/webfonts/fa-regular-400.ttf new file mode 100644 index 0000000..838b4e2 Binary files /dev/null and b/Minecraft-Modern-Theme/webfonts/fa-regular-400.ttf differ diff --git a/Minecraft-Modern-Theme/webfonts/fa-regular-400.woff2 b/Minecraft-Modern-Theme/webfonts/fa-regular-400.woff2 new file mode 100644 index 0000000..b6cabba Binary files /dev/null and b/Minecraft-Modern-Theme/webfonts/fa-regular-400.woff2 differ diff --git a/Minecraft-Modern-Theme/webfonts/fa-solid-900.ttf b/Minecraft-Modern-Theme/webfonts/fa-solid-900.ttf new file mode 100644 index 0000000..ec24749 Binary files /dev/null and b/Minecraft-Modern-Theme/webfonts/fa-solid-900.ttf differ diff --git a/Minecraft-Modern-Theme/webfonts/fa-solid-900.woff2 b/Minecraft-Modern-Theme/webfonts/fa-solid-900.woff2 new file mode 100644 index 0000000..824d518 Binary files /dev/null and b/Minecraft-Modern-Theme/webfonts/fa-solid-900.woff2 differ diff --git a/Minecraft-Modern-Theme/webfonts/fa-v4compatibility.ttf b/Minecraft-Modern-Theme/webfonts/fa-v4compatibility.ttf new file mode 100644 index 0000000..b175aa8 Binary files /dev/null and b/Minecraft-Modern-Theme/webfonts/fa-v4compatibility.ttf differ diff --git a/Minecraft-Modern-Theme/webfonts/fa-v4compatibility.woff2 b/Minecraft-Modern-Theme/webfonts/fa-v4compatibility.woff2 new file mode 100644 index 0000000..e09b5a5 Binary files /dev/null and b/Minecraft-Modern-Theme/webfonts/fa-v4compatibility.woff2 differ