<?php
/**
 * 1MZ Music Player — Painel de controlo (WP Admin)
 *
 * Menu próprio "1MZ Music Player" onde o admin controla o app:
 * versão/forçar update, gate de acesso, add-ons (e quais exigem conta),
 * mensagem global, e lista de contas do leitor.
 *
 * @package 1MZ_Music_Player
 */

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

add_action( 'admin_menu', 'mp_admin_menu' );
add_action( 'admin_init', 'mp_cloud_admin_download' );
add_action( 'wp_ajax_mp_cloud_user_catalog', 'mp_cloud_admin_user_catalog' );

/** Lê vários meta.json em paralelo; o fallback usa a HTTP API do WordPress. */
function mp_cloud_admin_metadata_batch( $meta_keys ) {
    $urls = [];
    foreach ( (array) $meta_keys as $folder => $key ) {
        $url = mp_s3_presign( 'GET', $key, 300 );
        if ( $url ) {
            $urls[ (string) $folder ] = $url;
        }
    }
    $out = [];
    if ( function_exists( 'curl_multi_init' ) ) {
        foreach ( array_chunk( $urls, 24, true ) as $batch ) {
            $multi = curl_multi_init();
            $handles = [];
            foreach ( $batch as $folder => $url ) {
                $ch = curl_init( $url );
                curl_setopt_array( $ch, [
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_FOLLOWLOCATION => false,
                    CURLOPT_CONNECTTIMEOUT => 5,
                    CURLOPT_TIMEOUT        => 15,
                    CURLOPT_SSL_VERIFYPEER => true,
                    CURLOPT_HTTPHEADER     => [ 'Accept: application/json' ],
                    CURLOPT_USERAGENT      => '1MZ-Music-Cloud-Admin',
                ] );
                curl_multi_add_handle( $multi, $ch );
                $handles[ $folder ] = $ch;
            }
            do {
                $status = curl_multi_exec( $multi, $running );
                if ( $running ) {
                    $selected = curl_multi_select( $multi, 1.0 );
                    if ( -1 === $selected ) {
                        usleep( 10000 );
                    }
                }
            } while ( $running && CURLM_OK === $status );
            foreach ( $handles as $folder => $ch ) {
                if ( 200 === (int) curl_getinfo( $ch, CURLINFO_RESPONSE_CODE ) ) {
                    $decoded = json_decode( (string) curl_multi_getcontent( $ch ), true );
                    if ( is_array( $decoded ) ) {
                        $out[ $folder ] = $decoded;
                    }
                }
                curl_multi_remove_handle( $multi, $ch );
                curl_close( $ch );
            }
            curl_multi_close( $multi );
        }
    }
    foreach ( $urls as $folder => $url ) {
        if ( isset( $out[ $folder ] ) ) {
            continue;
        }
        $resp = wp_remote_get( $url, [ 'timeout' => 12 ] );
        if ( ! is_wp_error( $resp ) && 200 === (int) wp_remote_retrieve_response_code( $resp ) ) {
            $decoded = json_decode( (string) wp_remote_retrieve_body( $resp ), true );
            if ( is_array( $decoded ) ) {
                $out[ $folder ] = $decoded;
            }
        }
    }
    return $out;
}

/** Monta o catálogo completo de uma conta e conserva-o enquanto a nuvem não mudar. */
function mp_cloud_admin_build_catalog( $uid, $refresh = false ) {
    $uid = (int) $uid;
    $version = (int) get_option( 'mp_cloudver_' . $uid, 0 );
    $cache_key = 'mp_clcat2_' . $uid . '_' . $version;
    if ( $refresh ) {
        delete_transient( $cache_key );
    } else {
        $cached = get_transient( $cache_key );
        if ( is_array( $cached ) ) {
            return $cached;
        }
    }

    $list_error = null;
    $objects = mp_s3_list( "players/{$uid}/", 10000, $list_error );
    if ( $list_error ) {
        return new WP_Error( 'cloud_list', $list_error );
    }
    $songs = [];
    $backups = [];
    $backup_keys = [];
    $meta_keys = [];
    foreach ( $objects as $obj ) {
        if ( preg_match( '#^players/\d+/Devices/([^/]+)/data\.json$#i', $obj['key'], $bm )
            || preg_match( '#^players/\d+/backup/(.+)$#', $obj['key'], $bm ) ) {
            $backup_ref = 'backup_' . count( $backups );
            $backups[] = [
                '_ref' => $backup_ref,
                'name' => $bm[1],
                'slot_id' => sanitize_key( pathinfo( $bm[1], PATHINFO_FILENAME ) ),
                'key' => $obj['key'],
                'size' => (int) $obj['size'],
                'modified' => (string) $obj['modified'],
                'legacy' => false !== strpos( $obj['key'], '/backup/' ),
            ];
            $backup_keys[ $backup_ref ] = $obj['key'];
            continue;
        }
        if ( ! preg_match( '#^players/\d+/audio/(.+)$#', $obj['key'], $m ) ) {
            continue;
        }
        $rest = $m[1];
        if ( false !== strpos( $rest, '/' ) ) {
            $folder = substr( $rest, 0, strpos( $rest, '/' ) );
            $fname = substr( $rest, strpos( $rest, '/' ) + 1 );
        } else {
            $folder = $rest;
            $fname = $rest;
        }
        if ( ! isset( $songs[ $folder ] ) ) {
            $songs[ $folder ] = [
                'folder' => $folder, 'files' => [], 'bytes' => 0, 'modified' => '',
                'track_key' => '', 'cover_key' => '', 'meta_key' => '',
            ];
        }
        $songs[ $folder ]['files'][] = [
            'name' => $fname, 'key' => $obj['key'], 'size' => (int) $obj['size'],
        ];
        $songs[ $folder ]['bytes'] += (int) $obj['size'];
        if ( $obj['modified'] > $songs[ $folder ]['modified'] ) {
            $songs[ $folder ]['modified'] = $obj['modified'];
        }
        if ( 0 === strpos( $fname, 'track.' ) || preg_match( '/\.(mp3|m4a|aac|ogg|wav|flac)(\.enc)?$/i', $fname ) ) {
            $songs[ $folder ]['track_key'] = $obj['key'];
        } elseif ( preg_match( '/\.(jpe?g|png|webp)$/i', $fname ) ) {
            $songs[ $folder ]['cover_key'] = $obj['key'];
        } elseif ( preg_match( '/meta\.json$/i', $fname ) ) {
            $songs[ $folder ]['meta_key'] = $obj['key'];
            $meta_keys[ $folder ] = $obj['key'];
        }
    }

    $backup_metadata = mp_cloud_admin_metadata_batch( $backup_keys );
    foreach ( $backups as &$backup ) {
        $payload = isset( $backup_metadata[ $backup['_ref'] ] ) && is_array( $backup_metadata[ $backup['_ref'] ] )
            ? $backup_metadata[ $backup['_ref'] ]
            : [];
        $data = isset( $payload['data'] ) && is_array( $payload['data'] ) ? $payload['data'] : [];
        $counts = [];
        foreach ( $data as $category => $value ) {
            $counts[ (string) $category ] = is_array( $value ) ? count( $value ) : ( null === $value ? 0 : 1 );
        }
        $backup['device'] = isset( $payload['device'] ) ? (string) $payload['device'] : '';
        $backup['device_id'] = isset( $payload['device_id'] ) ? (string) $payload['device_id'] : '';
        $backup['saved_at'] = isset( $payload['savedAt'] ) ? (int) $payload['savedAt'] : 0;
        $backup['schema_version'] = isset( $payload['schema_version'] ) ? (int) $payload['schema_version'] : 0;
        $backup['categories'] = array_keys( $data );
        $backup['category_counts'] = $counts;
        $backup['readable'] = ! empty( $payload );
        unset( $backup['_ref'] );
    }
    unset( $backup );
    usort( $backups, static function ( $a, $b ) {
        $at = $a['saved_at'] ?: strtotime( $a['modified'] ?: '1970-01-01' ) * 1000;
        $bt = $b['saved_at'] ?: strtotime( $b['modified'] ?: '1970-01-01' ) * 1000;
        return $bt <=> $at;
    } );

    $metadata = mp_cloud_admin_metadata_batch( $meta_keys );
    $tracks = [];
    foreach ( $songs as $folder => $song ) {
        $meta = isset( $metadata[ $folder ] ) && is_array( $metadata[ $folder ] ) ? $metadata[ $folder ] : [];
        $tags = isset( $meta['tags'] ) && is_array( $meta['tags'] ) ? $meta['tags'] : [];
        $pretty = preg_replace( '/-\d+$/', '', $folder );
        $fallback_artist = '';
        $fallback_title = $pretty;
        if ( false !== strpos( $pretty, ' - ' ) ) {
            [ $fallback_artist, $fallback_title ] = array_map( 'trim', explode( ' - ', $pretty, 2 ) );
        }
        $value = static function ( $key, $fallback = '' ) use ( $tags, $meta ) {
            if ( isset( $tags[ $key ] ) && '' !== trim( (string) $tags[ $key ] ) ) {
                return (string) $tags[ $key ];
            }
            return isset( $meta[ $key ] ) && '' !== trim( (string) $meta[ $key ] )
                ? (string) $meta[ $key ]
                : (string) $fallback;
        };
        $source = strtoupper( $value( 'source', '' ) );
        if ( '' === $source && false !== stripos( $value( 'sourceUrl', '' ), 'youtu' ) ) {
            $source = 'YOUTUBE';
        }
        $uploaded_ms = isset( $meta['uploadedAt'] ) ? (int) $meta['uploadedAt'] : 0;
        $tracks[] = [
            'folder' => $folder,
            'title' => $value( 'title', $fallback_title ),
            'artist' => $value( 'artist', $fallback_artist ),
            'album' => $value( 'album', '' ),
            'genre' => $value( 'genre', '' ),
            'year' => $value( 'year', '' ),
            'source' => $source ?: 'LOCAL',
            'source_url' => $value( 'sourceUrl', '' ),
            'song_id' => isset( $meta['id'] ) ? (string) $meta['id'] : '',
            'duration_ms' => isset( $meta['durationMs'] ) ? (int) $meta['durationMs'] : 0,
            'original_size' => isset( $meta['sizeBytes'] ) ? (int) $meta['sizeBytes'] : 0,
            'mime_type' => isset( $meta['mimeType'] ) ? (string) $meta['mimeType'] : '',
            'date_added' => isset( $meta['dateAdded'] ) ? (int) $meta['dateAdded'] : 0,
            'downloaded_at' => isset( $meta['downloadedAt'] ) ? (int) $meta['downloadedAt'] : 0,
            'device_folder' => isset( $meta['folderPath'] ) ? (string) $meta['folderPath'] : '',
            'clip_start_ms' => isset( $meta['clipStartMs'] ) ? (int) $meta['clipStartMs'] : 0,
            'clip_end_ms' => isset( $meta['clipEndMs'] ) ? (int) $meta['clipEndMs'] : 0,
            'encrypted' => ! empty( $meta['encrypted'] ),
            'uploaded_at' => $uploaded_ms,
            'modified' => (string) $song['modified'],
            'bytes' => (int) $song['bytes'],
            'track_key' => $song['track_key'],
            'cover_key' => $song['cover_key'],
            'meta_key' => $song['meta_key'],
            'files' => $song['files'],
            'metadata' => $meta,
            'status' => '' === $song['track_key'] ? 'broken' : ( '' === $song['cover_key'] || '' === $song['meta_key'] ? 'partial' : 'complete' ),
        ];
    }
    usort( $tracks, static function ( $a, $b ) {
        $at = $a['uploaded_at'] ?: strtotime( $a['modified'] ?: '1970-01-01' ) * 1000;
        $bt = $b['uploaded_at'] ?: strtotime( $b['modified'] ?: '1970-01-01' ) * 1000;
        return $bt <=> $at;
    } );
    $catalog = [ 'tracks' => $tracks, 'backups' => $backups, 'version' => $version ];
    set_transient( $cache_key, $catalog, 10 * MINUTE_IN_SECONDS );
    return $catalog;
}

/** AJAX: catálogo rico de um utilizador, usado apenas pelo modal da administração. */
function mp_cloud_admin_user_catalog() {
    if ( ! current_user_can( 'manage_options' ) ) {
        wp_send_json_error( [ 'message' => 'Sem permissão.' ], 403 );
    }
    check_ajax_referer( 'mp_cloud_catalog', 'nonce' );
    $uid = isset( $_POST['uid'] ) ? (int) $_POST['uid'] : 0;
    if ( $uid <= 0 || ! function_exists( 'mp_s3_list' ) || ! mp_s3_enabled() ) {
        wp_send_json_error( [ 'message' => 'Conta ou armazenamento inválido.' ], 400 );
    }
    $catalog = mp_cloud_admin_build_catalog( $uid, ! empty( $_POST['refresh'] ) );
    if ( is_wp_error( $catalog ) ) {
        wp_send_json_error( [ 'message' => $catalog->get_error_message() ], 502 );
    }

    global $wpdb;
    $account = $wpdb->get_row( $wpdb->prepare(
        "SELECT id, email, name, is_vip, vip_until, vip_source, platform, device_model, last_login FROM {$wpdb->prefix}mp_accounts WHERE id = %d",
        $uid
    ) );
    $delete_nonce = wp_create_nonce( 'mp_cloud_delete' );
    foreach ( $catalog['tracks'] as &$track ) {
        $track['cover_url'] = $track['cover_key'] ? mp_s3_presign( 'GET', $track['cover_key'], 3600 ) : '';
        $track['stream_url'] = $track['track_key']
            ? admin_url( 'admin.php' ) . '?page=mp-control&mp_cloud_dl=' . rawurlencode( $track['track_key'] )
                . '&mp_cloud_uid=' . $uid . '&stream=1&_wpnonce=' . wp_create_nonce( 'mp_cloud_dl' )
            : '';
        $track['download_url'] = $track['track_key']
            ? wp_nonce_url( admin_url( 'admin.php?page=mp-control&mp_cloud_dl=' . rawurlencode( $track['track_key'] ) . '&mp_cloud_uid=' . $uid ), 'mp_cloud_dl' )
            : '';
        $track['folder_key'] = "players/{$uid}/audio/" . $track['folder'];
        unset( $track['track_key'], $track['cover_key'], $track['meta_key'] );
    }
    unset( $track );
    foreach ( $catalog['backups'] as &$backup ) {
        $backup['download_url'] = wp_nonce_url(
            admin_url( 'admin.php?page=mp-control&mp_cloud_dl=' . rawurlencode( $backup['key'] ) . '&mp_cloud_uid=' . $uid ),
            'mp_cloud_dl'
        );
    }
    unset( $backup );
    $genres = $years = $sources = [];
    foreach ( $catalog['tracks'] as $track ) {
        if ( '' !== $track['genre'] ) { $genres[] = $track['genre']; }
        if ( '' !== $track['year'] ) { $years[] = $track['year']; }
        if ( '' !== $track['source'] ) { $sources[] = $track['source']; }
    }
    $unique_sorted = static function ( $values ) {
        $values = array_values( array_unique( array_filter( array_map( 'strval', $values ) ) ) );
        natcasesort( $values );
        return array_values( $values );
    };
    $backup_bytes = array_sum( array_map( static function ( $b ) { return (int) $b['size']; }, $catalog['backups'] ) );
    wp_send_json_success( [
        'user' => [
            'id' => $uid,
            'email' => $account ? $account->email : "Conta #{$uid}",
            'name' => $account ? (string) $account->name : '',
            'vip' => $account ? mp_vip_is_active( $account ) : false,
            'vip_source' => $account ? mp_vip_source( $account ) : '',
            'device' => $account ? trim( ucfirst( (string) $account->platform ) . ' · ' . (string) $account->device_model, ' ·' ) : '',
            'last_login' => $account ? (string) $account->last_login : '',
        ],
        'tracks' => $catalog['tracks'],
        'backups' => $catalog['backups'],
        'filters' => [
            'genres' => $unique_sorted( $genres ),
            'years' => array_reverse( $unique_sorted( $years ) ),
            'sources' => $unique_sorted( $sources ),
        ],
        'summary' => [
            'tracks' => count( $catalog['tracks'] ),
            'bytes' => array_sum( array_map( static function ( $t ) { return (int) $t['bytes']; }, $catalog['tracks'] ) ),
            'backups' => count( $catalog['backups'] ),
            'backup_bytes' => $backup_bytes,
            'complete' => count( array_filter( $catalog['tracks'], static function ( $t ) { return 'complete' === $t['status']; } ) ),
        ],
        'delete_nonce' => $delete_nonce,
        'post_url' => admin_url( 'admin.php?page=mp-control#nuvem' ),
    ] );
}

/**
 * Abrir/descarregar um ficheiro da nuvem já DESENCRIPTADO (só admins).
 * Os objetos no S3 estão cifrados com AES-256-CTR (IV nos primeiros 16 bytes);
 * o servidor conhece a chave da conta e devolve o áudio legível.
 */
function mp_cloud_admin_download() {
    if ( ! isset( $_GET['mp_cloud_dl'], $_GET['mp_cloud_uid'] ) ) {
        return;
    }
    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }
    check_admin_referer( 'mp_cloud_dl' );
    $key_s3 = (string) wp_unslash( $_GET['mp_cloud_dl'] );
    $uid    = (int) $_GET['mp_cloud_uid'];
    if ( strpos( $key_s3, 'players/' ) !== 0 || ! function_exists( 'mp_s3_presign' ) ) {
        return;
    }
    $resp = wp_remote_get( mp_s3_presign( 'GET', $key_s3, 300 ), [ 'timeout' => 90 ] );
    if ( is_wp_error( $resp ) ) {
        wp_die( 'Nuvem inacessível: ' . esc_html( $resp->get_error_message() ) );
    }
    $http = (int) wp_remote_retrieve_response_code( $resp );
    if ( 200 !== $http ) {
        // Diagnóstico completo: o XML de erro do S3 diz o código E a chave que
        // ele viu — compara com a pedida e o problema salta à vista.
        $body = (string) wp_remote_retrieve_body( $resp );
        $code = preg_match( '/<Code>([^<]+)<\/Code>/', $body, $m ) ? $m[1] : '?';
        $msg  = preg_match( '/<Message>([^<]+)<\/Message>/', $body, $m ) ? $m[1] : '';
        $seen = preg_match( '/<Key>([^<]+)<\/Key>/', $body, $m ) ? $m[1] : '(não devolvida)';
        wp_die(
            '<h2>Nuvem devolveu HTTP ' . (int) $http . ' — ' . esc_html( $code ) . '</h2>'
            . '<p>' . esc_html( $msg ) . '</p>'
            . '<p><strong>Chave pedida:</strong> <code>' . esc_html( $key_s3 ) . '</code><br>'
            . '<strong>Chave vista pelo S3:</strong> <code>' . esc_html( $seen ) . '</code></p>'
        );
    }
    $data = (string) wp_remote_retrieve_body( $resp );
    $name = basename( $key_s3 );

    if ( substr( $name, -4 ) === '.enc' && function_exists( 'mp_cloud_decrypt_heal' ) ) {
        // CURA DEFINITIVA: tenta a chave atual E o histórico de chaves antigas.
        // Se uma chave antiga servir, o ficheiro é re-encriptado com a atual e
        // atualizado no S3 na hora — nunca mais dá problema, sem reenvio.
        $out = mp_cloud_decrypt_heal( $uid, $key_s3, $data );
        if ( null === $out ) {
            // Nenhuma chave conhecida serve (ficheiro anterior ao histórico) →
            // último recurso: reenvio automático pelo telemóvel do utilizador.
            if ( function_exists( 'mp_reup_add' ) ) {
                mp_reup_add( $uid, $key_s3 );
            }
            wp_die(
                '<h2>Áudio ilegível — nenhuma chave conhecida serve</h2>'
                . '<p>Este ficheiro é anterior ao histórico de chaves da conta e não é recuperável no servidor.</p>'
                . '<p>📨 <strong>Já pedi o reenvio automático:</strong> na próxima vez que o utilizador abrir o app, '
                . 'a música é reenviada sozinha com a chave nova (o original continua no telemóvel dele).</p>'
                . '<p><code>' . esc_html( $key_s3 ) . '</code></p>'
            );
        }
        $data = $out;
        $name = substr( $name, 0, -4 ); // remove .enc
    }

    nocache_headers();
    // Content-Type pelo CONTEÚDO real (YouTube traz WebM/Opus, M4A, etc.).
    $ctype = 'audio/mpeg';
    if ( '.json' === substr( strtolower( $name ), -5 ) ) {
        $ctype = 'application/json; charset=utf-8';
    } elseif ( 0 === strpos( $data, "\x1A\x45\xDF\xA3" ) ) {
        $ctype = 'audio/webm';
    } elseif ( 'ftyp' === substr( $data, 4, 4 ) ) {
        $ctype = 'audio/mp4';
    } elseif ( 0 === strpos( $data, 'OggS' ) ) {
        $ctype = 'audio/ogg';
    } elseif ( 0 === strpos( $data, 'fLaC' ) ) {
        $ctype = 'audio/flac';
    } elseif ( 0 === strpos( $data, 'RIFF' ) ) {
        $ctype = 'audio/wav';
    }
    header( 'Content-Type: ' . $ctype );
    header( 'Content-Length: ' . strlen( $data ) );
    // stream=1 → toca inline no leitor do admin; sem stream → descarrega o ficheiro.
    $disposition = isset( $_GET['stream'] ) ? 'inline' : 'attachment';
    header( 'Content-Disposition: ' . $disposition . '; filename="' . rawurlencode( $name ) . '"' );
    header( 'Accept-Ranges: none' );
    echo $data; // phpcs:ignore
    exit;
}

function mp_admin_menu() {
    add_menu_page(
        '1MZ Music Player',
        '1MZ Music Player',
        'manage_options',
        'mp-control',
        'mp_admin_page',
        'dashicons-format-audio',
        59
    );
}

