<?php
/*
Plugin Name: AudioTyped UX – Chat-Style Transcripts for Podcasts
Plugin URI: https://audiotyped.com
Description: Adds speaker avatars and clean chat-style bubbles to your podcast transcripts — perfect for interviews and co-host formats.
Author: Helmut Naber, AudioTyped
Author URI: https://audiotyped.com
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: audiotyped-ux
Version: 1.5.0
*/

define( 'AUDIOTYPED_UX_VERSION', '1.5.0' );

function audiotyped_ux_defaults() {
  return [
    'audiotyped_tb_color'  => '#f3f5f7',
    'audiotyped_hb_color'  => '#6fa81e',
    'audiotyped_gb_color'  => '#4a90e2',
    'audiotyped_g2b_color' => '#9b59b6',
    'audiotyped_hf_color'  => '#ffffff',
    'audiotyped_gf_color'  => '#ffffff',
    'audiotyped_g2f_color' => '#ffffff',

    'audiotyped_avatar'      => 12,
    'audiotyped_bubble'      => 8,
    'audiotyped_shadow_blur' => 10,

    'audiotyped_df_size'   => 18,
    'audiotyped_dc_size'   => 80,
    'audiotyped_dgap_size' => 12,
    'audiotyped_dbpv_size' => 10,
    'audiotyped_dbph_size' => 16,

    'audiotyped_mf_size'   => 15,
    'audiotyped_ma_size'   => 50,
    'audiotyped_md_size'   => 35,
    'audiotyped_mgap_size' => 10,
    'audiotyped_mbpv_size' => 4,
    'audiotyped_mbph_size' => 12,
	'audiotyped_hide_avatars_arrows' => 0,
  ];
}

function audiotyped_ux_get( $key ) {
  $defaults = audiotyped_ux_defaults();
  $value    = get_option( $key, null );

  if ( $value === null || $value === '' ) {
    return $defaults[ $key ] ?? '';
  }
  return $value;
}

register_activation_hook( __FILE__, function () {
  foreach ( audiotyped_ux_defaults() as $key => $default ) {
    if ( get_option( $key, null ) === null ) {
      add_option( $key, $default );
    }
  }
});

// Insert function here - before use in hooks etc.
function audiotyped_enqueue_style( $handle, $relative_path, $deps = array(), $media = 'all' ) {
  $file_path = plugin_dir_path( __FILE__ ) . $relative_path;
  $file_url  = plugin_dir_url( __FILE__ ) . $relative_path;

  $version = defined( 'AUDIOTYPED_UX_VERSION' ) ? AUDIOTYPED_UX_VERSION : '1.5.0';
  if ( file_exists( $file_path ) ) {
      $version = filemtime( $file_path );
  }

  wp_enqueue_style( $handle, $file_url, $deps, $version, $media );
}

// Prohibit direct script loading.
defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );

add_action( 'wp_enqueue_scripts', 'audiotyped_enqueue_styles' );

function audiotyped_enqueue_styles() {
  audiotyped_enqueue_style( 'at_stylesheet', 'audiotyped.css' );

if ( (int) get_option( 'audiotyped_hide_avatars_arrows', 0 ) === 1 ) {

$md_size = (int) audiotyped_ux_get( 'audiotyped_md_size' );
$md_reduced = max( 0, $md_size - 40 );

$hb = sanitize_hex_color( audiotyped_ux_get( 'audiotyped_hb_color' ) );
$gb = sanitize_hex_color( audiotyped_ux_get( 'audiotyped_gb_color' ) );
$g2b = sanitize_hex_color( audiotyped_ux_get( 'audiotyped_g2b_color' ) );

$css = "
/* ==================================================
AudioTyped UX – Hide Avatars (Frontend)
Desktop: avatar size must NOT affect spacing/height
Mobile: keep existing logic + reduce vertical spacing
Keep bubble rounding unchanged
================================================== */

/* --------------------------------------------------
DESKTOP (>= 401px)

Collapse avatar box completely (prevents taller rows)

Draw arrows on the bubble (since avatar is collapsed)
-------------------------------------------------- */
@media (min-width: 401px){

/* 1) Avatar container must not take any space */
.transcript .transcriptAvatar{
width: 0 !important;
min-width: 0 !important;
height: 0 !important;
padding: 0 !important;
margin: 0 !important;
border: 0 !important;
box-shadow: none !important;
background: none !important;
overflow: hidden !important;
flex: 0 0 0 !important;
}

/* 2) Safety: hide any image inside avatar */
.transcript .transcriptAvatar img{
display: none !important;
}

/* 3) Remove old avatar-based arrow */
.transcript .transcriptHost .transcriptAvatar:after,
.transcript .transcriptGuest .transcriptAvatar:after,
.transcript .transcriptGuest.transcriptGuest2 .transcriptAvatar:after{
content: none !important;
}

/* 4) Remove gap that only existed between bubble and avatar */
.transcript .transcriptHost .transcriptSpeaking{
margin-left: 0 !important;
position: relative !important;
}
.transcript .transcriptGuest .transcriptSpeaking,
.transcript .transcriptGuest.transcriptGuest2 .transcriptSpeaking{
margin-right: 0 !important;
position: relative !important;
}

/* 5) Bubble arrows (desktop) */
.transcript .transcriptHost .transcriptSpeaking:before{
content: '';
position: absolute;
left: -12px;
top: 18px;
width: 0;
height: 0;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
border-right: 12px solid {$hb};
z-index: 2;
}

.transcript .transcriptGuest .transcriptSpeaking:before{
content: '';
position: absolute;
right: -12px;
top: 18px;
width: 0;
height: 0;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
border-left: 12px solid {$gb};
z-index: 2;
}

.transcript .transcriptGuest.transcriptGuest2 .transcriptSpeaking:before{
content: '';
position: absolute;
right: -12px;
top: 18px;
width: 0;
height: 0;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
border-left: 12px solid {$g2b};
z-index: 2;
}
}

/* --------------------------------------------------
MOBILE (<= 400px)
Keep your current mobile rendering.
Only reduce vertical spacing by 40px.
-------------------------------------------------- */
@media (max-width: 400px){

  /* Hide avatar visuals on mobile, but KEEP avatar box for layout + arrows */
  .transcript .transcriptAvatar{
    background-image: none !important;
    background-color: transparent !important;
    box-shadow: none !important;
  }

  .transcript .transcriptAvatar img{
    display: none !important;
  }

  /* Reduce vertical spacing (same logic as before) */
  .transcript .transcriptInterview li{
    padding-top: {$md_reduced}px !important;
    padding-bottom: {$md_reduced}px !important;
  }
}
";
wp_add_inline_style( 'at_stylesheet', $css );
}
}

// Admin stylesheets
add_action('admin_enqueue_scripts', 'audiotyped_admin_styles');

// Admin stylesheets for WP Backend Plugin Settings
if ( ! function_exists( 'audiotyped_admin_styles' ) ) {
  function audiotyped_admin_styles( $hook ) {
    if ( $hook !== 'settings_page_audiotyped-settings' ) {
      return;
    }	  	  		  
    // Optional: load only on plugin settings page
    if ($hook !== 'settings_page_audiotyped-settings') {
         return;
    }
 
    wp_enqueue_style(
        'audiotyped-admin-css',
        plugin_dir_url(__FILE__) . 'assets/admin-style.css',
        array(),
        AUDIOTYPED_UX_VERSION
    );
    wp_enqueue_style(
       'audiotyped-admin-transcript-css',
       plugin_dir_url(__FILE__) . 'audiotyped.css',
       array(),
       AUDIOTYPED_UX_VERSION
    );
 
    // Transcript layout JS (same as frontend)
    wp_enqueue_script(
        'audiotyped-transcript-js',
        plugin_dir_url(__FILE__) . 'audiotyped.js',
        array('jquery'),
        AUDIOTYPED_UX_VERSION,
        true
    );
    wp_localize_script( 'audiotyped-transcript-js', 'vname',  array(
       'tbcolor' => audiotyped_ux_get( 'audiotyped_tb_color' ),
       'gbcolor' => audiotyped_ux_get( 'audiotyped_gb_color' ),
       'hbcolor' => audiotyped_ux_get( 'audiotyped_hb_color' ),
       'gfcolor' => audiotyped_ux_get( 'audiotyped_gf_color' ),
       'hfcolor' => audiotyped_ux_get( 'audiotyped_hf_color' ),        
       'aradius' => audiotyped_ux_get( 'audiotyped_avatar' ),
       'bcorner' => audiotyped_ux_get( 'audiotyped_bubble' ),
       'mfsize' => audiotyped_ux_get( 'audiotyped_mf_size' ),
       'dfsize' => audiotyped_ux_get( 'audiotyped_df_size' ),
       'sradius' => audiotyped_ux_get( 'audiotyped_shadow_blur' ),
       'dgapsize' => audiotyped_ux_get( 'audiotyped_dgap_size' ),
       'dcsize' => audiotyped_ux_get( 'audiotyped_dc_size' ),
       'masize' => audiotyped_ux_get( 'audiotyped_ma_size' ),
       'mdsize' => audiotyped_ux_get( 'audiotyped_md_size' ),
       'mbpvsize' => audiotyped_ux_get( 'audiotyped_mbpv_size' ),
       'mbphsize' => audiotyped_ux_get( 'audiotyped_mbph_size' ),
       'dbpvsize' => audiotyped_ux_get( 'audiotyped_dbpv_size' ),
       'dbphsize' => audiotyped_ux_get( 'audiotyped_dbph_size' ),
       'mgapsize' => audiotyped_ux_get( 'audiotyped_mgap_size' ),
       'g2bcolor' => audiotyped_ux_get( 'audiotyped_g2b_color' ),
       'g2fcolor' => audiotyped_ux_get( 'audiotyped_g2f_color' )
    ) );
 
    // Copy-to-clipboard JS for the Transcript HTML tab
    wp_enqueue_script(
        'audiotyped-transcript-copy',
        plugin_dir_url(__FILE__) . 'assets/transcript-copy.js',
        array(),
        AUDIOTYPED_UX_VERSION,
        true
    );	
 } 
}

// Add the Color Picker
add_action( 'admin_enqueue_scripts', 'mw_enqueue_color_picker' );
function mw_enqueue_color_picker( $hook_suffix ) {
    //  check that $hook_suffix is appropriate for your admin page
    wp_enqueue_style( 'wp-color-picker' );
    wp_enqueue_script( 'my-script-handle', plugins_url('colorpicker.js', __FILE__ ), array( 'wp-color-picker' ), AUDIOTYPED_UX_VERSION, true );
}

// Call audiotyped_settings_menu function to load plugin menu in dashboard
add_action( 'admin_menu', 'audiotyped_settings_menu' );

// Create WordPress admin menu
if( !function_exists("audiotyped_settings_menu") )
{
function audiotyped_settings_menu(){

  $page_title = 'AudioTyped UX';
  $menu_title = 'AudioTyped UX';
  $capability = 'manage_options';
  $menu_slug  = 'audiotyped-settings';
  $function   = 'audiotyped_settings_page';
  $icon_url   = 'dashicons-testimonial';
  $position   = 4;
 
  add_submenu_page( 'options-general.php', $page_title, $menu_title, $capability, $menu_slug, $function );

  // Call update_audiotyped_settings function to update database
  add_action( 'admin_init', 'update_audiotyped_settings' );

}
}

// Create function to register plugin settings in the database
if( !function_exists("update_audiotyped_settings") )
{
function update_audiotyped_settings() {
  register_setting( 'audiotyped-settings', 'audiotyped_tb_color', [
    'sanitize_callback' => 'sanitize_hex_color', // Safe: sanitizes #hex values
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_gb_color', [
    'sanitize_callback' => 'sanitize_hex_color',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_hb_color', [
    'sanitize_callback' => 'sanitize_hex_color',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_gf_color', [
    'sanitize_callback' => 'sanitize_hex_color',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_hf_color', [
    'sanitize_callback' => 'sanitize_hex_color',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_avatar', [
    'sanitize_callback' => 'intval',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_bubble', [
    'sanitize_callback' => 'intval',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_mf_size', [
    'sanitize_callback' => 'intval',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_df_size', [
    'sanitize_callback' => 'intval',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_shadow_blur', [
    'sanitize_callback' => 'intval',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_dgap_size', [
    'sanitize_callback' => 'intval',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_dc_size', [
    'sanitize_callback' => 'intval',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_ma_size', [
    'sanitize_callback' => 'intval',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_md_size', [
    'sanitize_callback' => 'intval',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_mbpv_size', [
    'sanitize_callback' => 'intval',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_mbph_size', [
    'sanitize_callback' => 'intval',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_dbpv_size', [
    'sanitize_callback' => 'intval',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_dbph_size', [
    'sanitize_callback' => 'intval',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_mgap_size', [
    'sanitize_callback' => 'intval',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_g2b_color', [
    'sanitize_callback' => 'sanitize_hex_color',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_g2f_color', [
    'sanitize_callback' => 'sanitize_hex_color',
  ] );
  register_setting( 'audiotyped-settings', 'audiotyped_hide_avatars_arrows', [
    'sanitize_callback' => 'intval',
  ] );
}
}