function mp_admin_page() {
    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }

    // Selecionador de média do WordPress (explorador de ficheiros na aba Parcerias).
    wp_enqueue_media();

    global $wpdb;
    $sp_tracks = $wpdb->prefix . 'mp_sponsored_tracks';
    $sp_pay    = $wpdb->prefix . 'mp_sponsored_payouts';
    $sp_sess   = $wpdb->prefix . 'mp_sponsored_sessions';

    // ── Parcerias: definições do programa ───────────────────────────────
    if ( isset( $_POST['mp_sponsored_settings'] ) && check_admin_referer( 'mp_sponsored' ) ) {
        update_option( 'mp_sponsored_on', isset( $_POST['mp_sponsored_on'] ) ? 1 : 0 );
        update_option( 'mp_sponsored_min_payout', max( 0, (float) ( $_POST['mp_sponsored_min_payout'] ?? 5 ) ) );
        update_option( 'mp_sponsored_daily_cap_min', max( 1, (int) ( $_POST['mp_sponsored_daily_cap_min'] ?? 30 ) ) );
        // Regra de volume: % mínima para ganhar (0 = desliga a regra) e minutos de pausa.
        update_option( 'mp_sponsored_min_volume', min( 100, max( 0, (int) ( $_POST['mp_sponsored_min_volume'] ?? 20 ) ) ) );
        update_option( 'mp_sponsored_vol_pause_min', min( 120, max( 1, (int) ( $_POST['mp_sponsored_vol_pause_min'] ?? 10 ) ) ) );
        // Política para carro/Bluetooth (volume não verificável): allow|flag|block.
        $car_earn = sanitize_key( $_POST['mp_sponsored_car_earn'] ?? 'flag' );
        update_option( 'mp_sponsored_car_earn', in_array( $car_earn, [ 'allow', 'flag', 'block' ], true ) ? $car_earn : 'flag' );
        // Métodos de pagamento disponíveis (predefinidos: PayPal, M-Pesa, Emola).
        $methods = array_values( array_intersect(
            array_map( 'sanitize_text_field', (array) ( $_POST['mp_sponsored_methods'] ?? [] ) ),
            [ 'PayPal', 'M-Pesa', 'Emola' ]
        ) );
        update_option( 'mp_sponsored_methods', $methods );
        echo '<div class="notice notice-success is-dismissible"><p>Programa de parcerias atualizado.</p></div>';
    }

    // ── Parcerias: adicionar/editar faixa patrocinada ───────────────────
    if ( isset( $_POST['mp_sponsored_track'] ) && check_admin_referer( 'mp_sponsored' ) ) {
        $data = [
            'title'        => sanitize_text_field( $_POST['sp_title'] ?? '' ),
            'artist'       => sanitize_text_field( $_POST['sp_artist'] ?? '' ),
            'audio_url'    => esc_url_raw( $_POST['sp_audio'] ?? '' ),
            'cover_url'    => esc_url_raw( $_POST['sp_cover'] ?? '' ),
            'countries'    => strtoupper( sanitize_text_field( $_POST['sp_countries'] ?? '' ) ),
            'rate_per_min' => max( 0, (float) ( $_POST['sp_rate'] ?? 0 ) ),
            'budget_usd'   => max( 0, (float) ( $_POST['sp_budget'] ?? 0 ) ),
            'duration_sec' => max( 0, (int) ( $_POST['sp_duration'] ?? 0 ) ),
            'active'       => isset( $_POST['sp_active'] ) ? 1 : 0,
        ];
        $sp_id = (int) ( $_POST['sp_id'] ?? 0 );
        if ( $data['title'] !== '' && $data['audio_url'] !== '' ) {
            if ( $sp_id > 0 ) {
                $wpdb->update( $sp_tracks, $data, [ 'id' => $sp_id ] );
                echo '<div class="notice notice-success is-dismissible"><p>Faixa patrocinada atualizada.</p></div>';
            } else {
                $wpdb->insert( $sp_tracks, $data );
                echo '<div class="notice notice-success is-dismissible"><p>Faixa adicionada ao programa.</p></div>';
            }
        } else {
            echo '<div class="notice notice-error is-dismissible"><p>Título e URL do áudio são obrigatórios.</p></div>';
        }
    }
    if ( isset( $_POST['mp_sponsored_delete'], $_POST['sp_id'] ) && check_admin_referer( 'mp_sponsored' ) ) {
        $wpdb->delete( $sp_tracks, [ 'id' => (int) $_POST['sp_id'] ] );
        echo '<div class="notice notice-success is-dismissible"><p>Faixa removida do programa.</p></div>';
    }
    // ── Parcerias: IA anti-fraude revê uma conta suspeita ───────────────
    if ( isset( $_POST['mp_fraud_review'], $_POST['fraud_uid'] ) && check_admin_referer( 'mp_sponsored' ) ) {
        $uid = (int) $_POST['fraud_uid'];
        $verdict = mp_sponsored_ai_fraud_review( $uid );
        set_transient( 'mp_fraud_verdict_' . $uid, $verdict, 300 );
    }
    // ── Parcerias: limpar as bandeiras de fraude de uma conta ───────────
    if ( isset( $_POST['mp_fraud_clear'], $_POST['fraud_uid'] ) && check_admin_referer( 'mp_sponsored' ) ) {
        $uid = (int) $_POST['fraud_uid'];
        delete_option( 'mp_sponsored_flags_' . $uid );
        delete_option( 'mp_sponsored_score_' . $uid );
        echo '<div class="notice notice-success is-dismissible"><p>Bandeiras de fraude limpas.</p></div>';
    }

    // ── Parcerias: analisar um pedido de pagamento com a IA (sob demanda) ──
    if ( isset( $_POST['mp_payout_analyze'], $_POST['payout_id'] ) && check_admin_referer( 'mp_sponsored' ) ) {
        $pid = (int) $_POST['payout_id'];
        $prow = $wpdb->get_row( $wpdb->prepare( "SELECT account_id FROM {$sp_pay} WHERE id = %d", $pid ) );
        if ( $prow && function_exists( 'mp_sponsored_ai_fraud_review' ) ) {
            $verdict = mp_sponsored_ai_fraud_review( (int) $prow->account_id );
            $wpdb->update( $sp_pay, [ 'note' => mb_substr( (string) $verdict, 0, 255 ) ], [ 'id' => $pid ] );
        }
        echo '<div class="notice notice-success is-dismissible"><p>Análise anti-fraude concluída.</p></div>';
    }

    // ── Parcerias: pedir verificação ao DISPOSITIVO do utilizador ───────
    if ( isset( $_POST['mp_verify_device'], $_POST['fraud_uid'] ) && check_admin_referer( 'mp_sponsored' ) ) {
        $uid = (int) $_POST['fraud_uid'];
        update_option( 'mp_sponsored_verify_' . $uid, 'requested', false );
        echo '<div class="notice notice-success is-dismissible"><p>Pedido enviado — o dispositivo do utilizador fará o auto-diagnóstico na próxima abertura do app.</p></div>';
    }
    // ── Parcerias: DEVOLVER ganhos (clawback) de uma conta ──────────────
    if ( isset( $_POST['mp_clawback'], $_POST['fraud_uid'] ) && check_admin_referer( 'mp_sponsored' ) ) {
        $uid = (int) $_POST['fraud_uid'];
        $bal = mp_sponsored_balance( $uid );
        if ( $bal > 0 ) {
            update_option( 'mp_sponsored_clawback_' . $uid, mp_sponsored_clawback( $uid ) + $bal, false );
        }
        // Rejeita o pedido pendente (o dinheiro não sai).
        $wpdb->query( $wpdb->prepare( "UPDATE {$sp_pay} SET status = 'rejected' WHERE account_id = %d AND status = 'requested'", $uid ) );
        echo '<div class="notice notice-success is-dismissible"><p>Ganhos devolvidos: o saldo desta conta foi zerado e o pedido rejeitado.</p></div>';
    }

    // ── Parcerias: marcar pagamento como pago/rejeitado ─────────────────
    if ( isset( $_POST['mp_payout_action'], $_POST['payout_id'] ) && check_admin_referer( 'mp_sponsored' ) ) {
        $pid = (int) $_POST['payout_id'];
        $act = sanitize_key( $_POST['mp_payout_action'] );
        if ( $act === 'paid' ) {
            $wpdb->update( $sp_pay, [ 'status' => 'paid', 'paid_at' => current_time( 'mysql', true ) ], [ 'id' => $pid ] );
        } elseif ( $act === 'reject' ) {
            $wpdb->update( $sp_pay, [ 'status' => 'rejected' ], [ 'id' => $pid ] );
        }
        echo '<div class="notice notice-success is-dismissible"><p>Pagamento atualizado.</p></div>';
    }

    // ── Guardar definições ──────────────────────────────────────────────
    if ( isset( $_POST['mp_save'] ) && check_admin_referer( 'mp_save_settings' ) ) {
        update_option( 'mp_min_version_code', (int) ( $_POST['mp_min_version_code'] ?? 0 ) );
        update_option( 'mp_latest_version_code', (int) ( $_POST['mp_latest_version_code'] ?? 0 ) );
        update_option( 'mp_latest_version', sanitize_text_field( $_POST['mp_latest_version'] ?? '' ) );
        update_option( 'mp_store_url', esc_url_raw( $_POST['mp_store_url'] ?? '' ) );
        update_option( 'mp_force_message', sanitize_text_field( $_POST['mp_force_message'] ?? '' ) );
        update_option( 'mp_version_blocked', isset( $_POST['mp_version_blocked'] ) ? 1 : 0 );

        $access = sanitize_key( $_POST['mp_access_gate'] ?? 'open' );
        update_option( 'mp_access_gate', in_array( $access, [ 'open', 'account_required', 'blocked' ], true ) ? $access : 'open' );
        update_option( 'mp_access_message', sanitize_text_field( $_POST['mp_access_message'] ?? '' ) );

        update_option( 'mp_message_text', sanitize_textarea_field( $_POST['mp_message_text'] ?? '' ) );
        update_option( 'mp_message_type', sanitize_key( $_POST['mp_message_type'] ?? 'info' ) );

        // Pacotes VIP
        update_option( 'mp_vip_enabled', isset( $_POST['mp_vip_enabled'] ) ? 1 : 0 );
        update_option( 'mp_vip_currency', sanitize_text_field( $_POST['mp_vip_currency'] ?? '$' ) );
        update_option( 'mp_vip_monthly', sanitize_text_field( $_POST['mp_vip_monthly'] ?? '' ) );
        update_option( 'mp_vip_annual', sanitize_text_field( $_POST['mp_vip_annual'] ?? '' ) );
        update_option( 'mp_vip_annual_permonth', sanitize_text_field( $_POST['mp_vip_annual_permonth'] ?? '' ) );
        update_option( 'mp_vip_savings', (int) ( $_POST['mp_vip_savings'] ?? 0 ) );
        update_option( 'mp_vip_cta', esc_url_raw( $_POST['mp_vip_cta'] ?? '' ) );
        update_option( 'mp_vip_pay_instructions', sanitize_textarea_field( $_POST['mp_vip_pay_instructions'] ?? '' ) );

        // Armazenamento na cloud (Amazon S3 / compatível)
        update_option( 'mp_s3_enabled', isset( $_POST['mp_s3_enabled'] ) ? 1 : 0 );
        update_option( 'mp_s3_bucket', sanitize_text_field( $_POST['mp_s3_bucket'] ?? '' ) );
        update_option( 'mp_s3_region', sanitize_text_field( $_POST['mp_s3_region'] ?? 'us-east-1' ) );
        update_option( 'mp_s3_endpoint', esc_url_raw( $_POST['mp_s3_endpoint'] ?? '' ) );
        update_option( 'mp_s3_key', sanitize_text_field( $_POST['mp_s3_key'] ?? '' ) );
        // Segredo: só sobrescreve se enviarem um novo (campo vazio = manter; trava autofill).
        $s3_secret = trim( (string) ( $_POST['mp_s3_secret'] ?? '' ) );
        if ( $s3_secret !== '' ) {
            update_option( 'mp_s3_secret', sanitize_text_field( $s3_secret ) );
        }
        update_option( 'mp_cloud_quota_mb', max( 0, (int) ( $_POST['mp_cloud_quota_mb'] ?? 0 ) ) );
        update_option( 'mp_backup_devices', 5 );

        // Anúncios AdMob (o app obedece; VIP pode ficar isento).
        update_option( 'mp_ads_enabled', isset( $_POST['mp_ads_enabled'] ) ? 1 : 0 );
        update_option( 'mp_ads_banner_id', sanitize_text_field( $_POST['mp_ads_banner_id'] ?? '' ) );
        update_option( 'mp_ads_inter_id', sanitize_text_field( $_POST['mp_ads_inter_id'] ?? '' ) );
        update_option( 'mp_ads_inter_every', max( 0, (int) ( $_POST['mp_ads_inter_every'] ?? 0 ) ) );
        update_option( 'mp_ads_vip_free', isset( $_POST['mp_ads_vip_free'] ) ? 1 : 0 );
        // Nativos: anúncios com aspeto de linha de música dentro das listas.
        update_option( 'mp_ads_native_id', sanitize_text_field( $_POST['mp_ads_native_id'] ?? '' ) );
        // Premiados: ver anúncios → progresso → dias VIP.
        update_option( 'mp_ads_rew_id', sanitize_text_field( $_POST['mp_ads_rew_id'] ?? '' ) );
        update_option( 'mp_ads_rew_target', max( 1, (int) ( $_POST['mp_ads_rew_target'] ?? 10 ) ) );
        update_option( 'mp_ads_rew_days', max( 1, (int) ( $_POST['mp_ads_rew_days'] ?? 3 ) ) );
        update_option( 'mp_ads_rew_daily', max( 1, (int) ( $_POST['mp_ads_rew_daily'] ?? 20 ) ) );
        update_option( 'mp_ads_rew_cloud_audio', isset( $_POST['mp_ads_rew_cloud_audio'] ) ? 1 : 0 );
        // Quota VIP deslizante na nuvem (GB; 0 = desativada, usa a quota normal).
        update_option( 'mp_vip_quota_gb', max( 0, (int) ( $_POST['mp_vip_quota_gb'] ?? 1024 ) ) );

        // Formatos de áudio permitidos (chave → nível off|free|account|vip).
        if ( function_exists( 'mp_audio_format_keys' ) ) {
            $fmt_in  = (array) ( $_POST['mp_audio_fmt'] ?? [] );
            $fmt_out = [];
            foreach ( mp_audio_format_keys() as $fk ) {
                $fv = sanitize_key( $fmt_in[ $fk ] ?? 'free' );
                $fmt_out[ $fk ] = in_array( $fv, [ 'off', 'free', 'account', 'vip' ], true ) ? $fv : 'free';
            }
            update_option( 'mp_audio_formats', $fmt_out );
        }

        echo '<div class="notice notice-success is-dismissible"><p>Definições guardadas.</p></div>';
    }

    // ── Guardar campos S3 + testar a ligação (PUT/GET/DELETE reais no bucket) ──
    if ( isset( $_POST['mp_s3_test'] ) && check_admin_referer( 'mp_save_settings' ) ) {
        update_option( 'mp_s3_enabled', isset( $_POST['mp_s3_enabled'] ) ? 1 : 0 );
        update_option( 'mp_s3_bucket', sanitize_text_field( $_POST['mp_s3_bucket'] ?? '' ) );
        update_option( 'mp_s3_region', sanitize_text_field( $_POST['mp_s3_region'] ?? 'us-east-1' ) );
        update_option( 'mp_s3_endpoint', esc_url_raw( $_POST['mp_s3_endpoint'] ?? '' ) );
        update_option( 'mp_s3_key', sanitize_text_field( $_POST['mp_s3_key'] ?? '' ) );
        $s3_secret_t = trim( (string) ( $_POST['mp_s3_secret'] ?? '' ) );
        if ( $s3_secret_t !== '' ) {
            update_option( 'mp_s3_secret', sanitize_text_field( $s3_secret_t ) );
        }
        update_option( 'mp_cloud_quota_mb', max( 0, (int) ( $_POST['mp_cloud_quota_mb'] ?? 0 ) ) );
        update_option( 'mp_backup_devices', 5 );
        $test = function_exists( 'mp_s3_selftest' )
            ? mp_s3_selftest()
            : [ 'ok' => false, 'msg' => 'Controlador S3 não carregado.' ];
        echo '<div class="notice notice-' . ( $test['ok'] ? 'success' : 'error' ) . ' is-dismissible"><p><strong>'
            . ( $test['ok'] ? '✅ Armazenamento na nuvem ligado' : '❌ Ligação falhou' )
            . ':</strong> ' . esc_html( $test['msg'] ) . '</p></div>';
    }

    // ── Nuvem: apagar UM ficheiro de um utilizador ──────────────────────
    if ( isset( $_POST['mp_cloud_delete'], $_POST['mp_cloud_key'] ) && check_admin_referer( 'mp_cloud_delete' ) ) {
        $k = sanitize_text_field( wp_unslash( $_POST['mp_cloud_key'] ) );
        if ( strpos( $k, 'players/' ) === 0 && function_exists( 'mp_s3_presign' ) ) {
            $resp = wp_remote_request( mp_s3_presign( 'DELETE', $k, 300 ), [ 'method' => 'DELETE', 'timeout' => 20 ] );
            $ok = ! is_wp_error( $resp ) && (int) wp_remote_retrieve_response_code( $resp ) < 300;
            if ( $ok && function_exists( 'mp_cloud_bump' ) && preg_match( '#^players/(\d+)/#', $k, $bm ) ) {
                mp_cloud_bump( (int) $bm[1] ); // o web do utilizador atualiza sozinho
            }
            echo '<div class="notice notice-' . ( $ok ? 'success' : 'error' ) . ' is-dismissible"><p>'
                . ( $ok ? 'Ficheiro apagado da nuvem.' : 'Falha ao apagar o ficheiro.' ) . '</p></div>';
        }
    }

    // ── Nuvem: apagar a PASTA de uma música (áudio + capa + meta) ───────
    if ( isset( $_POST['mp_cloud_delete_folder'], $_POST['mp_cloud_folder'] ) && check_admin_referer( 'mp_cloud_delete' ) ) {
        $folder = sanitize_text_field( wp_unslash( $_POST['mp_cloud_folder'] ) );
        if ( strpos( $folder, 'players/' ) === 0 && function_exists( 'mp_s3_list' ) ) {
            $n = 0;
            foreach ( mp_s3_list( $folder, 1000 ) as $obj ) {
                $resp = wp_remote_request( mp_s3_presign( 'DELETE', $obj['key'], 300 ), [ 'method' => 'DELETE', 'timeout' => 20 ] );
                if ( ! is_wp_error( $resp ) && (int) wp_remote_retrieve_response_code( $resp ) < 300 ) {
                    $n++;
                }
            }
            if ( function_exists( 'mp_cloud_bump' ) && preg_match( '#^players/(\d+)/#', $folder, $bm ) ) {
                mp_cloud_bump( (int) $bm[1] );
            }
            echo '<div class="notice notice-success is-dismissible"><p>Música removida da nuvem (' . (int) $n . ' ficheiro(s)).</p></div>';
        }
    }

    // ── Suporte: apagar TODAS as cópias de dispositivos de uma conta ───
    if ( isset( $_POST['mp_cloud_delete_backups'], $_POST['mp_cloud_uid'] ) && check_admin_referer( 'mp_cloud_delete' ) ) {
        $uid = (int) $_POST['mp_cloud_uid'];
        if ( $uid > 0 && function_exists( 'mp_s3_list' ) ) {
            $n = 0;
            foreach ( [ "players/$uid/Devices/", "players/$uid/backup/" ] as $prefix ) {
                foreach ( mp_s3_list( $prefix, 1000 ) as $obj ) {
                    $resp = wp_remote_request( mp_s3_presign( 'DELETE', $obj['key'], 300 ), [ 'method' => 'DELETE', 'timeout' => 20 ] );
                    if ( ! is_wp_error( $resp ) && (int) wp_remote_retrieve_response_code( $resp ) < 300 ) {
                        $n++;
                    }
                }
            }
            if ( function_exists( 'mp_cloud_bump' ) ) {
                mp_cloud_bump( $uid );
            }
            echo '<div class="notice notice-success is-dismissible"><p>' . (int) $n
                . ' cópia(s) de dispositivo apagada(s) da conta #' . $uid . '.</p></div>';
        }
    }

    // ── Nuvem: apagar TODAS as músicas de um utilizador ─────────────────
    if ( isset( $_POST['mp_cloud_delete_user'], $_POST['mp_cloud_uid'] ) && check_admin_referer( 'mp_cloud_delete' ) ) {
        $uid = (int) $_POST['mp_cloud_uid'];
        if ( $uid > 0 && function_exists( 'mp_s3_list' ) ) {
            $n = 0;
            foreach ( mp_s3_list( "players/$uid/audio/", 1000 ) as $obj ) {
                $resp = wp_remote_request( mp_s3_presign( 'DELETE', $obj['key'], 300 ), [ 'method' => 'DELETE', 'timeout' => 20 ] );
                if ( ! is_wp_error( $resp ) && (int) wp_remote_retrieve_response_code( $resp ) < 300 ) {
                    $n++;
                }
            }
            if ( function_exists( 'mp_cloud_bump' ) ) {
                mp_cloud_bump( $uid );
            }
            echo '<div class="notice notice-success is-dismissible"><p>' . (int) $n . ' ficheiro(s) apagado(s) da nuvem do utilizador #' . $uid . '.</p></div>';
        }
    }

    // ── Guardar um add-on (modal "Configurar") ──────────────────────────
    if ( isset( $_POST['mp_addon_save'], $_POST['mp_addon_key'] ) && check_admin_referer( 'mp_addon_save' ) ) {
        $key     = sanitize_key( $_POST['mp_addon_key'] );
        $catalog = mp_feature_catalog();
        if ( isset( $catalog[ $key ] ) ) {
            $features = get_option( 'mp_features', [] );
            if ( ! is_array( $features ) ) {
                $features = [];
            }
            $features[ $key ] = [
                'enabled'          => isset( $_POST['addon_enabled'] ) ? 1 : 0,
                'requires_account' => isset( $_POST['addon_acct'] ) ? 1 : 0,
                'vip_only'         => isset( $_POST['addon_vip'] ) ? 1 : 0,
            ];
            update_option( 'mp_features', $features );

            // Regras específicas do YouTube.
            if ( $key === 'youtube_addon' ) {
                update_option( 'mp_yt_blocked_countries', sanitize_textarea_field( $_POST['mp_yt_blocked_countries'] ?? '' ) );
                update_option( 'mp_yt_blocked_artists', sanitize_textarea_field( $_POST['mp_yt_blocked_artists'] ?? '' ) );
                update_option( 'mp_yt_blocked_keywords', sanitize_textarea_field( $_POST['mp_yt_blocked_keywords'] ?? '' ) );
                update_option( 'mp_yt_prebuffer_kb', min( 4096, max( 128, (int) ( $_POST['mp_yt_prebuffer_kb'] ?? 768 ) ) ) );
                update_option( 'mp_yt_resolve_retries', min( 5, max( 1, (int) ( $_POST['mp_yt_resolve_retries'] ?? 3 ) ) ) );
            }

            // Sub-funções do Equalizador (marcar/desmarcar dentro do add-on principal).
            if ( $key === 'equalizer' ) {
                update_option( 'mp_eq_signatures', isset( $_POST['mp_eq_signatures'] ) ? 1 : 0 );
            }

            // Países elegíveis (globais) do programa de patrocinadas.
            if ( $key === 'sponsored' ) {
                update_option( 'mp_sponsored_countries', strtoupper( sanitize_textarea_field( $_POST['mp_sponsored_countries'] ?? '' ) ) );
            }

            // Configuração específica do Assistente IA (chave + modelo).
            if ( $key === 'ai_assistant' ) {
                $new_key = trim( (string) ( $_POST['mp_ai_api_key'] ?? '' ) );
                // Só sobrescreve se enviarem uma chave NOVA e PLAUSÍVEL (começa por "sk-ant-").
                // Campo vazio = manter a atual; autofill do browser com lixo = ignorado.
                if ( $new_key !== '' && strncmp( $new_key, 'sk-ant-', 7 ) === 0 ) {
                    update_option( 'mp_ai_api_key', sanitize_text_field( $new_key ) );
                }
                $model = sanitize_text_field( $_POST['mp_ai_model'] ?? 'claude-opus-4-8' );
                update_option( 'mp_ai_model', in_array( $model, [ 'claude-opus-4-8', 'claude-opus-4-6' ], true ) ? $model : 'claude-opus-4-8' );
                update_option( 'mp_ai_covers', isset( $_POST['mp_ai_covers'] ) ? 1 : 0 );
                update_option( 'mp_ai_tags', isset( $_POST['mp_ai_tags'] ) ? 1 : 0 );
                update_option( 'mp_ai_lookup', isset( $_POST['mp_ai_lookup'] ) ? 1 : 0 );
                update_option( 'mp_ai_translate', isset( $_POST['mp_ai_translate'] ) ? 1 : 0 );
                update_option( 'mp_ai_recommend', isset( $_POST['mp_ai_recommend'] ) ? 1 : 0 );
                update_option( 'mp_ai_playlist', isset( $_POST['mp_ai_playlist'] ) ? 1 : 0 );
                update_option( 'mp_ai_shuffle', isset( $_POST['mp_ai_shuffle'] ) ? 1 : 0 );
                update_option( 'mp_ai_diagnostics', isset( $_POST['mp_ai_diagnostics'] ) ? 1 : 0 );
            }
            echo '<div class="notice notice-success is-dismissible"><p>Add-on «' . esc_html( $catalog[ $key ] ) . '» guardado.</p></div>';
        }
    }

    // ── Ligar/desligar rápido de um add-on (toggle no card) ─────────────
    if ( isset( $_POST['mp_addon_toggle'], $_POST['mp_addon_key'] ) && check_admin_referer( 'mp_addon_toggle' ) ) {
        $key     = sanitize_key( $_POST['mp_addon_key'] );
        $catalog = mp_feature_catalog();
        if ( isset( $catalog[ $key ] ) ) {
            $features = get_option( 'mp_features', [] );
            if ( ! is_array( $features ) ) {
                $features = [];
            }
            $cur = isset( $features[ $key ] ) && is_array( $features[ $key ] ) ? $features[ $key ] : [];
            $cur['enabled'] = ( $_POST['mp_addon_toggle'] === 'on' ) ? 1 : 0;
            if ( ! isset( $cur['requires_account'] ) ) $cur['requires_account'] = 0;
            if ( ! isset( $cur['vip_only'] ) )         $cur['vip_only'] = 0;
            $features[ $key ] = $cur;
            update_option( 'mp_features', $features );
        }
    }

    // ── Acções por pedido VIP: aprovar (concede VIP) / rejeitar ─────────
    if ( isset( $_POST['mp_order_action'], $_POST['mp_order_id'] ) && check_admin_referer( 'mp_order_action' ) ) {
        $oid = (int) $_POST['mp_order_id'];
        $oa  = sanitize_key( $_POST['mp_order_action'] );
        if ( $oa === 'approve' && function_exists( 'mp_approve_order' ) ) {
            mp_approve_order( $oid );
            echo '<div class="notice notice-success is-dismissible"><p>Pedido aprovado — VIP concedido.</p></div>';
        } elseif ( $oa === 'reject' && function_exists( 'mp_reject_order' ) ) {
            mp_reject_order( $oid );
            echo '<div class="notice notice-warning is-dismissible"><p>Pedido rejeitado.</p></div>';
        }
    }

    // ── Acções por conta: bloquear/desbloquear + VIP on/off ─────────────
    if ( isset( $_POST['mp_acct_action'], $_POST['mp_acct_id'] ) && check_admin_referer( 'mp_acct_action' ) ) {
        global $wpdb;
        $id     = (int) $_POST['mp_acct_id'];
        $action = sanitize_key( $_POST['mp_acct_action'] );
        $table  = $wpdb->prefix . 'mp_accounts';
        // Limpa TODOS os ficheiros S3 do utilizador (audio + backups) e as chaves.
        $mp_wipe_cloud = function ( $uid ) {
            $n = 0;
            if ( function_exists( 'mp_s3_enabled' ) && mp_s3_enabled() ) {
                foreach ( mp_s3_list( "players/$uid/", 1000 ) as $obj ) {
                    $resp = wp_remote_request( mp_s3_presign( 'DELETE', $obj['key'], 300 ), [ 'method' => 'DELETE', 'timeout' => 20 ] );
                    if ( ! is_wp_error( $resp ) && (int) wp_remote_retrieve_response_code( $resp ) < 300 ) {
                        $n++;
                    }
                }
            }
            // NUNCA perder a chave: arquiva no histórico antes de apagar, para
            // qualquer ficheiro que sobre (ou reapareça) continuar recuperável.
            if ( function_exists( 'mp_cloud_key_archive' ) ) {
                mp_cloud_key_archive( $uid );
            }
            delete_option( 'mp_cloudkey_' . $uid );
            $prev = (string) get_option( 'mp_webtok_acc_' . $uid, '' );
            if ( $prev !== '' ) {
                delete_option( 'mp_webtok_' . $prev );
                delete_option( 'mp_webtok_acc_' . $uid );
            }
            if ( function_exists( 'mp_cloud_bump' ) ) {
                mp_cloud_bump( $uid );
            }
            return $n;
        };
        switch ( $action ) {
            case 'block':   $wpdb->update( $table, [ 'status' => 'blocked' ], [ 'id' => $id ] ); break;
            case 'unblock': $wpdb->update( $table, [ 'status' => 'active' ], [ 'id' => $id ] ); break;
            case 'vip_on':  $wpdb->update( $table, [
                'is_vip' => 1, 'vip_until' => null, 'vip_source' => 'admin', 'vip_full_until' => null,
            ], [ 'id' => $id ] ); break;
            case 'vip_off': $wpdb->update( $table, [
                'is_vip' => 0, 'vip_until' => null, 'vip_source' => null, 'vip_full_until' => null,
            ], [ 'id' => $id ] ); break;
            case 'clear_sync':
                $wpdb->update( $table, [ 'sync_data' => null, 'sync_updated' => null ], [ 'id' => $id ] );
                break;
            case 'wipe_all':
                // Tudo do utilizador: cópia de segurança + ficheiros na nuvem + chaves.
                $wpdb->update( $table, [ 'sync_data' => null, 'sync_updated' => null ], [ 'id' => $id ] );
                $n = $mp_wipe_cloud( $id );
                echo '<div class="notice notice-success is-dismissible"><p>Limpeza total: cópia apagada e ' . (int) $n . ' ficheiro(s) removido(s) da nuvem.</p></div>';
                break;
            case 'delete':
                $mp_wipe_cloud( $id ); // conta eliminada = nada dela fica no S3
                $wpdb->delete( $table, [ 'id' => $id ] );
                break;
            case 'remove_earn':
                // O admin SÓ pode remover ganhos patrocinados (nunca adicionar).
                // Retira via clawback: um valor específico ou todo o saldo.
                if ( function_exists( 'mp_sponsored_balance' ) ) {
                    $bal = mp_sponsored_balance( $id );
                    $amt = isset( $_POST['mp_earn_amount'] ) ? (float) $_POST['mp_earn_amount'] : 0;
                    if ( $amt <= 0 || $amt > $bal ) { $amt = $bal; } // 0/ inválido = tudo
                    if ( $amt > 0 ) {
                        update_option( 'mp_sponsored_clawback_' . $id, mp_sponsored_clawback( $id ) + $amt, false );
                        $sp_pay = $wpdb->prefix . 'mp_sponsored_payouts';
                        // Se retirou tudo, rejeita qualquer pedido pendente.
                        if ( mp_sponsored_balance( $id ) <= 0 ) {
                            $wpdb->query( $wpdb->prepare( "UPDATE {$sp_pay} SET status = 'rejected' WHERE account_id = %d AND status = 'requested'", $id ) );
                        }
                        echo '<div class="notice notice-success is-dismissible"><p>Removido $' . number_format( $amt, 2 ) . ' dos ganhos patrocinados desta conta.</p></div>';
                    } else {
                        echo '<div class="notice notice-warning is-dismissible"><p>Esta conta não tem saldo patrocinado para remover.</p></div>';
                    }
                }
                break;
            case 'sp_clear_earnings':
                $wpdb->delete( $wpdb->prefix . 'mp_sponsored_earnings', [ 'account_id' => $id ] );
                delete_option( 'mp_sponsored_clawback_' . $id );
                echo '<div class="notice notice-success is-dismissible"><p>Registo de ganhos apagado (histórico de escuta + devoluções).</p></div>';
                break;
            case 'sp_clear_sessions':
                $wpdb->delete( $wpdb->prefix . 'mp_sponsored_sessions', [ 'account_id' => $id ] );
                echo '<div class="notice notice-success is-dismissible"><p>Sessões anti-fraude apagadas.</p></div>';
                break;
            case 'sp_clear_payouts':
                $wpdb->delete( $wpdb->prefix . 'mp_sponsored_payouts', [ 'account_id' => $id ] );
                echo '<div class="notice notice-success is-dismissible"><p>Histórico de pagamentos apagado.</p></div>';
                break;
            case 'sp_clear_flags':
                delete_option( 'mp_sponsored_flags_' . $id );
                delete_option( 'mp_sponsored_score_' . $id );
                delete_option( 'mp_sponsored_verify_' . $id );
                echo '<div class="notice notice-success is-dismissible"><p>Bandeiras de fraude e verificação limpas.</p></div>';
                break;
            case 'sp_reset_program':
                // Reset TOTAL do programa para este utilizador (recomeça do zero).
                $wpdb->delete( $wpdb->prefix . 'mp_sponsored_earnings', [ 'account_id' => $id ] );
                $wpdb->delete( $wpdb->prefix . 'mp_sponsored_sessions', [ 'account_id' => $id ] );
                $wpdb->delete( $wpdb->prefix . 'mp_sponsored_payouts', [ 'account_id' => $id ] );
                delete_option( 'mp_sponsored_accept_' . $id );
                delete_option( 'mp_sponsored_clawback_' . $id );
                delete_option( 'mp_sponsored_flags_' . $id );
                delete_option( 'mp_sponsored_score_' . $id );
                delete_option( 'mp_sponsored_verify_' . $id );
                echo '<div class="notice notice-success is-dismissible"><p>Programa reposto para esta conta: ganhos, sessões, pagamentos, contrato e bandeiras — tudo apagado.</p></div>';
                break;
        }
        if ( ! in_array( $action, [ 'remove_earn', 'sp_clear_earnings', 'sp_clear_sessions', 'sp_clear_payouts', 'sp_clear_flags', 'sp_reset_program' ], true ) ) {
            echo '<div class="notice notice-success is-dismissible"><p>Conta atualizada.</p></div>';
        }
    }

    $features = mp_get_features();
    $access   = get_option( 'mp_access_gate', 'open' );

    global $wpdb;
    $accounts = $wpdb->get_results( "SELECT id, email, name, status, is_vip, vip_until, vip_source, vip_full_until, platform, device_model, device_id, sync_data, sync_updated, created_at, last_login FROM {$wpdb->prefix}mp_accounts ORDER BY id DESC LIMIT 500" );
    $vip_count = 0;
    foreach ( $accounts as $a ) { if ( (int) $a->is_vip === 1 ) { $vip_count++; } }

    // Estatísticas da nuvem por utilizador (1 chamada só): nº de faixas + bytes.
    $cloud_stats = [];
    if ( function_exists( 'mp_s3_enabled' ) && mp_s3_enabled() ) {
        foreach ( mp_s3_list( 'players/', 10000 ) as $obj ) {
            if ( ! preg_match( '#^players/(\d+)/#', $obj['key'], $m ) ) {
                continue;
            }
            $uid = (int) $m[1];
            if ( ! isset( $cloud_stats[ $uid ] ) ) {
                $cloud_stats[ $uid ] = [ 'tracks' => 0, 'bytes' => 0 ];
            }
            $cloud_stats[ $uid ]['bytes'] += (int) $obj['size'];
            $fname = basename( $obj['key'] );
            $is_audio = ( 0 === strpos( $fname, 'track.' ) )
                || preg_match( '/\.(mp3|m4a|aac|ogg|wav|flac)(\.enc)?$/i', $fname );
            if ( false !== strpos( $obj['key'], '/audio/' ) && $is_audio ) {
                $cloud_stats[ $uid ]['tracks']++;
            }
        }
    }

    $orders_tbl = $wpdb->prefix . 'mp_vip_orders';
    $acct_tbl   = $wpdb->prefix . 'mp_accounts';
    $orders = $wpdb->get_results( "SELECT o.*, a.email FROM {$orders_tbl} o LEFT JOIN {$acct_tbl} a ON a.id = o.account_id WHERE o.status = 'pending' ORDER BY o.id DESC LIMIT 200" );
    $mt     = get_option( 'mp_message_type', 'info' );
    $mp_url = admin_url( 'admin.php?page=mp-control' );
    $yt_subs = function_exists( 'mp_feature_subtitles' ) ? mp_feature_subtitles() : [];
    ?>
    <div class="wrap mp-admin">
        <?php mp_admin_styles(); ?>

        <div class="mp-hero">
            <div class="mp-hero-left">
                <div class="mp-hero-icon"><span class="dashicons dashicons-format-audio"></span></div>
                <div>
                    <h1>1MZ Music Player</h1>
                    <p class="mp-sub">Controlo remoto do app — versões, acesso, add-ons, VIP e contas.</p>
                </div>
            </div>
            <div class="mp-endpoint">
                <span class="mp-endpoint-label">Endpoint do app</span>
                <code><?php echo esc_html( rest_url( MP_API_NAMESPACE . '/app/config' ) ); ?></code>
            </div>
        </div>

        <div class="mp-stats">
            <div class="mp-stat"><div class="mp-stat-num"><?php echo count( $accounts ); ?></div><div class="mp-stat-label">Contas do leitor</div></div>
            <div class="mp-stat mp-stat--gold"><div class="mp-stat-num"><?php echo (int) $vip_count; ?></div><div class="mp-stat-label">Membros VIP</div></div>
            <div class="mp-stat <?php echo count( $orders ) ? 'mp-stat--alert' : ''; ?>"><div class="mp-stat-num"><?php echo count( $orders ); ?></div><div class="mp-stat-label">Pedidos pendentes</div></div>
            <div class="mp-stat"><div class="mp-stat-num"><?php echo count( array_filter( $features, function( $f ){ return $f['enabled']; } ) ); ?></div><div class="mp-stat-label">Funções ativas</div></div>
        </div>

        <nav class="mp-tabs">
            <button type="button" class="mp-tab-btn is-active" data-tab="definicoes"><span class="dashicons dashicons-admin-settings"></span> Definições</button>
            <button type="button" class="mp-tab-btn" data-tab="addons"><span class="dashicons dashicons-admin-plugins"></span> Add-ons</button>
            <button type="button" class="mp-tab-btn" data-tab="contas"><span class="dashicons dashicons-groups"></span> Contas<span class="mp-tab-count"><?php echo count( $accounts ); ?></span></button>
            <button type="button" class="mp-tab-btn" data-tab="nuvem"><span class="dashicons dashicons-cloud"></span> Nuvem</button>
            <?php if ( defined( 'RMBZ_SPONSORED_UNIFIED' ) ) : ?>
            <a class="mp-tab-btn" style="text-decoration:none" href="<?php echo esc_url( rmbz_sp_admin_url() ); ?>"><span class="dashicons dashicons-megaphone"></span> Campanhas</a>
            <?php else : ?>
            <button type="button" class="mp-tab-btn" data-tab="parcerias"><span class="dashicons dashicons-money-alt"></span> Parcerias</button>
            <?php endif; ?>
        </nav>

        <style>
            .mp-fmt-wrap{width:100%;overflow-x:auto;border:1px solid #e0e5e2;border-radius:8px}
            .mp-fmt-table{width:100%;min-width:470px;border-collapse:collapse}
            .mp-fmt-table th,.mp-fmt-table td{padding:9px 10px;text-align:center;border-bottom:1px solid #eceef1;font-size:13px}
            .mp-fmt-table th:first-child,.mp-fmt-table td:first-child{text-align:left}
            .mp-fmt-table thead th{background:#f5f7f6;color:#5f6368;font-size:11.5px;text-transform:uppercase;letter-spacing:0}
            .mp-fmt-table tbody tr:hover{background:#f8faf9}
            .mp-fmt-table tbody tr:last-child td{border-bottom:0}
            .mp-fmt-table input[type=radio]{width:17px;height:17px;margin:0}
        </style>
        <div class="mp-tab" id="tab-definicoes">
        <form method="post">
            <?php wp_nonce_field( 'mp_save_settings' ); ?>

            <div class="mp-settings-overview">
                <div class="mp-settings-title">
                    <span class="dashicons dashicons-admin-settings"></span>
                    <div><h2>Configuração do leitor</h2><p>Aplicação, monetização e infraestrutura num único lugar.</p></div>
                </div>
                <div class="mp-settings-statuses" aria-label="Estado atual">
                    <span class="mp-settings-status <?php echo 'blocked' === $access ? 'is-danger' : 'is-success'; ?>"><i></i><?php echo 'blocked' === $access ? 'App bloqueado' : ( 'account_required' === $access ? 'Conta obrigatória' : 'Acesso aberto' ); ?></span>
                    <span class="mp-settings-status <?php echo get_option( 'mp_ads_enabled', 0 ) ? 'is-info' : ''; ?>"><i></i><?php echo get_option( 'mp_ads_enabled', 0 ) ? 'Anúncios ativos' : 'Anúncios desligados'; ?></span>
                    <span class="mp-settings-status <?php echo ( function_exists( 'mp_s3_enabled' ) && mp_s3_enabled() ) ? 'is-success' : ''; ?>"><i></i><?php echo ( function_exists( 'mp_s3_enabled' ) && mp_s3_enabled() ) ? 'Cloud ligada' : 'Cloud por configurar'; ?></span>
                </div>
            </div>
            <nav class="mp-settings-nav" aria-label="Secções das definições">
                <a href="#mp-settings-app"><span class="dashicons dashicons-smartphone"></span> Aplicação</a>
                <a href="#mp-settings-vip"><span class="dashicons dashicons-star-filled"></span> VIP e receitas</a>
                <a href="#mp-settings-cloud"><span class="dashicons dashicons-cloud"></span> Cloud</a>
            </nav>

            <div class="mp-section-heading" id="mp-settings-app">
                <div><span class="dashicons dashicons-smartphone"></span><div><h2>Aplicação</h2><p>Versão, acesso, comunicação, compatibilidade e anúncios.</p></div></div>
                <span class="mp-section-count">5 módulos</span>
            </div>
            <?php
                $af_now = function_exists( 'mp_audio_formats' ) ? mp_audio_formats() : [];
                $af_meta = [
                    'mp3' => 'MP3', 'aac' => 'AAC / M4A', 'flac' => 'FLAC', 'ogg' => 'OGG / Opus',
                    'wav' => 'WAV', 'wma' => 'WMA', 'alac' => 'ALAC', 'midi' => 'MIDI', 'amr' => 'AMR',
                ];
                $af_counts = array_count_values( $af_now );
                $message_active = '' !== trim( (string) get_option( 'mp_message_text', '' ) );
                $ads_active = (bool) get_option( 'mp_ads_enabled', 0 );
            ?>
            <div class="mp-grid mp-grid--application">
                <button type="button" class="mp-settings-module" data-modal="mp-settings-modal-version" aria-haspopup="dialog">
                    <span class="mp-settings-module-head"><span class="mp-ic"><span class="dashicons dashicons-update"></span></span><span><strong>Versão / Atualização</strong><small>Distribuição e bloqueio remoto</small></span></span>
                    <span class="mp-settings-module-metrics"><span><b><?php echo (int) get_option( 'mp_min_version_code', 0 ); ?></b><small>Mínima</small></span><span><b><?php echo (int) get_option( 'mp_latest_version_code', 0 ); ?></b><small>Atual</small></span></span>
                    <span class="mp-settings-module-foot"><span class="mp-mini-state <?php echo get_option( 'mp_version_blocked', 0 ) ? 'is-danger' : 'is-success'; ?>"><?php echo get_option( 'mp_version_blocked', 0 ) ? 'Bloqueada' : 'Operacional'; ?></span><span>Configurar <span class="dashicons dashicons-arrow-right-alt2"></span></span></span>
                </button>
                <button type="button" class="mp-settings-module" data-modal="mp-settings-modal-access" aria-haspopup="dialog">
                    <span class="mp-settings-module-head"><span class="mp-ic"><span class="dashicons dashicons-lock"></span></span><span><strong>Acesso ao app</strong><small>Autenticação e manutenção</small></span></span>
                    <span class="mp-settings-module-summary"><?php echo 'blocked' === $access ? 'Acesso suspenso para todos' : ( 'account_required' === $access ? 'Entrada apenas com conta' : 'Leitor aberto sem login' ); ?></span>
                    <span class="mp-settings-module-foot"><span class="mp-mini-state <?php echo 'blocked' === $access ? 'is-danger' : 'is-success'; ?>"><?php echo 'blocked' === $access ? 'Bloqueado' : 'Disponível'; ?></span><span>Configurar <span class="dashicons dashicons-arrow-right-alt2"></span></span></span>
                </button>
                <button type="button" class="mp-settings-module" data-modal="mp-settings-modal-message" aria-haspopup="dialog">
                    <span class="mp-settings-module-head"><span class="mp-ic"><span class="dashicons dashicons-megaphone"></span></span><span><strong>Mensagem global</strong><small>Aviso enviado ao leitor</small></span></span>
                    <span class="mp-settings-module-summary"><?php echo $message_active ? 'Mensagem ' . esc_html( ucfirst( $mt ) ) . ' publicada' : 'Nenhum aviso publicado'; ?></span>
                    <span class="mp-settings-module-foot"><span class="mp-mini-state <?php echo $message_active ? 'is-info' : ''; ?>"><?php echo $message_active ? 'Publicada' : 'Inativa'; ?></span><span>Configurar <span class="dashicons dashicons-arrow-right-alt2"></span></span></span>
                </button>
                <button type="button" class="mp-settings-module" data-modal="mp-settings-modal-formats" aria-haspopup="dialog">
                    <span class="mp-settings-module-head"><span class="mp-ic"><span class="dashicons dashicons-format-audio"></span></span><span><strong>Formatos de áudio</strong><small>Compatibilidade por plano</small></span></span>
                    <span class="mp-settings-module-metrics"><span><b><?php echo count( $af_meta ); ?></b><small>Formatos</small></span><span><b><?php echo (int) ( $af_counts['off'] ?? 0 ); ?></b><small>Bloqueados</small></span></span>
                    <span class="mp-settings-module-foot"><span class="mp-mini-state is-success">Configurado</span><span>Configurar <span class="dashicons dashicons-arrow-right-alt2"></span></span></span>
                </button>
                <button type="button" class="mp-settings-module" data-modal="mp-settings-modal-ads" aria-haspopup="dialog">
                    <span class="mp-settings-module-head"><span class="mp-ic"><span class="dashicons dashicons-megaphone"></span></span><span><strong>Anúncios (AdMob)</strong><small>Receita e dias VIP</small></span></span>
                    <span class="mp-settings-module-summary"><?php echo $ads_active ? 'Banner, listas e recompensas disponíveis' : 'Publicidade desativada no app'; ?></span>
                    <span class="mp-settings-module-foot"><span class="mp-mini-state <?php echo $ads_active ? 'is-info' : ''; ?>"><?php echo $ads_active ? 'Ativos' : 'Desligados'; ?></span><span>Configurar <span class="dashicons dashicons-arrow-right-alt2"></span></span></span>
                </button>
            </div>

            <div class="mp-modal mp-settings-modal" id="mp-settings-modal-version" role="dialog" aria-modal="true" aria-labelledby="mp-settings-title-version" aria-hidden="true">
                <div class="mp-modal-box mp-settings-dialog mp-settings-dialog--md">
                    <div class="mp-modal-head"><div><h3 id="mp-settings-title-version">Versão / Atualização</h3><p>Controla a distribuição e os bloqueios remotamente.</p></div><button type="button" class="mp-modal-x" data-close aria-label="Fechar">&times;</button></div>
                    <div class="mp-modal-body"><div class="mp-dialog-grid">
                        <div class="mp-field"><label>Versão mínima (code)</label><input type="number" name="mp_min_version_code" value="<?php echo (int) get_option( 'mp_min_version_code', 0 ); ?>"><span class="mp-hint">Abaixo deste código, a atualização é obrigatória.</span></div>
                        <div class="mp-field"><label>Última versão (code)</label><input type="number" name="mp_latest_version_code" value="<?php echo (int) get_option( 'mp_latest_version_code', 0 ); ?>"><span class="mp-hint">Abaixo deste código, o app sugere atualizar.</span></div>
                        <div class="mp-field mp-field--full"><label>Última versão (nome)</label><input type="text" name="mp_latest_version" value="<?php echo esc_attr( get_option( 'mp_latest_version', '' ) ); ?>"></div>
                        <div class="mp-field mp-field--full"><label>URL da loja</label><input type="url" name="mp_store_url" value="<?php echo esc_attr( get_option( 'mp_store_url', '' ) ); ?>" placeholder="https://play.google.com/..."></div>
                        <div class="mp-field mp-field--full"><label>Mensagem de atualização</label><input type="text" name="mp_force_message" value="<?php echo esc_attr( get_option( 'mp_force_message', '' ) ); ?>"></div>
                        <label class="mp-check mp-danger-option"><input type="checkbox" name="mp_version_blocked" <?php checked( get_option( 'mp_version_blocked', 0 ), 1 ); ?>><span><strong>Bloqueio de emergência</strong><small>Bloquear todas as versões imediatamente.</small></span></label>
                    </div></div>
                    <div class="mp-modal-foot"><button type="button" class="mp-btn mp-btn--outline" data-close>Cancelar</button><button type="submit" name="mp_save" value="1" class="mp-btn mp-btn--primary"><span class="dashicons dashicons-saved"></span> Guardar alterações</button></div>
                </div>
            </div>

            <div class="mp-modal mp-settings-modal" id="mp-settings-modal-access" role="dialog" aria-modal="true" aria-labelledby="mp-settings-title-access" aria-hidden="true">
                <div class="mp-modal-box mp-settings-dialog mp-settings-dialog--sm">
                    <div class="mp-modal-head"><div><h3 id="mp-settings-title-access">Acesso ao app</h3><p>Define quem pode entrar no leitor.</p></div><button type="button" class="mp-modal-x" data-close aria-label="Fechar">&times;</button></div>
                    <div class="mp-modal-body"><div class="mp-field"><label>Modo</label><select name="mp_access_gate"><option value="open" <?php selected( $access, 'open' ); ?>>Aberto (leitor padrão, sem login)</option><option value="account_required" <?php selected( $access, 'account_required' ); ?>>Exige conta para usar o app</option><option value="blocked" <?php selected( $access, 'blocked' ); ?>>Bloqueado (manutenção)</option></select></div><div class="mp-field"><label>Mensagem do gate</label><input type="text" name="mp_access_message" value="<?php echo esc_attr( get_option( 'mp_access_message', '' ) ); ?>"><span class="mp-hint">Aparece quando a entrada exige uma ação do utilizador.</span></div></div>
                    <div class="mp-modal-foot"><button type="button" class="mp-btn mp-btn--outline" data-close>Cancelar</button><button type="submit" name="mp_save" value="1" class="mp-btn mp-btn--primary"><span class="dashicons dashicons-saved"></span> Guardar alterações</button></div>
                </div>
            </div>

            <div class="mp-modal mp-settings-modal" id="mp-settings-modal-message" role="dialog" aria-modal="true" aria-labelledby="mp-settings-title-message" aria-hidden="true">
                <div class="mp-modal-box mp-settings-dialog mp-settings-dialog--sm">
                    <div class="mp-modal-head"><div><h3 id="mp-settings-title-message">Mensagem global</h3><p>Publica um aviso dentro do app.</p></div><button type="button" class="mp-modal-x" data-close aria-label="Fechar">&times;</button></div>
                    <div class="mp-modal-body"><div class="mp-field"><label>Tipo</label><select name="mp_message_type"><option value="info" <?php selected( $mt, 'info' ); ?>>Informação</option><option value="warning" <?php selected( $mt, 'warning' ); ?>>Aviso</option><option value="maintenance" <?php selected( $mt, 'maintenance' ); ?>>Manutenção</option></select></div><div class="mp-field"><label>Texto da mensagem</label><textarea name="mp_message_text" rows="5" placeholder="Deixa vazio para remover a mensagem."><?php echo esc_textarea( get_option( 'mp_message_text', '' ) ); ?></textarea><span class="mp-hint">O texto vazio desativa o aviso global.</span></div></div>
                    <div class="mp-modal-foot"><button type="button" class="mp-btn mp-btn--outline" data-close>Cancelar</button><button type="submit" name="mp_save" value="1" class="mp-btn mp-btn--primary"><span class="dashicons dashicons-saved"></span> Guardar alterações</button></div>
                </div>
            </div>

            <div class="mp-modal mp-settings-modal" id="mp-settings-modal-formats" role="dialog" aria-modal="true" aria-labelledby="mp-settings-title-formats" aria-hidden="true">
                <div class="mp-modal-box mp-settings-dialog mp-settings-dialog--lg">
                    <div class="mp-modal-head"><div><h3 id="mp-settings-title-formats">Formatos de áudio</h3><p>Escolhe o nível de acesso de cada formato.</p></div><button type="button" class="mp-modal-x" data-close aria-label="Fechar">&times;</button></div>
                    <div class="mp-modal-body"><div class="mp-fmt-wrap"><table class="mp-fmt-table"><thead><tr><th>Formato</th><th>Desligado</th><th>Livre</th><th>Conta</th><th>VIP</th></tr></thead><tbody><?php foreach ( $af_meta as $fk => $flabel ) : $cur = $af_now[ $fk ] ?? 'free'; ?><tr><td><strong><?php echo esc_html( $flabel ); ?></strong></td><?php foreach ( [ 'off', 'free', 'account', 'vip' ] as $lvl ) : ?><td><input type="radio" name="mp_audio_fmt[<?php echo esc_attr( $fk ); ?>]" value="<?php echo $lvl; ?>" <?php checked( $cur, $lvl ); ?> aria-label="<?php echo esc_attr( $flabel . ' ' . $lvl ); ?>"></td><?php endforeach; ?></tr><?php endforeach; ?></tbody></table></div><p class="mp-hint">WMA, ALAC e outros formatos compatíveis usam o descodificador FFmpeg incluído no app.</p></div>
                    <div class="mp-modal-foot"><button type="button" class="mp-btn mp-btn--outline" data-close>Cancelar</button><button type="submit" name="mp_save" value="1" class="mp-btn mp-btn--primary"><span class="dashicons dashicons-saved"></span> Guardar alterações</button></div>
                </div>
            </div>

            <div class="mp-modal mp-settings-modal" id="mp-settings-modal-ads" role="dialog" aria-modal="true" aria-labelledby="mp-settings-title-ads" aria-hidden="true">
                <div class="mp-modal-box mp-settings-dialog mp-settings-dialog--xl">
                    <div class="mp-modal-head"><div><h3 id="mp-settings-title-ads">Anúncios (AdMob)</h3><p>Configura receita, frequência e recompensas VIP.</p></div><button type="button" class="mp-modal-x" data-close aria-label="Fechar">&times;</button></div>
                    <div class="mp-modal-body"><div class="mp-dialog-grid">
                        <label class="mp-check mp-field--full"><input type="checkbox" name="mp_ads_enabled" <?php checked( $ads_active, true ); ?>><span><strong>Mostrar anúncios no app</strong><small>Ativa os blocos configurados abaixo.</small></span></label>
                        <div class="mp-field"><label>ID do bloco Banner</label><input type="text" name="mp_ads_banner_id" value="<?php echo esc_attr( get_option( 'mp_ads_banner_id', '' ) ); ?>" placeholder="ca-app-pub-…/…"><span class="mp-hint">Aparece no fundo do ecrã.</span></div>
                        <div class="mp-field"><label>ID do bloco Intersticial</label><input type="text" name="mp_ads_inter_id" value="<?php echo esc_attr( get_option( 'mp_ads_inter_id', '' ) ); ?>" placeholder="ca-app-pub-…/…"><span class="mp-hint">Anúncio de ecrã inteiro.</span></div>
                        <div class="mp-field"><label>Intersticial a cada N músicas</label><input type="number" min="0" max="100" name="mp_ads_inter_every" value="<?php echo (int) get_option( 'mp_ads_inter_every', 0 ); ?>"><span class="mp-hint">0 desliga o intersticial.</span></div>
                        <div class="mp-field"><label>ID do bloco Nativo (nas listas)</label><input type="text" name="mp_ads_native_id" value="<?php echo esc_attr( get_option( 'mp_ads_native_id', '' ) ); ?>" placeholder="ca-app-pub-…/…"><span class="mp-hint">Linha patrocinada dentro das listas.</span></div>
                        <label class="mp-check mp-field--full"><input type="checkbox" name="mp_ads_vip_free" <?php checked( get_option( 'mp_ads_vip_free', 1 ), 1 ); ?>><span><strong>VIP sem publicidade</strong><small>Membros VIP não veem anúncios.</small></span></label>
                        <div class="mp-card-section-title mp-field--full"><span class="dashicons dashicons-awards"></span><div><strong>Premiados e dias VIP</strong><small>Recompensa por visualizações concluídas</small></div></div>
                        <div class="mp-field mp-field--full"><label>ID do bloco Premiado</label><input type="text" name="mp_ads_rew_id" value="<?php echo esc_attr( get_option( 'mp_ads_rew_id', '' ) ); ?>" placeholder="ca-app-pub-…/…"><span class="mp-hint">Vazio desliga as recompensas.</span></div>
                        <div class="mp-field"><label>Anúncios para completar</label><input type="number" min="1" max="100" name="mp_ads_rew_target" value="<?php echo (int) get_option( 'mp_ads_rew_target', 10 ); ?>"></div>
                        <div class="mp-field"><label>Dias VIP concedidos</label><input type="number" min="1" max="365" name="mp_ads_rew_days" value="<?php echo (int) get_option( 'mp_ads_rew_days', 3 ); ?>"></div>
                        <div class="mp-field mp-field--full"><label>Máximo premiado por dia</label><input type="number" min="1" max="200" name="mp_ads_rew_daily" value="<?php echo (int) get_option( 'mp_ads_rew_daily', 20 ); ?>"><span class="mp-hint">Limite anti-abuso por conta.</span></div>
                        <div class="mp-settings-subsection mp-field--full"><label>Permissões do VIP ganho por anúncios</label><label class="mp-check"><input type="checkbox" checked disabled>Sincronizar playlists, gostos e definições</label><label class="mp-check"><input type="checkbox" name="mp_ads_rew_cloud_audio" <?php checked( get_option( 'mp_ads_rew_cloud_audio', 0 ), 1 ); ?>>Permitir enviar ficheiros de música para a nuvem</label><span class="mp-hint">O áudio permanece bloqueado no servidor quando esta opção está desligada.</span></div>
                    </div></div>
                    <div class="mp-modal-foot"><button type="button" class="mp-btn mp-btn--outline" data-close>Cancelar</button><button type="submit" name="mp_save" value="1" class="mp-btn mp-btn--primary"><span class="dashicons dashicons-saved"></span> Guardar alterações</button></div>
                </div>
            </div>

            <div class="mp-section-heading" id="mp-settings-vip">
                <div><span class="dashicons dashicons-star-filled"></span><div><h2>VIP e receitas</h2><p>Planos pagos, recompensas e regras de subscrição.</p></div></div>
                <span class="mp-section-count">Subscrição</span>
            </div>
            <div class="mp-grid mp-grid--vip">

                <div class="mp-card mp-card--packages">
                    <div class="mp-card-head"><div class="mp-ic"><span class="dashicons dashicons-star-filled"></span></div><div><h2>Pacotes VIP</h2><div class="mp-card-sub">Preços e paywall</div></div></div>
                    <label class="mp-check"><input type="checkbox" name="mp_vip_enabled" <?php checked( get_option( 'mp_vip_enabled', 1 ), 1 ); ?>> Mostrar o ecrã «Tornar-se VIP» no app</label>
                    <div class="mp-row2">
                        <div class="mp-field"><label>Moeda</label><input type="text" name="mp_vip_currency" value="<?php echo esc_attr( get_option( 'mp_vip_currency', '$' ) ); ?>" placeholder="$ / MT"></div>
                        <div class="mp-field"><label>Poupança (%)</label><input type="number" name="mp_vip_savings" value="<?php echo (int) get_option( 'mp_vip_savings', 44 ); ?>"></div>
                    </div>
                    <div class="mp-row2">
                        <div class="mp-field"><label>Preço mensal</label><input type="text" name="mp_vip_monthly" value="<?php echo esc_attr( get_option( 'mp_vip_monthly', '2.99' ) ); ?>"></div>
                        <div class="mp-field"><label>Preço anual</label><input type="text" name="mp_vip_annual" value="<?php echo esc_attr( get_option( 'mp_vip_annual', '19.99' ) ); ?>"></div>
                        <div class="mp-field"><label>Anual / mês</label><input type="text" name="mp_vip_annual_permonth" value="<?php echo esc_attr( get_option( 'mp_vip_annual_permonth', '1.67' ) ); ?>"></div>
                    </div>
                    <div class="mp-field"><label>URL para assinar</label><input type="url" name="mp_vip_cta" value="<?php echo esc_attr( get_option( 'mp_vip_cta', '' ) ); ?>" placeholder="https://1musicmoz.com/vip"></div>
                    <div class="mp-field"><label>Instruções de pagamento</label><textarea name="mp_vip_pay_instructions" rows="2" placeholder="Ex: Envia por M-Pesa para 84xxxxxxx e usa a referência."><?php echo esc_textarea( get_option( 'mp_vip_pay_instructions', '' ) ); ?></textarea><span class="mp-hint">Mostrado ao user depois de criar o pedido.</span></div>
                </div>

                <div class="mp-card mp-card--muted mp-card--vip-flow">
                    <div class="mp-card-head"><div class="mp-ic"><span class="dashicons dashicons-info-outline"></span></div><div><h2>Como funciona o VIP</h2><div class="mp-card-sub">Fluxo de assinatura</div></div></div>
                    <ol class="mp-steps">
                        <li>O utilizador toca <strong>«Ativar VIP»</strong> no app e cria um pedido.</li>
                        <li>O pedido aparece em <strong>«Pedidos VIP pendentes»</strong> abaixo.</li>
                        <li>Confirmas o pagamento e clicas <strong>Aprovar</strong> → o VIP é concedido com validade.</li>
                        <li>As funções marcadas <strong>«Só VIP»</strong> desbloqueiam no app.</li>
                    </ol>
                </div>

                <?php
                    $s3_secret_set = trim( (string) get_option( 'mp_s3_secret', '' ) ) !== '';
                    $s3_on         = (bool) get_option( 'mp_s3_enabled', 0 );
                ?>
                <div class="mp-section-heading mp-section-heading--inside" id="mp-settings-cloud">
                    <div><span class="dashicons dashicons-cloud"></span><div><h2>Cloud</h2><p>Credenciais, quotas e cópias de segurança.</p></div></div>
                    <span class="mp-section-count"><?php echo $s3_on ? 'Ativa' : 'Inativa'; ?></span>
                </div>
                <div class="mp-card mp-card--cloud">
                    <div class="mp-card-head"><div class="mp-ic"><span class="dashicons dashicons-cloud"></span></div><div><h2>Armazenamento na cloud (S3) <?php echo ( function_exists( 'mp_s3_enabled' ) && mp_s3_enabled() ) ? '<span style="color:#1db985;font-size:12px;font-weight:700">· configurado</span>' : '<span style="color:#999;font-size:12px;font-weight:600">· por configurar</span>'; ?></h2><div class="mp-card-sub">Músicas e dados dos artistas · backup dos utilizadores</div></div></div>
                    <label class="mp-check"><input type="checkbox" name="mp_s3_enabled" <?php checked( $s3_on, true ); ?>> Ativar armazenamento na cloud</label>
                    <div class="mp-field"><label>Bucket</label><input type="text" name="mp_s3_bucket" value="<?php echo esc_attr( get_option( 'mp_s3_bucket', '' ) ); ?>" placeholder="o-meu-bucket"></div>
                    <div class="mp-field"><label>Região</label><input type="text" name="mp_s3_region" value="<?php echo esc_attr( get_option( 'mp_s3_region', 'us-east-1' ) ); ?>" placeholder="us-east-1"></div>
                    <div class="mp-field"><label>Endpoint (opcional — só para S3-compatível: Wasabi, Spaces, R2…)</label><input type="text" name="mp_s3_endpoint" value="<?php echo esc_attr( get_option( 'mp_s3_endpoint', '' ) ); ?>" placeholder="deixa vazio para AWS"></div>
                    <div class="mp-field"><label>Access Key ID</label><input type="text" name="mp_s3_key" value="<?php echo esc_attr( get_option( 'mp_s3_key', '' ) ); ?>" placeholder="AKIA..."></div>
                    <div class="mp-field"><label>Secret Access Key</label><input type="password" name="mp_s3_secret" autocomplete="new-password" data-1p-ignore data-lpignore="true" placeholder="<?php echo $s3_secret_set ? '•••••••••• (guardado — deixa vazio para manter)' : '••••••••••'; ?>"><span class="mp-hint">Fica <strong>só no servidor</strong>; o app recebe apenas URLs pré-assinadas temporárias.</span></div>
                    <div class="mp-field"><label>Quota de músicas por utilizador (MB)</label><input type="number" name="mp_cloud_quota_mb" min="0" value="<?php echo (int) get_option( 'mp_cloud_quota_mb', 0 ); ?>"><span class="mp-hint">0 = sem limite. Ao atingir a quota o app recusa novos envios.</span></div>
                    <div class="mp-field"><label>Quota VIP deslizante (GB)</label><input type="number" name="mp_vip_quota_gb" min="0" value="<?php echo (int) get_option( 'mp_vip_quota_gb', 1024 ); ?>"><span class="mp-hint">Padrão 1024 GB (1 TB). É proporcional aos dias de VIP restantes: cheia com 30+ dias, metade com 15, e vai caindo até expirar. VIP vitalício = sempre cheia. 0 = desativada (usa a quota normal).</span></div>
                    <div class="mp-field"><label>Dispositivos com cópia de segurança (por conta VIP)</label><input type="number" value="5" disabled><span class="mp-hint">Limite fixo de 5 dispositivos VIP. No app, o utilizador pode guardar este telefone como novo ou substituir a cópia de outro aparelho.</span></div>
                    <button type="submit" name="mp_s3_test" class="mp-btn mp-btn--outline" style="margin-top:8px"><span class="dashicons dashicons-yes-alt"></span> Guardar e testar ligação</button>
                    <span class="mp-hint">Faz um envio + leitura + remoção reais no bucket e diz-te já se está tudo certo.</span>
                </div>

            </div>

            <div class="mp-save-bar">
                <span class="mp-save-hint"><span class="dashicons dashicons-info-outline"></span> As alterações aplicam-se no app ao recarregar (puxar para atualizar ou reabrir).</span>
                <button type="submit" name="mp_save" class="mp-btn mp-btn--primary"><span class="dashicons dashicons-saved"></span> Guardar definições</button>
            </div>
        </form>
        </div><!-- /tab-definicoes -->

        <div class="mp-tab" id="tab-addons" hidden>
            <div class="mp-section-label"><span class="dashicons dashicons-admin-plugins"></span> Add-ons do app</div>
            <p class="mp-hint" style="margin:-4px 2px 16px">Liga/desliga cada add-on com o interruptor, ou abre <strong>Configurar</strong> para definir regras detalhadas.</p>
            <div class="mp-grid">
                <?php
                $addon_icons = [
                    'youtube_addon'    => [ 'dashicons-video-alt3', '#FF2D2D' ],
                    'offline_download' => [ 'dashicons-download', '#EC407A' ],
                    'lyrics'           => [ 'dashicons-format-status', '#E6A700' ],
                    'equalizer'        => [ 'dashicons-controls-volumeon', '#5C6BC0' ],
                    'resume_playback'  => [ 'dashicons-backup', '#26A69A' ],
                    'ai_assistant'     => [ 'dashicons-superhero', '#7C4DFF' ],
                ];
                foreach ( $features as $f ) :
                    $key   = $f['key'];
                    $ic    = $addon_icons[ $key ] ?? [ 'dashicons-admin-plugins', '#7E57C2' ];
                    $on    = ! empty( $f['enabled'] );
                    $sub   = $yt_subs[ $key ] ?? '';
                ?>
                <div class="mp-addon">
                    <div class="mp-addon-top">
                        <div class="mp-addon-ic" style="background:<?php echo esc_attr( $ic[1] ); ?>1f;color:<?php echo esc_attr( $ic[1] ); ?>"><span class="dashicons <?php echo esc_attr( $ic[0] ); ?>"></span></div>
                        <div class="mp-addon-info">
                            <div class="mp-addon-name"><?php echo esc_html( $f['label'] ); ?></div>
                            <div class="mp-addon-sub"><?php echo esc_html( $sub ); ?></div>
                        </div>
                        <form method="post" action="<?php echo esc_url( $mp_url . '#addons' ); ?>" class="mp-addon-switch-form">
                            <?php wp_nonce_field( 'mp_addon_toggle' ); ?>
                            <input type="hidden" name="mp_addon_key" value="<?php echo esc_attr( $key ); ?>">
                            <input type="hidden" name="mp_addon_toggle" value="<?php echo $on ? 'off' : 'on'; ?>">
                            <label class="mp-switch" title="<?php echo $on ? 'Desligar' : 'Ligar'; ?>">
                                <input type="checkbox" <?php checked( $on ); ?> onchange="this.form.submit()">
                                <span class="mp-switch-slider"></span>
                            </label>
                        </form>
                    </div>
                    <div class="mp-addon-foot">
                        <span class="mp-pill <?php echo $on ? 'mp-pill--active' : 'mp-pill--muted'; ?>"><?php echo $on ? 'Ativo' : 'Inativo'; ?></span>
                        <?php if ( ! empty( $f['vip_only'] ) ) : ?><span class="mp-pill mp-pill--vip">Só VIP</span><?php endif; ?>
                        <?php if ( ! empty( $f['requires_account'] ) ) : ?><span class="mp-pill mp-pill--muted">Exige conta</span><?php endif; ?>
                        <button type="button" class="mp-btn mp-btn--outline" data-modal="mp-modal-<?php echo esc_attr( $key ); ?>" style="margin-left:auto"><span class="dashicons dashicons-admin-generic"></span> Configurar</button>
                    </div>
                </div>
                <?php endforeach; ?>
            </div>

            <?php foreach ( $features as $f ) :
                $key = $f['key'];
            ?>
            <div class="mp-modal" id="mp-modal-<?php echo esc_attr( $key ); ?>">
                <div class="mp-modal-box">
                    <form method="post" action="<?php echo esc_url( $mp_url . '#addons' ); ?>">
                        <?php wp_nonce_field( 'mp_addon_save' ); ?>
                        <input type="hidden" name="mp_addon_key" value="<?php echo esc_attr( $key ); ?>">
                        <div class="mp-modal-head">
                            <h3>Configurar — <?php echo esc_html( $f['label'] ); ?></h3>
                            <button type="button" class="mp-modal-x" data-close>&times;</button>
                        </div>
                        <div class="mp-modal-body">
                            <label class="mp-check"><input type="checkbox" name="addon_enabled" <?php checked( $f['enabled'] ); ?>> Ativo — disponível no app</label>
                            <label class="mp-check"><input type="checkbox" name="addon_acct" <?php checked( $f['requires_account'] ); ?>> Exige conta para usar</label>
                            <label class="mp-check"><input type="checkbox" name="addon_vip" <?php checked( ! empty( $f['vip_only'] ) ); ?>> Só VIP (desbloqueia no paywall)</label>
                            <?php if ( $key === 'youtube_addon' ) : ?>
                                <hr class="mp-modal-sep">
                                <div class="mp-field"><label>Países bloqueados</label><textarea name="mp_yt_blocked_countries" rows="2" placeholder="Ex: US, GB, BR (ISO-2, por vírgula ou linha)"><?php echo esc_textarea( get_option( 'mp_yt_blocked_countries', '' ) ); ?></textarea><span class="mp-hint">Nesses países o add-on <strong>não aparece</strong>. ISO-2 (PT, MZ, US…).</span></div>
                                <div class="mp-field"><label>Artistas bloqueados</label><textarea name="mp_yt_blocked_artists" rows="3" placeholder="Um por linha"><?php echo esc_textarea( get_option( 'mp_yt_blocked_artists', '' ) ); ?></textarea><span class="mp-hint">Vídeos desse artista/canal <strong>não podem ser importados</strong>.</span></div>
                                <div class="mp-card" style="padding:14px;margin:0 0 14px;background:var(--rmbz-surface-soft,#f5f8f6)">
                                    <strong>Streaming Free protegido</strong>
                                    <p class="mp-hint" style="margin:5px 0 0">Utilizadores Free ouvem normalmente, mas recebem apenas um inicio temporario em cache. O ficheiro completo encriptado exige VIP ativo e o add-on Download offline.</p>
                                </div>
                                <div class="mp-field"><label>Inicio guardado por faixa (KB)</label><input type="number" name="mp_yt_prebuffer_kb" min="128" max="4096" step="128" value="<?php echo min( 4096, max( 128, (int) get_option( 'mp_yt_prebuffer_kb', 768 ) ) ); ?>"><span class="mp-hint">128-4096 KB. Recomendado: <strong>768 KB</strong>. E cache tecnico com limite global de 64 MB, nao download offline.</span></div>
                                <div class="mp-field"><label>Tentativas ao preparar audio</label><input type="number" name="mp_yt_resolve_retries" min="1" max="5" value="<?php echo min( 5, max( 1, (int) get_option( 'mp_yt_resolve_retries', 3 ) ) ); ?>"><span class="mp-hint">Renova o endereco do stream e repete com espera progressiva. Recomendado: <strong>3</strong>.</span></div>
                                <div class="mp-field"><label>Palavras bloqueadas</label><textarea name="mp_yt_blocked_keywords" rows="2" placeholder="Um termo por linha"><?php echo esc_textarea( get_option( 'mp_yt_blocked_keywords', '' ) ); ?></textarea><span class="mp-hint">Se o título/artista contiver o termo, a importação é recusada.</span></div>
                            <?php endif; ?>
                            <?php if ( $key === 'equalizer' ) : ?>
                                <hr class="mp-modal-sep">
                                <label class="mp-section-mini">Funções do Equalizador</label>
                                <label class="mp-check"><input type="checkbox" name="mp_eq_signatures" <?php checked( get_option( 'mp_eq_signatures', 1 ), 1 ); ?>> Assinaturas de som (Curva Harman e perfis premium)</label>
                            <?php endif; ?>
                            <?php if ( $key === 'sponsored' ) : ?>
                                <hr class="mp-modal-sep">
                                <label class="mp-section-mini">Onde o programa está disponível</label>
                                <div class="mp-field">
                                    <label>Países elegíveis (ISO-2)</label>
                                    <textarea name="mp_sponsored_countries" rows="2" placeholder="Ex: MZ, AO, PT (por vírgula ou linha) — vazio = todos os países"><?php echo esc_textarea( get_option( 'mp_sponsored_countries', '' ) ); ?></textarea>
                                    <span class="mp-hint">Só nestes países o programa <strong>aparece e paga</strong>. Deixa <strong>vazio</strong> para o mundo inteiro. (Cada faixa pode ainda restringir mais, no Gestor de Anúncios &amp; Campanhas.)</span>
                                </div>
                            <?php endif; ?>
                            <?php if ( $key === 'ai_assistant' ) :
                                $ai_key_set = trim( (string) get_option( 'mp_ai_api_key', '' ) ) !== '';
                                $ai_model   = get_option( 'mp_ai_model', 'claude-opus-4-8' );
                            ?>
                                <hr class="mp-modal-sep">
                                <div class="mp-field">
                                    <label>Chave da API (Anthropic)</label>
                                    <input type="password" name="mp_ai_api_key" autocomplete="new-password" data-1p-ignore data-lpignore="true" placeholder="<?php echo $ai_key_set ? '•••••••••• (guardada — deixa vazio para manter)' : 'sk-ant-...'; ?>">
                                    <span class="mp-hint">Fica <strong>só no servidor</strong>; o app nunca a recebe. <?php echo $ai_key_set ? 'Já existe uma chave guardada.' : 'Ainda sem chave.'; ?></span>
                                </div>
                                <div class="mp-field">
                                    <label>Modelo</label>
                                    <select name="mp_ai_model">
                                        <option value="claude-opus-4-8" <?php selected( $ai_model, 'claude-opus-4-8' ); ?>>Claude Opus 4.8 (recomendado)</option>
                                        <option value="claude-opus-4-6" <?php selected( $ai_model, 'claude-opus-4-6' ); ?>>Claude Opus 4.6</option>
                                    </select>
                                    <span class="mp-hint">Usado para traduzir letras e recomendar músicas.</span>
                                </div>
                                <label class="mp-section-mini">Funções da Assistente</label>
                                <label class="mp-check"><input type="checkbox" name="mp_ai_translate" <?php checked( get_option( 'mp_ai_translate', 1 ), 1 ); ?>> Traduzir letras</label>
                                <label class="mp-check"><input type="checkbox" name="mp_ai_recommend" <?php checked( get_option( 'mp_ai_recommend', 1 ), 1 ); ?>> Recomendações de músicas</label>
                                <label class="mp-check"><input type="checkbox" name="mp_ai_playlist" <?php checked( get_option( 'mp_ai_playlist', 1 ), 1 ); ?>> «Playlist para ti» (curadoria)</label>
                                <label class="mp-check"><input type="checkbox" name="mp_ai_shuffle" <?php checked( get_option( 'mp_ai_shuffle', 1 ), 1 ); ?>> Aleatório com IA</label>
                                <label class="mp-check"><input type="checkbox" name="mp_ai_covers" <?php checked( get_option( 'mp_ai_covers', 0 ), 1 ); ?>> Melhorar capas em HD (mesma capa, mais nítida)</label>
                                <label class="mp-check"><input type="checkbox" name="mp_ai_tags" <?php checked( get_option( 'mp_ai_tags', 1 ), 1 ); ?>> Pesquisar tags com Assistente (editor)</label>
                                <label class="mp-check"><input type="checkbox" name="mp_ai_lookup" <?php checked( get_option( 'mp_ai_lookup', 1 ), 1 ); ?>> Pesquisa avançada em plataformas (capa + tags oficiais)</label>
                                <label class="mp-check"><input type="checkbox" name="mp_ai_diagnostics" <?php checked( get_option( 'mp_ai_diagnostics', 1 ), 1 ); ?>> Diagnostico do telefone (interpreta apenas relatorio tecnico sem credenciais)</label>
                            <?php endif; ?>
                        </div>
                        <div class="mp-modal-foot">
                            <button type="button" class="mp-btn mp-btn--outline" data-close>Cancelar</button>
                            <button type="submit" name="mp_addon_save" value="1" class="mp-btn mp-btn--primary"><span class="dashicons dashicons-saved"></span> Guardar</button>
                        </div>
                    </form>
                </div>
            </div>
            <?php endforeach; ?>
        </div><!-- /tab-addons -->

        <div class="mp-tab" id="tab-contas" hidden>
        <div class="mp-card mp-card--wide" style="margin-top:0">
            <div class="mp-card-head"><div class="mp-ic"><span class="dashicons dashicons-cart"></span></div><div><h2>Pedidos VIP pendentes</h2><div class="mp-card-sub"><?php echo count( $orders ); ?> à espera de confirmação</div></div></div>
            <?php if ( empty( $orders ) ) : ?>
                <p class="mp-empty">Sem pedidos pendentes. Quando um utilizador toca «Ativar VIP» no app, o pedido aparece aqui para confirmares o pagamento.</p>
            <?php else : ?>
            <div class="mp-table-wrap">
                <table class="mp-table">
                    <thead><tr><th>Conta</th><th>Plano</th><th>Valor</th><th>Referência</th><th>Criado</th><th>Acções</th></tr></thead>
                    <tbody>
                    <?php foreach ( $orders as $o ) : ?>
                        <tr>
                            <td><?php echo esc_html( $o->email ); ?></td>
                            <td><span class="mp-pill mp-pill--muted"><?php echo $o->plan === 'annual' ? 'Anual' : 'Mensal'; ?></span></td>
                            <td><strong><?php echo esc_html( trim( $o->currency . $o->amount ) ); ?></strong></td>
                            <td><code class="mp-ref"><?php echo esc_html( $o->reference ); ?></code></td>
                            <td><?php echo esc_html( $o->created_at ); ?></td>
                            <td>
                                <form method="post" action="<?php echo esc_url( $mp_url . '#contas' ); ?>" style="display:inline-flex;gap:6px">
                                    <?php wp_nonce_field( 'mp_order_action' ); ?>
                                    <input type="hidden" name="mp_order_id" value="<?php echo (int) $o->id; ?>">
                                    <button class="mp-btn mp-btn--gold" name="mp_order_action" value="approve"
                                        onclick="return confirm('Confirmar pagamento e dar VIP a <?php echo esc_js( $o->email ); ?>?');">Aprovar</button>
                                    <button class="mp-btn mp-btn--outline" name="mp_order_action" value="reject"
                                        onclick="return confirm('Rejeitar este pedido?');">Rejeitar</button>
                                </form>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
            <?php endif; ?>
        </div>

        <div class="mp-card mp-card--wide">
            <div class="mp-card-head"><div class="mp-ic"><span class="dashicons dashicons-groups"></span></div><div><h2>Utilizadores do leitor</h2><div class="mp-card-sub"><?php echo count( $accounts ); ?> contas · <?php echo (int) $vip_count; ?> VIP</div></div></div>
            <?php if ( empty( $accounts ) ) : ?>
                <p class="mp-empty">Ainda não há contas registadas.</p>
            <?php else : ?>
            <div class="mp-table-wrap">
                <table class="mp-table">
                    <thead><tr><th>Conta</th><th>VIP</th><th>Dispositivo</th><th>Estado</th><th>Nuvem &amp; Cópia</th><th>Último login</th><th>Acções</th></tr></thead>
                    <tbody>
                    <?php foreach ( $accounts as $a ) :
                        $is_vip  = (int) $a->is_vip === 1;
                        $vip_source = mp_vip_source( $a );
                        $vip_label = [
                            'paid' => 'VIP pago', 'admin' => 'VIP admin', 'rewarded' => 'VIP anúncio',
                            'mixed' => 'VIP misto', 'legacy' => 'VIP legado',
                        ][ $vip_source ] ?? 'VIP';
                        $device  = trim( ( $a->platform ? ucfirst( $a->platform ) : '' ) . ( $a->device_model ? ' · ' . $a->device_model : '' ) );
                        $initial = strtoupper( mb_substr( $a->name ?: $a->email, 0, 1 ) );
                        $cs      = $cloud_stats[ (int) $a->id ] ?? null;
                        $cs_mb   = $cs ? ( $cs['bytes'] >= 1073741824 ? round( $cs['bytes'] / 1073741824, 1 ) . ' GB' : round( $cs['bytes'] / 1048576 ) . ' MB' ) : '';
                    ?>
                        <tr>
                            <td>
                                <div style="display:flex;align-items:center;gap:10px">
                                    <span class="mp-avatar"><?php echo esc_html( $initial ); ?></span>
                                    <div>
                                        <div style="font-weight:600"><?php echo esc_html( $a->name ?: '—' ); ?></div>
                                        <div style="color:#5f6368;font-size:12px"><?php echo esc_html( $a->email ); ?></div>
                                    </div>
                                </div>
                            </td>
                            <td><?php echo $is_vip ? '<span class="mp-pill mp-pill--vip">★ ' . esc_html( $vip_label ) . '</span>' : '<span class="mp-pill mp-pill--muted">Free</span>'; ?></td>
                            <td><?php echo $device ? esc_html( $device ) : '<span style="color:#aaa">—</span>'; ?></td>
                            <td><?php echo $a->status === 'active' ? '<span class="mp-pill mp-pill--active">Ativa</span>' : '<span class="mp-pill mp-pill--blocked">Bloqueada</span>'; ?></td>
                            <td>
                                <?php if ( $cs && $cs['tracks'] > 0 ) : ?>
                                    <span class="mp-pill mp-pill--active">☁ <?php echo (int) $cs['tracks']; ?> · <?php echo esc_html( $cs_mb ); ?></span>
                                <?php endif; ?>
                                <?php if ( $a->sync_data ) : ?>
                                    <span class="mp-pill mp-pill--vip" title="Cópia de segurança guardada em <?php echo esc_attr( $a->sync_updated ); ?>">💾 cópia</span>
                                <?php endif; ?>
                                <?php if ( ( ! $cs || $cs['tracks'] === 0 ) && ! $a->sync_data ) : ?>
                                    <span style="color:#aaa">—</span>
                                <?php endif; ?>
                            </td>
                            <td><?php echo $a->last_login ? esc_html( $a->last_login ) : '<span style="color:#aaa">—</span>'; ?></td>
                            <td>
                                <button type="button" class="mp-btn mp-btn--outline" onclick="mpUserModal(<?php echo (int) $a->id; ?>, true)">ℹ Mais info</button>
                                <form method="post" action="<?php echo esc_url( $mp_url . '#contas' ); ?>" style="display:inline-flex;gap:6px;flex-wrap:wrap">
                                    <?php wp_nonce_field( 'mp_acct_action' ); ?>
                                    <input type="hidden" name="mp_acct_id" value="<?php echo (int) $a->id; ?>">
                                    <button class="mp-btn <?php echo $is_vip ? 'mp-btn--outline' : 'mp-btn--gold'; ?>" name="mp_acct_action" value="<?php echo $is_vip ? 'vip_off' : 'vip_on'; ?>"><?php echo $is_vip ? 'Tirar VIP' : 'Dar VIP'; ?></button>
                                    <button class="mp-btn mp-btn--outline" name="mp_acct_action" value="<?php echo $a->status === 'active' ? 'block' : 'unblock'; ?>"><?php echo $a->status === 'active' ? 'Bloquear' : 'Desbloquear'; ?></button>
                                    <button class="mp-btn mp-btn--danger" name="mp_acct_action" value="delete"
                                        onclick="return confirm('Apagar definitivamente a conta <?php echo esc_js( $a->email ); ?>? Esta ação não pode ser desfeita.');"><span class="dashicons dashicons-trash"></span></button>
                                </form>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            </div>

            <?php // ---- Modais "Mais info" (raio-X completo de cada utilizador) ---- ?>
            <?php foreach ( $accounts as $a ) :
                $is_vip = (int) $a->is_vip === 1;
                $vip_source = mp_vip_source( $a );
                $vip_label = [
                    'paid' => 'VIP pago', 'admin' => 'VIP admin', 'rewarded' => 'VIP anúncio',
                    'mixed' => 'VIP misto', 'legacy' => 'VIP legado',
                ][ $vip_source ] ?? 'VIP';
                $cs     = $cloud_stats[ (int) $a->id ] ?? null;
                $cs_mb  = $cs ? ( $cs['bytes'] >= 1073741824 ? round( $cs['bytes'] / 1073741824, 1 ) . ' GB' : round( $cs['bytes'] / 1048576 ) . ' MB' ) : '0 MB';
                $sync   = $a->sync_data ? json_decode( $a->sync_data, true ) : null;
                $fav_n  = ( is_array( $sync['favorites'] ?? null ) ) ? count( $sync['favorites'] ) : 0;
                $pls    = is_array( $sync['playlists'] ?? null ) ? $sync['playlists'] : [];
                $tags_n = 0; $cov_n = 0; $yt_n = 0; $idx_n = 0;
                if ( $sync ) {
                    $t = json_decode( (string) ( $sync['tags'] ?? '' ), true );        $tags_n = is_array( $t ) ? count( $t ) : 0;
                    $c = json_decode( (string) ( $sync['covers'] ?? '' ), true );      $cov_n  = is_array( $c ) ? count( $c ) : 0;
                    $y = json_decode( (string) ( $sync['yt_tracks'] ?? '' ), true );   $yt_n   = is_array( $y ) ? count( $y ) : 0;
                    $x = json_decode( (string) ( $sync['cloud_audio'] ?? '' ), true ); $idx_n  = is_array( $x ) ? count( $x ) : 0;
                }
            ?>
            <div class="mp-umodal" id="mp-um-<?php echo (int) $a->id; ?>" onclick="if(event.target===this)mpUserModal(<?php echo (int) $a->id; ?>,false)">
                <div class="mp-umodal-card">
                    <div class="mp-um-head">
                        <span class="mp-avatar mp-avatar--big"><?php echo esc_html( strtoupper( mb_substr( $a->name ?: $a->email, 0, 1 ) ) ); ?></span>
                        <div style="flex:1;min-width:0">
                            <div style="font-weight:700;font-size:16px"><?php echo esc_html( $a->name ?: '—' ); ?></div>
                            <div style="color:#5f6368;font-size:13px"><?php echo esc_html( $a->email ); ?></div>
                            <div style="margin-top:6px;display:flex;gap:6px;flex-wrap:wrap">
                                <?php echo $is_vip ? '<span class="mp-pill mp-pill--vip">★ ' . esc_html( $vip_label ) . ( $a->vip_until ? ' até ' . esc_html( mysql2date( 'd/m/Y', $a->vip_until ) ) : ' vitalício' ) . '</span>' : '<span class="mp-pill mp-pill--muted">Free</span>'; ?>
                                <?php echo $a->status === 'active' ? '<span class="mp-pill mp-pill--active">Ativa</span>' : '<span class="mp-pill mp-pill--blocked">Bloqueada</span>'; ?>
                            </div>
                        </div>
                        <button type="button" class="mp-btn mp-btn--outline" onclick="mpUserModal(<?php echo (int) $a->id; ?>,false)">✕</button>
                    </div>

                    <div class="mp-um-grid">
                        <div class="mp-um-fact"><small>Entrou em</small><b><?php echo $a->created_at ? esc_html( mysql2date( 'd/m/Y H:i', $a->created_at ) ) : '—'; ?></b></div>
                        <div class="mp-um-fact"><small>Último login</small><b><?php echo $a->last_login ? esc_html( mysql2date( 'd/m/Y H:i', $a->last_login ) ) : '—'; ?></b></div>
                        <div class="mp-um-fact"><small>Dispositivo</small><b><?php echo esc_html( trim( ( $a->platform ? ucfirst( $a->platform ) : '—' ) . ( $a->device_model ? ' · ' . $a->device_model : '' ) ) ); ?></b></div>
                        <div class="mp-um-fact"><small>Cópia atualizada</small><b><?php echo $a->sync_updated ? esc_html( mysql2date( 'd/m/Y H:i', $a->sync_updated ) ) : 'sem cópia'; ?></b></div>
                    </div>

                    <h4 class="mp-um-title">💾 Cópia de segurança</h4>
                    <?php if ( $sync ) : ?>
                        <div class="mp-um-grid">
                            <div class="mp-um-fact"><small>Favoritas</small><b><?php echo (int) $fav_n; ?> músicas</b></div>
                            <div class="mp-um-fact"><small>Playlists</small><b><?php echo count( $pls ); ?></b></div>
                            <div class="mp-um-fact"><small>Tags editadas</small><b><?php echo (int) $tags_n; ?></b></div>
                            <div class="mp-um-fact"><small>Capas escolhidas</small><b><?php echo (int) $cov_n; ?></b></div>
                            <div class="mp-um-fact"><small>Faixas YouTube</small><b><?php echo (int) $yt_n; ?></b></div>
                            <div class="mp-um-fact"><small>Índice da nuvem</small><b><?php echo (int) $idx_n; ?> músicas</b></div>
                        </div>
                        <?php if ( ! empty( $pls ) ) : ?>
                            <div class="mp-um-pls">
                                <?php foreach ( array_slice( $pls, 0, 12 ) as $pl ) :
                                    $pn = is_array( $pl['songs'] ?? null ) ? count( $pl['songs'] ) : 0; ?>
                                    <span class="mp-pill mp-pill--muted">🎵 <?php echo esc_html( $pl['name'] ?? 'Playlist' ); ?> · <?php echo (int) $pn; ?></span>
                                <?php endforeach; ?>
                                <?php if ( count( $pls ) > 12 ) : ?><span class="mp-pill mp-pill--muted">+<?php echo count( $pls ) - 12; ?></span><?php endif; ?>
                            </div>
                        <?php endif; ?>
                    <?php else : ?>
                        <p class="mp-empty" style="margin:6px 0">Este utilizador ainda não guardou nenhuma cópia.</p>
                    <?php endif; ?>

                    <h4 class="mp-um-title">☁ Ficheiros na nuvem</h4>
                    <?php if ( $cs && $cs['tracks'] > 0 ) : ?>
                        <div class="mp-um-grid">
                            <div class="mp-um-fact"><small>Músicas</small><b><?php echo (int) $cs['tracks']; ?></b></div>
                            <div class="mp-um-fact"><small>Espaço</small><b><?php echo esc_html( $cs_mb ); ?></b></div>
                        </div>
                        <p style="margin:8px 0 0;color:#5f6368;font-size:12.5px">Para ouvir/baixar/apagar música a música, usa a aba <strong>Nuvem</strong>.</p>
                    <?php else : ?>
                        <p class="mp-empty" style="margin:6px 0">Sem ficheiros na nuvem.</p>
                    <?php endif; ?>

                    <?php // ---- Programa de Músicas Patrocinadas (resumo + botão) ---- ?>
                    <?php if ( function_exists( 'mp_sponsored_balance' ) ) :
                        $sp_on       = function_exists( 'mp_sponsored_enabled' ) && mp_sponsored_enabled();
                        $sp_accepted = function_exists( 'mp_sponsored_accepted' ) && mp_sponsored_accepted( (int) $a->id );
                        $sp_score    = (int) get_option( 'mp_sponsored_score_' . (int) $a->id, 0 );
                        $sp_clawback = function_exists( 'mp_sponsored_clawback' ) ? mp_sponsored_clawback( (int) $a->id ) : 0;
                        $sp_balance  = mp_sponsored_balance( (int) $a->id );
                        $sp_earn_tbl = $wpdb->prefix . 'mp_sponsored_earnings';
                        $sp_pay_tbl  = $wpdb->prefix . 'mp_sponsored_payouts';
                        $sp_ses_tbl  = $wpdb->prefix . 'mp_sponsored_sessions';
                        $sp_trk_tbl  = $wpdb->prefix . 'mp_sponsored_tracks';
                        $sp_total    = (float) $wpdb->get_var( $wpdb->prepare( "SELECT COALESCE(SUM(earned_usd),0) FROM {$sp_earn_tbl} WHERE account_id = %d", $a->id ) );
                        $sp_secs     = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COALESCE(SUM(seconds),0) FROM {$sp_earn_tbl} WHERE account_id = %d", $a->id ) );
                        $sp_mins     = (int) round( $sp_secs / 60 );
                        $sp_paid     = (float) $wpdb->get_var( $wpdb->prepare( "SELECT COALESCE(SUM(amount_usd),0) FROM {$sp_pay_tbl} WHERE account_id = %d AND status = 'paid'", $a->id ) );
                        $sp_verify   = (string) get_option( 'mp_sponsored_verify_' . (int) $a->id, '' );
                        $sp_bad_ai   = ( stripos( $sp_verify, 'FRAUDE' ) !== false || stripos( $sp_verify, 'SUSPEITO' ) !== false );
                        // Elegível = programa ligado + contrato aceite + sem bandeiras + IA não reprovou.
                        $sp_eligible = $sp_on && $sp_accepted && $sp_score === 0 && ! $sp_bad_ai;
                        $sp_active   = $sp_accepted || $sp_total > 0 || $sp_score > 0 || $sp_verify !== '';
                    ?>
                    <h4 class="mp-um-title"><span class="dashicons dashicons-megaphone"></span> Programa de Patrocinadas</h4>
                    <div class="mp-sprow">
                        <div class="mp-spbadges">
                            <?php if ( ! $sp_on ) : ?>
                                <span class="mp-pill mp-pill--muted">Programa desligado</span>
                            <?php elseif ( $sp_eligible ) : ?>
                                <span class="mp-pill mp-pill--active">Elegível</span>
                            <?php else : ?>
                                <span class="mp-pill mp-pill--blocked">Não elegível</span>
                            <?php endif; ?>
                            <span class="mp-pill <?php echo $sp_accepted ? 'mp-pill--active' : 'mp-pill--muted'; ?>"><?php echo $sp_accepted ? 'Contrato aceite' : 'Sem contrato'; ?></span>
                            <?php if ( $sp_score > 0 ) : ?><span class="mp-pill mp-pill--blocked"><?php echo (int) $sp_score; ?> alerta(s)</span><?php endif; ?>
                        </div>
                        <div class="mp-spbal"><span>Saldo</span><b>$<?php echo number_format( $sp_balance, 2 ); ?></b></div>
                        <button type="button" class="mp-btn mp-btn--gold" onclick="mpSpModal(<?php echo (int) $a->id; ?>,true)"><span class="dashicons dashicons-visibility"></span> Abrir gestão</button>
                    </div>
                    <?php endif; ?>

                    <div class="mp-um-actions">
                        <form method="post" action="<?php echo esc_url( $mp_url . '#contas' ); ?>" style="display:flex;gap:8px;flex-wrap:wrap">
                            <?php wp_nonce_field( 'mp_acct_action' ); ?>
                            <input type="hidden" name="mp_acct_id" value="<?php echo (int) $a->id; ?>">
                            <?php if ( $sync ) : ?>
                                <button class="mp-btn mp-btn--outline" name="mp_acct_action" value="clear_sync"
                                    onclick="return confirm('Apagar a cópia de segurança de <?php echo esc_js( $a->email ); ?>?');">Apagar cópia</button>
                            <?php endif; ?>
                            <button class="mp-btn mp-btn--danger" name="mp_acct_action" value="wipe_all"
                                onclick="return confirm('APAGAR TUDO de <?php echo esc_js( $a->email ); ?> — cópia de segurança + todos os ficheiros na nuvem? A conta continua a existir.');">Apagar tudo do utilizador</button>
                        </form>
                    </div>
                </div>
            </div>

            <?php // ===== MODAL GRANDE: Gestão do Programa de Patrocinadas ===== ?>
            <?php if ( function_exists( 'mp_sponsored_balance' ) ) :
                // Detalhe pesado (por faixa / pagamentos / bandeiras) só para contas com atividade.
                $sp_by_track = ! empty( $sp_active ) ? $wpdb->get_results( $wpdb->prepare(
                    "SELECT e.track_id, COALESCE(SUM(e.earned_usd),0) AS earned, COALESCE(SUM(e.seconds),0) AS secs, t.title, t.artist
                     FROM {$sp_earn_tbl} e LEFT JOIN {$sp_trk_tbl} t ON t.id = e.track_id
                     WHERE e.account_id = %d GROUP BY e.track_id ORDER BY earned DESC LIMIT 50", $a->id ) ) : [];
                $sp_payouts = ! empty( $sp_active ) ? $wpdb->get_results( $wpdb->prepare(
                    "SELECT * FROM {$sp_pay_tbl} WHERE account_id = %d ORDER BY id DESC LIMIT 20", $a->id ) ) : [];
                $sp_ses_stat = ! empty( $sp_active ) ? $wpdb->get_row( $wpdb->prepare(
                    "SELECT COUNT(*) AS n, COALESCE(SUM(bad_beats),0) AS bad, COALESCE(SUM(good_beats),0) AS good,
                            SUM(status='fraud') AS fraud FROM {$sp_ses_tbl} WHERE account_id = %d", $a->id ) ) : null;
                $sp_flags = get_option( 'mp_sponsored_flags_' . (int) $a->id, [] );
                if ( ! is_array( $sp_flags ) ) { $sp_flags = []; }
            ?>
            <div class="mp-spm" id="mp-spm-<?php echo (int) $a->id; ?>" onclick="if(event.target===this)mpSpModal(<?php echo (int) $a->id; ?>,false)">
                <div class="mp-spm-card">
                    <div class="mp-spm-head">
                        <span class="mp-spm-icon"><span class="dashicons dashicons-shield"></span></span>
                        <div style="flex:1;min-width:0">
                            <div style="font-weight:800;font-size:17px">Programa de Patrocinadas</div>
                            <div style="color:#5f6368;font-size:13px"><?php echo esc_html( $a->name ?: $a->email ); ?> · <?php echo esc_html( $a->email ); ?></div>
                        </div>
                        <button type="button" class="mp-btn mp-btn--outline mp-spm-close" onclick="mpSpModal(<?php echo (int) $a->id; ?>,false)" aria-label="Fechar"><span class="dashicons dashicons-no-alt"></span></button>
                    </div>

                    <?php // Faixa de elegibilidade (herói) ?>
                    <div class="mp-spm-hero <?php echo $sp_eligible ? 'ok' : ( $sp_on ? 'bad' : 'off' ); ?>">
                        <div class="mp-spm-hero-ic"><span class="dashicons <?php echo $sp_eligible ? 'dashicons-yes-alt' : ( $sp_on ? 'dashicons-warning' : 'dashicons-controls-pause' ); ?>"></span></div>
                        <div>
                            <b><?php echo ! $sp_on ? 'Programa desligado' : ( $sp_eligible ? 'Elegível para ganhar' : 'Não elegível' ); ?></b>
                            <small><?php
                                if ( ! $sp_on ) { echo 'Liga o programa no Gestor de Anúncios & Campanhas para esta conta poder ganhar.'; }
                                elseif ( $sp_eligible ) { echo 'Contrato aceite, sem bandeiras de fraude e IA sem objeções.'; }
                                else {
                                    $rz = [];
                                    if ( ! $sp_accepted ) { $rz[] = 'contrato não aceite'; }
                                    if ( $sp_score > 0 )   { $rz[] = $sp_score . ' bandeira(s) de fraude'; }
                                    if ( $sp_bad_ai )      { $rz[] = 'IA reprovou a verificação'; }
                                    echo esc_html( 'Motivo: ' . ( $rz ? implode( ' · ', $rz ) : 'requisitos por cumprir' ) );
                                }
                            ?></small>
                        </div>
                    </div>

                    <?php // Veredicto da IA do dispositivo, legível por inteiro ?>
                    <?php if ( $sp_verify === 'requested' ) : ?>
                        <div class="mp-spm-ai wait">⏳ À espera do auto-diagnóstico do dispositivo do utilizador (acontece na próxima abertura do app com internet).</div>
                    <?php elseif ( strpos( $sp_verify, '📱' ) === 0 ) : ?>
                        <div class="mp-spm-ai <?php echo $sp_bad_ai ? 'bad' : 'ok'; ?>"><b>Verificação no dispositivo (IA):</b><br><?php echo esc_html( trim( mb_substr( $sp_verify, strlen( '📱' ) ) ) ); ?></div>
                    <?php endif; ?>

                    <?php // Estatísticas ?>
                    <div class="mp-um-grid" style="margin-top:14px">
                        <div class="mp-um-fact"><small>Saldo atual</small><b>$<?php echo number_format( $sp_balance, 2 ); ?></b></div>
                        <div class="mp-um-fact"><small>Ganhos totais</small><b>$<?php echo number_format( $sp_total, 2 ); ?></b></div>
                        <div class="mp-um-fact"><small>Já pago</small><b>$<?php echo number_format( $sp_paid, 2 ); ?></b></div>
                        <div class="mp-um-fact"><small>Removido pelo admin</small><b>$<?php echo number_format( $sp_clawback, 2 ); ?></b></div>
                        <div class="mp-um-fact"><small>Tempo ouvido</small><b><?php echo (int) $sp_mins; ?> min</b></div>
                        <div class="mp-um-fact"><small>Sessões (más/boas)</small><b><?php echo $sp_ses_stat ? ( (int) $sp_ses_stat->n . ' · ' . (int) $sp_ses_stat->bad . '/' . (int) $sp_ses_stat->good ) : '0'; ?></b></div>
                    </div>

                    <?php // Ganhos por faixa ?>
                    <?php if ( $sp_by_track ) : ?>
                    <h4 class="mp-um-title"><span class="dashicons dashicons-format-audio"></span> Ganhos por faixa</h4>
                    <div class="mp-spm-list">
                        <?php foreach ( $sp_by_track as $bt ) : ?>
                        <div class="mp-spm-li">
                            <div style="flex:1;min-width:0">
                                <b><?php echo esc_html( $bt->title ?: ( 'Faixa #' . (int) $bt->track_id ) ); ?></b>
                                <small><?php echo esc_html( $bt->artist ?: '—' ); ?> · <?php echo (int) round( $bt->secs / 60 ); ?> min</small>
                            </div>
                            <span class="mp-spm-amt">$<?php echo number_format( (float) $bt->earned, 2 ); ?></span>
                        </div>
                        <?php endforeach; ?>
                    </div>
                    <?php endif; ?>

                    <?php // Histórico de pagamentos ?>
                    <?php if ( $sp_payouts ) : ?>
                    <h4 class="mp-um-title"><span class="dashicons dashicons-money-alt"></span> Pedidos de pagamento</h4>
                    <div class="mp-spm-list">
                        <?php foreach ( $sp_payouts as $po ) :
                            $stcls = $po->status === 'paid' ? 'mp-pill--active' : ( $po->status === 'rejected' ? 'mp-pill--blocked' : 'mp-pill--vip' );
                            $stlbl = $po->status === 'paid' ? 'Pago' : ( $po->status === 'rejected' ? 'Rejeitado' : 'Pendente' );
                        ?>
                        <div class="mp-spm-li">
                            <div style="flex:1;min-width:0">
                                <b>$<?php echo number_format( (float) $po->amount_usd, 2 ); ?> · <?php echo esc_html( $po->method ?: '—' ); ?></b>
                                <small><?php echo esc_html( $po->detail ?: '' ); ?> <?php echo $po->created_at ? '· ' . esc_html( mysql2date( 'd/m/Y', $po->created_at ) ) : ''; ?></small>
                            </div>
                            <span class="mp-pill <?php echo $stcls; ?>"><?php echo esc_html( $stlbl ); ?></span>
                        </div>
                        <?php endforeach; ?>
                    </div>
                    <?php endif; ?>

                    <?php // Bandeiras de fraude ?>
                    <?php if ( ! empty( $sp_flags ) ) : ?>
                    <h4 class="mp-um-title"><span class="dashicons dashicons-warning"></span> Alertas de integridade</h4>
                    <div class="mp-spm-list">
                        <?php foreach ( array_reverse( array_slice( $sp_flags, -10 ) ) as $fl ) : ?>
                        <div class="mp-spm-li">
                            <div style="flex:1;min-width:0"><b><?php echo esc_html( $fl['r'] ?? 'suspeita' ); ?></b>
                            <small><?php echo isset( $fl['t'] ) ? esc_html( mysql2date( 'd/m/Y H:i', date( 'Y-m-d H:i:s', (int) $fl['t'] ) ) ) : ''; ?></small></div>
                        </div>
                        <?php endforeach; ?>
                    </div>
                    <?php endif; ?>

                    <?php // ---- Ações do admin ---- ?>
                    <h4 class="mp-um-title"><span class="dashicons dashicons-admin-tools"></span> Ações do admin</h4>
                    <div class="mp-spm-tools">
                        <?php if ( $sp_balance > 0 ) : ?>
                        <form method="post" action="<?php echo esc_url( $mp_url . '#contas' ); ?>" class="mp-spm-tool">
                            <?php wp_nonce_field( 'mp_acct_action' ); ?>
                            <input type="hidden" name="mp_acct_id" value="<?php echo (int) $a->id; ?>">
                            <label>Remover dinheiro <span>(o admin só pode remover, nunca adicionar)</span></label>
                            <div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
                                <input type="number" step="0.01" min="0" max="<?php echo esc_attr( number_format( $sp_balance, 2, '.', '' ) ); ?>" name="mp_earn_amount" placeholder="tudo ($<?php echo number_format( $sp_balance, 2 ); ?>)" style="width:150px;padding:7px 9px;border:1px solid #dadce0;border-radius:8px">
                                <button class="mp-btn mp-btn--danger" name="mp_acct_action" value="remove_earn"
                                    onclick="return confirm('Remover ganhos patrocinados desta conta?');">Remover</button>
                            </div>
                        </form>
                        <?php endif; ?>

                        <div class="mp-spm-tool">
                            <label>IA & verificação</label>
                            <div style="display:flex;gap:8px;flex-wrap:wrap">
                                <form method="post" action="<?php echo esc_url( $mp_url . '#contas' ); ?>" style="display:inline">
                                    <?php wp_nonce_field( 'mp_sponsored' ); ?>
                                    <input type="hidden" name="fraud_uid" value="<?php echo (int) $a->id; ?>">
                                    <button class="mp-btn mp-btn--outline" name="mp_fraud_review" value="1"><span class="dashicons dashicons-search"></span> Analisar integridade</button>
                                </form>
                                <?php if ( $sp_verify !== 'requested' ) : ?>
                                <form method="post" action="<?php echo esc_url( $mp_url . '#contas' ); ?>" style="display:inline">
                                    <?php wp_nonce_field( 'mp_sponsored' ); ?>
                                    <input type="hidden" name="fraud_uid" value="<?php echo (int) $a->id; ?>">
                                    <button class="mp-btn mp-btn--outline" name="mp_verify_device" value="1"><span class="dashicons dashicons-smartphone"></span> Verificar dispositivo</button>
                                </form>
                                <?php endif; ?>
                            </div>
                        </div>

                        <div class="mp-spm-tool mp-spm-danger">
                            <label>Limpar registos do utilizador <span>(ações avançadas, sem recuperação)</span></label>
                            <form method="post" action="<?php echo esc_url( $mp_url . '#contas' ); ?>" style="display:flex;gap:8px;flex-wrap:wrap">
                                <?php wp_nonce_field( 'mp_acct_action' ); ?>
                                <input type="hidden" name="mp_acct_id" value="<?php echo (int) $a->id; ?>">
                                <button class="mp-btn mp-btn--outline" name="mp_acct_action" value="sp_clear_flags"
                                    onclick="return confirm('Limpar bandeiras de fraude e o resultado da verificação?');">Limpar bandeiras</button>
                                <button class="mp-btn mp-btn--outline" name="mp_acct_action" value="sp_clear_sessions"
                                    onclick="return confirm('Apagar as sessões anti-fraude desta conta?');">Apagar sessões</button>
                                <button class="mp-btn mp-btn--outline" name="mp_acct_action" value="sp_clear_payouts"
                                    onclick="return confirm('Apagar o histórico de pagamentos desta conta?');">Apagar pagamentos</button>
                                <button class="mp-btn mp-btn--danger" name="mp_acct_action" value="sp_clear_earnings"
                                    onclick="return confirm('Apagar o registo de ganhos (escuta + devoluções)? O saldo passa a zero.');">Apagar ganhos</button>
                                <button class="mp-btn mp-btn--danger" name="mp_acct_action" value="sp_reset_program"
                                    onclick="return confirm('REPOR o programa para esta conta? Apaga ganhos, sessões, pagamentos, contrato e bandeiras. Recomeça do zero.');">Repor tudo</button>
                            </form>
                        </div>
                    </div>
                </div>
            </div>
            <?php endif; ?>
            <?php endforeach; ?>

            <style>
                .mp-umodal{position:fixed;inset:0;background:rgba(15,17,19,.55);z-index:99999;display:none;align-items:center;justify-content:center;padding:20px}
                .mp-umodal-card{background:#fff;border-radius:8px;max-width:660px;width:100%;max-height:86vh;overflow:auto;padding:22px;box-shadow:0 24px 70px rgba(0,0,0,.28)}
                .mp-um-head{display:flex;align-items:flex-start;gap:14px;margin-bottom:16px}
                .mp-avatar--big{width:52px;height:52px;font-size:20px;line-height:52px}
                .mp-um-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px}
                .mp-um-fact{background:#f4f7f5;border-radius:8px;padding:10px 12px}
                .mp-um-fact small{display:block;color:#5f6368;font-size:11px;text-transform:uppercase;letter-spacing:.4px}
                .mp-um-fact b{font-size:13.5px}
                .mp-um-title{display:flex;align-items:center;gap:7px;margin:18px 0 8px;font-size:13.5px}
                .mp-um-title .dashicons{color:#146c43;font-size:17px;width:17px;height:17px}
                .mp-um-pls{margin-top:10px;display:flex;gap:6px;flex-wrap:wrap}
                .mp-um-actions{margin-top:20px;padding-top:14px;border-top:1px solid #eceef1}
                /* resumo do programa dentro do raio-X */
                .mp-sprow{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:8px 0 4px}
                .mp-spbadges{display:flex;gap:6px;flex-wrap:wrap;flex:1;min-width:120px}
                .mp-spbal{background:#f4f7f5;border-radius:8px;padding:6px 14px;text-align:center}
                .mp-spbal span{display:block;color:#5f6368;font-size:10.5px;text-transform:uppercase;letter-spacing:.4px}
                .mp-spbal b{font-size:16px}
                /* modal grande do programa */
                .mp-spm{position:fixed;inset:0;background:rgba(15,17,19,.6);z-index:100000;display:none;align-items:center;justify-content:center;padding:20px}
                .mp-spm-card{background:#fff;border-radius:8px;max-width:820px;width:100%;max-height:90vh;overflow:auto;padding:24px;box-shadow:0 30px 80px rgba(0,0,0,.3)}
                .mp-spm-head{display:flex;align-items:center;gap:14px;margin-bottom:18px}
                .mp-spm-icon{width:48px;height:48px;border-radius:8px;background:#d9efe2;color:#146c43;display:flex;align-items:center;justify-content:center;flex:none}
                .mp-spm-icon .dashicons{font-size:24px;width:24px;height:24px}
                .mp-spm-close{width:40px;height:40px;padding:0}
                .mp-spm-hero{display:flex;align-items:center;gap:14px;border-radius:8px;padding:16px 18px}
                .mp-spm-hero.ok{background:#e4f4e9;border:1px solid #b5e3c6}
                .mp-spm-hero.bad{background:#fdecea;border:1px solid #f3b6ae}
                .mp-spm-hero.off{background:#f1f3f4;border:1px solid #e0e3e6}
                .mp-spm-hero-ic{width:44px;height:44px;border-radius:50%;background:rgba(255,255,255,.7);display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0}
                .mp-spm-hero-ic .dashicons{font-size:22px;width:22px;height:22px}
                .mp-spm-hero b{display:block;font-size:15px}
                .mp-spm-hero small{color:#3c4043;font-size:12.5px}
                .mp-spm-ai{margin-top:12px;border-radius:8px;padding:12px 14px;font-size:13px;line-height:1.5}
                .mp-spm-ai.ok{background:#e8f7ee;border:1px solid #b5e3c6}
                .mp-spm-ai.bad{background:#fdecea;border:1px solid #f3b6ae}
                .mp-spm-ai.wait{background:#fff7e6;border:1px solid #f2d98a}
                .mp-spm-list{display:flex;flex-direction:column;gap:8px}
                .mp-spm-li{display:flex;align-items:center;gap:12px;background:#f4f7f5;border-radius:8px;padding:10px 14px}
                .mp-spm-li b{display:block;font-size:13.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
                .mp-spm-li small{display:block;color:#5f6368;font-size:11.5px}
                .mp-spm-amt{font-weight:800;color:#0b8a3e;font-size:14px;white-space:nowrap}
                .mp-spm-tools{display:flex;flex-direction:column;gap:14px}
                .mp-spm-tool{background:#f8f9fa;border:1px solid #eceef1;border-radius:8px;padding:14px}
                .mp-spm-tool>label{display:block;font-weight:700;font-size:13px;margin-bottom:10px}
                .mp-spm-tool>label span{font-weight:400;color:#9aa0a6;font-size:11.5px}
                .mp-spm-danger{background:#fff6f5;border-color:#f6d3ce}
            </style>
            <script>
                function mpUserModal(id, show){
                    var el = document.getElementById('mp-um-' + id);
                    if (el) el.style.display = show ? 'flex' : 'none';
                }
                function mpSpModal(id, show){
                    var el = document.getElementById('mp-spm-' + id);
                    if (el) el.style.display = show ? 'flex' : 'none';
                }
            </script>
            <?php endif; ?>
        </div>
        </div><!-- /tab-contas -->

        <div class="mp-tab" id="tab-nuvem" hidden>
        <div class="mp-card mp-card--wide mp-cloud-admin" style="margin-top:0">
            <div class="mp-card-head mp-cloud-head"><div class="mp-ic"><span class="dashicons dashicons-cloud"></span></div><div><h2>Gestão da nuvem</h2><div class="mp-card-sub">Bibliotecas, integridade e cópias de dados por utilizador</div></div></div>
            <?php if ( ! function_exists( 'mp_s3_enabled' ) || ! mp_s3_enabled() ) : ?>
                <p>Configura e ativa o <strong>Armazenamento na cloud (S3)</strong> na aba Definições para veres os uploads aqui.</p>
            <?php else :
                // Lista tudo debaixo de players/ e agrupa por conta.
                $cloud_list_error = null;
                $cloud_objects = mp_s3_list( 'players/', 10000, $cloud_list_error );
                if ( $cloud_list_error ) : ?>
                    <div class="notice notice-error inline"><p><strong>A listagem do bucket falhou:</strong> <?php echo esc_html( $cloud_list_error ); ?>.
                    <?php if ( false !== stripos( $cloud_list_error, 'AccessDenied' ) ) : ?>
                        A policy IAM precisa também de <code>s3:ListBucket</code> no ARN do bucket (sem <code>/*</code>).
                    <?php endif; ?></p></div>
                <?php endif; ?>
            <?php if ( ! $cloud_list_error ) :
                // Agrupa: utilizador → pasta da música (novo formato) ou ficheiro solto (legado)
                // + cópias por dispositivo (Devices atual e backup legado).
                $by_user = [];
                $bk_by_user = [];
                foreach ( $cloud_objects as $obj ) {
                    if ( preg_match( '#^players/(\d+)/Devices/([^/]+)/data\.json$#i', $obj['key'], $bm )
                        || preg_match( '#^players/(\d+)/backup/(.+)$#', $obj['key'], $bm ) ) {
                        $bk_by_user[ (int) $bm[1] ][] = [
                            'name' => $bm[2], 'key' => $obj['key'],
                            'size' => $obj['size'], 'modified' => $obj['modified'],
                        ];
                        continue;
                    }
                    if ( ! preg_match( '#^players/(\d+)/audio/(.+)$#', $obj['key'], $m ) ) {
                        continue;
                    }
                    $uid  = (int) $m[1];
                    $rest = $m[2];
                    if ( false !== strpos( $rest, '/' ) ) {
                        $folder = substr( $rest, 0, strpos( $rest, '/' ) );
                        $fname  = substr( $rest, strpos( $rest, '/' ) + 1 );
                    } else {
                        $folder = $rest; // legado: ficheiro solto vira a própria "música"
                        $fname  = $rest;
                    }
                    if ( ! isset( $by_user[ $uid ] ) ) {
                        $by_user[ $uid ] = [ 'songs' => [], 'bytes' => 0, 'count' => 0, 'last' => '' ];
                    }
                    if ( ! isset( $by_user[ $uid ]['songs'][ $folder ] ) ) {
                        $by_user[ $uid ]['songs'][ $folder ] = [ 'files' => [], 'bytes' => 0, 'modified' => '', 'track' => '' ];
                        $by_user[ $uid ]['count']++;
                    }
                    $s = &$by_user[ $uid ]['songs'][ $folder ];
                    $s['files'][] = [ 'name' => $fname, 'key' => $obj['key'], 'size' => $obj['size'] ];
                    $s['bytes'] += $obj['size'];
                    if ( $obj['modified'] > $s['modified'] ) { $s['modified'] = $obj['modified']; }
                    // Só ÁUDIO ganha o botão Tocar (nunca capas nem meta.json).
                    $is_audio = ( 0 === strpos( $fname, 'track.' ) )
                        || preg_match( '/\.(mp3|m4a|aac|ogg|wav|flac)(\.enc)?$/i', $fname );
                    if ( $is_audio && '' === $s['track'] ) { $s['track'] = $obj['key']; }
                    unset( $s );
                    $by_user[ $uid ]['bytes'] += $obj['size'];
                    if ( $obj['modified'] > $by_user[ $uid ]['last'] ) { $by_user[ $uid ]['last'] = $obj['modified']; }
                }
                $emails = [];
                $account_names = [];
                foreach ( $accounts as $a ) {
                    $emails[ (int) $a->id ] = $a->email;
                    $account_names[ (int) $a->id ] = (string) $a->name;
                }
                $total_files = 0; $total_bytes = 0; $total_broken = 0;
                foreach ( $by_user as $u ) {
                    $total_files += $u['count']; $total_bytes += $u['bytes'];
                    foreach ( $u['songs'] as $sg ) { if ( '' === $sg['track'] ) { $total_broken++; } }
                }
                $bk_count = 0; $bk_bytes = 0;
                foreach ( $bk_by_user as $list ) { foreach ( $list as $b ) { $bk_count++; $bk_bytes += $b['size']; } }
                $quota_mb = (int) get_option( 'mp_cloud_quota_mb', 0 );
            ?>
                <!-- ===== Painel de estatísticas ===== -->
                <div class="mp-cl-stats">
                    <div class="mp-cl-stat"><span class="dashicons dashicons-groups"></span><div><b><?php echo count( array_unique( array_merge( array_keys( $by_user ), array_keys( $bk_by_user ) ) ) ); ?></b><small>Utilizadores</small></div></div>
                    <div class="mp-cl-stat"><span class="dashicons dashicons-format-audio"></span><div><b><?php echo (int) $total_files; ?></b><small>Músicas</small></div></div>
                    <div class="mp-cl-stat"><span class="dashicons dashicons-cloud-saved"></span><div><b><?php echo esc_html( size_format( $total_bytes ) ); ?></b><small>Espaço em músicas</small></div></div>
                    <div class="mp-cl-stat"><span class="dashicons dashicons-database-export"></span><div><b><?php echo (int) $bk_count; ?></b><small>Cópias · <?php echo esc_html( size_format( $bk_bytes ) ); ?></small></div></div>
                    <div class="mp-cl-stat <?php echo $total_broken > 0 ? 'is-bad' : 'is-good'; ?>">
                        <span class="dashicons <?php echo $total_broken > 0 ? 'dashicons-warning' : 'dashicons-yes-alt'; ?>"></span><div><b><?php echo $total_broken > 0 ? (int) $total_broken : 'Tudo íntegro'; ?></b>
                        <small><?php echo $total_broken > 0 ? 'Música(s) sem áudio' : 'Áudio e dados disponíveis'; ?></small></div>
                    </div>
                    <div class="mp-cl-stat"><span class="dashicons dashicons-chart-area"></span><div><b><?php echo $quota_mb > 0 ? esc_html( size_format( $quota_mb * 1048576 ) ) : 'Sem limite'; ?></b><small>Quota base por utilizador</small></div></div>
                </div>

                <!-- ===== Pesquisa ===== -->
                <div class="mp-cl-toolbar">
                    <span class="dashicons dashicons-search"></span>
                    <input type="search" id="mp-cl-search" placeholder="Pesquisar utilizador ou e-mail" oninput="mpCloudFilter(this.value)">
                </div>

                <!-- ===== Leitor com diagnóstico ===== -->
                <div id="mp-cloud-player" style="display:none;flex-direction:column;gap:6px;background:#1a1a1f;border-radius:16px;padding:12px 16px;margin-bottom:16px">
                    <div style="display:flex;align-items:center;gap:14px">
                        <img id="mp-cp-cover" src="" alt="" style="width:52px;height:52px;border-radius:10px;object-fit:cover;background:#2a2a2e">
                        <div style="min-width:140px;max-width:260px">
                            <div id="mp-cp-title" style="color:#fff;font-weight:700;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis"></div>
                            <div id="mp-cp-user" style="color:#9aa0a6;font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis"></div>
                        </div>
                        <audio id="mp-cp-audio" controls preload="none" style="flex:1;height:36px"></audio>
                    </div>
                    <div id="mp-cp-status" style="display:none;font-size:12px;padding:6px 10px;border-radius:8px"></div>
                </div>
                <script>
                function mpCpStatus(msg, kind) {
                    var el = document.getElementById('mp-cp-status');
                    if (!msg) { el.style.display = 'none'; return; }
                    el.style.display = 'block';
                    el.textContent = msg;
                    el.style.background = kind === 'err' ? '#3d1f22' : '#1f3d27';
                    el.style.color = kind === 'err' ? '#ff9d9d' : '#9dffb0';
                }
                function mpCloudPlay(url, title, user, cover) {
                    var bar = document.getElementById('mp-cloud-player');
                    bar.style.display = 'flex';
                    document.getElementById('mp-cp-title').textContent = title;
                    document.getElementById('mp-cp-user').textContent = user;
                    var img = document.getElementById('mp-cp-cover');
                    img.src = cover || '';
                    img.style.display = cover ? 'block' : 'none';
                    var a = document.getElementById('mp-cp-audio');
                    mpCpStatus('A pedir o ficheiro à nuvem…');
                    a.onplaying = function(){ mpCpStatus('A tocar — desencriptado no servidor.', 'ok'); };
                    a.onerror = function(){
                        // Vai buscar o diagnóstico real — mas só mostra TEXTO (nunca bytes de áudio).
                        fetch(url).then(function(r){
                            var ct = (r.headers.get('content-type') || '').toLowerCase();
                            if (ct.indexOf('text/html') === -1 && ct.indexOf('text/plain') === -1) {
                                mpCpStatus('Erro: o ficheiro chegou mas o browser não conseguiu descodificar o áudio (formato inesperado). Se persistir, pede ao utilizador para reenviar no app.', 'err');
                                return;
                            }
                            r.text().then(function(t){
                                var doc = new DOMParser().parseFromString(t, 'text/html');
                                var msg = (doc.body ? doc.body.textContent : t).replace(/\s+/g, ' ').trim().slice(0, 320);
                                mpCpStatus('Erro: ' + (msg || 'o ficheiro não pôde ser lido.'), 'err');
                            });
                        }).catch(function(){ mpCpStatus('Erro de ligação ao buscar o ficheiro.', 'err'); });
                    };
                    a.src = url;
                    a.play();
                    bar.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
                }
                function mpCloudFilter(q) {
                    q = q.toLowerCase().trim();
                    document.querySelectorAll('.mp-cl-user').forEach(function(d){
                        var userHit = (d.dataset.search || '').indexOf(q) !== -1;
                        d.style.display = (userHit || q === '') ? '' : 'none';
                    });
                }
                // Listener delegado dos botões ▶ Tocar (imune a caracteres especiais).
                document.addEventListener('click', function(e){
                    var b = e.target.closest ? e.target.closest('.mp-cl-play') : null;
                    if (!b) return;
                    try {
                        mpCloudPlay(b.dataset.url, b.dataset.title, b.dataset.user, b.dataset.cover || '');
                    } catch (err) {
                        var bar = document.getElementById('mp-cloud-player');
                        if (bar) { bar.style.display = 'flex'; }
                        mpCpStatus('Erro de script ao iniciar o leitor: ' + err.message, 'err');
                    }
                });
                // Segurança total: QUALQUER erro de JavaScript nesta página aparece
                // na faixa de diagnóstico — nada falha em silêncio.
                window.addEventListener('error', function(ev){
                    var bar = document.getElementById('mp-cloud-player');
                    if (!bar || bar.style.display === 'none') return;
                    mpCpStatus('Erro de script: ' + (ev.message || 'desconhecido'), 'err');
                });
                </script>
                <?php if ( empty( $by_user ) && empty( $bk_by_user ) ) : ?>
                    <p>Ainda ninguém enviou músicas para a nuvem.</p>
                <?php else : ?>
                    <?php
                    $all_uids = array_unique( array_merge( array_keys( $by_user ), array_keys( $bk_by_user ) ) );
                    foreach ( $all_uids as $uid ) :
                        $data = $by_user[ $uid ] ?? [ 'songs' => [], 'bytes' => 0, 'count' => 0, 'last' => '' ];
                        $bks  = $bk_by_user[ $uid ] ?? [];
                        $email = $emails[ $uid ] ?? "Conta #$uid";
                        $name = trim( $account_names[ $uid ] ?? '' );
                        $over = $quota_mb > 0 && $data['bytes'] >= $quota_mb * 1048576;
                        $pct  = $quota_mb > 0 ? min( 100, round( $data['bytes'] / ( $quota_mb * 1048576 ) * 100 ) ) : 0;
                        $broken_user = 0;
                        foreach ( $data['songs'] as $sg ) { if ( '' === $sg['track'] ) { $broken_user++; } }
                    ?>
                        <details class="mp-cl-user" data-search="<?php echo esc_attr( strtolower( trim( $name . ' ' . $email ) ) ); ?>">
                            <summary class="mp-cl-user-summary" onclick="event.preventDefault();mpCloudOpenUser(<?php echo (int) $uid; ?>)">
                                <span class="mp-avatar"><?php echo esc_html( strtoupper( mb_substr( $name ?: $email, 0, 1 ) ) ); ?></span>
                                <span class="mp-cl-identity">
                                    <strong><?php echo esc_html( $name ?: $email ); ?></strong>
                                    <?php if ( $name ) : ?><small><?php echo esc_html( $email ); ?></small><?php endif; ?>
                                </span>
                                <span class="mp-cl-user-facts">
                                    <span><span class="dashicons dashicons-format-audio"></span><?php echo (int) $data['count']; ?> músicas</span>
                                    <span><span class="dashicons dashicons-cloud-saved"></span><?php echo esc_html( size_format( $data['bytes'] ) ); ?></span>
                                    <?php if ( ! empty( $bks ) ) : ?><span><span class="dashicons dashicons-smartphone"></span><?php echo count( $bks ); ?> cópia(s)</span><?php endif; ?>
                                </span>
                                <span class="mp-cl-user-health <?php echo $broken_user > 0 ? 'is-bad' : 'is-good'; ?>">
                                    <span class="dashicons <?php echo $broken_user > 0 ? 'dashicons-warning' : 'dashicons-yes-alt'; ?>"></span>
                                    <?php echo $broken_user > 0 ? (int) $broken_user . ' sem áudio' : 'Íntegro'; ?>
                                </span>
                                <?php if ( $over ) : ?><span class="mp-pill mp-pill--blocked">Quota cheia</span><?php endif; ?>
                                <?php if ( $data['last'] ) : ?><span class="mp-cl-last">Último envio<br><strong><?php echo esc_html( gmdate( 'd/m/Y H:i', strtotime( $data['last'] ) ) ); ?></strong></span><?php endif; ?>
                                <span class="dashicons dashicons-arrow-right-alt2 mp-cl-open" title="Abrir biblioteca"></span>
                            </summary>
                            <div class="mp-cl-legacy">

                            <?php if ( $quota_mb > 0 ) : ?>
                                <div style="height:7px;border-radius:4px;background:#eceef1;margin:10px 0 4px;overflow:hidden">
                                    <div style="height:100%;width:<?php echo (int) $pct; ?>%;background:<?php echo $over ? '#e05252' : '#ebb000'; ?>"></div>
                                </div>
                                <div style="color:#8a919b;font-size:12px;margin-bottom:6px"><?php echo (int) $pct; ?>% da quota (<?php echo esc_html( size_format( $data['bytes'] ) ); ?> de <?php echo (int) $quota_mb; ?> MB)</div>
                            <?php endif; ?>

                            <?php if ( ! empty( $data['songs'] ) ) : ?>
                            <table class="widefat striped" style="margin-top:10px">
                                <thead><tr><th>Música</th><th style="width:110px">Estado</th><th style="width:110px">Conteúdo</th><th style="width:90px">Tamanho</th><th style="width:130px">Enviada</th><th style="width:190px"></th></tr></thead>
                                <tbody>
                                <?php foreach ( $data['songs'] as $folder => $sng ) :
                                    $pretty = preg_replace( '/-\d+$/', '', $folder );
                                    $has = [];
                                    $cover_url = '';
                                    $has_cover = false; $has_meta = false;
                                    foreach ( $sng['files'] as $f ) {
                                        if ( 0 === strpos( $f['name'], 'track.' ) || preg_match( '/\.(mp3|m4a|aac|ogg|wav|flac)(\.enc)?$/i', $f['name'] ) ) {
                                            $has[] = '🎵';
                                        } elseif ( preg_match( '/\.(jpe?g|png|webp)$/i', $f['name'] ) ) {
                                            $has[] = '🖼️'; $has_cover = true;
                                            $cover_url = mp_s3_presign( 'GET', $f['key'], 3600 );
                                        } elseif ( preg_match( '/\.json$/i', $f['name'] ) ) {
                                            $has[] = '📄'; $has_meta = true;
                                        }
                                    }
                                    // Saúde da música: o erro salta à vista em vez de se esconder.
                                    if ( '' === $sng['track'] ) {
                                        $estado = '<span class="mp-pill mp-pill--blocked" title="A pasta existe mas o ficheiro de áudio nunca chegou — pede ao utilizador para reenviar no app.">✗ SEM ÁUDIO</span>';
                                    } elseif ( ! $has_cover || ! $has_meta ) {
                                        $falta = [];
                                        if ( ! $has_cover ) { $falta[] = 'capa'; }
                                        if ( ! $has_meta ) { $falta[] = 'dados'; }
                                        $estado = '<span class="mp-pill" style="background:#fff3d6;color:#8a6400" title="Toca na mesma; falta ' . esc_attr( implode( ' e ', $falta ) ) . '.">⚠ sem ' . esc_html( implode( '/', $falta ) ) . '</span>';
                                    } else {
                                        $estado = '<span class="mp-pill mp-pill--active" title="Áudio + capa + dados presentes.">✓ completa</span>';
                                    }
                                    // NOTA: wp_nonce_url() passa por esc_html() e deixa "&amp;" na
                                    // URL — ótimo num href (o browser corrige), FATAL em audio.src
                                    // via JS (o PHP recebe "amp;mp_cloud_dl" e o handler nem corre).
                                    // Para o leitor construímos a URL crua, com o nonce à mão.
                                    $stream_url = $sng['track']
                                        ? admin_url( 'admin.php' ) . '?page=mp-control&mp_cloud_dl=' . rawurlencode( $sng['track'] )
                                            . '&mp_cloud_uid=' . (int) $uid . '&stream=1&_wpnonce=' . wp_create_nonce( 'mp_cloud_dl' )
                                        : '';
                                ?>
                                    <tr data-search="<?php echo esc_attr( strtolower( $pretty . ' ' . $email ) ); ?>">
                                        <td>
                                            <span style="display:flex;align-items:center;gap:10px">
                                                <?php if ( $cover_url ) : ?>
                                                    <img src="<?php echo esc_url( $cover_url ); ?>" alt="" style="width:38px;height:38px;border-radius:8px;object-fit:cover" loading="lazy">
                                                <?php else : ?>
                                                    <span style="width:38px;height:38px;border-radius:8px;background:linear-gradient(140deg,#f6cf59,#ebb000);display:inline-flex;align-items:center;justify-content:center">🎵</span>
                                                <?php endif; ?>
                                                <strong><?php echo esc_html( $pretty ); ?></strong>
                                            </span>
                                        </td>
                                        <td><?php echo $estado; // phpcs:ignore ?></td>
                                        <td><?php echo esc_html( $has ? implode( ' ', $has ) : '—' ); ?></td>
                                        <td><?php echo esc_html( size_format( $sng['bytes'] ) ); ?></td>
                                        <td><?php echo esc_html( $sng['modified'] ? gmdate( 'd/m/Y H:i', strtotime( $sng['modified'] ) ) : '—' ); ?></td>
                                        <td style="white-space:nowrap">
                                            <?php if ( $stream_url ) : ?>
                                                <?php // data-attrs + listener delegado: apóstrofos em nomes
                                                      // (I'black…) NUNCA mais partem o HTML do botão. ?>
                                                <button type="button" class="button button-small button-primary mp-cl-play"
                                                    data-url="<?php echo esc_attr( $stream_url ); ?>"
                                                    data-title="<?php echo esc_attr( $pretty ); ?>"
                                                    data-user="<?php echo esc_attr( $email ); ?>"
                                                    data-cover="<?php echo esc_attr( (string) $cover_url ); ?>">▶ Tocar</button>
                                                <a class="button button-small" href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin.php?page=mp-control&mp_cloud_dl=' . rawurlencode( $sng['track'] ) . '&mp_cloud_uid=' . (int) $uid ), 'mp_cloud_dl' ) ); ?>">Baixar</a>
                                            <?php endif; ?>
                                            <form method="post" style="margin:0;display:inline" onsubmit="return confirm('Apagar «<?php echo esc_js( $pretty ); ?>» (áudio + capa + dados) da nuvem?')">
                                                <?php wp_nonce_field( 'mp_cloud_delete' ); ?>
                                                <input type="hidden" name="mp_cloud_folder" value="players/<?php echo (int) $uid; ?>/audio/<?php echo esc_attr( $folder ); ?>">
                                                <button type="submit" name="mp_cloud_delete_folder" value="1" class="button button-small">Apagar</button>
                                            </form>
                                        </td>
                                    </tr>
                                <?php endforeach; ?>
                                </tbody>
                            </table>
                            <?php endif; ?>

                            <?php if ( ! empty( $bks ) ) : ?>
                                <h4 style="margin:14px 0 6px">💾 Cópias de segurança (por dispositivo)</h4>
                                <table class="widefat striped">
                                    <thead><tr><th>Ficheiro</th><th style="width:90px">Tamanho</th><th style="width:150px">Guardada</th><th style="width:90px"></th></tr></thead>
                                    <tbody>
                                    <?php foreach ( $bks as $b ) : ?>
                                        <tr data-search="<?php echo esc_attr( strtolower( 'copia backup ' . $email ) ); ?>">
                                            <td><code style="font-size:11px"><?php echo esc_html( $b['name'] ); ?></code></td>
                                            <td><?php echo esc_html( size_format( $b['size'] ) ); ?></td>
                                            <td><?php echo esc_html( $b['modified'] ? gmdate( 'd/m/Y H:i', strtotime( $b['modified'] ) ) : '—' ); ?></td>
                                            <td>
                                                <form method="post" style="margin:0" onsubmit="return confirm('Apagar esta cópia de segurança? O dispositivo dela perde o restauro.')">
                                                    <?php wp_nonce_field( 'mp_cloud_delete' ); ?>
                                                    <input type="hidden" name="mp_cloud_key" value="<?php echo esc_attr( $b['key'] ); ?>">
                                                    <button type="submit" name="mp_cloud_delete" value="1" class="button button-small">Apagar</button>
                                                </form>
                                            </td>
                                        </tr>
                                    <?php endforeach; ?>
                                    </tbody>
                                </table>
                            <?php endif; ?>

                            <form method="post" style="margin:12px 0 0" onsubmit="return confirm('Apagar TODAS as músicas deste utilizador da nuvem? Esta ação não pode ser desfeita.')">
                                <?php wp_nonce_field( 'mp_cloud_delete' ); ?>
                                <input type="hidden" name="mp_cloud_uid" value="<?php echo (int) $uid; ?>">
                                <button type="submit" name="mp_cloud_delete_user" value="1" class="button button-small" style="color:#c0392b;border-color:#c0392b">Apagar tudo deste utilizador</button>
                            </form>
                            </div>
                        </details>
                    <?php endforeach; ?>
                <?php endif; ?>

                <div class="mp-cloud-modal" id="mp-cloud-modal" hidden aria-hidden="true">
                    <div class="mp-cloud-backdrop" onclick="mpCloudCloseUser()"></div>
                    <section class="mp-cloud-dialog" role="dialog" aria-modal="true" aria-labelledby="mp-cloud-modal-title">
                        <header class="mp-cloud-dialog-head">
                            <span class="mp-avatar mp-avatar--big" id="mp-cloud-modal-avatar">U</span>
                            <div class="mp-cloud-dialog-user">
                                <h2 id="mp-cloud-modal-title">Biblioteca na nuvem</h2>
                                <p id="mp-cloud-modal-user">A carregar conta…</p>
                                <small id="mp-cloud-modal-device"></small>
                            </div>
                            <button type="button" class="mp-cloud-icon-btn" onclick="mpCloudRefreshUser()" title="Atualizar catálogo" aria-label="Atualizar catálogo"><span class="dashicons dashicons-update"></span></button>
                            <button type="button" class="mp-cloud-icon-btn" onclick="mpCloudCloseUser()" title="Fechar" aria-label="Fechar"><span class="dashicons dashicons-no-alt"></span></button>
                        </header>
                        <div class="mp-cloud-dialog-body">
                            <div class="mp-cloud-user-stats" id="mp-cloud-user-stats"></div>
                            <div class="mp-cloud-tabs" role="tablist" aria-label="Conteúdo da conta">
                                <button type="button" class="is-active" id="mp-cloud-tab-tracks" onclick="mpCloudSwitchView('tracks')"><span class="dashicons dashicons-format-audio"></span> Músicas</button>
                                <button type="button" id="mp-cloud-tab-backups" onclick="mpCloudSwitchView('backups')"><span class="dashicons dashicons-smartphone"></span> Cópias de dispositivos <b id="mp-cloud-backup-count">0</b></button>
                            </div>
                            <div id="mp-cloud-view-tracks">
                            <div class="mp-cloud-filters">
                                <label class="mp-cloud-search"><span class="dashicons dashicons-search"></span><input type="search" id="mp-cloud-track-search" placeholder="Pesquisar música ou artista" oninput="mpCloudApplyFilters()"></label>
                                <label><span>Origem</span><select id="mp-cloud-source" onchange="mpCloudApplyFilters()"><option value="">Todas</option></select></label>
                                <label><span>Ano</span><select id="mp-cloud-year" onchange="mpCloudApplyFilters()"><option value="">Todos</option></select></label>
                                <label><span>Género</span><select id="mp-cloud-genre" onchange="mpCloudApplyFilters()"><option value="">Todos</option></select></label>
                            </div>
                            <div class="mp-cloud-result-head"><strong id="mp-cloud-result-count">Músicas</strong><span>12 por página</span></div>
                            <div class="mp-cloud-loading" id="mp-cloud-loading"><span class="spinner is-active"></span><strong>A organizar músicas e metadados…</strong><small>A primeira abertura pode demorar alguns segundos.</small></div>
                            <div class="mp-cloud-track-list" id="mp-cloud-track-list"></div>
                            <nav class="mp-cloud-pagination" id="mp-cloud-pagination" aria-label="Páginas das músicas"></nav>
                            </div>
                            <div id="mp-cloud-view-backups" hidden>
                                <div class="mp-cloud-backup-head">
                                    <div><strong>Cópias guardadas por dispositivo</strong><span>O suporte pode inspecionar, baixar ou remover cada slot após confirmar o pedido do titular.</span></div>
                                    <button type="button" class="mp-cloud-danger-btn" id="mp-cloud-delete-backups" onclick="mpCloudDeleteAllBackups()"><span class="dashicons dashicons-trash"></span> Apagar todas</button>
                                </div>
                                <div class="mp-cloud-backup-list" id="mp-cloud-backup-list"></div>
                            </div>
                        </div>
                    </section>
                </div>

                <script>
                var MP_CLOUD_AJAX = <?php echo wp_json_encode( admin_url( 'admin-ajax.php' ) ); ?>;
                var MP_CLOUD_NONCE = <?php echo wp_json_encode( wp_create_nonce( 'mp_cloud_catalog' ) ); ?>;
                var mpCloudCatalogCache = {};
                var mpCloudState = { uid: 0, payload: null, tracks: [], backups: [], filtered: [], page: 1, perPage: 12, view: 'tracks' };

                function mpCloudEsc(value) {
                    return String(value == null ? '' : value).replace(/[&<>"']/g, function(ch) {
                        return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#039;'}[ch];
                    });
                }
                function mpCloudBytes(bytes) {
                    bytes = Number(bytes || 0);
                    if (bytes >= 1073741824) return (bytes / 1073741824).toFixed(1).replace('.0','') + ' GB';
                    if (bytes >= 1048576) return (bytes / 1048576).toFixed(1).replace('.0','') + ' MB';
                    if (bytes >= 1024) return Math.round(bytes / 1024) + ' KB';
                    return bytes + ' B';
                }
                function mpCloudDuration(ms) {
                    var total = Math.max(0, Math.round(Number(ms || 0) / 1000));
                    var h = Math.floor(total / 3600), m = Math.floor((total % 3600) / 60), s = total % 60;
                    return h ? h + ':' + String(m).padStart(2,'0') + ':' + String(s).padStart(2,'0') : m + ':' + String(s).padStart(2,'0');
                }
                function mpCloudDate(track) {
                    var stamp = Number(track.uploaded_at || 0);
                    var date = stamp ? new Date(stamp) : new Date(track.modified || '');
                    return isNaN(date.getTime()) ? '—' : date.toLocaleString('pt-PT', {dateStyle:'short', timeStyle:'short'});
                }
                function mpCloudBackupDate(backup) {
                    var stamp = Number(backup.saved_at || 0);
                    var date = stamp ? new Date(stamp) : new Date(backup.modified || '');
                    return isNaN(date.getTime()) ? '—' : date.toLocaleString('pt-PT', {dateStyle:'short', timeStyle:'short'});
                }
                function mpCloudSource(source) {
                    source = String(source || 'LOCAL').toUpperCase();
                    return source.indexOf('YOUTUBE') !== -1 ? 'YouTube' : (source === 'LOCAL' ? 'Telefone' : source);
                }
                function mpCloudOpenUser(uid, refresh) {
                    var modal = document.getElementById('mp-cloud-modal');
                    mpCloudState.uid = Number(uid);
                    modal.hidden = false;
                    modal.setAttribute('aria-hidden', 'false');
                    document.body.classList.add('mp-cloud-modal-open');
                    document.getElementById('mp-cloud-modal-user').textContent = 'A carregar conta…';
                    var loading = document.getElementById('mp-cloud-loading');
                    loading.classList.remove('is-error');
                    loading.innerHTML = '<span class="spinner is-active"></span><strong>A organizar músicas e metadados…</strong><small>A primeira abertura pode demorar alguns segundos.</small>';
                    loading.style.display = 'flex';
                    document.getElementById('mp-cloud-track-list').innerHTML = '';
                    document.getElementById('mp-cloud-pagination').innerHTML = '';
                    document.getElementById('mp-cloud-backup-list').innerHTML = '';
                    document.getElementById('mp-cloud-backup-count').textContent = '0';
                    mpCloudSwitchView('tracks');
                    if (!refresh && mpCloudCatalogCache[uid]) {
                        mpCloudUseCatalog(mpCloudCatalogCache[uid]);
                        return;
                    }
                    var body = new URLSearchParams();
                    body.set('action', 'mp_cloud_user_catalog');
                    body.set('nonce', MP_CLOUD_NONCE);
                    body.set('uid', uid);
                    if (refresh) body.set('refresh', '1');
                    fetch(MP_CLOUD_AJAX, {method:'POST', credentials:'same-origin', headers:{'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8'}, body:body.toString()})
                        .then(function(response){ return response.json(); })
                        .then(function(json){
                            if (!json || !json.success) throw new Error(json && json.data && json.data.message ? json.data.message : 'Não foi possível ler a nuvem.');
                            mpCloudCatalogCache[uid] = json.data;
                            mpCloudUseCatalog(json.data);
                        })
                        .catch(function(error){
                            var loading = document.getElementById('mp-cloud-loading');
                            loading.style.display = 'flex';
                            loading.classList.add('is-error');
                            loading.innerHTML = '<span class="dashicons dashicons-warning"></span><strong>' + mpCloudEsc(error.message) + '</strong><small>Tenta atualizar o catálogo.</small>';
                        });
                }
                function mpCloudUseCatalog(data) {
                    mpCloudState.payload = data;
                    mpCloudState.tracks = (data.tracks || []).map(function(track, index){ track._index = index; return track; });
                    mpCloudState.backups = (data.backups || []).map(function(backup, index){ backup._index = index; return backup; });
                    mpCloudState.page = 1;
                    var user = data.user || {};
                    var shownName = user.name || user.email || ('Conta #' + user.id);
                    document.getElementById('mp-cloud-modal-avatar').textContent = shownName.charAt(0).toUpperCase() || 'U';
                    document.getElementById('mp-cloud-modal-title').textContent = shownName;
                    document.getElementById('mp-cloud-modal-user').textContent = user.name ? user.email : 'Biblioteca na nuvem';
                    document.getElementById('mp-cloud-modal-device').textContent = [user.device, user.vip ? 'VIP ' + (user.vip_source || '') : 'Conta gratuita'].filter(Boolean).join(' · ');
                    var summary = data.summary || {};
                    document.getElementById('mp-cloud-user-stats').innerHTML =
                        mpCloudMetric('format-audio', summary.tracks || 0, 'Músicas') +
                        mpCloudMetric('cloud-saved', mpCloudBytes(summary.bytes), 'Espaço usado') +
                        mpCloudMetric('yes-alt', summary.complete || 0, 'Completas') +
                        mpCloudMetric('database-export', summary.backups || 0, 'Cópias de dados');
                    mpCloudFillSelect('mp-cloud-source', data.filters && data.filters.sources, 'Todas');
                    mpCloudFillSelect('mp-cloud-year', data.filters && data.filters.years, 'Todos');
                    mpCloudFillSelect('mp-cloud-genre', data.filters && data.filters.genres, 'Todos');
                    document.getElementById('mp-cloud-track-search').value = '';
                    document.getElementById('mp-cloud-loading').classList.remove('is-error');
                    document.getElementById('mp-cloud-loading').style.display = 'none';
                    document.getElementById('mp-cloud-backup-count').textContent = mpCloudState.backups.length;
                    mpCloudApplyFilters();
                    mpCloudRenderBackups();
                    if (mpCloudState.view === 'tracks') document.getElementById('mp-cloud-track-search').focus();
                }
                function mpCloudMetric(icon, value, label) {
                    return '<div><span class="dashicons dashicons-' + icon + '"></span><p><strong>' + mpCloudEsc(value) + '</strong><small>' + mpCloudEsc(label) + '</small></p></div>';
                }
                function mpCloudFillSelect(id, values, first) {
                    var select = document.getElementById(id);
                    select.innerHTML = '<option value="">' + mpCloudEsc(first) + '</option>' + (values || []).map(function(value){
                        var label = id === 'mp-cloud-source' ? mpCloudSource(value) : value;
                        return '<option value="' + mpCloudEsc(value) + '">' + mpCloudEsc(label) + '</option>';
                    }).join('');
                }
                function mpCloudSwitchView(view) {
                    mpCloudState.view = view === 'backups' ? 'backups' : 'tracks';
                    var tracks = mpCloudState.view === 'tracks';
                    document.getElementById('mp-cloud-view-tracks').hidden = !tracks;
                    document.getElementById('mp-cloud-view-backups').hidden = tracks;
                    document.getElementById('mp-cloud-tab-tracks').classList.toggle('is-active', tracks);
                    document.getElementById('mp-cloud-tab-backups').classList.toggle('is-active', !tracks);
                    if (tracks && mpCloudState.payload) document.getElementById('mp-cloud-track-search').focus();
                }
                function mpCloudApplyFilters() {
                    if (!mpCloudState.payload) return;
                    var query = document.getElementById('mp-cloud-track-search').value.toLowerCase().trim();
                    var source = document.getElementById('mp-cloud-source').value;
                    var year = document.getElementById('mp-cloud-year').value;
                    var genre = document.getElementById('mp-cloud-genre').value;
                    mpCloudState.filtered = mpCloudState.tracks.filter(function(track){
                        var haystack = [track.title, track.artist, track.album, track.genre, track.year, track.source, track.folder].join(' ').toLowerCase();
                        return (!query || haystack.indexOf(query) !== -1) && (!source || track.source === source) && (!year || String(track.year) === year) && (!genre || track.genre === genre);
                    });
                    mpCloudState.page = 1;
                    mpCloudRenderTracks();
                }
                function mpCloudRenderTracks() {
                    var total = mpCloudState.filtered.length;
                    var pages = Math.max(1, Math.ceil(total / mpCloudState.perPage));
                    mpCloudState.page = Math.min(mpCloudState.page, pages);
                    var start = (mpCloudState.page - 1) * mpCloudState.perPage;
                    var visible = mpCloudState.filtered.slice(start, start + mpCloudState.perPage);
                    document.getElementById('mp-cloud-result-count').textContent = total + ' música' + (total === 1 ? '' : 's');
                    document.getElementById('mp-cloud-track-list').innerHTML = visible.length
                        ? visible.map(mpCloudTrackHtml).join('')
                        : '<div class="mp-cloud-empty"><span class="dashicons dashicons-search"></span><strong>Nenhuma música encontrada</strong><small>Experimenta outro artista, origem, ano ou género.</small></div>';
                    mpCloudRenderPagination(pages);
                }
                function mpCloudTrackHtml(track) {
                    var cover = track.cover_url
                        ? '<span class="mp-cloud-cover"><img src="' + mpCloudEsc(track.cover_url) + '" alt="" loading="lazy" onerror="this.hidden=true;this.nextElementSibling.hidden=false"><span class="dashicons dashicons-format-audio" hidden></span></span>'
                        : '<span class="mp-cloud-cover"><span class="dashicons dashicons-format-audio"></span></span>';
                    var status = track.status === 'complete' ? '<span class="mp-cloud-chip is-ok">Completa</span>' : (track.status === 'broken' ? '<span class="mp-cloud-chip is-bad">Sem áudio</span>' : '<span class="mp-cloud-chip is-warn">Parcial</span>');
                    var source = '<span class="mp-cloud-chip">' + mpCloudEsc(mpCloudSource(track.source)) + '</span>';
                    var meta = track.metadata || {};
                    var files = (track.files || []).map(function(file){ return '<tr><td>' + mpCloudEsc(file.name) + '</td><td>' + mpCloudEsc(mpCloudBytes(file.size)) + '</td></tr>'; }).join('');
                    var sourceLink = /^https?:\/\//i.test(track.source_url || '') ? '<a href="' + mpCloudEsc(track.source_url) + '" target="_blank" rel="noopener">Abrir origem</a>' : '—';
                    var actions = '';
                    if (track.stream_url) actions += '<button type="button" class="mp-cloud-row-action is-primary" onclick="event.preventDefault();event.stopPropagation();mpCloudPlayAt(' + track._index + ')" title="Tocar"><span class="dashicons dashicons-controls-play"></span></button>';
                    if (track.download_url) actions += '<a class="mp-cloud-row-action" href="' + mpCloudEsc(track.download_url) + '" onclick="event.stopPropagation()" title="Baixar"><span class="dashicons dashicons-download"></span></a>';
                    actions += '<button type="button" class="mp-cloud-row-action is-danger" onclick="event.preventDefault();event.stopPropagation();mpCloudDeleteAt(' + track._index + ')" title="Apagar"><span class="dashicons dashicons-trash"></span></button>';
                    return '<details class="mp-cloud-track"><summary>' + cover +
                        '<span class="mp-cloud-track-main"><strong>' + mpCloudEsc(track.title || 'Sem título') + '</strong><small>' + mpCloudEsc(track.artist || 'Artista desconhecido') + (track.album ? ' · ' + mpCloudEsc(track.album) : '') + '</small><span>' + source + status + (track.genre ? '<span class="mp-cloud-chip">' + mpCloudEsc(track.genre) + '</span>' : '') + (track.year ? '<span class="mp-cloud-chip">' + mpCloudEsc(track.year) + '</span>' : '') + '</span></span>' +
                        '<span class="mp-cloud-track-size"><strong>' + mpCloudEsc(mpCloudBytes(track.bytes)) + '</strong><small>' + mpCloudEsc(mpCloudDuration(track.duration_ms)) + '</small></span>' +
                        '<span class="mp-cloud-track-date"><strong>Enviada</strong><small>' + mpCloudEsc(mpCloudDate(track)) + '</small></span>' +
                        '<span class="mp-cloud-track-actions">' + actions + '</span><span class="dashicons dashicons-arrow-down-alt2 mp-cloud-expand"></span></summary>' +
                        '<div class="mp-cloud-track-detail"><dl>' +
                        mpCloudInfo('ID da música', track.song_id || '—') + mpCloudInfo('Título', track.title || '—') + mpCloudInfo('Artista', track.artist || '—') + mpCloudInfo('Álbum', track.album || '—') +
                        mpCloudInfo('Género', track.genre || '—') + mpCloudInfo('Ano', track.year || '—') + mpCloudInfo('Origem', mpCloudSource(track.source)) + mpCloudInfo('URL de origem', sourceLink, true) +
                        mpCloudInfo('Duração', mpCloudDuration(track.duration_ms)) + mpCloudInfo('Formato', track.mime_type || '—') + mpCloudInfo('Tamanho original', track.original_size ? mpCloudBytes(track.original_size) : '—') + mpCloudInfo('Pasta no aparelho', track.device_folder || '—') +
                        mpCloudInfo('Adicionada ao aparelho', track.date_added ? new Date(track.date_added * 1000).toLocaleString('pt-PT') : '—') + mpCloudInfo('Download offline', track.downloaded_at ? new Date(track.downloaded_at).toLocaleString('pt-PT') : '—') + mpCloudInfo('Início do corte', mpCloudDuration(track.clip_start_ms)) + mpCloudInfo('Fim do corte', track.clip_end_ms ? mpCloudDuration(track.clip_end_ms) : '—') +
                        mpCloudInfo('Encriptação', track.encrypted ? 'AES-256 ativa' : 'Não indicada') + mpCloudInfo('Pasta S3', track.folder) + mpCloudInfo('Tamanho na nuvem', mpCloudBytes(track.bytes)) +
                        '</dl><div class="mp-cloud-files"><h4>Ficheiros recolhidos</h4><table><tbody>' + files + '</tbody></table></div>' +
                        '<details class="mp-cloud-raw"><summary>Todos os dados recolhidos</summary><pre>' + mpCloudEsc(JSON.stringify(meta, null, 2)) + '</pre></details></div></details>';
                }
                function mpCloudRenderBackups() {
                    var list = document.getElementById('mp-cloud-backup-list');
                    var button = document.getElementById('mp-cloud-delete-backups');
                    button.disabled = mpCloudState.backups.length === 0;
                    list.innerHTML = mpCloudState.backups.length
                        ? mpCloudState.backups.map(mpCloudBackupHtml).join('')
                        : '<div class="mp-cloud-empty"><span class="dashicons dashicons-smartphone"></span><strong>Nenhuma cópia de dispositivo</strong><small>Esta conta ainda não guardou definições, playlists ou gostos por dispositivo.</small></div>';
                }
                function mpCloudCategoryLabel(key) {
                    return ({favorites:'Gostos', playlists:'Playlists', settings:'Definições', youtube:'YouTube', tags:'Tags', covers:'Capas', history:'Histórico', folders:'Pastas'})[key] || key;
                }
                function mpCloudBackupHtml(backup) {
                    var categories = (backup.categories || []).map(function(key){
                        var count = backup.category_counts && backup.category_counts[key];
                        return '<span class="mp-cloud-chip">' + mpCloudEsc(mpCloudCategoryLabel(key)) + (count ? ' · ' + mpCloudEsc(count) : '') + '</span>';
                    }).join('');
                    var status = backup.readable
                        ? '<span class="mp-cloud-chip is-ok">Íntegra</span>'
                        : '<span class="mp-cloud-chip is-warn">Formato antigo</span>';
                    var actions = '<a class="mp-cloud-row-action" href="' + mpCloudEsc(backup.download_url || '#') + '" onclick="event.stopPropagation()" title="Baixar JSON"><span class="dashicons dashicons-download"></span></a>' +
                        '<button type="button" class="mp-cloud-row-action is-danger" onclick="event.preventDefault();event.stopPropagation();mpCloudDeleteBackupAt(' + backup._index + ')" title="Apagar cópia"><span class="dashicons dashicons-trash"></span></button>';
                    return '<details class="mp-cloud-backup"><summary>' +
                        '<span class="mp-cloud-backup-icon"><span class="dashicons dashicons-smartphone"></span></span>' +
                        '<span class="mp-cloud-track-main"><strong>' + mpCloudEsc(backup.device || backup.slot_id || 'Dispositivo') + '</strong><small>Slot ' + mpCloudEsc(backup.slot_id || backup.name) + '</small><span>' + status + categories + '</span></span>' +
                        '<span class="mp-cloud-track-size"><strong>' + mpCloudEsc(mpCloudBytes(backup.size)) + '</strong><small>' + mpCloudEsc(mpCloudBackupDate(backup)) + '</small></span>' +
                        '<span class="mp-cloud-track-actions">' + actions + '</span><span class="dashicons dashicons-arrow-down-alt2 mp-cloud-expand"></span></summary>' +
                        '<div class="mp-cloud-backup-detail"><dl>' +
                        mpCloudInfo('Nome do aparelho', backup.device || '—') + mpCloudInfo('ID do dispositivo', backup.device_id || '—') +
                        mpCloudInfo('Slot', backup.slot_id || backup.name) + mpCloudInfo('Guardada em', mpCloudBackupDate(backup)) +
                        mpCloudInfo('Versão dos dados', backup.schema_version || 'Legada') + mpCloudInfo('Tamanho', mpCloudBytes(backup.size)) +
                        mpCloudInfo('Última alteração S3', backup.modified || '—') + mpCloudInfo('Chave S3', backup.key || '—') +
                        '</dl><div class="mp-cloud-backup-categories"><strong>Dados incluídos</strong><span>' + (categories || 'Não foi possível ler as categorias desta cópia.') + '</span></div></div></details>';
                }
                function mpCloudInfo(label, value, html) {
                    return '<div><dt>' + mpCloudEsc(label) + '</dt><dd>' + (html ? value : mpCloudEsc(value)) + '</dd></div>';
                }
                function mpCloudRenderPagination(totalPages) {
                    var nav = document.getElementById('mp-cloud-pagination');
                    if (totalPages <= 1) { nav.innerHTML = ''; return; }
                    var current = mpCloudState.page;
                    var start = Math.max(1, Math.min(current - 2, totalPages - 4));
                    var end = Math.min(totalPages, start + 4);
                    var pages = [];
                    if (start > 1) { pages.push(1); if (start > 2) pages.push('…'); }
                    for (var i = start; i <= end; i++) pages.push(i);
                    if (end < totalPages) { if (end < totalPages - 1) pages.push('…'); pages.push(totalPages); }
                    nav.innerHTML = '<button type="button" ' + (current === 1 ? 'disabled' : '') + ' onclick="mpCloudPage(' + (current - 1) + ')" aria-label="Página anterior"><span class="dashicons dashicons-arrow-left-alt2"></span></button>' +
                        pages.map(function(page){ return page === '…' ? '<span>…</span>' : '<button type="button" class="' + (page === current ? 'is-current' : '') + '" onclick="mpCloudPage(' + page + ')">' + page + '</button>'; }).join('') +
                        '<button type="button" ' + (current === totalPages ? 'disabled' : '') + ' onclick="mpCloudPage(' + (current + 1) + ')" aria-label="Página seguinte"><span class="dashicons dashicons-arrow-right-alt2"></span></button>';
                }
                function mpCloudPage(page) {
                    mpCloudState.page = page;
                    mpCloudRenderTracks();
                    document.getElementById('mp-cloud-track-list').scrollIntoView({behavior:'smooth', block:'start'});
                }
                function mpCloudPlayAt(index) {
                    var track = mpCloudState.tracks[index];
                    if (track && track.stream_url) mpCloudPlay(track.stream_url, track.title, track.artist || (mpCloudState.payload.user || {}).email, track.cover_url || '');
                }
                function mpCloudDeleteAt(index) {
                    var track = mpCloudState.tracks[index];
                    if (!track || !confirm('Apagar «' + (track.title || 'esta música') + '» da nuvem? Áudio, capa e dados serão removidos.')) return;
                    var form = document.createElement('form');
                    form.method = 'post'; form.action = mpCloudState.payload.post_url;
                    [['mp_cloud_folder', track.folder_key], ['mp_cloud_delete_folder', '1'], ['_wpnonce', mpCloudState.payload.delete_nonce]].forEach(function(pair){
                        var input = document.createElement('input'); input.type = 'hidden'; input.name = pair[0]; input.value = pair[1]; form.appendChild(input);
                    });
                    document.body.appendChild(form); form.submit();
                }
                function mpCloudDeleteBackupAt(index) {
                    var backup = mpCloudState.backups[index];
                    if (!backup || !confirm('Apagar a cópia de «' + (backup.device || backup.slot_id || 'este dispositivo') + '»? O utilizador deixará de poder importá-la.')) return;
                    mpCloudSubmit({mp_cloud_key: backup.key, mp_cloud_delete: '1'});
                }
                function mpCloudDeleteAllBackups() {
                    if (!mpCloudState.backups.length || !confirm('Apagar TODAS as cópias de dispositivos desta conta? Confirma primeiro o pedido do titular pelo suporte.')) return;
                    mpCloudSubmit({mp_cloud_uid: mpCloudState.uid, mp_cloud_delete_backups: '1'});
                }
                function mpCloudSubmit(fields) {
                    var form = document.createElement('form');
                    form.method = 'post'; form.action = mpCloudState.payload.post_url;
                    fields._wpnonce = mpCloudState.payload.delete_nonce;
                    Object.keys(fields).forEach(function(name){
                        var input = document.createElement('input'); input.type = 'hidden'; input.name = name; input.value = fields[name]; form.appendChild(input);
                    });
                    document.body.appendChild(form); form.submit();
                }
                function mpCloudRefreshUser() {
                    if (mpCloudState.uid) { delete mpCloudCatalogCache[mpCloudState.uid]; mpCloudOpenUser(mpCloudState.uid, true); }
                }
                function mpCloudCloseUser() {
                    var modal = document.getElementById('mp-cloud-modal');
                    modal.hidden = true; modal.setAttribute('aria-hidden', 'true');
                    document.body.classList.remove('mp-cloud-modal-open');
                }
                document.addEventListener('keydown', function(event){ if (event.key === 'Escape' && !document.getElementById('mp-cloud-modal').hidden) mpCloudCloseUser(); });
                </script>

                <style>
                    .mp-cloud-admin{border-radius:8px!important;padding:22px!important}.mp-cloud-head{margin-bottom:18px!important}
                    .mp-cl-stats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin-bottom:16px}
                    .mp-cl-stat{display:flex;align-items:center;gap:12px;background:#f8f9fb;border:1px solid #e3e6eb;border-radius:8px;padding:14px;min-height:58px}
                    .mp-cl-stat>.dashicons{width:34px;height:34px;font-size:20px;display:flex;align-items:center;justify-content:center;border-radius:8px;background:#e7e9ee;color:#40464f;flex:0 0 auto}
                    .mp-cl-stat div{min-width:0}.mp-cl-stat b{display:block;font-size:20px;line-height:1.15;color:#1a1d22}.mp-cl-stat small{display:block;color:#69717c;font-size:12px;margin-top:3px}
                    .mp-cl-stat.is-bad{border-color:#efb8b8;background:#fff8f7}.mp-cl-stat.is-bad b,.mp-cl-stat.is-bad>.dashicons{color:#b42318}.mp-cl-stat.is-good>.dashicons{color:#087a46;background:#dff5e8}
                    .mp-cl-toolbar{position:relative;max-width:460px;margin-bottom:14px}.mp-cl-toolbar>.dashicons{position:absolute;left:13px;top:50%;transform:translateY(-50%);color:#6c7480;pointer-events:none}
                    .mp-cl-toolbar input{width:100%;height:42px;padding:8px 14px 8px 42px!important;border:1px solid #cfd4dc!important;border-radius:8px!important;background:#fff!important;box-shadow:none!important}
                    .mp-cl-user{display:block;border:1px solid #e1e4e9;border-radius:8px;margin-bottom:8px;background:#fff;overflow:hidden}.mp-cl-user[open]{background:#fff}.mp-cl-user>summary::-webkit-details-marker{display:none}.mp-cl-user>summary{list-style:none}
                    .mp-cl-user-summary{display:grid;grid-template-columns:auto minmax(180px,1.1fr) minmax(250px,1.4fr) auto auto auto;align-items:center;gap:14px;padding:13px 14px;cursor:pointer;transition:background .15s,border-color .15s}
                    .mp-cl-user-summary:hover{background:#f6f7f9}.mp-cl-identity{display:flex;flex-direction:column;min-width:0}.mp-cl-identity strong,.mp-cl-identity small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mp-cl-identity strong{font-size:14px}.mp-cl-identity small{color:#6d7480;margin-top:3px}
                    .mp-cl-user-facts{display:flex;gap:14px;flex-wrap:wrap}.mp-cl-user-facts>span{display:inline-flex;align-items:center;gap:5px;color:#565e69;font-size:12px}.mp-cl-user-facts .dashicons{font-size:16px;width:16px;height:16px;color:#6a5f24}
                    .mp-cl-user-health{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:700;white-space:nowrap}.mp-cl-user-health.is-good{color:#087a46}.mp-cl-user-health.is-bad{color:#b42318}.mp-cl-user-health .dashicons{font-size:17px;width:17px;height:17px}.mp-cl-last{font-size:11px;color:#707985;line-height:1.35;white-space:nowrap}.mp-cl-last strong{color:#303640;font-size:12px}.mp-cl-open{color:#69717c}.mp-cl-legacy{display:none!important}
                    .mp-cloud-modal[hidden]{display:none!important}.mp-cloud-modal{position:fixed;inset:0;z-index:100000;display:flex;align-items:center;justify-content:center;padding:24px}.mp-cloud-backdrop{position:absolute;inset:0;background:rgba(18,20,24,.62)}
                    .mp-cloud-dialog{position:relative;width:min(1180px,calc(100vw - 48px));height:min(860px,calc(100vh - 48px));display:flex;flex-direction:column;background:#f7f8fa;border:1px solid #d9dde4;border-radius:8px;box-shadow:0 24px 80px rgba(0,0,0,.28);overflow:hidden}
                    .mp-cloud-dialog-head{display:flex;align-items:center;gap:13px;padding:16px 18px;background:#fff;border-bottom:1px solid #dfe3e8;flex:0 0 auto}.mp-cloud-dialog-user{flex:1;min-width:0}.mp-cloud-dialog-user h2{font-size:18px!important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mp-cloud-dialog-user p{margin:2px 0 0;color:#5f6772;font-size:13px}.mp-cloud-dialog-user small{display:block;margin-top:2px;color:#7a828d}
                    .mp-cloud-icon-btn,.mp-cloud-row-action{display:inline-flex;align-items:center;justify-content:center;border:1px solid #d4d9e0;background:#fff;color:#343a43;cursor:pointer;text-decoration:none}.mp-cloud-icon-btn{width:40px;height:40px;border-radius:50%;padding:0}.mp-cloud-icon-btn:hover,.mp-cloud-row-action:hover{background:#eef1f5;color:#15181d}.mp-cloud-icon-btn .dashicons{font-size:20px;width:20px;height:20px}
                    .mp-cloud-dialog-body{overflow:auto;padding:16px 18px 110px}.mp-cloud-user-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;margin-bottom:14px}.mp-cloud-user-stats>div{display:flex;align-items:center;gap:10px;border:1px solid #e0e3e8;background:#fff;border-radius:8px;padding:11px 12px}.mp-cloud-user-stats>div>.dashicons{color:#53606d}.mp-cloud-user-stats p{margin:0}.mp-cloud-user-stats strong,.mp-cloud-user-stats small{display:block}.mp-cloud-user-stats strong{font-size:16px}.mp-cloud-user-stats small{color:#707984;font-size:11px;margin-top:2px}
                    .mp-cloud-tabs{display:flex;gap:4px;border-bottom:1px solid #d9dde3;margin:0 0 14px}.mp-cloud-tabs button{display:inline-flex;align-items:center;gap:7px;min-height:42px;padding:8px 13px;border:0;border-bottom:3px solid transparent;background:transparent;color:#5a626d;cursor:pointer;font-weight:700}.mp-cloud-tabs button.is-active{color:#1f242b;border-bottom-color:#2271b1}.mp-cloud-tabs button:hover{background:#eef1f5}.mp-cloud-tabs b{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:20px;padding:0 5px;border-radius:10px;background:#e2e6eb;font-size:11px}.mp-cloud-tabs button.is-active b{background:#d8eaf7;color:#135e96}
                    .mp-cloud-filters{display:grid;grid-template-columns:minmax(260px,1.5fr) repeat(3,minmax(130px,.6fr));gap:8px;margin-bottom:12px}.mp-cloud-filters label:not(.mp-cloud-search){display:flex;flex-direction:column;gap:4px}.mp-cloud-filters label>span{font-size:11px;font-weight:700;color:#5f6772}.mp-cloud-filters input,.mp-cloud-filters select{width:100%;height:42px!important;min-height:42px;border:1px solid #ccd2da!important;border-radius:8px!important;background:#fff!important;box-shadow:none!important}.mp-cloud-search{position:relative;align-self:end}.mp-cloud-search>.dashicons{position:absolute;left:12px;top:50%;transform:translateY(-50%);z-index:1;color:#707985}.mp-cloud-search input{padding-left:40px!important}
                    .mp-cloud-result-head{display:flex;justify-content:space-between;align-items:center;margin:14px 2px 7px}.mp-cloud-result-head strong{font-size:14px}.mp-cloud-result-head span{font-size:11px;color:#737b86}.mp-cloud-loading,.mp-cloud-empty{min-height:220px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;color:#606976;text-align:center}.mp-cloud-loading .spinner{float:none;margin:0 0 8px}.mp-cloud-loading small,.mp-cloud-empty small{color:#808894}.mp-cloud-loading.is-error{color:#b42318}
                    .mp-cloud-track-list{background:#fff;border:1px solid #dfe3e8;border-radius:8px;overflow:hidden}.mp-cloud-track{border-bottom:1px solid #e9ebef}.mp-cloud-track:last-child{border-bottom:none}.mp-cloud-track>summary{display:grid;grid-template-columns:58px minmax(220px,1fr) 90px 120px auto 20px;gap:12px;align-items:center;padding:10px 12px;cursor:pointer;list-style:none}.mp-cloud-track>summary::-webkit-details-marker{display:none}.mp-cloud-track>summary:hover{background:#f7f8fa}.mp-cloud-cover{width:58px;height:58px;border-radius:6px;background:#e7e9ed;display:flex;align-items:center;justify-content:center;overflow:hidden;color:#5c6570}.mp-cloud-cover img{width:100%;height:100%;object-fit:cover}.mp-cloud-cover .dashicons{font-size:24px;width:24px;height:24px}.mp-cloud-track-main{display:flex;flex-direction:column;min-width:0}.mp-cloud-track-main>strong,.mp-cloud-track-main>small{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mp-cloud-track-main>strong{font-size:14px}.mp-cloud-track-main>small{color:#646d78;margin:3px 0 6px}.mp-cloud-track-main>span{display:flex;gap:5px;flex-wrap:wrap}.mp-cloud-chip{display:inline-flex;padding:2px 7px;border-radius:999px;background:#eceff3;color:#4d5661;font-size:10px;font-weight:700}.mp-cloud-chip.is-ok{background:#dff5e8;color:#087a46}.mp-cloud-chip.is-warn{background:#fff1cc;color:#805900}.mp-cloud-chip.is-bad{background:#fde5e2;color:#b42318}
                    .mp-cloud-track-size,.mp-cloud-track-date{display:flex;flex-direction:column;gap:3px}.mp-cloud-track-size small,.mp-cloud-track-date small{color:#737c87;font-size:11px}.mp-cloud-track-date strong{font-size:11px;text-transform:uppercase;color:#6d7580}.mp-cloud-track-actions{display:flex;gap:5px}.mp-cloud-row-action{width:34px;height:34px;border-radius:50%;padding:0}.mp-cloud-row-action.is-primary{background:#20242a;color:#fff;border-color:#20242a}.mp-cloud-row-action.is-danger{color:#b42318}.mp-cloud-row-action .dashicons{font-size:17px;width:17px;height:17px}.mp-cloud-expand{color:#6c7580;transition:transform .15s}.mp-cloud-track[open] .mp-cloud-expand{transform:rotate(180deg)}
                    .mp-cloud-track-detail{padding:14px 18px 18px 88px;background:#f8f9fb;border-top:1px solid #e5e8ed}.mp-cloud-track-detail>dl{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;margin:0}.mp-cloud-track-detail>dl>div{min-width:0;background:#fff;border:1px solid #e2e5ea;border-radius:6px;padding:9px}.mp-cloud-track-detail dt{font-size:10px;text-transform:uppercase;font-weight:700;color:#747d88}.mp-cloud-track-detail dd{margin:4px 0 0;font-size:12px;color:#292e35;overflow-wrap:anywhere}.mp-cloud-files{margin-top:12px}.mp-cloud-files h4{margin:0 0 6px}.mp-cloud-files table{width:100%;border-collapse:collapse;background:#fff;border:1px solid #e2e5ea}.mp-cloud-files td{padding:7px 9px;border-bottom:1px solid #eceef1;font-size:11px}.mp-cloud-files td:last-child{text-align:right;white-space:nowrap}.mp-cloud-raw{margin-top:10px}.mp-cloud-raw>summary{cursor:pointer;font-weight:700;font-size:12px;color:#4e5864}.mp-cloud-raw pre{max-height:300px;overflow:auto;background:#20242a;color:#e9edf2;padding:12px;border-radius:6px;font-size:11px;white-space:pre-wrap;overflow-wrap:anywhere}
                    .mp-cloud-pagination{display:flex;align-items:center;justify-content:center;gap:5px;margin-top:14px}.mp-cloud-pagination button{min-width:36px;height:36px;border:1px solid #ccd2da;border-radius:50%;background:#fff;cursor:pointer;font-weight:700;color:#343a43}.mp-cloud-pagination button.is-current{background:#20242a;color:#fff;border-color:#20242a}.mp-cloud-pagination button:disabled{opacity:.35;cursor:default}.mp-cloud-pagination>span{padding:0 4px;color:#707984}
                    .mp-cloud-backup-head{display:flex;align-items:center;justify-content:space-between;gap:16px;margin:4px 0 10px}.mp-cloud-backup-head>div{display:flex;flex-direction:column;gap:3px}.mp-cloud-backup-head>div>span{font-size:12px;color:#69727d}.mp-cloud-danger-btn{display:inline-flex;align-items:center;gap:6px;height:38px;padding:0 12px;border:1px solid #d7a7a3;border-radius:8px;background:#fff;color:#b42318;cursor:pointer;font-weight:700}.mp-cloud-danger-btn:hover{background:#fff3f1}.mp-cloud-danger-btn:disabled{opacity:.4;cursor:default}.mp-cloud-backup-list{background:#fff;border:1px solid #dfe3e8;border-radius:8px;overflow:hidden}.mp-cloud-backup{border-bottom:1px solid #e8ebef}.mp-cloud-backup:last-child{border-bottom:0}.mp-cloud-backup>summary{display:grid;grid-template-columns:52px minmax(240px,1fr) 150px auto 20px;gap:12px;align-items:center;padding:12px;cursor:pointer;list-style:none}.mp-cloud-backup>summary::-webkit-details-marker{display:none}.mp-cloud-backup>summary:hover{background:#f7f8fa}.mp-cloud-backup-icon{width:48px;height:48px;border-radius:8px;background:#e4eef6;color:#176899;display:flex;align-items:center;justify-content:center}.mp-cloud-backup-icon .dashicons{font-size:24px;width:24px;height:24px}.mp-cloud-backup[open] .mp-cloud-expand{transform:rotate(180deg)}.mp-cloud-backup-detail{padding:14px 18px 18px 76px;background:#f8f9fb;border-top:1px solid #e5e8ed}.mp-cloud-backup-detail dl{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;margin:0}.mp-cloud-backup-detail dl>div{min-width:0;background:#fff;border:1px solid #e2e5ea;border-radius:6px;padding:9px}.mp-cloud-backup-detail dt{font-size:10px;text-transform:uppercase;font-weight:700;color:#747d88}.mp-cloud-backup-detail dd{margin:4px 0 0;font-size:12px;overflow-wrap:anywhere}.mp-cloud-backup-categories{display:flex;align-items:center;gap:10px;margin-top:12px}.mp-cloud-backup-categories>span{display:flex;gap:5px;flex-wrap:wrap}
                    #mp-cloud-player{position:fixed!important;z-index:100002;right:34px;bottom:24px;width:min(680px,calc(100vw - 68px));margin:0!important;border:1px solid #3c4148;border-radius:8px!important;box-shadow:0 18px 48px rgba(0,0,0,.34)}body.mp-cloud-modal-open{overflow:hidden}
                    @media(max-width:900px){.mp-cl-stats{grid-template-columns:repeat(2,minmax(0,1fr))}.mp-cl-user-summary{grid-template-columns:auto minmax(150px,1fr) auto auto}.mp-cl-user-facts{grid-column:2/4}.mp-cl-last{display:none}.mp-cloud-user-stats{grid-template-columns:repeat(2,minmax(0,1fr))}.mp-cloud-filters{grid-template-columns:1fr 1fr}.mp-cloud-search{grid-column:1/-1}.mp-cloud-track>summary{grid-template-columns:52px minmax(160px,1fr) auto 20px}.mp-cloud-track-size,.mp-cloud-track-date{display:none}.mp-cloud-track-detail{padding-left:14px}.mp-cloud-track-detail>dl{grid-template-columns:repeat(2,minmax(0,1fr))}.mp-cloud-backup>summary{grid-template-columns:52px minmax(180px,1fr) auto 20px}.mp-cloud-backup>summary>.mp-cloud-track-size{display:flex}.mp-cloud-backup-detail{padding-left:14px}.mp-cloud-backup-detail dl{grid-template-columns:repeat(2,minmax(0,1fr))}}
                    @media(max-width:600px){.mp-cloud-modal{padding:0}.mp-cloud-dialog{width:100vw;height:100vh;border:0;border-radius:0}.mp-cloud-dialog-head{padding:12px}.mp-cloud-dialog-body{padding:12px 12px 110px}.mp-cloud-filters{grid-template-columns:1fr}.mp-cloud-search{grid-column:auto}.mp-cloud-track>summary{grid-template-columns:48px minmax(0,1fr) 20px;padding:9px}.mp-cloud-cover{width:48px;height:48px}.mp-cloud-track-actions{grid-column:2/3}.mp-cloud-track-detail>dl{grid-template-columns:1fr}.mp-cl-stats{grid-template-columns:1fr}.mp-cl-user-summary{grid-template-columns:auto 1fr auto}.mp-cl-user-facts{grid-column:2/4}.mp-cl-user-health,.mp-cl-open{display:none}.mp-cloud-tabs button{flex:1;justify-content:center;padding:7px;font-size:12px}.mp-cloud-backup-head{align-items:flex-start;flex-direction:column}.mp-cloud-backup>summary{grid-template-columns:44px minmax(0,1fr) 20px;padding:9px}.mp-cloud-backup-icon{width:42px;height:42px}.mp-cloud-backup>summary>.mp-cloud-track-size{display:none}.mp-cloud-backup>summary>.mp-cloud-track-actions{grid-column:2/3}.mp-cloud-backup-detail dl{grid-template-columns:1fr}.mp-cloud-backup-categories{align-items:flex-start;flex-direction:column}#mp-cloud-player{right:8px;bottom:8px;width:calc(100vw - 16px)}}
                </style>
            <?php endif; // !$cloud_list_error ?>
            <?php endif; // mp_s3_enabled ?>
        </div>
        </div><!-- /tab-nuvem -->

        <?php if ( ! defined( 'RMBZ_SPONSORED_UNIFIED' ) ) : ?>
        <div class="mp-tab" id="tab-parcerias" hidden>
        <?php
            $sp_on      = mp_sponsored_enabled();
            $sp_min     = (float) get_option( 'mp_sponsored_min_payout', 5 );
            $sp_cap     = (int) get_option( 'mp_sponsored_daily_cap_min', 30 );
            $sp_minvol  = (int) get_option( 'mp_sponsored_min_volume', 20 );
            $sp_volpz   = (int) get_option( 'mp_sponsored_vol_pause_min', 10 );
            $sp_carearn = (string) get_option( 'mp_sponsored_car_earn', 'flag' );
            $sp_methods = (array) get_option( 'mp_sponsored_methods', [ 'M-Pesa', 'Emola' ] );
            $sp_list    = $wpdb->get_results( "SELECT * FROM {$sp_tracks} ORDER BY id DESC LIMIT 200" );
            $sp_pending = $wpdb->get_results(
                "SELECT p.*, a.email FROM {$sp_pay} p LEFT JOIN {$wpdb->prefix}mp_accounts a ON a.id = p.account_id ORDER BY (p.status='requested') DESC, p.id DESC LIMIT 100" );
            $sp_total_paid = (float) $wpdb->get_var( "SELECT COALESCE(SUM(spent_usd),0) FROM {$sp_tracks}" );
            $sp_active_count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$sp_tracks} WHERE active = 1 AND (budget_usd = 0 OR spent_usd < budget_usd)" );
            $sp_valid_sessions = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$sp_sess} WHERE credited_sec > 0" );
            $sp_invalid_sessions = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$sp_sess} WHERE status = 'fraud' OR bad_beats > 0" );
            $sp_pending_count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$sp_pay} WHERE status = 'requested'" );
        ?>

        <section class="mp-sp-overview">
            <div class="mp-sp-overview-head">
                <div class="mp-sp-title-block">
                    <span class="mp-sp-title-icon"><span class="dashicons dashicons-megaphone"></span></span>
                    <div><div class="mp-sp-kicker">Parcerias</div><h2>Programa de Músicas Patrocinadas</h2>
                    <p>Campanhas com escuta validada e remuneração transparente.</p></div>
                </div>
                <button type="button" class="mp-btn mp-btn--gold" onclick="mpCfgModal(true)"><span class="dashicons dashicons-admin-generic"></span> Configurar programa</button>
            </div>
            <div class="mp-sp-metrics">
                <div class="mp-sp-metric"><span>Distribuído</span><strong>$<?php echo number_format( $sp_total_paid, 2 ); ?></strong></div>
                <div class="mp-sp-metric"><span>Faixas ativas</span><strong><?php echo (int) $sp_active_count; ?></strong></div>
                <div class="mp-sp-metric mp-sp-metric--valid"><span>Sessões válidas</span><strong><?php echo (int) $sp_valid_sessions; ?></strong></div>
                <div class="mp-sp-metric <?php echo $sp_invalid_sessions ? 'mp-sp-metric--alert' : ''; ?>"><span>Alertas</span><strong><?php echo (int) $sp_invalid_sessions; ?></strong></div>
                <div class="mp-sp-metric"><span>Pagamentos pendentes</span><strong><?php echo (int) $sp_pending_count; ?></strong></div>
            </div>
            <div class="mp-cfg-summary">
                <span class="mp-pill <?php echo $sp_on ? 'mp-pill--active' : 'mp-pill--muted'; ?>"><?php echo $sp_on ? 'Programa ativo' : 'Desligado'; ?></span>
                <span class="mp-cfg-chip">Pagamento mín. <b>$<?php echo esc_html( $sp_min ); ?></b></span>
                <span class="mp-cfg-chip">Limite diário <b><?php echo (int) $sp_cap; ?> min</b></span>
                <span class="mp-cfg-chip">Volume mín. <b><?php echo $sp_minvol > 0 ? (int) $sp_minvol . '%' : 'desligado'; ?></b><?php if ( $sp_minvol > 0 ) : ?> · pausa <b><?php echo (int) $sp_volpz; ?> min</b><?php endif; ?></span>
                <span class="mp-cfg-chip">Pagamentos: <b><?php echo esc_html( $sp_methods ? implode( ', ', $sp_methods ) : 'nenhum' ); ?></b></span>
            </div>
            <div class="mp-sp-integrity"><span class="dashicons dashicons-shield"></span><div><strong>Proteção de reproduções ativa</strong><span>Posição real, sequência de batimentos, duração, orçamento e limite diário são validados no servidor.</span></div></div>
        </section>

        <?php // ===== Modal de configuração do programa ===== ?>
        <div class="mp-umodal" id="mp-cfg-modal" onclick="if(event.target===this)mpCfgModal(false)">
            <div class="mp-umodal-card">
                <div class="mp-cfg-head">
                    <span class="mp-cfg-ic"><span class="dashicons dashicons-shield"></span></span>
                    <div style="flex:1;min-width:0">
                        <div style="font-weight:800;font-size:17px">Configurar programa</div>
                        <div style="color:#5f6368;font-size:13px">Regras de ganho, anti-fraude e pagamentos</div>
                    </div>
                    <button type="button" class="mp-btn mp-btn--outline mp-cfg-close" onclick="mpCfgModal(false)" aria-label="Fechar"><span class="dashicons dashicons-no-alt"></span></button>
                </div>
                <form method="post">
                    <?php wp_nonce_field( 'mp_sponsored' ); ?>
                    <label style="display:flex;align-items:center;gap:10px;margin:6px 0 16px">
                        <input type="checkbox" name="mp_sponsored_on" <?php checked( $sp_on ); ?>>
                        <strong>Programa ativo</strong> <span class="mp-hint">(também tens de ativar o add-on «Músicas Patrocinadas» na aba Add-ons)</span>
                    </label>

                    <h4 class="mp-cfg-title"><span class="dashicons dashicons-money-alt"></span> Pagamentos e limites</h4>
                    <div style="display:flex;gap:16px;flex-wrap:wrap">
                        <div class="mp-field"><label>Saldo mínimo para pagamento ($)</label>
                            <input type="number" step="0.5" min="0" name="mp_sponsored_min_payout" value="<?php echo esc_attr( $sp_min ); ?>"></div>
                        <div class="mp-field"><label>Limite diário por faixa (min/ouvinte)</label>
                            <input type="number" min="1" name="mp_sponsored_daily_cap_min" value="<?php echo esc_attr( $sp_cap ); ?>">
                            <span class="mp-hint">Anti-fraude: máximo que um ouvinte ganha por faixa/dia.</span></div>
                    </div>

                    <h4 class="mp-cfg-title"><span class="dashicons dashicons-controls-volumeon"></span> Regra de volume</h4>
                    <div style="display:flex;gap:16px;flex-wrap:wrap">
                        <div class="mp-field"><label>Volume mínimo para ganhar (%)</label>
                            <input type="number" min="0" max="100" name="mp_sponsored_min_volume" value="<?php echo esc_attr( $sp_minvol ); ?>">
                            <span class="mp-hint">Abaixo desta % o ouvinte não ganha. <strong>0 = desliga a regra.</strong></span></div>
                        <div class="mp-field"><label>Pausa por volume baixo (minutos)</label>
                            <input type="number" min="1" max="120" name="mp_sponsored_vol_pause_min" value="<?php echo esc_attr( $sp_volpz ); ?>">
                            <span class="mp-hint">Quanto tempo os ganhos ficam pausados após volume baixo.</span></div>
                        <div class="mp-field"><label>Carro / Bluetooth (volume não verificável)</label>
                            <select name="mp_sponsored_car_earn">
                                <option value="allow" <?php selected( $sp_carearn, 'allow' ); ?>>Permitir ganhar (sem regra de volume)</option>
                                <option value="flag" <?php selected( $sp_carearn, 'flag' ); ?>>Permitir mas sinalizar à IA (recomendado)</option>
                                <option value="block" <?php selected( $sp_carearn, 'block' ); ?>>Bloquear ganho no carro/Bluetooth</option>
                            </select>
                            <span class="mp-hint">Ligado ao carro/BT o telemóvel mostra 100% mas o carro pode estar em mute — o volume não é fiável.</span></div>
                    </div>

                    <h4 class="mp-cfg-title"><span class="dashicons dashicons-bank"></span> Métodos de pagamento disponíveis</h4>
                    <div style="display:flex;gap:18px;flex-wrap:wrap;margin-top:2px">
                        <?php foreach ( [ 'PayPal', 'M-Pesa', 'Emola' ] as $m ) : ?>
                            <label style="display:flex;align-items:center;gap:8px">
                                <input type="checkbox" name="mp_sponsored_methods[]" value="<?php echo esc_attr( $m ); ?>" <?php checked( in_array( $m, $sp_methods, true ) ); ?>>
                                <?php echo esc_html( $m ); ?>
                            </label>
                        <?php endforeach; ?>
                    </div>
                    <span class="mp-hint">Só os marcados aparecem ao ouvinte quando pede o pagamento. Desmarca os indisponíveis.</span>

                    <div class="mp-cfg-actions">
                        <button type="button" class="mp-btn mp-btn--outline" onclick="mpCfgModal(false)">Cancelar</button>
                        <button class="mp-btn mp-btn--gold" name="mp_sponsored_settings" value="1">Guardar programa</button>
                    </div>
                </form>
            </div>
        </div>
        <style>
            .mp-cfg-summary{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-top:16px}
            .mp-cfg-chip{background:#f1f4f2;border-radius:8px;padding:7px 12px;font-size:12.5px;color:#3c4942}
            .mp-cfg-chip b{color:#1b2022}
            /* modal de configuração (autossuficiente) */
            #mp-cfg-modal{position:fixed;inset:0;background:rgba(15,17,19,.6);z-index:100000;display:none;align-items:center;justify-content:center;padding:20px}
            #mp-cfg-modal .mp-umodal-card{background:#fff;border-radius:8px;max-width:720px;width:100%;max-height:90vh;overflow:auto;padding:24px;box-shadow:0 24px 64px rgba(0,0,0,.28)}
            .mp-cfg-head{display:flex;align-items:center;gap:14px;margin-bottom:8px}
            .mp-cfg-ic{width:48px;height:48px;border-radius:8px;display:flex;align-items:center;justify-content:center;background:#d9efe2;color:#146c43;flex-shrink:0}
            .mp-cfg-ic .dashicons{font-size:24px;width:24px;height:24px}
            .mp-cfg-title{display:flex;align-items:center;gap:8px;margin:24px 0 10px;font-size:14px;color:#24352c}
            .mp-cfg-title .dashicons{color:#146c43;font-size:18px;width:18px;height:18px}
            .mp-cfg-close{width:40px;height:40px;padding:0}
            .mp-cfg-actions{margin-top:22px;padding-top:16px;border-top:1px solid #eceef1;display:flex;gap:10px;justify-content:flex-end}
        </style>
        <script>
            function mpCfgModal(show){
                var el = document.getElementById('mp-cfg-modal');
                if (el) el.style.display = show ? 'flex' : 'none';
            }
        </script>

        <div class="mp-card mp-card--wide">
            <div class="mp-card-head"><div class="mp-ic"><span class="dashicons dashicons-plus"></span></div>
                <div><h2>Adicionar faixa patrocinada</h2><div class="mp-card-sub">Escolhe da biblioteca do WordPress — a duração é detetada do áudio</div></div></div>
            <form method="post" id="mp-sp-form">
                <?php wp_nonce_field( 'mp_sponsored' ); ?>
                <input type="hidden" name="sp_id" value="0">
                <div class="mp-sp-split">
                    <!-- ── Formulário ── -->
                    <div class="mp-sp-formcol">
                        <div class="mp-sp-grid">
                            <div class="mp-field"><label>Título *</label><input type="text" id="sp_title" name="sp_title" required></div>
                            <div class="mp-field"><label>Artista / Marca</label><input type="text" id="sp_artist" name="sp_artist"></div>
                        </div>

                        <div class="mp-field">
                            <label>Áudio *</label>
                            <div class="mp-sp-picker">
                                <input type="url" id="sp_audio" name="sp_audio" placeholder="https://…/promo.mp3" required>
                                <button type="button" class="mp-btn mp-btn--outline" id="mp-pick-audio"><span class="dashicons dashicons-upload"></span> Biblioteca</button>
                            </div>
                            <span class="mp-hint" id="sp_audio_status">Escolhe da biblioteca ou cola um URL HTTPS. A duração é lida automaticamente.</span>
                        </div>

                        <div class="mp-field">
                            <label>Capa</label>
                            <div class="mp-sp-picker">
                                <input type="url" id="sp_cover" name="sp_cover" placeholder="https://…/capa.jpg">
                                <button type="button" class="mp-btn mp-btn--outline" id="mp-pick-cover"><span class="dashicons dashicons-format-image"></span> Biblioteca</button>
                            </div>
                        </div>

                        <div class="mp-sp-grid">
                            <div class="mp-field"><label>Países elegíveis (ISO-2)</label>
                                <input type="text" id="sp_countries" name="sp_countries" placeholder="MZ,AO,PT — vazio = todos"></div>
                            <div class="mp-field"><label>Duração (segundos)</label>
                                <input type="number" min="0" id="sp_duration" name="sp_duration" placeholder="detetada do áudio"></div>
                            <div class="mp-field"><label>Taxa por minuto ($)</label>
                                <input type="number" step="0.0001" min="0" id="sp_rate" name="sp_rate" placeholder="0.02"></div>
                            <div class="mp-field"><label>Orçamento total ($)</label>
                                <input type="number" step="1" min="0" id="sp_budget" name="sp_budget" placeholder="0 = ilimitado"></div>
                        </div>

                        <label style="display:flex;align-items:center;gap:8px;margin:10px 0">
                            <input type="checkbox" name="sp_active" checked> Ativa desde já</label>
                        <button class="mp-btn mp-btn--gold" name="mp_sponsored_track" value="1"><span class="dashicons dashicons-saved"></span> Adicionar ao programa</button>
                        <button type="button" class="mp-btn mp-btn--outline" id="mp-sp-cancel" style="display:none">Cancelar edição</button>
                    </div>

                    <!-- ── Pré-visualização (como fica no app) ── -->
                    <div class="mp-sp-preview">
                        <div class="mp-sp-phone">
                            <div class="mp-sp-phone-top"><span class="dashicons dashicons-arrow-left-alt2"></span><div>Músicas patrocinadas<small>Escuta validada</small></div></div>
                            <div class="mp-sp-phone-balance"><span>Saldo disponível</span><strong>$0.00</strong><small>Tempo confirmado pelo servidor</small></div>
                            <div class="mp-sp-phone-section">Faixas disponíveis</div>
                            <div class="mp-sp-row">
                                <div class="mp-sp-cover" id="pv_cover"><span class="dashicons dashicons-money-alt"></span></div>
                                <div class="mp-sp-meta">
                                    <div class="mp-sp-ttl" id="pv_title">Título da faixa</div>
                                    <div class="mp-sp-sub" id="pv_sub">Artista · $0.0000/min</div>
                                </div>
                                <div class="mp-sp-add"><span class="dashicons dashicons-plus-alt2"></span></div>
                                <div class="mp-sp-play"><span class="dashicons dashicons-controls-play"></span></div>
                            </div>
                            <div class="mp-sp-earn" id="pv_earn"><span class="dashicons dashicons-shield"></span> Escuta completa até <b>$0.0000</b></div>
                        </div>
                        <p class="mp-hint" style="text-align:center;margin-top:10px">Pré-visualização Material 3 no app.</p>
                    </div>
                </div>
            </form>
            <audio id="mp-sp-probe" preload="metadata" style="display:none"></audio>
        </div>

        <div class="mp-card mp-card--wide">
            <div class="mp-card-head"><div class="mp-ic"><span class="dashicons dashicons-format-audio"></span></div>
                <div><h2>Faixas do programa</h2><div class="mp-card-sub"><?php echo count( $sp_list ); ?> faixa(s)</div></div></div>
            <?php if ( empty( $sp_list ) ) : ?>
                <p class="mp-empty">Ainda não há faixas patrocinadas.</p>
            <?php else : ?>
            <div class="mp-table-wrap">
                <table class="mp-table">
                    <thead><tr><th>Faixa</th><th>Países</th><th>$/min</th><th>Orçamento</th><th>Gasto</th><th>Plays</th><th>Estado</th><th></th></tr></thead>
                    <tbody>
                    <?php foreach ( $sp_list as $t ) :
                        $budget = $t->budget_usd > 0 ? '$' . number_format( $t->budget_usd, 2 ) : '∞';
                        $full   = $t->budget_usd > 0 && $t->spent_usd >= $t->budget_usd;
                    ?>
                        <tr>
                            <td>
                                <div style="display:flex;align-items:center;gap:10px">
                                    <?php if ( $t->cover_url ) : ?><img src="<?php echo esc_url( $t->cover_url ); ?>" style="width:38px;height:38px;border-radius:8px;object-fit:cover" loading="lazy"><?php endif; ?>
                                    <div><div style="font-weight:600"><?php echo esc_html( $t->title ); ?></div>
                                    <div style="color:#5f6368;font-size:12px"><?php echo esc_html( $t->artist ?: '—' ); ?></div></div>
                                </div>
                            </td>
                            <td><?php echo esc_html( $t->countries ?: '🌍 Todos' ); ?></td>
                            <td>$<?php echo number_format( $t->rate_per_min, 4 ); ?></td>
                            <td><?php echo esc_html( $budget ); ?></td>
                            <td>$<?php echo number_format( $t->spent_usd, 2 ); ?></td>
                            <td><?php echo (int) $t->plays; ?></td>
                            <td><?php
                                if ( ! $t->active ) echo '<span class="mp-pill mp-pill--muted">Inativa</span>';
                                elseif ( $full ) echo '<span class="mp-pill mp-pill--blocked">Orçamento cheio</span>';
                                else echo '<span class="mp-pill mp-pill--active">Ativa</span>';
                            ?></td>
                            <td style="white-space:nowrap">
                                <button type="button" class="mp-btn mp-btn--outline mp-sp-edit"
                                    data-id="<?php echo (int) $t->id; ?>"
                                    data-title="<?php echo esc_attr( $t->title ); ?>"
                                    data-artist="<?php echo esc_attr( (string) $t->artist ); ?>"
                                    data-audio="<?php echo esc_attr( $t->audio_url ); ?>"
                                    data-cover="<?php echo esc_attr( (string) $t->cover_url ); ?>"
                                    data-countries="<?php echo esc_attr( (string) $t->countries ); ?>"
                                    data-duration="<?php echo (int) $t->duration_sec; ?>"
                                    data-rate="<?php echo esc_attr( $t->rate_per_min ); ?>"
                                    data-budget="<?php echo esc_attr( $t->budget_usd ); ?>"
                                    data-active="<?php echo (int) $t->active; ?>"><span class="dashicons dashicons-edit"></span> Editar</button>
                                <form method="post" onsubmit="return confirm('Remover esta faixa do programa?')" style="margin:0;display:inline">
                                    <?php wp_nonce_field( 'mp_sponsored' ); ?>
                                    <input type="hidden" name="sp_id" value="<?php echo (int) $t->id; ?>">
                                    <button class="mp-btn mp-btn--danger" name="mp_sponsored_delete" value="1"><span class="dashicons dashicons-trash"></span></button>
                                </form>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
            <?php endif; ?>
        </div>

        <div class="mp-card mp-card--wide">
            <div class="mp-card-head"><div class="mp-ic"><span class="dashicons dashicons-shield"></span></div>
                <div><h2>Anti-fraude</h2><div class="mp-card-sub">Contas sinalizadas por reprodução suspeita · a IA analisa o padrão</div></div></div>
            <?php
                global $wpdb;
                // Contas com bandeiras (option mp_sponsored_flags_<id>).
                $flagged = $wpdb->get_col( "SELECT REPLACE(option_name,'mp_sponsored_flags_','') FROM {$wpdb->options} WHERE option_name LIKE 'mp_sponsored_flags_%'" );
                $flagged = array_filter( array_map( 'intval', (array) $flagged ) );
            ?>
            <?php if ( empty( $flagged ) ) : ?>
                <p class="mp-empty"><span class="dashicons dashicons-shield"></span> Nenhuma conta sinalizada.</p>
            <?php else : ?>
            <div class="mp-table-wrap">
                <table class="mp-table">
                    <thead><tr><th>Conta</th><th>Score</th><th>Veredicto da IA</th><th></th></tr></thead>
                    <tbody>
                    <?php foreach ( $flagged as $uid ) :
                        $email   = $wpdb->get_var( $wpdb->prepare( "SELECT email FROM {$wpdb->prefix}mp_accounts WHERE id = %d", $uid ) );
                        $score   = (int) get_option( 'mp_sponsored_score_' . $uid, 0 );
                        $verdict = get_transient( 'mp_fraud_verdict_' . $uid );
                    ?>
                        <tr>
                            <td><?php echo esc_html( $email ?: ( 'Conta #' . $uid ) ); ?></td>
                            <td><span class="mp-pill <?php echo $score >= 3 ? 'mp-pill--blocked' : 'mp-pill--vip'; ?>"><?php echo (int) $score; ?> bandeira(s)</span></td>
                            <td style="max-width:340px">
                                <?php if ( $verdict ) : ?>
                                    <?php
                                        $vcls = ( stripos( $verdict, 'FRAUDE' ) === 0 ) ? 'color:#c0392b;font-weight:600'
                                              : ( ( stripos( $verdict, 'SUSPEITO' ) === 0 ) ? 'color:#8a6400;font-weight:600' : 'color:#1e8e3e;font-weight:600' );
                                    ?>
                                    <span style="<?php echo esc_attr( $vcls ); ?>"><?php echo esc_html( $verdict ); ?></span>
                                <?php else : ?>
                                    <span style="color:#8a919b">— (carrega em «Analisar com IA»)</span>
                                <?php endif; ?>
                            </td>
                            <td style="white-space:nowrap">
                                <form method="post" style="display:inline">
                                    <?php wp_nonce_field( 'mp_sponsored' ); ?>
                                    <input type="hidden" name="fraud_uid" value="<?php echo (int) $uid; ?>">
                                    <button class="mp-btn mp-btn--gold" name="mp_fraud_review" value="1"><span class="dashicons dashicons-search"></span> Analisar integridade</button>
                                    <button class="mp-btn mp-btn--outline" name="mp_fraud_clear" value="1" onclick="return confirm('Limpar as bandeiras desta conta?')">Limpar</button>
                                </form>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
            <?php endif; ?>
        </div>

        <div class="mp-card mp-card--wide">
            <div class="mp-card-head"><div class="mp-ic"><span class="dashicons dashicons-money"></span></div>
                <div><h2>Pedidos de pagamento</h2><div class="mp-card-sub">Saldo que os ouvintes querem levantar</div></div></div>
            <?php if ( empty( $sp_pending ) ) : ?>
                <p class="mp-empty">Sem pedidos de pagamento.</p>
            <?php else : ?>
            <div class="mp-table-wrap">
                <table class="mp-table">
                    <thead><tr><th>Ouvinte</th><th>Valor</th><th>Método</th><th>Detalhe</th><th>Análise de integridade</th><th>Estado</th><th></th></tr></thead>
                    <tbody>
                    <?php foreach ( $sp_pending as $p ) :
                        $ai = (string) $p->note;
                        $ai_style = ( stripos( $ai, 'FRAUDE' ) === 0 ) ? 'color:#c0392b;font-weight:600'
                                  : ( ( stripos( $ai, 'SUSPEITO' ) === 0 ) ? 'color:#8a6400;font-weight:600' : 'color:#1e8e3e;font-weight:600' );
                    ?>
                        <tr>
                            <td><?php echo esc_html( $p->email ?: ( 'Conta #' . $p->account_id ) ); ?>
                                <div style="color:#8a919b;font-size:11px"><?php echo esc_html( gmdate( 'd/m/Y', strtotime( $p->created_at ) ) ); ?></div></td>
                            <td><strong>$<?php echo number_format( $p->amount_usd, 2 ); ?></strong></td>
                            <td><?php echo esc_html( $p->method ?: '—' ); ?></td>
                            <td style="max-width:160px;word-break:break-all"><?php echo esc_html( $p->detail ); ?></td>
                            <td style="max-width:320px">
                                <?php if ( $ai !== '' ) : ?>
                                    <span style="<?php echo esc_attr( $ai_style ); ?>"><?php echo esc_html( $ai ); ?></span>
                                <?php else : ?>
                                    <form method="post" style="margin:0">
                                        <?php wp_nonce_field( 'mp_sponsored' ); ?>
                                        <input type="hidden" name="payout_id" value="<?php echo (int) $p->id; ?>">
                                        <button class="mp-btn mp-btn--outline" name="mp_payout_analyze" value="1"><span class="dashicons dashicons-search"></span> Analisar</button>
                                    </form>
                                <?php endif; ?>
                            </td>
                            <td><?php
                                $cls = $p->status === 'paid' ? 'mp-pill--active' : ( $p->status === 'rejected' ? 'mp-pill--blocked' : 'mp-pill--vip' );
                                echo '<span class="mp-pill ' . $cls . '">' . esc_html( ucfirst( $p->status ) ) . '</span>';
                            ?></td>
                            <td style="white-space:nowrap">
                                <?php if ( $p->status === 'requested' ) :
                                    $vstate = (string) get_option( 'mp_sponsored_verify_' . (int) $p->account_id, '' );
                                ?>
                                <form method="post" style="display:inline">
                                    <?php wp_nonce_field( 'mp_sponsored' ); ?>
                                    <input type="hidden" name="payout_id" value="<?php echo (int) $p->id; ?>">
                                    <input type="hidden" name="fraud_uid" value="<?php echo (int) $p->account_id; ?>">
                                    <button class="mp-btn mp-btn--gold" name="mp_payout_action" value="paid">Pago</button>
                                    <button class="mp-btn mp-btn--outline" name="mp_payout_action" value="reject">Rejeitar</button>
                                    <?php if ( $vstate === 'requested' ) : ?>
                                        <span class="mp-pill mp-pill--vip">A aguardar dispositivo</span>
                                    <?php else : ?>
                                        <button class="mp-btn mp-btn--outline" name="mp_verify_device" value="1"><span class="dashicons dashicons-smartphone"></span> Verificar dispositivo</button>
                                    <?php endif; ?>
                                    <button class="mp-btn mp-btn--danger" name="mp_clawback" value="1"
                                        onclick="return confirm('Devolver TODOS os ganhos desta conta? O saldo fica a zero e o pedido é rejeitado.')"><span class="dashicons dashicons-undo"></span> Devolver ganhos</button>
                                </form>
                                <?php endif; ?>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
            <?php endif; ?>
        </div>
        </div><!-- /tab-parcerias -->
        <?php endif; ?>

        <?php mp_admin_scripts(); ?>
    </div>
    <?php
}

/** Tabs + modais (JS sem dependências). */
function mp_admin_scripts() {
    ?>
    <script>
    (function(){
        var root = document.querySelector('.mp-admin');
        if ( ! root ) return;

        function showTab( name ) {
            root.querySelectorAll('.mp-tab').forEach(function(p){ p.hidden = ( p.id !== 'tab-' + name ); });
            root.querySelectorAll('.mp-tab-btn').forEach(function(b){ b.classList.toggle('is-active', b.dataset.tab === name); });
        }
        root.querySelectorAll('.mp-tab-btn[data-tab]').forEach(function(btn){
            btn.addEventListener('click', function(){
                showTab( btn.dataset.tab );
                history.replaceState(null, '', '#' + btn.dataset.tab);
            });
        });
        var initial = ( location.hash || '' ).replace('#','');
        if ( initial && root.querySelector('#tab-' + initial) ) { showTab( initial ); }

        // Modais: foco preso no diálogo e Cancelar restaura os valores anteriores.
        function snapshotModal( modal ) {
            modal._mpSnapshot = Array.prototype.map.call(
                modal.querySelectorAll('input,select,textarea'),
                function(el){ return { el:el, value:el.value, checked:el.checked }; }
            );
        }
        function restoreModal( modal ) {
            ( modal._mpSnapshot || [] ).forEach(function(item){
                item.el.value = item.value;
                if ( item.el.type === 'checkbox' || item.el.type === 'radio' ) item.el.checked = item.checked;
            });
        }
        function closeModal( modal, restore ) {
            if ( restore !== false ) restoreModal( modal );
            modal.classList.remove('is-open');
            modal.setAttribute('aria-hidden', 'true');
            if ( ! root.querySelector('.mp-modal.is-open') ) document.documentElement.classList.remove('mp-modal-open');
            if ( modal._mpTrigger ) modal._mpTrigger.focus();
        }
        function openModal( id, trigger ) {
            var modal = document.getElementById(id);
            if ( ! modal ) return;
            root.querySelectorAll('.mp-modal.is-open').forEach(function(open){ closeModal(open, true); });
            snapshotModal(modal);
            modal._mpTrigger = trigger || document.activeElement;
            modal.classList.add('is-open');
            modal.setAttribute('aria-hidden', 'false');
            document.documentElement.classList.add('mp-modal-open');
            window.setTimeout(function(){
                var focus = modal.querySelector('input:not([disabled]),select:not([disabled]),textarea:not([disabled]),button:not([disabled])');
                if ( focus ) focus.focus();
            }, 0);
        }
        root.querySelectorAll('[data-modal]').forEach(function(btn){
            btn.addEventListener('click', function(){ openModal( btn.dataset.modal, btn ); });
        });
        root.querySelectorAll('.mp-modal').forEach(function(modal){
            modal.setAttribute('aria-hidden', modal.classList.contains('is-open') ? 'false' : 'true');
            modal.addEventListener('click', function(e){
                if ( e.target === modal || ( e.target.closest && e.target.closest('[data-close]') ) ) closeModal( modal, true );
            });
        });
        document.addEventListener('keydown', function(e){
            var modal = root.querySelector('.mp-modal.is-open');
            if ( ! modal ) return;
            if ( e.key === 'Escape' ) {
                closeModal(modal, true);
                return;
            }
            if ( e.key === 'Tab' ) {
                var focusable = Array.prototype.filter.call(
                    modal.querySelectorAll('button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),a[href]'),
                    function(el){ return el.offsetParent !== null; }
                );
                if ( ! focusable.length ) return;
                var first = focusable[0];
                var last = focusable[focusable.length - 1];
                if ( e.shiftKey && document.activeElement === first ) { e.preventDefault(); last.focus(); }
                else if ( ! e.shiftKey && document.activeElement === last ) { e.preventDefault(); first.focus(); }
            }
        });

        // ===== Faixa patrocinada: explorador WP + duração automática + preview =====
        var form = document.getElementById('mp-sp-form');
        if ( form ) {
            var $ = function(id){ return document.getElementById(id); };
            var probe = $('mp-sp-probe');

            function fmtRate(){ var r = parseFloat($('sp_rate').value) || 0; return '$' + r.toFixed(4); }
            function updatePreview(){
                $('pv_title').textContent = $('sp_title').value || 'Título da faixa';
                var artist = $('sp_artist').value || 'Patrocinado';
                $('pv_sub').textContent = artist + ' · ' + fmtRate() + '/min';
                var cover = $('sp_cover').value;
                var pc = $('pv_cover');
                if ( cover ) { pc.style.backgroundImage = 'url(' + cover + ')'; pc.classList.add('has-img'); }
                else { pc.style.backgroundImage = ''; pc.classList.remove('has-img'); }
                var dur = parseInt($('sp_duration').value, 10) || 0;
                var rate = parseFloat($('sp_rate').value) || 0;
                var earn = ( dur / 60 ) * rate;
                $('pv_earn').innerHTML = dur > 0
                    ? '<span class="dashicons dashicons-shield"></span> Escuta completa (' + Math.round(dur/60*10)/10 + ' min) até <b>$' + earn.toFixed(4) + '</b>'
                    : '<span class="dashicons dashicons-shield"></span> Escuta completa até <b>$0.0000</b>';
            }
            ['sp_title','sp_artist','sp_cover','sp_duration','sp_rate'].forEach(function(id){
                $(id).addEventListener('input', updatePreview);
            });

            // Deteção da duração a partir do próprio ficheiro de áudio.
            function detectDuration(url){
                if ( ! url ) return;
                $('sp_audio_status').textContent = 'A ler a duração do áudio…';
                probe.src = url;
                probe.onloadedmetadata = function(){
                    if ( isFinite(probe.duration) && probe.duration > 0 ) {
                        $('sp_duration').value = Math.round(probe.duration);
                        $('sp_audio_status').textContent = '✓ Duração detetada: ' + Math.floor(probe.duration/60) + ':' + ('0'+Math.round(probe.duration%60)).slice(-2);
                        updatePreview();
                    } else {
                        $('sp_audio_status').textContent = 'Não consegui ler a duração — preenche à mão.';
                    }
                };
                probe.onerror = function(){ $('sp_audio_status').textContent = 'Não consegui abrir o áudio para ler a duração.'; };
            }
            $('sp_audio').addEventListener('change', function(){ detectDuration(this.value); });

            // Explorador da biblioteca de média do WordPress.
            function pick(type, onPick){
                if ( typeof wp === 'undefined' || ! wp.media ) { alert('O selecionador de média do WordPress não carregou.'); return; }
                var frame = wp.media({ title: 'Escolher ' + type, library: { type: type }, multiple: false, button: { text: 'Usar' } });
                frame.on('select', function(){
                    var a = frame.state().get('selection').first().toJSON();
                    onPick(a);
                });
                frame.open();
            }
            $('mp-pick-audio').addEventListener('click', function(){
                pick('audio', function(a){
                    $('sp_audio').value = a.url;
                    if ( ! $('sp_title').value && a.title ) $('sp_title').value = a.title;
                    // WP às vezes já traz a duração nos metadados; senão, lemos do ficheiro.
                    var wpLen = a.fileLength || (a.meta && a.meta.length_formatted) || '';
                    if ( a.meta && a.meta.length ) { $('sp_duration').value = Math.round(a.meta.length); }
                    detectDuration(a.url);
                    updatePreview();
                });
            });
            $('mp-pick-cover').addEventListener('click', function(){
                pick('image', function(a){
                    $('sp_cover').value = ( a.sizes && a.sizes.medium ) ? a.sizes.medium.url : a.url;
                    updatePreview();
                });
            });

            // ── Editar faixa já publicada ──
            var submitBtn = form.querySelector('button[name="mp_sponsored_track"]');
            var cancelBtn = $('mp-sp-cancel');
            var heading   = form.closest('.mp-card').querySelector('.mp-card-head h2');
            function resetForm(){
                form.querySelector('input[name="sp_id"]').value = '0';
                ['sp_title','sp_artist','sp_audio','sp_cover','sp_countries','sp_duration','sp_rate','sp_budget'].forEach(function(id){ $(id).value = ''; });
                form.querySelector('input[name="sp_active"]').checked = true;
                heading.textContent = 'Adicionar faixa patrocinada';
                submitBtn.innerHTML = '<span class="dashicons dashicons-saved"></span> Adicionar ao programa';
                cancelBtn.style.display = 'none';
                $('sp_audio_status').textContent = 'Escolhe da biblioteca ou cola um URL HTTPS. A duração é lida automaticamente.';
                updatePreview();
            }
            cancelBtn.addEventListener('click', resetForm);
            document.querySelectorAll('.mp-sp-edit').forEach(function(btn){
                btn.addEventListener('click', function(){
                    var d = btn.dataset;
                    form.querySelector('input[name="sp_id"]').value = d.id;
                    $('sp_title').value = d.title || '';
                    $('sp_artist').value = d.artist || '';
                    $('sp_audio').value = d.audio || '';
                    $('sp_cover').value = d.cover || '';
                    $('sp_countries').value = d.countries || '';
                    $('sp_duration').value = d.duration || '';
                    $('sp_rate').value = d.rate || '';
                    $('sp_budget').value = d.budget || '';
                    form.querySelector('input[name="sp_active"]').checked = ( d.active === '1' );
                    heading.textContent = 'Editar «' + (d.title || 'faixa') + '»';
                    submitBtn.innerHTML = '<span class="dashicons dashicons-saved"></span> Guardar alterações';
                    cancelBtn.style.display = '';
                    updatePreview();
                    form.scrollIntoView({ behavior:'smooth', block:'start' });
                });
            });

            updatePreview();
        }
    })();
    </script>
    <?php
}

/** Estilos da página (linguagem visual «Projetos & Videoclipes»). */
function mp_admin_styles() {
    ?>
    <style>
    .mp-admin { margin:10px -20px 0 -20px; padding:24px 28px 70px; background:#f4f6f8;
        font-family:"Roboto",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif; color:#18211d; min-height:calc(100vh - 32px); }
    .mp-admin *, .mp-admin *::before, .mp-admin *::after { box-sizing:border-box; }
    .mp-admin h1, .mp-admin h2 { margin:0; padding:0; }
    .mp-hero, .mp-stats, .mp-tabs, .mp-tab { width:100%; max-width:1680px; margin-left:auto; margin-right:auto; }

    .mp-hero { display:flex; justify-content:space-between; align-items:center; gap:20px; flex-wrap:wrap; margin-bottom:22px; }
    .mp-hero-left { display:flex; align-items:center; gap:16px; }
    .mp-hero-icon { width:56px; height:56px; border-radius:16px; background:linear-gradient(135deg,#1a1a1f,#3a3a45);
        color:#f0b90b; display:flex; align-items:center; justify-content:center; box-shadow:0 6px 16px rgba(0,0,0,.14); }
    .mp-hero-icon .dashicons { font-size:30px; width:30px; height:30px; }
    .mp-hero h1 { font-size:26px; font-weight:800; letter-spacing:0; color:#1a1a1f; }
    .mp-sub { margin:4px 0 0; color:#5f6368; font-size:14px; }
    .mp-endpoint { background:#fff; border:1px solid #dde2e0; border-radius:8px; padding:10px 14px; max-width:100%; }
    .mp-endpoint-label { display:block; font-size:11px; text-transform:uppercase; letter-spacing:0; color:#5f6368; font-weight:700; margin-bottom:3px; }
    .mp-endpoint code { background:transparent; color:#1a1a1f; font-size:12px; padding:0; word-break:break-all; }

    .mp-stats { display:grid; grid-template-columns:repeat(auto-fill,minmax(180px,1fr)); gap:14px; margin-bottom:22px; }
    .mp-stat { background:#fff; border:1px solid #dde2e0; border-radius:8px; padding:18px; box-shadow:0 1px 2px rgba(18,38,28,.04); }
    .mp-stat-num { font-size:30px; font-weight:800; color:#1a1a1f; line-height:1; }
    .mp-stat-label { margin-top:6px; color:#5f6368; font-size:13px; font-weight:500; }
    .mp-stat--gold .mp-stat-num { color:#b8860b; }
    .mp-stat--alert { background:#fff7f7; border-color:#fecaca; }
    .mp-stat--alert .mp-stat-num { color:#dc2626; }

    .mp-section-label { display:flex; align-items:center; gap:7px; font-size:12px; font-weight:800; text-transform:uppercase;
        letter-spacing:0; color:#5f6368; margin:26px 2px 12px; }
    .mp-section-label .dashicons { font-size:16px; width:16px; height:16px; color:#9aa0a6; }

    .mp-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,360px),1fr)); gap:16px; align-items:start; }
    .mp-card { min-width:0; background:#fff; border:1px solid #dde2e0; border-radius:8px; padding:20px; display:flex; flex-direction:column; box-shadow:0 1px 2px rgba(18,38,28,.04); }
    .mp-card--wide { margin-top:18px; }
    .mp-card--muted { background:#fbfbfc; }
    .mp-steps { margin:0; padding-left:20px; color:#3c4043; font-size:13.5px; line-height:1.7; }
    .mp-steps li { margin-bottom:6px; }
    .mp-steps li::marker { color:#f0b90b; font-weight:700; }
    .mp-card-head { display:flex; align-items:center; gap:12px; margin-bottom:16px; }
    .mp-card-head .mp-ic { width:38px; height:38px; border-radius:8px; background:#eef2f0; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
    .mp-card-head .mp-ic .dashicons { color:#1a1a1f; font-size:19px; width:19px; height:19px; }
    .mp-card-head h2 { font-size:16px; font-weight:700; color:#1a1a1f; }
    .mp-card-head .mp-card-sub { font-size:12px; color:#5f6368; margin-top:1px; }

    .mp-field { margin-bottom:14px; }
    .mp-field:last-child { margin-bottom:0; }
    .mp-field > label { display:block; font-size:13px; font-weight:600; color:#1a1a1f; margin-bottom:6px; }
    .mp-admin input[type=text], .mp-admin input[type=url], .mp-admin input[type=number], .mp-admin textarea, .mp-admin select {
        width:100%; min-height:42px; padding:10px 12px; border:1px solid #cfd7d3; border-radius:8px; font-size:14px; line-height:1.4;
        background:#fbfcfc; color:#1a1a1f; outline:none; transition:.15s; font-family:inherit; box-shadow:none; }
    .mp-admin select { height:auto; }
    .mp-admin input:focus, .mp-admin textarea:focus, .mp-admin select:focus { border-color:#176b52; box-shadow:0 0 0 3px rgba(23,107,82,.12); background:#fff; }
    .mp-admin input[type=checkbox], .mp-admin input[type=radio] { accent-color:#176b52; }
    .mp-admin textarea { resize:vertical; min-height:56px; }
    .mp-hint { display:block; margin-top:5px; font-size:12px; color:#5f6368; }
    .mp-row2 { display:flex; gap:12px; flex-wrap:wrap; }
    .mp-row2 .mp-field { flex:1; min-width:110px; }
    .mp-check { display:flex; align-items:center; gap:10px; padding:8px 0; font-size:13.5px; font-weight:500; color:#1a1a1f; margin-bottom:8px; }
    .mp-check input { width:18px; height:18px; margin:0; }

    /* Definições: estrutura operacional Material 3 */
    #tab-definicoes { scroll-behavior:smooth; }
    .mp-settings-overview { display:flex; align-items:center; justify-content:space-between; gap:22px; padding:20px 22px;
        border:1px solid #d8e0dc; border-radius:8px 8px 0 0; background:#fff; }
    .mp-settings-title { display:flex; align-items:center; gap:14px; min-width:0; }
    .mp-settings-title > .dashicons { width:42px; height:42px; padding:10px; border-radius:8px; background:#dcefe7;
        color:#176b52; font-size:22px; flex:none; }
    .mp-settings-title h2 { color:#18211d; font-size:20px; line-height:1.2; font-weight:750; }
    .mp-settings-title p { margin:4px 0 0; color:#66716b; font-size:13px; }
    .mp-settings-statuses { display:flex; justify-content:flex-end; gap:8px; flex-wrap:wrap; }
    .mp-settings-status { display:inline-flex; align-items:center; gap:7px; min-height:30px; padding:6px 10px; border:1px solid #d8e0dc;
        border-radius:8px; background:#f5f7f6; color:#53605a; font-size:11.5px; font-weight:700; white-space:nowrap; }
    .mp-settings-status i { width:7px; height:7px; border-radius:50%; background:#8b9690; }
    .mp-settings-status.is-success { border-color:#b9ddce; background:#e7f5ee; color:#176b52; }
    .mp-settings-status.is-success i { background:#1a9a6c; }
    .mp-settings-status.is-info { border-color:#c9d9ee; background:#edf4fc; color:#315d8a; }
    .mp-settings-status.is-info i { background:#3f7dbd; }
    .mp-settings-status.is-danger { border-color:#efc5c0; background:#fff0ee; color:#a23b31; }
    .mp-settings-status.is-danger i { background:#c8483b; }
    .mp-settings-nav { position:sticky; top:32px; z-index:14; display:flex; align-items:center; gap:6px; padding:8px;
        border:1px solid #d8e0dc; border-top:0; border-radius:0 0 8px 8px; background:rgba(249,251,250,.96);
        box-shadow:0 5px 18px rgba(18,38,28,.06); backdrop-filter:blur(10px); }
    .mp-settings-nav a { display:inline-flex; align-items:center; gap:7px; min-height:36px; padding:8px 12px; border-radius:8px;
        color:#4c5953; font-size:12.5px; font-weight:700; text-decoration:none; }
    .mp-settings-nav a:hover, .mp-settings-nav a:focus { background:#e4f1eb; color:#176b52; box-shadow:none; outline:none; }
    .mp-settings-nav .dashicons { width:16px; height:16px; font-size:16px; }
    .mp-section-heading { scroll-margin-top:92px; display:flex; align-items:center; justify-content:space-between; gap:18px;
        margin:30px 0 12px; }
    .mp-section-heading > div { display:flex; align-items:center; gap:11px; min-width:0; }
    .mp-section-heading > div > .dashicons { width:34px; height:34px; padding:8px; border-radius:8px; background:#e9eeeb;
        color:#435048; font-size:18px; flex:none; }
    .mp-section-heading h2 { color:#18211d; font-size:17px; line-height:1.2; font-weight:750; }
    .mp-section-heading p { margin:2px 0 0; color:#748078; font-size:12px; }
    .mp-section-count { flex:none; padding:5px 9px; border-radius:8px; background:#e9eeeb; color:#526058; font-size:11px; font-weight:750; }
    .mp-section-heading--inside { grid-column:1 / -1; width:100%; margin:10px 0 -2px; padding-top:20px; border-top:1px solid #d8e0dc; }

    .mp-grid--application { grid-template-columns:repeat(5,minmax(0,1fr)); }
    .mp-grid--vip { grid-template-columns:repeat(12,minmax(0,1fr)); }
    .mp-card--packages { grid-column:span 7; }
    .mp-card--vip-flow { grid-column:span 5; }
    .mp-card--cloud { grid-column:1 / -1; display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); column-gap:18px; align-content:start; }
    .mp-card--cloud > .mp-card-head, .mp-card--cloud > .mp-check, .mp-card--cloud > button, .mp-card--cloud > .mp-hint { grid-column:1 / -1; }
    .mp-card-section-title { display:flex; align-items:center; gap:10px; margin:8px 0 14px; padding-top:16px; border-top:1px solid #e2e7e4; }
    .mp-card-section-title > .dashicons { width:32px; height:32px; padding:7px; border-radius:8px; background:#fff1c7; color:#8a6500; font-size:18px; }
    .mp-card-section-title strong, .mp-card-section-title small { display:block; }
    .mp-card-section-title strong { color:#202922; font-size:13.5px; }
    .mp-card-section-title small { margin-top:2px; color:#758078; font-size:11.5px; }
    .mp-settings-subsection { grid-column:1 / -1; margin-top:2px; padding:15px 0 4px; border-top:1px solid #e2e7e4; }
    .mp-settings-subsection > label:first-child { display:block; margin-bottom:5px; color:#202922; font-size:13px; font-weight:700; }
    .mp-settings-subsection .mp-check { margin:0; }

    .mp-settings-module { width:100%; min-width:0; min-height:190px; padding:18px; border:1px solid #d8e0dc; border-radius:8px;
        background:#fff; color:#18211d; display:flex; flex-direction:column; align-items:stretch; text-align:left; cursor:pointer;
        font-family:inherit; box-shadow:0 1px 2px rgba(18,38,28,.04); transition:border-color .16s,box-shadow .16s,transform .16s; }
    .mp-settings-module:hover { border-color:#92b9aa; box-shadow:0 8px 24px rgba(18,38,28,.09); transform:translateY(-2px); }
    .mp-settings-module:focus-visible { outline:3px solid rgba(23,107,82,.2); outline-offset:2px; border-color:#176b52; }
    .mp-settings-module-head { display:flex; align-items:center; gap:11px; min-width:0; }
    .mp-settings-module-head > span:last-child { min-width:0; }
    .mp-settings-module-head .mp-ic { width:38px; height:38px; border-radius:8px; background:#eef2f0; display:grid; place-items:center; flex:none; }
    .mp-settings-module-head .dashicons { width:19px; height:19px; font-size:19px; }
    .mp-settings-module-head strong, .mp-settings-module-head small { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
    .mp-settings-module-head strong { font-size:14px; line-height:1.3; }
    .mp-settings-module-head small { margin-top:2px; color:#748078; font-size:11.5px; font-weight:500; }
    .mp-settings-module-summary { min-height:44px; margin:22px 0 12px; color:#53605a; font-size:13px; line-height:1.5; }
    .mp-settings-module-metrics { display:grid; grid-template-columns:1fr 1fr; gap:8px; margin:18px 0 12px; }
    .mp-settings-module-metrics > span { padding:10px; border-radius:8px; background:#f4f7f5; }
    .mp-settings-module-metrics b, .mp-settings-module-metrics small { display:block; }
    .mp-settings-module-metrics b { color:#18211d; font-size:18px; line-height:1; }
    .mp-settings-module-metrics small { margin-top:4px; color:#748078; font-size:10.5px; font-weight:600; }
    .mp-settings-module-foot { display:flex; align-items:center; justify-content:space-between; gap:8px; margin-top:auto; padding-top:12px;
        border-top:1px solid #edf0ee; color:#176b52; font-size:11.5px; font-weight:750; }
    .mp-settings-module-foot > span:last-child { display:inline-flex; align-items:center; gap:3px; }
    .mp-settings-module-foot .dashicons { width:15px; height:15px; font-size:15px; }
    .mp-mini-state { padding:4px 7px; border-radius:7px; background:#edf0ee; color:#657069; font-size:10.5px; }
    .mp-mini-state.is-success { background:#e4f4ec; color:#176b52; }
    .mp-mini-state.is-info { background:#eaf2fb; color:#315d8a; }
    .mp-mini-state.is-danger { background:#fff0ee; color:#a23b31; }

    html.mp-modal-open { overflow:hidden; }
    .mp-modal-box.mp-settings-dialog { display:flex; flex-direction:column; overflow:hidden; max-height:min(90vh,900px); border-radius:8px; }
    .mp-modal-box.mp-settings-dialog--sm { max-width:560px; }
    .mp-modal-box.mp-settings-dialog--md { max-width:760px; }
    .mp-modal-box.mp-settings-dialog--lg { max-width:860px; }
    .mp-modal-box.mp-settings-dialog--xl { max-width:1000px; }
    .mp-settings-dialog .mp-modal-head { flex:none; }
    .mp-settings-dialog .mp-modal-head > div { min-width:0; }
    .mp-settings-dialog .mp-modal-head p { margin:3px 0 0; color:#748078; font-size:12px; }
    .mp-settings-dialog .mp-modal-body { overflow-y:auto; padding:20px 22px; }
    .mp-settings-dialog .mp-modal-foot { flex:none; background:#fff; }
    .mp-dialog-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:0 16px; }
    .mp-dialog-grid > .mp-field--full, .mp-dialog-grid > .mp-danger-option { grid-column:1 / -1; }
    .mp-dialog-grid .mp-settings-subsection { margin-top:4px; }
    .mp-danger-option { margin:4px 0 0; padding:13px 14px; border:1px solid #efc5c0; border-radius:8px; background:#fff5f3; }
    .mp-check > span strong, .mp-check > span small { display:block; }
    .mp-check > span small { margin-top:2px; color:#748078; font-size:11.5px; font-weight:500; }

    @media (max-width:1280px) {
        .mp-grid--application { grid-template-columns:repeat(3,minmax(0,1fr)); }
        .mp-grid--vip { grid-template-columns:repeat(2,minmax(0,1fr)); }
        .mp-section-heading--inside, .mp-card--cloud { grid-column:1 / -1; }
        .mp-card--packages, .mp-card--vip-flow { grid-column:span 1; }
    }
    @media (max-width:782px) {
        .mp-admin { padding:18px 16px 80px; }
        .mp-settings-nav { top:46px; overflow-x:auto; }
        .mp-settings-nav a { white-space:nowrap; }
        .mp-settings-overview { align-items:flex-start; flex-direction:column; padding:17px; }
        .mp-settings-statuses { justify-content:flex-start; }
        .mp-grid--application, .mp-grid--vip { grid-template-columns:1fr; }
        .mp-card--packages, .mp-card--vip-flow, .mp-card--cloud { grid-column:1; }
        .mp-card--cloud { grid-template-columns:1fr; }
        .mp-card--cloud > * { grid-column:1 !important; }
        .mp-settings-module { min-height:168px; }
        .mp-dialog-grid { grid-template-columns:1fr; }
        .mp-dialog-grid > * { grid-column:1 !important; }
        .mp-settings-dialog .mp-modal-body { padding:17px; }
        .mp-settings-dialog .mp-modal-foot { padding:12px; }
        .mp-settings-dialog .mp-modal-foot .mp-btn { flex:1; }
        .mp-section-heading p { display:none; }
        .mp-card { padding:17px; }
        .mp-save-bar { bottom:8px; padding:10px; }
        .mp-save-hint { display:none; }
        .mp-save-bar .mp-btn { width:100%; }
    }

    .mp-feat { width:100%; border-collapse:separate; border-spacing:0; }
    .mp-feat th { text-align:center; font-size:11px; text-transform:uppercase; letter-spacing:.4px; color:#5f6368; padding:0 6px 10px; font-weight:700; }
    .mp-feat th:first-child { text-align:left; }
    .mp-feat td { padding:11px 6px; border-top:1px solid #f1f3f5; font-size:14px; text-align:center; }
    .mp-feat td:first-child { text-align:left; font-weight:600; }
    .mp-feat tr:first-child td { border-top:none; }
    .mp-feat input[type=checkbox] { width:18px; height:18px; margin:0; }

    .mp-save-bar { margin-top:24px; padding:14px 18px; background:#fff; border:1px solid #cfd7d3; border-radius:8px;
        display:flex; justify-content:space-between; align-items:center; gap:14px; flex-wrap:wrap;
        position:sticky; bottom:14px; z-index:15; box-shadow:0 10px 30px rgba(18,38,28,.12); }
    .mp-save-hint { display:flex; align-items:center; gap:7px; font-size:13px; color:#5f6368; }
    .mp-save-hint .dashicons { font-size:16px; width:16px; height:16px; color:#9aa0a6; }
    .mp-btn { display:inline-flex; align-items:center; justify-content:center; gap:6px; padding:9px 16px; border-radius:8px;
        font-size:13px; font-weight:600; cursor:pointer; border:1px solid transparent; font-family:inherit; text-decoration:none; transition:.15s; line-height:1.4; }
    .mp-btn .dashicons { font-size:16px; width:16px; height:16px; }
    .mp-btn--primary { background:#1a1a1f; color:#fff; padding:11px 22px; font-size:14px; }
    .mp-btn--primary:hover { background:#2c3338; color:#fff; transform:translateY(-1px); }
    .mp-btn--primary .dashicons { color:#f0b90b; }
    .mp-btn--gold { background:#f0b90b; color:#1a1a1f; }
    .mp-btn--gold:hover { background:#d9a808; color:#1a1a1f; }
    .mp-btn--outline { background:#fff; border-color:#d8dae0; color:#1a1a1f; }
    .mp-btn--outline:hover { background:#f9fafb; }
    .mp-btn--danger { background:#fef2f2; border-color:#f3b4b4; color:#b91c1c; }
    .mp-btn--danger:hover { background:#dc2626; border-color:#dc2626; color:#fff; }
    .mp-btn--danger .dashicons { font-size:16px; width:16px; height:16px; }

    .mp-table-wrap { overflow-x:auto; }
    .mp-table { width:100%; border-collapse:separate; border-spacing:0; font-size:13px; }
    .mp-table th { text-align:left; font-size:11px; text-transform:uppercase; letter-spacing:.4px; color:#5f6368; font-weight:700; padding:0 12px 12px; white-space:nowrap; }
    .mp-table td { padding:12px; border-top:1px solid #f1f3f5; vertical-align:middle; }
    .mp-table tbody tr:hover td { background:#fafbfc; }
    .mp-pill { display:inline-flex; align-items:center; gap:5px; padding:3px 10px; border-radius:999px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.3px; white-space:nowrap; }
    .mp-pill--vip { background:#fef3c7; color:#92400e; }
    .mp-pill--muted { background:#f1f3f5; color:#5f6368; }
    .mp-pill--active { background:#d1fae5; color:#065f46; }
    .mp-pill--blocked { background:#fee2e2; color:#991b1b; }
    .mp-empty { color:#5f6368; font-size:14px; padding:6px 0; }
    .mp-avatar { width:34px; height:34px; border-radius:50%; background:linear-gradient(135deg,#1a1a1f,#3a3a45); color:#f0b90b; font-weight:700; display:inline-flex; align-items:center; justify-content:center; font-size:13px; flex-shrink:0; }
    code.mp-ref { background:#f3f4f6; border:1px solid #ebecf0; border-radius:6px; padding:2px 8px; font-size:12px; font-weight:600; color:#1a1a1f; }

    /* Tabs */
    .mp-admin [hidden] { display:none !important; }
    .mp-tabs { display:flex; gap:6px; margin-bottom:20px; border-bottom:1px solid #e3e5ea; flex-wrap:wrap; }
    .mp-tab-btn { display:inline-flex; align-items:center; gap:7px; padding:11px 18px; border:none; background:transparent;
        font-family:inherit; font-size:14px; font-weight:600; color:#5f6368; cursor:pointer; border-radius:10px 10px 0 0;
        border-bottom:2px solid transparent; margin-bottom:-1px; transition:.15s; }
    .mp-tab-btn:hover { color:#1a1a1f; background:#fff; }
    .mp-tab-btn.is-active { color:#1a1a1f; border-bottom-color:#f0b90b; background:#fff; }
    .mp-tab-btn .dashicons { font-size:17px; width:17px; height:17px; }
    .mp-tab-count { background:#f0b90b; color:#1a1a1f; font-size:11px; font-weight:800; padding:1px 8px; border-radius:999px; }

    /* Add-on cards */
    .mp-addon { background:#fff; border:1px solid #ebecf0; border-radius:16px; padding:18px; display:flex; flex-direction:column; gap:14px; }
    .mp-addon-top { display:flex; align-items:center; gap:14px; }
    .mp-addon-ic { width:46px; height:46px; border-radius:13px; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
    .mp-addon-ic .dashicons { font-size:24px; width:24px; height:24px; }
    .mp-addon-info { flex:1; min-width:0; }
    .mp-addon-name { font-size:15px; font-weight:700; color:#1a1a1f; }
    .mp-addon-sub { font-size:12px; color:#5f6368; margin-top:1px; }
    .mp-addon-foot { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
    .mp-addon-switch-form { margin:0; }

    /* Switch */
    .mp-switch { position:relative; display:inline-block; width:46px; height:26px; cursor:pointer; flex-shrink:0; }
    .mp-switch input { opacity:0; width:0; height:0; position:absolute; }
    .mp-switch-slider { position:absolute; inset:0; background:#cfd3d9; border-radius:999px; transition:.2s; }
    .mp-switch-slider::before { content:""; position:absolute; height:20px; width:20px; left:3px; top:3px; background:#fff; border-radius:50%; transition:.2s; box-shadow:0 1px 3px rgba(0,0,0,.25); }
    .mp-switch input:checked + .mp-switch-slider { background:#1DB985; }
    .mp-switch input:checked + .mp-switch-slider::before { transform:translateX(20px); }

    /* Modal */
    .mp-modal { display:none; position:fixed; inset:0; z-index:99999; background:rgba(15,15,20,.55); align-items:center; justify-content:center; padding:20px; }
    .mp-modal.is-open { display:flex; }
    .mp-modal-box { background:#fff; border-radius:16px; max-width:480px; width:100%; max-height:90vh; overflow:auto; box-shadow:0 24px 70px rgba(0,0,0,.3); }
    .mp-modal-head { display:flex; align-items:center; justify-content:space-between; padding:18px 20px; border-bottom:1px solid #f1f3f5; }
    .mp-modal-head h3 { margin:0; font-size:16px; font-weight:700; color:#1a1a1f; }
    .mp-modal-x { background:#f3f4f6; border:none; width:30px; height:30px; border-radius:8px; font-size:20px; line-height:1; color:#5f6368; cursor:pointer; }
    .mp-modal-x:hover { background:#e8eaed; color:#1a1a1f; }
    .mp-modal-body { padding:18px 20px; }
    .mp-modal-foot { display:flex; justify-content:flex-end; gap:10px; padding:16px 20px; border-top:1px solid #f1f3f5; }
    .mp-modal-sep { border:none; border-top:1px solid #f1f3f5; margin:14px 0; }

    /* Programa patrocinado — Material 3 */
    #tab-parcerias { --sp-primary:#146c43; --sp-on-primary:#fff; --sp-primary-container:#d9efe2;
        --sp-surface:#fff; --sp-surface-low:#f4f7f5; --sp-outline:#d5ddd8; --sp-text:#18251e; --sp-muted:#5d6962; }
    #tab-parcerias .mp-card { border-radius:8px; border-color:var(--sp-outline); box-shadow:none; }
    #tab-parcerias .mp-btn { min-height:40px; border-radius:8px; }
    #tab-parcerias .mp-btn--gold { background:var(--sp-primary); color:var(--sp-on-primary); }
    #tab-parcerias .mp-btn--gold:hover { background:#0d5936; color:#fff; }
    #tab-parcerias .mp-btn--outline { border-color:var(--sp-outline); color:var(--sp-text); }
    #tab-parcerias .mp-pill { border-radius:8px; letter-spacing:0; text-transform:none; }
    .mp-sp-overview { background:var(--sp-surface); border-bottom:1px solid var(--sp-outline); padding:22px 2px 24px; }
    .mp-sp-overview-head { display:flex; align-items:center; justify-content:space-between; gap:20px; flex-wrap:wrap; }
    .mp-sp-title-block { display:flex; align-items:center; gap:14px; min-width:0; }
    .mp-sp-title-icon { width:48px; height:48px; flex:none; display:flex; align-items:center; justify-content:center;
        border-radius:8px; color:var(--sp-primary); background:var(--sp-primary-container); }
    .mp-sp-title-icon .dashicons { width:24px; height:24px; font-size:24px; }
    .mp-sp-kicker { color:var(--sp-primary); text-transform:uppercase; font-size:11px; font-weight:800; letter-spacing:.5px; }
    .mp-sp-overview h2 { color:var(--sp-text); font-size:22px; font-weight:750; margin-top:2px; }
    .mp-sp-overview p { color:var(--sp-muted); font-size:13px; margin:4px 0 0; }
    .mp-sp-metrics { display:grid; grid-template-columns:repeat(5,minmax(130px,1fr)); gap:10px; margin-top:20px; }
    .mp-sp-metric { min-height:82px; background:var(--sp-surface-low); border:1px solid transparent; border-radius:8px; padding:14px; }
    .mp-sp-metric span { display:block; color:var(--sp-muted); font-size:11.5px; margin-bottom:7px; }
    .mp-sp-metric strong { color:var(--sp-text); display:block; font-size:22px; line-height:1; }
    .mp-sp-metric--valid { background:#e4f4e9; }
    .mp-sp-metric--valid strong { color:var(--sp-primary); }
    .mp-sp-metric--alert { background:#ffedea; border-color:#f4c7c0; }
    .mp-sp-metric--alert strong { color:#a73529; }
    .mp-sp-integrity { display:flex; align-items:flex-start; gap:12px; margin-top:14px; padding:13px 14px;
        border-radius:8px; background:var(--sp-primary-container); color:#173b29; }
    .mp-sp-integrity > .dashicons { color:var(--sp-primary); margin-top:1px; }
    .mp-sp-integrity strong,.mp-sp-integrity span { display:block; }
    .mp-sp-integrity strong { font-size:13px; }
    .mp-sp-integrity span { color:#466254; font-size:12px; margin-top:2px; }
    .mp-sp-split { display:grid; grid-template-columns:minmax(0,1fr) 340px; gap:24px; align-items:start; }
    .mp-sp-grid { display:grid; grid-template-columns:1fr 1fr; gap:14px; }
    .mp-sp-picker { display:flex; gap:8px; }
    .mp-sp-picker input { flex:1; min-width:0; }
    .mp-sp-preview { position:sticky; top:20px; }
    .mp-sp-phone { background:#fbfdfb; border:1px solid var(--sp-outline); border-radius:8px; padding:16px; box-shadow:0 8px 24px rgba(24,37,30,.10); color:var(--sp-text); }
    .mp-sp-phone-top { display:flex; align-items:center; gap:10px; font-weight:700; font-size:15px; margin-bottom:14px; }
    .mp-sp-phone-top > .dashicons { color:var(--sp-text); }
    .mp-sp-phone-top small { display:block; margin-top:1px; color:var(--sp-muted); font-size:10.5px; font-weight:500; }
    .mp-sp-phone-balance { display:block; background:var(--sp-primary-container); border-radius:8px; padding:14px; margin-bottom:16px; }
    .mp-sp-phone-balance span,.mp-sp-phone-balance small { display:block; color:#466254; font-size:10.5px; }
    .mp-sp-phone-balance strong { display:block; color:#173b29; font-size:26px; line-height:1.25; }
    .mp-sp-phone-section { font-weight:700; font-size:12px; margin-bottom:8px; }
    .mp-sp-row { display:flex; align-items:center; gap:9px; padding:8px 0; border-bottom:1px solid var(--sp-outline); }
    .mp-sp-cover { width:50px; height:50px; border-radius:6px; background:var(--sp-primary-container); background-size:cover; background-position:center; display:flex; align-items:center; justify-content:center; color:var(--sp-primary); flex:none; }
    .mp-sp-cover.has-img span { display:none; }
    .mp-sp-meta { flex:1; min-width:0; }
    .mp-sp-ttl { color:var(--sp-text); font-weight:700; font-size:13px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
    .mp-sp-sub { color:var(--sp-primary); font-weight:600; font-size:10.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
    .mp-sp-add,.mp-sp-play { width:34px; height:34px; border-radius:50%; display:flex; align-items:center; justify-content:center; flex:none; }
    .mp-sp-add { color:var(--sp-primary); background:var(--sp-primary-container); }
    .mp-sp-play { color:#fff; background:var(--sp-primary); }
    .mp-sp-add .dashicons,.mp-sp-play .dashicons { font-size:16px; width:16px; height:16px; }
    .mp-sp-earn { display:flex; align-items:center; gap:7px; margin-top:12px; padding:10px 12px; border-radius:8px; background:#e4f4e9; color:#24563b; font-size:11.5px; }
    .mp-sp-earn .dashicons { color:var(--sp-primary); font-size:16px; width:16px; height:16px; }
    @media (max-width:1200px){ .mp-sp-metrics { grid-template-columns:repeat(3,minmax(130px,1fr)); } }
    @media (max-width:1100px){ .mp-sp-split { grid-template-columns:1fr; } .mp-sp-preview { position:static; max-width:420px; } }
    @media (max-width:720px){ .mp-sp-metrics { grid-template-columns:repeat(2,minmax(120px,1fr)); } .mp-sp-grid { grid-template-columns:1fr; } .mp-sp-overview-head .mp-btn { width:100%; } }
    </style>
    <?php
}