function audiotyped_settings_page() {
  // Non-critical: Tab selection, no write operation - therefore no nonce necessary
  $active_tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'settings';
  ?>
  <div class="wrap">
      <h1>Podcast Transcript Interview UX</h1>
      <h2 class="nav-tab-wrapper">
          <a href="?page=audiotyped-settings&tab=settings" class="nav-tab <?php echo $active_tab == 'settings' ? 'nav-tab-active' : ''; ?>">Settings</a>
          <a href="?page=audiotyped-settings&tab=preview" class="nav-tab <?php echo $active_tab == 'preview' ? 'nav-tab-active' : ''; ?>">Preview</a>
          <a href="?page=audiotyped-settings&tab=transcript_html" class="nav-tab <?php echo $active_tab == 'transcript_html' ? 'nav-tab-active' : ''; ?>">Transcript HTML</a>
          <a href="?page=audiotyped-settings&tab=help" class="nav-tab <?php echo $active_tab == 'help' ? 'nav-tab-active' : ''; ?>">Help</a>
      </h2>

      <div class="tab-content">
          <?php
          switch ($active_tab) {
              case 'help':
                  audiotyped_help_tab();
                  break;
              case 'preview':
                  audiotyped_preview_tab();
                  break;
              case 'transcript_html':
                  audiotyped_transcriptux_transcript_html_tab();
                  break;
              case 'settings':
              default:
                  audiotyped_settings_tab();
                  break;
          }
          ?>
      </div>
  </div>
  <?php
}

// Create WordPress plugin page
if( !function_exists("audiotyped_settings_tab") )
{
function audiotyped_settings_tab(){       
?>             
  <form method="post" action="options.php">
    <?php settings_fields( 'audiotyped-settings' ); ?>
    <?php do_settings_sections( 'audiotyped-settings' ); ?>
    <table class="form-table">
      <p>Here you can make the settings for the individual design of your podcast interview transcripts.</p>

     <tr valign="top">
	<th scope="row">
		<?php echo esc_html__( 'Hide avatars', 'audiotyped-ux' ); ?>
	</th>
	<td>
		<label>
			<input
				type="checkbox"
				name="audiotyped_hide_avatars_arrows"
				value="1"
				<?php checked( 1, (int) get_option( 'audiotyped_hide_avatars_arrows', 0 ) ); ?>
			/>
			<?php echo esc_html__(
			'Hide avatar images while keeping arrows and bubble spacing',
			'audiotyped-ux'
			); ?>
		</label>
	</td>
    </tr>

      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-01-transcript-color.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
          Transcript color               
        </span>	        
      </th>
      <td><input type="text" name="audiotyped_tb_color" value="<?php echo esc_attr( audiotyped_ux_get('audiotyped_tb_color') ); ?>" class="my-color-field" /></td>
      </tr> 
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-02-host-bubble-color.png'); ?>"
               alt="Vorschau der Transkriptfarbe">
          Host bubble color            
        </span>	          
      </th>
      <td><input type="text" name="audiotyped_hb_color" value="<?php echo esc_attr( get_option('audiotyped_hb_color') ); ?>" class="my-color-field" /></td>
      </tr>    
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-03-guest-bubble-color.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
          Guest bubble color
        </span>	        
      </th>
      <td><input type="text" name="audiotyped_gb_color" value="<?php echo esc_attr( audiotyped_ux_get('audiotyped_gb_color') ); ?>" class="my-color-field" /></td>
      </tr>
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
          <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-03a-guest2-bubble-color.png' ); ?>"
               alt="Preview of the Guest 2 bubble color">
          Guest 2 bubble color
        </span>
      </th>
      <td><input type="text" name="audiotyped_g2b_color" value="<?php echo esc_attr( get_option('audiotyped_g2b_color') ); ?>" class="my-color-field" /></td>
      </tr>
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">          
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-04-host-font-color.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
          Host font color
        </span>	        
      </th>
      <td><input type="text" name="audiotyped_hf_color" value="<?php echo esc_attr( audiotyped_ux_get('audiotyped_hf_color') ); ?>" class="my-color-field" /></td>
      </tr>    
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-05-guest-font-color.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
          Guest font color
        </span>	      
      </th>
      <td><input type="text" name="audiotyped_gf_color" value="<?php echo esc_attr( get_option('audiotyped_gf_color') ); ?>" class="my-color-field" /></td>
      </tr>
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
          <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-05a-guest2-font-color.png' ); ?>"
               alt="Preview of the Guest 2 font color">
          Guest 2 font color
        </span>
      </th>
      <td><input type="text" name="audiotyped_g2f_color" value="<?php echo esc_attr( audiotyped_ux_get('audiotyped_g2f_color') ); ?>" class="my-color-field" /></td>
      </tr>

      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">          
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-06-avatar-rounding.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
          Avatar rounding
        </span>	        
      </th>
      <td><input type="number" min="0" max="50" name="audiotyped_avatar" value="<?php echo esc_attr( get_option('audiotyped_avatar') ); ?>"/> (Numbers from 0 to 50)</td>
      </tr>
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-07-bubble-rounding.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
          Bubble rounding
        </span>	          
      </th>
      <td><input type="number" min="0" max="10" name="audiotyped_bubble" value="<?php echo esc_attr( audiotyped_ux_get('audiotyped_bubble') ); ?>"/> (Numbers from 0 to 10)</td>
      </tr>    
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">          
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-08-bubble-shadow-blur.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
          Bubble shadow blur
        </span>	       
      </th>
      <td><input type="number" min="0" max="25" name="audiotyped_shadow_blur" value="<?php echo esc_attr( get_option('audiotyped_shadow_blur') ); ?>"/> (Numbers from 0 to 25)</td>
      </tr>   
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-09-d-avatar-size.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
          💻 Avatar size
        </span>	        
      </th>
      <td><input type="number" min="45" max="100" name="audiotyped_dc_size" value="<?php echo esc_attr( audiotyped_ux_get('audiotyped_dc_size') ); ?>"/> (from 45 to 100 px)</td>
      </tr>  
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-10-d-font-size.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
          💻 Font size
        </span>	       
      </th>
      <td><input type="number" min="12" max="30" name="audiotyped_df_size" value="<?php echo esc_attr( get_option('audiotyped_df_size') ); ?>"/> (from 12 to 30 px)</td>
      </tr>  
      <tr valign="top">
      <th scope="row">       
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-11-d-gap-bubble-avatar.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
          💻 Gap Bubble Avatar
        </span>	       
      </th>
      <td><input type="number" min="0" max="30" name="audiotyped_dgap_size" value="<?php echo esc_attr( audiotyped_ux_get('audiotyped_dgap_size') ); ?>"/> (from 0 to 30 px)</td>
      </tr>  
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-12-d-bubble-padding-vertical.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
          💻 Bubble Padding ⇅
        </span>      
      </th>
      <td><input type="number" min="0" max="40" name="audiotyped_dbpv_size" value="<?php echo esc_attr( get_option('audiotyped_dbpv_size') ); ?>"/> (from 0 to 40 px)</td>
      </tr>
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-13-d-bubble-padding-horizontal.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
          💻 Bubble Padding ⇆
        </span>        
      </th>
      <td><input type="number" min="6" max="50" name="audiotyped_dbph_size" value="<?php echo esc_attr( audiotyped_ux_get('audiotyped_dbph_size') ); ?>"/> (from 6 to 50 px)</td>
      </tr>  
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-14-mobile-avatar-size.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
          📱 Avatar size
        </span>          
      </th>
      <td><input type="number" min="40" max="80" name="audiotyped_ma_size" value="<?php echo esc_attr( get_option('audiotyped_ma_size') ); ?>"/> (from 40 to 80 px)</td>
      </tr> 
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-15-mobile-font-size.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
          📱 Font size
        </span>          
      </th>
      <td><input type="number" min="10" max="20" name="audiotyped_mf_size" value="<?php echo esc_attr( audiotyped_ux_get('audiotyped_mf_size') ); ?>"/> (from 10 to 20 px)</td>
      </tr>  
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-16-mobile-gap-bubble-avatar.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
            📱 Gap Bubble Avatar
        </span>        
      </th>
      <td><input type="number" min="0" max="20" name="audiotyped_mgap_size" value="<?php echo esc_attr( get_option('audiotyped_mgap_size') ); ?>"/> (from 0 to 20 px)</td>
      </tr>  
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-17-mobile-distance-vertical.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
            📱 Distance ⇅
        </span>          
      </th>
      <td><input type="number" min="30" max="80" name="audiotyped_md_size" value="<?php echo esc_attr( audiotyped_ux_get('audiotyped_md_size') ); ?>"/> (from 30 to 80 px)</td>
      </tr>   
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-18-mobile-bubble-padding-vertical.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
            📱 Bubble Padding ⇅
        </span>        
      </th>
      <td><input type="number" min="0" max="30" name="audiotyped_mbpv_size" value="<?php echo esc_attr( get_option('audiotyped_mbpv_size') ); ?>"/> (from 0 to 30 px)</td>
      </tr>
      <tr valign="top">
      <th scope="row">
        <span class="tooltip-wrapper">
	        <span class="tooltip-icon">?</span>
          <img class="tooltip-image"
               src="<?php echo esc_url( plugin_dir_url(__FILE__) . 'assets/audiotyped-ux-tooltip-19-mobile-bubble-padding-horizontal.png' ); ?>"
               alt="Vorschau der Transkriptfarbe">
            📱 Bubble Padding ⇆
        </span>        
      </th>
      <td><input type="number" min="6" max="30" name="audiotyped_mbph_size" value="<?php echo esc_attr( audiotyped_ux_get('audiotyped_mbph_size') ); ?>"/> (from 6 to 30 px)</td>
      </tr>    
    </table>
  <?php submit_button(); ?>
  </form>
<?php
}
}

function audiotyped_preview_tab() {
    // All relevant options
	$tscrpttbcolor   = audiotyped_ux_get('audiotyped_tb_color');
	$tscrptgbcolor   = audiotyped_ux_get('audiotyped_gb_color');
	$tscrpthbcolor   = audiotyped_ux_get('audiotyped_hb_color');
	$tscrptgfcolor   = audiotyped_ux_get('audiotyped_gf_color');
	$tscrpthfcolor   = audiotyped_ux_get('audiotyped_hf_color');

	$tscrptaradius   = (int) audiotyped_ux_get('audiotyped_avatar');
	$tscrptbcorner   = (int) audiotyped_ux_get('audiotyped_bubble');
	$tscrptmfsize    = (int) audiotyped_ux_get('audiotyped_mf_size');
	$tscrptdfsize    = (int) audiotyped_ux_get('audiotyped_df_size');
	$tscrptsradius   = (int) audiotyped_ux_get('audiotyped_shadow_blur');
	$tscrptdgapp     = (int) audiotyped_ux_get('audiotyped_dgap_size');
	$tscrptdcsize    = (int) audiotyped_ux_get('audiotyped_dc_size');
	$tscrptmasize    = (int) audiotyped_ux_get('audiotyped_ma_size');
	$tscrptmdsize    = (int) audiotyped_ux_get('audiotyped_md_size');
	$tscrptmbpvsize  = (int) audiotyped_ux_get('audiotyped_mbpv_size');
	$tscrptmbphsize  = (int) audiotyped_ux_get('audiotyped_mbph_size');
	$tscrptdbpvsize  = (int) audiotyped_ux_get('audiotyped_dbpv_size');
	$tscrptdbphsize  = (int) audiotyped_ux_get('audiotyped_dbph_size');
	$tscrptmgapp     = (int) audiotyped_ux_get('audiotyped_mgap_size');
	$tscrptg2bcolor  = audiotyped_ux_get('audiotyped_g2b_color');
	$tscrptg2fcolor  = audiotyped_ux_get('audiotyped_g2f_color');
?>
    <!-- Styling based on setting -->
<style>
.transcript {
  margin: 20px auto;
  padding: 10px;
  background-color: <?php echo esc_attr($tscrpttbcolor); ?> !important;
  border-radius: 6px;
  display: table;
  float: none;
}
.transcriptInterview {
  list-style: none;
  margin: 24px 0px 0px 0px;
  padding: 0px;
}
.transcriptInterview p {
  font-size: <?php echo esc_attr($tscrptdfsize); ?>px !important;
}
.transcript ol {
  margin-left: 0px !important;
  padding-left: 0px !important;
}
.transcriptInterview li {
  padding: 0.5rem;
  display: flex;
  clear: both;
}
.transcriptInner ul {
  list-style: disc !important;
  font-size: 18px !important;
  margin-bottom: 0px !important;
}	

.transcriptInner ul > li {
	font-size: <?php echo esc_attr($tscrptdfsize); ?>px !important;
	display: list-item !important;
}

.transcriptInner ol {
	list-style: decimal !important;
	font-size:  <?php echo esc_attr($tscrptdfsize); ?>px !important;
	margin-left: 20px !important;
	margin-bottom: 0px !important;
}	
.transcriptInner ol > li {
	font-size:  <?php echo esc_attr($tscrptdfsize); ?>px !important;
	list-style-type: decimal !important;
	display: list-item !important;
}
.transcriptBetween {
	margin: <?php echo esc_attr($tscrptdfsize); ?>px;
	font-size: 1em !important;
}
.transcriptBetween p {
	font-size: <?php echo esc_attr($tscrptdfsize); ?>px !important;
	margin: 0 0 10px !important;
}
.transcriptInterview .transcriptAvatar {
  position: relative;
	padding-top: 12px;
	padding-left: 6px;
	padding-right: 6px;
  height: <?php echo esc_attr($tscrptdcsize); ?>px; 
	min-width: <?php echo esc_attr($tscrptdcsize); ?>px;  
  border-radius: <?php echo esc_attr($tscrptaradius); ?>%;  
  box-shadow: 4px 4px <?php echo esc_attr($tscrptsradius); ?>px -6px rgba(0,0,0,0.25);
  background-size: cover;
  background-position: top center;
	top: 0px;
}

.transcriptInterview .transcriptAvatar img {
  display: block;
  border-radius: <?php echo esc_attr($tscrptaradius); ?>%; 
  max-width: 45px;
}
.transcriptHost{
	border-left: 0px solid #777777;  
  float: left;
}
    .transcriptHost .transcriptSpeaking {
      order: 1;
      border-radius: <?php echo esc_attr($tscrptbcorner) ?>px;
	    background-color: <?php echo esc_attr($tscrpthbcolor); ?> !important; 
      box-shadow: 4px 4px <?php echo esc_attr($tscrptsradius); ?>px -6px rgba(0,0,0,0.25);
      color: <?php echo esc_attr($tscrpthfcolor); ?>; 
      margin-left:<?php echo esc_attr($tscrptdgapp); ?>px; 
      z-index: 1;
    }

    .transcriptHost .transcriptAvatar:after {
  content: "";
  position: absolute;
  right: 0;
  width: 0;
  height: 0;
  border-left: 6px solid transparent;
	border-top: 6px solid <?php echo esc_attr($tscrpthbcolor); ?>;
	border-bottom: 6px solid transparent;
	border-right: 6px solid <?php echo esc_attr($tscrpthbcolor); ?>;
  margin-top: 0px;	
  margin-right: -<?php echo esc_attr($tscrptdgapp); ?>px;
  z-index: 2;
}
  
.transcriptGuest {
  justify-content: flex-start;
  align-items: flex-start;
	border-left: 0px dotted  #777777;
  float: right;
}
.transcriptGuest .transcriptSpeaking {
  order: 1;
  border-radius: <?php echo esc_attr($tscrptbcorner) ?>px;
	background-color: <?php echo esc_attr($tscrptgbcolor) ?> !important; 
  box-shadow: -4px 4px <?php echo esc_attr($tscrptsradius); ?>px -6px rgba(0,0,0,0.25);
  color: <?php echo esc_attr($tscrptgfcolor); ?>;
  margin-right: <?php echo esc_attr($tscrptdgapp); ?>px; 
  z-index: 1;
}
.transcriptGuest .transcriptAvatar {
  order: 2;
}
.transcriptGuest .transcriptAvatar:after{
  content: "";
  position: absolute;
  left: 0;
  width: 0;
  height: 0;
  border-top: 6px solid <?php echo esc_attr($tscrptgbcolor); ?>;
  border-bottom: 6px solid transparent;
  border-left: 6px solid <?php echo esc_attr($tscrptgbcolor); ?>;
  border-right: 6px solid transparent;
  margin-top: 0px;
  margin-left: -<?php echo esc_attr($tscrptdgapp); ?>px;
  z-index: 2;
}
.transcriptSpeaking {
  background: #f6f6f6;
  padding: 10px;
  margin-bottom: 16px;
  border-radius: <?php echo esc_attr($tscrptbcorner); ?>px; 
  box-shadow: 2px 2px 2px 0px rgba(0,0,0,.10);
	min-width: 180px;
  padding: <?php echo esc_attr($tscrptdbpvsize); ?>px <?php echo esc_attr($tscrptdbphsize); ?>px;
}
.transcriptSpeaking p {
  font-size: <?php echo esc_attr($tscrptdfsize); ?>px !important;
  margin: 12px 0 12px 0;
}
.transcriptSpeaking p:first-of-type {
  margin-top: 0px !important;
}
.transcriptHost .transcriptSpeaking strong {
    font-size: <?php echo esc_attr($tscrptdfsize); ?>px !important;
}
.transcriptGuest .transcriptSpeaking strong {
    font-size: <?php echo esc_attr($tscrptdfsize); ?>px !important;
}      
.transcriptHost code {
  background: none;
  color: <?php echo esc_attr($tscrpthfcolor); ?>;
  font-size: 0.825em;
  opacity: 0.5;
}
.transcriptGuest code {
  background: none;
  color: <?php echo esc_attr($tscrptgfcolor); ?>;
  font-size: 0.825em;
  opacity: 0.5;
}
@media (max-width: 400px)
	{ 
.transcript {
  margin: 20px auto;
  padding-top: 30px;
  word-break: break-all;
  word-break: break-word;
  hyphens: auto;
}
.transcriptInterview {
  list-style: none;
  margin: 24px 0 0 0 !important;
  padding: 0 0 50px 0;
}
.transcript ol {
  margin-left: 0px !important;
  padding-left: 0px !important;
}
.transcriptInterview li {
  padding: <?php echo esc_attr($tscrptmdsize); ?>px 0px <?php echo esc_attr($tscrptmdsize); ?>px 0px;
  display: flex;
}
.transcriptInterview .transcriptHost .transcriptAvatar {
  max-width: 80px;
  min-width: <?php echo esc_attr($tscrptmasize); ?>px;
  position: relative;
  padding-top: 0px;
  padding-left: 0px;
  padding-right: 0px;
  height: <?php echo esc_attr($tscrptmasize); ?>px;
  width: <?php echo esc_attr($tscrptmasize); ?>px;
  border-radius: <?php echo esc_attr($tscrptaradius); ?>%;
  box-shadow: 4px 4px <?php echo esc_attr($tscrptsradius); ?>px -6px rgba(0,0,0,0.25);
  background-size: cover;
  background-position: top center;
  top: -<?php echo esc_attr($tscrptmasize); ?>px;
  left: 0;
}
.transcriptInterview .transcriptAvatar img {
  display: block;
  border-radius: <?php echo esc_attr($tscrptaradius); ?>%;
  max-width: 28px;
}  
.transcriptHost{
	border-left: 0px solid #777777;
}
.transcriptHost .transcriptSpeaking {
  order: 1;
  border-radius: var(--tscrptbcorner);
  color: var(--tscrpthfcolor);
  margin-left: -<?php echo esc_attr($tscrptmasize); ?>px;
  z-index: 1;
}
.transcriptHost .transcriptAvatar::after {
    content: "";
    position: absolute;
    bottom: 0px;
    border-style: solid;
    border-width: 0 5px 10px 5px;
    border-color: transparent transparent <?php echo esc_attr($tscrpthbcolor); ?> transparent;
    border-top: 6px solid transparent;
    border-bottom: 6px solid <?php echo esc_attr($tscrpthbcolor); ?>;
    border-left: 6px solid <?php echo esc_attr($tscrpthbcolor); ?>;
    border-right: 6px solid transparent;
    margin-right: 0px;
    margin-bottom: -<?php echo esc_attr($tscrptmgapn); ?>px;
    z-index: 2;
}     
.transcriptGuest {
  justify-content: flex-start;
  align-items: flex-start;
	border-left: 0px dotted  #777777;
}
.transcriptGuest .transcriptSpeaking {
  order: 1;
  border-radius: <?php echo esc_attr($tscrptbcorner); ?>px;
  color: <?php echo esc_attr($tscrptgfcolor); ?>;
  margin-right: -<?php echo esc_attr($tscrptmasize); ?>px;
  z-index: 1;
}
.transcriptInterview .transcriptGuest .transcriptAvatar {
  order: 2;
  max-width: 80px;
  min-width: <?php echo esc_attr($tscrptmasize); ?>px;
  position: relative;
  padding-top: 0px;
  padding-left: 0px;
  padding-right: 0px;
  height: <?php echo esc_attr($tscrptmasize); ?>px;
  width: <?php echo esc_attr($tscrptmasize); ?>px;
  border-radius: <?php echo esc_attr($tscrptaradius); ?>%;
  box-shadow: 4px 4px <?php echo esc_attr($tscrptsradius); ?>px -6px rgba(0,0,0,0.25);
  background-size: cover;
  background-position: top center;
  top: -<?php echo esc_attr($tscrptmasize); ?>px;
  right: 0;
}
.transcriptGuest .transcriptAvatar:after{
    content: "";
    position: absolute;
    bottom: 0px;
    border-style: solid;
    border-width: 0 5px 10px 5px;
    border-color: transparent transparent <?php echo esc_attr($tscrptgbcolor); ?> transparent;
    border-top: 6px solid transparent;
    border-bottom: 6px solid <?php echo esc_attr($tscrptgbcolor); ?>;
    border-left: 6px solid transparent;
    border-right: 6px solid <?php echo esc_attr($tscrptgbcolor); ?>;
    margin-left: 0px;
    margin-bottom: -var(--tscrptmgapn);
    z-index: 2;
}
.transcriptSpeaking {
  background: #f6f6f6;
  padding: 6px 6px 6px 6px;
  margin-bottom: 10px;
  margin-top: <?php echo esc_attr($tscrptmgapp); ?>px;
  border-radius: <?php echo esc_attr($tscrptbcorner); ?>px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
  padding: <?php echo esc_attr($tscrptmbpvsize); ?>px <?php echo esc_attr($tscrptmbphsize); ?>px;
}
.transcriptInterview .transcriptSpeaking p {
  font-size: <?php echo esc_attr($tscrptmfsize); ?>px !important;
  margin: 12px 0 12px 0;
}
.transcriptHost .transcriptSpeaking strong {
  font-size: <?php echo esc_attr($tscrptmfsize); ?>px !important;
}
.transcriptGuest .transcriptSpeaking strong {
  font-size: <?php echo esc_attr($tscrptmfsize); ?>px !important;
}  
}
/* Avatar preview images for transcript preview */
<?php
    $avatars_base_url = plugin_dir_url( __FILE__ ) . 'assets/';
    $host_avatar_url  = $avatars_base_url . 'avatar-m-l-002.jpg';
    $guest_avatar_url = $avatars_base_url . 'avatar-w-l-008.jpg';
?>
.transcriptHost .transcriptAvatar {
  background-image: url("<?php echo esc_url( $host_avatar_url ); ?>");
}
.transcriptGuest .transcriptAvatar {
  background-image: url("<?php echo esc_url( $guest_avatar_url ); ?>");
}


/* ==================================================
   AudioTyped UX – Hide Avatars (Preview)
   Desktop: remove avatar gap + keep arrows (on bubble)
   Mobile: keep your current mobile logic (unchanged)
   ================================================== */
<?php if ( (int) get_option( 'audiotyped_hide_avatars_arrows', 0 ) === 1 ) : ?>

/* -----------------------------
   DESKTOP (>= 401px)
   - collapse avatar box (no gap)
   - move arrows from avatar to bubble
------------------------------ */
@media (min-width: 401px){

  /* 1) Avatar container must not take any space */
  .transcript .transcriptAvatar{
    width: 0 !important;
    min-width: 0 !important;
    height: 0 !important;
    padding: 0 !important;
    margin: 0 !important;
    border: 0 !important;
    box-shadow: none !important;
    background: none !important;
    overflow: hidden !important;
    flex: 0 0 0 !important;
  }

  /* 2) Safety: hide any image inside avatar */
  .transcript .transcriptAvatar img{
    display: none !important;
  }

  /* 3) Remove avatar-based arrows */
  .transcript .transcriptHost .transcriptAvatar:after,
  .transcript .transcriptGuest .transcriptAvatar:after,
  .transcript .transcriptGuest.transcriptGuest2 .transcriptAvatar:after{
    content: none !important;
  }

  /* 4) Remove bubble gap that used to sit next to avatar */
  .transcript .transcriptHost .transcriptSpeaking{
    margin-left: 0 !important;
    position: relative !important;
  }
  .transcript .transcriptGuest .transcriptSpeaking,
  .transcript .transcriptGuest.transcriptGuest2 .transcriptSpeaking{
    margin-right: 0 !important;
    position: relative !important;
  }

  /* 5) Draw arrows on the bubble (Preview desktop) */
  .transcript .transcriptHost .transcriptSpeaking:before{
    content: '';
    position: absolute;
    left: -12px;
    top: 18px;
    width: 0;
    height: 0;
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
    border-right: 12px solid <?php echo esc_attr( $tscrpthbcolor ); ?>;
    z-index: 2;
  }

  .transcript .transcriptGuest .transcriptSpeaking:before{
    content: '';
    position: absolute;
    right: -12px;
    top: 18px;
    width: 0;
    height: 0;
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
    border-left: 12px solid <?php echo esc_attr( $tscrptgbcolor ); ?>;
    z-index: 2;
  }

  .transcript .transcriptGuest.transcriptGuest2 .transcriptSpeaking:before{
    content: '';
    position: absolute;
    right: -12px;
    top: 18px;
    width: 0;
    height: 0;
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
    border-left: 12px solid <?php echo esc_attr( $tscrptg2bcolor ); ?>;
    z-index: 2;
  }
}

/* -----------------------------
   MOBILE (<= 400px)
   keep your existing preview mobile behavior,
   only reduce vertical spacing by 40px (as you already had)
------------------------------ */
@media (max-width: 400px){
  .transcript .transcriptInterview li{
    padding-top: calc(<?php echo esc_attr( $tscrptmdsize ); ?>px - 40px) !important;
    padding-bottom: calc(<?php echo esc_attr( $tscrptmdsize ); ?>px - 40px) !important;
  }
  .transcriptInterview{
    margin: 0px !important;
  }

  /* keep avatar box for layout/arrows on mobile, but hide visuals */
  .transcript .transcriptAvatar{
    background-image: none !important;
    background-color: transparent !important;
    box-shadow: none !important;
  }
  .transcript .transcriptAvatar img{
    display: none !important;
  }
}

<?php endif; ?>

    </style>
<div class='transcript'><ol class='transcriptInterview'>
    <li class='transcriptHost'>
        <div class='transcriptAvatar'></div>
        <div class='transcriptSpeaking'><strong>Host Name:</strong><p>Hello and welcome to this episode.</p></div>
    </li>
    <li class='transcriptGuest'>
        <div class='transcriptAvatar'></div>
        <div class='transcriptSpeaking'><strong>Guest Name:</strong><p>It's a pleasure for me to be here.</p></div>
    </li>
</ol></div>
  <?php
}

function audiotyped_normalize_speaker_name( $name ) {
    $name = sanitize_text_field( wp_unslash( $name ) );
    $name = trim( $name );

    // Remove one or multiple trailing colons (incl. optional whitespace):
    $name = preg_replace( '/\s*:+\s*$/u', '', $name );

    // Collapse multiple spaces into a single space
    $name = preg_replace( '/\s+/u', ' ', $name );

    return $name;
}

function audiotyped_transcriptux_transcript_html_tab() {
  $transcript      = '';
  $host_name       = '';
  $guest_name      = '';
  $guest2_name     = '';
  $host_img        = '';
  $guest_img       = '';
  $guest2_img      = '';
  $generated_html  = '';

  if (
      isset( $_POST['audiotyped_transcriptux_submit'] )
      && isset( $_POST['_wpnonce'] )
      && check_admin_referer( 'audiotyped_transcriptux_transcript_html' )
      && current_user_can( 'manage_options' )
  ) {
      $transcript = isset( $_POST['audiotyped_transcript'] )
          ? sanitize_textarea_field( wp_unslash( $_POST['audiotyped_transcript'] ) )
          : '';

      $host_name = isset( $_POST['audiotyped_host_name'] )
          ? audiotyped_normalize_speaker_name( $_POST['audiotyped_host_name'] )
		: '';

      $guest_name = isset( $_POST['audiotyped_guest_name'] )
          ? audiotyped_normalize_speaker_name( $_POST['audiotyped_guest_name'] )
          : '';

      $guest2_name = isset( $_POST['audiotyped_guest2_name'] )
          ? audiotyped_normalize_speaker_name( $_POST['audiotyped_guest2_name'] )
          : '';

      $host_img = isset( $_POST['audiotyped_host_img'] )
          ? esc_url_raw( wp_unslash( $_POST['audiotyped_host_img'] ) )
          : '';

      $guest_img = isset( $_POST['audiotyped_guest_img'] )
          ? esc_url_raw( wp_unslash( $_POST['audiotyped_guest_img'] ) )
          : '';

      // Guest 2 Avatar URL (optional)
      $guest2_img = isset( $_POST['audiotyped_guest2_img'] )
          ? esc_url_raw( wp_unslash( $_POST['audiotyped_guest2_img'] ) )
          : '';

      // Guest 2 is optional
      if ( ! empty( $transcript ) && ! empty( $host_name ) && ! empty( $guest_name ) ) {
          $generated_html = audiotyped_transcriptux_generate_html(
              $transcript,
              $host_name,
              $guest_name,
              $host_img,
              $guest_img,
              $guest2_name,
              $guest2_img
          );
      }
  }

  ?>
  <h3>Generate HTML for Interview Transcript</h3>
  <p>Paste your plain transcript text and add host / guest data. The generated HTML can be copied into your WordPress posts.</p>

  <form method="post">
      <?php wp_nonce_field( 'audiotyped_transcriptux_transcript_html' ); ?>

      <p>
          <label for="audiotyped_host_name"><strong>Host Name:</strong></label><br>
          <input type="text" id="audiotyped_host_name" name="audiotyped_host_name"
                 value="<?php echo esc_attr( $host_name ); ?>" style="width: 100%;">
      </p>

      <p>
          <label for="audiotyped_guest_name"><strong>Guest Name:</strong></label><br>
          <input type="text" id="audiotyped_guest_name" name="audiotyped_guest_name"
                 value="<?php echo esc_attr( $guest_name ); ?>" style="width: 100%;">
      </p>

      <!-- Guest 2 Name (optional) -->
      <p>
          <label for="audiotyped_guest2_name"><strong>Guest 2 Name (optional):</strong></label><br>
          <input type="text" id="audiotyped_guest2_name" name="audiotyped_guest2_name"
                 value="<?php echo esc_attr( $guest2_name ); ?>" style="width: 100%;">
      </p>

      <p>
          <label for="audiotyped_host_img"><strong>Host Avatar URL:</strong></label><br>
          <input type="text" id="audiotyped_host_img" name="audiotyped_host_img"
                 value="<?php echo esc_url( $host_img ); ?>" style="width: 100%;">
      </p>

      <p>
          <label for="audiotyped_guest_img"><strong>Guest Avatar URL:</strong></label><br>
          <input type="text" id="audiotyped_guest_img" name="audiotyped_guest_img"
                 value="<?php echo esc_url( $guest_img ); ?>" style="width: 100%;">
      </p>

      <!-- Guest 2 Avatar URL (optional) -->
      <p>
          <label for="audiotyped_guest2_img"><strong>Guest 2 Avatar URL (optional):</strong></label><br>
          <input type="text" id="audiotyped_guest2_img" name="audiotyped_guest2_img"
                 value="<?php echo esc_url( $guest2_img ); ?>" style="width: 100%;">
      </p>

      <p><strong>Transcript Input:</strong></p>
      <p>
          <textarea id="audiotyped_transcript" name="audiotyped_transcript"
                    style="width:100%; height:200px;"><?php echo esc_textarea( $transcript ); ?></textarea>
      </p>

      <p>
          <input type="submit" class="button button-primary"
                 name="audiotyped_transcriptux_submit"
                 value="Generate HTML">
      </p>
  </form>

  <?php if ( ! empty( $generated_html ) ) : ?>
      <h2>Generated HTML:</h2>
      <p>
          <button type="button" class="button button-secondary"
                  onclick="audiotypedCopyTranscriptHtml()">Copy HTML</button>
      </p>
      <textarea id="audiotyped_generated_html"
                style="width:80%; height:400px; font-family:monospace;"><?php
          echo esc_textarea( $generated_html );
      ?></textarea>
  <?php endif; ?>

  <?php
}

if ( ! function_exists( 'audiotyped_transcriptux_generate_html' ) ) {
  /**
   * Generate HTML structure for the interview transcript.
   *
   * @param string $transcript   Raw transcript text.
   * @param string $host_name    Host display name.
   * @param string $guest_name   Guest display name.
   * @param string $host_img     Host avatar URL.
   * @param string $guest_img    Guest avatar URL.
   * @param string $guest2_name  Second guest display name (optional).
   * @param string $guest2_img   Second guest avatar URL (optional).
   *
   * @return string Generated HTML.
   */
  function audiotyped_transcriptux_generate_html( $transcript, $host_name, $guest_name, $host_img, $guest_img, $guest2_name = '', $guest2_img = '' ) {
	  $host_name   = audiotyped_normalize_speaker_name( $host_name );
	  $guest_name  = audiotyped_normalize_speaker_name( $guest_name );
	  $guest2_name = audiotyped_normalize_speaker_name( $guest2_name );
      $host_img   = esc_url( $host_img );
      $guest_img  = esc_url( $guest_img );
      $guest2_img = esc_url( $guest2_img );

      // Guest 2 gets own class transcriptGuest2
      $css  = "<style>\n";
      if ( $host_img ) {
          $css .= ".transcriptHost .transcriptAvatar { background-image: url('{$host_img}'); }\n";
      }
      if ( $guest_img ) {
          $css .= ".transcriptGuest .transcriptAvatar { background-image: url('{$guest_img}'); }\n";
      }
      if ( $guest2_img ) {
          $css .= ".transcriptGuest2 .transcriptAvatar { background-image: url('{$guest2_img}'); }\n";
      }
      $css .= "</style>\n";

      //  for speaker labels, colons
      if ( $host_name !== '' ) {
          $transcript = str_replace( $host_name . ':', '[HOST_SPEAKER_TEMP]', $transcript );
      }
      if ( $guest_name !== '' ) {
          $transcript = str_replace( $guest_name . ':', '[GUEST_SPEAKER_TEMP]', $transcript );
      }
      if ( $guest2_name !== '' ) {
          $transcript = str_replace( $guest2_name . ':', '[GUEST2_SPEAKER_TEMP]', $transcript );
      }

      // Alle the other colons
      $transcript = str_replace( ':', '[NO_SPEAKER_COLON]', $transcript );

      // Retrieve speaker labels
      if ( $host_name !== '' ) {
          $transcript = str_replace( '[HOST_SPEAKER_TEMP]', $host_name . ':', $transcript );
      }
      if ( $guest_name !== '' ) {
          $transcript = str_replace( '[GUEST_SPEAKER_TEMP]', $guest_name . ':', $transcript );
      }
      if ( $guest2_name !== '' ) {
          $transcript = str_replace( '[GUEST2_SPEAKER_TEMP]', $guest2_name . ':', $transcript );
      }

      // Split rows (Windows / Mac / Linux)
      $lines = preg_split( "/\r\n|\n|\r/", trim( $transcript ) );

      $html            = $css . "<div class='transcript'><ol class='transcriptInterview'>\n";
      $current_speaker = '';
      $current_class   = '';
      $buffer          = '';

      // Build regex patterns dynamically based on existing names
      $names = array();
      if ( $host_name !== '' ) {
          $names[] = preg_quote( $host_name, '/' );
      }
      if ( $guest_name !== '' ) {
          $names[] = preg_quote( $guest_name, '/' );
      }
      if ( $guest2_name !== '' ) {
          $names[] = preg_quote( $guest2_name, '/' );
      }

      $pattern = '';
      if ( ! empty( $names ) ) {
          $pattern = '/^(' . implode( '|', $names ) . '):\s*(.*)$/';
      }

      foreach ( $lines as $line ) {
          $line = trim( $line );
          if ( $line === '' ) {
              continue;
          }

          // New speaker row?
          if ( $pattern && preg_match( $pattern, $line, $matches ) ) {
              // flush old block
              if ( $current_speaker !== '' ) {
                  $buffer_html = nl2br( trim( $buffer ) );
                  $html       .= "    <li class='{$current_class}'>\n";
                  $html       .= "        <div class='transcriptAvatar'></div>\n";
                  $html       .= "        <div class='transcriptSpeaking'><strong>" . esc_html( $current_speaker ) . ":</strong><p>{$buffer_html}</p></div>\n";
                  $html       .= "    </li>\n";
              }

              $current_speaker = trim( $matches[1] );

              // class assignment:
              // Host -> transcriptHost
              // Guest -> transcriptGuest
              // Guest2 -> transcriptGuest transcriptGuest2 (inherits layout from Guest, can be styled separately)
              if ( $current_speaker === $host_name ) {
                  $current_class = 'transcriptHost';
              } elseif ( $current_speaker === $guest_name ) {
                  $current_class = 'transcriptGuest';
              } elseif ( $guest2_name !== '' && $current_speaker === $guest2_name ) {
                  $current_class = 'transcriptGuest transcriptGuest2';
              } else {
                  // Fallback (should not occur in practice)
                  $current_class = 'transcriptGuest';
              }

              $buffer = $matches[2];
          } else {
              // Continuation of the current speaker or free text before it
              if ( $current_speaker !== '' ) {
                  $buffer .= "\n" . $line;
              } else {
                  $html .= "        <p>" . esc_html( $line ) . "</p>\n";
              }
          }
      }

      // Flush last block
      if ( $current_speaker !== '' ) {
          $buffer_html = nl2br( trim( $buffer ) );
          $html       .= "    <li class='{$current_class}'>\n";
          $html       .= "        <div class='transcriptAvatar'></div>\n";
          $html       .= "        <div class='transcriptSpeaking'><strong>" . esc_html( $current_speaker ) . ":</strong><p>{$buffer_html}</p></div>\n";
          $html       .= "    </li>\n";
      }

      $html .= "</ol></div>\n";

      // Restore secure colons in the text
      $html = str_replace( '[NO_SPEAKER_COLON]', ':', $html );

      return $html;
  }
}

function audiotyped_help_tab() {
  echo '<p>The help section is currently being prepared and will be available shortly.</p>';
}

// Passing the values to Javascript
add_action( 'wp_enqueue_scripts', 'audiotyped_enqueue_scripts' );
function audiotyped_enqueue_scripts() {
      $file_url = plugins_url('audiotyped.js',__FILE__);
      wp_enqueue_script( 'at_javascript', $file_url, array(), AUDIOTYPED_UX_VERSION, true );
      wp_localize_script( 'at_javascript', 'vname',  array(
          'tbcolor' => get_option( 'audiotyped_tb_color' ),
          'gbcolor' => get_option( 'audiotyped_gb_color' ),
          'hbcolor' => get_option( 'audiotyped_hb_color' ),
          'gfcolor' => get_option( 'audiotyped_gf_color' ),
          'hfcolor' => get_option( 'audiotyped_hf_color' ),        
          'aradius' => get_option( 'audiotyped_avatar' ),
          'bcorner' => get_option( 'audiotyped_bubble' ),
          'mfsize' => get_option( 'audiotyped_mf_size' ),
          'dfsize' => get_option( 'audiotyped_df_size' ),
          'sradius' => get_option( 'audiotyped_shadow_blur' ),
          'dgapsize' => get_option( 'audiotyped_dgap_size' ),
          'dcsize' => get_option( 'audiotyped_dc_size' ),
          'masize' => get_option( 'audiotyped_ma_size' ),
          'mdsize' => get_option( 'audiotyped_md_size' ),
          'mbpvsize' => get_option( 'audiotyped_mbpv_size' ),
          'mbphsize' => get_option( 'audiotyped_mbph_size' ),
          'dbpvsize' => get_option( 'audiotyped_dbpv_size' ),
          'dbphsize' => get_option( 'audiotyped_dbph_size' ),
          'mgapsize' => get_option( 'audiotyped_mgap_size' ),
          'g2bcolor' => get_option( 'audiotyped_g2b_color' ),
          'g2fcolor' => get_option( 'audiotyped_g2f_color' )
));
}

?>