<?php
error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
ini_set('display_errors', '0');
date_default_timezone_set('America/Sao_Paulo');

// =========================================================================
// RE9 WEBMAIL FEDERADO: INSTALAÇÕES INDEPENDENTES POR CLIENTE/CPANEL
// Cada cliente mantém sua própria pasta, dados privados, IMAP e credenciais
// cPanel. Quando vinculado, consulta a Central Renove por HTTPS + token único
// para receber anúncios, catálogo público e identidade visual; também envia
// sinais de presença das caixas abertas. O compartilhamento direto de arquivos
// só é utilizado quando as instalações realmente pertencem ao mesmo HOME.
// =========================================================================
$RE9_CURRENT_APP_DIR = realpath(__DIR__) ? realpath(__DIR__) : __DIR__;
$RE9_CPANEL_HOME = '';
if (preg_match('#^(/home/[^/]+)(?:/|$)#', str_replace('\\', '/', $RE9_CURRENT_APP_DIR), $re9HomeMatch)) {
    $RE9_CPANEL_HOME = $re9HomeMatch[1];
}
$RE9_CANONICAL_APP_DIR = $RE9_CURRENT_APP_DIR;
if ($RE9_CPANEL_HOME !== '') {
    $re9CanonicalCandidate = $RE9_CPANEL_HOME . '/public_html/webmail9';
    if (is_dir($re9CanonicalCandidate)) {
        $RE9_CANONICAL_APP_DIR = realpath($re9CanonicalCandidate) ? realpath($re9CanonicalCandidate) : $re9CanonicalCandidate;
    } elseif (basename(str_replace('\\', '/', $RE9_CURRENT_APP_DIR)) !== 'webmail9') {
        $re9SharedFallback = $RE9_CPANEL_HOME . '/.re9_webmail_shared';
        if (!is_dir($re9SharedFallback)) @mkdir($re9SharedFallback, 0700, true);
        $RE9_CANONICAL_APP_DIR = $re9SharedFallback;
    }
}
$RE9_CANONICAL_SCRIPT_PATH = rtrim($RE9_CANONICAL_APP_DIR, '/\\') . '/index.php';
$RE9_SHARED_DATA_DIR = rtrim($RE9_CANONICAL_APP_DIR, '/\\') . '/webmail_data';
$RE9_SHARED_UPLOAD_DIR = rtrim($RE9_CANONICAL_APP_DIR, '/\\') . '/webmail_uploads';
$RE9_INSTANCE_HOST = isset($_SERVER['HTTP_HOST']) ? strtolower(preg_replace('/:\\d+$/', '', (string)$_SERVER['HTTP_HOST'])) : 'local';
if ($RE9_INSTANCE_HOST === '') $RE9_INSTANCE_HOST = 'local';
$RE9_INSTANCE_HOST = preg_replace('/^www\\./', '', $RE9_INSTANCE_HOST);
$RE9_IS_CENTRAL_HUB = in_array(preg_replace('/^www\\./', '', $RE9_INSTANCE_HOST), array('re9.rio.br'), true);
$RE9_CENTRAL_HUB_URL = 'https://re9.rio.br/webmail9/index.php';

// =========================================================================
// ENTREGA SEGURA DE IMAGENS PÚBLICAS DO WEBMAIL (LOGO, CARTAZES E PRODUTOS)
// Faz o servidor entregar a imagem com MIME correto, sem depender de regras
// estáticas/alias do Apache. Apenas arquivos de imagem da raiz de webmail_uploads.
// Anexos privados nunca passam por esta rota.
// =========================================================================
if (isset($_GET['re9_asset'])) {
    $requestedAsset = rawurldecode((string)$_GET['re9_asset']);
    $requestedAsset = str_replace('\\', '/', $requestedAsset);
    $assetName = basename($requestedAsset);
    $allowedAssetExt = array('jpg','jpeg','png','gif','webp','bmp');
    $assetExt = strtolower(pathinfo($assetName, PATHINFO_EXTENSION));
    $assetRoot = realpath(isset($RE9_SHARED_UPLOAD_DIR) ? $RE9_SHARED_UPLOAD_DIR : (__DIR__ . '/webmail_uploads'));

    if ($assetRoot === false || !preg_match('/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,180}$/', $assetName) || !in_array($assetExt, $allowedAssetExt, true)) {
        http_response_code(404);
        header('Content-Type: text/plain; charset=utf-8');
        echo 'Imagem não encontrada.';
        exit;
    }

    $assetPath = realpath($assetRoot . DIRECTORY_SEPARATOR . $assetName);
    if ($assetPath === false || strpos($assetPath, $assetRoot . DIRECTORY_SEPARATOR) !== 0 || !is_file($assetPath) || !is_readable($assetPath)) {
        http_response_code(404);
        header('Content-Type: text/plain; charset=utf-8');
        echo 'Imagem não encontrada.';
        exit;
    }

    $assetInfo = @getimagesize($assetPath);
    $assetMime = is_array($assetInfo) && !empty($assetInfo['mime']) ? strtolower($assetInfo['mime']) : '';
    $allowedAssetMimes = array('image/jpeg','image/png','image/gif','image/webp','image/bmp');
    if (!in_array($assetMime, $allowedAssetMimes, true)) {
        http_response_code(415);
        header('Content-Type: text/plain; charset=utf-8');
        echo 'Formato de imagem não permitido.';
        exit;
    }

    $assetEtag = '"' . sha1($assetName . '|' . filesize($assetPath) . '|' . filemtime($assetPath)) . '"';
    header('X-Content-Type-Options: nosniff');
    header('Content-Type: ' . $assetMime);
    header('Cache-Control: public, max-age=86400, stale-while-revalidate=3600');
    header('ETag: ' . $assetEtag);
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($assetPath)) . ' GMT');
    if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && trim((string)$_SERVER['HTTP_IF_NONE_MATCH']) === $assetEtag) {
        http_response_code(304);
        exit;
    }
    header('Content-Length: ' . filesize($assetPath));
    readfile($assetPath);
    exit;
}

// =========================================================================
// 0. MOTOR PWA INTEGRADO (ÍCONE RE9 EMAIL, MANIFEST.JSON E SERVICE WORKER)
// =========================================================================
if (isset($_GET['pwa'])) {
    $pwa_type = $_GET['pwa'];

    if ($pwa_type === 'icon') {
        header('Content-Type: image/svg+xml; charset=utf-8');
        header('Cache-Control: public, max-age=604800');
        echo '<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
    <defs>
        <linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
            <stop offset="0%" stop-color="#00264d"/>
            <stop offset="100%" stop-color="#001226"/>
        </linearGradient>
    </defs>
    <rect width="512" height="512" rx="110" fill="url(#bgGrad)"/>
    <rect x="14" y="14" width="484" height="484" rx="98" fill="none" stroke="#f28c38" stroke-width="6" stroke-opacity="0.35"/>
    <g transform="translate(176, 85)">
        <rect x="0" y="0" width="160" height="108" rx="18" fill="#002d5a" stroke="#4b6bfb" stroke-width="6"/>
        <path d="M 10 14 L 80 66 L 150 14" fill="none" stroke="#f28c38" stroke-width="10" stroke-linecap="round" stroke-linejoin="round"/>
    </g>
    <text x="256" y="318" text-anchor="middle" font-family="Arial Black, Impact, system-ui, sans-serif" font-weight="900" font-size="84" letter-spacing="-1">
        <tspan fill="#f28c38">RE9</tspan><tspan fill="#ffffff">EMAIL</tspan>
    </text>
    <text x="295" y="372" text-anchor="middle" font-family="Arial, system-ui, sans-serif" font-weight="800" font-size="25" fill="#4b6bfb" letter-spacing="5">
        EMAIL CORPORATIVO
    </text>
</svg>';
        exit;
    }

    if ($pwa_type === 'logo_horizontal') {
        header('Content-Type: image/svg+xml; charset=utf-8');
        header('Cache-Control: public, max-age=604800');
        echo '<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 430 95" width="430" height="95">
    <rect width="430" height="95" rx="10" fill="#002244"/>
    <text x="215" y="60" text-anchor="middle" font-family="Arial Black, Impact, system-ui, sans-serif" font-weight="900" font-size="56" letter-spacing="0">
        <tspan fill="#f28c38">RE9</tspan><tspan fill="#ffffff">EMAIL</tspan>
    </text>
</svg>';
        exit;
    }

    if ($pwa_type === 'manifest') {
        header('Content-Type: application/manifest+json; charset=utf-8');
        $base_path = strtok($_SERVER['REQUEST_URI'], '?');
        $manifest = array(
            'id'               => $base_path,
            'name'             => 'Plataforma Corporativa',
            'short_name'       => 'RE9 EMAIL',
            'description'      => 'Aplicativo oficial RE9 EMAIL Corporativo com Robô Anti-Phishing integrado.',
            'start_url'        => $base_path,
            'scope'            => $base_path,
            'display'          => 'standalone',
            'orientation'      => 'portrait',
            'background_color' => '#00152b',
            'theme_color'      => '#002244',
            'icons'            => array(
                array(
                    'src'     => $base_path . '?pwa=icon',
                    'sizes'   => '192x192 512x512',
                    'type'    => 'image/svg+xml',
                    'purpose' => 'any maskable'
                )
            )
        );
        echo json_encode($manifest);
        exit;
    }

    if ($pwa_type === 'sw') {
        header('Content-Type: application/javascript; charset=utf-8');
        header('Service-Worker-Allowed: /');
        echo "
self.addEventListener('install', function(e) { self.skipWaiting(); });
self.addEventListener('activate', function(e) { e.waitUntil(self.clients.claim()); });
self.addEventListener('fetch', function(e) { return; });
";
        exit;
    }
    exit;
}

@ini_set('session.use_strict_mode', '1');
@ini_set('session.use_only_cookies', '1');
@ini_set('session.cookie_httponly', '1');
@ini_set('session.cookie_samesite', 'Lax');
if (!empty($_SERVER['HTTPS']) && strtolower((string)$_SERVER['HTTPS']) !== 'off') @ini_set('session.cookie_secure', '1');
session_start();
$RE9_CLIENT_BUILD_VERSION = '2026.11.15.03';
if (!headers_sent()) { header('X-Content-Type-Options: nosniff'); header('Referrer-Policy: strict-origin-when-cross-origin'); header('X-Frame-Options: SAMEORIGIN'); header('Permissions-Policy: camera=(), microphone=(), geolocation=()'); header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header('Pragma: no-cache'); header('Expires: 0'); header('X-RE9-Build: re9-federated-auto-update-2026-11-15-03'); header('X-RE9-Shared-Store: ' . ((isset($RE9_SHARED_DATA_DIR) && dirname($RE9_SHARED_DATA_DIR) === $RE9_CANONICAL_APP_DIR) ? 'canonical' : 'local')); }
if (!empty($_SESSION['wm_email']) && empty($_SESSION['re9_private_csrf'])) {
    $re9_csrf_bytes = function_exists('openssl_random_pseudo_bytes') ? openssl_random_pseudo_bytes(24) : false;
    $_SESSION['re9_private_csrf'] = $re9_csrf_bytes ? bin2hex($re9_csrf_bytes) : sha1(uniqid((string)mt_rand(), true));
}

// Normaliza imagens salvas em versões antigas (caminhos relativos, absolutos ou
// URLs do próprio domínio) para a rota segura ?re9_asset=arquivo.ext.
function re9_public_image_url($value) {
    $value = trim((string)$value);
    if ($value === '') return '';
    if (preg_match('~^data:image/(?:png|jpe?g|gif|webp);base64,~i', $value)) return $value;

    $scriptPath = !empty($_SERVER['SCRIPT_NAME']) ? (string)$_SERVER['SCRIPT_NAME'] : '/index.php';
    if (strpos($value, '?pwa=') === 0) return $scriptPath . $value;

    $parsed = @parse_url($value);
    $path = is_array($parsed) && isset($parsed['path']) ? rawurldecode((string)$parsed['path']) : rawurldecode($value);
    $pathNormalized = str_replace('\\', '/', $path);
    $uploadMarker = '/webmail_uploads/';
    $markerPos = stripos('/' . ltrim($pathNormalized, '/'), $uploadMarker);

    $currentHost = isset($_SERVER['HTTP_HOST']) ? strtolower(preg_replace('/:\\d+$/', '', (string)$_SERVER['HTTP_HOST'])) : '';
    $imageHost = is_array($parsed) && !empty($parsed['host']) ? strtolower((string)$parsed['host']) : '';
    $isSameHost = ($imageHost === '' || $currentHost === '' || $imageHost === $currentHost || preg_replace('/^www\\./', '', $imageHost) === preg_replace('/^www\\./', '', $currentHost));

    // Cartazes e logos salvos pela plataforma usam o armazenamento central.
    // Mesmo se a URL antiga apontar para re9.rio.br, entregue pelo host atual.
    if ($markerPos !== false) {
        $fileName = basename($pathNormalized);
        if (preg_match('/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,180}\\.(?:jpe?g|png|gif|webp|bmp)$/i', $fileName)) {
            return $scriptPath . '?re9_asset=' . rawurlencode($fileName);
        }
    }

    // Caminho no formato legado: webmail_uploads/nome.ext ou apenas nome.ext.
    $relative = ltrim($pathNormalized, './');
    if (strpos($relative, 'webmail_uploads/') === 0 || strpos($relative, '/webmail_uploads/') !== false) {
        $fileName = basename($relative);
        if (preg_match('/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,180}\\.(?:jpe?g|png|gif|webp|bmp)$/i', $fileName)) {
            return $scriptPath . '?re9_asset=' . rawurlencode($fileName);
        }
    }
    if (strpos($value, '://') === false && strpos($value, '/') === false && preg_match('/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,180}\\.(?:jpe?g|png|gif|webp|bmp)$/i', $value)) {
        return $scriptPath . '?re9_asset=' . rawurlencode($value);
    }

    // URLs externas permanecem externas; caminhos absolutos do site permanecem
    // absolutos. O navegador poderá carregá-los com a política de referência segura.
    if (preg_match('~^https?://~i', $value) || strpos($value, '//') === 0 || strpos($value, '/') === 0) return $value;
    $appDir = rtrim(str_replace('\\', '/', dirname($scriptPath)), '/');
    return ($appDir !== '' ? $appDir : '') . '/' . ltrim($value, './');
}

// =========================================================================
// 1. DIRETÓRIOS BLINDADOS + ARQUIVOS DE SEGURANÇA, ONLINE E CONTAS EXTERNAS
// =========================================================================
$DATA_DIR   = isset($RE9_SHARED_DATA_DIR) ? $RE9_SHARED_DATA_DIR : (dirname(__FILE__) . '/webmail_data');
$UPLOAD_DIR = isset($RE9_SHARED_UPLOAD_DIR) ? $RE9_SHARED_UPLOAD_DIR : (dirname(__FILE__) . '/webmail_uploads');
$PRIVATE_ATTACHMENT_DIR = $UPLOAD_DIR . '/private_attachments';

if (!is_dir($DATA_DIR)) {
    @mkdir($DATA_DIR, 0755, true);
}
if (!is_dir($UPLOAD_DIR)) {
    @mkdir($UPLOAD_DIR, 0755, true);
}
if (!is_dir($PRIVATE_ATTACHMENT_DIR)) @mkdir($PRIVATE_ATTACHMENT_DIR, 0700, true);

// Blindagem dos diretórios: arquivos de dados jamais podem ser servidos pela web.
$data_htaccess = "Options -Indexes\n<IfModule mod_authz_core.c>\nRequire all denied\n</IfModule>\n<IfModule !mod_authz_core.c>\nDeny from all\n</IfModule>\n";
@file_put_contents($DATA_DIR . '/.htaccess', $data_htaccess, LOCK_EX);
// Uploads podem conter imagens públicas, mas nunca podem executar PHP ou scripts.
$upload_htaccess = "Options -Indexes\n<FilesMatch \"\\.(php[0-9]?|phtml|phar|cgi|pl|py|sh|shtml)$\">\n<IfModule mod_authz_core.c>Require all denied</IfModule>\n<IfModule !mod_authz_core.c>Deny from all</IfModule>\n</FilesMatch>\n<IfModule mod_php.c>php_flag engine off</IfModule>\n";
@file_put_contents($UPLOAD_DIR . '/.htaccess', $upload_htaccess, LOCK_EX);
@file_put_contents($PRIVATE_ATTACHMENT_DIR . '/.htaccess', "Options -Indexes\n<IfModule mod_authz_core.c>Require all denied</IfModule>\n<IfModule !mod_authz_core.c>Deny from all</IfModule>\n", LOCK_EX);
if (!file_exists($DATA_DIR . '/index.html')) {
    @file_put_contents($DATA_DIR . '/index.html', '');
}

$CONFIG_FILE   = $DATA_DIR . '/secure_config.php';
$SIGS_FILE     = $DATA_DIR . '/secure_signatures.php';
$PHONES_FILE   = $DATA_DIR . '/secure_phones.php';
$IDENTITY_FILE = $DATA_DIR . '/secure_identity.php';
$PASSWORD_RECOVERY_FILE = $DATA_DIR . '/secure_password_recovery.php';
$ADMIN_PHONE_CHALLENGES_FILE = $DATA_DIR . '/secure_admin_phone_challenges.php';
$SECURITY_FILE = $DATA_DIR . '/secure_security.php';
$LOGIN_ATTEMPTS_FILE = $DATA_DIR . '/secure_login_attempts.php';
$ONLINE_FILE   = $DATA_DIR . '/secure_online.php';
$EXTERNAL_FILE = $DATA_DIR . '/secure_external.php';
$AGENDA_FILE = $DATA_DIR . '/secure_agenda.php';
$CONTACTS_FILE = $DATA_DIR . '/secure_contacts.php';
$PRIVATE_MESSAGES_FILE = $DATA_DIR . '/secure_private_messages.php';
$DIRECTORY_NAMES_FILE = $DATA_DIR . '/secure_directory_names.php';
$SALES_ORDERS_FILE = $DATA_DIR . '/secure_sales_orders.php';
$INSTANCES_FILE = $DATA_DIR . '/secure_instances.php';
$CENTRAL_SITES_FILE = $DATA_DIR . '/secure_central_sites.php';
$CENTRAL_PRESENCE_FILE = $DATA_DIR . '/secure_central_presence.php';
$CENTRAL_COMMANDS_FILE = $DATA_DIR . '/secure_central_commands.php';
$CENTRAL_MAILBOX_REPORT_FILE = $DATA_DIR . '/secure_central_mailboxes.php';
$CENTRAL_CLIENT_SYNC_FILE = $DATA_DIR . '/secure_central_client_sync.php';
$CENTRAL_WELCOME_FILE = $DATA_DIR . '/secure_central_welcome_notice.php';
$CENTRAL_CLIENT_RELEASE_SOURCE_FILE = $DATA_DIR . '/secure_client_release_source.bin';
$CENTRAL_CLIENT_RELEASE_META_FILE = $DATA_DIR . '/secure_client_release_meta.php';
$SALES_SUPPORT_EMAIL = 'suporte@renove.rio.br';
$RE9_SHARED_STORAGE_READY = is_dir($DATA_DIR) && is_writable($DATA_DIR) && is_dir($UPLOAD_DIR) && is_writable($UPLOAD_DIR);
if (!$RE9_SHARED_STORAGE_READY) { error_log('[RE9 GLOBAL] O armazenamento central não está acessível para leitura e gravação neste domínio. Verifique se todas as instalações usam o mesmo usuário cPanel e as permissões do diretório /home/USUARIO/public_html/webmail9.'); }


function save_protected_json($filepath, $data_array) {
    $guard = "<?php http_response_code(403); exit; ?>\n";
    $json = json_encode($data_array, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    if ($json === false) return false;
    $dir = dirname($filepath);
    $tmp = @tempnam($dir, '.re9tmp_');
    if ($tmp === false) return false;
    $written = @file_put_contents($tmp, $guard . $json, LOCK_EX);
    if ($written === false) { @unlink($tmp); return false; }
    @chmod($tmp, 0600);
    $ok = @rename($tmp, $filepath);
    if (!$ok) { @unlink($tmp); return false; }
    @chmod($filepath, 0600);
    return true;
}

function load_protected_json($filepath) {
    if (!file_exists($filepath)) return array();
    $raw = @file_get_contents($filepath);
    if (!$raw) return array();
    $pos = strpos($raw, "\n");
    $json_str = ($pos !== false) ? substr($raw, $pos + 1) : $raw;
    $decoded = @json_decode($json_str, true);
    return is_array($decoded) ? $decoded : array();
}

function re9_acquire_file_lock($filepath, $mode = LOCK_EX) {
    $handle = @fopen($filepath . '.shared.lock', 'c');
    if (!$handle) return false;
    if (!@flock($handle, $mode)) { @fclose($handle); return false; }
    return $handle;
}

function re9_release_file_lock($handle) {
    if (is_resource($handle)) { @flock($handle, LOCK_UN); @fclose($handle); }
}

$detected_cp_user = '';
if (preg_match('#^/home/([^/]+)/#', dirname(__FILE__), $m_cp)) {
    $detected_cp_user = $m_cp[1];
}

$default_config = array(
    'brand_name'         => 'E-mails Profissional',
    'brand_logo'         => '',
    'domain_name'        => 're9.rio.br',
    'brand_description'  => 'Plataforma corporativa de e-mails, alta performance e comunicação segura.',
    'color_navy'         => '#002244',
    'color_blood'        => '#990000',
    'color_chrome'       => '#475569',
    'admin_pass'         => 'admin123',
    'agenda_cron_key'    => '',
    'mobile_ad_interval' => 15,
    'whatsapp_api_url'   => '',
    'whatsapp_api_token' => '',
    // Integração Datavalid V5 (credenciais e autorização fornecidas pelo Serpro/GCC).
    'datavalid_environment' => 'production',
    'datavalid_consumer_key' => '',
    'datavalid_consumer_secret' => '',
    'datavalid_template_id' => '',
    'datavalid_gcc_token' => '',
    'datavalid_cnpj_anuente' => '',
    'cpanel_host'        => '162.240.100.87',
    'cpanel_user'        => $detected_cp_user,
    'cpanel_api_token'   => '',
    'cpanel_quota_mb'    => 250,
    // Vinculação segura desta instalação independente à Central Renove.
    'central_hub_url'    => 'https://re9.rio.br/webmail9/index.php',
    'central_site_id'    => '',
    'central_site_token' => '',
    'admin_emails'       => array(
        'suporte@re9.rio.br',
        'eliasvendas@hotmail.com',
        'admin@re9.rio.br',
        'contato@re9.rio.br'
    ),
    'ads_pool'           => array(
        array(
            'id'          => 'ad_def_1',
            'sender'      => 'RE9 Soluções Digitais',
            'badge'       => 'Patrocinado',
            'title'       => 'Hospedagem de Alta Performance e E-mail Profissional',
            'description' => 'Garanta estabilidade máxima para os e-mails e sistemas da sua empresa.',
            'image'       => '',
            'cta_text'    => 'Contratar Agora',
            'url'         => 'https://www.re9seusite.com.br'
        )
    )
);

if (!$RE9_IS_CENTRAL_HUB && $RE9_INSTANCE_HOST !== 'local' && preg_match('/^(?:[a-z0-9-]+\.)*[a-z0-9-]+$/i', $RE9_INSTANCE_HOST)) {
    $default_config['domain_name'] = $RE9_INSTANCE_HOST;
}
if (!file_exists($CONFIG_FILE)) {
    save_protected_json($CONFIG_FILE, $default_config);
}

$loaded_cfg = load_protected_json($CONFIG_FILE);
$APP_CONFIG = !empty($loaded_cfg) ? array_merge($default_config, $loaded_cfg) : $default_config;
// Migra instalações antigas que gravaram a senha administrativa com a chave legada.
if ((!isset($loaded_cfg['admin_pass']) || trim((string)$loaded_cfg['admin_pass']) === '') && !empty($loaded_cfg['admin_password'])) {
    $APP_CONFIG['admin_pass'] = (string)$loaded_cfg['admin_password'];
    save_protected_json($CONFIG_FILE, $APP_CONFIG);
}
// Em ambiente de teste, se nenhuma senha administrativa foi cadastrada, manter o padrão informado no painel.
// A senha padrão só é aplicada quando o campo está ausente ou vazio; senhas já configuradas são preservadas.
if (!isset($APP_CONFIG['admin_pass']) || !is_scalar($APP_CONFIG['admin_pass']) || trim((string)$APP_CONFIG['admin_pass']) === '') {
    $APP_CONFIG['admin_pass'] = 'admin123';
    save_protected_json($CONFIG_FILE, $APP_CONFIG);
}

// O RE9 mantém seu domínio principal; cada instalação cliente preserva o próprio domínio
// como atalho de login. A autenticação continua aceitando endereços completos de outros domínios.
if ($RE9_IS_CENTRAL_HUB) {
    if (strtolower(trim((string)get_val($APP_CONFIG, 'domain_name', ''))) !== 're9.rio.br') { $APP_CONFIG['domain_name'] = 're9.rio.br'; save_protected_json($CONFIG_FILE, $APP_CONFIG); }
} elseif ($RE9_INSTANCE_HOST !== 'local' && preg_match('/^(?:[a-z0-9-]+\.)*[a-z0-9-]+$/i', $RE9_INSTANCE_HOST)) {
    if (strtolower(trim((string)get_val($APP_CONFIG, 'domain_name', ''))) === '' || strtolower(trim((string)get_val($APP_CONFIG, 'domain_name', ''))) === 're9.rio.br') { $APP_CONFIG['domain_name'] = $RE9_INSTANCE_HOST; save_protected_json($CONFIG_FILE, $APP_CONFIG); }
}

if (empty($APP_CONFIG['agenda_cron_key'])) {
    $agenda_random = function_exists('openssl_random_pseudo_bytes') ? openssl_random_pseudo_bytes(24) : false;
    if ($agenda_random === false) { $agenda_random = sha1(uniqid((string)mt_rand(), true)); }
    $APP_CONFIG['agenda_cron_key'] = bin2hex($agenda_random);
    save_protected_json($CONFIG_FILE, $APP_CONFIG);
}
if (empty($APP_CONFIG['cpanel_user']) && !empty($detected_cp_user)) {
    $APP_CONFIG['cpanel_user'] = $detected_cp_user;
}
if (empty($APP_CONFIG['cpanel_host']) || $APP_CONFIG['cpanel_host'] === '127.0.0.1') {
    $APP_CONFIG['cpanel_host'] = '162.240.100.87';
}
if (empty($APP_CONFIG['ads_pool']) || !is_array($APP_CONFIG['ads_pool'])) {
    $APP_CONFIG['ads_pool'] = $default_config['ads_pool'];
}
if (!file_exists($CENTRAL_SITES_FILE)) save_protected_json($CENTRAL_SITES_FILE, array());
if (!file_exists($CENTRAL_PRESENCE_FILE)) save_protected_json($CENTRAL_PRESENCE_FILE, array());
if (!file_exists($CENTRAL_COMMANDS_FILE)) save_protected_json($CENTRAL_COMMANDS_FILE, array());
if (!file_exists($CENTRAL_MAILBOX_REPORT_FILE)) save_protected_json($CENTRAL_MAILBOX_REPORT_FILE, array());
if (!file_exists($CENTRAL_CLIENT_SYNC_FILE)) save_protected_json($CENTRAL_CLIENT_SYNC_FILE, array());
if (!file_exists($CENTRAL_WELCOME_FILE)) save_protected_json($CENTRAL_WELCOME_FILE, array('active'=>false,'title'=>'','body'=>'','published_at'=>0,'updated_at'=>0));
if (!file_exists($CENTRAL_CLIENT_RELEASE_META_FILE)) save_protected_json($CENTRAL_CLIENT_RELEASE_META_FILE, array('version'=>'','sha256'=>'','size'=>0,'published_at'=>0,'published_by'=>''));

// =========================================================================
// CENTRAL RENOVE: FEDERAÇÃO ENTRE INSTALAÇÕES EM CPANELS DIFERENTES
// Cada domínio cliente mantém suas caixas, credenciais cPanel e dados privados
// localmente. Somente anúncios/branding públicos e presença são sincronizados.
// =========================================================================
function re9_central_random_token() {
    if (function_exists('random_bytes')) { try { return bin2hex(random_bytes(32)); } catch (Exception $e) {} }
    if (function_exists('openssl_random_pseudo_bytes')) { $strong = false; $bytes = @openssl_random_pseudo_bytes(32, $strong); if ($strong && is_string($bytes) && strlen($bytes) === 32) return bin2hex($bytes); }
    return '';
}
function re9_central_default_welcome_notice() {
    return array('active'=>false,'title'=>"Bem-vindo ao seu Webmail",'body'=>"Olá! Seja muito bem-vindo(a) à sua caixa de e-mail.\n\nSua conta está pronta para uso. Além de enviar e receber e-mails, você conta com recursos para organizar sua rotina e se comunicar com mais segurança:\n\n✉️ E-mail profissional: envie, receba, responda, encaminhe, organize pastas, pesquise mensagens e utilize assinaturas e anexos.\n\n📅 Agenda inteligente: cadastre compromissos, organize horários e configure lembretes para não perder seus compromissos.\n\n👥 Contatos: mantenha seus contatos organizados e consulte o diretório disponível na sua instalação.\n\n💬 Mensagens privadas: converse com outros usuários cadastrados nesta plataforma. As mensagens ficam disponíveis para consulta mesmo quando o destinatário está offline.\n\n🛡️ Robô Anti-Golpe e Anti-Phishing: análise de mensagens, links e anexos para ajudar a identificar tentativas de fraude. Imagens externas são protegidas e só carregam quando você autoriza.\n\n🛍️ Loja e anúncios: consulte os anúncios e produtos publicados na plataforma e acompanhe os recursos de compra quando estiverem disponíveis para sua instalação.\n\n📱 Acesso pelo celular: você pode utilizar o webmail no navegador do celular e instalar o aplicativo quando a opção estiver disponível.\n\n🔐 Segurança da conta: utilize os recursos de recuperação de senha e mantenha seu e-mail secundário atualizado, quando solicitado.\n\nPrecisa de ajuda? Entre em contato com o suporte: suporte@re9.rio.br.\n\nEsta mensagem é um comunicado oficial fixado pela administração. Ela permanecerá na sua Caixa de Entrada para consulta.",'published_at'=>0,'updated_at'=>0);
}
function re9_central_get_welcome_notice() {
    global $RE9_IS_CENTRAL_HUB, $CENTRAL_WELCOME_FILE, $APP_CONFIG;
    if (!empty($RE9_IS_CENTRAL_HUB)) {
        $notice = load_protected_json($CENTRAL_WELCOME_FILE);
    } else {
        $notice = get_val($APP_CONFIG, 'central_welcome_notice', array());
    }
    if (!is_array($notice)) $notice = array();
    $defaults = re9_central_default_welcome_notice();
    $notice = array_merge($defaults, $notice);
    $notice['active'] = !empty($notice['active']);
    $notice['title'] = trim(strip_tags((string)$notice['title']));
    $notice['body'] = trim(strip_tags((string)$notice['body']));
    $notice['published_at'] = max(0, (int)$notice['published_at']);
    $notice['updated_at'] = max(0, (int)$notice['updated_at']);
    return $notice;
}
function re9_central_post_url($baseUrl, $action, $payload) {
    $baseUrl = trim((string)$baseUrl);
    if (!preg_match('#^https://[a-z0-9.-]+(?::443)?(?:/[^\s]*)?$#i', $baseUrl)) return array('status'=>'error','msg'=>'URL central HTTPS inválida.');
    $separator = (strpos($baseUrl, '?') === false) ? '?' : '&';
    $url = $baseUrl . $separator . 'api=' . rawurlencode((string)$action);
    $body = http_build_query(is_array($payload) ? $payload : array(), '', '&');
    $requestTimeout = ((string)$action === 'central_client_fetch_update') ? 30 : 8;
    $raw = false; $httpCode = 0;
    if (function_exists('curl_init')) {
        $ch = curl_init($url);
        curl_setopt_array($ch, array(
            CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>$body, CURLOPT_RETURNTRANSFER=>true,
            CURLOPT_CONNECTTIMEOUT=>5, CURLOPT_TIMEOUT=>$requestTimeout,
            CURLOPT_HTTPHEADER=>array('Content-Type: application/x-www-form-urlencoded','Accept: application/json'),
            CURLOPT_SSL_VERIFYPEER=>true, CURLOPT_SSL_VERIFYHOST=>2,
            CURLOPT_FOLLOWLOCATION=>false
        ));
        $raw = curl_exec($ch); $httpCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch);
    } else {
        $context = stream_context_create(array('http'=>array('method'=>'POST','header'=>"Content-Type: application/x-www-form-urlencoded\r\nAccept: application/json\r\n",'content'=>$body,'timeout'=>$requestTimeout,'ignore_errors'=>true),'ssl'=>array('verify_peer'=>true,'verify_peer_name'=>true)));
        $raw = @file_get_contents($url, false, $context);
        if (isset($http_response_header) && is_array($http_response_header)) foreach ($http_response_header as $h) if (preg_match('/^HTTP\/\S+\s+(\d+)/', $h, $m)) $httpCode=(int)$m[1];
    }
    $decoded = is_string($raw) ? json_decode($raw, true) : null;
    if (!is_array($decoded)) return array('status'=>'error','msg'=>'A Central Renove não respondeu com JSON válido.','http_code'=>$httpCode);
    $decoded['_http_code'] = $httpCode;
    return $decoded;
}
function re9_central_is_client_connected() {
    global $RE9_IS_CENTRAL_HUB, $APP_CONFIG;
    return empty($RE9_IS_CENTRAL_HUB) && !empty($APP_CONFIG['central_site_id']) && !empty($APP_CONFIG['central_site_token']);
}
function re9_central_authorize_site($siteId, $token, $touch) {
    global $RE9_IS_CENTRAL_HUB, $CENTRAL_SITES_FILE;
    if (empty($RE9_IS_CENTRAL_HUB)) return false;
    $siteId = strtolower(trim((string)$siteId));
    $token = trim((string)$token);
    if ($siteId === '' || $token === '' || !preg_match('/^(?:[a-z0-9-]+\.)*[a-z0-9-]+$/i', $siteId)) return false;
    $lock = re9_acquire_file_lock($CENTRAL_SITES_FILE, LOCK_EX);
    if (!$lock) return false;
    $sites = load_protected_json($CENTRAL_SITES_FILE); if (!is_array($sites)) $sites = array();
    $valid = isset($sites[$siteId]) && !empty($sites[$siteId]['enabled']) && !empty($sites[$siteId]['token_hash']) && hash_equals((string)$sites[$siteId]['token_hash'], hash('sha256', $token));
    if ($valid && $touch) {
        $sites[$siteId]['last_seen'] = time();
        $sites[$siteId]['last_ip'] = isset($_SERVER['REMOTE_ADDR']) ? (string)$_SERVER['REMOTE_ADDR'] : '';
        save_protected_json($CENTRAL_SITES_FILE, $sites);
    }
    re9_release_file_lock($lock);
    return $valid;
}
function re9_central_public_image_url($value) {
    $value = trim((string)$value);
    if ($value === '') return '';
    if (preg_match('#^https?://#i', $value) && stripos($value, 'webmail_uploads/') === false) return $value;
    $path = str_replace('\\', '/', $value);
    $file = basename($path);
    if (preg_match('/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,180}\.(?:jpe?g|png|gif|webp|bmp)$/i', $file)) return 'https://re9.rio.br/webmail9/index.php?re9_asset=' . rawurlencode($file);
    return $value;
}
function re9_central_public_payload() {
    global $APP_CONFIG;
    $ads = isset($APP_CONFIG['ads_pool']) && is_array($APP_CONFIG['ads_pool']) ? array_values($APP_CONFIG['ads_pool']) : array();
    foreach ($ads as &$ad) { if (!is_array($ad)) continue; if (!empty($ad['image'])) $ad['image'] = re9_central_public_image_url($ad['image']); }
    unset($ad);
    $payload = array(
        'brand_name'=>(string)get_val($APP_CONFIG,'brand_name','RE9 EMAIL'),
        'brand_description'=>(string)get_val($APP_CONFIG,'brand_description',''),
        'brand_logo'=>re9_central_public_image_url(get_val($APP_CONFIG,'brand_logo','')),
        'color_navy'=>(string)get_val($APP_CONFIG,'color_navy','#002244'),
        'color_blood'=>(string)get_val($APP_CONFIG,'color_blood','#990000'),
        'color_chrome'=>(string)get_val($APP_CONFIG,'color_chrome','#475569'),
        'ads_pool'=>$ads
    );
    $payload['revision'] = hash('sha256', json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
    return $payload;
}
function re9_central_sync_public_data($force) {
    global $RE9_IS_CENTRAL_HUB, $APP_CONFIG, $CONFIG_FILE;
    static $lastSync = 0;
    if (!empty($RE9_IS_CENTRAL_HUB) || !re9_central_is_client_connected()) return false;
    if (!$force && (time() - $lastSync) < 30) return true;
    $lastSync = time();
    $payload = array('site_id'=>(string)$APP_CONFIG['central_site_id'],'token'=>(string)$APP_CONFIG['central_site_token']);
    $reply = re9_central_post_url(get_val($APP_CONFIG,'central_hub_url','https://re9.rio.br/webmail9/index.php'), 'central_client_pull', $payload);
    if (get_val($reply,'status') !== 'ok' || !isset($reply['public']) || !is_array($reply['public'])) {
        error_log('[RE9 CENTRAL] Falha ao sincronizar conteúdo público da central para ' . (string)$APP_CONFIG['central_site_id'] . ': ' . (string)get_val($reply,'msg','sem resposta'));
        return false;
    }
    $public = $reply['public'];
    $publicFields = array('ads_pool','brand_name','brand_description','brand_logo','color_navy','color_blood','color_chrome');
    $changed = false;
    foreach ($publicFields as $field) {
        if (!array_key_exists($field, $public)) continue;
        if ($field === 'ads_pool' && !is_array($public[$field])) continue;
        if (!array_key_exists($field, $APP_CONFIG) || $APP_CONFIG[$field] !== $public[$field]) $changed = true;
        $APP_CONFIG[$field] = $public[$field];
    }
    $welcomeNotice = isset($public['welcome_notice']) && is_array($public['welcome_notice']) ? $public['welcome_notice'] : array('active'=>false,'title'=>'','body'=>'','published_at'=>0,'updated_at'=>0);
    if (!isset($APP_CONFIG['central_welcome_notice']) || $APP_CONFIG['central_welcome_notice'] !== $welcomeNotice) $changed = true;
    $APP_CONFIG['central_welcome_notice'] = $welcomeNotice;

    $revision = (string)get_val($public,'revision','');
    if ($revision !== '' && (string)get_val($APP_CONFIG,'central_public_revision','') !== $revision) $changed = true;
    if ($revision !== '') $APP_CONFIG['central_public_revision'] = $revision;

    // Persiste somente os campos públicos recebidos da Central, preservando
    // os segredos e as configurações locais deste cliente/cPanel.
    if ($changed && !empty($CONFIG_FILE)) {
        $stored = load_protected_json($CONFIG_FILE);
        if (!is_array($stored)) $stored = array();
        foreach ($publicFields as $field) if (array_key_exists($field,$APP_CONFIG)) $stored[$field] = $APP_CONFIG[$field];
        $stored['central_welcome_notice'] = $welcomeNotice;
        if ($revision !== '') $stored['central_public_revision'] = $revision;
        if (!save_protected_json($CONFIG_FILE, $stored)) {
            error_log('[RE9 CENTRAL] Não foi possível persistir anúncios/identidade visual em ' . (string)get_val($APP_CONFIG,'central_site_id','domínio cliente'));
        }
    }
    return true;
}
function re9_central_send_presence($email) {
    global $RE9_IS_CENTRAL_HUB, $APP_CONFIG, $RE9_INSTANCE_HOST;
    if (!empty($RE9_IS_CENTRAL_HUB) || !re9_central_is_client_connected()) return array('status'=>'disabled');
    $email = strtolower(trim((string)$email));
    $ua = isset($_SERVER['HTTP_USER_AGENT']) ? (string)$_SERVER['HTTP_USER_AGENT'] : '';
    $device = preg_match('/(android|iphone|ipad|ipod|mobile)/i',$ua) ? 'Celular' : 'Computador (PC)';
    $payload = array(
        'site_id'=>(string)$APP_CONFIG['central_site_id'], 'token'=>(string)$APP_CONFIG['central_site_token'],
        'email'=>$email, 'session_mark'=>function_exists('session_id') ? substr(hash('sha256',session_id()),0,14) : 'no-session',
        'device'=>$device, 'login_time'=>date('H:i:s'), 'domain'=>strtolower((string)$RE9_INSTANCE_HOST)
    );
    return re9_central_post_url(get_val($APP_CONFIG,'central_hub_url','https://re9.rio.br/webmail9/index.php'), 'central_client_heartbeat', $payload);
}


/** Lista as caixas reais de um domínio usando somente a UAPI do cPanel local. */
function re9_central_collect_cpanel_mailboxes($domain, &$errorMessage) {
    $domain = strtolower(trim((string)$domain));
    $errorMessage = '';
    if (!preg_match('/^(?=.{3,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,63}$/i', $domain)) {
        $errorMessage = 'Domínio inválido para consulta de caixas.';
        return array();
    }
    $result = call_cpanel_uapi('Email', 'list_pops', array('domain'=>$domain));
    if (!is_array($result) || get_val($result,'status') !== 'ok') {
        $errorMessage = (string)get_val($result,'msg','O cPanel não confirmou a listagem de caixas deste domínio.');
        return array();
    }
    $accounts = array();
    $walk = function($items) use (&$walk, &$accounts, $domain) {
        if (!is_array($items)) return;
        foreach ($items as $row) {
            if (is_string($row)) {
                $mail = strtolower(trim($row));
                if (strpos($mail,'@') === false) $mail .= '@'.$domain;
                if (filter_var($mail,FILTER_VALIDATE_EMAIL) && substr($mail, strrpos($mail,'@')+1) === $domain) {
                    $accounts[$mail] = array('email'=>$mail,'suspended'=>false);
                }
                continue;
            }
            if (!is_array($row)) continue;
            $mail = '';
            foreach (array('email','email_address','login','address') as $key) {
                if (isset($row[$key]) && is_string($row[$key]) && trim($row[$key]) !== '') { $mail = strtolower(trim($row[$key])); break; }
            }
            if ($mail !== '' && strpos($mail,'@') === false) $mail .= '@'.$domain;
            if ($mail === '') {
                foreach (array('user','username','account','mailbox','email_user') as $key) {
                    if (isset($row[$key]) && is_string($row[$key]) && trim($row[$key]) !== '') { $mail = strtolower(trim($row[$key])).'@'.$domain; break; }
                }
            }
            if ($mail !== '' && filter_var($mail,FILTER_VALIDATE_EMAIL) && substr($mail,strrpos($mail,'@')+1) === $domain) {
                $suspended = false;
                foreach (array('suspended','suspended_incoming','suspended_outgoing','login_suspended') as $sk) {
                    if (isset($row[$sk]) && in_array(strtolower((string)$row[$sk]),array('1','yes','true','suspended'),true)) $suspended = true;
                }
                $accounts[$mail] = array('email'=>$mail,'suspended'=>$suspended);
            }
            foreach (array('accounts','data','items','pops','list') as $nested) if (isset($row[$nested]) && is_array($row[$nested])) $walk($row[$nested]);
        }
    };
    $walk(get_val($result,'data',array()));
    ksort($accounts, SORT_NATURAL | SORT_FLAG_CASE);
    return array_values($accounts);
}

function re9_central_client_report_mailboxes($force) {
    global $RE9_IS_CENTRAL_HUB, $APP_CONFIG, $CENTRAL_CLIENT_SYNC_FILE, $IDENTITY_FILE, $RE9_CLIENT_BUILD_VERSION;
    if (!empty($RE9_IS_CENTRAL_HUB) || !re9_central_is_client_connected()) return false;
    $state = load_protected_json($CENTRAL_CLIENT_SYNC_FILE); if (!is_array($state)) $state=array();
    $now = time();
    if (!$force && ($now-(int)get_val($state,'last_mailbox_report',0)) < 300) return true;
    $domain = strtolower((string)get_val($APP_CONFIG,'central_site_id',''));
    $error = '';
    $accounts = re9_central_collect_cpanel_mailboxes($domain,$error);
    if (!$accounts) {
        error_log('[RE9 CENTRAL] Inventário de caixas não enviado para '.$domain.': '.($error!==''?$error:'nenhuma caixa foi retornada pelo cPanel.'));
        return false;
    }
    $identities = load_protected_json($IDENTITY_FILE); if (!is_array($identities)) $identities=array();
    $items = array();
    foreach ($accounts as $account) {
        $email = $account['email'];
        $identity = isset($identities[$email]) && is_array($identities[$email]) ? $identities[$email] : array();
        $released = !empty($identity['admin_manual_release_at']) || !empty($identity['admin_phone_verified_at']) || (!empty($identity['verified_at']) && !empty($identity['cpf_hash']) && !empty($identity['phone_hash']));
        $items[] = array('email'=>$email,'domain'=>$domain,'suspended'=>!empty($account['suspended']),'released'=>$released,'release_type'=>!empty($identity['admin_manual_release_at'])?'manual_support':(!empty($identity['admin_phone_verified_at'])?'phone_verified':($released?'identity_verified':'')));
    }
    $payload = array('site_id'=>$domain,'token'=>(string)$APP_CONFIG['central_site_token'],'client_version'=>(string)$RE9_CLIENT_BUILD_VERSION,'inventory_json'=>json_encode($items,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES));
    $reply = re9_central_post_url(get_val($APP_CONFIG,'central_hub_url','https://re9.rio.br/webmail9/index.php'),'central_client_mailbox_report',$payload);
    if (get_val($reply,'status') !== 'ok') { error_log('[RE9 CENTRAL] Falha ao enviar inventário de '.$domain.': '.(string)get_val($reply,'msg','sem resposta')); return false; }
    $state['last_mailbox_report']=$now; $state['last_mailbox_count']=count($items); save_protected_json($CENTRAL_CLIENT_SYNC_FILE,$state);
    return true;
}

function re9_central_process_pending_commands() {
    global $RE9_IS_CENTRAL_HUB, $APP_CONFIG, $IDENTITY_FILE, $CENTRAL_CLIENT_SYNC_FILE;
    if (!empty($RE9_IS_CENTRAL_HUB) || !re9_central_is_client_connected()) return;
    $syncState=load_protected_json($CENTRAL_CLIENT_SYNC_FILE); if (!is_array($syncState)) $syncState=array();
    if ((time()-(int)get_val($syncState,'last_command_poll',0)) < 20) return;
    $syncState['last_command_poll']=time(); save_protected_json($CENTRAL_CLIENT_SYNC_FILE,$syncState);
    $siteId = strtolower((string)get_val($APP_CONFIG,'central_site_id',''));
    $payload = array('site_id'=>$siteId,'token'=>(string)$APP_CONFIG['central_site_token']);
    $reply = re9_central_post_url(get_val($APP_CONFIG,'central_hub_url','https://re9.rio.br/webmail9/index.php'),'central_client_poll_commands',$payload);
    if (get_val($reply,'status') !== 'ok') return;
    $commands = isset($reply['commands']) && is_array($reply['commands']) ? $reply['commands'] : array();
    foreach ($commands as $command) {
        $commandId = preg_replace('/[^a-z0-9_-]/i','',(string)get_val($command,'id',''));
        $action = (string)get_val($command,'action','');
        $domain = strtolower(trim((string)get_val($command,'domain','')));
        $resultStatus = 'error'; $resultMessage = 'Comando não reconhecido ou domínio não corresponde a esta instalação.'; $affected = 0; $found = 0;
        if ($commandId !== '' && $action === 'bulk_release_existing_mailboxes' && $domain === $siteId && strtolower((string)get_val($APP_CONFIG,'domain_name','')) === $siteId) {
            $listError = '';
            $accounts = re9_central_collect_cpanel_mailboxes($domain,$listError);
            $found = count($accounts);
            if ($found < 1) {
                $resultMessage = $listError !== '' ? $listError : 'O cPanel não retornou nenhuma caixa para o domínio solicitado. Nenhuma conta foi alterada.';
            } else {
                $identities = load_protected_json($IDENTITY_FILE); if (!is_array($identities)) $identities=array();
                $now = time();
                foreach ($accounts as $account) {
                    $email = strtolower($account['email']);
                    if (!isset($identities[$email]) || !is_array($identities[$email])) $identities[$email]=array();
                    $identities[$email]['admin_manual_release_at']=$now;
                    $identities[$email]['pending_review_at']=0;
                    $identities[$email]['method']='central_bulk_release_existing_mailboxes';
                    $identities[$email]['reviewed_by']='suporte@re9.rio.br';
                    $identities[$email]['central_bulk_release_domain']=$domain;
                    $affected++;
                }
                if (save_protected_json($IDENTITY_FILE,$identities)) {
                    $resultStatus='ok';
                    $resultMessage='Liberação administrativa em lote concluída. As caixas e senhas do cPanel não foram alteradas.';
                    re9_central_client_report_mailboxes(true);
                } else {
                    $affected=0;
                    $resultMessage='O cPanel listou as caixas, mas o arquivo de identidade não pôde ser salvo. Nenhuma confirmação de liberação foi enviada.';
                }
            }
        }
        if ($commandId !== '') {
            re9_central_post_url(get_val($APP_CONFIG,'central_hub_url','https://re9.rio.br/webmail9/index.php'),'central_client_command_result',array(
                'site_id'=>$siteId,'token'=>(string)$APP_CONFIG['central_site_token'],'command_id'=>$commandId,
                'result_status'=>$resultStatus,'result_message'=>$resultMessage,'found_count'=>$found,'affected_count'=>$affected
            ));
        }
    }
}


/** Atualizador remoto seguro do index.php do cliente. A instalação só recebe pacotes
 * da Central HTTPS autenticada pelo token individual do domínio. Dados e segredos locais
 * nunca são sobrescritos; somente o arquivo PHP principal é substituído.
 */
function re9_central_client_check_for_updates() {
    global $RE9_IS_CENTRAL_HUB, $APP_CONFIG, $CENTRAL_CLIENT_SYNC_FILE, $DATA_DIR, $RE9_CLIENT_BUILD_VERSION;
    if (!empty($RE9_IS_CENTRAL_HUB) || !re9_central_is_client_connected()) return false;
    $state = load_protected_json($CENTRAL_CLIENT_SYNC_FILE); if (!is_array($state)) $state = array();
    $now = time();
    if (($now - (int)get_val($state, 'last_update_check', 0)) < 180) return false;
    $state['last_update_check'] = $now; save_protected_json($CENTRAL_CLIENT_SYNC_FILE, $state);

    $siteId = strtolower((string)get_val($APP_CONFIG, 'central_site_id', ''));
    $centralUrl = (string)get_val($APP_CONFIG, 'central_hub_url', 'https://re9.rio.br/webmail9/index.php');
    $payload = array('site_id'=>$siteId, 'token'=>(string)get_val($APP_CONFIG, 'central_site_token', ''), 'client_version'=>(string)$RE9_CLIENT_BUILD_VERSION);
    $reply = re9_central_post_url($centralUrl, 'central_client_fetch_update', $payload);
    if (get_val($reply, 'status') !== 'ok' || empty($reply['update_available'])) return false;

    $newVersion = trim((string)get_val($reply, 'version', ''));
    $expectedHash = strtolower(trim((string)get_val($reply, 'sha256', '')));
    $encoded = (string)get_val($reply, 'package_b64', '');
    if ($newVersion === '' || !preg_match('/^[0-9A-Za-z._-]{3,40}$/', $newVersion) || version_compare($newVersion, (string)$RE9_CLIENT_BUILD_VERSION, '<=') || $encoded === '' || !preg_match('/^[a-f0-9]{64}$/', $expectedHash)) {
        error_log('[RE9 UPDATE] Manifesto de atualização inválido para ' . $siteId . '.');
        return false;
    }
    $source = base64_decode($encoded, true);
    if (!is_string($source) || strlen($source) < 50000 || strlen($source) > 2097152 || !hash_equals($expectedHash, hash('sha256', $source))) {
        error_log('[RE9 UPDATE] Pacote de atualização vazio, grande demais ou com hash divergente para ' . $siteId . '.');
        return false;
    }
    if (strpos(ltrim($source, "\xEF\xBB\xBF\r\n\t "), '<?php') !== 0 || strpos($source, 're9_central_client_check_for_updates') === false || strpos($source, 'central_client_fetch_update') === false) {
        error_log('[RE9 UPDATE] O pacote recebido não é um index.php RE9 compatível.');
        return false;
    }
    if (!preg_match('/\\$RE9_CLIENT_BUILD_VERSION\\s*=\\s*[\\\'\\\"]' . preg_quote($newVersion, '/') . '[\\\'\\\"]/', $source)) {
        error_log('[RE9 UPDATE] A versão declarada não corresponde ao manifesto.');
        return false;
    }

    $target = realpath(__FILE__);
    if ($target === false || basename($target) !== 'index.php') {
        error_log('[RE9 UPDATE] Atualização automática recusada: o script ativo não se chama index.php.');
        return false;
    }
    $targetDir = dirname($target);
    if (!is_dir($targetDir) || !is_writable($targetDir)) {
        error_log('[RE9 UPDATE] A pasta da instalação não permite atualizar index.php.');
        return false;
    }
    $temp = @tempnam($targetDir, '.re9_update_');
    if ($temp === false) { error_log('[RE9 UPDATE] Não foi possível criar arquivo temporário.'); return false; }
    $written = @file_put_contents($temp, $source, LOCK_EX);
    if ($written === false || $written !== strlen($source)) { @unlink($temp); error_log('[RE9 UPDATE] Falha ao gravar pacote temporário.'); return false; }
    @chmod($temp, 0644);

    $backupDir = rtrim($DATA_DIR, '/\\\\') . DIRECTORY_SEPARATOR . 're9_index_backups';
    if (!is_dir($backupDir) && !@mkdir($backupDir, 0700, true)) { @unlink($temp); error_log('[RE9 UPDATE] Não foi possível criar pasta privada de backup.'); return false; }
    @file_put_contents($backupDir . DIRECTORY_SEPARATOR . '.htaccess', "Options -Indexes\n<IfModule mod_authz_core.c>Require all denied</IfModule>\n<IfModule !mod_authz_core.c>Deny from all</IfModule>\n", LOCK_EX);
    $backupName = 'index_' . date('Ymd_His') . '_' . substr(hash('sha256', $siteId . '|' . $newVersion . '|' . microtime(true)), 0, 10) . '.php';
    $backupPath = $backupDir . DIRECTORY_SEPARATOR . $backupName;
    if (!@copy($target, $backupPath)) { @unlink($temp); error_log('[RE9 UPDATE] Não foi possível criar backup do index.php.'); return false; }
    @chmod($backupPath, 0600);
    if (!@rename($temp, $target)) { @unlink($temp); error_log('[RE9 UPDATE] Não foi possível substituir o index.php. O backup foi preservado.'); return false; }
    @chmod($target, 0644);
    if (function_exists('opcache_invalidate')) @opcache_invalidate($target, true);

    $state['last_update_applied'] = time();
    $state['last_update_version'] = $newVersion;
    save_protected_json($CENTRAL_CLIENT_SYNC_FILE, $state);
    $report = re9_central_post_url($centralUrl, 'central_client_update_result', array(
        'site_id'=>$siteId, 'token'=>(string)get_val($APP_CONFIG, 'central_site_token', ''),
        'client_version'=>$newVersion, 'result_status'=>'ok',
        'result_message'=>'Atualização automática aplicada. Backup privado criado em webmail_data/re9_index_backups.'
    ));
    if (get_val($report, 'status') !== 'ok') error_log('[RE9 UPDATE] Arquivo atualizado para ' . $newVersion . ', mas a confirmação não chegou à Central.');
    error_log('[RE9 UPDATE] Instalação ' . $siteId . ' atualizada automaticamente para ' . $newVersion . '.');

    // Mantém apenas os cinco backups mais recentes, todos fora da área pública.
    $backups = glob($backupDir . DIRECTORY_SEPARATOR . 'index_*.php');
    if (is_array($backups) && count($backups) > 5) {
        usort($backups, function($a, $b) { return filemtime($b) - filemtime($a); });
        foreach (array_slice($backups, 5) as $oldBackup) @unlink($oldBackup);
    }
    return true;
}

if (!file_exists($SIGS_FILE)) {
    save_protected_json($SIGS_FILE, array());
}
if (!file_exists($PHONES_FILE)) {
    save_protected_json($PHONES_FILE, array());
}
if (!file_exists($IDENTITY_FILE)) {
    save_protected_json($IDENTITY_FILE, array());
}
if (!file_exists($PASSWORD_RECOVERY_FILE)) {
    save_protected_json($PASSWORD_RECOVERY_FILE, array());
}
if (!file_exists($DIRECTORY_NAMES_FILE)) {
    save_protected_json($DIRECTORY_NAMES_FILE, array());
}
if (!file_exists($SECURITY_FILE)) {
    save_protected_json($SECURITY_FILE, array());
}
if (!file_exists($ONLINE_FILE)) {
    save_protected_json($ONLINE_FILE, array());
}
if (!file_exists($PRIVATE_MESSAGES_FILE)) {
    save_protected_json($PRIVATE_MESSAGES_FILE, array());
}
if (!file_exists($CONTACTS_FILE)) {
    save_protected_json($CONTACTS_FILE, array());
}
if (!file_exists($EXTERNAL_FILE)) {
    save_protected_json($EXTERNAL_FILE, array());
}
if (!file_exists($AGENDA_FILE)) {
    save_protected_json($AGENDA_FILE, array());
}
if (!file_exists($SALES_ORDERS_FILE)) {
    save_protected_json($SALES_ORDERS_FILE, array());
}
if (!file_exists($INSTANCES_FILE)) {
    save_protected_json($INSTANCES_FILE, array());
}


function get_val($arr, $key, $default = '') {
    return isset($arr[$key]) ? $arr[$key] : $default;
}

function encrypt_ext_pass($plain) {
    global $RE9_CANONICAL_SCRIPT_PATH;
    $key = sha1((isset($RE9_CANONICAL_SCRIPT_PATH) ? $RE9_CANONICAL_SCRIPT_PATH : __FILE__) . '_re9_ext_secret_key');
    return base64_encode($plain ^ str_repeat($key, 4));
}

function decrypt_ext_pass($encoded) {
    if (empty($encoded)) return '';
    global $RE9_CANONICAL_SCRIPT_PATH;
    $key = sha1((isset($RE9_CANONICAL_SCRIPT_PATH) ? $RE9_CANONICAL_SCRIPT_PATH : __FILE__) . '_re9_ext_secret_key');
    return base64_decode($encoded) ^ str_repeat($key, 4);
}

// =========================================================================
// 1.2 MOTOR EXCLUSIVO: SOMENTE QUEM ESTÁ COM A CAIXA DE E-MAIL CONECTADA AGORA
// =========================================================================
function update_user_online_status($email) {
    global $ONLINE_FILE, $RE9_INSTANCE_HOST;
    $email_key = strtolower(trim($email));
    if (empty($email_key) || strpos($email_key, '@') === false) return;

    $onlineLock = re9_acquire_file_lock($ONLINE_FILE, LOCK_EX);
    if (!$onlineLock) return;
    $online = load_protected_json($ONLINE_FILE);
    $now = time();
    foreach ($online as $k => $info) {
        if (!is_array($info) || !isset($info['last_seen']) || ($now - (int)$info['last_seen']) > 45) unset($online[$k]);
    }

    $ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
    $is_mobile = preg_match('/(android|iphone|ipad|ipod|mobile)/i', $ua);
    $parts = explode('@', $email_key);
    $dom = isset($parts[1]) ? $parts[1] : 're9.rio.br';
    $session_mark = function_exists('session_id') ? substr(hash('sha256', session_id()), 0, 14) : 'no-session';
    $host = isset($RE9_INSTANCE_HOST) ? strtolower((string)$RE9_INSTANCE_HOST) : 'local';
    $presence_key = $email_key . '|' . $host . '|' . $session_mark;
    $previous = isset($online[$presence_key]) && is_array($online[$presence_key]) ? $online[$presence_key] : array();

    $online[$presence_key] = array(
        'email' => $email_key,
        'domain' => $dom,
        'access_host' => $host,
        'session_mark' => $session_mark,
        'last_seen' => $now,
        'ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '',
        'device' => $is_mobile ? 'Celular' : 'Computador (PC)',
        'login_time' => isset($previous['login_time']) ? $previous['login_time'] : date('H:i:s')
    );
    save_protected_json($ONLINE_FILE, $online);
    re9_release_file_lock($onlineLock);
}

function remove_user_online_status($email) {
    global $ONLINE_FILE, $RE9_INSTANCE_HOST;
    $email_key = strtolower(trim($email));
    if (empty($email_key)) return;
    $onlineLock = re9_acquire_file_lock($ONLINE_FILE, LOCK_EX);
    if (!$onlineLock) return;
    $online = load_protected_json($ONLINE_FILE);
    $host = isset($RE9_INSTANCE_HOST) ? strtolower((string)$RE9_INSTANCE_HOST) : 'local';
    $session_mark = function_exists('session_id') ? substr(hash('sha256', session_id()), 0, 14) : 'no-session';
    $changed = false;
    foreach ($online as $key => $info) {
        if (!is_array($info)) continue;
        $row_email = strtolower((string)(isset($info['email']) ? $info['email'] : explode('|', (string)$key)[0]));
        $row_host = strtolower((string)(isset($info['access_host']) ? $info['access_host'] : ''));
        $row_session = (string)(isset($info['session_mark']) ? $info['session_mark'] : '');
        if ($row_email === $email_key && (($row_host === $host && ($row_session === '' || $row_session === $session_mark)) || $key === $email_key)) {
            unset($online[$key]);
            $changed = true;
        }
    }
    if ($changed) save_protected_json($ONLINE_FILE, $online);
    re9_release_file_lock($onlineLock);
}

function get_strictly_connected_webmail_users() {
    global $ONLINE_FILE, $APP_CONFIG;
    $now = time();
    $onlineLock = re9_acquire_file_lock($ONLINE_FILE, LOCK_EX);
    if (!$onlineLock) return array('server_ip'=>!empty($APP_CONFIG['cpanel_host']) ? $APP_CONFIG['cpanel_host'] : '162.240.100.87','online_count'=>0,'users'=>array());
    $online_map = load_protected_json($ONLINE_FILE);
    $changed = false;
    $active_list = array();

    foreach ($online_map as $presence_key => $info) {
        $last_ts = is_array($info) && isset($info['last_seen']) ? (int)$info['last_seen'] : 0;
        $diff = $now - $last_ts;
        if ($last_ts <= 0 || $diff > 45) {
            unset($online_map[$presence_key]);
            $changed = true;
            continue;
        }
        $email = is_array($info) && !empty($info['email']) ? strtolower(trim((string)$info['email'])) : strtolower(trim((string)explode('|', (string)$presence_key)[0]));
        $parts = explode('@', $email);
        $dom = isset($parts[1]) ? strtolower(trim($parts[1])) : '';
        $active_list[] = array(
            'email' => $email,
            'domain' => $dom,
            'access_host' => isset($info['access_host']) ? (string)$info['access_host'] : 'domínio RE9',
            'is_online' => true,
            'seconds_ago' => max(0, $diff),
            'last_seen_fmt' => 'Conectado agora (sinal há ' . max(1, $diff) . 's)',
            'login_time' => isset($info['login_time']) ? $info['login_time'] : date('H:i:s', $last_ts),
            'ip' => isset($info['ip']) ? $info['ip'] : '-',
            'device' => isset($info['device']) ? $info['device'] : 'Webmail'
        );
    }
    if ($changed) save_protected_json($ONLINE_FILE, $online_map);
    re9_release_file_lock($onlineLock);

    // Sessões das instalações clientes vinculadas à Central Renove (CPanels independentes).
    global $RE9_IS_CENTRAL_HUB, $CENTRAL_PRESENCE_FILE;
    if (!empty($RE9_IS_CENTRAL_HUB)) {
        $remoteLock = re9_acquire_file_lock($CENTRAL_PRESENCE_FILE, LOCK_EX);
        if ($remoteLock) {
            $remoteMap = load_protected_json($CENTRAL_PRESENCE_FILE); if (!is_array($remoteMap)) $remoteMap = array();
            $remoteChanged = false;
            foreach ($remoteMap as $remoteKey => $remoteInfo) {
                $remoteSeen = is_array($remoteInfo) && isset($remoteInfo['last_seen']) ? (int)$remoteInfo['last_seen'] : 0;
                $remoteDiff = $now - $remoteSeen;
                if ($remoteSeen <= 0 || $remoteDiff > 60) { unset($remoteMap[$remoteKey]); $remoteChanged = true; continue; }
                $remoteEmail = strtolower(trim((string)get_val($remoteInfo,'email','')));
                if (!filter_var($remoteEmail,FILTER_VALIDATE_EMAIL)) continue;
                $remoteDomain = strtolower(substr(strrchr($remoteEmail,'@'),1));
                $active_list[] = array('email'=>$remoteEmail,'domain'=>$remoteDomain,'access_host'=>(string)get_val($remoteInfo,'site_id','instalação cliente'),'is_online'=>true,'seconds_ago'=>max(0,$remoteDiff),'last_seen_fmt'=>'Conectado (sinal há '.max(1,$remoteDiff).'s)','login_time'=>(string)get_val($remoteInfo,'login_time','-'),'ip'=>'-','device'=>(string)get_val($remoteInfo,'device','Webmail'),'installation_type'=>'Cliente Renove');
            }
            if ($remoteChanged) save_protected_json($CENTRAL_PRESENCE_FILE,$remoteMap);
            re9_release_file_lock($remoteLock);
        }
    }
    usort($active_list, function($a, $b) { return strcasecmp($a['email'], $b['email']); });
    return array(
        'server_ip' => !empty($APP_CONFIG['cpanel_host']) ? $APP_CONFIG['cpanel_host'] : '162.240.100.87',
        'online_count' => count($active_list),
        'users' => $active_list
    );
}

if (!empty($_SESSION['wm_email'])) {
    update_user_online_status($_SESSION['wm_email']);
}

function re9_register_instance($host) {
    global $INSTANCES_FILE;
    $host = strtolower(trim((string)$host));
    $host = preg_replace('/:\\d+$/', '', $host);
    if ($host === '' || $host === 'local' || !preg_match('/^(?:[a-z0-9-]+\\.)*[a-z0-9-]+$/i', $host)) return;
    $instanceLock = re9_acquire_file_lock($INSTANCES_FILE, LOCK_EX);
    if (!$instanceLock) return;
    $instances = load_protected_json($INSTANCES_FILE);
    if (!is_array($instances)) $instances = array();
    $now = time();
    $existing = isset($instances[$host]) && is_array($instances[$host]) ? $instances[$host] : array();
    if (isset($existing['last_seen']) && ($now - (int)$existing['last_seen']) < 300) { re9_release_file_lock($instanceLock); return; }
    foreach ($instances as $key => $info) {
        if (!is_array($info) || empty($info['last_seen']) || ($now - (int)$info['last_seen']) > 2592000) unset($instances[$key]);
    }
    $instances[$host] = array('host'=>$host, 'path'=>isset($_SERVER['SCRIPT_NAME']) ? (string)$_SERVER['SCRIPT_NAME'] : '/index.php', 'last_seen'=>$now);
    save_protected_json($INSTANCES_FILE, $instances);
    re9_release_file_lock($instanceLock);
}

function re9_get_registered_instances() {
    global $INSTANCES_FILE;
    $instances = load_protected_json($INSTANCES_FILE);
    if (!is_array($instances)) return array();
    $now = time();
    $rows = array();
    foreach ($instances as $host => $info) {
        if (!is_array($info) || empty($info['last_seen']) || ($now - (int)$info['last_seen']) > 2592000) continue;
        $rows[] = array('host'=>(string)(isset($info['host']) ? $info['host'] : $host), 'last_seen'=>(int)$info['last_seen'], 'last_seen_text'=>date('d/m/Y H:i', (int)$info['last_seen']));
    }
    usort($rows, function($a, $b) { return (int)$b['last_seen'] - (int)$a['last_seen']; });
    return $rows;
}

if (isset($RE9_INSTANCE_HOST) && $RE9_INSTANCE_HOST !== 'local') {
    re9_register_instance($RE9_INSTANCE_HOST);
}
if (!isset($_GET['api']) && !isset($_GET['central_setup']) && !isset($_GET['central_admin']) && !isset($_GET['re9_asset']) && !isset($_GET['pwa'])) { re9_central_sync_public_data(true); if (re9_central_is_client_connected()) { re9_central_process_pending_commands(); re9_central_client_report_mailboxes(false); re9_central_client_check_for_updates(); } }

// =========================================================================
// 1.5 MOTOR DO ROBÔ DE SEGURANÇA ANTI-PHISHING / ANTI-MALWARE
// =========================================================================
function extract_clean_email($from_str) {
    if (preg_match('/<([^>]+)>/', $from_str, $m)) {
        return strtolower(trim($m[1]));
    }
    if (preg_match('/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/', $from_str, $m)) {
        return strtolower(trim($m[0]));
    }
    return strtolower(trim($from_str));
}

function get_user_security_rules($user_email) {
    global $SECURITY_FILE;
    $all = load_protected_json($SECURITY_FILE);
    $key = strtolower(trim($user_email));
    if (!isset($all[$key]) || !is_array($all[$key])) {
        return array(
            'whitelist_emails' => array('suporte@re9.rio.br', 'contato@re9.rio.br', 'admin@re9.rio.br'),
            'blocked_emails'   => array(),
            'blocked_domains'  => array(),
            'blocked_ips'      => array()
        );
    }
    $entry = $all[$key];
    $normalize = function($items) {
        if (!is_array($items)) return array();
        $out = array();
        foreach ($items as $item) { $item = strtolower(trim((string)$item)); if ($item !== '' && !in_array($item, $out, true)) $out[] = $item; }
        return $out;
    };
    return array(
        'whitelist_emails' => $normalize(isset($entry['whitelist_emails']) ? $entry['whitelist_emails'] : array()),
        'blocked_emails'   => $normalize(isset($entry['blocked_emails']) ? $entry['blocked_emails'] : array()),
        'blocked_domains'  => $normalize(isset($entry['blocked_domains']) ? $entry['blocked_domains'] : array()),
        'blocked_ips'      => $normalize(isset($entry['blocked_ips']) ? $entry['blocked_ips'] : array())
    );
}

function save_user_security_rules($user_email, $rules) {
    global $SECURITY_FILE;
    $all = load_protected_json($SECURITY_FILE);
    $key = strtolower(trim($user_email));
    $all[$key] = $rules;
    return save_protected_json($SECURITY_FILE, $all);
}

function is_sender_blocked($user_email, $from_str, $sender_ip = '', $sender_server = '') {
    $rules = get_user_security_rules($user_email);
    $clean_from = extract_clean_email($from_str);
    return ($clean_from !== '' && in_array(strtolower($clean_from), $rules['blocked_emails'], true));
}

function sanitize_email_html($html) {
    $html = (string)$html;
    $html = preg_replace('~<(script|iframe|object|embed|form|input|button|textarea|select|meta|base|link|style)[^>]*>.*?</\\1\\s*>~is', '', $html);
    $html = preg_replace('~<(script|iframe|object|embed|form|input|button|textarea|select|meta|base|link|style)\\b[^>]*/?>~is', '', $html);
    $html = preg_replace("~\\s+on[a-z]+\\s*=\\s*(\"[^\"]*\"|'[^']*'|[^\\s>]+)~i", '', $html);
    $html = preg_replace("~\\s+(src|href|action|formaction)\\s*=\\s*(\"|')\\s*(javascript:|vbscript:|data:text/html)[^\"']*\\2~i", ' $1="#bloqueado-pelo-re9"', $html);

    // Preserva as imagens locais/embutidas e guarda as remotas para carregamento sob demanda.
    // Isso evita pixels de rastreamento e vazamento automático do IP, sem apagar as imagens.
    $html = preg_replace_callback('/<img\\b[^>]*>/i', function($m) {
        $tag = $m[0];
        $srcPattern = "~\\s+src\\s*=\\s*(\"[^\"]*\"|'[^']*'|[^\\s>]+)~i";
        if (!preg_match($srcPattern, $tag, $srcMatch)) {
            return preg_replace("~\\s+srcset\\s*=\\s*(\"[^\"]*\"|'[^']*'|[^\\s>]+)~i", '', $tag);
        }

        $raw = trim($srcMatch[1]);
        if (strlen($raw) >= 2 && (($raw[0] === '"' && substr($raw, -1) === '"') || ($raw[0] === "'" && substr($raw, -1) === "'"))) {
            $raw = substr($raw, 1, -1);
        }
        $src = html_entity_decode($raw, ENT_QUOTES, 'UTF-8');
        $tagWithoutSrc = preg_replace($srcPattern, '', $tag, 1);
        $tagWithoutSrc = preg_replace("~\\s+srcset\\s*=\\s*(\"[^\"]*\"|'[^']*'|[^\\s>]+)~i", '', $tagWithoutSrc);
        $tagBase = preg_replace('~\\s*/?>$~', '', $tagWithoutSrc);

        if (preg_match('~^https?://~i', $src)) {
            $safeSrc = htmlspecialchars($src, ENT_QUOTES, 'UTF-8');
            return $tagBase . ' data-re9-remote-src="' . $safeSrc . '" referrerpolicy="strict-origin-when-cross-origin" loading="lazy" decoding="async">';
        }

        $isLocalUpload = (bool)preg_match("~^(?:\\./|/)?webmail_uploads/[a-zA-Z0-9._/-]+(?:\\?[^\"'<>]*)?$~", $src);
        $isSafeDataImage = (strlen($src) <= 6000000 && (bool)preg_match('~^data:image/(?:png|jpe?g|gif|webp);base64,[a-z0-9+/=\\r\\n]+$~i', $src));
        if ($isLocalUpload || $isSafeDataImage) {
            $displaySrc = $isLocalUpload ? re9_public_image_url($src) : $src;
            $safeSrc = htmlspecialchars($displaySrc, ENT_QUOTES, 'UTF-8');
            return $tagBase . ' src="' . $safeSrc . '" referrerpolicy="strict-origin-when-cross-origin" loading="lazy" decoding="async">';
        }

        // Protocolos como javascript:, file:, blob: e cid: não são executados.
        return $tagBase . '>';
    }, $html);

    return $html;
}

function security_bot_analyze_email($user_email, $from_str, $subject_str, $body_str = '') {
    $rules = get_user_security_rules($user_email);
    $clean_from = extract_clean_email($from_str);

    if (!empty($clean_from) && in_array($clean_from, $rules['whitelist_emails'])) {
        return array('suspicious' => false, 'reasons' => array(), 'trusted' => true);
    }

    $reasons = array();
    $text_to_scan = mb_strtolower($subject_str . ' ' . strip_tags($body_str), 'UTF-8');

    $phishing_phrases = array(
        'atualize seu webmail'       => 'Tentativa de golpe pedindo atualização de Webmail',
        'atualizar seu webmail'      => 'Tentativa de golpe pedindo atualização de Webmail',
        'atualize sua caixa'         => 'Tentativa de golpe pedindo atualização de caixa de entrada',
        'trocar de senha'            => 'Solicitação suspeita para troca de senha',
        'troque sua senha'           => 'Solicitação suspeita para troca de senha',
        'atualize sua senha'         => 'Solicitação suspeita para atualização de senha',
        'redefinir sua senha'        => 'Solicitação suspeita de redefinição de senha',
        'anomalia'                   => 'Alegação falsa de anomalia na conta de e-mail',
        'atividade incomum'          => 'Alegação suspeita de atividade incomum',
        'clique aqui para trocar'    => 'Indução direta a clique para alteração de credenciais',
        'clique aqui para atualizar' => 'Indução direta a clique para suposta atualização',
        'clique aqui para validar'   => 'Indução direta a clique para suposta validação',
        'clique aqui para confirmar' => 'Indução direta a clique para confirmação',
        'conta sera suspensa'        => 'Ameaça falsa de suspensão de conta',
        'conta será suspensa'        => 'Ameaça falsa de suspensão de conta',
        'e-mail sera desativado'     => 'Ameaça falsa de desativação de e-mail',
        'email será desativado'      => 'Ameaça falsa de desativação de e-mail',
        'cota excedida'              => 'Golpe de falsa cota de armazenamento cheia',
        'armazenamento cheio'        => 'Golpe de falso limite de armazenamento',
        'evitar o bloqueio'          => 'Coerção para clicar em link sob ameaça de bloqueio',
        'confirme seus dados'        => 'Tentativa de coleta de dados (Phishing)',
        'falha na entrega'           => 'Possível isca de vírus simulando erro de entrega',
        'comprovante anexo'          => 'Possível isca financeira maliciosa',
        'fatura vencida'             => 'Possível isca de boleto/link falso',
        'intimacao'                  => 'Possível isca jurídica maliciosa',
        'intimação'                  => 'Possível isca jurídica maliciosa'
    );

    foreach ($phishing_phrases as $phrase => $reason_desc) {
        if (strpos($text_to_scan, $phrase) !== false) {
            $reasons[] = $reason_desc . ' ("' . $phrase . '")';
        }
    }

    if (!empty($body_str)) {
        $has_links = preg_match('/<a\s+[^>]*href=["\']([^"\']+)["\']/i', $body_str) || preg_match('/https?:\/\/[^\s<>"\']+/i', $body_str);

        if (preg_match('/https?:\/\/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i', $body_str)) {
            $reasons[] = 'Contém link apontando para um endereço IP numérico oculto (Alto Risco)';
        }
        if (preg_match('/https?:\/\/(bit\.ly|tinyurl\.com|cutt\.ly|is\.gd|t\.co|rb\.gy|rebrand\.ly)\//i', $body_str)) {
            $reasons[] = 'Contém link encurtado que esconde o endereço real de destino';
        }
        if (stripos($body_str, '<form') !== false || stripos($body_str, '<input') !== false) {
            $reasons[] = 'Contém formulário embutido tentando capturar senhas dentro do e-mail';
        }
        if (preg_match('/\.(exe|scr|bat|cmd|vbs|msi|jar|ps1)(\?|"|\'|\s|$)/i', $body_str)) {
            $reasons[] = 'Referência a arquivo executável potencialmente infectado (.exe/.scr/.bat)';
        }
        if ($has_links && preg_match('/(urgente|imediato|bloqueio|senha|webmail|cpanel|atualiz|clique|acione|procedimento)/i', $text_to_scan)) {
            if (empty($reasons)) {
                $reasons[] = 'Mensagem contém links externos combinados com termos de manutenção/senha';
            }
        }
    }

    if (preg_match('/(webmail|suporte|admin|cpanel|seguranca|equipe|segurança)/iu', $from_str) && strpos($clean_from, '@re9.rio.br') === false) {
        $reasons[] = 'Remetente externo tentando se passar por suporte técnico / administrador';
    }
    if (!empty($body_str)) {
        if (preg_match_all('/<a\\b[^>]*href=\"([^\"]+)\"[^>]*>(.*?)<\\/a>/is', $body_str, $link_matches, PREG_SET_ORDER)) {
            foreach ($link_matches as $link) {
                $href = html_entity_decode(trim($link[1]), ENT_QUOTES, 'UTF-8');
                $label = trim(strip_tags($link[2]));
                if (preg_match('/^(javascript|data|vbscript):/i', $href)) $reasons[] = 'Link usa protocolo executável ou conteúdo embutido';
                if (preg_match('/^http:\\/\\//i', $href)) $reasons[] = 'Link externo sem HTTPS';
                if ($label !== '' && preg_match('/^[a-z0-9.-]+\\.[a-z]{2,}(\\/.*)?$/i', $label) && stripos($href, $label) === false) $reasons[] = 'Texto exibido no link não corresponde ao endereço real de destino';
                if (preg_match('/@|%40/', $href) && preg_match('/https?:\\/\\//i', $href)) $reasons[] = 'Link contém padrão de usuário/senha ou redirecionamento disfarçado';
            }
        }
        if (preg_match('/https?:\\/\\/[^[:space:]\"]{0,250}(login|signin|verify|secure|account|password|webmail)[^[:space:]\"]*/i', $body_str) && preg_match('/(senha|password|login|validar|confirmar|bloqueio|urgente)/i', $text_to_scan)) $reasons[] = 'Link de autenticação combinado com pedido urgente de credenciais';
        if (preg_match('/https?:\\/\\/[^[:space:]\"]*(xn--|%[0-9a-f]{2})/i', $body_str)) $reasons[] = 'Link contém domínio internacionalizado ou codificação que pode ocultar o destino';
        if (preg_match('/<img[^>]+(?:width=\"?1|height=\"?1|display\\s*:\\s*none)/i', $body_str)) $reasons[] = 'Mensagem contém pixel de rastreamento oculto';
    }

    return array(
        'suspicious' => !empty($reasons),
        'reasons'    => array_values(array_unique($reasons)),
        'trusted'    => false
    );
}

function validate_strong_password($pass) {
    if (strlen($pass) < 8) {
        return 'A senha deve ter no mínimo 8 caracteres.';
    }
    if (!preg_match('/[A-Z]/', $pass)) {
        return 'A senha precisa ter pelo menos 1 letra MAIÚSCULA (A-Z).';
    }
    if (!preg_match('/[a-z]/', $pass)) {
        return 'A senha precisa ter pelo menos 1 letra minúscula (a-z).';
    }
    if (!preg_match('/[0-9]/', $pass)) {
        return 'A senha precisa ter pelo menos 1 número (0-9).';
    }
    if (!preg_match('/[^a-zA-Z0-9]/', $pass)) {
        return 'A senha precisa ter pelo menos 1 símbolo especial (Ex: @ # $ % ! * &).';
    }
    return '';
}

function translate_cpanel_error($err_msg) {
    $lower = strtolower($err_msg);
    if (strpos($lower, 'password') !== false && (strpos($lower, 'strength') !== false || strpos($lower, 'weak') !== false || strpos($lower, 'minimum') !== false)) {
        return 'A senha escolhida ainda é considerada fraca pelo servidor. Use pelo menos 8 caracteres misturando Letras Maiúsculas, minúsculas, números e símbolos (Ex: @, #, !).';
    }
    if (strpos($lower, 'already exists') !== false || strpos($lower, 'taken') !== false) {
        return 'Este nome de e-mail já está cadastrado! Por favor, escolha outro nome de usuário.';
    }
    if (strpos($lower, 'invalid') !== false && strpos($lower, 'user') !== false) {
        return 'Nome de usuário inválido. Utilize apenas letras, números, ponto ou traço.';
    }
    if (strpos($lower, 'quota') !== false) {
        return 'Limite de espaço da hospedagem atingido.';
    }
    return 'Não foi possível concluir a solicitação. Verifique se a senha é forte (com letras maiúsculas, números e símbolos) ou tente outro nome de e-mail.';
}

function re9_login_throttle($email, $ip, $success = false) {
    global $LOGIN_ATTEMPTS_FILE;
    $records = load_protected_json($LOGIN_ATTEMPTS_FILE);
    if (!is_array($records)) $records = array();
    $ip = (string)$ip;
    $email = strtolower(trim((string)$email));
    $ip_key = 'ip_' . hash('sha256', $ip);
    $account_key = 'account_' . hash('sha256', $ip . '|' . $email);
    $now = time();
    foreach (array($ip_key, $account_key) as $key) {
        if (isset($records[$key]) && (!is_array($records[$key]) || (int)get_val($records[$key], 'window', 0) < $now - 900)) unset($records[$key]);
    }
    $blocked_until = max((int)get_val(isset($records[$ip_key]) ? $records[$ip_key] : array(), 'blocked_until', 0), (int)get_val(isset($records[$account_key]) ? $records[$account_key] : array(), 'blocked_until', 0));
    if ($success === true) {
        unset($records[$account_key]);
        unset($records[$ip_key]);
        save_protected_json($LOGIN_ATTEMPTS_FILE, $records);
        return array('blocked' => false, 'retry_after' => 0);
    }
    if ($blocked_until > $now) return array('blocked' => true, 'retry_after' => $blocked_until - $now);
    if ($success === 'check') return array('blocked' => false, 'retry_after' => 0);
    foreach (array($ip_key => 25, $account_key => 8) as $key => $limit) {
        $row = isset($records[$key]) && is_array($records[$key]) ? $records[$key] : array('window' => $now, 'count' => 0, 'blocked_until' => 0);
        if ((int)get_val($row, 'window', 0) < $now - 900) $row = array('window' => $now, 'count' => 0, 'blocked_until' => 0);
        $row['count'] = (int)get_val($row, 'count', 0) + 1;
        if ($row['count'] >= $limit) $row['blocked_until'] = $now + 900;
        $records[$key] = $row;
    }
    save_protected_json($LOGIN_ATTEMPTS_FILE, $records);
    $blocked_until = max((int)get_val($records[$ip_key], 'blocked_until', 0), (int)get_val($records[$account_key], 'blocked_until', 0));
    return array('blocked' => $blocked_until > $now, 'retry_after' => max(0, $blocked_until - $now));
}

function set_session_credentials($email, $pass) {
    if (session_status() === PHP_SESSION_ACTIVE) @session_regenerate_id(true);
    if (empty($_SESSION['wm_cipher_key'])) {
        $_SESSION['wm_cipher_key'] = md5(uniqid(mt_rand(), true));
    }
    $_SESSION['wm_email'] = $email;
    $_SESSION['wm_pass']  = base64_encode($pass ^ str_repeat($_SESSION['wm_cipher_key'], 4));
}

function get_session_password() {
    if (empty($_SESSION['wm_pass']) || empty($_SESSION['wm_cipher_key'])) return '';
    $raw = base64_decode($_SESSION['wm_pass']);
    return $raw ^ str_repeat($_SESSION['wm_cipher_key'], 4);
}

function is_user_admin() {
    global $APP_CONFIG;
    if (empty($_SESSION['wm_email'])) return false;
    if (!empty($_SESSION['wm_is_admin'])) return true;

    $email = strtolower(trim($_SESSION['wm_email']));
    $admins = isset($APP_CONFIG['admin_emails']) && is_array($APP_CONFIG['admin_emails']) ? $APP_CONFIG['admin_emails'] : array();
    foreach ($admins as $adm) {
        if (strtolower(trim($adm)) === $email) {
            $_SESSION['wm_is_admin'] = true;
            return true;
        }
    }
    if (isset($_GET['admin']) && $_GET['admin'] == '1') {
        $_SESSION['wm_is_admin'] = true;
        return true;
    }
    return false;
}

function re9_admin_password_matches($provided) {
    global $APP_CONFIG;
    $stored = isset($APP_CONFIG['admin_pass']) ? (string)$APP_CONFIG['admin_pass'] : '';
    $provided = is_scalar($provided) ? (string)$provided : '';
    // Remove apenas espaços acidentais nas extremidades, comuns em copiar/colar.
    $stored = trim($stored);
    $provided = trim($provided);
    return ($stored !== '' && $provided !== '' && hash_equals($stored, $provided));
}

/** Envia a mensagem de boas-vindas após a liberação administrativa. */
function re9_send_member_welcome($email, $display_name = '') {
    global $APP_CONFIG, $DIRECTORY_NAMES_FILE, $IDENTITY_FILE;
    $email = strtolower(trim((string)$email));
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) return array('ok'=>false, 'message'=>'Endereço do novo membro inválido.');
    $identities = load_protected_json($IDENTITY_FILE);
    if (isset($identities[$email]['welcome_email_sent_at']) && !empty($identities[$email]['welcome_email_sent_at'])) {
        return array('ok'=>true, 'already'=>true, 'message'=>'A mensagem de boas-vindas já havia sido enviada anteriormente.');
    }
    $names = load_protected_json($DIRECTORY_NAMES_FILE);
    if ($display_name === '' && isset($names[$email])) $display_name = (string)$names[$email];
    if ($display_name === '' && isset($identities[$email]['name'])) $display_name = (string)$identities[$email]['name'];
    $display_name = trim(strip_tags((string)$display_name));
    if ($display_name === '') $display_name = 'novo membro';
    $safe_name = htmlspecialchars($display_name, ENT_QUOTES, 'UTF-8');
    $safe_email = htmlspecialchars($email, ENT_QUOTES, 'UTF-8');

    $https = (!empty($_SERVER['HTTPS']) && strtolower((string)$_SERVER['HTTPS']) !== 'off') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower((string)$_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https');
    $scheme = $https ? 'https://' : 'http://';
    $host = isset($_SERVER['HTTP_HOST']) ? preg_replace('/[^a-zA-Z0-9.:-]/', '', (string)$_SERVER['HTTP_HOST']) : 're9.rio.br';
    $script = isset($_SERVER['SCRIPT_NAME']) ? str_replace('\\', '/', (string)$_SERVER['SCRIPT_NAME']) : '/webmail9/index20.php';
    $login_url = $scheme . $host . $script;
    $safe_url = htmlspecialchars($login_url, ENT_QUOTES, 'UTF-8');

    $subject_text = 'Bem-vindo ao Renove Mail! Sua conta está liberada';
    $subject = '=?UTF-8?B?' . base64_encode($subject_text) . '?=';
    $html = '<!doctype html><html lang="pt-BR"><head><meta charset="UTF-8"></head><body style="margin:0;background:#f1f5f9;font-family:Arial,sans-serif;color:#172033">'
        . '<div style="max-width:680px;margin:24px auto;background:#fff;border-radius:18px;overflow:hidden;border:1px solid #e2e8f0">'
        . '<div style="background:#002244;padding:30px 26px;text-align:center;color:#fff"><div style="font-size:30px;font-weight:900;letter-spacing:1px"><span style="color:#f28c38">Renove</span> Mail</div><div style="margin-top:8px;font-size:13px;color:#dbeafe">Seu e-mail corporativo, sua comunicação e sua comunidade em um só lugar</div></div>'
        . '<div style="padding:28px 26px"><h1 style="margin:0 0 14px;color:#002244;font-size:25px">Olá, '.$safe_name.'! Seja muito bem-vindo ao Renove Mail!</h1>'
        . '<p style="font-size:15px;line-height:1.7">É uma alegria ter você com a gente! Sua conta <strong>'.$safe_email.'</strong> foi liberada pela nossa equipe. A partir de agora, você faz parte da comunidade Renove Mail: um espaço para se comunicar, organizar sua rotina e contar com recursos pensados para tornar seu dia a dia mais simples e seguro.</p>'
        . '<h2 style="font-size:18px;color:#002244;margin:26px 0 12px">Conheça o que você pode utilizar</h2>'
        . '<div style="border:1px solid #e2e8f0;border-radius:12px;padding:16px;margin:10px 0"><strong>✉️ E-mail profissional</strong><br><span style="font-size:14px;line-height:1.6;color:#475569">Envie, receba, responda, encaminhe e organize suas mensagens em pastas, com recursos de pesquisa e gerenciamento.</span></div>'
        . '<div style="border:1px solid #e2e8f0;border-radius:12px;padding:16px;margin:10px 0"><strong>📅 Agenda inteligente</strong><br><span style="font-size:14px;line-height:1.6;color:#475569">Cadastre compromissos, organize horários e configure lembretes por e-mail para não perder seus compromissos.</span></div>'
        . '<div style="border:1px solid #e2e8f0;border-radius:12px;padding:16px;margin:10px 0"><strong>👥 Contatos e rede RE9</strong><br><span style="font-size:14px;line-height:1.6;color:#475569">Cadastre e consulte contatos e encontre outros membros da rede RE9 para facilitar sua comunicação.</span></div>'
        . '<div style="border:1px solid #e2e8f0;border-radius:12px;padding:16px;margin:10px 0"><strong>💬 Mensagens privadas</strong><br><span style="font-size:14px;line-height:1.6;color:#475569">Converse diretamente com outros usuários RE9. As mensagens ficam registradas para que o destinatário possa consultá-las mesmo quando estiver offline.</span></div>'
        . '<div style="border:1px solid #e2e8f0;border-radius:12px;padding:16px;margin:10px 0"><strong>🛡️ Anti-Golpe — robô de proteção inteligente</strong><br><span style="font-size:14px;line-height:1.6;color:#475569">Nosso robô de segurança analisa mensagens e identifica sinais de phishing, tentativas de fraude e links suspeitos. Quando uma mensagem apresenta risco, os links podem ficar protegidos contra cliques acidentais. Se você estiver aguardando aquele e-mail e reconhecer a origem, poderá revisar o aviso e liberar o acesso ao link conscientemente. Na dúvida, não clique: fale com nosso suporte.</span></div>'
        . '<div style="border:1px solid #e2e8f0;border-radius:12px;padding:16px;margin:10px 0"><strong>🔐 Segurança e controle da conta</strong><br><span style="font-size:14px;line-height:1.6;color:#475569">Conte com recursos de proteção, recuperação de senha por e-mail secundário e ferramentas para gerenciar suas mensagens e sua conta.</span></div>'
        . '<div style="border:1px solid #e2e8f0;border-radius:12px;padding:16px;margin:10px 0"><strong>🛍️ Central de vendas e anúncios</strong><br><span style="font-size:14px;line-height:1.6;color:#475569">Acesse a área de anúncios e a vitrine de produtos integrada à plataforma, quando disponível para sua conta.</span></div>'
        . '<div style="margin:24px 0;padding:20px;border-radius:14px;background:#fff7ed;border:1px solid #fdba74"><div style="font-size:18px;font-weight:900;color:#9a3412">🤝 Suporte humano avançado da equipe Renove Mail</div><p style="margin:9px 0 0;font-size:15px;line-height:1.65;color:#7c2d12"><strong>Você não está sozinho nessa jornada.</strong> Nossa equipe oferece suporte humano avançado, 24 horas por dia, para orientar você e ajudar com a utilização da plataforma. Sempre que precisar, entre em contato conosco. Será um prazer ajudar!</p></div>'
        . '<div style="text-align:center;margin:28px 0 18px"><a href="'.$safe_url.'" style="display:inline-block;background:#f28c38;color:#172033;text-decoration:none;font-weight:900;padding:15px 28px;border-radius:10px">ABRIR MINHA CAIXA DE E-MAIL</a></div>'
        . '<p style="font-size:13px;line-height:1.6;color:#64748b">Para entrar, utilize seu endereço RE9 e a senha que você cadastrou. Por segurança, este link abre a página oficial de acesso e não inclui sua senha.</p>'
        . '<p style="font-size:12px;color:#94a3b8;border-top:1px solid #e2e8f0;padding-top:18px;margin-top:24px">Uma mensagem de boas-vindas do Renove Mail — seu e-mail corporativo.</p></div></div></body></html>';
    $from = 'suporte@re9.rio.br';
    $headers = "MIME-Version: 1.0\r\n" . "Content-Type: text/html; charset=UTF-8\r\n" . 'From: RE9 EMAIL <'.$from.">\r\n" . 'Reply-To: '.$from."\r\n" . "X-Mailer: RE9 EMAIL\r\n";
    $warning = '';
    set_error_handler(function($severity, $message) use (&$warning) { if ($severity === E_WARNING) { $warning = (string)$message; return true; } return false; }, E_WARNING);
    $sent = @mail($email, $subject, $html, $headers, '-f'.$from);
    restore_error_handler();
    if (!$sent) {
        error_log('[RE9 WELCOME] Falha ao enviar boas-vindas para '.$email.': '.($warning !== '' ? $warning : 'mail() retornou false'));
        return array('ok'=>false, 'message'=>'A conta foi liberada, mas o servidor não confirmou o envio do e-mail de boas-vindas.');
    }
    if (!isset($identities[$email]) || !is_array($identities[$email])) $identities[$email] = array();
    $identities[$email]['welcome_email_sent_at'] = time();
    save_protected_json($IDENTITY_FILE, $identities);
    return array('ok'=>true, 'message'=>'Mensagem de boas-vindas enviada para '.$email.'.');
}

function handle_image_upload($file_key, $prefix) {
    global $UPLOAD_DIR;
    if (!isset($_FILES[$file_key]) || $_FILES[$file_key]['error'] !== UPLOAD_ERR_OK) {
        return false;
    }
    $tmp_name  = $_FILES[$file_key]['tmp_name'];
    $orig_name = $_FILES[$file_key]['name'];
    $ext       = strtolower(pathinfo($orig_name, PATHINFO_EXTENSION));
    $allowed   = array('jpg', 'jpeg', 'png', 'gif', 'webp', 'jfif', 'bmp');
    if (!in_array($ext, $allowed)) return false;
    $image_info = @getimagesize($tmp_name);
    $allowed_mimes = array('image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/bmp');
    if (!$image_info || empty($image_info['mime']) || !in_array(strtolower($image_info['mime']), $allowed_mimes, true)) return false;
    $new_filename = $prefix . '_' . time() . '_' . rand(1000, 9999) . '.' . $ext;
    $dest = $UPLOAD_DIR . '/' . $new_filename;
    if (@move_uploaded_file($tmp_name, $dest)) {
        @chmod($dest, 0644);
        return 'webmail_uploads/' . $new_filename;
    }
    return false;
}

// =========================================================================
// 1.8 MOTOR DE ASSINATURA EXECUTIVA (PADRÃO FUNDO BRANCO + FOTO REDONDA GRANDE)
// =========================================================================
function get_webmail_base_url() {
    $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 're9.rio.br';
    $is_local = (strpos($host, 'localhost') !== false || strpos($host, '127.0.0.1') !== false);
    $proto = $is_local ? 'http' : 'https';
    $dir = rtrim(str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'])), '/');
    return $proto . '://' . $host . ($dir ? $dir . '/' : '/');
}

function normalize_signature_images($html) {
    $base = get_webmail_base_url();
    return preg_replace_callback('#src=["\']([^"\']*webmail_uploads/[^"\']+)["\']#i', function($m) use ($base) {
        $resolved = re9_public_image_url($m[1]);
        if (strpos($resolved, 'http://') !== 0 && strpos($resolved, 'https://') !== 0 && strpos($resolved, '//') !== 0) {
            $resolved = $base . ltrim($resolved, '/');
        }
        return 'src="' . htmlspecialchars($resolved, ENT_QUOTES, 'UTF-8') . '"';
    }, (string)$html);
}

function format_br_phone($raw_phone) {
    $digits = preg_replace('/\D/', '', $raw_phone);
    if (strlen($digits) === 11) {
        return '(' . substr($digits, 0, 2) . ') ' . substr($digits, 2, 5) . '-' . substr($digits, 7, 4);
    }
    if (strlen($digits) === 10) {
        return '(' . substr($digits, 0, 2) . ') ' . substr($digits, 2, 4) . '-' . substr($digits, 6, 4);
    }
    return trim($raw_phone);
}

function build_clean_signature_html($email, $nome = '', $cargo = '', $zap = '', $site = '', $logo_url = '') {
    $base_url = get_webmail_base_url();
    $display_name = trim($nome) !== '' ? trim($nome) : $email;
    if ($display_name === $email && preg_match('/^([^@]+)/', $email, $m_user)) {
        $display_name = ucwords(str_replace(array('.', '_', '-'), ' ', $m_user[1]));
    }
    $display_role = trim($cargo) !== '' ? trim($cargo) : 'Atendimento Corporativo';
    $display_site = trim($site) !== '' ? trim($site) : 'www.re9seusite.com.br';

    if (!empty($logo_url) && strpos($logo_url, 'via.placeholder.com') === false) {
        if (strpos($logo_url, 'http') !== 0 && strpos($logo_url, 'data:') !== 0) {
            $logo_url = $base_url . ltrim($logo_url, '/');
        }
        $logo_url = preg_replace('/^http:\/\/(?!localhost|127\.0\.0\.1)/i', 'https://', $logo_url);
        $avatar_html = '<img src="' . htmlspecialchars($logo_url) . '" width="125" height="125" style="width:125px;height:125px;min-width:125px;border-radius:50%;object-fit:cover;display:block;border:0;" alt="Foto">';
    } else {
        $initial = strtoupper(substr($display_name, 0, 1));
        $avatar_html = '<div style="width:125px;height:225px;border-radius:50%;background:#2d3b36;color:#ffffff;text-align:center;line-height:125px;font-weight:700;font-size:48px;font-family:\'Segoe UI\',Helvetica,Arial,sans-serif;">' . htmlspecialchars($initial) . '</div>';
    }

    $html  = '<br><br><!-- SIG_CLEAN_V4 -->'
           . '<table cellpadding="0" cellspacing="0" border="0" style="font-family:\'Segoe UI\',-apple-system,BlinkMacSystemFont,Roboto,Helvetica,Arial,sans-serif;background:#ffffff;padding:1px 6px;border-collapse:collapse;">'
           . '<tr>'
           . '<td style="vertical-align:middle;padding-right:26px;">'
           . $avatar_html
           . '</td>'
           . '<td style="vertical-align:middle;background:#ffffff;text-align:left;">'
           . '<div style="font-size:21px;font-weight:800;color:#2d3b36;line-height:1.2;margin:0 0 3px 0;letter-spacing:-0.2px;">' . htmlspecialchars($display_name) . '</div>'
           . '<div style="font-size:15px;font-weight:400;color:#4a5568;line-height:1.3;margin:0 0 14px 0;">' . htmlspecialchars($display_role) . '</div>'
           . '<table cellpadding="0" cellspacing="0" border="0" style="font-size:14px;color:#334155;border-collapse:collapse;">';

    if (!empty($zap)) {
        $clean_zap = preg_replace('/\D/', '', $zap);
        $fmt_zap   = format_br_phone($zap);
        $html .= '<tr>'
               . '<td style="padding:4px 10px 4px 0;vertical-align:middle;width:20px;"><img src="https://img.icons8.com/ios-filled/50/2d3b36/phone.png" width="16" height="16" style="display:block;border:0;" alt="Tel"></td>'
               . '<td style="padding:4px 0;vertical-align:middle;"><a href="https://wa.me/55' . $clean_zap . '" target="_blank" style="color:#334155;text-decoration:none;">' . htmlspecialchars($fmt_zap) . '</a></td>'
               . '</tr>';
    }

    $html .= '<tr>'
           . '<td style="padding:4px 10px 4px 0;vertical-align:middle;width:20px;"><img src="https://img.icons8.com/ios-filled/50/2d3b36/mail.png" width="16" height="16" style="display:block;border:0;" alt="E-mail"></td>'
           . '<td style="padding:4px 0;vertical-align:middle;"><a href="mailto:' . htmlspecialchars($email) . '" style="color:#334155;text-decoration:none;">' . htmlspecialchars($email) . '</a></td>'
           . '</tr>';

    if (!empty($display_site)) {
        $formatted_site = (strpos($display_site, 'http') === 0) ? $display_site : 'https://' . $display_site;
        $clean_site_label = preg_replace('#^https?://#i', '', $formatted_site);
        $html .= '<tr>'
               . '<td style="padding:4px 10px 4px 0;vertical-align:middle;width:20px;"><img src="https://img.icons8.com/ios-filled/50/2d3b36/globe--v1.png" width="16" height="16" style="display:block;border:0;" alt="Site"></td>'
               . '<td style="padding:4px 0;vertical-align:middle;"><a href="' . htmlspecialchars($formatted_site) . '" target="_blank" style="color:#334155;text-decoration:none;">' . htmlspecialchars($clean_site_label) . '</a></td>'
               . '</tr>';
    }

    $html .= '</table>'
           . '</td>'
           . '</tr>'
           . '</table>';

    return $html;
}

function get_user_signature($email) {
    global $SIGS_FILE;
    $sigs = load_protected_json($SIGS_FILE);

    if (is_array($sigs) && !empty($sigs[$email])) {
        $entry = $sigs[$email];

        if (is_array($entry)) {
            return build_clean_signature_html(
                $email,
                isset($entry['nome']) ? $entry['nome'] : '',
                isset($entry['cargo']) ? $entry['cargo'] : '',
                isset($entry['zap']) ? $entry['zap'] : '',
                isset($entry['site']) ? $entry['site'] : '',
                isset($entry['logo']) ? $entry['logo'] : ''
            );
        }

        if (is_string($entry)) {
            // Se já estiver no modelo novo V4, apenas normaliza a URL da foto
            if (strpos($entry, '<!-- SIG_CLEAN_V4 -->') !== false) {
                return normalize_signature_images($entry);
            }

            // Converte automaticamente assinaturas antigas salvas para o novo modelo limpo da imagem
            $old_logo = '';
            if (preg_match('/src=["\']([^"\']*webmail_uploads\/user_logo_[^"\']+)["\']/i', $entry, $m_img)) {
                $old_logo = $m_img[1];
            }
            $old_name = '';
            if (preg_match('/font-size:(?:15|17|19|21)px;font-weight:[78]00;color:#[0-9a-fA-F]+;[^>]*>([^<]+)<\/div>/i', $entry, $m_nm)) {
                $old_name = html_entity_decode(trim($m_nm[1]), ENT_QUOTES, 'UTF-8');
            }
            $old_role = '';
            if (preg_match('/(?:letter-spacing:0\.5px|letter-spacing:1px|color:#4a5568)[^>]*>([^<]+)<\/div>/i', $entry, $m_rl)) {
                $old_role = html_entity_decode(trim($m_rl[1]), ENT_QUOTES, 'UTF-8');
            }
            $old_zap = '';
            if (preg_match('/wa\.me\/55(\d+)/i', $entry, $m_zp)) {
                $old_zap = $m_zp[1];
            }
            $old_site = 'www.re9seusite.com.br';
            if (preg_match_all('/href=["\'](https?:\/\/[^"\']+)["\']/i', $entry, $m_links)) {
                foreach ($m_links[1] as $lnk) {
                    if (strpos($lnk, 'wa.me') === false && strpos($lnk, 'flaticon') === false && strpos($lnk, 'icons8') === false) {
                        $old_site = preg_replace('#^https?://#i', '', $lnk);
                        break;
                    }
                }
            }

            $upgraded_html = build_clean_signature_html($email, $old_name, $old_role, $old_zap, $old_site, $old_logo);
            $sigs[$email] = array(
                'nome'  => $old_name,
                'cargo' => $old_role,
                'zap'   => $old_zap,
                'site'  => $old_site,
                'logo'  => $old_logo,
                'html'  => $upgraded_html
            );
            save_protected_json($SIGS_FILE, $sigs);
            return $upgraded_html;
        }
    }

    return build_clean_signature_html($email);
}

function save_user_signature($email, $html_or_data) {
    global $SIGS_FILE;
    $sigs = load_protected_json($SIGS_FILE);
    $sigs[$email] = is_string($html_or_data) ? normalize_signature_images($html_or_data) : $html_or_data;
    return save_protected_json($SIGS_FILE, $sigs);
}

function decode_mime_header_str($str) {
    if (empty($str)) return '';
    if (function_exists('mb_decode_mimeheader')) {
        $res = @mb_decode_mimeheader($str);
        if (!empty($res)) return $res;
    }
    if (preg_match_all('/=\?([^\?]+)\?([BQbq])\?([^\?]+)\?=/i', $str, $matches, PREG_SET_ORDER)) {
        foreach ($matches as $m) {
            $charset = strtoupper($m[1]);
            $enc     = strtoupper($m[2]);
            $data    = $m[3];
            $dec     = ($enc === 'B') ? base64_decode($data) : quoted_printable_decode(str_replace('_', ' ', $data));
            if ($charset !== 'UTF-8' && function_exists('iconv')) {
                $conv = @iconv($charset, 'UTF-8//IGNORE', $dec);
                if ($conv !== false) $dec = $conv;
            }
            $str = str_replace($m[0], $dec, $str);
        }
    }
    return $str;
}

function classify_email_date_group($ts) {
    if (!$ts || $ts <= 0) return 'Mais Antigas';
    $today_start      = strtotime('today');
    $yesterday_start  = strtotime('yesterday');
    $week_start       = strtotime('-7 days', $today_start);
    $this_month_start = strtotime(date('Y-m-01 00:00:00'));
    $last_month_start = strtotime(date('Y-m-01 00:00:00', strtotime('first day of last month')));
    $this_year_start  = strtotime(date('Y-01-01 00:00:00'));

    if ($ts >= $today_start) {
        return 'Hoje';
    } elseif ($ts >= $yesterday_start) {
        return 'Ontem';
    } elseif ($ts >= $week_start) {
        return 'Esta Semana';
    } elseif ($ts >= $this_month_start) {
        return 'Este Mês';
    } elseif ($ts >= $last_month_start) {
        return 'Mês Passado';
    } elseif ($ts >= $this_year_start) {
        return 'Este Ano';
    } else {
        return 'Ano Passado / Antigas';
    }
}

function re9_valid_cpf($cpf) {
    $cpf = preg_replace('/\D/', '', (string)$cpf);
    if (strlen($cpf) !== 11 || preg_match('/^(\d)\1{10}$/', $cpf)) return false;
    for ($t = 9; $t < 11; $t++) {
        $sum = 0;
        for ($i = 0; $i < $t; $i++) $sum += (int)$cpf[$i] * (($t + 1) - $i);
        $digit = ((10 * $sum) % 11) % 10;
        if ((int)$cpf[$t] !== $digit) return false;
    }
    return true;
}

function re9_datavalid_access_token() {
    global $APP_CONFIG;
    if (!function_exists('curl_init')) return array('ok'=>false, 'msg'=>'O servidor não possui cURL habilitado para consultar o Datavalid.');
    $key = trim(get_val($APP_CONFIG, 'datavalid_consumer_key'));
    $secret = trim(get_val($APP_CONFIG, 'datavalid_consumer_secret'));
    if ($key === '' || $secret === '') return array('ok'=>false, 'msg'=>'A integração Datavalid ainda não foi configurada na Central Admin.');
    if (!empty($_SESSION['re9_datavalid_token']) && !empty($_SESSION['re9_datavalid_token_exp']) && (int)$_SESSION['re9_datavalid_token_exp'] > time() + 60) {
        return array('ok'=>true, 'token'=>$_SESSION['re9_datavalid_token']);
    }
    $ch = curl_init('https://gateway.apiserpro.serpro.gov.br/token');
    curl_setopt_array($ch, array(
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => 'grant_type=client_credentials',
        CURLOPT_HTTPHEADER => array('Authorization: Basic ' . base64_encode($key . ':' . $secret), 'Content-Type: application/x-www-form-urlencoded', 'Accept: application/json'),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 20,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2
    ));
    $raw = curl_exec($ch);
    $http = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $err = curl_error($ch);
    curl_close($ch);
    $json = is_string($raw) ? json_decode($raw, true) : null;
    if ($err !== '' || $http < 200 || $http >= 300 || !is_array($json) || empty($json['access_token'])) {
        return array('ok'=>false, 'msg'=>'Não foi possível autenticar no Datavalid. Confira as credenciais Serpro e a contratação do serviço.');
    }
    $_SESSION['re9_datavalid_token'] = $json['access_token'];
    $_SESSION['re9_datavalid_token_exp'] = time() + (isset($json['expires_in']) ? max(120, (int)$json['expires_in'] - 90) : 3300);
    return array('ok'=>true, 'token'=>$json['access_token']);
}

function re9_datavalid_validate_identity($cpf, $full_name) {
    global $APP_CONFIG;
    $template = trim(get_val($APP_CONFIG, 'datavalid_template_id'));
    $gccToken = trim(get_val($APP_CONFIG, 'datavalid_gcc_token'));
    $cnpj = preg_replace('/\D/', '', get_val($APP_CONFIG, 'datavalid_cnpj_anuente'));
    if ($template === '' || $gccToken === '' || strlen($cnpj) !== 14) {
        return array('ok'=>false, 'msg'=>'A configuração Datavalid está incompleta. Informe o template RFB, o token de autorização da GCC e o CNPJ anuente na Central Admin.');
    }
    $auth = re9_datavalid_access_token();
    if (empty($auth['ok'])) return $auth;
    $environment = strtolower(trim(get_val($APP_CONFIG, 'datavalid_environment', 'production')));
    $base = ($environment === 'demo') ? 'https://gateway.apiserpro.serpro.gov.br/datavalid-demonstracao' : 'https://gateway.apiserpro.serpro.gov.br/datavalid';
    $url = $base . '/v5/pessoa-fisica/validacao';
    $payload = array(
        'privacidade' => array(
            'rfb' => array('id_template' => $template),
            'senatran' => array('token' => $gccToken, 'cnpj_anuente' => $cnpj)
        ),
        'cpf' => preg_replace('/\D/', '', $cpf),
        'validacao' => array('nome' => trim($full_name))
    );
    $ch = curl_init($url);
    curl_setopt_array($ch, array(
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode($payload),
        CURLOPT_HTTPHEADER => array('Authorization: Bearer ' . $auth['token'], 'Content-Type: application/json', 'Accept: application/json'),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2
    ));
    $raw = curl_exec($ch);
    $http = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $err = curl_error($ch);
    curl_close($ch);
    $result = is_string($raw) ? json_decode($raw, true) : null;
    if ($err !== '' || $http !== 200 || !is_array($result)) {
        // Não repassa resposta bruta da API: ela pode conter dados pessoais e detalhes contratuais.
        return array('ok'=>false, 'msg'=>'A validação oficial não foi concluída. Confira o contrato, o token da GCC, o template e o ambiente Datavalid. Nenhuma caixa foi criada.');
    }
    $rfb = isset($result['rfb']) && is_array($result['rfb']) ? $result['rfb'] : array();
    $cpfExists = !empty($result['rfb_existe']);
    $cpfRegular = !empty($rfb['situacao_cpf']);
    $nameScore = isset($rfb['nome_similaridade']) ? (float)$rfb['nome_similaridade'] : 0;
    if (!$cpfExists || !$cpfRegular || $nameScore < 0.85) {
        return array('ok'=>false, 'msg'=>'Os dados informados não foram confirmados pela base oficial. Confira o nome completo e o CPF. A criação do e-mail foi bloqueada.');
    }
    return array('ok'=>true, 'msg'=>'Identidade cadastral validada pelo Datavalid.');
}

function re9_account_is_verified($email) {
    global $IDENTITY_FILE, $APP_CONFIG;
    $email = strtolower(trim((string)$email));
    $domain = strtolower(trim((string)get_val($APP_CONFIG, 'domain_name', 're9.rio.br')));
    if ($email === '' || strpos($email, '@') === false) return false;
    $parts = explode('@', $email);
    if (count($parts) !== 2 || strtolower(trim($parts[1])) !== $domain) return true;
    $records = load_protected_json($IDENTITY_FILE);
    return isset($records[$email]) && is_array($records[$email]) && (
        !empty($records[$email]['admin_manual_release_at']) ||
        !empty($records[$email]['admin_phone_verified_at']) ||
        (!empty($records[$email]['verified_at']) && !empty($records[$email]['cpf_hash']) && !empty($records[$email]['phone_hash']))
    );
}

function re9_datavalid_config_ready() {
    global $APP_CONFIG;
    $cnpj = preg_replace('/\D/', '', (string)get_val($APP_CONFIG, 'datavalid_cnpj_anuente', ''));
    return trim((string)get_val($APP_CONFIG, 'datavalid_consumer_key', '')) !== ''
        && trim((string)get_val($APP_CONFIG, 'datavalid_consumer_secret', '')) !== ''
        && trim((string)get_val($APP_CONFIG, 'datavalid_template_id', '')) !== ''
        && trim((string)get_val($APP_CONFIG, 'datavalid_gcc_token', '')) !== ''
        && strlen($cnpj) === 14;
}

function re9_account_pending_review($email) {
    global $IDENTITY_FILE;
    $records = load_protected_json($IDENTITY_FILE);
    $key = strtolower(trim((string)$email));
    return isset($records[$key]) && is_array($records[$key]) && !empty($records[$key]['pending_review_at']) && empty($records[$key]['admin_phone_verified_at']);
}

function re9_identity_gate_required($email) {
    global $APP_CONFIG;
    if (re9_account_is_verified($email) || re9_account_pending_review($email)) return false;
    $admins = isset($APP_CONFIG['admin_emails']) && is_array($APP_CONFIG['admin_emails']) ? $APP_CONFIG['admin_emails'] : array();
    $is_configured_admin = in_array(strtolower(trim((string)$email)), array_map('strtolower', array_map('trim', $admins)), true);
    if ($is_configured_admin && !re9_datavalid_config_ready()) return false;
    return true;
}

function re9_save_pending_identity($email, $name, $cpf_hash, $phone_hash, $phone, $consent_at) {
    global $IDENTITY_FILE;
    $records = load_protected_json($IDENTITY_FILE);
    if (!is_array($records)) $records = array();
    $key = strtolower(trim((string)$email));
    $records[$key] = array(
        'name' => agenda_clean_text($name, 100),
        'cpf_hash' => (string)$cpf_hash,
        'phone_hash' => (string)$phone_hash,
        'phone' => preg_replace('/\D/', '', (string)$phone),
        'cpf_math_valid' => true,
        'pending_review_at' => time(),
        'consent_at' => (int)$consent_at,
        'method' => 'cpf_math_and_manual_phone_review'
    );
    return save_protected_json($IDENTITY_FILE, $records) !== false;
}

function re9_save_verified_identity($email, $name, $cpf_hash, $phone_hash, $consent_at) {
    global $IDENTITY_FILE;
    $records = load_protected_json($IDENTITY_FILE);
    if (!is_array($records)) $records = array();
    $key = strtolower(trim((string)$email));
    $records[$key] = array(
        'name' => agenda_clean_text($name, 100),
        'cpf_hash' => (string)$cpf_hash,
        'phone_hash' => (string)$phone_hash,
        'verified_at' => time(),
        'consent_at' => (int)$consent_at,
        'method' => 'datavalid_plus_phone_otp'
    );
    return save_protected_json($IDENTITY_FILE, $records) !== false;
}

function send_verification_sms_whatsapp($phone, $code) {
    global $APP_CONFIG;
    $api_url   = isset($APP_CONFIG['whatsapp_api_url']) ? trim($APP_CONFIG['whatsapp_api_url']) : '';
    $api_token = isset($APP_CONFIG['whatsapp_api_token']) ? trim($APP_CONFIG['whatsapp_api_token']) : '';
    if ($api_url === '' || $api_token === '' || !function_exists('curl_init')) return false;
    $msg = "Seu codigo de confirmacao RE9 Webmail e: *" . $code . "*. Valido por 10 minutos.";
    $ch = curl_init($api_url);
    $payload = json_encode(array('number' => '55' . preg_replace('/\D/', '', $phone), 'text' => $msg));
    curl_setopt_array($ch, array(
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $payload,
        CURLOPT_HTTPHEADER => array('Content-Type: application/json', 'apikey: ' . $api_token, 'Authorization: Bearer ' . $api_token),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CONNECTTIMEOUT => 8,
        CURLOPT_TIMEOUT => 15,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2
    ));
    $response = curl_exec($ch);
    $http = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = curl_error($ch);
    curl_close($ch);
    return ($error === '' && $http >= 200 && $http < 300 && $response !== false);
}

// =========================================================================
// 2. COMUNICAÇÃO REAL COM A UAPI DO CPANEL PELO IP DA VPS (162.240.100.87)
// =========================================================================
function re9_create_server_sender_block($mailbox, $sender_email) {
    $mailbox = strtolower(trim((string)$mailbox));
    $sender_email = strtolower(trim((string)$sender_email));
    if (!filter_var($mailbox, FILTER_VALIDATE_EMAIL) || !filter_var($sender_email, FILTER_VALIDATE_EMAIL)) {
        return array('status' => 'error', 'msg' => 'Endereço de e-mail inválido para criar o filtro do servidor.');
    }
    // Um filtro individual e simples por remetente: o Exim descarta a mensagem
    // antes da entrega à caixa postal. /dev/null é o destino de descarte do cPanel.
    $filter_name = 'RE9_Block_' . substr(hash('sha256', $sender_email), 0, 20);
    return call_cpanel_uapi('Email', 'store_filter', array(
        'account'   => $mailbox,
        'filtername'=> $filter_name,
        'action1'   => 'deliver',
        'dest1'     => '/dev/null',
        'match1'    => 'is',
        'part1'     => '$header_from:',
        'val1'      => $sender_email
    ));
}

function call_cpanel_uapi($module, $function, $params = array()) {
    global $APP_CONFIG;
    $cp_user = trim(get_val($APP_CONFIG, 'cpanel_user'));
    $cp_auth = trim(get_val($APP_CONFIG, 'cpanel_api_token'));
    $cp_host = !empty($APP_CONFIG['cpanel_host']) ? trim($APP_CONFIG['cpanel_host']) : '162.240.100.87';

    $query = http_build_query($params);

    if (!empty($cp_user) && !empty($cp_auth) && function_exists('curl_init')) {
        $hosts_to_try = array_unique(array($cp_host, '127.0.0.1', '162.240.100.87'));
        $urls = array();
        foreach ($hosts_to_try as $h) {
            $urls[] = "https://{$h}:2083/execute/{$module}/{$function}?{$query}";
        }

        foreach ($urls as $url) {
            $auth_headers = array(
                "Authorization: cpanel {$cp_user}:{$cp_auth}",
                "Authorization: Basic " . base64_encode("{$cp_user}:{$cp_auth}")
            );

            foreach ($auth_headers as $header_str) {
                $ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, $url);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
                curl_setopt($ch, CURLOPT_TIMEOUT, 10);
                curl_setopt($ch, CURLOPT_HTTPHEADER, array($header_str));
                $resp = curl_exec($ch);
                $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                curl_close($ch);

                if ($resp && $http_code == 200) {
                    $json = @json_decode($resp, true);
                    if (is_array($json)) {
                        // UAPI padrão retorna result.status; algumas versões/rotas antigas
                        // retornam status diretamente na raiz. Aceita ambos os formatos.
                        $api_result = (isset($json['result']) && is_array($json['result'])) ? $json['result'] : $json;
                        if (isset($api_result['status'])) {
                            if ((int)$api_result['status'] === 1) {
                                return array('status' => 'ok', 'data' => isset($api_result['data']) ? $api_result['data'] : array());
                            } else {
                                $errors = isset($api_result['errors']) ? $api_result['errors'] : array();
                                $err_raw = is_array($errors) ? implode(' | ', $errors) : (string)$errors;
                                return array('status' => 'error', 'msg' => translate_cpanel_error($err_raw));
                            }
                        }
                    }
                }
            }
        }
    }

    $uapi_bin = '/usr/local/cpanel/bin/uapi';
    if (file_exists($uapi_bin) && function_exists('shell_exec')) {
        $cmd_parts = array($uapi_bin, '--output=json', escapeshellarg($module), escapeshellarg($function));
        foreach ($params as $k => $v) {
            $cmd_parts[] = escapeshellarg($k . '=' . $v);
        }
        $out = @shell_exec(implode(' ', $cmd_parts));
        if (!empty($out)) {
            $json = @json_decode($out, true);
            if (isset($json['result']['status'])) {
                if ($json['result']['status'] == 1) {
                    return array('status' => 'ok', 'data' => isset($json['result']['data']) ? $json['result']['data'] : array());
                } else {
                    $err_raw = !empty($json['result']['errors']) ? implode(' ', $json['result']['errors']) : '';
                    return array('status' => 'error', 'msg' => translate_cpanel_error($err_raw));
                }
            }
        }
    }

    return array(
        'status' => 'error',
        'msg'    => 'Para conectar ao servidor cPanel da VPS (162.240.100.87), acesse a Aba 1 do Admin e salve o Usuário e Senha/Token do seu cPanel.'
    );
}

function re9_get_cpanel_domains() {
    global $APP_CONFIG;
    $domains = array();
    $fallback = strtolower(trim((string)get_val($APP_CONFIG, 'domain_name', 're9.rio.br')));
    if ($fallback !== '' && preg_match('/^(?=.{1,253}$)[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/i', $fallback)) $domains[] = $fallback;
    $domainResult = call_cpanel_uapi('DomainInfo', 'list_domains', array());
    if (is_array($domainResult) && get_val($domainResult, 'status') === 'ok') {
        $domainData = get_val($domainResult, 'data', array());
        $extract = function($value, $allowed = false) use (&$extract, &$domains) {
            if (is_string($value)) {
                if ($allowed) {
                    $candidate = strtolower(trim($value));
                    if ($candidate !== '' && preg_match('/^(?=.{1,253}$)[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/i', $candidate)) $domains[] = $candidate;
                }
                return;
            }
            if (!is_array($value)) return;
            foreach ($value as $key => $item) {
                if (in_array((string)$key, array('main_domain','addon_domains','parked_domains','sub_domains','domains','domain','domain_name'), true)) {
                    $extract($item, true);
                } elseif ($allowed && (is_int($key) || ctype_digit((string)$key))) {
                    $extract($item, true);
                } elseif (is_array($item)) {
                    $extract($item, false);
                }
            }
        };
        $extract($domainData, false);
    }
    $domains = array_values(array_unique($domains));
    sort($domains, SORT_NATURAL | SORT_FLAG_CASE);
    return $domains;
}

function create_cpanel_email($username, $password, $domain) {
    global $APP_CONFIG;
    $quota = isset($APP_CONFIG['cpanel_quota_mb']) ? (int)$APP_CONFIG['cpanel_quota_mb'] : 250;

    return call_cpanel_uapi('Email', 'add_pop', array(
        'email'              => $username,
        'password'           => $password,
        'domain'             => $domain,
        'quota'              => $quota,
        'send_welcome_email' => 1
    ));
}

function update_cpanel_password($email, $new_password) {
    $parts    = explode('@', $email);
    $username = $parts[0];
    $domain   = isset($parts[1]) ? $parts[1] : 're9.rio.br';

    return call_cpanel_uapi('Email', 'passwd_pop', array(
        'email'    => $username,
        'password' => $new_password,
        'domain'   => $domain
    ));
}

// =========================================================================
// 3. MOTOR IMAP VIA SOCKET PURO + IMPORTADOR DE CONTAS EXTERNAS
// =========================================================================
class CpanelImapSocket {
    private $sock = null;
    private $tag = 1;
    public $last_error = '';

    public function connect($user, $pass, $host = 'localhost', $port = 993) {
        // Contas da VPS tentam o serviço IMAP local, o host cPanel configurado
        // e nomes MX/mail do domínio somente quando o DNS prova que apontam para
        // o mesmo IP desta VPS. Nunca enviamos credenciais a um MX externo.
        $targets = array();
        $seen = array();
        $addTarget = function($targetHost, $targetPort) use (&$targets, &$seen) {
            $targetHost = strtolower(trim((string)$targetHost));
            $targetPort = (int)$targetPort;
            if ($targetHost === '' || !in_array($targetPort, array(143, 993), true)) return;
            if (!preg_match('/^[a-z0-9.-]+$/i', $targetHost)) return;
            if ($targetHost !== 'localhost' && !filter_var($targetHost, FILTER_VALIDATE_IP)) {
                $resolved = @gethostbyname($targetHost);
                if ($resolved === $targetHost) return;
            }
            $key = $targetHost . ':' . $targetPort;
            if (isset($seen[$key])) return;
            $seen[$key] = true;
            $targets[] = array('host' => $targetHost, 'port' => $targetPort);
        };

        if ($host !== 'localhost' || (int)$port !== 993) {
            // Contas de provedores externos permanecem isoladas e usam apenas
            // o servidor explicitamente informado no cadastro dessa conexão.
            $addTarget($host, $port);
        } else {
            global $APP_CONFIG;
            $cpanelHost = isset($APP_CONFIG['cpanel_host']) ? trim((string)$APP_CONFIG['cpanel_host']) : '';
            $addTarget($cpanelHost, 993);

            /*
             * Descobre o endpoint IMAP de cada domínio, mas SÓ o adiciona
             * quando o IP do MX/mail.<domínio> coincide com o IP do próprio
             * cPanel/servidor web configurado nesta instalação.
             * Assim, domínios adicionais e contas de outros usuários cPanel
             * na mesma VPS podem usar o nome TLS correto (SNI), sem enviar
             * senha a servidores MX externos.
             */
            $localIps = array();
            $rememberLocalIps = function($hostHint) use (&$localIps) {
                $hostHint = trim((string)$hostHint);
                if ($hostHint === '') return;
                if (filter_var($hostHint, FILTER_VALIDATE_IP)) {
                    $localIps[] = $hostHint;
                    return;
                }
                $resolvedIps = function_exists('gethostbynamel') ? @gethostbynamel($hostHint) : false;
                if (!is_array($resolvedIps) || !$resolvedIps) {
                    $oneIp = @gethostbyname($hostHint);
                    if ($oneIp !== $hostHint && filter_var($oneIp, FILTER_VALIDATE_IP)) $resolvedIps = array($oneIp);
                }
                if (is_array($resolvedIps)) {
                    foreach ($resolvedIps as $ip) if (filter_var($ip, FILTER_VALIDATE_IP)) $localIps[] = $ip;
                }
            };
            $rememberLocalIps($cpanelHost);
            $rememberLocalIps(get_val($_SERVER, 'SERVER_ADDR', ''));
            $rememberLocalIps(get_val($_SERVER, 'LOCAL_ADDR', ''));
            if (function_exists('gethostname')) $rememberLocalIps(@gethostname());
            $localIps = array_values(array_unique($localIps));

            $domainImapHosts = array();
            $atPos = strrpos((string)$user, '@');
            $mailDomain = ($atPos !== false) ? strtolower(trim(substr((string)$user, $atPos + 1))) : '';
            if ($mailDomain !== '' && preg_match('/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/i', $mailDomain) && $localIps) {
                $candidateHosts = array();
                $mxHosts = array();
                $mxWeights = array();
                if (function_exists('getmxrr') && @getmxrr($mailDomain, $mxHosts, $mxWeights) && is_array($mxHosts)) {
                    if (is_array($mxWeights) && count($mxWeights) === count($mxHosts)) {
                        array_multisort($mxWeights, SORT_ASC, SORT_NUMERIC, $mxHosts);
                    }
                    foreach ($mxHosts as $mxHost) $candidateHosts[] = rtrim(strtolower((string)$mxHost), '.');
                }
                $candidateHosts[] = 'mail.' . $mailDomain;
                $candidateHosts[] = 'imap.' . $mailDomain;
                $candidateHosts[] = $mailDomain;
                $candidateHosts[] = 'webmail.' . $mailDomain;
                if (function_exists('gethostname')) $candidateHosts[] = strtolower(trim((string)@gethostname()));
                $serverName = strtolower(trim((string)get_val($_SERVER, 'SERVER_NAME', '')));
                if ($serverName !== '') $candidateHosts[] = preg_replace('/:\d+$/', '', $serverName);
                $candidateHosts = array_values(array_unique(array_filter($candidateHosts)));

                foreach ($candidateHosts as $candidateHost) {
                    if (count($domainImapHosts) >= 3) break;
                    if (!preg_match('/^[a-z0-9.-]+$/i', $candidateHost)) continue;
                    $resolved = function_exists('gethostbynamel') ? @gethostbynamel($candidateHost) : false;
                    if (!is_array($resolved) || !$resolved) {
                        $one = @gethostbyname($candidateHost);
                        $resolved = ($one !== $candidateHost && filter_var($one, FILTER_VALIDATE_IP)) ? array($one) : array();
                    }
                    if (array_intersect($localIps, $resolved)) $domainImapHosts[] = $candidateHost;
                }
                // Prioriza o MX/mail do próprio domínio quando ele é comprovadamente
                // servido por esta VPS; depois usa os endereços locais padrão.
                foreach ($domainImapHosts as $domainImapHost) $addTarget($domainImapHost, 993);
            }
            $addTarget('localhost', 993);
            $addTarget('127.0.0.1', 993);
            $addTarget($cpanelHost, 993);

            // Porta 143 só é utilizada quando STARTTLS é anunciado e concluído.
            // A senha nunca é transmitida em texto puro.
            foreach ($domainImapHosts as $domainImapHost) $addTarget($domainImapHost, 143);
            $addTarget('localhost', 143);
            $addTarget('127.0.0.1', 143);
            $addTarget($cpanelHost, 143);
        }

        if (!$targets) {
            $this->last_error = 'Nenhum host IMAP local/configurado válido foi encontrado.';
            return false;
        }

        $attempts = array();
        foreach ($targets as $target) {
            $targetHost = $target['host'];
            $targetPort = (int)$target['port'];
            $implicitTls = ($targetPort === 993);
            $proto = $implicitTls ? 'ssl://' : 'tcp://';
            $errno = 0;
            $errstr = '';
            $ctx = stream_context_create(array(
                'ssl' => array(
                    'verify_peer' => false,
                    'verify_peer_name' => false,
                    'allow_self_signed' => true,
                    'SNI_enabled' => true,
                    'peer_name' => $targetHost
                )
            ));
            $this->sock = @stream_socket_client(
                $proto . $targetHost . ':' . $targetPort,
                $errno,
                $errstr,
                5,
                STREAM_CLIENT_CONNECT,
                $ctx
            );
            if (!$this->sock) {
                $attempts[] = $targetHost . ':' . $targetPort . ' conexão recusada (' . (int)$errno . ')';
                continue;
            }
            $this->tag = 1;
            @stream_set_timeout($this->sock, 7);
            $greeting = @fgets($this->sock, 1024);
            if (!is_string($greeting) || (stripos($greeting, '* OK') !== 0 && stripos($greeting, '* PREAUTH') !== 0)) {
                $attempts[] = $targetHost . ':' . $targetPort . ' saudação IMAP inválida';
                $this->close();
                continue;
            }

            if (!$implicitTls) {
                $capability = $this->cmd('CAPABILITY');
                if ($capability['status'] !== 'OK' || stripos($capability['raw'], 'STARTTLS') === false) {
                    $attempts[] = $targetHost . ':' . $targetPort . ' sem STARTTLS';
                    $this->close();
                    continue;
                }
                $startTls = $this->cmd('STARTTLS');
                if ($startTls['status'] !== 'OK') {
                    $attempts[] = $targetHost . ':' . $targetPort . ' rejeitou STARTTLS';
                    $this->close();
                    continue;
                }
                $crypto = @stream_socket_enable_crypto($this->sock, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
                if ($crypto !== true) {
                    $attempts[] = $targetHost . ':' . $targetPort . ' falha ao iniciar TLS';
                    $this->close();
                    continue;
                }
                $this->tag = 1;
            }

            $res = $this->cmd('LOGIN "' . $this->escape($user) . '" "' . $this->escape($pass) . '"');
            $authenticated = ($res['status'] === 'OK');
            if ($authenticated) {
                $this->last_error = '';
                return true;
            }
            $attempts[] = $targetHost . ':' . $targetPort . ' autenticação recusada';
            $this->close();
        }

        $this->last_error = implode('; ', $attempts);
        // Registra domínio e resultado técnico, nunca e-mail completo, senha
        // ou conteúdo das mensagens.
        $at = strrpos((string)$user, '@');
        $domainForLog = ($at !== false) ? strtolower(substr((string)$user, $at + 1)) : 'desconhecido';
        error_log('[RE9 IMAP] Falha de autenticação/conexão para domínio ' . $domainForLog . ': ' . $this->last_error);
        return false;
    }

    private function escape($str) {
        return str_replace(array('\\', '"'), array('\\\\', '\\"'), $str);
    }

    public function cmd($command) {
        $t = 'A' . str_pad($this->tag++, 4, '0', STR_PAD_LEFT);
        fputs($this->sock, "$t $command\r\n");
        $lines = array();
        $status = 'ERR';
        while (($line = fgets($this->sock, 8192)) !== false) {
            if (strpos($line, $t . ' ') === 0) {
                if (preg_match('/^' . $t . '\s+(OK|NO|BAD)/i', $line, $m)) {
                    $status = strtoupper($m[1]);
                }
                break;
            }
            $lines[] = $line;
        }
        return array('status' => $status, 'lines' => $lines, 'raw' => implode('', $lines));
    }

    public function selectFolder($folder) {
        $res = $this->cmd('SELECT "' . $this->escape($folder) . '"');
        if ($res['status'] !== 'OK' && strtoupper($folder) !== 'INBOX') {
            $this->cmd('CREATE "' . $this->escape($folder) . '"');
            $this->cmd('SUBSCRIBE "' . $this->escape($folder) . '"');
            $res = $this->cmd('SELECT "' . $this->escape($folder) . '"');
        }
        $exists = 0;
        foreach ($res['lines'] as $l) {
            if (preg_match('/\*\s+(\d+)\s+EXISTS/i', $l, $m)) {
                $exists = (int)$m[1];
            }
        }
        return array('ok' => ($res['status'] === 'OK'), 'total' => $exists);
    }

    public function countUnseen($folder = 'INBOX') {
        $sel = $this->selectFolder($folder);
        if (!$sel['ok'] || $sel['total'] === 0) return 0;

        $res = $this->cmd('SEARCH UNSEEN');
        foreach ($res['lines'] as $line) {
            if (preg_match('/^\*\s+SEARCH\s+(.+)$/i', trim($line), $m)) {
                $ids = preg_split('/\s+/', trim($m[1]));
                $count = 0;
                foreach ($ids as $id) {
                    if (is_numeric($id)) $count++;
                }
                return $count;
            }
        }
        return 0;
    }

    public function listEmails($folder = 'INBOX', $limit = 45, $user_email = '') {
        $sel = $this->selectFolder($folder);
        if (!$sel['ok'] || $sel['total'] === 0) {
            return array('total' => 0, 'unseen' => 0, 'emails' => array());
        }

        $total  = $sel['total'];
        $start  = max(1, $total - $limit + 1);
        $emails = array();

        for ($i = $total; $i >= $start; $i--) {
            $res = $this->cmd("FETCH $i (UID FLAGS RFC822.SIZE BODY.PEEK[HEADER.FIELDS (FROM TO SUBJECT DATE RECEIVED X-RE9-Agenda-Reminder)])");
            $raw = $res['raw'];
            if (empty($raw)) continue;

            $uid = $i;
            if (preg_match('/UID\s+(\d+)/i', $raw, $m)) $uid = (int)$m[1];

            $seen = (stripos($raw, '\\Seen') !== false);
            $size = '';
            if (preg_match('/RFC822\.SIZE\s+(\d+)/i', $raw, $m)) {
                $size = round(((int)$m[1]) / 1024, 1) . ' KB';
            }

            $parsed = $this->parseHeaders($raw);
            if (strtoupper($folder) === 'INBOX' && is_sender_blocked($user_email, $parsed['from'], $parsed['sender_ip'], $parsed['sender_server'])) {
                // Aplica o bloqueio no fluxo real: futuras mensagens do endereço saem da Entrada.
                $this->deleteEmail($folder, $uid);
                continue;
            }
            $bot_scan = security_bot_analyze_email($user_email, $parsed['from'], $parsed['subject'], '');

            $emails[] = array(
                'seq'           => $i,
                'uid'           => $uid,
                'from'          => $parsed['from'],
                'from_label'    => $parsed['from_label'],
                'agenda_reminder' => !empty($parsed['agenda_reminder']),
                'clean_from'    => extract_clean_email($parsed['from']),
                'sender_ip'     => $parsed['sender_ip'],
                'sender_server' => $parsed['sender_server'],
                'to'            => $parsed['to'],
                'subject'       => $parsed['subject'],
                'date'          => $parsed['date'],
                'timestamp'     => $parsed['timestamp'],
                'date_group'    => classify_email_date_group($parsed['timestamp']),
                'seen'          => $seen,
                'size'          => $size,
                'suspicious'    => $bot_scan['suspicious'],
                'trusted'       => $bot_scan['trusted'],
                'bot_reasons'   => $bot_scan['reasons']
            );
        }

        $unseen = $this->countUnseen($folder);

        usort($emails, function($a, $b) {
            return $b['timestamp'] - $a['timestamp'];
        });

        return array('total' => count($emails), 'unseen' => $unseen, 'emails' => $emails);
    }

    public function readEmail($folder, $uid, $user_email = '') {
        $this->selectFolder($folder);
        $this->cmd("UID STORE " . (int)$uid . " +FLAGS (\\Seen)");
        $res = $this->cmd("UID FETCH " . (int)$uid . " (BODY.PEEK[])");
        $raw = $res['raw'];
        if (empty($raw)) return false;

        $first_nl = strpos($raw, "\n");
        if ($first_nl !== false) {
            $raw = substr($raw, $first_nl + 1);
        }
        $raw = preg_replace('/\)\r?\n?$/', '', $raw);

        $split = preg_split("/\r?\n\r?\n/", $raw, 2);
        $h_raw = isset($split[0]) ? $split[0] : '';
        $b_raw = isset($split[1]) ? $split[1] : '';

        $headers   = $this->parseHeaders($h_raw);
        $extracted = $this->extractBody($h_raw, $b_raw);
        $body      = is_array($extracted) ? $extracted['body'] : $extracted;
        $atts      = (is_array($extracted) && isset($extracted['attachments'])) ? $extracted['attachments'] : array();
        $bot_scan  = security_bot_analyze_email($user_email, $headers['from'], $headers['subject'], $body);
        foreach ($atts as $attachment) {
            $filename = strtolower((string)get_val($attachment, 'filename', ''));
            if (preg_match('/\\.(exe|scr|bat|cmd|com|pif|vbs|vbe|js|jse|wsf|wsh|ps1|psm1|hta|cpl|dll|msi|msp|jar|apk|iso|img|lnk|reg)(\\.|$)/i', $filename)) {
                $bot_scan['suspicious'] = true;
                $bot_scan['reasons'][] = 'Anexo com extensão executável ou script de alto risco: ' . $filename;
            } elseif (preg_match('/\\.(zip|rar|7z|iso)$/i', $filename)) {
                $bot_scan['suspicious'] = true;
                $bot_scan['reasons'][] = 'Anexo compactado ou imagem de disco não inspecionado internamente: ' . $filename;
            }
        }
        $bot_scan['reasons'] = array_values(array_unique($bot_scan['reasons']));

        return array(
            'status'        => 'ok',
            'uid'           => $uid,
            'from'          => $headers['from'],
            'from_label'    => $headers['from_label'],
            'agenda_reminder' => !empty($headers['agenda_reminder']),
            'clean_from'    => extract_clean_email($headers['from']),
            'sender_ip'     => $headers['sender_ip'],
            'sender_server' => $headers['sender_server'],
            'to'            => $headers['to'],
            'subject'       => $headers['subject'],
            'date'          => $headers['date'],
            'body'          => sanitize_email_html($body),
            'attachments'   => $atts,
            'suspicious'    => $bot_scan['suspicious'],
            'trusted'       => $bot_scan['trusted'],
            'bot_reasons'   => $bot_scan['reasons']
        );
    }

    public function fetchTodayRawMessages($max_fetch = 15) {
        $sel = $this->selectFolder('INBOX');
        if (!$sel['ok'] || $sel['total'] === 0) return array();

        $imap_date = date('j-M-Y');
        $res = $this->cmd('SEARCH SINCE "' . $imap_date . '"');
        $seq_ids = array();

        foreach ($res['lines'] as $line) {
            if (preg_match('/^\*\s+SEARCH\s+(.+)$/i', trim($line), $m)) {
                $parts = preg_split('/\s+/', trim($m[1]));
                foreach ($parts as $p) {
                    if (is_numeric($p)) $seq_ids[] = (int)$p;
                }
            }
        }

        if (empty($seq_ids)) {
            $total = $sel['total'];
            $start = max(1, $total - 9);
            for ($i = $total; $i >= $start; $i--) {
                $seq_ids[] = $i;
            }
        } else {
            $seq_ids = array_slice($seq_ids, -$max_fetch);
        }

        $today_ymd = date('Y-m-d');
        $messages = array();

        foreach ($seq_ids as $seq) {
            $hdr_res = $this->cmd("FETCH $seq (BODY.PEEK[HEADER.FIELDS (MESSAGE-ID DATE SUBJECT FROM)])");
            $hdr_raw = $hdr_res['raw'];
            if (empty($hdr_raw)) continue;

            $parsed = $this->parseHeaders($hdr_raw);
            if (date('Y-m-d', $parsed['timestamp']) !== $today_ymd) {
                continue;
            }

            $msg_id = '';
            if (preg_match('/Message-ID:\s*([^\r\n]+)/i', $hdr_raw, $m_id)) {
                $msg_id = trim($m_id[1]);
            }
            if (empty($msg_id)) {
                $msg_id = md5($parsed['from'] . '_' . $parsed['subject'] . '_' . $parsed['date']);
            }

            $full_res = $this->cmd("FETCH $seq (BODY.PEEK[])");
            $raw = $full_res['raw'];
            if (empty($raw)) continue;

            $first_nl = strpos($raw, "\n");
            if ($first_nl !== false) {
                $raw = substr($raw, $first_nl + 1);
            }
            $raw = preg_replace('/\)\r?\n?$/', '', $raw);

            if (!empty($raw)) {
                $messages[$msg_id] = $raw;
            }
        }

        return $messages;
    }

    public function deleteEmail($folder, $uid) {
        $uid = (int)$uid;
        if ($uid <= 0) return false;

        $sel = $this->selectFolder($folder);
        if (!$sel['ok']) return false;

        // Mensagens fora da Lixeira são primeiro copiadas para ela.
        if (strtoupper($folder) !== 'INBOX.TRASH') {
            $copy = $this->cmd('UID COPY ' . $uid . ' "INBOX.Trash"');
            if ($copy['status'] !== 'OK') return false;
        }

        // UID STORE é obrigatório: a interface trabalha com UID, não número de sequência.
        $store = $this->cmd('UID STORE ' . $uid . ' +FLAGS.SILENT (\\Deleted)');
        if ($store['status'] !== 'OK') return false;

        $expunge = $this->cmd('EXPUNGE');
        return ($expunge['status'] === 'OK');
    }

    public function emptyTrash() {
        $sel = $this->selectFolder('INBOX.Trash');
        if (!$sel['ok']) return false;

        // Busca os UIDs reais; o total de mensagens não é um UID e pode causar falhas.
        $search = $this->cmd('UID SEARCH ALL');
        if ($search['status'] !== 'OK') return false;

        $uids = array();
        foreach ($search['lines'] as $line) {
            if (preg_match('/^\*\s+SEARCH\s*(.*)$/i', trim($line), $m)) {
                $parts = preg_split('/\s+/', trim($m[1]));
                foreach ($parts as $part) {
                    if ($part !== '' && ctype_digit($part)) $uids[] = (int)$part;
                }
            }
        }
        $uids = array_values(array_unique(array_filter($uids)));
        if (empty($uids)) return true;

        // Envia lotes para evitar comandos IMAP excessivamente grandes.
        foreach (array_chunk($uids, 100) as $chunk) {
            $store = $this->cmd('UID STORE ' . implode(',', $chunk) . ' +FLAGS.SILENT (\\Deleted)');
            if ($store['status'] !== 'OK') return false;
        }

        $expunge = $this->cmd('EXPUNGE');
        if ($expunge['status'] !== 'OK') return false;

        // Confirma no servidor que a Lixeira ficou realmente vazia.
        $verify = $this->cmd('UID SEARCH ALL');
        if ($verify['status'] !== 'OK') return false;
        foreach ($verify['lines'] as $line) {
            if (preg_match('/^\*\s+SEARCH\s+(.+)$/i', trim($line), $m) && trim($m[1]) !== '') {
                return false;
            }
        }
        return true;
    }

    public function appendMessageToFolder($folder, $raw_mime, $flags = '\\Seen') {
        $this->selectFolder($folder);
        $len = strlen($raw_mime);
        $t = 'A' . str_pad($this->tag++, 4, '0', STR_PAD_LEFT);
        fputs($this->sock, "$t APPEND \"" . $this->escape($folder) . "\" ($flags) {" . $len . "}\r\n");
        $cont = fgets($this->sock, 1024);
        if (strpos($cont, '+') === 0) {
            fputs($this->sock, $raw_mime . "\r\n");
            while (($line = fgets($this->sock, 1024)) !== false) {
                if (strpos($line, $t . ' ') === 0) break;
            }
        }
    }

    private function parseHeaders($raw) {
        $unfolded = preg_replace("/\r?\n[ \t]+/", ' ', $raw);
        $lines = preg_split("/\r?\n/", $unfolded);
        $data = array(
            'from'          => 'Desconhecido',
            'to'            => '',
            'subject'       => '(Sem Assunto)',
            'date'          => '',
            'timestamp'     => time(),
            'sender_ip'     => '',
            'sender_server' => '',
            'agenda_reminder' => false,
            'from_label' => ''
        );

        foreach ($lines as $line) {
            $line = trim($line);
            if (stripos($line, 'From:') === 0) {
                $data['from'] = decode_mime_header_str(trim(substr($line, 5)));
            } elseif (stripos($line, 'To:') === 0) {
                $data['to'] = decode_mime_header_str(trim(substr($line, 3)));
            } elseif (stripos($line, 'Subject:') === 0) {
                $subj = decode_mime_header_str(trim(substr($line, 8)));
                $data['subject'] = ($subj !== '') ? $subj : '(Sem Assunto)';
            } elseif (stripos($line, 'Date:') === 0) {
                $raw_d = trim(substr($line, 5));
                $ts = @strtotime($raw_d);
                if ($ts) {
                    $data['timestamp'] = $ts;
                    $data['date'] = (date('Y-m-d', $ts) === date('Y-m-d')) ? date('H:i', $ts) : date('d/m/Y H:i', $ts);
                } else {
                    $data['date'] = $raw_d;
                }
            } elseif (stripos($line, 'X-RE9-Agenda-Reminder:') === 0) {
                $data['agenda_reminder'] = in_array(strtolower(trim(substr($line, 22))), array('1','yes','true'), true);
            } elseif (stripos($line, 'Received:') === 0) {
                if (empty($data['sender_ip']) && preg_match('/\[(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\]/', $line, $m_ip)) {
                    if ($m_ip[1] !== '127.0.0.1') {
                        $data['sender_ip'] = $m_ip[1];
                    }
                }
                if (empty($data['sender_server']) && preg_match('/from\s+([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/i', $line, $m_srv)) {
                    $data['sender_server'] = strtolower($m_srv[1]);
                }
            }
        }
        // Reconhece também lembretes antigos enviados com o nome AGENDA HOJE.
        if (!$data['agenda_reminder'] && stripos((string)$data['from'], 'AGENDA HOJE') !== false && stripos((string)$data['subject'], 'Lembrete de compromisso') !== false) {
            $data['agenda_reminder'] = true;
        }
        $data['from_label'] = $data['agenda_reminder'] ? 'DA AGENDA' : $data['from'];
        return $data;
    }

    private function extractBody($headers_raw, $body_raw) {
        $attachments = array();

        if (preg_match('/boundary="?([^"\r\n;]+)"?/i', $headers_raw, $m)) {
            $boundary = $m[1];
            $parts = explode('--' . $boundary, $body_raw);
            $html_part = '';
            $text_part = '';

            foreach ($parts as $p) {
                // Identifica e extrai anexos do e-mail
                if (preg_match('/Content-Disposition:\s*(?:attachment|inline);\s*filename="?([^"\r\n;]+)"?/i', $p, $m_att) ||
                    preg_match('/Content-Type:\s*[^;]+;\s*name="?([^"\r\n;]+)"?/i', $p, $m_att)) {

                    $filename = decode_mime_header_str(trim($m_att[1], ' "\''));
                    $sub = preg_split("/\r?\n\r?\n/", $p, 2);
                    if (isset($sub[1])) {
                        $att_content = preg_replace('/--\r?\n?$/', '', trim($sub[1]));
                        if (stripos($p, 'Content-Transfer-Encoding: base64') !== false) {
                            $att_content = base64_decode($att_content);
                        } elseif (stripos($p, 'Content-Transfer-Encoding: quoted-printable') !== false) {
                            $att_content = quoted_printable_decode($att_content);
                        }

                        global $UPLOAD_DIR, $PRIVATE_ATTACHMENT_DIR;
                        $owner_key = substr(hash('sha256', strtolower((string)get_val($_SESSION, 'wm_email', 'guest'))), 0, 32);
                        $owner_dir = $PRIVATE_ATTACHMENT_DIR . '/' . $owner_key;
                        if (!is_dir($owner_dir)) @mkdir($owner_dir, 0700, true);
                        @file_put_contents($owner_dir . '/.htaccess', "Options -Indexes\n<IfModule mod_authz_core.c>Require all denied</IfModule>\n<IfModule !mod_authz_core.c>Deny from all</IfModule>\n", LOCK_EX);
                        $safe_filename = 'att_' . md5($filename . strlen($att_content)) . '_' . preg_replace('/[^a-zA-Z0-9._-]/', '_', $filename);
                        $saved_attachment = @file_put_contents($owner_dir . '/' . $safe_filename, $att_content, LOCK_EX);
                        if ($saved_attachment !== false) @chmod($owner_dir . '/' . $safe_filename, 0600);

                        $attachments[] = array(
                            'filename' => $filename,
                            'file'     => $safe_filename,
                            'url'      => '?api=download_attachment&file=' . rawurlencode($safe_filename),
                            'size'     => round(strlen($att_content) / 1024, 1) . ' KB'
                        );
                    }
                }

                if (stripos($p, 'Content-Type: multipart/') !== false) {
                    $sub = preg_split("/\r?\n\r?\n/", $p, 2);
                    if (isset($sub[1])) {
                        $nested = $this->extractBody($sub[0], $sub[1]);
                        if (!empty($nested)) {
                            if (is_array($nested)) {
                                if (!empty($nested['body'])) $html_part = $nested['body'];
                                if (!empty($nested['attachments'])) {
                                    $attachments = array_merge($attachments, $nested['attachments']);
                                }
                            } else {
                                $html_part = $nested;
                            }
                        }
                    }
                } elseif (stripos($p, 'Content-Type: text/html') !== false) {
                    $sub = preg_split("/\r?\n\r?\n/", $p, 2);
                    if (isset($sub[1])) $html_part = $this->decodePart($sub[0], $sub[1]);
                } elseif (stripos($p, 'Content-Type: text/plain') !== false) {
                    $sub = preg_split("/\r?\n\r?\n/", $p, 2);
                    if (isset($sub[1])) $text_part = nl2br(htmlspecialchars($this->decodePart($sub[0], $sub[1])));
                }
            }

            $final_body = ($html_part !== '') ? $html_part : $text_part;

            // Adiciona a caixa de botões de download dos anexos no rodapé da mensagem
            if (!empty($attachments)) {
                $final_body .= '<br><hr><div style="margin-top:15px;padding:12px;background:#f8fafc;border:1px solid #cbd5e1;border-radius:8px;"><strong>Anexos da Mensagem:</strong><ul style="margin:8px 0 0 20px;padding:0;">';
                foreach ($attachments as $att) {
                    $final_body .= '<li style="margin-bottom:4px;"><a href="' . htmlspecialchars($att['url']) . '" target="_blank" download style="color:#002244;font-weight:bold;text-decoration:underline;">' . htmlspecialchars($att['filename']) . '</a> <span style="color:#64748b;font-size:11px;">(' . $att['size'] . ')</span></li>';
                }
                $final_body .= '</ul></div>';
            }

            return array('body' => $final_body, 'attachments' => $attachments);
        }

        $decoded = $this->decodePart($headers_raw, $body_raw);
        $body_res = (stripos($headers_raw, 'text/html') === false) ? nl2br(htmlspecialchars($decoded)) : $decoded;
        return array('body' => $body_res, 'attachments' => array());
    }

    private function decodePart($head, $body) {
        $body = trim($body);
        if (stripos($head, 'Content-Transfer-Encoding: base64') !== false) {
            $body = base64_decode($body);
        } elseif (stripos($head, 'Content-Transfer-Encoding: quoted-printable') !== false) {
            $body = quoted_printable_decode($body);
        }
        if (preg_match('/charset="?([^"\r\n;]+)"?/i', $head, $m)) {
            $ch = strtoupper(trim($m[1]));
            if ($ch !== 'UTF-8' && $ch !== 'DEFAULT' && function_exists('iconv')) {
                $conv = @iconv($ch, 'UTF-8//IGNORE', $body);
                if ($conv !== false) $body = $conv;
            }
        }
        return $body;
    }

    public function close() {
        if ($this->sock) {
            @fputs($this->sock, "ZZZZ LOGOUT\r\n");
            @fclose($this->sock);
            $this->sock = null;
        }
    }
}

function detect_imap_host_by_email($email) {
    $parts = explode('@', strtolower(trim($email)));
    $dom = isset($parts[1]) ? $parts[1] : '';
    if (strpos($dom, 'gmail.com') !== false || strpos($dom, 'googlemail.com') !== false) {
        return 'imap.gmail.com';
    }
    if (strpos($dom, 'hotmail.') !== false || strpos($dom, 'outlook.') !== false || strpos($dom, 'live.') !== false || strpos($dom, 'msn.') !== false) {
        return 'imap-mail.outlook.com';
    }
    if (strpos($dom, 'yahoo.') !== false) {
        return 'imap.mail.yahoo.com';
    }
    if (strpos($dom, 'icloud.com') !== false) {
        return 'imap.mail.me.com';
    }
    if (strpos($dom, 'uol.com.br') !== false) {
        return 'imap.uol.com.br';
    }
    if (strpos($dom, 'terra.com.br') !== false) {
        return 'imap.terra.com.br';
    }
    return 'mail.' . $dom;
}

function get_user_external_accounts($user_email) {
    global $EXTERNAL_FILE;
    $all = load_protected_json($EXTERNAL_FILE);
    $key = strtolower(trim($user_email));
    if (!isset($all[$key]) || !is_array($all[$key])) {
        return array('accounts' => array(), 'imported_ids' => array());
    }
    return array(
        'accounts'     => isset($all[$key]['accounts']) && is_array($all[$key]['accounts']) ? $all[$key]['accounts'] : array(),
        'imported_ids' => isset($all[$key]['imported_ids']) && is_array($all[$key]['imported_ids']) ? $all[$key]['imported_ids'] : array()
    );
}

function save_user_external_accounts($user_email, $data) {
    global $EXTERNAL_FILE;
    $all = load_protected_json($EXTERNAL_FILE);
    $key = strtolower(trim($user_email));
    if (!empty($data['imported_ids']) && count($data['imported_ids']) > 300) {
        $data['imported_ids'] = array_slice($data['imported_ids'], -300, null, true);
    }
    $all[$key] = $data;
    return save_protected_json($EXTERNAL_FILE, $all);
}

function send_cpanel_smtp($from, $password, $to, $subject, $html_body, $forwarded_attachments = array()) {
    global $UPLOAD_DIR, $PRIVATE_ATTACHMENT_DIR;
    $html_body = normalize_signature_images($html_body);

    $ctx = stream_context_create(array(
        'ssl' => array('verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true)
    ));
    $socket = @stream_socket_client("ssl://localhost:465", $errno, $errstr, 10, STREAM_CLIENT_CONNECT, $ctx);
    if (!$socket) {
        $socket = @stream_socket_client("tcp://localhost:25", $errno, $errstr, 10, STREAM_CLIENT_CONNECT);
    }

    $sender_name = $_SESSION['wm_email'];
    if (preg_match('/^([^@]+)/', $_SESSION['wm_email'], $m)) {
        $sender_name = ucwords(str_replace(array('.', '_'), ' ', $m[1]));
    }

    $formatted_from = "=?UTF-8?B?" . base64_encode($sender_name) . "?= <$from>";
    $formal_subject = (stripos($subject, 'Assunto:') === 0 || stripos($subject, 'Enc:') === 0 || stripos($subject, 'Re:') === 0) ? $subject : "Assunto: " . $subject;

    $raw_mime  = "Date: " . date("r") . "\r\n";
    $raw_mime .= "To: <$to>\r\n";
    $raw_mime .= "From: " . $formatted_from . "\r\n";
    $raw_mime .= "Subject: =?UTF-8?B?" . base64_encode($formal_subject) . "?=\r\n";
    $raw_mime .= "MIME-Version: 1.0\r\n";

    if (!empty($forwarded_attachments) && is_array($forwarded_attachments)) {
        $boundary = "----=_NextPart_RE9_" . md5(uniqid((string)time(), true));
        $raw_mime .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\r\n\r\n";
        $raw_mime .= "--$boundary\r\n";
        $raw_mime .= "Content-Type: text/html; charset=UTF-8\r\n";
        $raw_mime .= "Content-Transfer-Encoding: base64\r\n\r\n";
        $raw_mime .= chunk_split(base64_encode($html_body)) . "\r\n";

        foreach ($forwarded_attachments as $att) {
            $safe_file = basename(isset($att['file']) ? $att['file'] : '');
            $orig_name = isset($att['filename']) ? $att['filename'] : $safe_file;
            $owner_key = substr(hash('sha256', strtolower((string)$from)), 0, 32);
            $full_path = $PRIVATE_ATTACHMENT_DIR . '/' . $owner_key . '/' . $safe_file;

            if (preg_match('/^att_[a-f0-9]{32}_[a-zA-Z0-9._-]+$/', $safe_file) && file_exists($full_path) && is_file($full_path)) {
                $file_data = @file_get_contents($full_path);
                $encoded_name = "=?UTF-8?B?" . base64_encode($orig_name) . "?=";
                $raw_mime .= "--$boundary\r\n";
                $raw_mime .= "Content-Type: application/octet-stream; name=\"$encoded_name\"\r\n";
                $raw_mime .= "Content-Transfer-Encoding: base64\r\n";
                $raw_mime .= "Content-Disposition: attachment; filename=\"$encoded_name\"\r\n\r\n";
                $raw_mime .= chunk_split(base64_encode($file_data)) . "\r\n";
            }
        }
        $raw_mime .= "--$boundary--\r\n";
    } else {
        $raw_mime .= "Content-Type: text/html; charset=UTF-8\r\n";
        $raw_mime .= "Content-Transfer-Encoding: base64\r\n\r\n";
        $raw_mime .= chunk_split(base64_encode($html_body));
    }

    if (!$socket) {
        $headers = "MIME-Version: 1.0\r\nContent-type: text/html; charset=UTF-8\r\nFrom: " . $formatted_from . "\r\nReply-To: <$from>\r\n";
        if (@mail($to, "=?UTF-8?B?" . base64_encode($formal_subject) . "?=", $html_body, $headers)) {
            $imap = new CpanelImapSocket();
            if ($imap->connect($from, $password)) {
                $imap->appendMessageToFolder('INBOX.Sent', $raw_mime, '\\Seen');
                $imap->close();
            }
            return array('status' => 'ok');
        }
        return array('status' => 'error', 'msg' => "Erro de conexão SMTP ($errstr)");
    }

    while ($s = fgets($socket, 515)) { if (substr($s, 3, 1) == " ") break; }
    $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
    fputs($socket, "EHLO $host\r\n");
    while ($s = fgets($socket, 515)) { if (substr($s, 3, 1) == " ") break; }

    fputs($socket, "AUTH LOGIN\r\n"); fgets($socket, 515);
    fputs($socket, base64_encode($from) . "\r\n"); fgets($socket, 515);
    fputs($socket, base64_encode($password) . "\r\n");
    $auth = fgets($socket, 515);

    if (strpos($auth, '235') === false) {
        fclose($socket);
        return array('status' => 'error', 'msg' => 'Falha na autenticação SMTP.');
    }

    fputs($socket, "MAIL FROM: <$from>\r\n"); fgets($socket, 515);
    fputs($socket, "RCPT TO: <$to>\r\n");     fgets($socket, 515);
    fputs($socket, "DATA\r\n");               fgets($socket, 515);

    fputs($socket, $raw_mime . "\r\n.\r\n");
    $res = fgets($socket, 515);
    fputs($socket, "QUIT\r\n");
    fclose($socket);

    if (strpos($res, '250') !== false) {
        $imap = new CpanelImapSocket();
        if ($imap->connect($from, $password)) {
            $imap->appendMessageToFolder('INBOX.Sent', $raw_mime, '\\Seen');
            $imap->close();
        }
        return array('status' => 'ok');
    }
    return array('status' => 'error', 'msg' => 'Falha ao enviar: ' . trim($res));
}

// =========================================================================
// AGENDA RE9 - armazenamento por conta e lembrete diário
// =========================================================================
function agenda_load_all() {
    global $AGENDA_FILE;
    $data = load_protected_json($AGENDA_FILE);
    return is_array($data) ? $data : array();
}
function agenda_save_all($data) {
    global $AGENDA_FILE;
    return save_protected_json($AGENDA_FILE, $data);
}
function agenda_value($array, $key, $default = '') {
    return (is_array($array) && isset($array[$key])) ? $array[$key] : $default;
}
function agenda_random_id($bytes = 10) {
    $raw = function_exists('openssl_random_pseudo_bytes') ? openssl_random_pseudo_bytes($bytes) : false;
    if ($raw === false) { $raw = substr(hash('sha256', uniqid((string)mt_rand(), true)), 0, $bytes * 2); return $raw; }
    return bin2hex($raw);
}
function agenda_clean_text($value, $max = 500) {
    $value = trim(strip_tags((string)$value));
    if (function_exists('mb_substr')) return mb_substr($value, 0, $max, 'UTF-8');
    return substr($value, 0, $max);
}
function agenda_log_message($message) {
    error_log('[RE9 AGENDA] ' . trim((string)$message));
}

/** Retorna o horário padrão do lembrete: 30 minutos antes do compromisso. */
function agenda_default_reminder_time($appointment_time) {
    $appointment_time = trim((string)$appointment_time);
    if (!preg_match('/^([01]\d|2[0-3]):[0-5]\d$/', $appointment_time)) {
        return '06:00';
    }
    $parts = explode(':', $appointment_time);
    $minutes = max(0, ((int)$parts[0] * 60 + (int)$parts[1]) - 30);
    return sprintf('%02d:%02d', (int)floor($minutes / 60), $minutes % 60);
}

/**
 * Envia os compromissos de hoje para a própria caixa de cada usuário.
 * O arquivo de trava impede que duas execuções do Cron enviem a mesma
 * mensagem simultaneamente. Um compromisso só é marcado como enviado
 * quando mail() confirma que o servidor aceitou a mensagem.
 */
function agenda_send_daily_reminders() {
    global $DATA_DIR;

    $lock_path = rtrim($DATA_DIR, '/\\') . '/agenda_reminder_send.lock';
    $lock_handle = @fopen($lock_path, 'c');
    if (!$lock_handle) {
        agenda_log_message('Não foi possível abrir o arquivo de trava do envio.');
        return array('status' => 'error', 'sent_accounts' => 0, 'sent_appointments' => 0, 'failed_accounts' => 0, 'errors' => array('Não foi possível abrir o arquivo de trava.'));
    }

    if (!@flock($lock_handle, LOCK_EX | LOCK_NB)) {
        fclose($lock_handle);
        return array('status' => 'busy', 'sent_accounts' => 0, 'sent_appointments' => 0, 'failed_accounts' => 0, 'errors' => array());
    }

    $all = agenda_load_all();
    $today = date('Y-m-d');
    $current_time = date('H:i');
    $sent_accounts = 0;
    $sent_appointments = 0;
    $failed_accounts = 0;
    $errors = array();

    foreach ($all as $email => &$items) {
        $email = strtolower(trim((string)$email));
        if (!filter_var($email, FILTER_VALIDATE_EMAIL) || !is_array($items)) {
            continue;
        }

        $today_items = array();
        $pending_indexes = array();
        foreach ($items as $index => $item) {
            if (!is_array($item)) {
                continue;
            }
            $item_date = (string)agenda_value($item, 'date');
            $already_sent = trim((string)agenda_value($item, 'reminder_sent'));
            $item_reminder_time = trim((string)agenda_value($item, 'reminder_time'));
            if (!preg_match('/^([01]\d|2[0-3]):[0-5]\d$/', $item_reminder_time)) {
                // Compromissos antigos recebem, automaticamente, lembrete 30 min antes.
                $item_reminder_time = agenda_default_reminder_time(agenda_value($item, 'time'));
            }
            if ($item_date === $today && $already_sent === '' && $current_time >= $item_reminder_time) {
                $item['reminder_time'] = $item_reminder_time;
                $today_items[] = $item;
                $pending_indexes[] = $index;
            }
        }

        if (empty($today_items)) {
            continue;
        }

        $rows = '';
        foreach ($today_items as $appointment) {
            $rows .= '<section style="padding:14px;margin:12px 0;border:1px solid #dbe3ed;border-radius:10px">';
            $fields = array(
                'Assunto' => agenda_value($appointment, 'subject'),
                'Tipo' => agenda_value($appointment, 'type'),
                'Pessoa' => agenda_value($appointment, 'person'),
                'Horário' => agenda_value($appointment, 'time'),
                'Horário do lembrete por e-mail' => agenda_value($appointment, 'reminder_time', agenda_default_reminder_time(agenda_value($appointment, 'time'))),
                'Horário de chegada' => agenda_value($appointment, 'arrival'),
                'Local' => agenda_value($appointment, 'location'),
                'Observações' => agenda_value($appointment, 'notes')
            );
            foreach ($fields as $label => $value) {
                $value = trim((string)$value);
                if ($value !== '') {
                    $rows .= '<p><strong>' . htmlspecialchars($label, ENT_QUOTES, 'UTF-8') . ':</strong> ' . nl2br(htmlspecialchars($value, ENT_QUOTES, 'UTF-8')) . '</p>';
                }
            }
            $rows .= '</section>';
        }

        $body = '<html><body style="font-family:Arial,sans-serif;color:#172033">'
            . '<h2>Lembrete de compromisso</h2>'
            . '<p>Você programou este aviso para receber os compromissos abaixo em ' . date('d/m/Y') . '.</p>'
            . $rows
            . '<p style="color:#64748b;font-size:12px">Mensagem automática do RE9 EMAIL.</p>'
            . '</body></html>';
        $subject = '=?UTF-8?B?' . base64_encode('Lembrete de compromisso da AGENDA') . '?=';
        $headers = "MIME-Version: 1.0\r\n"
            . "Content-Type: text/html; charset=UTF-8\r\n"
            . 'From:  AGENDA <' . $email . ">\r\n"
            . 'Reply-To: ' . $email . "\r\n"
            . "X-RE9-Agenda-Reminder: 1\r\n"
            . "X-Mailer: RE9 EMAIL Agenda\r\n";


        // Captura o aviso real do PHP, sem exibi-lo na tela do usuário.
        $mail_warning = '';
        set_error_handler(function ($severity, $message) use (&$mail_warning) {
            if ($severity === E_WARNING) {
                $mail_warning = (string)$message;
                return true;
            }
            return false;
        }, E_WARNING);
        $mail_ok = mail($email, $subject, $body, $headers, '-f' . $email);
        restore_error_handler();

        if ($mail_ok) {
            foreach ($pending_indexes as $index) {
                if (isset($items[$index]) && is_array($items[$index])) {
                    $items[$index]['reminder_sent'] = date('c');
                    unset($items[$index]['reminder_error']);
                }
            }
            $sent_accounts++;
            $sent_appointments += count($pending_indexes);
        } else {
            $failed_accounts++;
            $error_message = $mail_warning !== '' ? $mail_warning : 'A função mail() retornou false sem informar o motivo.';
            $errors[] = $email . ': ' . $error_message;
            agenda_log_message('Falha ao enviar para ' . $email . ': ' . $error_message);
            // Mantém reminder_sent vazio para permitir nova tentativa na próxima execução.
            foreach ($pending_indexes as $index) {
                if (isset($items[$index]) && is_array($items[$index])) {
                    $items[$index]['reminder_error'] = date('c') . ' - ' . $error_message;
                }
            }
        }
    }
    unset($items);

    $save_ok = agenda_save_all($all);
    if (!$save_ok) {
        $errors[] = 'Não foi possível salvar o controle dos lembretes no arquivo da agenda.';
        agenda_log_message('Falha ao salvar o arquivo de controle da agenda após o processamento.');
    }

    @flock($lock_handle, LOCK_UN);
    fclose($lock_handle);

    $status = (!$save_ok || $failed_accounts > 0) ? 'partial' : 'ok';
    return array(
        'status' => $status,
        'sent_accounts' => $sent_accounts,
        'sent_appointments' => $sent_appointments,
        'failed_accounts' => $failed_accounts,
        'errors' => $errors
    );
}

/**
 * Plano de recuperação: se o Cron não executar, a atividade de uma conta
 * conectada tenta enviar os lembretes cujo horário escolhido já chegou.
 * Isso é uma proteção extra; não substitui o Cron para garantir o horário.
 */
function agenda_auto_recovery_if_needed() {
    global $DATA_DIR;

    if (empty($_SESSION['wm_email'])) {
        return;
    }

    $throttle_path = rtrim($DATA_DIR, '/\\') . '/agenda_auto_recovery.dat';
    $handle = @fopen($throttle_path, 'c+');
    if (!$handle) {
        agenda_log_message('Não foi possível abrir o controle da recuperação automática.');
        return;
    }

    if (!@flock($handle, LOCK_EX | LOCK_NB)) {
        fclose($handle);
        return;
    }

    rewind($handle);
    $last_attempt = (int)trim((string)stream_get_contents($handle));
    if ($last_attempt > 0 && (time() - $last_attempt) < 60) {
        @flock($handle, LOCK_UN);
        fclose($handle);
        return;
    }

    ftruncate($handle, 0);
    rewind($handle);
    fwrite($handle, (string)time());
    fflush($handle);
    @flock($handle, LOCK_UN);
    fclose($handle);

    $result = agenda_send_daily_reminders();
    if (isset($result['status']) && in_array($result['status'], array('error', 'partial'), true)) {
        agenda_log_message('Recuperação automática: ' . implode(' | ', (array)get_val($result, 'errors', array())));
    }
}

// Endpoint protegido para execução pelo Cron da hospedagem.
// O Cron pode chamar a URL a cada minuto; cada compromisso só dispara no horário escolhido.
if (isset($_GET['cron_agenda'])) {
    $saved_key = trim((string)get_val($APP_CONFIG, 'agenda_cron_key'));
    $given_key = (string)$_GET['cron_agenda'];
    if ($saved_key === '' || !hash_equals($saved_key, $given_key)) {
        http_response_code(403);
        exit('Acesso negado');
    }

    header('Content-Type: text/plain; charset=UTF-8');
    $result = agenda_send_daily_reminders();
    if (get_val($result, 'status') === 'busy') {
        echo 'Outra execução da agenda já está em andamento. Tente novamente na próxima verificação.';
        exit;
    }

    echo 'RE9 EMAIL - Agenda automática' . PHP_EOL;
    echo 'Data/hora local: ' . date('d/m/Y H:i:s') . ' (America/Sao_Paulo)' . PHP_EOL;
    echo 'Contas com e-mail aceito pelo servidor: ' . (int)get_val($result, 'sent_accounts', 0) . PHP_EOL;
    echo 'Compromissos incluídos: ' . (int)get_val($result, 'sent_appointments', 0) . PHP_EOL;
    echo 'Contas com falha: ' . (int)get_val($result, 'failed_accounts', 0) . PHP_EOL;
    if (!empty($result['errors'])) {
        foreach ($result['errors'] as $error) {
            echo 'ERRO: ' . $error . PHP_EOL;
        }
    }
    if (get_val($result, 'status') === 'ok' && (int)get_val($result, 'sent_accounts', 0) === 0) {
        echo 'Nenhum lembrete chegou ao horário programado neste momento.' . PHP_EOL;
    }
    exit;
}

// Recuperação adicional se a hospedagem não executar o Cron.
// Só atua em sessões autenticadas e respeita o horário individual de cada lembrete.
agenda_auto_recovery_if_needed();

// =========================================================================
// MENSAGENS PRIVADAS RE9 - ENTRE CONTAS ADICIONADAS À REDE
// =========================================================================
function private_messages_lock($exclusive = true) {
    global $PRIVATE_MESSAGES_FILE;
    $handle = @fopen($PRIVATE_MESSAGES_FILE . '.lock', 'c');
    if (!$handle) return false;
    $mode = $exclusive ? LOCK_EX : LOCK_SH;
    if (!@flock($handle, $mode)) {
        @fclose($handle);
        return false;
    }
    return $handle;
}

function private_messages_unlock($handle) {
    if (is_resource($handle)) {
        @flock($handle, LOCK_UN);
        @fclose($handle);
    }
}

function private_messages_load_locked() {
    global $PRIVATE_MESSAGES_FILE;
    $items = load_protected_json($PRIVATE_MESSAGES_FILE);
    return is_array($items) ? $items : array();
}

function private_messages_save_locked($items) {
    global $PRIVATE_MESSAGES_FILE;
    $guard = "<?php header('HTTP/1.0 403 Forbidden'); exit; ?>\n";
    $json = json_encode(array_values($items), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    if ($json === false) return false;
    return @file_put_contents($PRIVATE_MESSAGES_FILE, $guard . $json, LOCK_EX) !== false;
}

function private_messages_find_contact($owner, $peer_email) {
    global $CONTACTS_FILE;
    $all = load_protected_json($CONTACTS_FILE);
    $contacts = isset($all[$owner]) && is_array($all[$owner]) ? $all[$owner] : array();
    foreach ($contacts as $contact) {
        $email = strtolower(trim((string)agenda_value($contact, 'email', '')));
        if ($email !== '' && $email === strtolower(trim($peer_email))) return $contact;
    }
    return false;
}

function private_messages_peer_online($peer_email) {
    global $ONLINE_FILE;
    $online = load_protected_json($ONLINE_FILE);
    $peer_email = strtolower(trim($peer_email));
    if (!is_array($online) || $peer_email === '') return false;
    $now = time();
    foreach ($online as $key => $info) {
        if (!is_array($info)) continue;
        $row_email = strtolower((string)(isset($info['email']) ? $info['email'] : explode('|', (string)$key)[0]));
        $last_seen = (int)agenda_value($info, 'last_seen', 0);
        if ($row_email === $peer_email && $last_seen > 0 && ($now - $last_seen) <= 45) return true;
    }
    return false;
}

function private_messages_peer_name($owner, $peer_email) {
    global $DIRECTORY_NAMES_FILE;
    $contact = private_messages_find_contact($owner, $peer_email);
    $name = is_array($contact) ? trim((string)agenda_value($contact, 'name', '')) : '';
    if ($name !== '') return $name;

    // Quando a pessoa ainda não salvou o remetente na agenda pessoal,
    // usa o nome público informado no cadastro da conta RE9.
    $public_names = load_protected_json($DIRECTORY_NAMES_FILE);
    $email_key = strtolower(trim((string)$peer_email));
    if (isset($public_names[$email_key]) && trim((string)$public_names[$email_key]) !== '') {
        return trim((string)$public_names[$email_key]);
    }

    $username = strstr($email_key, '@', true);
    if ($username === false || $username === '') $username = $email_key;
    return ucfirst(str_replace(array('.', '_', '-'), ' ', $username));
}

// =========================================================================
// CENTRAL DE VENDAS RE9 - PRODUTOS, PEDIDOS, CHAT E NOTIFICAÇÕES
// =========================================================================
function sales_orders_load() {
    global $SALES_ORDERS_FILE;
    $orders = load_protected_json($SALES_ORDERS_FILE);
    return is_array($orders) ? $orders : array();
}

function sales_orders_lock() {
    global $SALES_ORDERS_FILE;
    $handle = @fopen($SALES_ORDERS_FILE . '.lock', 'c');
    if (!$handle) return false;
    if (!@flock($handle, LOCK_EX)) { @fclose($handle); return false; }
    return $handle;
}

function sales_orders_unlock($handle) {
    if (is_resource($handle)) { @flock($handle, LOCK_UN); @fclose($handle); }
}

function sales_orders_save_locked($orders) {
    global $SALES_ORDERS_FILE;
    return save_protected_json($SALES_ORDERS_FILE, array_values($orders));
}

function sales_resolve_seller_email($ad, $exclude_email = '') {
    global $APP_CONFIG;
    $domain = strtolower(trim((string)get_val($APP_CONFIG, 'domain_name', 're9.rio.br')));
    $exclude_email = strtolower(trim((string)$exclude_email));
    $candidates = array();

    if (is_array($ad)) {
        $candidates[] = agenda_value($ad, 'seller_email', '');
    }
    $candidates[] = get_val($APP_CONFIG, 'sales_fallback_seller_email', '');

    $admins = get_val($APP_CONFIG, 'admin_emails', array());
    if (is_array($admins)) {
        foreach ($admins as $admin_email) $candidates[] = $admin_email;
    }
    $candidates[] = 'suporte@' . $domain;

    foreach ($candidates as $candidate) {
        $candidate = strtolower(trim((string)$candidate));
        // Anunciantes podem usar qualquer domínio hospedado na VPS. O endereço
        // é escolhido a partir do próprio anúncio e validado como e-mail; não
        // é mais limitado ao domínio principal RE9.
        if (!filter_var($candidate, FILTER_VALIDATE_EMAIL) || $candidate === $exclude_email) continue;
        return $candidate;
    }
    return '';
}

function sales_get_products() {
    global $APP_CONFIG, $CONFIG_FILE;
    $products = array();

    // Na instalação central e nas instalações locais não vinculadas, releia
    // o arquivo persistente para refletir alterações recentes do Banco de Cartazes.
    // Em domínio cliente federado, use primeiro o catálogo recém-sincronizado da
    // Central Renove; o arquivo local pode conter uma cópia antiga do catálogo.
    $pool = array();
    if (re9_central_is_client_connected()) {
        $pool = isset($APP_CONFIG['ads_pool']) && is_array($APP_CONFIG['ads_pool']) ? $APP_CONFIG['ads_pool'] : array();
    } else {
        $config_for_store = array();
        if (!empty($CONFIG_FILE) && file_exists($CONFIG_FILE)) $config_for_store = load_protected_json($CONFIG_FILE);
        if (isset($config_for_store['ads_pool']) && is_array($config_for_store['ads_pool'])) $pool = $config_for_store['ads_pool'];
        else $pool = isset($APP_CONFIG['ads_pool']) && is_array($APP_CONFIG['ads_pool']) ? $APP_CONFIG['ads_pool'] : array();
    }

    // Todos os cartazes cadastrados no Banco de Cartazes são considerados na
    // vitrine. Os anúncios antigos não tinham o campo is_product; exigir esse
    // campo fazia produtos já publicados desaparecerem da loja.
    foreach ($pool as $pool_key => $ad) {
        if (!is_array($ad)) continue;

        $ad_id = trim((string)agenda_value($ad, 'id', agenda_value($ad, 'ad_id', '')));
        $title = trim((string)agenda_value($ad, 'title', agenda_value($ad, 'ad_title', agenda_value($ad, 'name', ''))));
        if ($title === '') continue;

        // Ignora somente o cartaz padrão de demonstração, não os anúncios reais.
        if ($ad_id !== '' && strpos($ad_id, 'ad_def_') === 0) continue;

        // Compatibilidade com registros antigos que não possuam identificador.
        if ($ad_id === '') {
            $identity_source = json_encode($ad);
            $ad_id = 'legacy_ad_' . substr(md5($identity_source . '|' . (string)$pool_key), 0, 16);
        }

        $ad['id'] = $ad_id;
        $ad['title'] = $title;
        if (!isset($ad['description'])) $ad['description'] = agenda_value($ad, 'ad_desc', '');
        if (!isset($ad['sender'])) $ad['sender'] = agenda_value($ad, 'ad_sender', 'Anunciante RE9');
        if (!isset($ad['image'])) $ad['image'] = agenda_value($ad, 'ad_image', '');
        if (!empty($ad['image'])) $ad['image'] = re9_public_image_url($ad['image']);

        $price = isset($ad['price']) ? (float)$ad['price'] : (isset($ad['ad_price']) ? (float)$ad['ad_price'] : 0);
        if ($price < 0) $price = 0;
        $seller = sales_resolve_seller_email($ad);
        $ad['price'] = $price;
        $ad['price_pending'] = ($price <= 0);
        $ad['seller_email'] = $seller;
        if (empty($ad['category'])) $ad['category'] = 'Geral';
        if (empty($ad['fulfillment']) || !in_array($ad['fulfillment'], array('digital','physical','service','made_to_order'), true)) {
            $ad['fulfillment'] = 'service';
        }

        $products[] = $ad;
    }

    return $products;
}

function sales_find_product($product_id) {
    foreach (sales_get_products() as $product) {
        if ((string)agenda_value($product, 'id', '') === (string)$product_id) return $product;
    }
    return false;
}

function sales_product_url($product_id) {
    $script = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : 'index20.php';
    return $script . '?loja=checkout&id=' . rawurlencode((string)$product_id);
}

/** Resolve anúncios para o domínio em uso: produtos abrem o checkout local; links vazios/legados abrem a loja. */
function re9_build_ad_target_url($ad) {
    $script = isset($_SERVER['SCRIPT_NAME']) && trim((string)$_SERVER['SCRIPT_NAME']) !== '' ? (string)$_SERVER['SCRIPT_NAME'] : '/index.php';
    if (substr($script, 0, 1) !== '/') $script = '/' . $script;
    $storeHome = $script . '?loja=1';
    if (!is_array($ad)) return $storeHome;

    $productId = trim((string)agenda_value($ad, 'id', agenda_value($ad, 'ad_id', '')));
    $savedUrl = trim((string)agenda_value($ad, 'url', ''));
    $savedParts = @parse_url($savedUrl);
    $savedQuery = array();
    if (is_array($savedParts) && !empty($savedParts['query'])) parse_str($savedParts['query'], $savedQuery);
    $isSavedCheckout = isset($savedQuery['loja']) && $savedQuery['loja'] === 'checkout';
    $isProduct = !empty($ad['is_product']) && (string)$ad['is_product'] !== '0';
    if ($isProduct || $isSavedCheckout) {
        $targetId = $productId !== '' ? $productId : trim((string)agenda_value($savedQuery, 'id', ''));
        return $targetId !== '' ? $script . '?loja=checkout&id=' . rawurlencode($targetId) : $storeHome;
    }

    $raw = trim((string)agenda_value($ad, 'external_url', $savedUrl));
    if ($raw === '' || $raw === '#') return $storeHome;
    if (preg_match('/(?:^|\.)re9seusite\.com\.br$/i', (string)parse_url((strpos($raw, '://') === false ? 'https://' . $raw : $raw), PHP_URL_HOST))) return $storeHome;
    if (stripos($raw, 'javascript:') === 0 || stripos($raw, 'data:') === 0 || stripos($raw, 'vbscript:') === 0) return $storeHome;

    // URLs de checkout gravadas pela instalação central são reconstruídas no domínio cliente.
    $parts = @parse_url($raw);
    $query = array();
    if (is_array($parts) && !empty($parts['query'])) parse_str($parts['query'], $query);
    if (isset($query['loja']) && $query['loja'] === 'checkout') {
        $targetId = $productId !== '' ? $productId : trim((string)agenda_value($query, 'id', ''));
        if ($targetId !== '') return $script . '?loja=checkout&id=' . rawurlencode($targetId);
    }

    // Aceita apenas HTTP/HTTPS para destinos externos. Um domínio sem esquema recebe HTTPS.
    if (strpos($raw, '//') === 0) $raw = 'https:' . $raw;
    elseif (!preg_match('#^https?://#i', $raw) && preg_match('/^[a-z0-9.-]+\.[a-z]{2,}(?::\d+)?(?:\/|$)/i', $raw)) $raw = 'https://' . $raw;
    $scheme = strtolower((string)parse_url($raw, PHP_URL_SCHEME));
    if ($scheme !== 'http' && $scheme !== 'https') {
        // Caminhos relativos internos são permitidos apenas no próprio domínio.
        if (isset($raw[0]) && $raw[0] === '/') return $raw;
        return $storeHome;
    }
    if (!filter_var($raw, FILTER_VALIDATE_URL)) return $storeHome;
    return $raw;
}

function sales_public_name($email) {
    global $DIRECTORY_NAMES_FILE;
    $email = strtolower(trim((string)$email));
    $names = load_protected_json($DIRECTORY_NAMES_FILE);
    if (isset($names[$email]) && trim((string)$names[$email]) !== '') return trim((string)$names[$email]);
    $part = strstr($email, '@', true);
    if ($part === false || $part === '') $part = $email;
    return ucfirst(str_replace(array('.', '_', '-'), ' ', $part));
}

function sales_ensure_chat_pair($buyer_email, $buyer_name, $seller_email, $seller_name) {
    global $CONTACTS_FILE;
    $buyer_email = strtolower(trim($buyer_email));
    $seller_email = strtolower(trim($seller_email));
    $contacts = load_protected_json($CONTACTS_FILE);
    if (!is_array($contacts)) $contacts = array();
    $pairs = array(
        array('owner'=>$buyer_email, 'peer'=>$seller_email, 'name'=>$seller_name),
        array('owner'=>$seller_email, 'peer'=>$buyer_email, 'name'=>$buyer_name)
    );
    foreach ($pairs as $pair) {
        $owner = $pair['owner'];
        if (!isset($contacts[$owner]) || !is_array($contacts[$owner])) $contacts[$owner] = array();
        $exists = false;
        foreach ($contacts[$owner] as $contact) {
            if (strtolower(trim((string)agenda_value($contact, 'email', ''))) === $pair['peer']) { $exists = true; break; }
        }
        if (!$exists) {
            $contacts[$owner][] = array(
                'id' => agenda_random_id(12),
                'name' => $pair['name'],
                'phone' => '',
                'email' => $pair['peer'],
                'company' => 'Contato de pedido RE9',
                'notes' => 'Contato conectado automaticamente por uma compra realizada na Loja RE9.',
                'updated_at' => date('c')
            );
        }
    }
    return save_protected_json($CONTACTS_FILE, $contacts);
}

function sales_send_chat_message($from_email, $to_email, $message) {
    $lock = private_messages_lock(true);
    if (!$lock) return false;
    $messages = private_messages_load_locked();
    $messages[] = array(
        'id' => agenda_random_id(12),
        'from' => strtolower(trim($from_email)),
        'to' => strtolower(trim($to_email)),
        'message' => (string)$message,
        'created' => time(),
        'recipient_was_offline' => !private_messages_peer_online($to_email),
        'read' => false,
        'read_at' => 0,
        'source' => 'sales_order'
    );
    if (count($messages) > 10000) $messages = array_slice($messages, -8000);
    $ok = private_messages_save_locked($messages);
    private_messages_unlock($lock);
    return $ok;
}

function re9_notify_new_member($member_email, $member_name, $phone, $recovery_email, $created_at) {
    $to = 'suporte@re9.rio.br';
    $from = 'suporte@re9.rio.br';
    $subject = '=?UTF-8?B?' . base64_encode('Novo membro') . '?=';
    $body = "NOVO MEMBRO CADASTRADO NO RE9\r\n\r\n";
    $body .= 'Nome: ' . trim((string)$member_name) . "\r\n";
    $body .= 'Nova conta RE9: ' . strtolower(trim((string)$member_email)) . "\r\n";
    $body .= 'Telefone informado: ' . preg_replace('/\\D/', '', (string)$phone) . "\r\n";
    $body .= 'E-mail secundário para recuperação: ' . strtolower(trim((string)$recovery_email)) . "\r\n";
    $body .= 'Data do cadastro: ' . date('d/m/Y H:i:s', (int)$created_at) . "\r\n\r\n";
    $body .= "STATUS: AGUARDANDO CONFERÊNCIA E LIBERAÇÃO ADMINISTRATIVA.\r\n\r\n";
    $body .= "Acesse o painel administrativo do RE9, confira os dados do cliente e utilize o botão Liberar após a checagem.\r\n";
    $headers = "MIME-Version: 1.0\r\n";
    $headers .= "Content-Type: text/plain; charset=UTF-8\r\n";
    $headers .= 'From: RE9 - Novo membro <' . $from . ">\r\n";
    $headers .= 'Reply-To: ' . $from . "\r\n";
    $headers .= "X-Mailer: RE9 EMAIL - Aviso de novo membro\r\n";
    return @mail($to, $subject, $body, $headers, '-f' . $from);
}

function sales_notify_support_email($order) {
    global $SALES_SUPPORT_EMAIL, $APP_CONFIG;
    $support = $SALES_SUPPORT_EMAIL;
    $subject_text = 'Nova compra RE9 - Pedido ' . agenda_value($order, 'id', '');
    $subject = '=?UTF-8?B?' . base64_encode($subject_text) . '?=';
    $from_domain = strtolower(trim((string)agenda_value($APP_CONFIG, 'domain_name', 're9.rio.br')));
    $from_email = !empty($_SESSION['wm_email']) && filter_var($_SESSION['wm_email'], FILTER_VALIDATE_EMAIL) ? strtolower(trim((string)$_SESSION['wm_email'])) : ('suporte@' . $from_domain);
    $body = "NOVA COMPRA NA LOJA RE9\r\n\r\n";
    $body .= 'Pedido: ' . agenda_value($order, 'id', '') . "\r\n";
    $body .= 'Status: Aguardando confirmação de pagamento' . "\r\n";
    $body .= 'Produto: ' . agenda_value($order, 'product_title', '') . "\r\n";
    $body .= 'Categoria: ' . agenda_value($order, 'category', '') . "\r\n";
    $body .= 'Tipo de entrega: ' . agenda_value($order, 'fulfillment_label', '') . "\r\n";
    $body .= 'Quantidade: ' . (int)agenda_value($order, 'quantity', 1) . "\r\n";
    if (!empty($order['price_pending'])) {
        $body .= "Valor: A COMBINAR COM O ANUNCIANTE\r\n";
        $body .= "Total: A DEFINIR\r\n\r\n";
    } else {
        $body .= 'Valor unitário: R$ ' . number_format((float)agenda_value($order, 'unit_price', 0), 2, ',', '.') . "\r\n";
        $body .= 'Total: R$ ' . number_format((float)agenda_value($order, 'total', 0), 2, ',', '.') . "\r\n\r\n";
    }
    $body .= 'Comprador: ' . agenda_value($order, 'buyer_name', '') . "\r\n";
    $body .= 'E-mail: ' . agenda_value($order, 'buyer_email', '') . "\r\n";
    $body .= 'Telefone: ' . agenda_value($order, 'buyer_phone', '') . "\r\n";
    $body .= 'Endereço: ' . agenda_value($order, 'shipping_address', 'Não informado') . "\r\n";
    $body .= 'Anunciante: ' . agenda_value($order, 'seller_name', '') . "\r\n";
    $body .= 'Conta do anunciante: ' . agenda_value($order, 'seller_email', '') . "\r\n\r\n";
    $body .= 'Observações: ' . agenda_value($order, 'buyer_notes', 'Nenhuma') . "\r\n\r\n";
    $body .= 'Acesse a Central de Vendas: ' . get_webmail_base_url() . basename(isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : 'index20.php') . '?loja=pedidos' . "\r\n";
    $body .= 'Confirme o pagamento e atualize a etapa de produção, entrega ou liberação do produto.' . "\r\n";
    $headers = "MIME-Version: 1.0\r\n";
    $headers .= "Content-Type: text/plain; charset=UTF-8\r\n";
    $headers .= 'From: Loja RE9 <' . $from_email . ">\r\n";
    $headers .= 'Reply-To: ' . agenda_value($order, 'buyer_email', $support) . "\r\n";
    $headers .= "X-Mailer: RE9 EMAIL Central de Vendas\r\n";
    return @mail($support, $subject, $body, $headers, '-f' . $from_email);
}

function sales_order_status_label($status) {
    $labels = array(
        'awaiting_payment_confirmation' => 'Aguardando confirmação de pagamento',
        'payment_confirmed' => 'Pagamento confirmado',
        'in_production' => 'Em produção / preparação',
        'ready_for_delivery' => 'Pronto para entrega',
        'dispatched' => 'Enviado / em transporte',
        'product_released' => 'Produto liberado',
        'completed' => 'Concluído',
        'cancelled' => 'Cancelado'
    );
    return isset($labels[$status]) ? $labels[$status] : 'Aguardando confirmação de pagamento';
}

// =========================================================================
// 4. ROTEADOR AJAX DA API INTERNA
// =========================================================================
if (isset($_GET['api'])) {
    header('Content-Type: application/json; charset=UTF-8');
    header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    header('Pragma: no-cache');
    header('Expires: 0');
    $action = $_GET['api'];

    if ($action === 'client_check_release') {
        if (!empty($RE9_IS_CENTRAL_HUB) || !re9_central_is_client_connected()) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Esta instalação não está vinculada à Central Renove.')); exit; }
        if (empty($_SESSION['wm_email'])) { http_response_code(401); echo json_encode(array('status'=>'error','msg'=>'Sessão do webmail encerrada.')); exit; }
        $beforeVersion = (string)$RE9_CLIENT_BUILD_VERSION;
        $updated = re9_central_client_check_for_updates();
        echo json_encode(array('status'=>'ok','update_applied'=>($updated === true),'before_version'=>$beforeVersion,'message'=>($updated === true ? 'Atualização instalada. Recarregue a página para utilizar a nova versão.' : 'Nenhuma atualização pendente.'))); exit;
    }

    if ($action === 'central_queue_bulk_release') {
        if (empty($RE9_IS_CENTRAL_HUB) || !is_user_admin()) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Ação restrita à Central Renove.')); exit; }
        if ($_SERVER['REQUEST_METHOD'] !== 'POST' || empty($_SESSION['re9_private_csrf']) || !hash_equals((string)$_SESSION['re9_private_csrf'],(string)get_val($_POST,'csrf',''))) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Validação de segurança falhou.')); exit; }
        if (!re9_admin_password_matches(get_val($_POST,'admin_pass',''))) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Senha administrativa incorreta.')); exit; }
        $siteId=strtolower(trim((string)get_val($_POST,'site_id','')));
        $sites=load_protected_json($CENTRAL_SITES_FILE); $reports=load_protected_json($CENTRAL_MAILBOX_REPORT_FILE);
        if (!isset($sites[$siteId]) || empty($sites[$siteId]['enabled'])) { http_response_code(404); echo json_encode(array('status'=>'error','msg'=>'Domínio não cadastrado ou desativado na Central.')); exit; }
        $report=isset($reports[$siteId]) && is_array($reports[$siteId]) ? $reports[$siteId] : array();
        $count=(int)get_val($report,'count',0);
        if ($count < 1) { http_response_code(409); echo json_encode(array('status'=>'error','msg'=>'Esta instalação ainda não enviou o inventário de caixas. Atualize a instalação cliente e aguarde a primeira sincronização.')); exit; }
        $safeCommandToken=re9_central_random_token();
        if ($safeCommandToken === '') { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Não foi possível gerar identificador seguro para a operação.')); exit; }
        $commandId='cmd_'.substr($safeCommandToken,0,24);
        $lock=re9_acquire_file_lock($CENTRAL_COMMANDS_FILE,LOCK_EX);
        if (!$lock) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Não foi possível colocar a operação na fila.')); exit; }
        $commands=load_protected_json($CENTRAL_COMMANDS_FILE); if (!is_array($commands)) $commands=array();
        foreach ($commands as $existingId=>$existingCommand) {
            if (is_array($existingCommand) && strtolower((string)get_val($existingCommand,'site_id',''))===$siteId && get_val($existingCommand,'action','')==='bulk_release_existing_mailboxes' && in_array(get_val($existingCommand,'status',''),array('pending','running'),true)) {
                re9_release_file_lock($lock);
                echo json_encode(array('status'=>'ok','command_id'=>(string)$existingId,'site_id'=>$siteId,'expected_count'=>$count,'message'=>'Já existe uma solicitação de liberação em andamento para este domínio.')); exit;
            }
        }
        $commands[$commandId]=array('id'=>$commandId,'site_id'=>$siteId,'domain'=>$siteId,'action'=>'bulk_release_existing_mailboxes','status'=>'pending','expected_count'=>$count,'created_at'=>time(),'requested_by'=>strtolower((string)$_SESSION['wm_email']));
        $saved=save_protected_json($CENTRAL_COMMANDS_FILE,$commands); re9_release_file_lock($lock);
        if (!$saved) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'A operação não pôde ser salva.')); exit; }
        echo json_encode(array('status'=>'ok','command_id'=>$commandId,'site_id'=>$siteId,'expected_count'=>$count,'message'=>'Solicitação enviada à fila segura. A instalação cliente executará a liberação no próximo acesso ou sincronismo.')); exit;
    }

    // Endpoints de federação entre instalações. As chamadas cliente-servidor usam token
    // individual por domínio; não compartilham senha IMAP, cPanel, contatos nem mensagens privadas.
    if (in_array($action, array('central_client_verify','central_client_pull','central_client_heartbeat','central_client_poll_commands','central_client_command_result','central_client_mailbox_report'), true)) {
        if (empty($RE9_IS_CENTRAL_HUB)) { http_response_code(404); echo json_encode(array('status'=>'error','msg'=>'Endpoint disponível somente na Central Renove.')); exit; }
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); echo json_encode(array('status'=>'error','msg'=>'Método não permitido.')); exit; }
        $siteId = strtolower(trim((string)get_val($_POST,'site_id',''))); $siteToken = trim((string)get_val($_POST,'token',''));
        if (!re9_central_authorize_site($siteId,$siteToken,true)) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Instalação não autorizada ou token inválido.')); exit; }
        if ($action === 'central_client_verify') { echo json_encode(array('status'=>'ok','site_id'=>$siteId,'message'=>'Instalação autorizada pela Central Renove.')); exit; }
        if ($action === 'central_client_pull') { echo json_encode(array('status'=>'ok','site_id'=>$siteId,'public'=>re9_central_public_payload(),'server_time'=>time())); exit; }
        if ($action === 'central_client_poll_commands') {
            $commandLock = re9_acquire_file_lock($CENTRAL_COMMANDS_FILE, LOCK_EX);
            if (!$commandLock) { http_response_code(503); echo json_encode(array('status'=>'error','msg'=>'Não foi possível consultar comandos.')); exit; }
            $commandRows = load_protected_json($CENTRAL_COMMANDS_FILE); if (!is_array($commandRows)) $commandRows=array();
            $pending = array(); $now=time();
            foreach ($commandRows as $commandId=>$commandRow) {
                if (!is_array($commandRow) || strtolower((string)get_val($commandRow,'site_id','')) !== $siteId) continue;
                $status = (string)get_val($commandRow,'status','pending');
                $started = (int)get_val($commandRow,'started_at',0);
                if ($status === 'running' && $started > 0 && ($now-$started) > 600) $status='pending';
                if ($status === 'pending' && count($pending) < 5) {
                    $commandRows[$commandId]['status']='running'; $commandRows[$commandId]['started_at']=$now; $commandRows[$commandId]['attempts']=(int)get_val($commandRow,'attempts',0)+1;
                    $pending[] = array('id'=>(string)$commandId,'action'=>(string)get_val($commandRow,'action',''),'domain'=>(string)get_val($commandRow,'domain',''),'expected_count'=>(int)get_val($commandRow,'expected_count',0));
                }
            }
            save_protected_json($CENTRAL_COMMANDS_FILE,$commandRows); re9_release_file_lock($commandLock);
            echo json_encode(array('status'=>'ok','site_id'=>$siteId,'commands'=>$pending)); exit;
        }
        if ($action === 'central_client_command_result') {
            $commandId = preg_replace('/[^a-z0-9_-]/i','',(string)get_val($_POST,'command_id',''));
            $commandLock = re9_acquire_file_lock($CENTRAL_COMMANDS_FILE, LOCK_EX);
            if (!$commandLock || $commandId === '') { if ($commandLock) re9_release_file_lock($commandLock); http_response_code(400); echo json_encode(array('status'=>'error','msg'=>'Comando inválido.')); exit; }
            $commandRows = load_protected_json($CENTRAL_COMMANDS_FILE); if (!isset($commandRows[$commandId]) || !is_array($commandRows[$commandId]) || strtolower((string)get_val($commandRows[$commandId],'site_id','')) !== $siteId) { re9_release_file_lock($commandLock); http_response_code(404); echo json_encode(array('status'=>'error','msg'=>'Comando não encontrado para esta instalação.')); exit; }
            $resultStatus = get_val($_POST,'result_status','error') === 'ok' ? 'completed' : 'failed';
            $commandRows[$commandId]['status']=$resultStatus; $commandRows[$commandId]['finished_at']=time();
            $commandRows[$commandId]['result_message']=agenda_clean_text(get_val($_POST,'result_message',''),500);
            $commandRows[$commandId]['found_count']=max(0,(int)get_val($_POST,'found_count',0));
            $commandRows[$commandId]['affected_count']=max(0,(int)get_val($_POST,'affected_count',0));
            save_protected_json($CENTRAL_COMMANDS_FILE,$commandRows); re9_release_file_lock($commandLock);
            echo json_encode(array('status'=>'ok','command_id'=>$commandId)); exit;
        }
        if ($action === 'central_client_mailbox_report') {
            $rawInventory = (string)get_val($_POST,'inventory_json','');
            $decodedInventory = json_decode($rawInventory,true);
            if (!is_array($decodedInventory) || count($decodedInventory)>3000) { http_response_code(400); echo json_encode(array('status'=>'error','msg'=>'Inventário inválido ou acima do limite.')); exit; }
            $safeItems=array();
            foreach ($decodedInventory as $item) {
                if (!is_array($item)) continue;
                $mail=strtolower(trim((string)get_val($item,'email','')));
                if (!filter_var($mail,FILTER_VALIDATE_EMAIL) || substr($mail,strrpos($mail,'@')+1) !== $siteId) continue;
                $safeItems[$mail]=array('email'=>$mail,'domain'=>$siteId,'suspended'=>!empty($item['suspended']),'released'=>!empty($item['released']),'release_type'=>preg_match('/^(manual_support|phone_verified|identity_verified)$/',(string)get_val($item,'release_type',''))?(string)$item['release_type']:'');
            }
            $reports=load_protected_json($CENTRAL_MAILBOX_REPORT_FILE); if (!is_array($reports)) $reports=array();
            $reports[$siteId]=array('site_id'=>$siteId,'updated_at'=>time(),'count'=>count($safeItems),'items'=>array_values($safeItems));
            if (!save_protected_json($CENTRAL_MAILBOX_REPORT_FILE,$reports)) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Não foi possível salvar o inventário remoto.')); exit; }
            echo json_encode(array('status'=>'ok','site_id'=>$siteId,'count'=>count($safeItems))); exit;
        }
        $email = strtolower(trim((string)get_val($_POST,'email',''))); $sessionMark = preg_replace('/[^a-f0-9-]/i','',(string)get_val($_POST,'session_mark',''));
        $presenceLock = re9_acquire_file_lock($CENTRAL_PRESENCE_FILE, LOCK_EX);
        if (!$presenceLock) { http_response_code(503); echo json_encode(array('status'=>'error','msg'=>'Não foi possível registrar a presença.')); exit; }
        $presence = load_protected_json($CENTRAL_PRESENCE_FILE); if (!is_array($presence)) $presence = array();
        $presenceKey = $siteId . '|' . ($sessionMark !== '' ? $sessionMark : 'session');
        if (filter_var($email,FILTER_VALIDATE_EMAIL)) {
            $presence[$presenceKey] = array('site_id'=>$siteId,'email'=>$email,'session_mark'=>$sessionMark,'last_seen'=>time(),'device'=>agenda_clean_text(get_val($_POST,'device','Webmail'),40),'login_time'=>agenda_clean_text(get_val($_POST,'login_time',date('H:i:s')),20));
        } else { unset($presence[$presenceKey]); }
        save_protected_json($CENTRAL_PRESENCE_FILE,$presence); re9_release_file_lock($presenceLock);
        $siteLock = re9_acquire_file_lock($CENTRAL_SITES_FILE, LOCK_EX);
        if ($siteLock) { $siteRows=load_protected_json($CENTRAL_SITES_FILE); if (isset($siteRows[$siteId])) { $siteRows[$siteId]['last_seen']=time(); $siteRows[$siteId]['reported_domain']=agenda_clean_text(get_val($_POST,'domain',$siteId),253); save_protected_json($CENTRAL_SITES_FILE,$siteRows); } re9_release_file_lock($siteLock); }
        echo json_encode(array('status'=>'ok','site_id'=>$siteId,'server_time'=>time())); exit;
    }

    if ($action === 'central_issue_site_token') {
        if (empty($RE9_IS_CENTRAL_HUB) || !is_user_admin()) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Apenas um administrador da Central Renove pode cadastrar instalações.')); exit; }
        if ($_SERVER['REQUEST_METHOD'] !== 'POST' || empty($_SESSION['re9_private_csrf']) || !hash_equals((string)$_SESSION['re9_private_csrf'],(string)get_val($_POST,'csrf',''))) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Validação de segurança falhou.')); exit; }
        if (!re9_admin_password_matches(get_val($_POST,'admin_pass',''))) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Senha administrativa incorreta.')); exit; }
        $siteId = strtolower(trim((string)get_val($_POST,'site_id',''))); $siteId = preg_replace('#^https?://#i','',$siteId); $siteId = preg_replace('/[\\/?#].*$/','',$siteId); $siteId = preg_replace('/:\\d+$/','',$siteId); $siteId = preg_replace('/^www\\./','',$siteId); $siteId = rtrim($siteId,'.');
        if (!preg_match('/^(?=.{3,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,63}$/i',$siteId) || $siteId === 're9.rio.br') { http_response_code(400); echo json_encode(array('status'=>'error','msg'=>'Informe o domínio completo do cliente, por exemplo cliente.com.br.')); exit; }
        $token = re9_central_random_token(); if ($token === '') { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'O servidor não conseguiu gerar um token seguro.')); exit; }
        $lock = re9_acquire_file_lock($CENTRAL_SITES_FILE, LOCK_EX); if (!$lock) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Não foi possível registrar o domínio.')); exit; }
        $sites = load_protected_json($CENTRAL_SITES_FILE); if (!is_array($sites)) $sites=array();
        $previous = isset($sites[$siteId]) && is_array($sites[$siteId]) ? $sites[$siteId] : array();
        $sites[$siteId] = array('site_id'=>$siteId,'token_hash'=>hash('sha256',$token),'enabled'=>true,'created_at'=>time(),'last_seen'=>isset($previous['last_seen'])?(int)$previous['last_seen']:0,'reported_domain'=>$siteId,'token_rotated_at'=>time());
        $savedSite = save_protected_json($CENTRAL_SITES_FILE,$sites); re9_release_file_lock($lock);
        if (!$savedSite) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'O token foi gerado, mas não foi possível gravar o cadastro do domínio.')); exit; }
        echo json_encode(array('status'=>'ok','site_id'=>$siteId,'token'=>$token,'hub_url'=>'https://re9.rio.br/webmail9/index.php','setup_url'=>'https://'.$siteId.'/webmail9/index.php?central_setup=1','message'=>'Copie o token agora. Ele só será mostrado nesta emissão.')); exit;
    }

    if ($action === 'central_sites_list') {
        if (empty($RE9_IS_CENTRAL_HUB) || !is_user_admin()) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Acesso restrito à administração da Central Renove.')); exit; }
        $sites=load_protected_json($CENTRAL_SITES_FILE); $rows=array(); $now=time();
        $mailboxReports=load_protected_json($CENTRAL_MAILBOX_REPORT_FILE); if (!is_array($mailboxReports)) $mailboxReports=array();
        $allRemoteMailboxes=array();
        $commandRows=load_protected_json($CENTRAL_COMMANDS_FILE); if (!is_array($commandRows)) $commandRows=array();
        foreach ($sites as $siteId=>$site) {
            if (!is_array($site)) continue;
            $seen=(int)get_val($site,'last_seen',0);
            $report=isset($mailboxReports[$siteId]) && is_array($mailboxReports[$siteId]) ? $mailboxReports[$siteId] : array();
            $items=isset($report['items']) && is_array($report['items']) ? $report['items'] : array();
            $releasedCount=0; foreach ($items as $item) { if (!empty($item['released'])) $releasedCount++; $allRemoteMailboxes[]=$item; }
            $lastCommand=null;
            foreach ($commandRows as $cmd) { if (is_array($cmd) && (string)get_val($cmd,'site_id','')===(string)$siteId && (!$lastCommand || (int)get_val($cmd,'created_at',0)>(int)get_val($lastCommand,'created_at',0))) $lastCommand=$cmd; }
            $rows[]=array('site_id'=>(string)$siteId,'enabled'=>!empty($site['enabled']),'online'=>($seen>0 && ($now-$seen)<=180),'last_seen'=>$seen,'last_seen_text'=>$seen>0?date('d/m/Y H:i:s',$seen):'Ainda não conectou','reported_domain'=>(string)get_val($site,'reported_domain',$siteId),'mailbox_count'=>count($items),'released_count'=>$releasedCount,'mailboxes_updated_at'=>(int)get_val($report,'updated_at',0),'mailboxes_updated_text'=>!empty($report['updated_at'])?date('d/m/Y H:i:s',(int)$report['updated_at']):'Inventário ainda não recebido','last_command_status'=>$lastCommand?(string)get_val($lastCommand,'status',''):'','last_command_message'=>$lastCommand?(string)get_val($lastCommand,'result_message',''):'','last_command_affected'=>$lastCommand?(int)get_val($lastCommand,'affected_count',0):0);
        }
        usort($rows,function($a,$b){return (int)$b['last_seen']-(int)$a['last_seen'];});
        usort($allRemoteMailboxes,function($a,$b){return strcmp((string)$a['email'],(string)$b['email']);});
        $online=get_strictly_connected_webmail_users();
        echo json_encode(array('status'=>'ok','sites'=>$rows,'remote_mailboxes'=>$allRemoteMailboxes,'online_users'=>$online['users'],'online_count'=>$online['online_count'],'central_url'=>'https://re9.rio.br/webmail9/index.php')); exit;
    }

    if ($action === 'central_connect_client') {
        if (!empty($RE9_IS_CENTRAL_HUB)) { http_response_code(400); echo json_encode(array('status'=>'error','msg'=>'Esta é a instalação central; não precisa ser conectada a si mesma.')); exit; }
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); echo json_encode(array('status'=>'error','msg'=>'Método não permitido.')); exit; }
        $token = trim((string)get_val($_POST,'token','')); $siteId = strtolower((string)$RE9_INSTANCE_HOST);
        if (!preg_match('/^(?=.{3,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,63}$/i',$siteId) || strlen($token)<40 || strlen($token)>200) { http_response_code(400); echo json_encode(array('status'=>'error','msg'=>'Domínio ou token inválido.')); exit; }
        $verify = re9_central_post_url('https://re9.rio.br/webmail9/index.php','central_client_verify',array('site_id'=>$siteId,'token'=>$token));
        if (get_val($verify,'status') !== 'ok') { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>get_val($verify,'msg','A Central Renove recusou o token. Confirme o domínio cadastrado.'))); exit; }
        $APP_CONFIG['central_hub_url']='https://re9.rio.br/webmail9/index.php'; $APP_CONFIG['central_site_id']=$siteId; $APP_CONFIG['central_site_token']=$token;
        if (empty($APP_CONFIG['domain_name']) || strtolower((string)$APP_CONFIG['domain_name'])==='re9.rio.br') $APP_CONFIG['domain_name']=$siteId;
        if (!save_protected_json($CONFIG_FILE,$APP_CONFIG)) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Token validado, mas não foi possível salvar a configuração local. Verifique webmail_data.')); exit; }
        $synced = re9_central_sync_public_data(true);
        echo json_encode(array('status'=>'ok','site_id'=>$siteId,'synced'=>$synced,'message'=>'Esta instalação foi vinculada à Central Renove. Anúncios, catálogo da loja e identidade visual serão sincronizados automaticamente. A presença das caixas abertas será exibida na Central Renove.')); exit;
    }

    if ($action === 'central_refresh_public') {
        if (!re9_central_is_client_connected()) { http_response_code(409); echo json_encode(array('status'=>'error','msg'=>'Esta instalação ainda não está conectada à Central Renove.')); exit; }
        $synced = re9_central_sync_public_data(true);
        echo json_encode(array('status'=>$synced?'ok':'error','ads_pool'=>get_val($APP_CONFIG,'ads_pool',array()),'brand_logo'=>get_val($APP_CONFIG,'brand_logo',''),'brand_name'=>get_val($APP_CONFIG,'brand_name',''),'welcome_notice'=>get_val($APP_CONFIG,'central_welcome_notice',array('active'=>false)),'msg'=>$synced?'Conteúdo sincronizado.':'Não foi possível sincronizar agora.')); exit;
    }

    // Canal básico de comunicação permanece disponível mesmo durante a conferência cadastral.
    // Isso permite que o novo membro fale com o suporte e com contatos que ele próprio salvou,
    // sem liberar envio de e-mails, administração, compras ou outras operações restritas.
    $re9_communication_actions = array(
        'contacts_list', 'contacts_save', 'contacts_delete', 're9_directory_search',
        'private_message_send', 'private_message_history', 'private_message_poll'
    );
    $re9_identity_exempt_actions = array_merge(
        array('legacy_identity_start','legacy_identity_confirm','logout','password_recovery_request','password_recovery_reset','presence_ping'),
        $re9_communication_actions
    );

    // Contas sem cadastro de identidade ainda precisam preencher os dados, mas podem contatar o suporte.
    if (!empty($_SESSION['wm_email']) && re9_identity_gate_required($_SESSION['wm_email']) && !in_array($action, $re9_identity_exempt_actions, true)) {
        http_response_code(403);
        echo json_encode(array('status'=>'error','msg'=>'Informe seus dados para enviar a conta à análise administrativa.'));
        exit;
    }
    if (!empty($_SESSION['wm_email']) && re9_account_pending_review($_SESSION['wm_email']) && !is_user_admin()) {
        $readonly_actions = array_merge(array('list_emails','read_email','logout','presence_ping'), $re9_communication_actions);
        if (!in_array($action, $readonly_actions, true)) {
            http_response_code(403);
            echo json_encode(array('status'=>'pending_review','msg'=>'Sua conta está aguardando conferência manual. Enquanto isso, o acesso à caixa permanece somente para leitura; o canal de contatos e suporte continua disponível.'));
            exit;
        }
    }

    if ($action === 'presence_ping') {
        if (empty($_SESSION['wm_email'])) { http_response_code(401); echo json_encode(array('status'=>'unauthorized')); exit; }
        update_user_online_status($_SESSION['wm_email']);
        re9_register_instance(isset($RE9_INSTANCE_HOST) ? $RE9_INSTANCE_HOST : '');
        if (re9_central_is_client_connected()) {
            re9_central_sync_public_data(true);
            $centralHeartbeat = re9_central_send_presence($_SESSION['wm_email']);
            re9_central_process_pending_commands();
            echo json_encode(array('status'=>'ok','central_connected'=>get_val($centralHeartbeat,'status')==='ok','ads_pool'=>get_val($APP_CONFIG,'ads_pool',array()),'brand_logo'=>get_val($APP_CONFIG,'brand_logo',''),'brand_name'=>get_val($APP_CONFIG,'brand_name','')));
        } else { echo json_encode(array('status'=>'ok','central_connected'=>false)); }
        exit;
    }

    if ($action === 'download_attachment') {
        if (empty($_SESSION['wm_email'])) { http_response_code(401); echo 'Autenticação necessária.'; exit; }
        $file = basename((string)get_val($_GET, 'file', ''));
        if (!preg_match('/^att_[a-f0-9]{32}_[a-zA-Z0-9._-]+$/', $file)) { http_response_code(400); echo 'Arquivo inválido.'; exit; }
        $owner_key = substr(hash('sha256', strtolower((string)$_SESSION['wm_email'])), 0, 32);
        $base = realpath($PRIVATE_ATTACHMENT_DIR . '/' . $owner_key);
        $path = $base ? realpath($base . '/' . $file) : false;
        if (!$base || !$path || strpos($path, $base . DIRECTORY_SEPARATOR) !== 0 || !is_file($path)) { http_response_code(404); echo 'Anexo não encontrado.'; exit; }
        $download_name = preg_replace('/[^a-zA-Z0-9._-]/', '_', preg_replace('/^att_[a-f0-9]{32}_/', '', $file));
        header('Content-Type: application/octet-stream');
        header('X-Content-Type-Options: nosniff');
        header('Content-Disposition: attachment; filename="' . $download_name . '"');
        header('Content-Length: ' . filesize($path));
        header('Cache-Control: private, no-store, no-cache, must-revalidate');
        readfile($path);
        exit;
    }

    if ($action === 'legacy_identity_start') {
        if (empty($_SESSION['wm_email'])) { http_response_code(401); echo json_encode(array('status'=>'error','msg'=>'Faça login para confirmar sua conta.')); exit; }
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); echo json_encode(array('status'=>'error','msg'=>'Método não permitido.')); exit; }
        if (empty($_SESSION['re9_private_csrf']) || !hash_equals((string)$_SESSION['re9_private_csrf'], (string)get_val($_POST,'csrf',''))) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Sessão de segurança expirada. Atualize a página.')); exit; }
        $email = strtolower(trim((string)$_SESSION['wm_email']));
        $name = agenda_clean_text(get_val($_POST,'full_name'),100);
        $cpf = preg_replace('/\D/','',(string)get_val($_POST,'cpf'));
        $phone = preg_replace('/\D/','',(string)get_val($_POST,'phone'));
        if (count(preg_split('/\s+/', trim($name))) < 2 || strlen($name) < 5) { echo json_encode(array('status'=>'error','msg'=>'Informe seu nome completo, com nome e sobrenome.')); exit; }
        if (!re9_valid_cpf($cpf)) { echo json_encode(array('status'=>'error','msg'=>'CPF inválido. Confira os 11 números informados.')); exit; }
        if (strlen($phone) < 10 || strlen($phone) > 11) { echo json_encode(array('status'=>'error','msg'=>'Informe um telefone celular válido com DDD.')); exit; }
        if (get_val($_POST,'identity_consent') !== '1') { echo json_encode(array('status'=>'error','msg'=>'Autorize o tratamento dos dados para análise da conta.')); exit; }
        $phone_hash = hash('sha256','re9_salt_'.$phone);
        $cpf_hash = hash('sha256','re9_cpf_salt_'.$cpf);
        $bindings = load_protected_json($PHONES_FILE); if (!is_array($bindings)) $bindings = array();
        if ((isset($bindings[$phone_hash]) && strtolower((string)$bindings[$phone_hash]) !== $email) || (isset($bindings['cpf_'.$cpf_hash]) && strtolower((string)$bindings['cpf_'.$cpf_hash]) !== $email)) {
            echo json_encode(array('status'=>'error','msg'=>'Este CPF ou telefone já está vinculado a outra conta RE9. Entre em contato com o suporte para revisão.')); exit;
        }
        if (!re9_save_pending_identity($email,$name,$cpf_hash,$phone_hash,$phone,time())) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Não foi possível registrar sua solicitação.')); exit; }
        $bindings[$phone_hash] = $email; $bindings['cpf_'.$cpf_hash] = $email; save_protected_json($PHONES_FILE,$bindings);
        $names = load_protected_json($DIRECTORY_NAMES_FILE); if (!is_array($names)) $names = array(); $names[$email] = $name; save_protected_json($DIRECTORY_NAMES_FILE,$names);
        echo json_encode(array('status'=>'ok','msg'=>'CPF válido pelos cálculos de verificação. Sua conta foi enviada para conferência manual do telefone e ficará em modo somente leitura até a liberação.')); exit;
    }

    if ($action === 'legacy_identity_confirm') {
        http_response_code(410); echo json_encode(array('status'=>'error','msg'=>'A confirmação por código foi substituída pela conferência manual do RE9.')); exit;
    }

    if (re9_central_is_client_connected() && in_array($action,array('save_ad_pool','delete_ad_pool','save_store_product_price'),true)) {
        http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Os anúncios e produtos são administrados pela Central Renove. Faça as alterações em re9.rio.br; elas serão sincronizadas automaticamente nesta instalação.')); exit;
    }

    // Loja RE9: cadastro de pedido e gestão do fluxo de entrega.
    if ($action === 'shop_place_order') {
        if (empty($_SESSION['wm_email'])) { http_response_code(401); echo json_encode(array('status'=>'error','msg'=>'Crie ou acesse sua conta RE9 para finalizar a compra e conversar com o anunciante.')); exit; }
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); echo json_encode(array('status'=>'error','msg'=>'Método não permitido.')); exit; }
        if (empty($_SESSION['re9_sales_csrf'])) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Sessão expirada. Atualize a página do checkout.')); exit; }
        $csrf = (string)get_val($_POST, 'csrf', '');
        if ($csrf === '' || !hash_equals((string)$_SESSION['re9_sales_csrf'], $csrf)) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Validação de segurança falhou. Atualize a página.')); exit; }

        $buyer_email = strtolower(trim((string)$_SESSION['wm_email']));
        $product_id = trim((string)get_val($_POST, 'product_id', ''));
        $product = sales_find_product($product_id);
        if (!is_array($product)) { http_response_code(404); echo json_encode(array('status'=>'error','msg'=>'Este produto não está disponível para compra.')); exit; }
        $seller_email = sales_resolve_seller_email($product, $buyer_email);
        if (!filter_var($seller_email, FILTER_VALIDATE_EMAIL)) { echo json_encode(array('status'=>'error','msg'=>'Não há uma conta RE9 de atendimento configurada para receber este pedido. Configure sales_fallback_seller_email ou admin_emails.')); exit; }

        $buyer_name = agenda_clean_text(get_val($_POST, 'buyer_name'), 160);
        $buyer_phone = agenda_clean_text(get_val($_POST, 'buyer_phone'), 40);
        $shipping_address = agenda_clean_text(get_val($_POST, 'shipping_address'), 500);
        $buyer_notes = agenda_clean_text(get_val($_POST, 'buyer_notes'), 1200);
        $quantity = (int)get_val($_POST, 'quantity', 1);
        if ($buyer_name === '' || $buyer_phone === '') { echo json_encode(array('status'=>'error','msg'=>'Informe seu nome e telefone para o pedido.')); exit; }
        if ($quantity < 1 || $quantity > 99) { echo json_encode(array('status'=>'error','msg'=>'A quantidade deve ser entre 1 e 99.')); exit; }
        $fulfillment = (string)agenda_value($product, 'fulfillment', 'digital');
        $fulfillment_labels = array('digital'=>'Produto digital / liberação de acesso','physical'=>'Produto físico / envio','service'=>'Serviço / agendamento','made_to_order'=>'Produto sob encomenda / confecção');
        if (!isset($fulfillment_labels[$fulfillment])) $fulfillment = 'digital';
        if (($fulfillment === 'physical' || $fulfillment === 'made_to_order') && $shipping_address === '') { echo json_encode(array('status'=>'error','msg'=>'Informe o endereço para entrega ou envio do produto.')); exit; }
        $unit_price = (float)agenda_value($product, 'price', 0);
        if ($unit_price <= 0) {
            echo json_encode(array('status'=>'error','msg'=>'Este produto ainda está sem preço cadastrado. O administrador precisa informar o valor na Central Admin antes da compra.'));
            exit;
        }
        $price_pending = false;

        $order_id = 'RE9-' . date('ymd') . '-' . strtoupper(substr(agenda_random_id(5), 0, 8));
        $seller_name = sales_public_name($seller_email);
        $order = array(
            'id'=>$order_id,
            'product_id'=>$product_id,
            'product_title'=>agenda_clean_text(agenda_value($product, 'title', ''), 180),
            'product_description'=>agenda_clean_text(agenda_value($product, 'description', ''), 1200),
            'category'=>agenda_clean_text(agenda_value($product, 'category', 'Geral'), 100),
            'fulfillment'=>$fulfillment,
            'fulfillment_label'=>$fulfillment_labels[$fulfillment],
            'buyer_email'=>$buyer_email,
            'buyer_name'=>$buyer_name,
            'buyer_phone'=>$buyer_phone,
            'shipping_address'=>$shipping_address,
            'buyer_notes'=>$buyer_notes,
            'seller_email'=>$seller_email,
            'seller_name'=>$seller_name,
            'quantity'=>$quantity,
            'unit_price'=>$unit_price,
            'total'=>$unit_price * $quantity,
            'price_pending'=>$price_pending,
            'status'=>'awaiting_payment_confirmation',
            'created_at'=>time(),
            'updated_at'=>time(),
            'updated_by'=>'',
            'delivery_link'=>'',
            'delivery_info'=>'',
            'support_email_sent'=>false
        );

        $order_lock = sales_orders_lock();
        if (!$order_lock) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Não foi possível acessar o arquivo de pedidos.')); exit; }
        $orders = sales_orders_load();
        $orders[] = $order;
        $saved = sales_orders_save_locked($orders);
        sales_orders_unlock($order_lock);
        if (!$saved) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Não foi possível registrar o pedido. Verifique as permissões da pasta webmail_data.')); exit; }

        $buyer_directory_name = sales_public_name($buyer_email);
        sales_ensure_chat_pair($buyer_email, $buyer_name, $seller_email, $seller_name);
        $order_chat_text = 'Novo pedido ' . $order_id . ': ' . $order['product_title'] . '. ';
        $order_chat_text .= 'Valor informado: R$ ' . number_format($unit_price * $quantity, 2, ',', '.') . '. ';
        $order_chat_text .= 'Status: aguardando confirmação de pagamento. O comprador concluiu o checkout e pode conversar por aqui.';
        sales_send_chat_message($buyer_email, $seller_email, $order_chat_text);

        $mail_sent = sales_notify_support_email($order);
        $order_lock = sales_orders_lock();
        if ($order_lock) {
            $latest_orders = sales_orders_load();
            foreach ($latest_orders as $idx => $saved_order) {
                if (agenda_value($saved_order, 'id') === $order_id) {
                    $latest_orders[$idx]['support_email_sent'] = $mail_sent ? true : false;
                    $latest_orders[$idx]['support_email_attempted_at'] = time();
                    break;
                }
            }
            sales_orders_save_locked($latest_orders);
            sales_orders_unlock($order_lock);
        }
        echo json_encode(array('status'=>'ok','order_id'=>$order_id,'order_status'=>'Aguardando confirmação de pagamento','support_email_sent'=>$mail_sent ? true : false,'seller_email'=>$seller_email,'msg'=>'Pedido registrado com sucesso. Ele ficará aguardando a confirmação do pagamento. O anunciante e a equipe RE9 poderão continuar o atendimento pelo chat.'));
        exit;
    }

    if ($action === 'shop_orders_list') {
        if (empty($_SESSION['wm_email'])) { http_response_code(401); echo json_encode(array('status'=>'error','msg'=>'Faça login para consultar seus pedidos.')); exit; }
        $me = strtolower(trim((string)$_SESSION['wm_email']));
        $admin = is_user_admin();
        $orders = sales_orders_load();
        $visible = array();
        foreach ($orders as $order) {
            if (!is_array($order)) continue;
            $buyer = strtolower(trim((string)agenda_value($order, 'buyer_email', '')));
            $seller = strtolower(trim((string)agenda_value($order, 'seller_email', '')));
            if ($admin || $buyer === $me || $seller === $me) {
                $order['status_label'] = sales_order_status_label(agenda_value($order, 'status', ''));
                if (!empty($order['price_pending']) && agenda_value($order, 'status', '') === 'awaiting_payment_confirmation') {
                    $order['status_label'] = 'Aguardando definição do valor e confirmação do pagamento';
                }
                $order['can_manage'] = $admin || $seller === $me;
                $order['is_admin'] = $admin;
                $visible[] = $order;
            }
        }
        usort($visible, function($a, $b) { return (int)agenda_value($b, 'created_at', 0) - (int)agenda_value($a, 'created_at', 0); });
        echo json_encode(array('status'=>'ok','orders'=>$visible,'me'=>$me,'is_admin'=>$admin));
        exit;
    }

    if ($action === 'shop_order_update') {
        if (empty($_SESSION['wm_email'])) { http_response_code(401); echo json_encode(array('status'=>'error','msg'=>'Faça login para atualizar pedidos.')); exit; }
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); echo json_encode(array('status'=>'error','msg'=>'Método não permitido.')); exit; }
        if (empty($_SESSION['re9_sales_csrf']) || !hash_equals((string)$_SESSION['re9_sales_csrf'], (string)get_val($_POST, 'csrf', ''))) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Validação de segurança falhou. Atualize a página.')); exit; }
        $me = strtolower(trim((string)$_SESSION['wm_email']));
        $order_id = agenda_clean_text(get_val($_POST, 'order_id'), 80);
        $new_status = trim((string)get_val($_POST, 'status'));
        $allowed_status = array('awaiting_payment_confirmation','payment_confirmed','in_production','ready_for_delivery','dispatched','product_released','completed','cancelled');
        if (!in_array($new_status, $allowed_status, true)) { echo json_encode(array('status'=>'error','msg'=>'Status de pedido inválido.')); exit; }
        $delivery_link = trim((string)get_val($_POST, 'delivery_link'));
        if ($delivery_link !== '' && !preg_match('#^https?://#i', $delivery_link)) { echo json_encode(array('status'=>'error','msg'=>'O link de entrega deve começar com http:// ou https://.')); exit; }
        $delivery_info = agenda_clean_text(get_val($_POST, 'delivery_info'), 1000);
        $order_lock = sales_orders_lock();
        if (!$order_lock) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Não foi possível acessar os pedidos.')); exit; }
        $orders = sales_orders_load();
        $found = false;
        $target_order = array();
        foreach ($orders as $idx => $order) {
            if (!is_array($order) || agenda_value($order, 'id') !== $order_id) continue;
            $seller = strtolower(trim((string)agenda_value($order, 'seller_email', '')));
            if (!is_user_admin() && $seller !== $me) {
                sales_orders_unlock($order_lock);
                http_response_code(403);
                echo json_encode(array('status'=>'error','msg'=>'Somente o anunciante responsável ou o administrador pode atualizar este pedido.'));
                exit;
            }
            $orders[$idx]['status'] = $new_status;
            $orders[$idx]['updated_at'] = time();
            $orders[$idx]['updated_by'] = $me;
            $orders[$idx]['delivery_link'] = $delivery_link;
            $orders[$idx]['delivery_info'] = $delivery_info;
            $target_order = $orders[$idx];
            $found = true;
            break;
        }
        if (!$found) { sales_orders_unlock($order_lock); http_response_code(404); echo json_encode(array('status'=>'error','msg'=>'Pedido não encontrado.')); exit; }
        $saved = sales_orders_save_locked($orders);
        sales_orders_unlock($order_lock);
        if (!$saved) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Não foi possível salvar a atualização do pedido.')); exit; }

        $buyer = strtolower(trim((string)agenda_value($target_order, 'buyer_email', '')));
        $seller = strtolower(trim((string)agenda_value($target_order, 'seller_email', '')));
        $buyer_name = agenda_value($target_order, 'buyer_name', sales_public_name($buyer));
        $seller_name = agenda_value($target_order, 'seller_name', sales_public_name($seller));
        sales_ensure_chat_pair($buyer, $buyer_name, $seller, $seller_name);
        if ($me !== $seller) sales_ensure_chat_pair($buyer, $buyer_name, $me, sales_public_name($me));
        $message = 'Atualização do pedido ' . $order_id . ': ' . sales_order_status_label($new_status) . '.';
        if ($delivery_info !== '') $message .= ' Informação: ' . $delivery_info;
        if ($delivery_link !== '') $message .= ' Link para acesso/entrega: ' . $delivery_link;
        sales_send_chat_message($me, $buyer, $message);
        echo json_encode(array('status'=>'ok','msg'=>'Pedido atualizado e comprador notificado pelo chat.'));
        exit;
    }

    if ($action === 'shop_resend_support_email') {
        if (empty($_SESSION['wm_email']) || !is_user_admin()) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Somente o administrador pode reenviar o aviso ao suporte.')); exit; }
        if (empty($_SESSION['re9_sales_csrf']) || !hash_equals((string)$_SESSION['re9_sales_csrf'], (string)get_val($_POST, 'csrf', ''))) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Validação de segurança falhou. Atualize a página.')); exit; }
        $order_id = agenda_clean_text(get_val($_POST, 'order_id'), 80);
        $orders = sales_orders_load();
        $target = false;
        foreach ($orders as $order) { if (is_array($order) && agenda_value($order, 'id') === $order_id) { $target = $order; break; } }
        if (!is_array($target)) { http_response_code(404); echo json_encode(array('status'=>'error','msg'=>'Pedido não encontrado.')); exit; }
        $sent = sales_notify_support_email($target);
        $lock = sales_orders_lock();
        if ($lock) {
            $latest = sales_orders_load();
            foreach ($latest as $i => $order) {
                if (agenda_value($order, 'id') === $order_id) { $latest[$i]['support_email_sent'] = $sent ? true : false; $latest[$i]['support_email_attempted_at'] = time(); break; }
            }
            sales_orders_save_locked($latest);
            sales_orders_unlock($lock);
        }
        echo json_encode(array('status'=>$sent ? 'ok' : 'error','msg'=>$sent ? 'Aviso reenviado para suporte@renove.rio.br.' : 'O servidor não aceitou o envio do e-mail. Confira a configuração de envio de e-mails do cPanel.'));
        exit;
    }

    // Mensagens privadas RE9: o destinatário pode estar online ou offline.
    if (in_array($action, array('private_message_send','private_message_history','private_message_poll'), true)) {
        if (empty($_SESSION['wm_email'])) {
            http_response_code(401);
            echo json_encode(array('status'=>'error','msg'=>'Faça login para usar as mensagens privadas.'));
            exit;
        }

        $me = strtolower(trim((string)$_SESSION['wm_email']));
        $domain = strtolower(trim((string)get_val($APP_CONFIG, 'domain_name', 're9.rio.br')));
        if (empty($_SESSION['re9_private_csrf'])) {
            $csrf_bytes = function_exists('openssl_random_pseudo_bytes') ? openssl_random_pseudo_bytes(24) : false;
            $_SESSION['re9_private_csrf'] = $csrf_bytes ? bin2hex($csrf_bytes) : sha1(uniqid((string)mt_rand(), true));
        }

        if ($action === 'private_message_send') {
            if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
                http_response_code(405);
                echo json_encode(array('status'=>'error','msg'=>'Método não permitido.'));
                exit;
            }
            $csrf = (string)get_val($_SERVER, 'HTTP_X_RE9_CSRF', '');
            if ($csrf === '' || !hash_equals((string)$_SESSION['re9_private_csrf'], $csrf)) {
                http_response_code(403);
                echo json_encode(array('status'=>'error','msg'=>'Sessão de segurança expirada. Atualize a página.'));
                exit;
            }

            $to = strtolower(trim((string)get_val($_POST, 'to')));
            $message = agenda_clean_text(get_val($_POST, 'message'), 2000);
            if (!filter_var($to, FILTER_VALIDATE_EMAIL) || $to === $me) {
                echo json_encode(array('status'=>'error','msg'=>'Selecione um contato válido da sua rede.'));
                exit;
            }
                $is_my_contact = private_messages_find_contact($me, $to) !== false;
            $has_previous_conversation = false;
            if (!$is_my_contact) {
                $check_lock = private_messages_lock(false);
                if ($check_lock) {
                    $existing_messages = private_messages_load_locked();
                    foreach ($existing_messages as $existing_message) {
                        if (!is_array($existing_message)) continue;
                        $existing_from = strtolower(trim((string)agenda_value($existing_message, 'from', '')));
                        $existing_to = strtolower(trim((string)agenda_value($existing_message, 'to', '')));
                        if (($existing_from === $me && $existing_to === $to) || ($existing_from === $to && $existing_to === $me)) {
                            $has_previous_conversation = true;
                            break;
                        }
                    }
                    private_messages_unlock($check_lock);
                }
            }
            $is_official_support = ($to === 'suporte@re9.rio.br');
            if (!$is_my_contact && !$has_previous_conversation && !$is_official_support) {
                http_response_code(403);
                echo json_encode(array('status'=>'error','msg'=>'Para iniciar uma conversa, adicione primeiro o endereço à sua lista de contatos. Você também pode responder a uma conversa já iniciada.'));
                exit;
            }
            if ($message === '') {
                echo json_encode(array('status'=>'error','msg'=>'Digite uma mensagem antes de enviar.'));
                exit;
            }

            $lock = private_messages_lock(true);
            if (!$lock) {
                http_response_code(500);
                echo json_encode(array('status'=>'error','msg'=>'Não foi possível acessar o armazenamento das mensagens.'));
                exit;
            }
            $messages = private_messages_load_locked();
            $online = private_messages_peer_online($to);
            $messages[] = array(
                'id' => agenda_random_id(12),
                'from' => $me,
                'to' => $to,
                'message' => $message,
                'created' => time(),
                'recipient_was_offline' => !$online,
                'read' => false,
                'read_at' => 0
            );
            // Mantém o arquivo de mensagens sob controle sem apagar conversas recentes.
            if (count($messages) > 10000) $messages = array_slice($messages, -8000);
            $saved = private_messages_save_locked($messages);
            private_messages_unlock($lock);
            if (!$saved) {
                http_response_code(500);
                echo json_encode(array('status'=>'error','msg'=>'Não foi possível salvar a mensagem. Verifique as permissões da pasta webmail_data.'));
                exit;
            }
            echo json_encode(array(
                'status'=>'ok',
                'peer_online'=>$online,
                'msg'=>$online ? 'Mensagem enviada.' : 'Mensagem salva. O destinatário receberá quando voltar ao webmail.'
            ));
            exit;
        }

        if ($action === 'private_message_history') {
            $peer = strtolower(trim((string)get_val($_GET, 'peer')));
            if (!filter_var($peer, FILTER_VALIDATE_EMAIL) || $peer === $me) {
                echo json_encode(array('status'=>'error','msg'=>'Contato inválido.'));
                exit;
            }

            $lock = private_messages_lock(true);
            if (!$lock) {
                http_response_code(500);
                echo json_encode(array('status'=>'error','msg'=>'Não foi possível acessar as mensagens.'));
                exit;
            }
            $messages = private_messages_load_locked();
            $history = array();
            $changed = false;
            $has_conversation = false;
            foreach ($messages as $index => $item) {
                if (!is_array($item)) continue;
                $from = strtolower(trim((string)agenda_value($item, 'from', '')));
                $to = strtolower(trim((string)agenda_value($item, 'to', '')));
                if (!(($from === $me && $to === $peer) || ($from === $peer && $to === $me))) continue;
                $has_conversation = true;
                if ($to === $me && empty($item['read'])) {
                    $messages[$index]['read'] = true;
                    $messages[$index]['read_at'] = time();
                    $item['read'] = true;
                    $changed = true;
                }
                $history[] = array(
                    'id' => (string)agenda_value($item, 'id', ''),
                    'from' => $from,
                    'to' => $to,
                    'message' => (string)agenda_value($item, 'message', ''),
                    'created' => (int)agenda_value($item, 'created', 0),
                    'read' => !empty($item['read'])
                );
            }
            $contact = private_messages_find_contact($me, $peer);
            $is_official_support = ($peer === 'suporte@re9.rio.br');
            if ($contact === false && !$has_conversation && !$is_official_support) {
                private_messages_unlock($lock);
                http_response_code(403);
                echo json_encode(array('status'=>'error','msg'=>'Este contato não está na sua rede e não existe uma conversa com ele.'));
                exit;
            }
            if ($changed && !private_messages_save_locked($messages)) {
                private_messages_unlock($lock);
                http_response_code(500);
                echo json_encode(array('status'=>'error','msg'=>'Não foi possível atualizar a leitura das mensagens.'));
                exit;
            }
            private_messages_unlock($lock);
            usort($history, function($a, $b) {
                $createdA = isset($a['created']) ? (int)$a['created'] : 0;
                $createdB = isset($b['created']) ? (int)$b['created'] : 0;
                if ($createdA == $createdB) return 0;
                return ($createdA < $createdB) ? -1 : 1;
            });
            echo json_encode(array(
                'status'=>'ok',
                'messages'=>$history,
                'peer_online'=>private_messages_peer_online($peer),
                'peer_name'=>private_messages_peer_name($me, $peer)
            ));
            exit;
        }

        // Consulta de mensagens recebidas: alimenta o aviso de nova mensagem no webmail.
        $lock = private_messages_lock(false);
        if (!$lock) {
            http_response_code(500);
            echo json_encode(array('status'=>'error','msg'=>'Não foi possível consultar as mensagens.'));
            exit;
        }
        $messages = private_messages_load_locked();
        private_messages_unlock($lock);
        $unread = array();
        $unread_by_sender = array();
        $unread_conversations = array();
        foreach ($messages as $item) {
            if (!is_array($item) || strtolower(trim((string)agenda_value($item, 'to', ''))) !== $me || !empty($item['read'])) continue;
            $sender = strtolower(trim((string)agenda_value($item, 'from', '')));
            if ($sender === '') continue;
            $created = (int)agenda_value($item, 'created', 0);
            $messageText = (string)agenda_value($item, 'message', '');
            if (!isset($unread_by_sender[$sender])) $unread_by_sender[$sender] = 0;
            $unread_by_sender[$sender]++;
            if (!isset($unread_conversations[$sender])) {
                $unread_conversations[$sender] = array(
                    'email' => $sender,
                    'name' => private_messages_peer_name($me, $sender),
                    'count' => 0,
                    'latest_message' => '',
                    'latest_created' => 0
                );
            }
            $unread_conversations[$sender]['count']++;
            if ($created >= (int)$unread_conversations[$sender]['latest_created']) {
                $unread_conversations[$sender]['latest_message'] = $messageText;
                $unread_conversations[$sender]['latest_created'] = $created;
            }
            $unread[] = array(
                'id'=>(string)agenda_value($item, 'id', ''),
                'from'=>$sender,
                'from_name'=>private_messages_peer_name($me, $sender),
                'was_offline'=>array_key_exists('recipient_was_offline', $item) ? !empty($item['recipient_was_offline']) : true,
                'message'=>$messageText,
                'created'=>$created
            );
        }
        $unread_conversations = array_values($unread_conversations);
        usort($unread_conversations, function($a, $b) {
            $ca = isset($a['latest_created']) ? (int)$a['latest_created'] : 0;
            $cb = isset($b['latest_created']) ? (int)$b['latest_created'] : 0;
            if ($ca === $cb) return 0;
            return ($ca > $cb) ? -1 : 1;
        });
        echo json_encode(array(
            'status'=>'ok',
            'unread_count'=>count($unread),
            'unread_by_sender'=>$unread_by_sender,
            'unread_conversations'=>array_slice($unread_conversations, 0, 50),
            'unread_messages'=>array_slice($unread, -10)
        ));
        exit;
    }

    // Diretório corporativo: pesquisa caixas dos domínios hospedados nesta conta cPanel.
    // Retorna apenas endereço e nome público; nunca expõe senha, telefone ou dados internos.
    if ($action === 're9_directory_search') {
        if (empty($_SESSION['wm_email'])) { http_response_code(401); echo json_encode(array('status'=>'error','msg'=>'Faça login para pesquisar no diretório corporativo.')); exit; }
        $query = strtolower(trim(agenda_clean_text(get_val($_GET, 'q'), 100)));
        if (strlen($query) < 2) { echo json_encode(array('status'=>'ok','items'=>array())); exit; }

        $defaultDomain = strtolower(trim((string)get_val($APP_CONFIG, 'domain_name', 're9.rio.br')));
        $domains = array();
        if ($defaultDomain !== '' && preg_match('/^[a-z0-9.-]+$/i', $defaultDomain)) $domains[] = $defaultDomain;

        // DomainInfo::list_domains inclui domínio principal, adicionais, estacionados e subdomínios.
        $domainResult = call_cpanel_uapi('DomainInfo', 'list_domains', array());
        if (is_array($domainResult) && get_val($domainResult, 'status') === 'ok') {
            $domainData = get_val($domainResult, 'data', array());
            $extractDomainList = function($value) use (&$extractDomainList, &$domains) {
                if (is_string($value)) {
                    $candidate = strtolower(trim($value));
                    if ($candidate !== '' && preg_match('/^(?=.{1,253}$)[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/i', $candidate)) $domains[] = $candidate;
                    return;
                }
                if (!is_array($value)) return;
                foreach ($value as $key => $item) {
                    if (in_array((string)$key, array('main_domain','addon_domains','parked_domains','sub_domains','domains','domain','domain_name'), true)) {
                        $extractDomainList($item);
                    } elseif (is_array($item) || is_int($key) || ctype_digit((string)$key)) {
                        $extractDomainList($item);
                    }
                }
            };
            $extractDomainList($domainData);
        }
        $domains = array_values(array_unique($domains));
        $names = load_protected_json($DIRECTORY_NAMES_FILE);
        if (!is_array($names)) $names = array();
        $emails = array();
        $successfulDomains = 0;
        $collectAccounts = function($rows, $defaultDomainForRows) use (&$collectAccounts, &$emails) {
            if (!is_array($rows)) return;
            foreach ($rows as $row) {
                if (is_string($row) && filter_var($row, FILTER_VALIDATE_EMAIL)) {
                    $emails[] = strtolower(trim($row));
                    continue;
                }
                if (!is_array($row)) continue;
                $is_suspended = false;
                foreach (array('suspended','suspended_incoming','suspended_outgoing') as $suspend_key) {
                    if (isset($row[$suspend_key]) && in_array(strtolower((string)$row[$suspend_key]), array('1','yes','true','suspended'), true)) { $is_suspended = true; break; }
                }
                if ($is_suspended) continue;
                $candidate = '';
                foreach (array('email','email_address','login') as $key) {
                    if (!empty($row[$key]) && is_string($row[$key]) && strpos($row[$key], '@') !== false) { $candidate = strtolower(trim($row[$key])); break; }
                }
                if ($candidate === '') {
                    $rowDomain = '';
                    foreach (array('domain','domain_name') as $domainKey) {
                        if (!empty($row[$domainKey]) && is_string($row[$domainKey])) { $rowDomain = strtolower(trim($row[$domainKey])); break; }
                    }
                    $useDomain = ($rowDomain !== '') ? $rowDomain : $defaultDomainForRows;
                    foreach (array('user','username','email') as $key) {
                        if (!empty($row[$key]) && is_string($row[$key]) && strpos($row[$key], '@') === false && $useDomain !== '') {
                            $candidate = strtolower(trim($row[$key])) . '@' . $useDomain;
                            break;
                        }
                    }
                }
                if ($candidate !== '' && filter_var($candidate, FILTER_VALIDATE_EMAIL)) $emails[] = $candidate;
                foreach (array('accounts','data','items') as $nested) {
                    if (isset($row[$nested]) && is_array($row[$nested])) $collectAccounts($row[$nested], $defaultDomainForRows);
                }
            }
        };

        foreach ($domains as $domainForList) {
            $directory = call_cpanel_uapi('Email', 'list_pops', array('domain'=>$domainForList));
            if (is_array($directory) && get_val($directory, 'status') === 'ok') {
                $successfulDomains++;
                $collectAccounts(get_val($directory, 'data', array()), $domainForList);
            }
        }
        if ($successfulDomains === 0) {
            http_response_code(503);
            echo json_encode(array('status'=>'error','msg'=>'Não foi possível consultar o diretório de caixas do cPanel. Verifique a permissão da API e a conexão da VPS.'));
            exit;
        }

        $emails = array_values(array_unique($emails));
        $me = strtolower(trim($_SESSION['wm_email']));
        $matches = array();
        foreach ($emails as $email) {
            if ($email === $me) continue;
            $display = isset($names[$email]) && trim((string)$names[$email]) !== '' ? trim($names[$email]) : ucfirst(str_replace(array('.','_','-'), ' ', substr($email, 0, strpos($email, '@'))));
            if (strpos($email, $query) !== false || strpos(strtolower($display), $query) !== false) {
                $matches[] = array('email'=>$email, 'name'=>$display, 'is_member'=>true);
                if (count($matches) >= 30) break;
            }
        }
        usort($matches, function($a,$b) { return strcasecmp($a['name'], $b['name']); });
        echo json_encode(array('status'=>'ok','items'=>$matches,'domains_checked'=>$successfulDomains)); exit;
    }

    if (in_array($action, array('contacts_list','contacts_save','contacts_delete'), true)) {
        if (empty($_SESSION['wm_email'])) { http_response_code(401); echo json_encode(array('status'=>'error','msg'=>'Faça login para acessar os contatos.')); exit; }
        $owner = strtolower(trim($_SESSION['wm_email']));
        $contacts = load_protected_json($CONTACTS_FILE);
        if (!is_array($contacts)) $contacts = array();
        if (!isset($contacts[$owner]) || !is_array($contacts[$owner])) $contacts[$owner] = array();
        if ($action === 'contacts_list') {
            // Contato de suporte garantido também para contas antigas, criadas antes da inclusão automática.
            $support_email = 'suporte@re9.rio.br';
            $support_exists = false;
            foreach ($contacts[$owner] as $saved_contact) {
                if (strtolower(trim((string)agenda_value($saved_contact, 'email', ''))) === $support_email) {
                    $support_exists = true;
                    break;
                }
            }
            if (!$support_exists) {
                $contacts[$owner][] = array(
                    'id' => agenda_random_id(12),
                    'name' => 'Suporte RE9',
                    'phone' => '',
                    'email' => $support_email,
                    'company' => 'Equipe de atendimento RE9',
                    'notes' => 'Contato oficial para solicitar suporte pela mensagem privada.',
                    'updated_at' => date('c')
                );
                save_protected_json($CONTACTS_FILE, $contacts);
            }
            usort($contacts[$owner], function($a,$b) { return strcasecmp(agenda_value($a,'name'), agenda_value($b,'name')); });
            echo json_encode(array('status'=>'ok','items'=>array_values($contacts[$owner]))); exit;
        }
        if (in_array($action, array('contacts_save','contacts_delete'), true)) {
            $contacts_csrf = (string)get_val($_SERVER, 'HTTP_X_RE9_CSRF', '');
            if ($contacts_csrf === '' || empty($_SESSION['re9_private_csrf']) || !hash_equals((string)$_SESSION['re9_private_csrf'], $contacts_csrf)) {
                http_response_code(403);
                echo json_encode(array('status'=>'error','msg'=>'Sessão de segurança expirada. Atualize a página e tente novamente.'));
                exit;
            }
        }
        if ($action === 'contacts_save') {
            $id = agenda_clean_text(get_val($_POST,'id'),80);
            $name = agenda_clean_text(get_val($_POST,'name'),160);
            $phone_raw = trim((string)get_val($_POST,'phone'));
            $phone = preg_replace('/[^0-9+]/', '', $phone_raw);
            $digits = preg_replace('/\D/', '', $phone);
            $email = strtolower(agenda_clean_text(get_val($_POST,'email'),180));
            $company = agenda_clean_text(get_val($_POST,'company'),160);
            $notes = agenda_clean_text(get_val($_POST,'notes'),1200);
            if ($name === '') { echo json_encode(array('status'=>'error','msg'=>'Informe o nome do contato.')); exit; }
            if ($phone !== '' && (strlen($digits) < 8 || strlen($digits) > 15)) { echo json_encode(array('status'=>'error','msg'=>'Informe um telefone válido com DDD e código do país quando necessário.')); exit; }
            if ($email !== '' && !filter_var($email,FILTER_VALIDATE_EMAIL)) { echo json_encode(array('status'=>'error','msg'=>'Informe um e-mail válido.')); exit; }
            $entry = array('id'=>$id !== '' ? $id : agenda_random_id(12),'name'=>$name,'phone'=>$phone,'email'=>$email,'company'=>$company,'notes'=>$notes,'updated_at'=>date('c'));
            $found = false;
            foreach ($contacts[$owner] as $i=>$old) {
                if (agenda_value($old,'id') === $entry['id']) { $contacts[$owner][$i] = $entry; $found = true; break; }
            }
            if (!$found) $contacts[$owner][] = $entry;
            if (!save_protected_json($CONTACTS_FILE,$contacts)) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Não foi possível gravar os contatos. Verifique as permissões da pasta webmail_data.')); exit; }
            echo json_encode(array('status'=>'ok','item'=>$entry)); exit;
        }
        if ($action === 'contacts_delete') {
            $id = agenda_clean_text(get_val($_POST,'id'),80);
            $contacts[$owner] = array_values(array_filter($contacts[$owner], function($c) use ($id) { return agenda_value($c,'id') !== $id; }));
            if (!save_protected_json($CONTACTS_FILE,$contacts)) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Não foi possível excluir o contato.')); exit; }
            echo json_encode(array('status'=>'ok')); exit;
        }
    }

    if (in_array($action, array('agenda_list','agenda_save','agenda_delete'), true)) {
        if (empty($_SESSION['wm_email'])) { http_response_code(401); echo json_encode(array('status'=>'error','msg'=>'Faça login para acessar a agenda.')); exit; }
        $owner = strtolower(trim($_SESSION['wm_email']));
        $all = agenda_load_all();
        if (!isset($all[$owner]) || !is_array($all[$owner])) $all[$owner] = array();
        if ($action === 'agenda_list') {
            usort($all[$owner], function($a,$b) { return strcmp(agenda_value($a, 'date').agenda_value($a, 'time'), agenda_value($b, 'date').agenda_value($b, 'time')); });
            echo json_encode(array('status'=>'ok','items'=>array_values($all[$owner]))); exit;
        }
        if ($action === 'agenda_save') {
            $id = agenda_clean_text(get_val($_POST,'id'),80);
            $date = trim(get_val($_POST,'date'));
            $time = trim(get_val($_POST,'time'));
            $reminder_time = trim(get_val($_POST,'reminder_time'));
            if (!preg_match('/^\\d{4}-\\d{2}-\\d{2}$/',$date) || !checkdate((int)substr($date,5,2),(int)substr($date,8,2),(int)substr($date,0,4)) || !preg_match('/^([01]\\d|2[0-3]):[0-5]\\d$/',$time)) {
                echo json_encode(array('status'=>'error','msg'=>'Informe uma data e um horário válidos.')); exit;
            }
            if (!preg_match('/^([01]\d|2[0-3]):[0-5]\d$/', $reminder_time)) {
                $reminder_time = agenda_default_reminder_time($time);
            }
            $entry = array('id'=>$id !== '' ? $id : agenda_random_id(10), 'date'=>$date, 'time'=>$time, 'reminder_time'=>$reminder_time,
                'type'=>agenda_clean_text(get_val($_POST,'type'),100), 'subject'=>agenda_clean_text(get_val($_POST,'subject'),180),
                'person'=>agenda_clean_text(get_val($_POST,'person'),180), 'arrival'=>agenda_clean_text(get_val($_POST,'arrival'),20),
                'location'=>agenda_clean_text(get_val($_POST,'location'),250), 'notes'=>agenda_clean_text(get_val($_POST,'notes'),2000), 'reminder_sent'=>'');
            if ($entry['subject'] === '') { echo json_encode(array('status'=>'error','msg'=>'Informe o assunto do agendamento.')); exit; }
            $found = false;
            foreach ($all[$owner] as $i => $old) if (agenda_value($old, 'id') === $entry['id']) { $all[$owner][$i] = $entry; $found = true; break; }
            if (!$found) $all[$owner][] = $entry;
            if (!agenda_save_all($all)) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Não foi possível gravar o agendamento. Verifique as permissões da pasta webmail_data.')); exit; }
            echo json_encode(array('status'=>'ok','item'=>$entry)); exit;
        }
        if ($action === 'agenda_delete') {
            $id = agenda_clean_text(get_val($_POST,'id'),80);
            if ($id === '') { http_response_code(400); echo json_encode(array('status'=>'error','msg'=>'Identificador do compromisso não informado.')); exit; }
            $before = count($all[$owner]);
            $all[$owner] = array_values(array_filter($all[$owner], function($a) use ($id) { return agenda_value($a, 'id') !== $id; }));
            if (count($all[$owner]) === $before) { echo json_encode(array('status'=>'error','msg'=>'Este compromisso não foi encontrado.')); exit; }
            if (!agenda_save_all($all)) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Não foi possível excluir o agendamento. Verifique as permissões da pasta webmail_data.')); exit; }
            echo json_encode(array('status'=>'ok')); exit;
        }
    }

    if ($action === 'request_email_code') {
        // Cadastro público gratuito é exclusivo da Central RE9.
        // Instalações de clientes (ex.: OABRJ32) não podem criar caixas
        // no próprio domínio por este fluxo; devem encaminhar o pedido ao suporte.
        if (empty($RE9_IS_CENTRAL_HUB)) {
            http_response_code(403);
            echo json_encode(array('status'=>'error','msg'=>'A criação gratuita de e-mails está disponível somente na Central Renove, para endereços @re9.rio.br. Para solicitar uma caixa corporativa deste domínio, fale com suporte@re9.rio.br.'));
            exit;
        }
        global $PHONES_FILE;
        $username = strtolower(preg_replace('/[^a-z0-9._-]/', '', trim(get_val($_POST, 'new_user'))));
        $display_name = agenda_clean_text(get_val($_POST, 'display_name'), 100);
        $password = get_val($_POST, 'new_pass');
        $phone = preg_replace('/\D/', '', get_val($_POST, 'new_phone'));
        $recovery_email = strtolower(trim((string)get_val($_POST, 'recovery_email', '')));
        $cpf = preg_replace('/\D/', '', get_val($_POST, 'new_cpf'));
        $consent = get_val($_POST, 'identity_consent') === '1';
        if (count(preg_split('/\s+/', trim($display_name))) < 2 || strlen($display_name) < 5) { echo json_encode(array('status'=>'error','msg'=>'Informe seu nome completo, com nome e sobrenome.')); exit; }
        if (!re9_valid_cpf($cpf)) { echo json_encode(array('status'=>'error','msg'=>'CPF inválido. Confira os 11 números informados.')); exit; }
        if (!$consent) { echo json_encode(array('status'=>'error','msg'=>'É necessário autorizar a análise manual dos dados.')); exit; }
        if (strlen($username) < 2) { echo json_encode(array('status'=>'error','msg'=>'O nome do e-mail deve ter pelo menos 2 letras ou números.')); exit; }
        $pass_err = validate_strong_password($password); if ($pass_err !== '') { echo json_encode(array('status'=>'error','msg'=>$pass_err)); exit; }
        if (strlen($phone) < 10 || strlen($phone) > 11) { echo json_encode(array('status'=>'error','msg'=>'Informe um número de celular válido com DDD.')); exit; }
        if (!filter_var($recovery_email, FILTER_VALIDATE_EMAIL) || strtolower(substr(strrchr($recovery_email, '@'), 1)) === strtolower((string)$APP_CONFIG['domain_name'])) { echo json_encode(array('status'=>'error','msg'=>'Informe um e-mail secundário válido de outro provedor, como Gmail ou Hotmail.')); exit; }
        $phone_hash = hash('sha256', 're9_salt_' . $phone); $cpf_hash = hash('sha256', 're9_cpf_salt_' . $cpf);
        $bindings = load_protected_json($PHONES_FILE); if (!is_array($bindings)) $bindings = array();
        if (isset($bindings[$phone_hash]) || isset($bindings[$phone])) { echo json_encode(array('status'=>'error','msg'=>'Este número de celular já está vinculado a uma conta RE9.')); exit; }
        if (isset($bindings['cpf_' . $cpf_hash])) { echo json_encode(array('status'=>'error','msg'=>'Este CPF já está vinculado a uma conta RE9.')); exit; }
        $_SESSION['temp_reg'] = array('username'=>$username,'display_name'=>$display_name,'password'=>$password,'phone'=>$phone,'recovery_email'=>$recovery_email,'phone_hash'=>$phone_hash,'cpf_hash'=>$cpf_hash,'identity_verified'=>true,'identity_verified_at'=>time(),'consent_at'=>time());
        echo json_encode(array('status'=>'ok','msg'=>'CPF válido pelos cálculos. Agora crie sua caixa; o telefone será conferido manualmente pelo administrador.')); exit;
    }

    if ($action === 'confirm_email_code') {
        // Segunda barreira: mesmo uma sessão/cadastro antigo não cria caixa
        // em domínio de cliente. Apenas re9.rio.br pode concluir autoinscrição.
        if (empty($RE9_IS_CENTRAL_HUB)) {
            unset($_SESSION['temp_reg']);
            http_response_code(403);
            echo json_encode(array('status'=>'error','msg'=>'A criação pública de caixas neste domínio está desativada. Solicite a criação corporativa pelo suporte@re9.rio.br.'));
            exit;
        }
        global $PHONES_FILE;
        if (empty($_SESSION['temp_reg']) || empty($_SESSION['temp_reg']['identity_verified']) || empty($_SESSION['temp_reg']['cpf_hash'])) { echo json_encode(array('status'=>'error','msg'=>'Os dados do cadastro expiraram. Reinicie o cadastro.')); exit; }
        $reg = $_SESSION['temp_reg'];
        $username = $reg['username']; $password = $reg['password']; $phone = $reg['phone'];
        $phone_hash = $reg['phone_hash']; $cpf_hash = $reg['cpf_hash']; $domain = $APP_CONFIG['domain_name'];
        $bindings = load_protected_json($PHONES_FILE); if (!is_array($bindings)) $bindings = array();
        if (isset($bindings[$phone_hash]) || isset($bindings['cpf_' . $cpf_hash])) { unset($_SESSION['temp_reg']); echo json_encode(array('status'=>'error','msg'=>'Este CPF ou telefone acabou de ser vinculado a outra conta. Reinicie o cadastro ou contate o suporte.')); exit; }
        $res = create_cpanel_email($username, $password, $domain);
        if ($res['status'] === 'ok') {
            $full_email = strtolower($username . '@' . $domain);
            $bindings = load_protected_json($PHONES_FILE); if (!is_array($bindings)) $bindings = array();
            $bindings[$phone_hash] = $full_email; $bindings['cpf_' . $cpf_hash] = $full_email; save_protected_json($PHONES_FILE, $bindings);
            if (!re9_save_pending_identity($full_email, $reg['display_name'], $cpf_hash, $phone_hash, $phone, $reg['consent_at'])) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'A caixa foi criada, mas não foi possível registrar a análise de identidade. Contate o suporte.')); exit; }
            $identity_store = load_protected_json($IDENTITY_FILE); if (!is_array($identity_store)) $identity_store = array();
            if (isset($identity_store[$full_email]) && is_array($identity_store[$full_email])) {
                $identity_store[$full_email]['recovery_email'] = strtolower(trim((string)$reg['recovery_email']));
                $identity_store[$full_email]['recovery_email_added_at'] = time();
                save_protected_json($IDENTITY_FILE, $identity_store);
            }
            $public_names = load_protected_json($DIRECTORY_NAMES_FILE); if (!is_array($public_names)) $public_names = array();
            $public_names[$full_email] = agenda_clean_text($reg['display_name'], 100); save_protected_json($DIRECTORY_NAMES_FILE, $public_names);
            $all_contacts = load_protected_json($CONTACTS_FILE); if (!is_array($all_contacts)) $all_contacts = array();
            if (!isset($all_contacts[$full_email]) || !is_array($all_contacts[$full_email])) $all_contacts[$full_email] = array();
            $support_email = 'suporte@re9.rio.br'; $support_exists = false;
            foreach ($all_contacts[$full_email] as $saved_contact) if (strtolower((string)get_val($saved_contact,'email','')) === $support_email) $support_exists = true;
            if (!$support_exists) $all_contacts[$full_email][] = array('name'=>'Suporte RE9','email'=>$support_email);
            save_protected_json($CONTACTS_FILE, $all_contacts);
            // Notifica o suporte somente depois que o cPanel confirmou a criação da nova caixa.
            $member_notice_sent = re9_notify_new_member($full_email, $reg['display_name'], $phone, $reg['recovery_email'], time());
            $identity_store = load_protected_json($IDENTITY_FILE); if (!is_array($identity_store)) $identity_store = array();
            if (!isset($identity_store[$full_email]) || !is_array($identity_store[$full_email])) $identity_store[$full_email] = array();
            $identity_store[$full_email]['new_member_notice_sent'] = $member_notice_sent ? true : false;
            $identity_store[$full_email]['new_member_notice_attempted_at'] = time();
            save_protected_json($IDENTITY_FILE, $identity_store);
            set_session_credentials($full_email, $password); update_user_online_status($full_email); unset($_SESSION['temp_reg']);
            $notice_msg = $member_notice_sent ? ' Um aviso com o assunto “Novo membro” foi enviado ao suporte@re9.rio.br.' : ' A conta foi criada, mas o servidor não confirmou o envio do aviso ao suporte; confira a configuração de e-mail da hospedagem.';
            echo json_encode(array('status'=>'ok','email'=>$full_email,'pending_review'=>true,'support_notice_sent'=>$member_notice_sent ? true : false,'msg'=>'Conta criada! Você já pode visualizar sua caixa. Enviamos seus dados para conferência manual; envio e demais funções ficam bloqueados até a liberação.' . $notice_msg)); exit;
        }
        echo json_encode(array('status'=>'error','msg'=>$res['msg'])); exit;
    }

    if ($action === 'update_password') {
        if (empty($_SESSION['wm_email'])) {
            echo json_encode(array('status' => 'error', 'msg' => 'Sessão expirada.'));
            exit;
        }
        $new_pass = get_val($_POST, 'new_pass');
        $pass_err = validate_strong_password($new_pass);
        if ($pass_err !== '') {
            echo json_encode(array('status' => 'error', 'msg' => $pass_err));
            exit;
        }
        $res = update_cpanel_password($_SESSION['wm_email'], $new_pass);
        if ($res['status'] === 'ok') {
            set_session_credentials($_SESSION['wm_email'], $new_pass);
            echo json_encode(array('status' => 'ok'));
        } else {
            echo json_encode(array('status' => 'error', 'msg' => $res['msg']));
        }
        exit;
    }

    if ($action === 'login') {
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); echo json_encode(array('status'=>'error','msg'=>'Método não permitido.')); exit; }
        $email = strtolower(trim((string)get_val($_POST, 'email')));
        $pass  = (string)get_val($_POST, 'password');
        // O webmail atende caixas hospedadas em qualquer domínio desta VPS.
        // A validação final do domínio/caixa/senha é feita pelo serviço IMAP local,
        // que só autentica contas realmente existentes no servidor de e-mail.
        if (!filter_var($email, FILTER_VALIDATE_EMAIL) || strlen($email) > 254 || strpos($email, "\n") !== false || strpos($email, "\r") !== false) {
            http_response_code(400);
            echo json_encode(array('status'=>'error','msg'=>'Informe o endereço completo da sua caixa corporativa, incluindo @ e o domínio.'));
            exit;
        }
        if ($pass === '' || strlen($pass) > 1024) {
            http_response_code(400);
            echo json_encode(array('status'=>'error','msg'=>'Informe sua senha.'));
            exit;
        }
        $client_ip = (string)get_val($_SERVER, 'REMOTE_ADDR', 'unknown');
        $rate_state = re9_login_throttle($email, $client_ip, 'check');
        if (!empty($rate_state['blocked'])) { http_response_code(429); echo json_encode(array('status'=>'error','msg'=>'Muitas tentativas de acesso. Por segurança, aguarde 15 minutos antes de tentar novamente.')); exit; }

        $imap = new CpanelImapSocket();
        if ($imap->connect($email, $pass)) {
            $imap->close();
            re9_login_throttle($email, $client_ip, true);
            set_session_credentials($email, $pass);
            update_user_online_status($email);
            echo json_encode(array('status' => 'ok'));
        } else {
            re9_login_throttle($email, $client_ip, false);
            session_destroy();
            echo json_encode(array('status' => 'error', 'msg' => 'O servidor não confirmou o acesso. Confira o e-mail completo e a senha. Se a caixa existe no cPanel, peça ao administrador para conferir se o MX do domínio aponta para esta VPS e se o serviço IMAP está ativo.'));
        }
        exit;
    }

    if ($action === 'logout') {
        if (re9_central_is_client_connected()) re9_central_send_presence('');
        if (!empty($_SESSION['wm_email'])) {
            remove_user_online_status($_SESSION['wm_email']);
        }
        session_destroy();
        echo json_encode(array('status' => 'ok'));
        exit;
    }

    // Recuperação de senha por e-mail secundário, sem exigir sessão autenticada.
    if ($action === 'password_recovery_request') {
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); echo json_encode(array('status'=>'error','msg'=>'Método não permitido.')); exit; }
        $account_email = strtolower(trim((string)get_val($_POST,'account_email','')));
        $recovery_email = strtolower(trim((string)get_val($_POST,'recovery_email','')));
        $generic = 'Se os dados corresponderem a uma conta, enviaremos um link de recuperação para o e-mail secundário cadastrado.';
        $tokens = load_protected_json($PASSWORD_RECOVERY_FILE); if (!is_array($tokens)) $tokens = array();
        foreach ($tokens as $key => $old) if (!is_array($old) || (int)get_val($old,'expires',0) < time()) unset($tokens[$key]);
        $ip_hash = hash('sha256',(string)get_val($_SERVER,'REMOTE_ADDR','unknown'));
        $rate_key = 'rate_'.$ip_hash;
        $rate = isset($tokens[$rate_key]) && is_array($tokens[$rate_key]) ? $tokens[$rate_key] : array();
        if ((int)get_val($rate,'window',0) < time()-600) $rate = array('window'=>time(),'count'=>0,'expires'=>time()+600);
        $rate['count'] = (int)get_val($rate,'count',0)+1; $tokens[$rate_key] = $rate;
        if ($rate['count'] > 5) { save_protected_json($PASSWORD_RECOVERY_FILE,$tokens); http_response_code(429); echo json_encode(array('status'=>'error','msg'=>'Muitas tentativas. Aguarde alguns minutos e tente novamente.')); exit; }
        $records = load_protected_json($IDENTITY_FILE); if (!is_array($records)) $records = array();
        $matched = '';
        foreach ($records as $mail => $record) {
            if (!is_array($record)) continue;
            if (strtolower(trim((string)$mail)) === $account_email && strtolower(trim((string)get_val($record,'recovery_email',''))) === $recovery_email) { $matched = strtolower(trim((string)$mail)); break; }
        }
        if ($matched !== '' && filter_var($matched,FILTER_VALIDATE_EMAIL) && filter_var($recovery_email,FILTER_VALIDATE_EMAIL)) {
            $token_bytes = false;
            if (function_exists('random_bytes')) {
                try { $token_bytes = random_bytes(32); } catch (Exception $token_error) { $token_bytes = false; }
            }
            if ($token_bytes === false && function_exists('openssl_random_pseudo_bytes')) {
                $token_strong = false;
                $token_bytes = @openssl_random_pseudo_bytes(32, $token_strong);
                if (!$token_strong) $token_bytes = false;
            }
            if (!is_string($token_bytes) || strlen($token_bytes) !== 32) {
                http_response_code(500);
                echo json_encode(array('status'=>'error','msg'=>'O servidor não disponibilizou geração segura de token. Contate o suporte.'));
                exit;
            }
            $raw_token = bin2hex($token_bytes);
            $token_hash = hash('sha256',$raw_token);
            $tokens[$token_hash] = array('account'=>$matched,'expires'=>time()+3600,'created_at'=>time(),'attempts'=>0);
            if (!save_protected_json($PASSWORD_RECOVERY_FILE,$tokens)) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Não foi possível preparar a recuperação. Tente novamente mais tarde.')); exit; }
            $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'https';
            $host = isset($_SERVER['HTTP_HOST']) ? preg_replace('/[^a-zA-Z0-9.:-]/','',$_SERVER['HTTP_HOST']) : '';
            $script = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '/';
            $link = $scheme.'://'.$host.$script.'?reset_password='.rawurlencode($raw_token);
            $subject = 'RE9 Webmail - Recuperação de senha';
            $body = '<div style="font-family:Arial,sans-serif;max-width:560px;margin:auto;color:#1e293b"><h2 style="color:#002244">Recuperação de senha RE9</h2><p>Recebemos uma solicitação para redefinir a senha da conta <strong>'.htmlspecialchars($matched,ENT_QUOTES,'UTF-8').'</strong>.</p><p><a href="'.htmlspecialchars($link,ENT_QUOTES,'UTF-8').'" style="display:inline-block;background:#002244;color:#fff;padding:13px 20px;border-radius:8px;text-decoration:none;font-weight:bold">Criar nova senha</a></p><p>O link expira em 1 hora e só pode ser utilizado uma vez. Se não solicitou esta alteração, ignore esta mensagem.</p></div>';
            $from = 'suporte@re9.rio.br';
            $headers = "MIME-Version: 1.0\r\nContent-Type: text/html; charset=UTF-8\r\nFrom: RE9 Webmail <".$from.">\r\nReply-To: ".$from."\r\n";
            if (!@mail($recovery_email,'=?UTF-8?B?'.base64_encode($subject).'?=',$body,$headers,'-f'.$from)) {
                unset($tokens[$token_hash]); save_protected_json($PASSWORD_RECOVERY_FILE,$tokens);
                http_response_code(502); echo json_encode(array('status'=>'error','msg'=>'O servidor não confirmou o envio do e-mail. Confira a configuração de envio de e-mails da hospedagem.')); exit;
            }
        }
        save_protected_json($PASSWORD_RECOVERY_FILE,$tokens);
        echo json_encode(array('status'=>'ok','msg'=>$generic)); exit;
    }

    if ($action === 'password_recovery_reset') {
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); echo json_encode(array('status'=>'error','msg'=>'Método não permitido.')); exit; }
        $raw_token = preg_replace('/[^a-f0-9]/i','',(string)get_val($_POST,'token',''));
        $new_pass = (string)get_val($_POST,'new_pass','');
        $pass_err = validate_strong_password($new_pass);
        if ($pass_err !== '') { echo json_encode(array('status'=>'error','msg'=>$pass_err)); exit; }
        if (strlen($raw_token) !== 64) { http_response_code(400); echo json_encode(array('status'=>'error','msg'=>'Link inválido ou incompleto. Solicite uma nova recuperação.')); exit; }
        $tokens = load_protected_json($PASSWORD_RECOVERY_FILE); if (!is_array($tokens)) $tokens = array();
        $hash = hash('sha256',$raw_token); $entry = isset($tokens[$hash]) && is_array($tokens[$hash]) ? $tokens[$hash] : null;
        if (!$entry || (int)get_val($entry,'expires',0) < time()) { if (isset($tokens[$hash])) { unset($tokens[$hash]); save_protected_json($PASSWORD_RECOVERY_FILE,$tokens); } http_response_code(400); echo json_encode(array('status'=>'error','msg'=>'Este link expirou ou já foi utilizado. Solicite uma nova recuperação.')); exit; }
        $account = strtolower(trim((string)get_val($entry,'account','')));
        if (!filter_var($account,FILTER_VALIDATE_EMAIL) || strpos($account,'@') === false) { http_response_code(400); echo json_encode(array('status'=>'error','msg'=>'Conta vinculada ao link inválida.')); exit; }
        $cp = update_cpanel_password($account,$new_pass);
        if (!is_array($cp) || get_val($cp,'status') !== 'ok') { http_response_code(502); echo json_encode(array('status'=>'error','msg'=>get_val($cp,'msg','O servidor de e-mail não confirmou a troca da senha. Tente novamente.'))); exit; }
        unset($tokens[$hash]); save_protected_json($PASSWORD_RECOVERY_FILE,$tokens);
        // Revoga todos os outros links pendentes para esta mesma conta.
        foreach ($tokens as $k => $v) if (is_array($v) && strtolower((string)get_val($v,'account','')) === $account) unset($tokens[$k]);
        save_protected_json($PASSWORD_RECOVERY_FILE,$tokens);
        set_session_credentials($account,$new_pass); update_user_online_status($account);
        echo json_encode(array('status'=>'ok','email'=>$account,'msg'=>'Senha alterada com sucesso. Você já está conectado à sua caixa RE9.')); exit;
    }

    if (empty($_SESSION['wm_email'])) {
        echo json_encode(array('status' => 'unauthorized'));
        exit;
    }

    $current_pass = get_session_password();

    // Central Admin: inventário e gerenciamento das caixas reais no cPanel.
    if (in_array($action, array('admin_mailboxes_list','admin_mailbox_manage','admin_phone_confirmation','admin_identity_review'), true)) {
        if (!is_user_admin()) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Acesso restrito ao administrador.')); exit; }
        $admin_domains = re9_get_cpanel_domains();
        if (empty($admin_domains)) $admin_domains = array('re9.rio.br');
        if ($action === 'admin_mailboxes_list') {
            $names = load_protected_json($DIRECTORY_NAMES_FILE); if (!is_array($names)) $names = array();
            $identity_records = load_protected_json($IDENTITY_FILE); if (!is_array($identity_records)) $identity_records = array();
            $accounts = array();
            $successful_domains = array();
            $failed_domains = array();
            foreach ($admin_domains as $domain_for_list) {
                $result = call_cpanel_uapi('Email', 'list_pops', array('domain' => $domain_for_list));
                if (!is_array($result) || get_val($result, 'status') !== 'ok') {
                    $failed_domains[] = $domain_for_list;
                    continue;
                }
                $successful_domains[] = $domain_for_list;
                $walk = function($items, $default_domain) use (&$walk, &$accounts, $names, $identity_records) {
                    if (!is_array($items)) return;
                    foreach ($items as $row) {
                        if (is_string($row)) {
                            $mail = strtolower(trim($row));
                            if (strpos($mail, '@') === false && $default_domain !== '') $mail .= '@' . $default_domain;
                            if (filter_var($mail, FILTER_VALIDATE_EMAIL)) {
                                $accounts[$mail] = array(
                                    'email'=>$mail, 'domain'=>strtolower(substr(strrchr($mail, '@'), 1)),
                                    'name'=>isset($names[$mail]) ? $names[$mail] : '', 'suspended'=>false,
                                    'diskused'=>'', 'diskquota'=>'',
                                    'phone_verified_at'=>!empty($identity_records[$mail]['admin_phone_verified_at']) ? (int)$identity_records[$mail]['admin_phone_verified_at'] : (!empty($identity_records[$mail]['verified_at']) ? (int)$identity_records[$mail]['verified_at'] : 0),
                                    'phone_last4'=>isset($identity_records[$mail]['admin_phone_last4']) ? $identity_records[$mail]['admin_phone_last4'] : '',
                                    'phone'=>isset($identity_records[$mail]['phone']) ? (string)$identity_records[$mail]['phone'] : '',
                                    'identity_name'=>isset($identity_records[$mail]['name']) ? (string)$identity_records[$mail]['name'] : '',
                                    'pending_review'=>!empty($identity_records[$mail]['pending_review_at']) && empty($identity_records[$mail]['admin_phone_verified_at']), 'manual_release'=>!empty($identity_records[$mail]['admin_manual_release_at']), 'released'=>!empty($identity_records[$mail]['admin_manual_release_at']) || !empty($identity_records[$mail]['admin_phone_verified_at']) || (!empty($identity_records[$mail]['verified_at']) && !empty($identity_records[$mail]['cpf_hash']) && !empty($identity_records[$mail]['phone_hash']))
                                );
                            }
                            continue;
                        }
                        if (!is_array($row)) continue;
                        $mail = '';
                        foreach (array('email','email_address','login') as $key) {
                            if (!empty($row[$key]) && is_string($row[$key])) { $mail = strtolower(trim($row[$key])); break; }
                        }
                        $row_domain = '';
                        foreach (array('domain','domain_name') as $domain_key) {
                            if (!empty($row[$domain_key]) && is_string($row[$domain_key])) { $row_domain = strtolower(trim($row[$domain_key])); break; }
                        }
                        $use_domain = $row_domain !== '' ? $row_domain : $default_domain;
                        if ($mail !== '' && strpos($mail, '@') === false && $use_domain !== '') $mail .= '@' . $use_domain;
                        if ($mail === '') {
                            foreach (array('user','username') as $key) {
                                if (!empty($row[$key]) && is_string($row[$key]) && $use_domain !== '') { $mail = strtolower(trim($row[$key])) . '@' . $use_domain; break; }
                            }
                        }
                        if ($mail !== '' && filter_var($mail, FILTER_VALIDATE_EMAIL)) {
                            $suspended = false;
                            foreach (array('suspended','suspended_incoming','suspended_outgoing','login_suspended') as $sk) {
                                if (isset($row[$sk]) && in_array(strtolower((string)$row[$sk]), array('1','yes','true','suspended'), true)) $suspended = true;
                            }
                            $accounts[$mail] = array(
                                'email'=>$mail, 'domain'=>strtolower(substr(strrchr($mail, '@'), 1)),
                                'name'=>isset($names[$mail]) ? $names[$mail] : '', 'suspended'=>$suspended,
                                'diskused'=>isset($row['diskused']) ? (string)$row['diskused'] : '',
                                'diskquota'=>isset($row['diskquota']) ? (string)$row['diskquota'] : '',
                                'phone_verified_at'=>!empty($identity_records[$mail]['admin_phone_verified_at']) ? (int)$identity_records[$mail]['admin_phone_verified_at'] : (!empty($identity_records[$mail]['verified_at']) ? (int)$identity_records[$mail]['verified_at'] : 0),
                                'phone_last4'=>isset($identity_records[$mail]['admin_phone_last4']) ? $identity_records[$mail]['admin_phone_last4'] : '',
                                'phone'=>isset($identity_records[$mail]['phone']) ? (string)$identity_records[$mail]['phone'] : '',
                                'identity_name'=>isset($identity_records[$mail]['name']) ? (string)$identity_records[$mail]['name'] : '',
                                'pending_review'=>!empty($identity_records[$mail]['pending_review_at']) && empty($identity_records[$mail]['admin_phone_verified_at']), 'manual_release'=>!empty($identity_records[$mail]['admin_manual_release_at']), 'released'=>!empty($identity_records[$mail]['admin_manual_release_at']) || !empty($identity_records[$mail]['admin_phone_verified_at']) || (!empty($identity_records[$mail]['verified_at']) && !empty($identity_records[$mail]['cpf_hash']) && !empty($identity_records[$mail]['phone_hash']))
                            );
                        }
                        foreach (array('accounts','data','items','pops','list') as $nested) if (isset($row[$nested]) && is_array($row[$nested])) $walk($row[$nested], $default_domain);
                    }
                };
                $walk(get_val($result, 'data', array()), $domain_for_list);
            }
            if (empty($successful_domains)) {
                http_response_code(503);
                echo json_encode(array('status'=>'error','msg'=>'Não foi possível consultar caixas em nenhum domínio da conta cPanel. Confira a permissão da API e os domínios configurados.','domains'=>$admin_domains));
                exit;
            }
            $accounts = array_values($accounts);
            usort($accounts, function($a, $b) { return strcmp($a['email'], $b['email']); });
            echo json_encode(array('status'=>'ok','accounts'=>$accounts,'count'=>count($accounts),'domains'=>$successful_domains,'failed_domains'=>$failed_domains,'domain'=>'Todos os domínios hospedados nesta conta cPanel'));
            exit;
        }
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); echo json_encode(array('status'=>'error','msg'=>'Método não permitido.')); exit; }
        if (empty($_SESSION['re9_private_csrf']) || !hash_equals((string)$_SESSION['re9_private_csrf'], (string)get_val($_POST, 'csrf', ''))) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Sessão de segurança expirada. Atualize a página.')); exit; }
        if (!re9_admin_password_matches(get_val($_POST, 'admin_pass', ''))) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Senha administrativa incorreta.')); exit; }

        $email = strtolower(trim((string)get_val($_POST, 'email', '')));
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { http_response_code(400); echo json_encode(array('status'=>'error','msg'=>'Informe um endereço de e-mail válido.')); exit; }
        $email_parts = explode('@', $email, 2);
        $target_domain = isset($email_parts[1]) ? strtolower(trim($email_parts[1])) : '';
        if ($target_domain === '' || !in_array($target_domain, $admin_domains, true)) {
            http_response_code(400);
            echo json_encode(array('status'=>'error','msg'=>'Este domínio não foi identificado como hospedado nesta conta cPanel. Domínios disponíveis: ' . implode(', ', $admin_domains)));
            exit;
        }

        if ($action === 'admin_phone_confirmation' || $action === 'admin_identity_review') {
            $identities = load_protected_json($IDENTITY_FILE); if (!is_array($identities)) $identities = array();
            if (!isset($identities[$email]) || !is_array($identities[$email])) $identities[$email] = array();
            $now = time();
            $phone = preg_replace('/\\D/', '', (string)get_val($identities[$email], 'phone', ''));
            $identities[$email]['admin_manual_release_at'] = $now;
            $identities[$email]['admin_phone_verified_at'] = $now;
            if (strlen($phone) >= 10 && strlen($phone) <= 11) $identities[$email]['admin_phone_last4'] = substr($phone, -4);
            $identities[$email]['verified_at'] = $now;
            $identities[$email]['method'] = 'manual_admin_release';
            $identities[$email]['pending_review_at'] = 0;
            $identities[$email]['reviewed_by'] = strtolower((string)$_SESSION['wm_email']);
            if (save_protected_json($IDENTITY_FILE, $identities) === false) { http_response_code(500); echo json_encode(array('status'=>'error','msg'=>'Não foi possível salvar a liberação.')); exit; }
            $welcome = re9_send_member_welcome($email, isset($identities[$email]['name']) ? (string)$identities[$email]['name'] : '');
            echo json_encode(array('status'=>'ok','msg'=>'Conta liberada com sucesso. ' . $welcome['message'] . ' O membro já pode entrar no RE9 EMAIL.','welcome_sent'=>!empty($welcome['ok'])));
            exit;
        }

        $operation = (string)get_val($_POST, 'operation', '');
        $params = array('email'=>$email_parts[0], 'domain'=>$target_domain);
        if ($operation === 'delete') $cp = call_cpanel_uapi('Email', 'delete_pop', $params);
        elseif ($operation === 'suspend') $cp = call_cpanel_uapi('Email', 'suspend_login', $params);
        elseif ($operation === 'unsuspend') $cp = call_cpanel_uapi('Email', 'unsuspend_login', $params);
        else { http_response_code(400); echo json_encode(array('status'=>'error','msg'=>'Operação não reconhecida.')); exit; }
        if (!is_array($cp) || get_val($cp, 'status') !== 'ok') { http_response_code(502); echo json_encode(array('status'=>'error','msg'=>get_val($cp, 'msg', 'O cPanel não confirmou a operação. Verifique o retorno da UAPI e as permissões do token.'))); exit; }
        if ($operation === 'delete') {
            $identity_cleanup = load_protected_json($IDENTITY_FILE); if (!is_array($identity_cleanup)) $identity_cleanup = array();
            if (isset($identity_cleanup[$email])) { unset($identity_cleanup[$email]); save_protected_json($IDENTITY_FILE, $identity_cleanup); }
            $name_cleanup = load_protected_json($DIRECTORY_NAMES_FILE); if (!is_array($name_cleanup)) $name_cleanup = array();
            if (isset($name_cleanup[$email])) { unset($name_cleanup[$email]); save_protected_json($DIRECTORY_NAMES_FILE, $name_cleanup); }
        }
        echo json_encode(array('status'=>'ok','msg'=>$operation === 'delete' ? 'Conta excluída no cPanel. A caixa e suas mensagens foram removidas pelo servidor.' : ($operation === 'suspend' ? 'Login da conta suspenso.' : 'Login da conta reativado.')));
        exit;
    }

    if ($action === 'get_online_users') {
        if (!is_user_admin()) {
            echo json_encode(array('status' => 'error', 'msg' => 'Acesso negado.'));
            exit;
        }
        $vps_data = get_strictly_connected_webmail_users();
        $instanceRows = re9_get_registered_instances();
        if (!empty($RE9_IS_CENTRAL_HUB)) {
            $centralSiteRows = load_protected_json($CENTRAL_SITES_FILE); $nowCentral = time();
            foreach ($centralSiteRows as $siteKey=>$siteRow) { if (!is_array($siteRow)) continue; $seenCentral=(int)get_val($siteRow,'last_seen',0); $instanceRows[] = array('host'=>(string)$siteKey,'last_seen'=>$seenCentral,'last_seen_text'=>$seenCentral>0?date('d/m/Y H:i',$seenCentral):'Ainda não conectou','central_client'=>true,'online'=>($seenCentral>0 && ($nowCentral-$seenCentral)<=180)); }
        }
        echo json_encode(array(
            'status'       => 'ok',
            'server_ip'    => $vps_data['server_ip'],
            'online_count' => $vps_data['online_count'],
            'users'        => $vps_data['users'],
            'instances'    => $instanceRows,
            'shared_storage_ready' => !empty($RE9_SHARED_STORAGE_READY),
            'federated_mode' => !empty($RE9_IS_CENTRAL_HUB),
            'scope' => !empty($RE9_IS_CENTRAL_HUB) ? 'Instalações clientes conectadas por API segura' : 'Instalação local'
        ));
        exit;
    }

    if ($action === 'add_external_account') {
        $ext_email = strtolower(trim(get_val($_POST, 'ext_email')));
        $ext_pass  = str_replace(' ', '', trim(get_val($_POST, 'ext_pass')));
        $ext_host  = strtolower(trim(get_val($_POST, 'ext_host')));
        $ext_port  = (int)get_val($_POST, 'ext_port', 993);

        if (empty($ext_email) || empty($ext_pass)) {
            echo json_encode(array('status' => 'error', 'msg' => 'Informe o e-mail e a senha de aplicativo.'));
            exit;
        }
        if (empty($ext_host)) {
            $ext_host = detect_imap_host_by_email($ext_email);
        }
        if ($ext_port <= 0) $ext_port = 993;

        $hosts_to_try = array($ext_host);
        if (strpos($ext_email, '@hotmail.') !== false || strpos($ext_email, '@outlook.') !== false || strpos($ext_email, '@live.') !== false) {
            $hosts_to_try = array_unique(array($ext_host, 'imap-mail.outlook.com', 'outlook.office365.com'));
        }

        $connected_host = '';
        foreach ($hosts_to_try as $try_h) {
            $ext_imap = new CpanelImapSocket();
            if ($ext_imap->connect($ext_email, $ext_pass, $try_h, $ext_port)) {
                $ext_imap->close();
                $connected_host = $try_h;
                break;
            }
        }

        if (empty($connected_host)) {
            echo json_encode(array(
                'status' => 'error',
                'msg'    => 'A Microsoft/Google recusou a conexão direta por senha. Recomendamos clicar na Aba 1 ("Encaminhamento em 1 Minuto") acima para ativar o envio automático sem precisar de senha!'
            ));
            exit;
        }

        $ext_data = get_user_external_accounts($_SESSION['wm_email']);
        $ext_data['accounts'][$ext_email] = array(
            'email'     => $ext_email,
            'pass_enc'  => encrypt_ext_pass($ext_pass),
            'host'      => $connected_host,
            'port'      => $ext_port,
            'last_sync' => 'Conectado com sucesso'
        );
        save_user_external_accounts($_SESSION['wm_email'], $ext_data);

        $public_list = array();
        foreach ($ext_data['accounts'] as $acc) {
            $public_list[] = array(
                'email'     => $acc['email'],
                'host'      => $acc['host'],
                'port'      => $acc['port'],
                'last_sync' => $acc['last_sync']
            );
        }

        echo json_encode(array('status' => 'ok', 'accounts' => $public_list));
        exit;
    }

    if ($action === 'delete_external_account') {
        $del_email = strtolower(trim(get_val($_POST, 'ext_email')));
        $ext_data  = get_user_external_accounts($_SESSION['wm_email']);
        if (isset($ext_data['accounts'][$del_email])) {
            unset($ext_data['accounts'][$del_email]);
            save_user_external_accounts($_SESSION['wm_email'], $ext_data);
        }
        $public_list = array();
        foreach ($ext_data['accounts'] as $acc) {
            $public_list[] = array(
                'email'     => $acc['email'],
                'host'      => $acc['host'],
                'port'      => $acc['port'],
                'last_sync' => $acc['last_sync']
            );
        }
        echo json_encode(array('status' => 'ok', 'accounts' => $public_list));
        exit;
    }

    if ($action === 'sync_external_accounts') {
        $ext_data = get_user_external_accounts($_SESSION['wm_email']);
        if (empty($ext_data['accounts'])) {
            echo json_encode(array('status' => 'error', 'msg' => 'Nenhuma conta externa cadastrada via IMAP.'));
            exit;
        }

        $local_imap = new CpanelImapSocket();
        if (!$local_imap->connect($_SESSION['wm_email'], $current_pass)) {
            echo json_encode(array('status' => 'error', 'msg' => 'Erro ao abrir sua caixa local.'));
            exit;
        }

        $imported_count = 0;
        $errors = array();

        foreach ($ext_data['accounts'] as $em_key => &$acc) {
            $ext_pass = decrypt_ext_pass($acc['pass_enc']);
            $ext_imap = new CpanelImapSocket();
            if ($ext_imap->connect($acc['email'], $ext_pass, $acc['host'], (int)$acc['port'])) {
                $today_msgs = $ext_imap->fetchTodayRawMessages(15);
                $ext_imap->close();

                foreach ($today_msgs as $msg_id => $raw_mime) {
                    $unique_hash = md5($em_key . '_' . $msg_id);
                    if (!isset($ext_data['imported_ids'][$unique_hash])) {
                        $local_imap->appendMessageToFolder('INBOX', $raw_mime, '');
                        $ext_data['imported_ids'][$unique_hash] = time();
                        $imported_count++;
                    }
                }
                $acc['last_sync'] = 'Sincronizado hoje às ' . date('H:i');
            } else {
                $errors[] = 'Falha ao autenticar em ' . $acc['email'];
                $acc['last_sync'] = 'Erro de conexão às ' . date('H:i');
            }
        }
        unset($acc);

        $local_imap->close();
        save_user_external_accounts($_SESSION['wm_email'], $ext_data);

        $public_list = array();
        foreach ($ext_data['accounts'] as $acc) {
            $public_list[] = array(
                'email'     => $acc['email'],
                'host'      => $acc['host'],
                'port'      => $acc['port'],
                'last_sync' => $acc['last_sync']
            );
        }

        echo json_encode(array(
            'status'         => 'ok',
            'imported_count' => $imported_count,
            'accounts'       => $public_list,
            'errors'         => $errors
        ));
        exit;
    }

    if ($action === 'trust_sender') {
        if ($_SERVER['REQUEST_METHOD'] !== 'POST' || empty($_SESSION['re9_private_csrf']) || !hash_equals((string)$_SESSION['re9_private_csrf'], (string)get_val($_SERVER, 'HTTP_X_RE9_CSRF', ''))) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Validação de segurança falhou. Atualize a página.')); exit; }
        $sender_email = extract_clean_email(get_val($_POST, 'sender_email'));
        if (!empty($sender_email)) {
            $rules = get_user_security_rules($_SESSION['wm_email']);
            if (!in_array($sender_email, $rules['whitelist_emails'])) {
                $rules['whitelist_emails'][] = $sender_email;
            }
            $rules['blocked_emails'] = array_values(array_diff($rules['blocked_emails'], array($sender_email)));
            save_user_security_rules($_SESSION['wm_email'], $rules);
        }
        echo json_encode(array('status' => 'ok'));
        exit;
    }

    if ($action === 'block_and_delete_sender') {
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); echo json_encode(array('status'=>'error','msg'=>'Método não permitido.')); exit; }
        if (empty($_SESSION['re9_private_csrf']) || !hash_equals((string)$_SESSION['re9_private_csrf'], (string)get_val($_SERVER, 'HTTP_X_RE9_CSRF', ''))) { http_response_code(403); echo json_encode(array('status'=>'error','msg'=>'Sessão de segurança expirada. Atualize a página.')); exit; }
        $uid           = (int)get_val($_POST, 'uid', 0);
        $folder        = get_val($_POST, 'folder', 'INBOX');
        $sender_email  = extract_clean_email(get_val($_POST, 'sender_email'));
        $sender_ip     = trim(get_val($_POST, 'sender_ip'));
        $sender_server = strtolower(trim(get_val($_POST, 'sender_server')));
        if (!filter_var($sender_email, FILTER_VALIDATE_EMAIL)) { http_response_code(400); echo json_encode(array('status'=>'error','msg'=>'Não foi possível identificar um endereço de remetente válido para bloquear.')); exit; }

        $rules = get_user_security_rules($_SESSION['wm_email']);

        if (filter_var($sender_email, FILTER_VALIDATE_EMAIL) && !in_array($sender_email, $rules['blocked_emails'], true)) {
            $rules['blocked_emails'][] = $sender_email;
        }
        // Não bloqueia domínio, IP ou servidor MX compartilhado automaticamente.

        if (!empty($sender_email)) {
            $rules['whitelist_emails'] = array_values(array_diff($rules['whitelist_emails'], array($sender_email)));
        }

        if (!save_user_security_rules($_SESSION['wm_email'], $rules)) {
            http_response_code(500);
            echo json_encode(array('status' => 'error', 'msg' => 'Não foi possível salvar o bloqueio na proteção da conta.'));
            exit;
        }

        $server_filter = re9_create_server_sender_block($_SESSION['wm_email'], $sender_email);
        $server_filter_active = (isset($server_filter['status']) && $server_filter['status'] === 'ok');

        $imap = new CpanelImapSocket();
        if ($imap->connect($_SESSION['wm_email'], $current_pass)) {
            $deleted = ($uid <= 0) ? true : $imap->deleteEmail($folder, $uid);
            $unseen = $imap->countUnseen('INBOX');
            $imap->close();
            $message = $server_filter_active
                ? 'Bloqueio do servidor ativado: novas mensagens deste endereço serão descartadas antes de chegar à caixa. A mensagem atual foi movida para a Lixeira.'
                : 'Bloqueio local ativado: novas mensagens deste endereço serão retiradas da Entrada quando o webmail atualizar. O filtro direto do servidor não foi confirmado pela hospedagem.';
            if (!$deleted) $message .= ' Atenção: o servidor não confirmou a movimentação da mensagem atual.';
            echo json_encode(array('status' => 'ok', 'unseen' => $unseen, 'server_filter_active' => $server_filter_active, 'message_moved' => $deleted, 'msg' => $message));
        } else {
            $message = $server_filter_active
                ? 'Bloqueio do servidor ativado: novas mensagens deste endereço serão descartadas antes de chegar à caixa. Não foi possível mover a mensagem atual.'
                : 'Bloqueio salvo localmente, mas não foi possível confirmar o filtro do servidor nem mover a mensagem atual. Atualize a caixa para aplicar a proteção local.';
            echo json_encode(array('status' => 'ok', 'server_filter_active' => $server_filter_active, 'message_moved' => false, 'msg' => $message));
        }
        exit;
    }

    if ($action === 'list_emails') {
        $folder = get_val($_GET, 'folder', 'INBOX');
        $imap = new CpanelImapSocket();
        if (!$imap->connect($_SESSION['wm_email'], $current_pass)) {
            echo json_encode(array('status' => 'error', 'msg' => 'Erro ao conectar na caixa de correio.'));
            exit;
        }
        $list = $imap->listEmails($folder, 45, $_SESSION['wm_email']);
        $inbox_unseen = ($folder === 'INBOX') ? $list['unseen'] : $imap->countUnseen('INBOX');
        $imap->close();
        echo json_encode(array(
            'status' => 'ok',
            'total'  => $list['total'],
            'unseen' => $inbox_unseen,
            'emails' => $list['emails']
        ));
        exit;
    }

    if ($action === 'read_email') {
        $uid    = (int)get_val($_GET, 'uid', 0);
        $folder = get_val($_GET, 'folder', 'INBOX');
        $imap   = new CpanelImapSocket();
        if (!$imap->connect($_SESSION['wm_email'], $current_pass)) {
            echo json_encode(array('status' => 'error', 'msg' => 'Falha na conexão.'));
            exit;
        }
        $mail = $imap->readEmail($folder, $uid, $_SESSION['wm_email']);
        $unseen = $imap->countUnseen('INBOX');
        $imap->close();
        if ($mail) {
            $mail['unseen'] = $unseen;
            echo json_encode($mail);
        } else {
            echo json_encode(array('status' => 'error', 'msg' => 'E-mail não encontrado.'));
        }
        exit;
    }

    if ($action === 'delete_email') {
        $folder = get_val($_POST, 'folder', 'INBOX');
        $uids_raw = get_val($_POST, 'uids');
        $uids = array();
        if (!empty($uids_raw)) {
            $uids = array_map('intval', explode(',', $uids_raw));
        }

        $imap = new CpanelImapSocket();
        if ($imap->connect($_SESSION['wm_email'], $current_pass)) {
            $delete_ok = true;
            foreach ($uids as $uid) {
                if ($uid > 0 && !$imap->deleteEmail($folder, $uid)) {
                    $delete_ok = false;
                }
            }
            $unseen = $imap->countUnseen('INBOX');
            $imap->close();
            if ($delete_ok) {
                echo json_encode(array('status' => 'ok', 'unseen' => $unseen));
            } else {
                echo json_encode(array('status' => 'error', 'msg' => 'O servidor de e-mail não confirmou a exclusão de uma ou mais mensagens.'));
            }
        } else {
            echo json_encode(array('status' => 'error', 'msg' => 'Erro ao excluir mensagens.'));
        }
        exit;
    }

    if ($action === 'empty_trash') {
        $imap = new CpanelImapSocket();
        if ($imap->connect($_SESSION['wm_email'], $current_pass)) {
            $emptied = $imap->emptyTrash();
            $unseen = $imap->countUnseen('INBOX');
            $imap->close();
            if ($emptied) {
                echo json_encode(array('status' => 'ok', 'unseen' => $unseen));
            } else {
                echo json_encode(array('status' => 'error', 'msg' => 'O servidor não confirmou que a Lixeira foi esvaziada. Verifique a pasta e tente novamente.'));
            }
        } else {
            echo json_encode(array('status' => 'error', 'msg' => 'Erro ao esvaziar lixeira.'));
        }
        exit;
    }

    if ($action === 'save_draft') {
        $to      = trim(get_val($_POST, 'to'));
        $subject = trim(get_val($_POST, 'subject', '(Rascunho sem assunto)'));
        $body    = normalize_signature_images(get_val($_POST, 'body'));

        $raw_mime  = "Date: " . date("r") . "\r\n";
        $raw_mime .= "To: <$to>\r\n";
        $raw_mime .= "From: <" . $_SESSION['wm_email'] . ">\r\n";
        $raw_mime .= "Subject: =?UTF-8?B?" . base64_encode("Assunto: " . $subject) . "?=\r\n";
        $raw_mime .= "MIME-Version: 1.0\r\n";
        $raw_mime .= "Content-Type: text/html; charset=UTF-8\r\n";
        $raw_mime .= "Content-Transfer-Encoding: base64\r\n\r\n";
        $raw_mime .= chunk_split(base64_encode($body));

        $imap = new CpanelImapSocket();
        if ($imap->connect($_SESSION['wm_email'], $current_pass)) {
            $imap->appendMessageToFolder('INBOX.Drafts', $raw_mime, '\\Seen \\Draft');
            $imap->close();
            echo json_encode(array('status' => 'ok'));
        } else {
            echo json_encode(array('status' => 'error', 'msg' => 'Erro ao salvar rascunho.'));
        }
        exit;
    }

    if ($action === 'send_email') {
        $to      = trim(get_val($_POST, 'to'));
        $subject = trim(get_val($_POST, 'subject', '(Sem Assunto)'));
        $body    = get_val($_POST, 'body');
        $fw_atts = json_decode(get_val($_POST, 'forwarded_attachments', '[]'), true);
        if (!is_array($fw_atts)) $fw_atts = array();

        if (!filter_var($to, FILTER_VALIDATE_EMAIL)) {
            echo json_encode(array('status' => 'error', 'msg' => 'Destinatário inválido.'));
            exit;
        }
        echo json_encode(send_cpanel_smtp($_SESSION['wm_email'], $current_pass, $to, $subject, $body, $fw_atts));
        exit;
    }

    if ($action === 'save_signature_card') {
        global $SIGS_FILE;
        $email = $_SESSION['wm_email'];
        $nome  = trim(get_val($_POST, 'sig_nome'));
        $cargo = trim(get_val($_POST, 'sig_cargo'));
        $zap   = trim(get_val($_POST, 'sig_whatsapp'));
        $site  = trim(get_val($_POST, 'sig_site'));

        $base_url = get_webmail_base_url();
        $user_logo_uploaded = handle_image_upload('sig_logo_file', 'user_logo');
        $sigs = load_protected_json($SIGS_FILE);
        $existing_sig_html = get_user_signature($email);
        $logo_url = '';

        if ($user_logo_uploaded) {
            $logo_url = $base_url . $user_logo_uploaded;
        } elseif (isset($sigs[$email]) && is_array($sigs[$email]) && !empty($sigs[$email]['logo'])) {
            $logo_url = $sigs[$email]['logo'];
        } elseif (preg_match('/src=["\']([^"\']*webmail_uploads\/user_logo_[^"\']+)["\']/i', $existing_sig_html, $m_old)) {
            $logo_url = $m_old[1];
        }

        if (!empty($logo_url) && strpos($logo_url, 'http') !== 0 && strpos($logo_url, 'data:') !== 0) {
            $logo_url = $base_url . ltrim($logo_url, '/');
        }

        $card_html = build_clean_signature_html($email, $nome, $cargo, $zap, $site, $logo_url);

        $sigs[$email] = array(
            'nome'  => $nome,
            'cargo' => $cargo,
            'zap'   => $zap,
            'site'  => $site,
            'logo'  => $logo_url,
            'html'  => $card_html
        );
        save_protected_json($SIGS_FILE, $sigs);

        echo json_encode(array('status' => 'ok', 'signature' => $card_html));
        exit;
    }

    if ($action === 'save_branding') {
        if (!is_user_admin() || !re9_admin_password_matches(get_val($_POST, 'admin_pass'))) {
            echo json_encode(array('status' => 'error', 'msg' => 'Acesso negado ou senha incorreta!'));
            exit;
        }

        $APP_CONFIG['brand_name']         = get_val($_POST, 'brand_name', $APP_CONFIG['brand_name']);
        $APP_CONFIG['cpanel_host']        = trim(get_val($_POST, 'cpanel_host', $APP_CONFIG['cpanel_host']));
        $APP_CONFIG['cpanel_user']        = trim(get_val($_POST, 'cpanel_user', $APP_CONFIG['cpanel_user']));
        $APP_CONFIG['whatsapp_api_url']   = trim(get_val($_POST, 'whatsapp_api_url', get_val($APP_CONFIG, 'whatsapp_api_url')));
        $wa_tok = trim(get_val($_POST, 'whatsapp_api_token'));
        if ($wa_tok !== '') $APP_CONFIG['whatsapp_api_token'] = $wa_tok;
        $dv_env = strtolower(trim(get_val($_POST, 'datavalid_environment', 'production')));
        $APP_CONFIG['datavalid_environment'] = ($dv_env === 'demo') ? 'demo' : 'production';
        $APP_CONFIG['datavalid_template_id'] = trim(get_val($_POST, 'datavalid_template_id', get_val($APP_CONFIG, 'datavalid_template_id')));
        $APP_CONFIG['datavalid_cnpj_anuente'] = preg_replace('/\D/', '', get_val($_POST, 'datavalid_cnpj_anuente', get_val($APP_CONFIG, 'datavalid_cnpj_anuente')));
        $dv_key = trim(get_val($_POST, 'datavalid_consumer_key'));
        $dv_secret = trim(get_val($_POST, 'datavalid_consumer_secret'));
        $dv_gcc = trim(get_val($_POST, 'datavalid_gcc_token'));
        if ($dv_key !== '') $APP_CONFIG['datavalid_consumer_key'] = $dv_key;
        if ($dv_secret !== '') $APP_CONFIG['datavalid_consumer_secret'] = $dv_secret;
        if ($dv_gcc !== '') $APP_CONFIG['datavalid_gcc_token'] = $dv_gcc;
        
        $cp_tok = trim(get_val($_POST, 'cpanel_api_token'));
        if (!empty($cp_tok)) {
            $APP_CONFIG['cpanel_api_token'] = $cp_tok;
        }
        $interval = (int)get_val($_POST, 'mobile_ad_interval', 15);
        $APP_CONFIG['mobile_ad_interval'] = max(5, $interval);

        $up_logo = handle_image_upload('brand_logo_file', 'logo_topo');
        if ($up_logo) {
            $APP_CONFIG['brand_logo'] = $up_logo;
        }

        save_protected_json($CONFIG_FILE, $APP_CONFIG);
        echo json_encode(array('status' => 'ok', 'logo' => $APP_CONFIG['brand_logo']));
        exit;
    }

    if ($action === 'save_store_product_price') {
        if (!is_user_admin() || !re9_admin_password_matches(get_val($_POST, 'admin_pass'))) {
            http_response_code(403);
            echo json_encode(array('status' => 'error', 'msg' => 'Acesso negado ou senha incorreta.'));
            exit;
        }
        $price_id = trim((string)get_val($_POST, 'ad_id', ''));
        $price_raw = trim((string)get_val($_POST, 'price', ''));
        $price_raw = str_replace(',', '.', $price_raw);
        if ($price_id === '' || $price_raw === '' || !is_numeric($price_raw) || (float)$price_raw <= 0) {
            echo json_encode(array('status' => 'error', 'msg' => 'Informe um preço válido, maior que zero.'));
            exit;
        }
        $price_value = round((float)$price_raw, 2);
        $pool = isset($APP_CONFIG['ads_pool']) && is_array($APP_CONFIG['ads_pool']) ? $APP_CONFIG['ads_pool'] : array();
        $updated = false;
        foreach ($pool as &$price_ad) {
            if (!is_array($price_ad)) continue;
            $current_id = (string)agenda_value($price_ad, 'id', agenda_value($price_ad, 'ad_id', ''));
            if ($current_id !== $price_id) continue;
            $price_ad['price'] = $price_value;
            $price_ad['ad_price'] = $price_value;
            $price_ad['is_product'] = 1;
            if (empty($price_ad['seller_email'])) $price_ad['seller_email'] = sales_resolve_seller_email($price_ad);
            $updated = true;
            break;
        }
        unset($price_ad);
        if (!$updated) {
            echo json_encode(array('status' => 'error', 'msg' => 'Produto não encontrado no Banco de Cartazes.'));
            exit;
        }
        $APP_CONFIG['ads_pool'] = $pool;
        if (!save_protected_json($CONFIG_FILE, $APP_CONFIG)) {
            echo json_encode(array('status' => 'error', 'msg' => 'Não foi possível gravar o preço no banco de anúncios.'));
            exit;
        }
        echo json_encode(array('status' => 'ok', 'price' => $price_value, 'ads_pool' => array_values($pool)));
        exit;
    }

    if ($action === 'save_ad_pool') {
        if (!is_user_admin() || !re9_admin_password_matches(get_val($_POST, 'admin_pass'))) {
            echo json_encode(array('status' => 'error', 'msg' => 'Acesso negado ou senha incorreta!'));
            exit;
        }

        $ad_id        = get_val($_POST, 'ad_id');
        $uploaded_img = handle_image_upload('ad_image_file', 'cartaz');
        
        $found = false;
        if (!empty($ad_id)) {
            foreach ($APP_CONFIG['ads_pool'] as &$item) {
                if ($item['id'] === $ad_id) {
                    $item['sender']      = trim(get_val($_POST, 'ad_sender', $item['sender']));
                    $item['badge']       = trim(get_val($_POST, 'ad_badge', $item['badge']));
                    $item['title']       = trim(get_val($_POST, 'ad_title', $item['title']));
                    $item['description'] = trim(get_val($_POST, 'ad_desc', $item['description']));
                    $item['cta_text']    = trim(get_val($_POST, 'ad_cta', $item['cta_text']));
                    $item['external_url'] = trim(get_val($_POST, 'ad_url', agenda_value($item, 'external_url', $item['url'])));
                    $item['is_product']  = !empty($_POST['ad_is_product']) ? 1 : 0;
                    $item['price']       = (float)str_replace(',', '.', trim((string)get_val($_POST, 'ad_price', agenda_value($item, 'price', 0))));
                    $item['category']    = agenda_clean_text(get_val($_POST, 'ad_category', agenda_value($item, 'category', 'Geral')), 100);
                    $item['seller_email']= strtolower(trim((string)get_val($_POST, 'ad_seller_email', agenda_value($item, 'seller_email', $_SESSION['wm_email']))));
                    $item['fulfillment'] = trim((string)get_val($_POST, 'ad_fulfillment', agenda_value($item, 'fulfillment', 'digital')));
                    if (!in_array($item['fulfillment'], array('digital','physical','service','made_to_order'), true)) $item['fulfillment'] = 'digital';
                    if ($item['is_product'] && ($item['price'] <= 0 || !filter_var($item['seller_email'], FILTER_VALIDATE_EMAIL))) {
                        echo json_encode(array('status'=>'error','msg'=>'Para publicar na Loja, informe um preço maior que zero e um e-mail corporativo válido do anunciante.'));
                        exit;
                    }
                    $item['url'] = $item['is_product'] ? sales_product_url($item['id']) : $item['external_url'];
                    if ($uploaded_img) {
                        $item['image']   = $uploaded_img;
                    }
                    $found = true;
                    break;
                }
            }
            unset($item);
        }

        if (!$found) {
            $new_ad = array(
                'id'          => 'ad_' . time() . '_' . rand(100, 999),
                'sender'      => trim(get_val($_POST, 'ad_sender', 'Patrocinado')),
                'badge'       => trim(get_val($_POST, 'ad_badge', 'Anúncio')),
                'title'       => trim(get_val($_POST, 'ad_title', 'Oferta Especial')),
                'description' => trim(get_val($_POST, 'ad_desc', '')),
                'image'       => $uploaded_img ? $uploaded_img : '',
                'cta_text'    => trim(get_val($_POST, 'ad_cta', 'Saiba Mais')),
                'url'         => trim(get_val($_POST, 'ad_url', 'https://www.re9seusite.com.br')),
                'external_url'=> trim(get_val($_POST, 'ad_url', 'https://www.re9seusite.com.br')),
                'is_product'  => !empty($_POST['ad_is_product']) ? 1 : 0,
                'price'       => (float)str_replace(',', '.', trim((string)get_val($_POST, 'ad_price', '0'))),
                'category'    => agenda_clean_text(get_val($_POST, 'ad_category', 'Geral'), 100),
                'seller_email'=> strtolower(trim((string)get_val($_POST, 'ad_seller_email', $_SESSION['wm_email']))),
                'fulfillment' => trim((string)get_val($_POST, 'ad_fulfillment', 'digital'))
            );
            if (!in_array($new_ad['fulfillment'], array('digital','physical','service','made_to_order'), true)) $new_ad['fulfillment'] = 'digital';
            if ($new_ad['is_product'] && ($new_ad['price'] <= 0 || !filter_var($new_ad['seller_email'], FILTER_VALIDATE_EMAIL))) {
                echo json_encode(array('status'=>'error','msg'=>'Para publicar na Loja, informe um preço maior que zero e um e-mail corporativo válido do anunciante.'));
                exit;
            }
            if ($new_ad['is_product']) $new_ad['url'] = sales_product_url($new_ad['id']);
            array_unshift($APP_CONFIG['ads_pool'], $new_ad);
        }

        save_protected_json($CONFIG_FILE, $APP_CONFIG);
        echo json_encode(array('status' => 'ok', 'ads_pool' => $APP_CONFIG['ads_pool']));
        exit;
    }

    if ($action === 'delete_ad_pool') {
        if (!is_user_admin() || !re9_admin_password_matches(get_val($_POST, 'admin_pass'))) {
            echo json_encode(array('status' => 'error', 'msg' => 'Acesso negado ou senha incorreta!'));
            exit;
        }
        $del_id = get_val($_POST, 'ad_id');
        $new_pool = array();
        foreach ($APP_CONFIG['ads_pool'] as $item) {
            if ($item['id'] !== $del_id) {
                $new_pool[] = $item;
            }
        }
        if (empty($new_pool)) {
            $new_pool = $default_config['ads_pool'];
        }
        $APP_CONFIG['ads_pool'] = $new_pool;
        save_protected_json($CONFIG_FILE, $APP_CONFIG);
        echo json_encode(array('status' => 'ok', 'ads_pool' => $APP_CONFIG['ads_pool']));
        exit;
    }
    exit;
}

// =========================================================================
// PAINEL DE VINCULAÇÃO DE INSTALAÇÕES CLIENTES À CENTRAL RENOVE
// =========================================================================
if (isset($_GET['central_admin'])) {
    if (empty($RE9_IS_CENTRAL_HUB) || !is_user_admin()) { http_response_code(403); echo 'Acesso restrito ao administrador da Central Renove.'; exit; }
    $centralCsrf = isset($_SESSION['re9_private_csrf']) ? (string)$_SESSION['re9_private_csrf'] : '';
    header('Content-Type: text/html; charset=UTF-8');
    $centralCsrfHtml = htmlspecialchars($centralCsrf, ENT_QUOTES, 'UTF-8');
    $centralCsrfJson = json_encode($centralCsrf);
    echo <<<HTML
<!doctype html>
<html lang="pt-BR"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Domínios clientes | Central Renove</title><script src="https://cdn.tailwindcss.com"></script></head>
<body class="min-h-screen bg-slate-100 p-4 text-slate-800"><main class="mx-auto max-w-4xl space-y-5">
<header class="rounded-2xl bg-[#002244] p-5 text-white"><a href="index.php" class="text-xs text-orange-200 underline">← Voltar ao Webmail RE9</a><h1 class="mt-3 text-2xl font-black">Central Renove — instalações clientes</h1><p class="mt-1 text-sm text-blue-100">Cadastre cada domínio de cliente, gere um token individual e acompanhe os acessos conectados.</p></header>
<section class="rounded-2xl bg-white p-5 shadow"><h2 class="text-lg font-extrabold">Conectar novo domínio</h2><p class="mt-1 text-sm text-slate-500">Digite o domínio do cliente (com ou sem www, ou cole a URL). O token é individual e aparece apenas uma vez.</p>
<form id="centralIssueForm" class="mt-4 grid gap-3 sm:grid-cols-[1fr_1fr_auto]"><input id="centralSiteId" class="rounded-lg border p-3" placeholder="cliente.com.br" required><input id="centralAdminPass" type="password" class="rounded-lg border p-3" placeholder="Senha administrativa" required><button class="rounded-lg bg-[#002244] px-4 py-3 font-bold text-white">Gerar token</button></form>
<input id="centralCsrf" type="hidden" value="{$centralCsrfHtml}"><div id="centralIssueResult" class="mt-4 hidden rounded-xl border border-emerald-200 bg-emerald-50 p-4 text-sm"></div></section>
<section class="rounded-2xl bg-white p-5 shadow"><div class="flex items-center justify-between gap-3"><div><h2 class="text-lg font-extrabold">Domínios vinculados</h2><p class="text-sm text-slate-500">Online significa que a instalação enviou sinal nos últimos 3 minutos.</p></div><button id="centralReload" class="rounded-lg bg-slate-100 px-3 py-2 text-sm font-bold">Atualizar</button></div><div id="centralSitesList" class="mt-4 space-y-2"><p class="text-sm text-slate-500">Carregando...</p></div></section>
<section class="rounded-2xl bg-white p-5 shadow"><div class="flex flex-wrap items-center justify-between gap-2"><div><h2 class="text-lg font-extrabold">Caixas conectadas em todos os domínios</h2><p class="text-sm text-slate-500">Contas com sessão ativa em todas as instalações RE9 vinculadas.</p></div><strong id="centralOnlineCount" class="rounded-full bg-emerald-100 px-3 py-1 text-sm text-emerald-800">0 online</strong></div><div id="centralOnlineUsers" class="mt-4 space-y-2"><p class="text-sm text-slate-500">Carregando...</p></div></section>
<section class="rounded-2xl bg-white p-5 shadow"><div class="flex flex-wrap items-center justify-between gap-2"><div><h2 class="text-lg font-extrabold">Contas de e-mail dos domínios clientes</h2><p class="text-sm text-slate-500">Inventário remoto enviado por cada instalação. Liberação em lote não altera senhas nem remove caixas do cPanel.</p></div><span id="centralMailboxSummary" class="rounded-full bg-blue-100 px-3 py-1 text-sm font-bold text-blue-800">0 contas</span></div><div id="centralRemoteMailboxList" class="mt-4 max-h-[520px] space-y-2 overflow-y-auto"><p class="text-sm text-slate-500">Aguardando inventário dos domínios clientes.</p></div></section>
<section class="rounded-2xl border border-amber-200 bg-amber-50 p-4 text-sm text-amber-900"><strong>Importante:</strong> em cada domínio cliente, preserve o <code>webmail_data/secure_config.php</code> e as credenciais cPanel próprias. No domínio cliente, abra <code>?central_setup=1</code> e cole o token gerado aqui. Não copie credenciais cPanel ou dados privados do RE9 para os clientes.</section>
</main>
<script>
var csrf = {$centralCsrfJson};
function esc(v){return String(v||"").replace(/[&<>\"']/g,function(c){return {"&":"&amp;","<":"&lt;",">":"&gt;","\"":"&quot;","'":"&#39;"}[c];});}
var issueForm=document.getElementById("centralIssueForm");
issueForm.addEventListener("submit",async function(e){e.preventDefault();var box=document.getElementById("centralIssueResult");var fd=new FormData();fd.append("site_id",document.getElementById("centralSiteId").value.trim());fd.append("admin_pass",document.getElementById("centralAdminPass").value);fd.append("csrf",csrf);try{var r=await fetch("?api=central_issue_site_token",{method:"POST",body:fd,credentials:"same-origin"});var d=await r.json();if(d.status!=="ok")throw new Error(d.msg||"Falha ao gerar token.");box.classList.remove("hidden");box.innerHTML="<strong>Token criado para "+esc(d.site_id)+".</strong><p class=\"mt-1\">Abra no domínio cliente: <a class=\"underline font-bold\" href=\""+esc(d.setup_url)+"\" target=\"_blank\" rel=\"noopener\">"+esc(d.setup_url)+"</a></p><label class=\"mt-3 block text-xs font-bold\">Token (copie agora; não será exibido novamente)</label><textarea id=\"centralNewToken\" class=\"mt-1 w-full rounded-lg border p-3 font-mono text-xs\" rows=3 readonly></textarea><button type=\"button\" id=\"centralCopyToken\" class=\"mt-2 rounded-lg bg-emerald-700 px-3 py-2 font-bold text-white\">Copiar token</button><p class=\"mt-2 text-xs\">No outro domínio, entre em <strong>?central_setup=1</strong> e cole o token. Não envie por e-mail público.</p>";document.getElementById("centralNewToken").value=d.token;document.getElementById("centralCopyToken").onclick=function(){document.getElementById("centralNewToken").select();document.execCommand("copy");};document.getElementById("centralAdminPass").value="";loadCentralSites();}catch(err){box.classList.remove("hidden");box.className="mt-4 rounded-xl border border-red-200 bg-red-50 p-4 text-sm text-red-800";box.textContent=err.message;}});
async function loadCentralSites(){var box=document.getElementById("centralSitesList");var usersBox=document.getElementById("centralOnlineUsers");var mailboxBox=document.getElementById("centralRemoteMailboxList");try{var r=await fetch("?api=central_sites_list",{credentials:"same-origin",cache:"no-store"});var d=await r.json();if(d.status!=="ok")throw new Error(d.msg||"Falha ao consultar domínios.");box.innerHTML=(d.sites||[]).map(function(site){var progress=Number(site.released_count||0)+" / "+Number(site.mailbox_count||0)+" liberadas";var command=site.last_command_status?" · Última operação: "+site.last_command_status+(site.last_command_affected?" ("+site.last_command_affected+")":"")+(site.last_command_message?" — "+site.last_command_message:""):"";var btn=Number(site.mailbox_count||0)>0&&Number(site.released_count||0)<Number(site.mailbox_count||0)?"<button type=\"button\" data-domain=\""+esc(site.site_id)+"\" data-count=\""+esc(site.mailbox_count)+"\" onclick=\"centralBulkRelease(this.dataset.domain, this.dataset.count)\" class=\"mt-2 rounded-lg bg-emerald-700 px-3 py-2 text-xs font-extrabold text-white\">Liberar todas as "+esc(site.mailbox_count)+" caixas deste domínio</button>":"";return "<div class=\"rounded-xl border p-3\"><div class=\"flex flex-wrap items-center justify-between gap-2\"><div><strong>"+esc(site.site_id)+"</strong><div class=\"text-xs text-slate-500\">Último sinal: "+esc(site.last_seen_text)+"</div><div class=\"mt-1 text-xs font-semibold text-slate-700\">Contas: "+esc(site.mailbox_count||0)+" · "+esc(progress)+"</div><div class=\"text-[11px] text-slate-500\">Inventário: "+esc(site.mailboxes_updated_text||"não recebido")+esc(command)+"</div>"+btn+"</div><span class=\"rounded-full px-3 py-1 text-xs font-bold "+(site.online?"bg-emerald-100 text-emerald-800":"bg-slate-100 text-slate-600")+"\">"+(site.online?"Conectado":"Sem sinal")+"</span></div></div>";}).join("")||"<p class=\"text-sm text-slate-500\">Nenhum domínio cadastrado ainda.</p>";var users=d.online_users||[];document.getElementById("centralOnlineCount").textContent=String(users.length)+" online";usersBox.innerHTML=users.map(function(u){return "<div class=\"flex flex-wrap items-center justify-between gap-2 rounded-xl border border-emerald-100 p-3\"><div><strong>"+esc(u.email)+"</strong><div class=\"text-xs text-slate-500\">"+esc(u.access_host||u.domain||"Domínio cliente")+" · "+esc(u.device||"Webmail")+"</div></div><span class=\"rounded-full bg-emerald-100 px-3 py-1 text-xs font-bold text-emerald-800\">"+esc(u.last_seen_fmt||"Conectado")+"</span></div>";}).join("")||"<p class=\"text-sm text-slate-500\">Nenhuma caixa de domínio cliente conectada neste momento.</p>";var mailboxes=d.remote_mailboxes||[];document.getElementById("centralMailboxSummary").textContent=mailboxes.length+" contas";mailboxBox.innerHTML=mailboxes.map(function(m){var released=!!m.released;return "<div class=\"flex flex-wrap items-center justify-between gap-2 rounded-lg border border-slate-200 p-3\"><div class=\"min-w-0\"><strong class=\"break-all text-sm text-slate-800\">"+esc(m.email)+"</strong><div class=\"text-[11px] text-slate-500\">"+esc(m.domain||"")+"</div></div><span class=\"rounded-full px-3 py-1 text-[10px] font-extrabold "+(released?"bg-emerald-100 text-emerald-800":"bg-amber-100 text-amber-800")+"\">"+(released?"LIBERADO":"PENDENTE DE LIBERAÇÃO")+"</span></div>";}).join("")||"<p class=\"text-sm text-slate-500\">Nenhum inventário recebido. A instalação cliente precisa abrir o webmail com a versão federada atualizada para enviar a lista.</p>";}catch(e){box.textContent=e.message;if(usersBox)usersBox.textContent=e.message;if(mailboxBox)mailboxBox.textContent=e.message;}}
async function centralBulkRelease(domain,count){if(!confirm("Você confirma que quer marcar como LIBERADAS todas as "+count+" caixas existentes em "+domain+"? A ação não cria nem exclui contas e não altera senhas do cPanel."))return;var pass=window.prompt("Digite a senha administrativa da Central Renove para autorizar a liberação em lote:");if(pass===null||pass==="")return;var body=new URLSearchParams({site_id:domain,admin_pass:pass,csrf:csrf});try{var r=await fetch("?api=central_queue_bulk_release",{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:body.toString()});var d=await r.json();if(!r.ok||d.status!=="ok")throw new Error(d.msg||"Não foi possível enviar a operação.");alert(d.message+" O comando será executado quando a instalação cliente fizer o próximo sincronismo.");loadCentralSites();}catch(e){alert(e.message||"Falha ao solicitar liberação em lote.");}}
document.getElementById("centralReload").addEventListener("click",loadCentralSites);loadCentralSites();setInterval(loadCentralSites,15000);
</script></body></html>
HTML;
    exit;
}

if (isset($_GET['central_setup'])) {
    if (!empty($RE9_IS_CENTRAL_HUB)) { header('Location: index.php?central_admin=1'); exit; }
    $setupHost = (string)$RE9_INSTANCE_HOST;
    $alreadyLinked = re9_central_is_client_connected();
    header('Content-Type: text/html; charset=UTF-8');
    $setupHostHtml = htmlspecialchars($setupHost, ENT_QUOTES, 'UTF-8');
    $alreadyLinkedHtml = $alreadyLinked ? '<div class="mt-4 rounded-lg bg-emerald-50 p-3 text-sm text-emerald-800">Esta instalação já está conectada. Inserir um novo token fará a rotação da conexão.</div>' : '';
    echo <<<HTML
<!doctype html>
<html lang="pt-BR"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Conectar ao Renove</title><script src="https://cdn.tailwindcss.com"></script></head>
<body class="min-h-screen bg-slate-100 p-4"><main class="mx-auto mt-10 max-w-xl rounded-2xl bg-white p-6 shadow-xl">
<div class="rounded-xl bg-[#002244] p-4 text-white"><p class="text-xs font-bold uppercase tracking-wider text-orange-300">Integração segura</p><h1 class="mt-1 text-2xl font-black">Conectar este Webmail ao Renove</h1><p class="mt-1 text-sm text-blue-100">Domínio detectado: {$setupHostHtml}</p></div>
{$alreadyLinkedHtml}
<p class="mt-4 text-sm text-slate-600">Cole abaixo o token individual gerado no painel Central Renove. As caixas de e-mail e as credenciais cPanel permanecem neste servidor; anúncios, catálogo da loja e identidade visual serão sincronizados com a central. Presença das caixas abertas será enviada para o painel Renove; mensagens e credenciais permanecem neste domínio.</p>
<form id="centralConnectForm" class="mt-4 space-y-3"><textarea id="centralClientToken" class="w-full rounded-lg border p-3 font-mono text-xs" rows="4" placeholder="Cole aqui o token de conexão" required></textarea><button class="w-full rounded-lg bg-[#002244] p-3 font-bold text-white">Validar e conectar ao Renove</button></form>
<div id="centralConnectFeedback" class="mt-3 hidden rounded-lg p-3 text-sm"></div><p class="mt-5 text-xs text-slate-400">Conexão HTTPS autenticada. Não envie senhas de caixas postais para a central.</p>
</main><script>
document.getElementById("centralConnectForm").addEventListener("submit",async function(e){e.preventDefault();var b=e.target.querySelector("button");var box=document.getElementById("centralConnectFeedback");b.disabled=true;b.textContent="Validando token...";var fd=new FormData();fd.append("token",document.getElementById("centralClientToken").value.trim());try{var r=await fetch("?api=central_connect_client",{method:"POST",body:fd});var d=await r.json();if(d.status!=="ok")throw new Error(d.msg||"Não foi possível conectar.");box.className="mt-3 rounded-lg bg-emerald-50 p-3 text-sm text-emerald-800";box.textContent=d.message+" Atualize o webmail para carregar os anúncios centrais.";document.getElementById("centralClientToken").value="";}catch(err){box.className="mt-3 rounded-lg bg-red-50 p-3 text-sm text-red-800";box.textContent=err.message;}finally{box.classList.remove("hidden");b.disabled=false;b.textContent="Validar e conectar ao Renove";}});
</script></body></html>
HTML;
    exit;
}

// Cores recebidas da Central são validadas e aplicadas nas telas do webmail e da loja.
$re9ThemeSafeHex = function($value, $fallback) {
    $value = strtoupper(trim((string)$value));
    return preg_match('/^#[0-9A-F]{6}$/', $value) ? $value : $fallback;
};
$re9ThemeShade = function($hex, $factor) {
    $hex = ltrim((string)$hex, '#');
    if (!preg_match('/^[0-9A-Fa-f]{6}$/', $hex)) return '#00152B';
    $r = max(0, min(255, (int)round(hexdec(substr($hex,0,2)) * $factor)));
    $g = max(0, min(255, (int)round(hexdec(substr($hex,2,2)) * $factor)));
    $b = max(0, min(255, (int)round(hexdec(substr($hex,4,2)) * $factor)));
    return sprintf('#%02X%02X%02X', $r, $g, $b);
};
$RE9_THEME_NAVY = $re9ThemeSafeHex(get_val($APP_CONFIG, 'color_navy', '#002244'), '#002244');
$RE9_THEME_BLOOD = $re9ThemeSafeHex(get_val($APP_CONFIG, 'color_blood', '#990000'), '#990000');
$RE9_THEME_CHROME = $re9ThemeSafeHex(get_val($APP_CONFIG, 'color_chrome', '#475569'), '#475569');
$RE9_THEME_NAVY_DARK = $re9ThemeShade($RE9_THEME_NAVY, 0.72);
$RE9_THEME_BLOOD_LIGHT = $re9ThemeShade($RE9_THEME_BLOOD, 1.18);
$RE9_THEME_CHROME_HOVER = $re9ThemeShade($RE9_THEME_CHROME, 0.78);

// =========================================================================
// LOJA RE9 / CHECKOUT / CENTRAL DE PEDIDOS
// =========================================================================
if (isset($_GET['loja'])) {
    $store_mode = trim((string)$_GET['loja']);
    $store_file = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : './';
    $store_logged = !empty($_SESSION['wm_email']);
    if ($store_logged && re9_identity_gate_required($_SESSION['wm_email'])) {
        header('Location: ' . (isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : './'));
        exit;
    }
    if (in_array($store_mode, array('checkout','pedidos'), true) && !$store_logged) {
        $_SESSION['re9_shop_return'] = $store_mode === 'pedidos' ? '?loja=pedidos' : '?loja=checkout&id=' . rawurlencode((string)get_val($_GET, 'id', ''));
        header('Location: ' . (isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : './'));
        exit;
    }
    if (empty($_SESSION['re9_sales_csrf'])) {
        $sales_csrf_bytes = function_exists('openssl_random_pseudo_bytes') ? openssl_random_pseudo_bytes(24) : false;
        $_SESSION['re9_sales_csrf'] = $sales_csrf_bytes ? bin2hex($sales_csrf_bytes) : sha1(uniqid((string)mt_rand(), true));
    }
    $store_csrf = (string)$_SESSION['re9_sales_csrf'];
    $store_me = $store_logged ? strtolower(trim((string)$_SESSION['wm_email'])) : '';
    $store_product = false;
    if ($store_mode === 'checkout') $store_product = sales_find_product(get_val($_GET, 'id', ''));
    if ($store_mode === 'checkout' && !is_array($store_product)) $store_mode = '1';
    $store_products = sales_get_products();
    $store_name = $store_logged ? sales_public_name($store_me) : '';
    $store_is_admin = $store_logged ? is_user_admin() : false;
    $money = function($value) { return 'R$ ' . number_format((float)$value, 2, ',', '.'); };
    $fulfillment_labels = array('digital'=>'Produto digital / liberação de acesso','physical'=>'Produto físico / envio','service'=>'Serviço / agendamento','made_to_order'=>'Produto sob encomenda / confecção');
    ?><!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Loja RE9 | Central de Vendas</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<style>
:root{--color-navy:<?php echo htmlspecialchars($RE9_THEME_NAVY,ENT_QUOTES,'UTF-8'); ?>;--color-navy-dark:<?php echo htmlspecialchars($RE9_THEME_NAVY_DARK,ENT_QUOTES,'UTF-8'); ?>;--color-blood:<?php echo htmlspecialchars($RE9_THEME_BLOOD,ENT_QUOTES,'UTF-8'); ?>;--color-blood-light:<?php echo htmlspecialchars($RE9_THEME_BLOOD_LIGHT,ENT_QUOTES,'UTF-8'); ?>;--color-chrome:<?php echo htmlspecialchars($RE9_THEME_CHROME,ENT_QUOTES,'UTF-8'); ?>;--color-chrome-hover:<?php echo htmlspecialchars($RE9_THEME_CHROME_HOVER,ENT_QUOTES,'UTF-8'); ?>}
[class~="bg-[#002244]"]{background-color:var(--color-navy)!important}[class~="text-[#002244]"]{color:var(--color-navy)!important}[class~="border-[#002244]"]{border-color:var(--color-navy)!important}
[class~="bg-[#990000]"]{background-color:var(--color-blood)!important}[class~="text-[#990000]"]{color:var(--color-blood)!important}[class~="border-[#990000]"]{border-color:var(--color-blood)!important}
[class~="bg-[#475569]"]{background-color:var(--color-chrome)!important}[class~="text-[#475569]"]{color:var(--color-chrome)!important}[class~="border-[#475569]"]{border-color:var(--color-chrome)!important}
*{box-sizing:border-box}
html{background:#f3f6fa}
body{font-family:Inter,'Segoe UI',system-ui,sans-serif;background:#f3f6fa;color:#172b3e;font-size:16px}
.re9-navy{background:linear-gradient(118deg,var(--color-navy-dark) 0%,var(--color-navy) 58%,var(--color-chrome) 100%)}
.re9-orange{color:#ffb15e}
.re9-btn{background:linear-gradient(110deg,#f28c38,#ffad55);color:#172b3e;box-shadow:0 7px 18px rgba(194,103,26,.24);transition:transform .18s ease,box-shadow .18s ease}
.re9-btn:hover{background:linear-gradient(110deg,#ed8128,#ffb15e);transform:translateY(-1px);box-shadow:0 10px 22px rgba(194,103,26,.3)}
.re9-card{box-shadow:0 10px 28px rgba(15,23,42,.075)}
.re9-store-header-inner{width:100%;max-width:1320px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;gap:1.25rem}
.re9-store-nav{display:flex;align-items:center;justify-content:flex-end;gap:.55rem;flex-wrap:wrap}
.re9-store-nav a{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;min-height:43px;padding:.62rem 1rem;border:1px solid rgba(255,255,255,.2);border-radius:.85rem;background:rgba(255,255,255,.1);font-size:13px;font-weight:850;white-space:nowrap;transition:all .18s ease}
.re9-store-nav a:hover{background:rgba(255,255,255,.2);border-color:rgba(255,255,255,.42);transform:translateY(-1px)}
.re9-store-nav a.re9-store-home{background:#ffb15e;color:#1a3045;border-color:#ffb15e}
.re9-store-hero{position:relative;isolation:isolate;overflow:hidden;border-radius:1.5rem;background:radial-gradient(circle at 86% 15%,rgba(255,177,94,.25),transparent 27%),linear-gradient(120deg,var(--color-navy-dark) 0%,var(--color-navy) 100%);padding:clamp(1.25rem,3vw,2.25rem);color:#fff;box-shadow:0 14px 34px rgba(0,34,68,.14)}
.re9-store-hero:after{content:"";position:absolute;z-index:-1;width:240px;height:240px;right:-65px;bottom:-145px;border:1px solid rgba(255,255,255,.16);border-radius:50%;box-shadow:0 0 0 26px rgba(255,255,255,.035),0 0 0 54px rgba(255,255,255,.025)}
.re9-store-trust{display:flex;flex-wrap:wrap;gap:.55rem;margin-top:1.15rem}
.re9-store-trust span{display:inline-flex;align-items:center;gap:.45rem;padding:.48rem .7rem;border:1px solid rgba(255,255,255,.18);border-radius:999px;background:rgba(255,255,255,.09);font-size:11px;font-weight:750;color:#f1f5f9}
.re9-products-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem;width:100%;align-items:stretch}
.re9-product-card{display:flex;min-width:0;width:100%;flex-direction:column;border:1px solid #e4eaf1;border-radius:1.15rem;background:#fff;overflow:hidden;box-shadow:0 7px 20px rgba(15,23,42,.07);transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease}
.re9-product-card:hover{transform:translateY(-3px);box-shadow:0 16px 34px rgba(15,23,42,.13);border-color:#cbd7e3}
.re9-product-media{position:relative;display:block;width:100%;aspect-ratio:1/1;margin:0;padding:0;overflow:hidden;background:#eef2f6;line-height:0}
.re9-product-media .re9-product-image{width:100%;height:100%}img.re9-product-image{display:block!important;width:100%!important;height:100%!important;max-width:none!important;max-height:none!important;margin:0!important;padding:0!important;aspect-ratio:auto!important;object-fit:cover!important;object-position:center!important;background:#eef2f6}
.re9-product-info{display:flex;flex:1;min-width:0;flex-direction:column;padding:.9rem}
.re9-product-info h2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:2.55em}
.re9-product-info .re9-product-description{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;line-height:1.45;min-height:2.8em}
.re9-product-category{display:inline-flex;max-width:65%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-radius:999px;background:#fff1e4;color:#8a420d;padding:.3rem .62rem;font-size:10px;font-weight:900;letter-spacing:.04em;text-transform:uppercase}
.re9-product-price{white-space:nowrap;letter-spacing:-.035em}
.re9-product-buy{display:flex;width:100%;min-height:44px;align-items:center;justify-content:center;gap:.5rem;border-radius:.78rem;padding:.68rem .8rem;font-size:13px;font-weight:950;letter-spacing:.01em}
@media(min-width:640px){.re9-products-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:1.1rem}.re9-product-media{aspect-ratio:4/3}}
@media(min-width:1024px){.re9-products-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:1.25rem}}
@media(min-width:1280px){.re9-products-grid{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media(max-width:639px){
 body{background:#f5f7fa;font-size:16.5px}
 header .re9-store-header-inner{display:flex;flex-direction:column;align-items:stretch;gap:.9rem;padding:.85rem .9rem}
 .re9-store-nav{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));width:100%;gap:.5rem}
 .re9-store-nav a{width:100%;min-width:0;min-height:46px;padding:.55rem .35rem;font-size:12px;border-radius:.75rem}
 main.mx-auto{padding:1rem .65rem}
 .re9-store-hero{border-radius:1rem;padding:1.2rem}
 .re9-store-hero h1{font-size:1.5rem;line-height:1.18}
 .re9-store-trust{gap:.4rem}
 .re9-store-trust span{font-size:10px;padding:.42rem .55rem}
 .re9-products-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:.65rem}
 .re9-product-card{border-radius:.9rem}
 .re9-product-media{aspect-ratio:1/1}
 .re9-product-info{padding:.62rem}
 .re9-product-info h2{font-size:13px;line-height:1.28;margin-top:.45rem;min-height:2.55em}
 .re9-product-info .re9-product-description{font-size:10.5px;line-height:1.35;margin-top:.3rem;min-height:2.7em}
 .re9-product-category{font-size:9px;padding:.22rem .45rem;max-width:100%}
 .re9-product-info .re9-seller{display:none}
 .re9-product-price{font-size:14px!important}
 .re9-product-buy{min-height:39px;padding:.5rem .3rem;font-size:10.5px;gap:.35rem}
}
/* Cartazes da loja: preservar a arte inteira e fazer o card acompanhar sua proporção. */
.re9-product-media{aspect-ratio:auto!important;height:auto!important;min-height:0;overflow:hidden;background:#fff;}
.re9-product-media > img.re9-product-image{display:block!important;width:100%!important;height:auto!important;max-width:100%!important;max-height:none!important;aspect-ratio:auto!important;object-fit:contain!important;object-position:center center!important;margin:0!important;padding:0!important;background:#fff!important;}
.re9-product-media > div.re9-product-image{width:100%;min-height:210px;aspect-ratio:4/3;height:auto;}

        #re9TimePicker { z-index: 12000 !important; box-sizing: border-box; }
        #re9TimePicker > div { box-sizing: border-box; }
        #re9TimePicker .grid { min-width: 0; }
        .re9-time-field { display:block; width:100%; min-width:0; max-width:100%; box-sizing:border-box; cursor:pointer; background-color:#fff; }
        body.re9-timepicker-open { overflow:hidden !important; }
    </style>
</head>
<body class="min-h-screen bg-slate-100 text-slate-800">
<header class="re9-navy text-white shadow-lg">
 <div class="re9-store-header-inner px-4 py-4">
  <a href="<?php echo htmlspecialchars($store_file, ENT_QUOTES, 'UTF-8'); ?>?loja=1" class="flex items-center gap-3"><span class="flex h-11 w-11 items-center justify-center rounded-xl bg-white/10 text-2xl re9-orange"><i class="fa-solid fa-store"></i></span><span><strong class="block text-lg font-black">RE9 <span class="re9-orange">LOJA</span></strong><small class="text-xs text-slate-300">Central de Vendas Inteligente</small></span></a>
  <nav aria-label="Navegação da Loja RE9" class="re9-store-nav flex flex-wrap items-center gap-2 text-xs sm:text-sm">
   <a href="<?php echo htmlspecialchars($store_file, ENT_QUOTES, 'UTF-8'); ?>?loja=1" class="re9-store-home"><i class="fa-solid fa-grid-2"></i>Produtos</a>
   <?php if ($store_logged): ?><a href="<?php echo htmlspecialchars($store_file, ENT_QUOTES, 'UTF-8'); ?>?loja=pedidos"><i class="fa-solid fa-box-open"></i>Meus pedidos</a><a href="<?php echo htmlspecialchars($store_file, ENT_QUOTES, 'UTF-8'); ?>?chat_with=<?php echo rawurlencode($store_me); ?>"><i class="fa-regular fa-comments"></i>Chat</a><?php endif; ?>
   <a href="<?php echo htmlspecialchars($store_file, ENT_QUOTES, 'UTF-8'); ?>" class="re9-store-webmail"><i class="fa-solid fa-envelope"></i>Voltar ao Webmail</a>
  </nav>
 </div>
</header>
<main class="mx-auto max-w-7xl px-4 py-7">
<?php if ($store_mode === 'pedidos'): ?>
 <div class="mb-6 flex flex-wrap items-end justify-between gap-3"><div><p class="text-xs font-extrabold uppercase tracking-widest text-orange-700">Painel de vendas</p><h1 class="mt-1 text-2xl font-black text-[#002244]">Central de pedidos</h1><p class="mt-1 text-sm text-slate-500">Comprador e anunciante acompanham o andamento pelo chat privado da plataforma.</p></div><span class="rounded-full bg-white px-3 py-2 text-xs font-bold text-slate-600 shadow-sm"><?php echo htmlspecialchars($store_me, ENT_QUOTES, 'UTF-8'); ?></span></div>
 <div id="shopOrders" class="space-y-3"><div class="rounded-xl bg-white p-6 text-center text-sm text-slate-500">Carregando pedidos...</div></div>
 <div class="mt-6 rounded-xl border border-blue-200 bg-blue-50 p-4 text-xs leading-relaxed text-blue-900"><strong>Fluxo:</strong> novo pedido entra como aguardando confirmação de pagamento. O anunciante ou administrador confirma o pagamento e atualiza a etapa correta: produção, entrega, envio ou liberação digital. Cada atualização gera uma mensagem no chat privado do comprador.</div>
<?php elseif ($store_mode === 'checkout' && is_array($store_product)): ?>
 <div class="mb-5"><a href="<?php echo htmlspecialchars($store_file, ENT_QUOTES, 'UTF-8'); ?>?loja=1" class="text-sm font-bold text-blue-700 hover:underline"><i class="fa-solid fa-arrow-left mr-1"></i>Voltar aos produtos</a></div>
 <div class="grid gap-6 lg:grid-cols-[minmax(0,1fr)_minmax(360px,.9fr)]">
  <section class="overflow-hidden rounded-2xl bg-white re9-card">
   <?php if (!empty($store_product['image'])): ?><img src="<?php echo htmlspecialchars(re9_public_image_url($store_product['image']), ENT_QUOTES, 'UTF-8'); ?>" referrerpolicy="strict-origin-when-cross-origin" alt="<?php echo htmlspecialchars(agenda_value($store_product, 'title', 'Produto'), ENT_QUOTES, 'UTF-8'); ?>" class="max-h-80 w-full bg-slate-50 object-contain"><?php else: ?><div class="flex h-52 items-center justify-center bg-gradient-to-br from-[#002244] to-[#174a7a] text-6xl text-orange-300"><i class="fa-solid fa-bag-shopping"></i></div><?php endif; ?>
   <div class="p-6"><span class="rounded-full bg-orange-100 px-3 py-1 text-[11px] font-extrabold uppercase text-orange-800"><?php echo htmlspecialchars(agenda_value($store_product, 'category', 'Geral'), ENT_QUOTES, 'UTF-8'); ?></span><h1 class="mt-3 text-2xl font-black text-[#002244]"><?php echo htmlspecialchars(agenda_value($store_product, 'title', 'Produto'), ENT_QUOTES, 'UTF-8'); ?></h1><p class="mt-3 whitespace-pre-line text-sm leading-relaxed text-slate-600"><?php echo htmlspecialchars(agenda_value($store_product, 'description', ''), ENT_QUOTES, 'UTF-8'); ?></p><div class="mt-5 text-3xl font-black text-emerald-700"><?php echo !empty($store_product['price_pending']) ? 'Preço não cadastrado' : $money(agenda_value($store_product, 'price', 0)); ?></div><p class="mt-2 text-xs text-slate-500">Anunciante: <?php echo htmlspecialchars(agenda_value($store_product, 'sender', ''), ENT_QUOTES, 'UTF-8'); ?></p><p class="mt-1 text-xs text-slate-500">Modalidade: <?php echo htmlspecialchars(isset($fulfillment_labels[agenda_value($store_product, 'fulfillment', 'digital')]) ? $fulfillment_labels[agenda_value($store_product, 'fulfillment', 'digital')] : 'Entrega a combinar', ENT_QUOTES, 'UTF-8'); ?></p></div>
  </section>
  <section class="rounded-2xl bg-white p-5 re9-card sm:p-6">
   <div class="mb-4"><p class="text-xs font-extrabold uppercase tracking-widest text-orange-700">Checkout seguro RE9</p><h2 class="mt-1 text-xl font-black text-[#002244]">Finalizar pedido</h2><p class="mt-1 text-xs text-slate-500">Sua conta corporativa será usada para manter o atendimento no chat.</p></div>
   <form id="shopCheckoutForm" class="space-y-3">
    <input type="hidden" name="csrf" value="<?php echo htmlspecialchars($store_csrf, ENT_QUOTES, 'UTF-8'); ?>"><input type="hidden" name="product_id" value="<?php echo htmlspecialchars(agenda_value($store_product, 'id', ''), ENT_QUOTES, 'UTF-8'); ?>">
    <div class="rounded-lg bg-slate-50 p-3 text-xs"><strong>Conta conectada:</strong> <?php echo htmlspecialchars($store_me, ENT_QUOTES, 'UTF-8'); ?></div>
    <label class="block text-xs font-bold text-slate-700">Nome completo<input required maxlength="160" name="buyer_name" value="<?php echo htmlspecialchars($store_name, ENT_QUOTES, 'UTF-8'); ?>" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-sm"></label>
    <label class="block text-xs font-bold text-slate-700">Telefone / WhatsApp<input required maxlength="40" name="buyer_phone" type="tel" placeholder="DDD + número" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-sm"></label>
    <label class="block text-xs font-bold text-slate-700">Quantidade<input required type="number" min="1" max="99" name="quantity" value="1" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-sm"></label>
    <?php if (in_array(agenda_value($store_product, 'fulfillment', 'digital'), array('physical','made_to_order'), true)): ?><label class="block text-xs font-bold text-slate-700">Endereço para entrega / envio<textarea required maxlength="500" rows="3" name="shipping_address" placeholder="Rua, número, complemento, bairro, cidade e CEP" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-sm"></textarea></label><?php else: ?><label class="block text-xs font-bold text-slate-700">Endereço (opcional, se necessário)<textarea maxlength="500" rows="2" name="shipping_address" placeholder="Informe apenas se for necessário para o atendimento" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-sm"></textarea></label><?php endif; ?>
    <label class="block text-xs font-bold text-slate-700">Observações para o anunciante<textarea maxlength="1200" rows="3" name="buyer_notes" placeholder="Detalhes do pedido, preferências ou informações adicionais" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-sm"></textarea></label>
    <div class="rounded-xl border border-amber-200 bg-amber-50 p-3 text-xs leading-relaxed text-amber-900"><strong>Importante:</strong> <?php if (!empty($store_product['price_pending'])): ?>este anúncio ainda não tem preço cadastrado. Ao finalizar, você enviará uma solicitação de compra; o anunciante combinará o valor e a forma de pagamento pelo chat RE9.<?php else: ?>ao finalizar, o pedido será registrado como <strong>Aguardando confirmação de pagamento</strong>. Este checkout ainda não cobra automaticamente no cartão ou Pix. A equipe e o anunciante orientarão a confirmação e a entrega pelo chat RE9.<?php endif; ?></div>
    <button id="shopSubmitOrder" type="submit" class="re9-btn w-full rounded-xl px-4 py-3.5 text-sm font-extrabold shadow"><i class="fa-solid fa-check mr-2"></i>Concluir pedido</button><p id="shopCheckoutFeedback" class="text-xs" aria-live="polite"></p>
   </form>
  </section>
 </div>
<?php else: ?>
 <section class="re9-store-hero mb-6"><div class="relative z-10 max-w-3xl"><p class="text-[11px] font-black uppercase tracking-[.2em] text-orange-300"><i class="fa-solid fa-bag-shopping mr-1.5"></i>Vitrine corporativa RE9</p><h1 class="mt-2 text-2xl font-black sm:text-3xl">Produtos que valem a sua escolha</h1><p class="mt-2 max-w-2xl text-sm leading-relaxed text-slate-200">Descubra ofertas, compare opções e fale diretamente com o anunciante. Escolha seu produto e avance para um pedido acompanhado pela plataforma.</p><div class="re9-store-trust"><span><i class="fa-solid fa-shield-halved text-orange-300"></i> Pedido acompanhado</span><span><i class="fa-solid fa-comments text-orange-300"></i> Atendimento pelo chat</span><span><i class="fa-solid fa-store text-orange-300"></i> Anúncios da plataforma</span></div></div></section>
 <?php if (empty($store_products)): ?><div class="rounded-2xl border border-dashed border-slate-300 bg-white p-10 text-center"><i class="fa-solid fa-store text-4xl text-slate-300"></i><h2 class="mt-3 font-extrabold text-[#002244]">A loja está sendo preparada</h2><p class="mt-1 text-sm text-slate-500">Ainda não há anúncios ativos cadastrados no banco de cartazes da Administração.</p></div><?php else: ?>
 <div class="re9-products-grid">
 <?php foreach ($store_products as $product): ?>
  <article class="re9-product-card re9-card">
   <div class="re9-product-media">
    <?php if (!empty($product['image'])): ?><img src="<?php echo htmlspecialchars(re9_public_image_url($product['image']), ENT_QUOTES, 'UTF-8'); ?>" referrerpolicy="strict-origin-when-cross-origin" alt="<?php echo htmlspecialchars(agenda_value($product, 'title', 'Produto'), ENT_QUOTES, 'UTF-8'); ?>" class="re9-product-image" loading="lazy"><?php else: ?><div class="re9-product-image flex items-center justify-center bg-gradient-to-br from-[#002244] to-[#174a7a] text-5xl text-orange-300"><i class="fa-solid fa-bag-shopping"></i></div><?php endif; ?>
   </div>
   <div class="re9-product-info">
    <div class="flex min-w-0 items-center justify-between gap-2"><span class="re9-product-category"><?php echo htmlspecialchars(agenda_value($product, 'category', 'Geral'), ENT_QUOTES, 'UTF-8'); ?></span><span class="re9-seller truncate text-[10px] font-semibold text-slate-400"><?php echo htmlspecialchars(agenda_value($product, 'sender', ''), ENT_QUOTES, 'UTF-8'); ?></span></div>
    <h2 class="mt-2 line-clamp-2 text-[15px] font-extrabold leading-snug text-[#002244]"><?php echo htmlspecialchars(agenda_value($product, 'title', 'Produto'), ENT_QUOTES, 'UTF-8'); ?></h2>
    <p class="re9-product-description mt-1.5 text-xs text-slate-600"><?php echo htmlspecialchars(agenda_value($product, 'description', ''), ENT_QUOTES, 'UTF-8'); ?></p>
    <div class="mt-auto pt-3"><div class="mb-2 flex min-w-0 items-center justify-between gap-1"><span class="text-[9px] font-bold uppercase tracking-wide text-slate-400">Preço</span><strong class="re9-product-price text-lg font-black text-emerald-700"><?php echo !empty($product['price_pending']) ? 'A combinar' : $money(agenda_value($product, 'price', 0)); ?></strong></div><a href="<?php echo htmlspecialchars(sales_product_url(agenda_value($product, 'id', '')), ENT_QUOTES, 'UTF-8'); ?>" class="re9-btn re9-product-buy"><i class="fa-solid fa-cart-shopping"></i><span>Comprar agora</span><i class="fa-solid fa-arrow-right text-[10px]"></i></a></div>
   </div>
  </article>
 <?php endforeach; ?>
 </div><?php endif; ?>
<?php endif; ?>
</main>
<footer class="mt-10 border-t border-slate-200 bg-white px-4 py-5 text-center text-xs text-slate-500">Loja RE9 • Atendimento, pedido e acompanhamento pelo chat privado da plataforma.</footer>
<script>
(function(){
 var csrf=<?php echo json_encode($store_csrf); ?>;
 var form=document.getElementById('shopCheckoutForm');
 if(form){form.addEventListener('submit',async function(ev){ev.preventDefault();var btn=document.getElementById('shopSubmitOrder');var feedback=document.getElementById('shopCheckoutFeedback');btn.disabled=true;btn.innerHTML='<i class="fa-solid fa-spinner fa-spin mr-2"></i>Registrando pedido...';feedback.textContent='';try{var response=await fetch('?api=shop_place_order',{method:'POST',body:new FormData(form),credentials:'same-origin'});var data=await response.json();if(data.status!=='ok')throw new Error(data.msg||'Não foi possível registrar o pedido.');feedback.className='rounded-lg border border-emerald-200 bg-emerald-50 p-3 text-sm text-emerald-800';feedback.innerHTML='<strong>Pedido '+String(data.order_id).replace(/[&<>"']/g,'')+' registrado!</strong><br>Status: Aguardando confirmação de pagamento.<br><a class="mt-2 inline-block font-bold text-blue-700 underline" href="<?php echo htmlspecialchars($store_file, ENT_QUOTES, 'UTF-8'); ?>?loja=pedidos">Acompanhar meu pedido</a><br><a class="mt-1 inline-block font-bold text-blue-700 underline" href="<?php echo htmlspecialchars($store_file, ENT_QUOTES, 'UTF-8'); ?>?chat_with='+encodeURIComponent(data.seller_email)+'">Abrir chat com o anunciante</a>';}catch(err){feedback.className='text-sm font-semibold text-red-700';feedback.textContent=err.message||'Erro ao registrar pedido.';}finally{btn.disabled=false;btn.innerHTML='<i class="fa-solid fa-check mr-2"></i>Concluir pedido';}});}
 var orderBox=document.getElementById('shopOrders');
 if(orderBox){
  function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c];});}
  var statusLabels={awaiting_payment_confirmation:'Aguardando confirmação de pagamento',payment_confirmed:'Pagamento confirmado',in_production:'Em produção / preparação',ready_for_delivery:'Pronto para entrega',dispatched:'Enviado / em transporte',product_released:'Produto liberado',completed:'Concluído',cancelled:'Cancelado'};
  var statusOptions=['awaiting_payment_confirmation','payment_confirmed','in_production','ready_for_delivery','dispatched','product_released','completed','cancelled'];
  function money(v){return 'R$ '+Number(v||0).toFixed(2).replace('.',',');}
  function render(items,me){if(!items.length){orderBox.innerHTML='<div class="rounded-xl border border-dashed border-slate-300 bg-white p-8 text-center text-sm text-slate-500">Nenhum pedido encontrado para esta conta.</div>';return;}orderBox.innerHTML=items.map(function(o){var isSeller=String(o.seller_email||'').toLowerCase()===String(me||'').toLowerCase();var peer=isSeller?o.buyer_email:o.seller_email;var peerName=isSeller?o.buyer_name:o.seller_name;var statusOptionsHtml=statusOptions.map(function(st){return '<option value="'+st+'" '+(o.status===st?'selected':'')+'>'+statusLabels[st]+'</option>';}).join('');var chatPeer=isSeller?o.buyer_email:((o.updated_by&&String(o.updated_by).toLowerCase()!==String(o.seller_email||'').toLowerCase())?o.updated_by:o.seller_email);var chatPeerName=isSeller?o.buyer_name:((chatPeer===o.seller_email)?o.seller_name:'Equipe RE9');var controls=o.can_manage?'<div class="mt-4 grid gap-2 sm:grid-cols-[1fr_1fr_auto]"><select data-status class="rounded-lg border border-slate-300 p-2 text-xs">'+statusOptionsHtml+'</select><input data-delivery-link value="'+esc(o.delivery_link||'')+'" placeholder="Link de liberação / rastreio (opcional)" class="rounded-lg border border-slate-300 p-2 text-xs"><button data-update-order="'+esc(o.id)+'" class="rounded-lg bg-[#002244] px-4 py-2 text-xs font-bold text-white">Atualizar pedido</button></div><input data-delivery-info class="mt-2 w-full rounded-lg border border-slate-300 p-2 text-xs" placeholder="Orientação de produção, entrega ou atendimento" value="'+esc(o.delivery_info||'')+'">':'';var emailState='<p class="mt-2 text-[11px] '+(o.support_email_sent?'text-emerald-700':'text-amber-700')+'"><i class="fa-regular fa-envelope mr-1"></i>'+(o.support_email_sent?'Aviso enviado ao suporte@renove.rio.br':'Aviso de e-mail ao suporte não confirmado pelo servidor')+'</p>';var resend=(o.is_admin&&!o.support_email_sent)?'<button data-resend-email="'+esc(o.id)+'" class="rounded-lg border border-amber-300 bg-amber-50 px-3 py-2 text-xs font-bold text-amber-900">Reenviar aviso ao suporte</button>':'';return '<article class="rounded-2xl border border-slate-200 bg-white p-4 shadow-sm"><div class="flex flex-wrap items-start justify-between gap-3"><div><p class="text-[10px] font-extrabold uppercase tracking-widest text-slate-400">'+esc(o.id)+' • '+esc(new Date(Number(o.created_at||0)*1000).toLocaleString('pt-BR'))+'</p><h3 class="mt-1 text-base font-extrabold text-[#002244]">'+esc(o.product_title)+'</h3><p class="mt-1 text-xs text-slate-500">'+esc(o.category)+' • '+esc(o.fulfillment_label)+' • Quantidade: '+esc(o.quantity)+'</p></div><span class="rounded-full bg-amber-100 px-3 py-1.5 text-[11px] font-extrabold text-amber-900">'+esc(o.status_label||statusLabels[o.status]||o.status)+'</span></div><div class="mt-3 grid gap-2 text-xs sm:grid-cols-2"><p><strong>Comprador:</strong> '+esc(o.buyer_name)+' ('+esc(o.buyer_email)+')</p><p><strong>Anunciante:</strong> '+esc(o.seller_name)+' ('+esc(o.seller_email)+')</p><p><strong>Telefone:</strong> '+esc(o.buyer_phone)+'</p><p><strong>Total:</strong> <span class="font-extrabold text-emerald-700">'+(o.price_pending?'A combinar':money(o.total))+'</span></p><p class="sm:col-span-2"><strong>Entrega:</strong> '+esc(o.shipping_address||'A combinar / digital')+'</p><p class="sm:col-span-2"><strong>Observações:</strong> '+esc(o.buyer_notes||'Nenhuma')+'</p></div>'+emailState+'<div class="mt-3 flex flex-wrap gap-2"><a href="?chat_with='+encodeURIComponent(chatPeer)+'" class="rounded-lg border border-blue-200 bg-blue-50 px-3 py-2 text-xs font-bold text-blue-800"><i class="fa-regular fa-comments mr-1"></i>Conversar com '+esc(chatPeerName||chatPeer)+'</a>'+resend+'</div>'+controls+'</article>';}).join('');}
  async function load(){try{var r=await fetch('?api=shop_orders_list',{credentials:'same-origin',cache:'no-store'});var d=await r.json();if(d.status!=='ok')throw new Error(d.msg||'Não foi possível carregar pedidos.');render(d.orders||[],d.me||'');}catch(e){orderBox.innerHTML='<div class="rounded-xl border border-red-200 bg-white p-5 text-sm text-red-700">'+esc(e.message)+'</div>';}}
  orderBox.addEventListener('click',async function(ev){var resend=ev.target.closest('button[data-resend-email]');if(resend){if(!confirm('Deseja reenviar o aviso deste pedido para suporte@renove.rio.br?'))return;var resendFd=new FormData();resendFd.append('csrf',csrf);resendFd.append('order_id',resend.getAttribute('data-resend-email'));resend.disabled=true;resend.textContent='Enviando...';try{var mailResponse=await fetch('?api=shop_resend_support_email',{method:'POST',body:resendFd,credentials:'same-origin'});var mailData=await mailResponse.json();if(mailData.status!=='ok')throw new Error(mailData.msg||'Não foi possível reenviar.');await load();}catch(mailError){alert(mailError.message);}finally{resend.disabled=false;}return;}var btn=ev.target.closest('button[data-update-order]');if(!btn)return;var card=btn.closest('article');var fd=new FormData();fd.append('csrf',csrf);fd.append('order_id',btn.getAttribute('data-update-order'));fd.append('status',card.querySelector('[data-status]').value);fd.append('delivery_link',card.querySelector('[data-delivery-link]').value);fd.append('delivery_info',card.querySelector('[data-delivery-info]').value);btn.disabled=true;btn.textContent='Atualizando...';try{var r=await fetch('?api=shop_order_update',{method:'POST',body:fd,credentials:'same-origin'});var d=await r.json();if(d.status!=='ok')throw new Error(d.msg||'Falha ao atualizar.');await load();}catch(e){alert(e.message);}finally{btn.disabled=false;}});
  load();
 }
})();
</script>
</body></html><?php exit;
}


// Gate obrigatório de confirmação única para contas RE9 já existentes.
if (!empty($_SESSION['wm_email']) && re9_identity_gate_required($_SESSION['wm_email'])) {
    $verify_csrf = (string)get_val($_SESSION,'re9_private_csrf','');
    $verify_email = strtolower(trim((string)$_SESSION['wm_email']));
    $verify_domain = strtolower(trim((string)get_val($APP_CONFIG,'domain_name','re9.rio.br')));
    $verify_return_url = !empty($_SESSION['re9_shop_return']) ? (string)$_SESSION['re9_shop_return'] : (isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : './');
    unset($_SESSION['re9_shop_return']);
    ?><!DOCTYPE html>
    <html lang="pt-BR"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Confirmar conta RE9</title><script src="https://cdn.tailwindcss.com"></script></head>
    <body class="min-h-screen bg-slate-100 flex items-center justify-center p-4"><main class="w-full max-w-xl rounded-2xl bg-white p-6 shadow-xl border-t-4 border-orange-500">
      <div class="text-center"><div class="mx-auto flex h-14 w-14 items-center justify-center rounded-2xl bg-blue-50 text-2xl text-blue-900">✉</div><h1 class="mt-3 text-2xl font-extrabold text-slate-900">Envie seus dados para análise RE9</h1><p class="mt-2 text-sm text-slate-600">Estamos atualizando a segurança das contas existentes. Para visualizar sua caixa enquanto a equipe confere seus dados, informe nome, CPF e telefone da conta <strong><?php echo htmlspecialchars($verify_email,ENT_QUOTES,'UTF-8'); ?></strong>.</p></div>
      <form id="legacyIdentityForm" class="mt-6 space-y-4">
       <label class="block text-sm font-bold text-slate-700">Nome completo<input id="legacyFullName" required maxlength="100" autocomplete="name" class="mt-1 w-full rounded-xl border border-slate-300 p-3" placeholder="Nome conforme cadastro oficial"></label>
       <label class="block text-sm font-bold text-slate-700">CPF<input id="legacyCpf" required inputmode="numeric" maxlength="14" autocomplete="off" class="mt-1 w-full rounded-xl border border-slate-300 p-3" placeholder="000.000.000-00"></label>
       <label class="block text-sm font-bold text-slate-700">Telefone / WhatsApp com DDD<input id="legacyPhone" required inputmode="tel" maxlength="20" autocomplete="tel" class="mt-1 w-full rounded-xl border border-slate-300 p-3" placeholder="(21) 99999-9999"></label>
       <label class="flex items-start gap-2 text-xs leading-relaxed text-slate-600"><input id="legacyConsent" type="checkbox" class="mt-0.5" required><span>Autorizo o uso destes dados para a conferência manual da conta RE9. Entendo que a validade matemática do CPF não comprova titularidade e que o telefone será conferido pela equipe.</span></label>
       <div id="legacyCodeArea" class="hidden"><label class="block text-sm font-bold text-slate-700">Código recebido no telefone<input id="legacyCode" inputmode="numeric" maxlength="6" autocomplete="one-time-code" class="mt-1 w-full rounded-xl border border-slate-300 p-3 text-center text-xl tracking-[.4em]" placeholder="000000"></label></div>
       <p id="legacyFeedback" class="hidden rounded-lg p-3 text-sm" aria-live="polite"></p>
       <button id="legacyStartBtn" type="submit" class="w-full rounded-xl bg-[#002244] px-4 py-3 font-extrabold text-white">Enviar para análise manual</button>
       <button id="legacyConfirmBtn" type="button" class="hidden w-full rounded-xl bg-emerald-700 px-4 py-3 font-extrabold text-white">Confirmar código e liberar Webmail</button>
      </form>
      <p class="mt-5 text-center text-xs text-slate-500">Domínio das contas RE9: @<?php echo htmlspecialchars($verify_domain,ENT_QUOTES,'UTF-8'); ?>. Se não reconhecer esta solicitação, saia e contate o suporte.</p>
      <form method="post" action="?api=logout" class="mt-3 text-center"><button type="button" id="legacyLogout" class="text-sm font-semibold text-slate-500 underline">Sair da conta</button></form>
    </main><script>
    (function(){var csrf=<?php echo json_encode($verify_csrf); ?>;var form=document.getElementById('legacyIdentityForm');var feedback=document.getElementById('legacyFeedback');var start=document.getElementById('legacyStartBtn');var confirmBtn=document.getElementById('legacyConfirmBtn');var codeArea=document.getElementById('legacyCodeArea');var pending=false;
    function show(msg,ok){feedback.textContent=msg;feedback.className='rounded-lg p-3 text-sm '+(ok?'bg-emerald-50 text-emerald-800':'bg-red-50 text-red-700');}
    form.addEventListener('submit',async function(e){e.preventDefault();start.disabled=true;start.textContent='Conferindo CPF e enviando para análise...';var fd=new FormData();fd.append('csrf',csrf);fd.append('full_name',document.getElementById('legacyFullName').value);fd.append('cpf',document.getElementById('legacyCpf').value);fd.append('phone',document.getElementById('legacyPhone').value);fd.append('identity_consent',document.getElementById('legacyConsent').checked?'1':'0');try{var r=await fetch('?api=legacy_identity_start',{method:'POST',body:fd,credentials:'same-origin',cache:'no-store'});var d=await r.json();if(d.status!=='ok')throw new Error(d.msg||'Não foi possível validar os dados.');show(d.msg,true);setTimeout(function(){window.location.reload();},900);}catch(err){show(err.message,false);start.disabled=false;start.textContent='Enviar para análise manual';}});
    confirmBtn.addEventListener('click',async function(){var fd=new FormData();fd.append('csrf',csrf);fd.append('code',document.getElementById('legacyCode').value);confirmBtn.disabled=true;confirmBtn.textContent='Confirmando...';try{var r=await fetch('?api=legacy_identity_confirm',{method:'POST',body:fd,credentials:'same-origin',cache:'no-store'});var d=await r.json();if(d.status!=='ok')throw new Error(d.msg||'Código não confirmado.');show(d.msg,true);window.location.href=<?php echo json_encode($verify_return_url); ?>;}catch(err){show(err.message,false);confirmBtn.disabled=false;confirmBtn.textContent='Confirmar código e liberar Webmail';}});
    document.getElementById('legacyLogout').addEventListener('click',async function(){try{await fetch('?api=logout',{method:'POST',credentials:'same-origin'});}catch(e){}window.location.href=<?php echo json_encode(isset($_SERVER['SCRIPT_NAME'])?$_SERVER['SCRIPT_NAME']:'./'); ?>;});
    var cpf=document.getElementById('legacyCpf');cpf.addEventListener('input',function(){var d=this.value.replace(/\D/g,'').slice(0,11);if(d.length>9)this.value=d.replace(/(\d{3})(\d{3})(\d{3})(\d{1,2})/,'$1.$2.$3-$4');else if(d.length>6)this.value=d.replace(/(\d{3})(\d{3})(\d{1,3})/,'$1.$2.$3');else if(d.length>3)this.value=d.replace(/(\d{3})(\d{1,3})/,'$1.$2');else this.value=d;});})();
    </script></body></html><?php
    exit;
}

// Link de recuperação deve abrir a tela pública mesmo se o navegador tiver outra sessão ativa.
if (isset($_GET['reset_password']) && !empty($_SESSION['wm_email'])) {
    remove_user_online_status($_SESSION['wm_email']);
    unset($_SESSION['wm_email'], $_SESSION['wm_pass'], $_SESSION['wm_cipher_key'], $_SESSION['wm_is_admin']);
}
$is_logged = !empty($_SESSION['wm_email']);
$is_admin  = is_user_admin();
$user_sig  = $is_logged ? get_user_signature($_SESSION['wm_email']) : '';

// Nome para identificação no cabeçalho: prioriza o nome informado no cadastro,
// depois a identidade validada e, por último, deriva uma forma legível do e-mail.
$logged_user_display_name = '';
$logged_user_first_name = '';
if ($is_logged) {
    $logged_user_email_key = strtolower(trim((string)$_SESSION['wm_email']));

    $header_public_names = load_protected_json($DIRECTORY_NAMES_FILE);
    if (is_array($header_public_names) && isset($header_public_names[$logged_user_email_key])) {
        $logged_user_display_name = trim(strip_tags((string)$header_public_names[$logged_user_email_key]));
    }

    if ($logged_user_display_name === '') {
        $header_identity_records = load_protected_json($IDENTITY_FILE);
        if (is_array($header_identity_records)
            && isset($header_identity_records[$logged_user_email_key])
            && is_array($header_identity_records[$logged_user_email_key])
            && !empty($header_identity_records[$logged_user_email_key]['name'])) {
            $logged_user_display_name = trim(strip_tags((string)$header_identity_records[$logged_user_email_key]['name']));
        }
    }

    if ($logged_user_display_name === '') {
        $logged_user_part = strstr($logged_user_email_key, '@', true);
        if ($logged_user_part === false || $logged_user_part === '') $logged_user_part = $logged_user_email_key;
        $logged_user_display_name = ucwords(str_replace(array('.', '_', '-'), ' ', $logged_user_part));
    }

    $logged_user_name_parts = preg_split('/\s+/u', trim($logged_user_display_name));
    $logged_user_first_name = (is_array($logged_user_name_parts) && !empty($logged_user_name_parts[0]))
        ? $logged_user_name_parts[0]
        : $logged_user_display_name;
}

$logo_src = !empty($APP_CONFIG['brand_logo'])
    ? re9_public_image_url($APP_CONFIG['brand_logo'])
    : ((isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '/index.php') . '?pwa=logo_horizontal');

$random_initial_ad = $APP_CONFIG['ads_pool'][array_rand($APP_CONFIG['ads_pool'])];
if (is_array($random_initial_ad) && !empty($random_initial_ad['image'])) { $random_initial_ad['image'] = re9_public_image_url($random_initial_ad['image']); }

$protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') ? "https" : "http";
$base_path = strtok($_SERVER['REQUEST_URI'], '?');
$current_url = $protocol . "://" . $_SERVER['HTTP_HOST'] . $base_path;
$app_icon_url = $current_url . '?pwa=icon';
$wa_url_val = get_val($APP_CONFIG, 'whatsapp_api_url');
$wa_tok_val = get_val($APP_CONFIG, 'whatsapp_api_token');
$initial_vps_data = $is_admin ? get_strictly_connected_webmail_users() : array('server_ip' => '162.240.100.87', 'online_count' => 0, 'users' => array());

$user_ext_accounts_public = array();
if ($is_logged) {
    $raw_ext = get_user_external_accounts($_SESSION['wm_email']);
    foreach ($raw_ext['accounts'] as $acc) {
        $user_ext_accounts_public[] = array(
            'email'     => $acc['email'],
            'host'      => $acc['host'],
            'port'      => $acc['port'],
            'last_sync' => $acc['last_sync']
        );
    }
}
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title id="pageTitle"><?php echo htmlspecialchars($APP_CONFIG['brand_name']); ?></title>

    <link rel="manifest" href="?pwa=manifest">
    <meta name="theme-color" content="<?php echo htmlspecialchars($RE9_THEME_NAVY, ENT_QUOTES, 'UTF-8'); ?>">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="apple-mobile-web-app-title" content="RE9 EMAIL">
    <link rel="apple-touch-icon" href="?pwa=icon">
    <link rel="icon" type="image/svg+xml" href="?pwa=icon">

    <meta name="description" content="<?php echo htmlspecialchars($APP_CONFIG['brand_description']); ?>">
    <meta property="og:title" content="<?php echo htmlspecialchars($APP_CONFIG['brand_name']); ?>">
    <meta property="og:description" content="<?php echo htmlspecialchars($APP_CONFIG['brand_description']); ?>">
    <meta property="og:image" content="<?php echo htmlspecialchars($app_icon_url); ?>">
    <meta property="og:url" content="<?php echo htmlspecialchars($current_url); ?>">
    <meta property="og:type" content="website">

    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
    <style>
        :root {
            --color-navy: <?php echo htmlspecialchars($RE9_THEME_NAVY, ENT_QUOTES, 'UTF-8'); ?>;
            --color-navy-dark: <?php echo htmlspecialchars($RE9_THEME_NAVY_DARK, ENT_QUOTES, 'UTF-8'); ?>;
            --color-blood: <?php echo htmlspecialchars($RE9_THEME_BLOOD, ENT_QUOTES, 'UTF-8'); ?>;
            --color-blood-light: <?php echo htmlspecialchars($RE9_THEME_BLOOD_LIGHT, ENT_QUOTES, 'UTF-8'); ?>;
            --color-chrome: <?php echo htmlspecialchars($RE9_THEME_CHROME, ENT_QUOTES, 'UTF-8'); ?>;
            --color-chrome-hover: <?php echo htmlspecialchars($RE9_THEME_CHROME_HOVER, ENT_QUOTES, 'UTF-8'); ?>;
        }
        /* Substitui também as classes Tailwind com cores fixas usadas no layout antigo. */
        [class~="bg-[#002244]"] { background-color: var(--color-navy) !important; }
        [class~="text-[#002244]"] { color: var(--color-navy) !important; }
        [class~="border-[#002244]"] { border-color: var(--color-navy) !important; }
        [class~="bg-[#00152b]"] { background-color: var(--color-navy-dark) !important; }
        [class~="bg-[#990000]"] { background-color: var(--color-blood) !important; }
        [class~="text-[#990000]"] { color: var(--color-blood) !important; }
        [class~="border-[#990000]"] { border-color: var(--color-blood) !important; }
        [class~="bg-[#b30000]"] { background-color: var(--color-blood-light) !important; }
        [class~="bg-[#475569]"] { background-color: var(--color-chrome) !important; }
        [class~="text-[#475569]"] { color: var(--color-chrome) !important; }
        [class~="border-[#475569]"] { border-color: var(--color-chrome) !important; }
        [class~="hover:bg-[#00152b]"]:hover { background-color: var(--color-navy-dark) !important; }
        [class~="hover:bg-[#334155]"]:hover { background-color: var(--color-chrome-hover) !important; }
        [class~="hover:bg-[#b30000]"]:hover { background-color: var(--color-blood-light) !important; }
        [class~="hover:text-[#475569]"]:hover { color: var(--color-chrome) !important; }
        [class~="focus:border-[#475569]"]:focus { border-color: var(--color-chrome) !important; }
        [class~="from-[#00152b]"][class~="via-[#002244]"][class~="to-[#1e293b]"] {
            background-image: linear-gradient(to bottom right, var(--color-navy-dark), var(--color-navy), var(--color-chrome)) !important;
        }
        html, body {
            font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
            min-height: 100%;
            font-size: 16px;
        }
        /* Tipografia equilibrada: leitura padrão no desktop e confortável no celular. */
        body { line-height: 1.5; }
        input, select, textarea, button { font: inherit; }
        input, select, textarea { font-size: 15px !important; }
        label { font-size: 14px; line-height: 1.45; }
        button { line-height: 1.35; }
        @media (min-width: 768px) {
            label { font-size: 14px; }
        }
        .folder-btn { font-size: 14px; }
        [class~="text-[10px]"] { font-size: 10px !important; line-height: 1.35; }
        [class~="text-[11px]"] { font-size: 11px !important; line-height: 1.35; }
        [class~="text-[12px]"] { font-size: 12px !important; line-height: 1.4; }
        .bg-navy { background-color: var(--color-navy); }
        .bg-navy-dark { background-color: var(--color-navy-dark); }
        .bg-blood { background-color: var(--color-blood); }
        .bg-chrome { background-color: var(--color-chrome); }
        .text-navy { color: var(--color-navy); }
        .text-blood { color: var(--color-blood); }
        .text-chrome { color: var(--color-chrome); }
        .border-navy { border-color: var(--color-navy); }
        .border-blood { border-color: var(--color-blood); }
        .border-chrome { border-color: var(--color-chrome); }

        .btn-chrome {
            background-color: var(--color-chrome);
            color: #ffffff;
            font-weight: 700;
            transition: all 0.2s;
        }
        .btn-chrome:hover { background-color: var(--color-chrome-hover); transform: translateY(-1px); }

        .btn-blood {
            background-color: var(--color-blood);
            color: #ffffff;
            font-weight: 600;
        }
        .btn-blood:hover { background-color: var(--color-blood-light); }

        ::-webkit-scrollbar { width: 5px; height: 5px; }
        ::-webkit-scrollbar-thumb { background: #94a3b8; border-radius: 3px; }

        @keyframes pulse-blood {
            0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(153, 0, 0, 0.8); }
            50% { transform: scale(1.08); box-shadow: 0 0 0 7px rgba(153, 0, 0, 0); }
        }
        .unread-badge-pulse { animation: pulse-blood 1.6s infinite; }

        @media (max-width: 767px) {
            .mobile-email-sender { font-size: 15px !important; line-height: 1.4 !important; }
            .mobile-email-subject { font-size: 14px !important; line-height: 1.4 !important; }
            .mobile-email-date { font-size: 12px !important; }
            .mobile-touch-row { padding-top: 15px !important; padding-bottom: 15px !important; }
        }

        /* RENOVE MAIL: leitura ampliada, tipografia limpa e navegação mobile. */
        html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-padding-top: calc(var(--re9-header-height, 150px) + 18px); }
        body {
            font-family: Arial, Helvetica, sans-serif !important;
            font-size: 16px !important;
            line-height: 1.5 !important;
            font-style: normal !important;
            text-shadow: none !important;
        }
        body :not(i):not(svg):not(path):not(.fa):not([class*="fa-"]) {
            font-family: Arial, Helvetica, sans-serif !important;
            font-style: normal !important;
            text-shadow: none !important;
        }
        /* Mantém a hierarquia dos tamanhos compactos do Tailwind, sem ampliar metadados. */
        [class~="text-[10px]"] { font-size: 10px !important; line-height: 1.35 !important; }
        [class~="text-[11px]"] { font-size: 11px !important; line-height: 1.35 !important; }
        [class~="text-[12px]"] { font-size: 12px !important; line-height: 1.4 !important; }
        [class~="text-[13px]"] { font-size: 13px !important; line-height: 1.4 !important; }
        [class~="text-[14px]"] { font-size: 14px !important; line-height: 1.45 !important; }
        [class~="text-xs"] { font-size: 12px !important; line-height: 1.45 !important; }
        [class~="text-sm"] { font-size: 14px !important; line-height: 1.5 !important; }
        [class~="text-base"] { font-size: 16px !important; line-height: 1.5 !important; }
        [class~="text-lg"] { font-size: 18px !important; line-height: 1.4 !important; }
        #re9FixedTopBar {
            position: -webkit-sticky !important;
            position: sticky !important;
            top: 0 !important;
            z-index: 80 !important;
            width: 100%;
            flex-shrink: 0;
            isolation: isolate;
            box-shadow: 0 5px 18px rgba(0,0,0,.22);
        }
        #re9LiveDate, #re9LiveTime { font-size: 13px !important; line-height: 1.4 !important; }
        .re9-top-date-time {
            display: flex;
            flex-direction: column;
            justify-content: center;
            gap: 2px;
            flex: 0 1 auto;
            min-width: 0;
            max-width: 250px;
            padding-left: 10px;
            border-left: 1px solid rgba(255,255,255,.22);
            color: #e2e8f0;
            white-space: nowrap;
        }
        #re9FixedTopBar .re9-news-window { width: 100%; min-width: 0; }
        #re9FixedTopBar > div:nth-child(3) { width: 100%; flex: 1 0 100%; }
        #re9FixedTopBar > div:nth-child(3) > div { width: 100%; }
        .re9-top-date-time #re9LiveDate {
            display: block;
            max-width: 100%;
            overflow: hidden;
            text-overflow: ellipsis;
            font-size: 12px !important;
            line-height: 1.2 !important;
        }
        .re9-top-date-time #re9LiveTime {
            display: block;
            color: #fed7aa;
            font-size: 14px !important;
            line-height: 1.2 !important;
        }
        .re9-news-track { font-size: 14px !important; line-height: 1.45 !important; gap: 1.75rem !important; }
        button, [role="button"], input, select, textarea {
            font-family: Arial, Helvetica, sans-serif !important;
            font-size: 14px !important;
            line-height: 1.45 !important;
        }
        button, [role="button"] { font-weight: 700 !important; }
        input, select, textarea { min-height: 46px; }
        a { text-decoration-thickness: 1px; text-underline-offset: 3px; }
        @media (max-width: 767px) {
            html, body { min-width: 320px; width: 100%; }
            body { font-size: 16.5px !important; line-height: 1.55 !important; }
            #re9FixedTopBar { padding: 10px 12px !important; gap: 10px !important; }
            #re9FixedTopBar > div:first-child { min-width: 0; flex: 1 1 42%; }
            #re9FixedTopBar > div:nth-child(2) { flex: 0 1 auto; }
            #re9FixedTopBar button { min-height: 46px; min-width: 44px; padding: 10px 12px !important; }
            #re9FixedTopBar img { max-height: 38px; max-width: 100px !important; }
            #re9FixedTopBar > div:nth-child(3) { gap: 8px !important; padding-top: 9px !important; }
            .re9-top-date-time { max-width: 94px; padding-left: 7px; gap: 1px; }
            .re9-top-date-time #re9LiveDate { font-size: 10px !important; line-height: 1.15 !important; }
            .re9-top-date-time #re9LiveTime { font-size: 12px !important; line-height: 1.15 !important; }
            .re9-news-track { font-size: 14px !important; animation-duration: 110s !important; }
            .re9-news-window { min-height: 28px; display: flex; align-items: center; }
            .mobile-email-sender { font-size: 16.5px !important; }
            .mobile-email-subject { font-size: 15.5px !important; }
            .mobile-email-date { font-size: 12px !important; }
            .mobile-touch-row { min-height: 62px; padding: 15px 12px !important; }
            #folderSidebar { width: min(88vw, 360px) !important; padding: 16px !important; }
            #emailReaderSection { min-height: 0 !important; }
            main, section, article { max-width: 100%; }
            input, select, textarea { font-size: 16px !important; min-height: 48px; }
            button, [role="button"] { min-height: 44px; }
            img, video, iframe { max-width: 100%; }
        }
        /* RE9: acabamento visual dos anúncios, chamada de criação de conta e ações de e-mail. */
        .re9-inbox-ad-cta {
            min-width: 0 !important;
            width: auto !important;
            min-height: 0 !important;
            height: 26px !important;
            display: inline-flex !important;
            align-items: center !important;
            justify-content: center !important;
            padding: 3px 8px !important;
            border: 1px solid #f28c38 !important;
            border-radius: 5px !important;
            background: #ffffff !important;
            color: #a94f08 !important;
            font-size: 12px !important;
            line-height: 1 !important;
            letter-spacing: .01em !important;
            white-space: nowrap !important;
            box-shadow: none !important;
        }
        .re9-inbox-ad-sponsored,
        .re9-message-ad-sponsored {
            font-size: 12px !important;
            line-height: 1.25 !important;
            letter-spacing: .06em !important;
        }
        .re9-message-ad-text { font-size: 16.5px !important; line-height: 1.45 !important; }
        .re9-message-ad-buy {
            display: inline-flex !important;
            align-items: center !important;
            justify-content: center !important;
            gap: 4px !important;
            color: #a94f08 !important;
            background: #ffffff !important;
            border: 1px solid #f28c38 !important;
            border-radius: 5px !important;
            font-size: 12px !important;
            font-weight: 800 !important;
            line-height: 1 !important;
            min-height: 0 !important;
            height: 26px !important;
            padding: 3px 8px !important;
            box-shadow: none !important;
            text-decoration: none !important;
        }
        .re9-message-ad-buy i {
            color: #f28c38 !important;
            font-size: 10px !important;
        }
        .re9-create-mail-cta {
            width: 100% !important;
            min-height: 58px !important;
            padding: 14px 18px !important;
            border: 2px solid #f28c38 !important;
            font-size: 16px !important;
            line-height: 1.2 !important;
            font-weight: 900 !important;
            letter-spacing: .005em !important;
            box-shadow: 0 8px 20px rgba(3, 11, 156, .22), 0 0 0 2px rgba(242, 140, 56, .12) !important;
        }
        .re9-create-mail-copy { font-size: 16px !important; font-weight: 900 !important; white-space: nowrap; }
        .re9-create-mail-domain {
            display: inline-block;
            padding: 6px 9px;
            border: 1px solid rgba(255, 208, 138, .8);
            border-radius: 8px;
            background: rgba(242, 140, 56, .18);
            color: #ffd08a !important;
            font-size: 16.5px !important;
            font-weight: 900 !important;
            line-height: 1.15 !important;
            white-space: nowrap;
        }
        .re9-message-action-btn {
            width: 42px !important;
            height: 42px !important;
            min-width: 42px !important;
            min-height: 42px !important;
            padding: 0 !important;
            border-radius: 10px !important;
            vertical-align: middle !important;
        }
        .re9-message-action-icon {
            display: inline-block !important;
            width: auto !important;
            height: auto !important;
            min-width: 0 !important;
            font-family: "Font Awesome 6 Free" !important;
            font-style: normal !important;
            font-weight: 900 !important;
            font-size: 18px !important;
            line-height: 1 !important;
            font-stretch: normal !important;
            letter-spacing: 0 !important;
            transform: none !important;
            vertical-align: middle !important;
            text-rendering: geometricPrecision;
        }
        @media (max-width: 767px) {
            .re9-create-mail-cta { gap: 8px !important; padding: 13px 10px !important; }
            .re9-create-mail-copy { font-size: 15px !important; }
            .re9-create-mail-domain { font-size: 15.5px !important; padding: 5px 7px; }
            .re9-inbox-ad-cta { min-width: 0 !important; width: auto !important; height: 26px !important; font-size: 12px !important; padding: 3px 8px !important; }
            .re9-message-ad-text { font-size: 16px !important; }
            .re9-message-ad-buy { height: 26px !important; min-height: 0 !important; font-size: 12px !important; padding: 3px 8px !important; }
            .re9-message-action-btn { width: 42px !important; height: 42px !important; }
            .re9-message-action-icon { font-size: 18px !important; }
        }

        /* RE9: camadas de modal, menu lateral e rolagem móvel */
        :root { --re9-header-height: 150px; }
        #onlineUsersModal {
            z-index: 10050 !important;
            align-items: center !important;
            justify-content: center !important;
            padding: max(10px, env(safe-area-inset-top)) 10px max(10px, env(safe-area-inset-bottom)) !important;
            overscroll-behavior: contain;
        }
        #onlineUsersModal > div {
            position: relative;
            max-height: calc(100dvh - 20px) !important;
            min-height: 260px;
        }
        #onlineUsersModal .re9-online-modal-close {
            position: sticky;
            top: 0;
            z-index: 30;
            min-width: 46px;
            min-height: 46px;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            border: 2px solid rgba(255,255,255,.5);
            background: #990000;
            color: #fff;
            border-radius: 12px;
            font-size: 20px;
        }
        #folderSidebar {
            top: var(--re9-header-height) !important;
            bottom: 0 !important;
            height: calc(100dvh - var(--re9-header-height)) !important;
            max-height: calc(100dvh - var(--re9-header-height)) !important;
            overflow-y: scroll !important;
            overscroll-behavior-y: contain;
            -webkit-overflow-scrolling: touch !important;
            touch-action: pan-y;
            scrollbar-width: auto;
            scrollbar-color: rgba(203,213,225,.65) rgba(255,255,255,.08);
            padding-bottom: max(22px, env(safe-area-inset-bottom)) !important;
        }
        #mobileDrawerBackdrop {
            top: var(--re9-header-height) !important;
            bottom: 0 !important;
        }
        body.re9-authenticated #re9WorkArea {
            padding-top: 18px !important;
            scroll-margin-top: calc(var(--re9-header-height) + 14px);
        }
        body.re9-authenticated #createEmailModal,
        body.re9-authenticated #recoverPasswordModal,
        body.re9-authenticated #extAccountsModal,
        body.re9-authenticated #changePasswordModal,
        body.re9-authenticated #composeModal,
        body.re9-authenticated #sigModal,
        body.re9-authenticated #brandModal {
            z-index: 10055 !important;
            align-items: flex-start !important;
            padding-top: calc(var(--re9-header-height) + 12px) !important;
            padding-bottom: max(12px, env(safe-area-inset-bottom)) !important;
            overflow-y: auto !important;
            box-sizing: border-box;
        }
        body.re9-authenticated #createEmailModal > div,
        body.re9-authenticated #recoverPasswordModal > div,
        body.re9-authenticated #extAccountsModal > div,
        body.re9-authenticated #changePasswordModal > div,
        body.re9-authenticated #composeModal > div,
        body.re9-authenticated #sigModal > div,
        body.re9-authenticated #brandModal > div {
            max-height: calc(100dvh - var(--re9-header-height) - 24px) !important;
            overflow-y: auto;
            -webkit-overflow-scrolling: touch;
            margin-top: 0 !important;
            margin-bottom: 0 !important;
        }
        body.re9-authenticated #newMailToast,
        body.re9-authenticated #privateMessageToast {
            top: calc(var(--re9-header-height) + 12px) !important;
            z-index: 10070 !important;
        }
        #agendaModal, #contactsModal, #privateMessageModal {
            z-index: 10060 !important;
            align-items: flex-start !important;
            padding-top: calc(var(--re9-header-height) + 12px) !important;
            padding-bottom: max(12px, env(safe-area-inset-bottom)) !important;
            overflow-y: auto !important;
            box-sizing: border-box;
        }
        #agendaModal > div, #contactsModal > div, #privateMessageModal > div {
            max-height: calc(100dvh - var(--re9-header-height) - 24px) !important;
            overflow-y: auto !important;
            -webkit-overflow-scrolling: touch;
            margin-top: 0 !important;
            margin-bottom: 0 !important;
        }
        body.re9-modal-open { overflow: hidden !important; touch-action: none; }
        @media (max-width: 767px) {
            :root { --re9-header-height: 184px; }
            #onlineUsersModal { align-items: stretch !important; padding: max(6px, env(safe-area-inset-top)) 6px max(6px, env(safe-area-inset-bottom)) !important; }
            #onlineUsersModal > div { width: 100% !important; height: 100% !important; max-height: 100% !important; border-radius: 14px !important; }
            #onlineUsersModal > div > div:first-child { padding: 12px !important; gap: 8px !important; }
            #onlineUsersModal h3 { font-size: 16px !important; line-height: 1.3 !important; }
            #onlineUsersModal .re9-online-modal-close { min-width: 48px; min-height: 48px; }
            #folderSidebar { width: min(90vw, 380px) !important; }
            #agendaModal, #contactsModal, #privateMessageModal {
                padding: calc(var(--re9-header-height) + 8px) 6px max(6px, env(safe-area-inset-bottom)) !important;
                align-items: flex-start !important;
            }
            #agendaModal > div, #contactsModal > div, #privateMessageModal > div {
                max-height: calc(100dvh - var(--re9-header-height) - 14px) !important;
                overflow-y: auto !important;
                -webkit-overflow-scrolling: touch;
            }
        }
        /* RE9: janela privada flutuante, sempre abaixo do cabeçalho e com botão fechar acessível */
        #privateMessageModal {
            position: fixed !important;
            inset: var(--re9-header-height) 0 0 0 !important;
            z-index: 10080 !important;
            align-items: flex-start !important;
            justify-content: flex-end !important;
            padding: 14px max(14px, env(safe-area-inset-right)) max(14px, env(safe-area-inset-bottom)) !important;
            overflow-y: auto !important;
            box-sizing: border-box !important;
            background: rgba(15, 23, 42, .30) !important;
            -webkit-backdrop-filter: blur(2px);
            backdrop-filter: blur(2px);
            touch-action: pan-y !important;
        }
        body.re9-modal-open.re9-private-chat-open { touch-action: pan-y !important; }
        #privateMessageModal > div {
            position: relative !important;
            width: min(460px, calc(100vw - 28px)) !important;
            max-width: 460px !important;
            height: min(690px, calc(100dvh - var(--re9-header-height) - 30px)) !important;
            max-height: calc(100dvh - var(--re9-header-height) - 30px) !important;
            min-height: min(340px, calc(100dvh - var(--re9-header-height) - 30px)) !important;
            margin: 0 14px 0 auto !important;
            overflow: hidden !important;
            border: 1px solid rgba(255,255,255,.72) !important;
            box-shadow: 0 22px 70px rgba(2, 8, 23, .36) !important;
        }
        #privateMessageModal > div > div:first-child {
            position: relative !important;
            z-index: 2 !important;
            flex-shrink: 0 !important;
            padding: 13px 15px !important;
        }
        #privateMessageModal #privateMessageHistory {
            min-height: 0 !important;
            flex: 1 1 auto !important;
            overscroll-behavior: contain;
            touch-action: pan-y !important;
        }
        #privateMessageModal button[aria-label="Fechar janela da conversa"] {
            position: relative !important;
            z-index: 5 !important;
            min-width: 76px !important;
            min-height: 44px !important;
            cursor: pointer !important;
            touch-action: manipulation;
        }
        @media (max-width: 767px) {
            #privateMessageModal {
                inset: var(--re9-header-height) 0 0 0 !important;
                align-items: flex-start !important;
                justify-content: center !important;
                padding: 8px 8px max(8px, env(safe-area-inset-bottom)) !important;
                background: rgba(15, 23, 42, .24) !important;
            }
            #privateMessageModal > div {
                width: min(100%, 480px) !important;
                max-width: 480px !important;
                height: calc(100dvh - var(--re9-header-height) - 16px) !important;
                max-height: calc(100dvh - var(--re9-header-height) - 16px) !important;
                min-height: 280px !important;
                margin: 0 auto !important;
                border-radius: 14px !important;
            }
            #privateMessageModal > div > div:first-child { padding: 11px 12px !important; }
            #privateMessageModal #privateMessageHint { padding: 8px 12px !important; }
            #privateMessageModal #privateMessageHistory { padding: 12px !important; }
            #privateMessageModal #privateMessageForm { padding: 9px !important; }
        }
        @media (prefers-reduced-motion: reduce) {
            *, *::before, *::after { scroll-behavior: auto !important; animation-duration: .01ms !important; transition-duration: .01ms !important; }
        }
    </style>

<style id="re9-clean-professional-mobile-ui">
:root {
  --re9-clean-navy: #0b1f36;
  --re9-clean-navy-2: #142b45;
  --re9-clean-graphite: #334155;
  --re9-clean-slate: #64748b;
  --re9-clean-line: #e2e8f0;
  --re9-clean-soft: #f7f9fc;
  --re9-clean-white: #ffffff;
  --re9-clean-green: #166534;
  --re9-clean-red: #991b1b;
}

/* Acabamento geral: menos blocos coloridos, mais respiro e hierarquia. */
#folderSidebar {
  background: linear-gradient(180deg, #10263e 0%, #0b1f36 100%) !important;
  border-right: 1px solid rgba(203,213,225,.18) !important;
  box-shadow: 12px 0 36px rgba(2,8,23,.18) !important;
  padding: 16px 14px max(20px, env(safe-area-inset-bottom)) !important;
  width: min(86vw, 326px) !important;
  color: #e2e8f0 !important;
}
#folderSidebar > div:first-child {
  padding: 4px 2px 13px !important;
  margin-bottom: 12px !important;
  border-color: rgba(203,213,225,.16) !important;
}
#folderSidebar > div:first-child > span {
  color: #cbd5e1 !important;
  letter-spacing: .12em !important;
  font-size: 11px !important;
}
#folderSidebar > div:first-child > span i { color: #94a3b8 !important; }
#folderSidebar .mb-3.shrink-0.rounded-xl.border {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  padding: 0 !important;
  margin-bottom: 12px !important;
}
#folderSidebar .mb-3.shrink-0.rounded-xl.border > p {
  padding: 0 8px 7px !important;
  color: #94a3b8 !important;
  font-size: 10px !important;
  letter-spacing: .13em !important;
}
#folderSidebar .mb-3.shrink-0.rounded-xl.border > button,
#folderSidebar .mb-3.shrink-0.rounded-xl.border > a,
#folderSidebar > div:last-child > button {
  display: flex !important;
  align-items: center !important;
  gap: 11px !important;
  min-height: 48px !important;
  padding: 10px 12px !important;
  margin: 5px 0 !important;
  background: rgba(255,255,255,.045) !important;
  border: 1px solid rgba(203,213,225,.12) !important;
  border-radius: 11px !important;
  color: #e5edf5 !important;
  font-size: 14px !important;
  font-weight: 650 !important;
  line-height: 1.35 !important;
  box-shadow: none !important;
  text-align: left !important;
  transition: background .18s ease, border-color .18s ease !important;
}
#folderSidebar .mb-3.shrink-0.rounded-xl.border > button:hover,
#folderSidebar .mb-3.shrink-0.rounded-xl.border > a:hover,
#folderSidebar > div:last-child > button:hover {
  background: rgba(255,255,255,.095) !important;
  border-color: rgba(203,213,225,.28) !important;
}
#folderSidebar .mb-3.shrink-0.rounded-xl.border > button span.flex.h-9.w-9,
#folderSidebar .mb-3.shrink-0.rounded-xl.border > a span.flex.h-9.w-9 {
  width: 34px !important;
  height: 34px !important;
  min-width: 34px !important;
  border-radius: 9px !important;
  background: #263a51 !important;
  color: #dbe5ef !important;
}
#folderSidebar .mb-3.shrink-0.rounded-xl.border > button span.flex.h-9.w-9 i,
#folderSidebar .mb-3.shrink-0.rounded-xl.border > a span.flex.h-9.w-9 i { color: #dbe5ef !important; }
#folderSidebar nav {
  padding-bottom: 10px !important;
  margin-bottom: 4px !important;
  border-bottom: 1px solid rgba(203,213,225,.15) !important;
}
#folderSidebar nav button {
  min-height: 45px !important;
  margin: 3px 0 !important;
  padding: 10px 12px !important;
  border: 1px solid transparent !important;
  border-radius: 10px !important;
  background: transparent !important;
  color: #d7e0ea !important;
  font-size: 14px !important;
  font-weight: 600 !important;
}
#folderSidebar nav button:hover {
  background: rgba(255,255,255,.07) !important;
  border-color: rgba(203,213,225,.12) !important;
}
#folderSidebar nav button[class~="bg-[#002244]"] {
  background: rgba(203,213,225,.12) !important;
  border: 1px solid rgba(203,213,225,.2) !important;
  border-left: 3px solid #94a3b8 !important;
  color: #ffffff !important;
}
#folderSidebar nav button i { color: #cbd5e1 !important; }
#folderSidebar > div:last-child {
  padding-top: 12px !important;
  margin-top: 8px !important;
  border-color: rgba(203,213,225,.16) !important;
  gap: 7px !important;
}
#folderSidebar > div:last-child > div {
  min-height: 42px !important;
  border: 1px solid rgba(203,213,225,.12) !important;
  border-radius: 10px !important;
  background: rgba(2,8,23,.22) !important;
  color: #cbd5e1 !important;
  font-size: 12px !important;
}
#folderSidebar > div:last-child > button i { color: #cbd5e1 !important; }
#folderSidebar > div:last-child > button.btn-blood {
  background: #7f1d1d !important;
  border-color: #991b1b !important;
  color: #ffffff !important;
}
#folderSidebar > div:last-child > button.btn-blood i { color: #ffffff !important; }
#folderSidebar #privateUnreadContactsBadge,
#folderSidebar #privateUnreadMenuBadge,
#folderSidebar #unreadRedBall { background: #991b1b !important; color: #ffffff !important; }

/* Janela de contatos: dimensionamento responsivo real, sem rolagem horizontal. */
#contactsModal {
  padding: calc(var(--re9-header-height) + 10px) 10px max(12px, env(safe-area-inset-bottom)) !important;
  align-items: flex-start !important;
  overflow-x: hidden !important;
  overflow-y: auto !important;
  background: rgba(15,23,42,.48) !important;
}
#contactsModal > div {
  width: min(1080px, calc(100vw - 20px)) !important;
  max-width: calc(100vw - 20px) !important;
  max-height: calc(100dvh - var(--re9-header-height) - 22px) !important;
  margin: 0 auto !important;
  border: 1px solid #dce3eb !important;
  border-radius: 16px !important;
  overflow-x: hidden !important;
  overflow-y: auto !important;
  box-shadow: 0 18px 52px rgba(15,23,42,.2) !important;
  box-sizing: border-box !important;
}
#contactsModal > div > .sticky {
  background: #10263e !important;
  padding: 15px 18px !important;
  border-bottom: 1px solid #dbe3ec !important;
}
#contactsModal > div > .sticky h2 { font-size: 19px !important; letter-spacing: -.015em !important; }
#contactsModal > div > .sticky p { font-size: 13px !important; color: #cbd5e1 !important; }
#contactsModal > div > .grid {
  display: grid !important;
  grid-template-columns: minmax(0,.9fr) minmax(0,1.1fr) !important;
  gap: 16px !important;
  padding: 16px !important;
  min-width: 0 !important;
  box-sizing: border-box !important;
}
#contactsModal form,
#contactsModal section,
#contactsModal #contactsList,
#contactsModal #re9DirectoryResults,
#contactsModal #privateUnreadConversations { min-width: 0 !important; max-width: 100% !important; }
#contactsModal form {
  background: #ffffff !important;
  border: 1px solid #e2e8f0 !important;
  border-radius: 13px !important;
  padding: 16px !important;
  box-shadow: 0 2px 8px rgba(15,23,42,.035) !important;
}
#contactsModal .bg-orange-50,
#contactsModal .bg-orange-50\/60 {
  background: #f7f9fc !important;
  border: 1px solid #e2e8f0 !important;
  border-radius: 13px !important;
  box-shadow: none !important;
}
#contactsModal .border-2 { border-width: 1px !important; }
#contactsModal .border-\[\#f28c38\],
#contactsModal .border-orange-200 { border-color: #dbe3ec !important; }
#contactsModal [class~="text-[#002244]"] { color: #10263e !important; }
#contactsModal [class~="text-[#f28c38]"],
#contactsModal [class~="text-[#d97706]"] { color: #64748b !important; }
#contactsModal .text-orange-900,
#contactsModal .text-orange-800 { color: #475569 !important; }
#contactsModal input,
#contactsModal textarea,
#contactsModal select {
  width: 100% !important;
  max-width: 100% !important;
  min-width: 0 !important;
  box-sizing: border-box !important;
  border-color: #cbd5e1 !important;
  border-radius: 10px !important;
  background: #ffffff !important;
  color: #1e293b !important;
  font-size: 15px !important;
}
#contactsModal input:focus,
#contactsModal textarea:focus,
#contactsModal select:focus {
  border-color: #64748b !important;
  box-shadow: 0 0 0 3px rgba(100,116,139,.12) !important;
  outline: none !important;
}
#contactsModal label { min-width: 0 !important; color: #334155 !important; font-size: 13px !important; }
#contactsModal p { overflow-wrap: anywhere; }
#contactsModal .text-xs { font-size: 13px !important; line-height: 1.5 !important; }
#contactsModal .text-sm { font-size: 14px !important; line-height: 1.5 !important; }
#contactsModal .text-base { font-size: 15px !important; }
#contactsModal #privateUnreadConversations { padding: 12px; border: 1px solid #e2e8f0; border-radius: 13px; background: #f8fafc; }
#privateUnreadConversations h3 { color: #334155 !important; font-size: 15px !important; letter-spacing: 0 !important; }
#privateUnreadConversations button {
  min-width: 0 !important;
  border: 1px solid #e2e8f0 !important;
  border-radius: 12px !important;
  background: #ffffff !important;
  padding: 12px !important;
  box-shadow: none !important;
}
#privateUnreadConversations button:hover { background: #f8fafc !important; border-color: #cbd5e1 !important; }
#privateUnreadConversations button > span:first-child { background: #eef2f6 !important; color: #475569 !important; }
#privateUnreadConversations button > span:nth-child(2) strong { font-size: 15px !important; color: #1e293b !important; }
#privateUnreadConversations button > span:nth-child(2) > span { font-size: 13px !important; line-height: 1.4 !important; }
#privateUnreadConversations button > span:nth-child(2) > span:nth-of-type(2) { font-size: 14px !important; color: #475569 !important; }
#privateUnreadConversations button > span:last-child { background: #991b1b !important; }
#contactsModal #contactsList > * { min-width: 0 !important; max-width: 100% !important; overflow-wrap: anywhere; }
#contactsModal #contactsList button { min-width: 42px; }

/* Avisos discretos e legíveis: não cobrem campos de busca nem botões do modal. */
#newMailToast {
  background: #10263e !important;
  border-left: 3px solid #64748b !important;
  border-radius: 13px !important;
  box-shadow: 0 12px 34px rgba(15,23,42,.2) !important;
  animation: none !important;
}
#newMailToast .unread-badge-pulse { animation: none !important; background: #334155 !important; }
#newMailToast > div:nth-child(2) .text-xs { color: #cbd5e1 !important; font-size: 13px !important; }
#privateMessageToast {
  top: auto !important;
  bottom: max(16px, env(safe-area-inset-bottom)) !important;
  left: 50% !important;
  right: auto !important;
  width: min(500px, calc(100vw - 24px)) !important;
  max-width: 500px !important;
  padding: 15px 16px !important;
  border: 1px solid #dbe3ec !important;
  border-left: 4px solid #334155 !important;
  border-radius: 13px !important;
  background: #ffffff !important;
  color: #1e293b !important;
  box-shadow: 0 16px 42px rgba(15,23,42,.2) !important;
  ring: 0 !important;
  z-index: 10090 !important;
}
#privateMessageToast strong { color: #10263e !important; font-size: 15px !important; }
#privateMessageToast #privateMessageToastText { color: #475569 !important; font-size: 14.5px !important; line-height: 1.5 !important; }
#privateMessageToast > div:last-child { color: #334155 !important; font-size: 13px !important; }
#privateMessageToast .text-orange-700,
#privateMessageToast .text-\[\#d97706\] { color: #64748b !important; }

/* Painel de caixas online: cabeçalho sóbrio, botões neutros e lista clara. */
#onlineUsersModal { background: rgba(15,23,42,.58) !important; }
#onlineUsersModal > div {
  border: 1px solid #dbe3ec !important;
  border-top: 3px solid #166534 !important;
  border-radius: 17px !important;
  box-shadow: 0 24px 70px rgba(2,8,23,.25) !important;
  background: #ffffff !important;
}
#onlineUsersModal > div > div:first-child { background: #10263e !important; padding: 15px 18px !important; }
#onlineUsersModal .re9-online-modal-close {
  background: #334155 !important;
  border: 1px solid #64748b !important;
  border-radius: 10px !important;
  min-width: 100px !important;
  min-height: 42px !important;
  font-size: 13px !important;
}
#onlineUsersModal button[onclick="refreshOnlineUsers()"] {
  background: #e2e8f0 !important;
  color: #1e293b !important;
  border: 1px solid #cbd5e1 !important;
  box-shadow: none !important;
  padding: 9px 13px !important;
  font-size: 13px !important;
}
#onlineUsersModal > div > div:nth-child(2) { background: #f7f9fc !important; border-color: #e2e8f0 !important; }
#onlineUsersModal #adminOnlineUsersList { background: #f8fafc !important; padding: 14px !important; }
#adminOnlineUsersList > div {
  border-color: #e2e8f0 !important;
  border-radius: 12px !important;
  box-shadow: 0 1px 4px rgba(15,23,42,.04) !important;
}
#adminOnlineUsersList > div .rounded-full.bg-\[\#002244\] { background: #e9eef4 !important; color: #334155 !important; }
#adminOnlineUsersList > div .bg-emerald-100 { background: #ecfdf3 !important; color: #166534 !important; }

/* Agenda e janelas internas: neutros claros com acentos pequenos em verde/vermelho. */
#agendaModal > div,
#privateMessageModal > div { border: 1px solid #dbe3ec !important; box-shadow: 0 18px 54px rgba(15,23,42,.18) !important; }
#agendaModal .bg-amber-50,
#agendaModal .bg-orange-50,
#agendaModal .bg-blue-50 { background: #f7f9fc !important; border-color: #e2e8f0 !important; color: #475569 !important; }
#agendaModal [class~="text-[#f28c38]"],
#agendaModal [class~="text-[#d97706]"] { color: #64748b !important; }
#agendaModal .border-orange-200,
#agendaModal .border-amber-200 { border-color: #e2e8f0 !important; }

/* Pequenos detalhes do tema: laranja substituído por cinza; verde/vermelho reservados a status. */
#folderSidebar .text-orange-300,
#folderSidebar .text-orange-200,
#folderSidebar .text-\[\#f8a45f\],
#folderSidebar .text-\[\#f28c38\] { color: #cbd5e1 !important; }
#folderSidebar .bg-orange-500,
#folderSidebar .bg-orange-600,
#folderSidebar .bg-\[\#f28c38\] { background: #334155 !important; }

@media (min-width: 768px) {
  #folderSidebar { width: 310px !important; }
  #contactsModal > div > .grid { gap: 20px !important; padding: 20px !important; }
  #privateMessageToast { bottom: 22px !important; }
}
@media (max-width: 900px) {
  #contactsModal > div > .grid { grid-template-columns: minmax(0,1fr) !important; }
}
@media (max-width: 767px) {
  #folderSidebar { width: min(88vw, 340px) !important; padding: 13px 12px max(18px, env(safe-area-inset-bottom)) !important; }
  #folderSidebar .mb-3.shrink-0.rounded-xl.border > button,
  #folderSidebar .mb-3.shrink-0.rounded-xl.border > a,
  #folderSidebar > div:last-child > button { min-height: 46px !important; margin: 4px 0 !important; padding: 9px 11px !important; font-size: 14px !important; }
  #folderSidebar nav button { min-height: 43px !important; padding: 9px 11px !important; }
  #contactsModal { padding: calc(var(--re9-header-height) + 8px) 8px max(10px, env(safe-area-inset-bottom)) !important; }
  #contactsModal > div { width: calc(100vw - 16px) !important; max-width: calc(100vw - 16px) !important; max-height: calc(100dvh - var(--re9-header-height) - 16px) !important; border-radius: 14px !important; }
  #contactsModal > div > .sticky { padding: 12px 14px !important; }
  #contactsModal > div > .sticky h2 { font-size: 17px !important; }
  #contactsModal > div > .grid { grid-template-columns: minmax(0,1fr) !important; gap: 12px !important; padding: 12px !important; }
  #contactsModal form { padding: 13px !important; }
  #contactsModal section .mb-4 { margin-bottom: 12px !important; }
  #contactsModal input, #contactsModal textarea, #contactsModal select { font-size: 16px !important; min-height: 46px !important; }
  #contactsModal .text-xs { font-size: 13.5px !important; }
  #contactsModal .text-sm { font-size: 14.5px !important; }
  #privateUnreadConversations button { gap: 9px !important; padding: 10px !important; }
  #privateUnreadConversations button > span:first-child { width: 36px !important; height: 36px !important; }
  #privateUnreadConversations button > span:nth-child(2) strong { font-size: 15px !important; }
  #privateUnreadConversations button > span:nth-child(2) > span:nth-of-type(2) { font-size: 14px !important; }
  #onlineUsersModal { align-items: center !important; padding: max(10px, env(safe-area-inset-top)) 8px max(10px, env(safe-area-inset-bottom)) !important; }
  #onlineUsersModal > div { width: calc(100vw - 16px) !important; height: calc(100dvh - 20px) !important; max-height: calc(100dvh - 20px) !important; border-radius: 14px !important; }
  #onlineUsersModal > div > div:first-child { padding: 12px !important; }
  #onlineUsersModal h3 { font-size: 15px !important; line-height: 1.35 !important; }
  #onlineUsersModal .re9-online-modal-close { min-width: 88px !important; min-height: 42px !important; }
  #onlineUsersModal #adminOnlineUsersList { padding: 10px !important; }
  #privateMessageToast { bottom: max(14px, env(safe-area-inset-bottom)) !important; width: calc(100vw - 20px) !important; max-width: 500px !important; padding: 13px 14px !important; }
  #privateMessageToast strong { font-size: 15px !important; }
  #privateMessageToast #privateMessageToastText { font-size: 15px !important; }
}
</style>
<style id="re9-mobile-clean-polish-v2">
:root{
  --re9-clean-navy:#203a55;
  --re9-clean-navy-deep:#172f48;
  --re9-clean-graphite:#46576a;
  --re9-clean-steel:#e8edf2;
  --re9-clean-soft:#f4f6f9;
  --re9-clean-line:#d9e1e9;
  --re9-clean-ink:#263648;
  --re9-clean-muted:#657589;
  --re9-clean-red:#9b2634;
  --re9-clean-green:#1e684a;
}

/* Cabeçalho OAB: azul institucional mais claro; faixa de notícias permanece azul-marinho. */
#re9FixedTopBar{
  background:linear-gradient(120deg,#5b83aa 0%,#47749d 54%,#37658f 100%) !important;
  border-bottom:3px solid #9b2634 !important;
  box-shadow:0 5px 16px rgba(24,55,83,.13) !important;
}
#re9FixedTopBar #topHeaderLogo{
  background:#fff !important;
  border:1px solid #d8e1e9 !important;
  border-radius:9px !important;
  padding:4px 7px !important;
}
#re9FixedTopBar .re9-top-date-time{
  color:#e5edf4 !important;
  border-left:1px solid rgba(226,232,240,.38);
  padding-left:10px;
  line-height:1.2;
  font-size:12px;
}
#re9FixedTopBar .re9-top-clock-time{color:#fff !important;font-size:14px;letter-spacing:.02em}
#re9FixedTopBar button[onclick*="toggleMobileSidebar"],
#re9FixedTopBar button[onclick*="loadEmails('INBOX')"]{
  background:#e8eef4 !important;
  color:#263e56 !important;
  border:1px solid #cbd6e0 !important;
  box-shadow:none !important;
}
#re9FixedTopBar button[onclick*="openComposeModal"],
#re9FixedTopBar button.btn-chrome{
  background:#dfe7ef !important;
  color:#203a55 !important;
  border:1px solid #c4d0dc !important;
  box-shadow:none !important;
}
#re9FixedTopBar button[onclick*="openComposeModal"] i{color:#29465f !important}
#re9FixedTopBar > div.w-full.flex.items-center.gap-2.border-t{
  border-top:1px solid rgba(255,255,255,.30) !important;
  padding:8px 9px 0 !important;
  margin-top:4px;
}
#re9FixedTopBar > div.w-full.flex.items-center.gap-2.border-t > div{
  background:#142f4a !important;
  border:1px solid rgba(255,255,255,.16) !important;
  border-radius:9px !important;
  padding:8px 11px !important;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05) !important;
}
#re9FixedTopBar .re9-news-window{
  background:transparent !important;
  border:0 !important;
  border-radius:0 !important;
  padding:5px 7px !important;
  color:#fff !important;
}
#re9FixedTopBar .re9-news-track a{color:#fff !important;font-weight:500 !important}
#re9FixedTopBar .re9-news-track a:hover{color:#f5dce0 !important;text-decoration:underline !important}
#re9FixedTopBar .re9-news-separator{color:#d36c78 !important}
#re9FixedTopBar .re9-news-window + span,
#re9FixedTopBar > div.w-full.flex.items-center.gap-2.border-t > div > span:first-child{color:#fff !important}
#re9FixedTopBar > div.w-full.flex.items-center.gap-2.border-t > div > span:first-child{color:#fff !important}
#re9FixedTopBar .re9-news-window > .re9-news-track{font-weight:500 !important;letter-spacing:.005em}

/* Menu lateral claro, com itens consistentes e sem blocos saturados. */
#folderSidebar{
  background:#f3f6f9 !important;
  color:var(--re9-clean-ink) !important;
  border-right:1px solid #d5dee7 !important;
  box-shadow:0 18px 44px rgba(15,23,42,.18) !important;
}
#folderSidebar > div:first-child{border-bottom:1px solid var(--re9-clean-line) !important}
#folderSidebar > div:first-child > span{color:#42566c !important;font-size:12px !important;letter-spacing:.08em}
#folderSidebar > div:first-child > span i{color:#58718a !important}
#folderSidebar > div:first-child > button{background:#e7edf3 !important;color:#42566c !important;border:1px solid #d5dee7 !important}
#folderSidebar .mb-3.shrink-0.rounded-xl.border{
  background:#fff !important;
  border:1px solid #dce4ec !important;
  border-radius:13px !important;
  box-shadow:0 3px 10px rgba(23,47,72,.045) !important;
}
#folderSidebar .mb-3.shrink-0.rounded-xl.border > p{color:#718095 !important;font-size:11px !important;letter-spacing:.09em}
#folderSidebar .mb-3.shrink-0.rounded-xl.border > button,
#folderSidebar .mb-3.shrink-0.rounded-xl.border > a{
  min-height:48px !important;
  margin:3px 0 !important;
  padding:9px 10px !important;
  border:1px solid transparent !important;
  border-radius:10px !important;
  background:transparent !important;
  color:#2d4055 !important;
  font-size:15px !important;
  font-weight:650 !important;
  line-height:1.25 !important;
  box-shadow:none !important;
}
#folderSidebar .mb-3.shrink-0.rounded-xl.border > button:hover,
#folderSidebar .mb-3.shrink-0.rounded-xl.border > a:hover{background:#edf2f6 !important;border-color:#e0e7ee !important}
#folderSidebar .mb-3.shrink-0.rounded-xl.border > button > span:first-child,
#folderSidebar .mb-3.shrink-0.rounded-xl.border > a > span:first-child{
  width:34px !important;height:34px !important;min-width:34px !important;
  border-radius:9px !important;background:#edf2f6 !important;color:#3b5874 !important;
  border:1px solid #e0e7ee !important;
}
#folderSidebar .mb-3.shrink-0.rounded-xl.border > a > span:first-child{color:#246247 !important}
#folderSidebar .mb-3.shrink-0.rounded-xl.border .fa-chevron-right,
#folderSidebar .mb-3.shrink-0.rounded-xl.border .fa-arrow-up-right-from-square{color:#8291a2 !important}
#folderSidebar nav{padding-top:7px !important}
#folderSidebar .folder-btn{
  min-height:46px !important;
  margin:3px 0 !important;
  padding:10px 12px !important;
  border:1px solid #e1e7ed !important;
  border-left:3px solid transparent !important;
  border-radius:10px !important;
  background:#fff !important;
  color:#34485e !important;
  font-size:14.5px !important;
  font-weight:650 !important;
  box-shadow:none !important;
}
#folderSidebar .folder-btn:hover{background:#edf2f6 !important;border-color:#d8e1e9 !important}
#folderSidebar .folder-btn[onclick*="loadEmails('INBOX',"]{
  background:#263f59 !important;color:#fff !important;border-color:#263f59 !important;
  border-left:3px solid #8ea4b9 !important;box-shadow:0 3px 9px rgba(32,58,85,.14) !important;
}
#folderSidebar .folder-btn i{color:#6b8197 !important}
#folderSidebar .folder-btn[onclick*="loadEmails('INBOX',"] i{color:#e3ebf2 !important}
#folderSidebar .folder-btn #unreadRedBall,
#folderSidebar #privateUnreadContactsBadge,
#folderSidebar #privateUnreadMenuBadge{background:var(--re9-clean-red) !important;color:#fff !important}
#folderSidebar > div.border-t{border-top:1px solid #d8e0e8 !important}
#folderSidebar > div.border-t > div{
  background:#e8edf2 !important;color:#405267 !important;border:1px solid #d6dee7 !important;
  border-radius:9px !important;font-size:12px !important;padding:10px 11px !important;
}
#folderSidebar > div.border-t button{
  min-height:47px !important;margin:2px 0 !important;padding:10px 12px !important;
  border:1px solid #dce4eb !important;border-radius:10px !important;
  background:#fff !important;color:#354a60 !important;font-size:14.5px !important;
  font-weight:650 !important;box-shadow:none !important;
}
#folderSidebar > div.border-t button:hover{background:#edf2f6 !important;border-color:#cbd6e0 !important}
#folderSidebar > div.border-t button i{color:#536d86 !important}
#folderSidebar > div.border-t button[onclick*="onlineUsersModal"]{background:#edf5f0 !important;border-color:#d3e4d9 !important;color:#24583f !important}
#folderSidebar > div.border-t button[onclick*="onlineUsersModal"] i{color:#246247 !important}
#folderSidebar > div.border-t button[onclick*="logoutWebmail"]{background:#8f2633 !important;border-color:#8f2633 !important;color:#fff !important}
#folderSidebar > div.border-t button[onclick*="logoutWebmail"] i{color:#fff !important}
#folderSidebar > div.border-t button[onclick*="brandModal"]{background:#eef2f6 !important;color:#34485e !important}
#folderSidebar > div.border-t button[onclick*="showInstallBannerManual"]{background:#e9eef4 !important;color:#334e68 !important}
#mobileDrawerBackdrop{background:rgba(17,31,47,.38) !important;backdrop-filter:blur(1.5px)}

/* Recado fixo: visual leve, tipografia regular e apenas um pequeno detalhe vermelho. */
#emailListContainer button[aria-label="Abrir mensagem fixa de boas-vindas"]{
  display:block !important;width:100% !important;min-width:0 !important;
  padding:13px 15px !important;text-align:left !important;
  background:#f8fafc !important;border:1px solid #e2e8ef !important;
  border-left:2px solid #a33a47 !important;border-radius:0 0 10px 10px !important;
  color:#526477 !important;box-shadow:inset 0 1px 0 #fff !important;
  font-weight:400 !important;
}
#emailListContainer button[aria-label="Abrir mensagem fixa de boas-vindas"]:hover{background:#f0f5f9 !important}
#emailListContainer button[aria-label="Abrir mensagem fixa de boas-vindas"] > span:first-child{gap:7px !important;margin-bottom:6px !important}
#emailListContainer button[aria-label="Abrir mensagem fixa de boas-vindas"] > span:first-child span:first-child{
  background:#edf3f8 !important;color:#61758a !important;border:1px solid #e0e8ef !important;
  font-size:10px !important;font-weight:600 !important;padding:3px 8px !important;border-radius:999px !important;
}
#emailListContainer button[aria-label="Abrir mensagem fixa de boas-vindas"] > span:first-child span:nth-child(2){color:#8391a0 !important;font-size:11px !important;font-weight:500 !important}
#emailListContainer button[aria-label="Abrir mensagem fixa de boas-vindas"] > span:first-child i{color:#a33a47 !important;font-size:11px !important}
#emailListContainer button[aria-label="Abrir mensagem fixa de boas-vindas"] > strong{font-size:15px !important;line-height:1.4 !important;color:#405a73 !important;font-weight:600 !important}
#emailListContainer button[aria-label="Abrir mensagem fixa de boas-vindas"] > span:nth-child(3){font-size:14px !important;line-height:1.55 !important;color:#718093 !important;margin-top:5px !important;font-weight:400 !important}
#emailListContainer button[aria-label="Abrir mensagem fixa de boas-vindas"] > span:nth-child(4){font-size:12px !important;line-height:1.4 !important;color:#587a9a !important;margin-top:7px !important;font-weight:500 !important}

/* Aviso de mensagem privada: legível, discreto e fora dos controles superiores. */
#privateMessageToast{
  top:auto !important;bottom:24px !important;left:50% !important;right:auto !important;
  transform:translateX(-50%) !important;width:min(92vw,470px) !important;max-width:470px !important;
  padding:15px 17px !important;background:#fff !important;color:#27384b !important;
  border:1px solid #cfd9e3 !important;border-radius:14px !important;
  box-shadow:0 14px 34px rgba(15,23,42,.18) !important;ring:0 !important;z-index:10090 !important;
}
#privateMessageToast strong{font-size:16px !important;line-height:1.35 !important;color:#203a55 !important}
#privateMessageToast strong i{color:#476783 !important}
#privateMessageToast #privateMessageToastText{font-size:16px !important;line-height:1.48 !important;color:#46576a !important}
#privateMessageToast > div:last-child{font-size:14px !important;color:#315c7e !important;margin-top:9px !important}
#privateMessageToast button{background:#eef2f6 !important;color:#46576a !important;border:1px solid #dce4eb !important;min-width:34px;min-height:34px}
#newMailToast{border-left-color:#617b95 !important;box-shadow:0 12px 28px rgba(15,23,42,.16) !important}

/* Contatos e mensagens: elimina largura excedente e rolagem horizontal no celular. */
#contactsModal,#agendaModal,#privateMessageModal{overflow-x:hidden !important}
#contactsModal > div,#agendaModal > div,#privateMessageModal > div{
  width:min(100%,980px) !important;max-width:calc(100vw - 24px) !important;min-width:0 !important;
  overflow-x:hidden !important;border:1px solid #dce3ea !important;box-shadow:0 18px 46px rgba(15,23,42,.18) !important;
}
#contactsModal > div > .sticky{background:#213b56 !important}
#contactsModal > div > .sticky .fa-address-book{color:#d4e0eb !important}
#contactsModal > div > .grid{min-width:0 !important;width:100% !important;grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr) !important}
#contactsModal > div > .grid > *{min-width:0 !important;max-width:100% !important}
#contactsModal input,#contactsModal textarea,#contactsModal select{width:100% !important;max-width:100% !important;min-width:0 !important;box-sizing:border-box !important}
#contactsModal .overflow-x-auto,#contactsModal .overflow-auto{max-width:100% !important}
#contactsModal *{overflow-wrap:anywhere}
#contactsModal form,#contactsModal section{border-color:#dce4eb !important;border-radius:12px !important}
#contactsModal h2,#contactsModal h3{color:#263f59 !important}
#contactsModal .text-orange-700,#contactsModal .text-orange-800,#contactsModal .text-\[\#f28c38\]{color:#3d5d7a !important}
#contactsModal .bg-orange-50,#contactsModal .bg-orange-100{background:#f1f4f7 !important}
#contactsModal .border-orange-200,#contactsModal .border-orange-300{border-color:#dbe3eb !important}

/* Janela de usuários online e botões com cores de status mais contidas. */
#onlineUsersModal > div > div:first-child{background:#213b56 !important}
#onlineUsersModal > div > div:first-child button[onclick*="refreshOnlineUsers"]{background:#e4ebf2 !important;color:#29445f !important;box-shadow:none !important}
#onlineUsersModal .re9-online-modal-close{background:#e8eef4 !important;color:#30465d !important;border:1px solid #cad5df !important}
#onlineUsersModal > div > div:nth-child(2){background:#f2f5f8 !important}
#onlineUsersModal input{background:#fff !important;border-color:#d5dee7 !important;color:#26384b !important;font-size:15px !important}
#onlineUsersModal .bg-orange-50,#onlineUsersModal .bg-amber-50{background:#f1f4f7 !important}
#onlineUsersModal .border-orange-200,#onlineUsersModal .border-amber-200{border-color:#dce4eb !important}

@media (max-width:900px){
  #contactsModal > div > .grid{grid-template-columns:minmax(0,1fr) !important}
}
@media (max-width:767px){
  #re9FixedTopBar{padding:8px 10px !important;gap:8px 6px !important;min-height:0 !important}
  #re9FixedTopBar > div:first-child{flex:1 1 auto !important;min-width:0 !important;gap:8px !important}
  #re9FixedTopBar > div:first-child > div{gap:7px !important;min-width:0 !important}
  #re9FixedTopBar #topHeaderLogo{height:38px !important;max-width:132px !important;padding:4px 6px !important}
  #re9FixedTopBar .re9-top-date-time{font-size:11px !important;padding-left:8px !important}
  #re9FixedTopBar .re9-top-clock-time{font-size:13px !important}
  #re9FixedTopBar > div:nth-child(2){flex:0 0 auto !important;gap:6px !important}
  #re9FixedTopBar > div:nth-child(2) button{min-height:42px !important;padding:8px 10px !important;border-radius:10px !important}
  #re9FixedTopBar > div:nth-child(2) button[onclick*="openComposeModal"] span{font-size:12px !important}
  #re9FixedTopBar > div.w-full.flex.items-center.gap-2.border-t{flex:1 1 100% !important;margin-top:2px !important;padding-top:7px !important}
  #re9FixedTopBar .re9-news-window{padding:8px 10px !important;min-height:40px !important}
  #re9FixedTopBar .re9-news-track{gap:1.1rem !important;font-size:14px !important}
  #folderSidebar{width:min(88vw,350px) !important;padding:14px 12px max(20px,env(safe-area-inset-bottom)) !important}
  #folderSidebar .mb-3.shrink-0.rounded-xl.border > button,
  #folderSidebar .mb-3.shrink-0.rounded-xl.border > a{min-height:49px !important;padding:9px 10px !important;font-size:15px !important}
  #folderSidebar .folder-btn{min-height:48px !important;font-size:15px !important;padding:10px 12px !important}
  #folderSidebar > div.border-t button{min-height:49px !important;font-size:15px !important}
  #privateMessageToast{bottom:max(82px,calc(env(safe-area-inset-bottom) + 70px)) !important;width:calc(100vw - 22px) !important;max-width:480px !important;padding:14px 15px !important}
  #privateMessageToast strong{font-size:16px !important}
  #privateMessageToast #privateMessageToastText{font-size:16px !important;line-height:1.5 !important}
  #privateMessageToast > div:last-child{font-size:14px !important}
  #contactsModal{padding:calc(var(--re9-header-height) + 7px) 8px max(12px,env(safe-area-inset-bottom)) !important;align-items:flex-start !important}
  #contactsModal > div{width:calc(100vw - 16px) !important;max-width:calc(100vw - 16px) !important;max-height:calc(100dvh - var(--re9-header-height) - 16px) !important;border-radius:14px !important}
  #contactsModal > div > .sticky{padding:12px 14px !important;gap:10px !important}
  #contactsModal > div > .sticky h2{font-size:17px !important;line-height:1.3 !important}
  #contactsModal > div > .sticky p{font-size:13.5px !important;line-height:1.4 !important}
  #contactsModal > div > .grid{grid-template-columns:minmax(0,1fr) !important;gap:12px !important;padding:12px !important}
  #contactsModal form{padding:13px !important}
  #contactsModal input,#contactsModal textarea,#contactsModal select{font-size:16px !important;min-height:46px !important}
  #contactsModal .text-xs{font-size:14px !important;line-height:1.45 !important}
  #contactsModal .text-sm{font-size:15px !important;line-height:1.45 !important}
  #privateUnreadConversations button{gap:10px !important;padding:12px !important}
  #privateUnreadConversations button > span:first-child{width:40px !important;height:40px !important;flex:0 0 40px !important}
  #privateUnreadConversations button > span:nth-child(2) strong{font-size:16px !important}
  #privateUnreadConversations button > span:nth-child(2) > span:nth-of-type(2){font-size:15px !important;line-height:1.45 !important}
  #onlineUsersModal > div > div:first-child{padding:12px !important;gap:9px !important}
  #onlineUsersModal h3{font-size:16px !important;line-height:1.35 !important}
  #onlineUsersModal .re9-online-modal-close{min-width:46px !important;min-height:42px !important}
  #emailListContainer button[aria-label="Abrir mensagem fixa de boas-vindas"]{padding:14px 13px !important}
  #emailListContainer button[aria-label="Abrir mensagem fixa de boas-vindas"] > strong{font-size:15px !important;font-weight:600 !important}
  #emailListContainer button[aria-label="Abrir mensagem fixa de boas-vindas"] > span:nth-child(3){font-size:14px !important;line-height:1.55 !important;font-weight:400 !important}
  #emailListContainer button[aria-label="Abrir mensagem fixa de boas-vindas"] > span:nth-child(4){font-size:12px !important;font-weight:500 !important}
}
@media (prefers-reduced-motion:reduce){
  #folderSidebar *,#privateMessageToast *,#re9FixedTopBar *{scroll-behavior:auto !important;transition-duration:.01ms !important}
}
</style>

</head>
<!-- RE9 BUILD: re9-client-soft-oab-blue-20261115-03 | loja integrada neste index.php -->
<body class="bg-slate-100 text-slate-800 overflow-y-auto overflow-x-hidden min-h-[115vh] flex flex-col select-none md:select-auto<?php echo $is_logged ? ' re9-authenticated' : ''; ?>">
<?php if (!empty($_SESSION['wm_email']) && re9_account_pending_review($_SESSION['wm_email']) && !is_user_admin()): ?>
<div class="relative z-[1] border-b-2 border-amber-400 bg-amber-50 px-4 py-3 text-center text-sm text-amber-950 shadow"><strong>Conta aguardando confirmação dos dados.</strong> Sua caixa está disponível para visualizar mensagens recebidas. O envio de e-mails e as demais funções restritas serão liberados após a conferência manual pela equipe RE9. O canal de contatos e suporte permanece disponível. <span class="font-semibold">Aguarde a análise.</span></div>
<?php endif; ?>

<!-- POPUP AUTOMÁTICO DE INSTALAÇÃO DO APLICATIVO (PWA) -->
<div id="pwaInstallBanner" class="hidden fixed bottom-3 left-3 right-3 md:left-auto md:right-5 md:bottom-5 md:w-96 z-50 bg-[#00152b] text-white p-4 rounded-2xl shadow-2xl border-2 border-[#f28c38] flex-col gap-3">
    <div class="flex items-center gap-3.5">
        <img src="<?php echo htmlspecialchars((isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '/index.php') . '?pwa=icon', ENT_QUOTES, 'UTF-8'); ?>" alt="Ícone RE9 EMAIL" class="w-14 h-14 rounded-2xl shadow-md shrink-0 border border-white/15">
        <div class="flex-1 min-w-0">
            <div class="flex items-center justify-between">
                <span class="text-[10px] font-extrabold uppercase tracking-wider px-2 py-0.5 rounded bg-[#f28c38] text-[#00152b]">App Oficial</span>
                <button onclick="dismissPwaBanner()" class="text-slate-400 hover:text-white p-1"><i class="fa-solid fa-xmark"></i></button>
            </div>
            <h4 class="font-extrabold text-sm text-white mt-1 truncate">Baixar App RE9 EMAIL</h4>
            <p class="text-xs text-slate-300 leading-snug">Instale o ícone direto no seu celular para acesso rápido em 1 toque.</p>
        </div>
    </div>
    <div id="iosInstallHint" class="hidden p-2.5 rounded-xl bg-white/10 text-xs text-slate-200 leading-relaxed">
        No iPhone: Toque no ícone <strong>Compartilhar</strong> <i class="fa-solid fa-arrow-up-from-bracket text-[#f28c38] mx-1"></i> abaixo e escolha <strong>"Adicionar à Tela de Início"</strong>.
    </div>
    <div class="flex items-center justify-end gap-2">
        <button onclick="dismissPwaBanner()" class="px-3 py-2 text-xs text-slate-300 hover:text-white font-semibold">Agora não</button>
        <button id="btnTriggerPwaInstall" onclick="triggerPwaInstall()" class="px-5 py-2.5 rounded-xl bg-[#f28c38] hover:bg-[#e07b27] text-[#00152b] font-extrabold text-xs flex items-center gap-1.5 shadow-lg">
            <i class="fa-solid fa-download"></i>
            <span>Baixar Aplicativo</span>
        </button>
    </div>
</div>

<?php if (!$is_logged): ?>
<!-- =========================================================================
     TELA DE LOGIN COM AUTO-CADASTRO E BOTÃO DE BAIXAR APP
     ========================================================================= -->
<div class="flex-1 flex items-center justify-center p-3 sm:p-4 bg-gradient-to-br from-[#00152b] via-[#002244] to-[#1e293b] overflow-y-auto">
    <div class="max-w-4xl w-full bg-white rounded-2xl shadow-2xl overflow-hidden flex flex-col md:flex-row my-auto border-t-4 border-[#f28c38]">
        <div class="w-full md:w-1/2 p-6 sm:p-8 lg:p-10 flex flex-col justify-center">
            <div class="mb-6 text-center md:text-left">
                <img src="<?php echo htmlspecialchars($logo_src, ENT_QUOTES, 'UTF-8'); ?>" referrerpolicy="strict-origin-when-cross-origin" alt="RE9 EMAIL" onerror="this.onerror=null;this.src='<?php echo htmlspecialchars((isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '/index.php') . '?pwa=logo_horizontal', ENT_QUOTES, 'UTF-8'); ?>';" class="h-14 object-contain mb-3 mx-auto md:mx-0 rounded-lg">
                <h1 class="text-2xl font-extrabold text-[#002244]"><?php echo htmlspecialchars($APP_CONFIG['brand_name']); ?></h1>
                <p class="text-sm text-slate-500">Acesse sua caixa de entrada corporativa protegida</p>
            </div>
            <form id="loginForm" class="space-y-4">
                <div>
                    <label class="block text-xs font-bold uppercase text-[#002244] mb-1">E-mail corporativo</label>
                    <div class="flex w-full overflow-hidden rounded-lg border border-slate-300 focus-within:border-[#475569] focus-within:ring-1 focus-within:ring-[#475569]">
                        <input type="text" id="loginEmailUser" name="email" required autocomplete="username" autocapitalize="none" spellcheck="false" inputmode="email" aria-label="Endereço completo de e-mail" placeholder="usuario@re9.rio.br ou usuario@seudominio.com.br"
                               class="min-w-0 flex-1 px-4 py-3.5 outline-none text-base sm:text-sm">
                    </div>
                </div>
                <div>
                    <label class="block text-xs font-bold uppercase text-[#002244] mb-1">Senha</label>
                    <input type="password" name="password" required placeholder="••••••••••••"
                           class="w-full px-4 py-3.5 rounded-lg border border-slate-300 focus:border-[#475569] outline-none text-base sm:text-sm">
                </div>
                <div id="loginError" class="hidden p-3 rounded-lg bg-red-50 border border-[#990000] text-[#990000] text-sm font-semibold"></div>
                <button type="submit" id="btnLogin" class="w-full py-3.5 rounded-lg btn-chrome text-base sm:text-sm flex items-center justify-center gap-2 shadow-lg">
                    <span>Acessar e-mail</span>
                    <i class="fa-solid fa-arrow-right"></i>
                </button>
            </form>
            <a href="<?php echo htmlspecialchars($_SERVER['SCRIPT_NAME'], ENT_QUOTES, 'UTF-8'); ?>?loja=1" class="mt-3 flex w-full items-center justify-center gap-2 rounded-xl border border-emerald-200 bg-emerald-50 px-4 py-3 text-sm font-extrabold text-emerald-800 hover:bg-emerald-100"><i class="fa-solid fa-store"></i>Conhecer a Loja RE9</a>

            <div class="mt-5 pt-4 border-t border-slate-200 flex flex-col items-center gap-2.5">
                <?php if (!empty($RE9_IS_CENTRAL_HUB)): ?>
                    <button type="button" onclick="openModal('createEmailModal')" aria-label="Criar e-mail grátis no domínio @re9.rio.br"
                            class="re9-create-mail-cta w-full py-3.5 px-5 rounded-xl bg-[#030b9c] hover:bg-[#00152b] text-white font-extrabold text-base flex items-center justify-center gap-2.5 shadow-lg">
                        <i class="fa-solid fa-user-plus text-[#ffd08a] text-lg shrink-0"></i>
                        <span class="re9-create-mail-copy">Crie seu e-mail grátis</span>
                        <strong class="re9-create-mail-domain">@re9.rio.br</strong>
                    </button>
                <?php else: ?>
                    <a href="https://re9.rio.br/webmail9/index.php" target="_blank" rel="noopener noreferrer"
                       aria-label="Acessar a Central Renove para criar e-mail grátis @re9.rio.br"
                       class="re9-create-mail-cta w-full py-3.5 px-5 rounded-xl bg-[#030b9c] hover:bg-[#00152b] text-white font-extrabold text-base flex items-center justify-center gap-2.5 shadow-lg">
                        <i class="fa-solid fa-user-plus text-[#ffd08a] text-lg shrink-0"></i>
                        <span class="re9-create-mail-copy">Crie seu e-mail grátis</span>
                        <strong class="re9-create-mail-domain">@re9.rio.br</strong>
                    </a>
                    <div class="w-full rounded-lg border border-amber-200 bg-amber-50 px-3 py-2.5 text-center text-xs leading-relaxed text-amber-950">
                        <strong>Contas @<?php echo htmlspecialchars($APP_CONFIG['domain_name'], ENT_QUOTES, 'UTF-8'); ?> são criadas somente mediante solicitação e autorização do suporte.</strong>
                        <a class="ml-1 inline-block font-extrabold underline text-[#002244]" href="mailto:suporte@re9.rio.br?subject=Solicita%C3%A7%C3%A3o%20de%20cria%C3%A7%C3%A3o%20de%20e-mail%20corporativo">Solicitar ao suporte</a>
                    </div>
                <?php endif; ?>
                <div class="flex items-center justify-between w-full text-xs pt-1">
                    <button type="button" onclick="openModal('recoverPasswordModal')"
                            class="text-slate-600 hover:text-[#990000] font-semibold">
                        <i class="fa-solid fa-key text-[#990000] mr-1"></i> Recuperar Senha
                    </button>
                    <button type="button" onclick="showInstallBannerManual()"
                            class="text-[#002244] hover:text-[#f28c38] font-bold flex items-center gap-1">
                        <i class="fa-solid fa-mobile-screen-button text-[#f28c38]"></i> Baixar App no Celular
                    </button>
                </div>
            </div>
        </div>

        <div class="w-full md:w-1/2 bg-[#00152b] text-white p-6 sm:p-8 lg:p-10 flex flex-col justify-between relative">
            <div>
                <span class="inline-block px-3 py-1 rounded bg-[#990000] text-white text-xs font-bold uppercase mb-3 tracking-wider">
                    <?php echo htmlspecialchars((string)agenda_value($random_initial_ad, 'badge', 'Anúncio'), ENT_QUOTES, 'UTF-8'); ?>
                </span>
                <?php if (!empty($random_initial_ad['image'])): ?>
                <img src="<?php echo htmlspecialchars($random_initial_ad['image'], ENT_QUOTES, 'UTF-8'); ?>" referrerpolicy="strict-origin-when-cross-origin" alt="Cartaz" class="w-full max-h-48 object-contain rounded-lg mb-4 bg-black/20">
                <?php endif; ?>
                <h2 class="text-xl font-bold mb-2 text-[#cbd5e1]"><?php echo htmlspecialchars($random_initial_ad['title']); ?></h2>
                <p class="text-slate-300 text-sm mb-5 leading-relaxed"><?php echo htmlspecialchars($random_initial_ad['description']); ?></p>
                <a href="<?php echo htmlspecialchars(re9_build_ad_target_url($random_initial_ad), ENT_QUOTES, 'UTF-8'); ?>" target="_blank"
                   class="inline-flex items-center gap-2 px-5 py-3 rounded-lg btn-chrome text-sm shadow">
                    <span><?php echo htmlspecialchars($random_initial_ad['cta_text']); ?></span>
                    <i class="fa-solid fa-up-right-from-square text-xs"></i>
                </a>
            </div>
            <div class="mt-6 pt-4 border-t border-white/10 text-xs text-slate-400 flex justify-between">
                <span><?php echo htmlspecialchars($random_initial_ad['sender']); ?></span>
                <span class="text-[#f28c38] font-semibold"><i class="fa-solid fa-shield-halved mr-1"></i>Robô Anti-Phishing Ativo</span>
            </div>
        </div>
    </div>
</div>

<?php if (!empty($RE9_IS_CENTRAL_HUB)): ?>
<!-- MODAL DE CRIAÇÃO GRATUITA EXCLUSIVO DA CENTRAL RE9 -->
<div id="createEmailModal" class="fixed inset-0 bg-slate-900/80 hidden items-center justify-center z-50 p-3 overflow-y-auto">
    <div class="bg-white w-full max-w-md rounded-2xl shadow-2xl p-5 sm:p-6 border-t-4 border-[#002244] my-auto">
        <div class="flex items-center justify-between pb-3 border-b mb-3">
            <h3 class="font-extrabold text-base text-[#002244] flex items-center gap-2">
                <i class="fa-solid fa-shield-halved text-[#990000]"></i>
                <span>Criar Conta @<?php echo htmlspecialchars($APP_CONFIG['domain_name']); ?></span>
            </h3>
            <button onclick="closeModal('createEmailModal')" class="text-slate-400 hover:text-slate-700 p-1"><i class="fa-solid fa-xmark text-lg"></i></button>
        </div>

        <form id="step1Form" onsubmit="submitStep1(event)" class="space-y-3.5 text-sm">
            <div>
                <label class="block font-bold text-[#002244] mb-1 text-xs uppercase">1. Nome completo (conforme cadastro oficial)</label>
                <input type="text" id="newEmailDisplayName" required maxlength="100" placeholder="Ex.: Maria Oliveira"
                       class="w-full p-2.5 border rounded-lg bg-white outline-none focus:border-[#002244] text-base sm:text-sm">
                <p class="mt-1 text-xs text-slate-500">O nome será conferido com o CPF na validação oficial.</p>
            </div>
            <div>
                <label class="block font-bold text-[#002244] mb-1 text-xs uppercase">2. Escolha seu Nome de E-mail</label>
                <div class="flex items-center">
                    <input type="text" id="newEmailUser" required placeholder="ex: comercial"
                           class="w-full p-2.5 border border-r-0 rounded-l-lg bg-white outline-none focus:border-[#002244] text-base sm:text-sm">
                    <span class="bg-slate-200 px-3 py-2.5 border border-l-0 rounded-r-lg text-[#002244] font-bold select-none text-sm">@<?php echo htmlspecialchars($APP_CONFIG['domain_name']); ?></span>
                </div>
            </div>

            <div>
                <label class="block font-bold text-[#002244] mb-1 text-xs uppercase">3. CPF</label>
                <input type="text" id="newEmailCpf" required inputmode="numeric" autocomplete="off" maxlength="14" placeholder="000.000.000-00"
                       class="w-full p-2.5 border rounded-lg bg-white outline-none focus:border-[#002244] text-base sm:text-sm">
            </div>

            <div>
                <label class="block font-bold text-[#002244] mb-1 text-xs uppercase">4. Seu Celular / WhatsApp com DDD</label>
                <input type="tel" id="newEmailPhone" required inputmode="tel" placeholder="21986297787" maxlength="11"
                       class="w-full p-2.5 border rounded-lg bg-white outline-none focus:border-[#002244] text-base sm:text-sm">
                <p class="text-[11px] text-slate-500 mt-0.5">O código confirma que você tem acesso a este número. Limite de 1 conta por telefone e por CPF.</p>
            </div>

            <div>
                <label class="block font-bold text-[#002244] mb-1 text-xs uppercase">5. E-mail secundário para recuperação</label>
                <input type="email" id="newEmailRecovery" required autocomplete="email" placeholder="seunome@gmail.com ou@hotmail.com" class="w-full p-2.5 border rounded-lg bg-white outline-none focus:border-[#002244] text-base sm:text-sm">
                <p class="text-[11px] text-slate-500 mt-0.5">Use um Gmail, Hotmail ou outro e-mail externo ao RE9. É nele que enviaremos o link para criar uma nova senha.</p>
            </div>

            <div>
                <div class="flex items-center justify-between mb-1">
                    <label class="font-bold text-[#002244] text-xs uppercase">6. Crie uma Senha Forte</label>
                    <button type="button" onclick="generateStrongPassword('newEmailPass')" class="text-[11px] font-bold text-[#990000] hover:underline">
                        <i class="fa-solid fa-wand-magic-sparkles"></i> Sugerir Senha Forte
                    </button>
                </div>
                <div class="relative">
                    <input type="text" id="newEmailPass" required placeholder="Ex: Re9@2026Forte"
                           oninput="checkPasswordRules(this.value, 'reg')"
                           class="w-full p-2.5 border rounded-lg bg-white outline-none focus:border-[#002244] text-base sm:text-sm font-mono">
                </div>

                <div class="mt-2 p-2.5 rounded-lg bg-slate-50 border border-slate-200 text-[11px] space-y-1">
                    <div class="font-bold text-slate-700 mb-1">Requisitos para aprovação imediata:</div>
                    <div id="reg_rule_len" class="text-slate-500 flex items-center gap-1.5"><i class="fa-regular fa-circle"></i> Mínimo de 8 caracteres</div>
                    <div id="reg_rule_case" class="text-slate-500 flex items-center gap-1.5"><i class="fa-regular fa-circle"></i> Letras MAIÚSCULAS e minúsculas</div>
                    <div id="reg_rule_num" class="text-slate-500 flex items-center gap-1.5"><i class="fa-regular fa-circle"></i> Pelo menos 1 número (0-9)</div>
                    <div id="reg_rule_sym" class="text-slate-500 flex items-center gap-1.5"><i class="fa-regular fa-circle"></i> Pelo menos 1 símbolo (@ # $ % ! & *)</div>
                </div>
            </div>

            <label class="flex items-start gap-2 text-xs text-slate-600"><input type="checkbox" id="newEmailConsent" required class="mt-0.5"><span>Autorizo o uso do meu nome, CPF e telefone para prevenção a fraudes e conferência manual da conta RE9. Entendo que o cálculo do CPF não comprova titularidade e que o telefone será conferido pela equipe.</span></label>
            <div id="step1Msg" class="hidden p-3 rounded-lg text-xs font-semibold"></div>

            <div class="pt-2 border-t flex justify-end gap-2">
                <button type="button" onclick="closeModal('createEmailModal')" class="px-4 py-2.5 text-slate-600 font-semibold">Cancelar</button>
                <button type="submit" id="btnSendCode" class="px-5 py-2.5 btn-chrome rounded-lg shadow text-sm">
                    <span>Conferir CPF e continuar</span>
                    <i class="fa-solid fa-arrow-right ml-1"></i>
                </button>
            </div>
        </form>

        <form id="step2Form" onsubmit="submitStep2(event)" class="hidden space-y-4 text-sm">
            <div class="p-3 bg-slate-100 rounded-xl border border-slate-300 text-xs text-slate-700">
                <p class="font-bold text-[#002244] mb-1">CPF válido pelo cálculo • Telefone aguardando revisão</p>
                <p>Seu CPF passou pela verificação matemática dos dígitos. A conta será criada e ficará em modo de visualização até a equipe RE9 conversar com você e confirmar manualmente o telefone informado (<span id="displayPhone"></span>).</p>
            </div>


            <div id="step2Msg" class="hidden p-3 rounded-lg text-xs font-semibold"></div>

            <div class="pt-3 border-t flex justify-between items-center gap-2">
                <button type="button" onclick="backToStep1()" class="text-xs text-slate-500 hover:underline">← Corrigir dados</button>
                <button type="submit" id="btnConfirmCode" class="px-5 py-2.5 btn-chrome rounded-lg shadow text-sm">
                    <i class="fa-solid fa-check mr-1"></i> Criar minha caixa
                </button>
            </div>
        </form>
    </div>
</div>
<?php endif; // cadastro público disponível somente na Central Renove ?>

<!-- MODAL: RECUPERAR SENHA POR E-MAIL SECUNDÁRIO -->
<div id="recoverPasswordModal" class="fixed inset-0 bg-slate-900/80 hidden items-center justify-center z-50 p-3 overflow-y-auto">
    <div class="bg-white w-full max-w-md rounded-2xl shadow-2xl p-6 border-t-4 border-[#990000] my-auto">
        <div class="flex items-center justify-between pb-3 border-b mb-4">
            <h3 class="font-extrabold text-base text-[#002244] flex items-center gap-2"><i class="fa-solid fa-key text-[#990000]"></i><span>Recuperar Senha</span></h3>
            <button type="button" onclick="closeModal('recoverPasswordModal')" class="text-slate-400 hover:text-slate-700 p-1"><i class="fa-solid fa-xmark text-lg"></i></button>
        </div>
        <form id="recoverRequestForm" class="space-y-3 text-sm" onsubmit="requestPasswordRecovery(event)">
            <p class="text-slate-600">Informe sua conta RE9 e o e-mail secundário cadastrado. Enviaremos um link seguro para esse endereço.</p>
            <label class="block text-xs font-bold text-[#002244]">SUA CONTA RE9<input id="recoverAccountEmail" type="email" required placeholder="usuario@re9.rio.br" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-sm"></label>
            <label class="block text-xs font-bold text-[#002244]">E-MAIL SECUNDÁRIO<input id="recoverSecondaryEmail" type="email" required placeholder="seunome@gmail.com" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-sm"></label>
            <div id="recoverRequestMsg" class="hidden rounded-lg p-3 text-xs font-semibold"></div>
            <button id="recoverRequestBtn" type="submit" class="w-full rounded-xl bg-[#002244] py-3 font-bold text-white">Enviar link de recuperação</button>
        </form>
        <form id="recoverResetForm" class="hidden space-y-3 text-sm" onsubmit="submitPasswordRecovery(event)">
            <p class="text-slate-600">Crie sua nova senha. O link é válido por uma hora e só pode ser usado uma vez.</p>
            <label class="block text-xs font-bold text-[#002244]">NOVA SENHA<input id="recoverNewPass" type="password" required autocomplete="new-password" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-sm"></label>
            <label class="block text-xs font-bold text-[#002244]">CONFIRMAR NOVA SENHA<input id="recoverNewPassConfirm" type="password" required autocomplete="new-password" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-sm"></label>
            <div id="recoverResetMsg" class="hidden rounded-lg p-3 text-xs font-semibold"></div>
            <button id="recoverResetBtn" type="submit" class="w-full rounded-xl bg-emerald-700 py-3 font-bold text-white">Salvar nova senha e entrar</button>
        </form>
    </div>
</div>

<script>
function re9AnyModalVisible() {
    return Array.prototype.some.call(document.querySelectorAll('[id$="Modal"]'), function(m) {
        return !m.classList.contains('hidden');
    });
}
function re9SyncModalScrollLock() {
    if (re9AnyModalVisible()) document.body.classList.add('re9-modal-open');
    else document.body.classList.remove('re9-modal-open');
}
function openModal(id) {
    var el = document.getElementById(id);
    if (el) {
        el.classList.remove('hidden');
        el.classList.add('flex');
        re9SyncModalScrollLock();
        if (id === 'onlineUsersModal') {
            var closeBtn = el.querySelector('.re9-online-modal-close');
            if (closeBtn) closeBtn.focus({preventScroll:true});
        }
    }
}
function closeModal(id) {
    var el = document.getElementById(id);
    if (el) { el.classList.add('hidden'); el.classList.remove('flex'); }
    re9SyncModalScrollLock();
}
async function requestPasswordRecovery(event) {
    event.preventDefault();
    var btn=document.getElementById('recoverRequestBtn'), msg=document.getElementById('recoverRequestMsg');
    btn.disabled=true; btn.textContent='Enviando...'; msg.classList.add('hidden');
    var fd=new FormData(); fd.append('account_email',document.getElementById('recoverAccountEmail').value.trim()); fd.append('recovery_email',document.getElementById('recoverSecondaryEmail').value.trim());
    try { var r=await fetch('?api=password_recovery_request',{method:'POST',body:fd,credentials:'same-origin'}); var d=await r.json(); if(d.status!=='ok') throw new Error(d.msg||'Não foi possível solicitar a recuperação.'); msg.textContent=d.msg; msg.className='rounded-lg p-3 text-xs font-semibold bg-emerald-50 text-emerald-800'; msg.classList.remove('hidden'); }
    catch(e){msg.textContent=e.message;msg.className='rounded-lg p-3 text-xs font-semibold bg-red-50 text-red-700';msg.classList.remove('hidden');}
    finally{btn.disabled=false;btn.textContent='Enviar link de recuperação';}
}
async function submitPasswordRecovery(event) {
    event.preventDefault();
    var p=document.getElementById('recoverNewPass').value, c=document.getElementById('recoverNewPassConfirm').value;
    var msg=document.getElementById('recoverResetMsg'), btn=document.getElementById('recoverResetBtn');
    if(p!==c){msg.textContent='As senhas não conferem.';msg.className='rounded-lg p-3 text-xs font-semibold bg-red-50 text-red-700';msg.classList.remove('hidden');return;}
    btn.disabled=true;btn.textContent='Salvando senha...';msg.classList.add('hidden');
    var fd=new FormData();fd.append('token',new URLSearchParams(window.location.search).get('reset_password')||'');fd.append('new_pass',p);
    try{var r=await fetch('?api=password_recovery_reset',{method:'POST',body:fd,credentials:'same-origin'});var d=await r.json();if(d.status!=='ok')throw new Error(d.msg||'Não foi possível alterar a senha.');msg.textContent=d.msg;msg.className='rounded-lg p-3 text-xs font-semibold bg-emerald-50 text-emerald-800';msg.classList.remove('hidden');setTimeout(function(){window.location.href=window.location.pathname;},1400);}
    catch(e){msg.textContent=e.message;msg.className='rounded-lg p-3 text-xs font-semibold bg-red-50 text-red-700';msg.classList.remove('hidden');btn.disabled=false;btn.textContent='Salvar nova senha e entrar';}
}

(function(){var params=new URLSearchParams(window.location.search);if(params.has('reset_password')){var request=document.getElementById('recoverRequestForm'),reset=document.getElementById('recoverResetForm');if(request)request.classList.add('hidden');if(reset)reset.classList.remove('hidden');openModal('recoverPasswordModal');}})();

function checkPasswordRules(val, prefix) {
    var hasLen  = val.length >= 8;
    var hasCase = /[A-Z]/.test(val) && /[a-z]/.test(val);
    var hasNum  = /[0-9]/.test(val);
    var hasSym  = /[^a-zA-Z0-9]/.test(val);

    setRuleState(prefix + '_rule_len', hasLen, 'Mínimo de 8 caracteres');
    setRuleState(prefix + '_rule_case', hasCase, 'Letras MAIÚSCULAS e minúsculas');
    setRuleState(prefix + '_rule_num', hasNum, 'Pelo menos 1 número (0-9)');
    setRuleState(prefix + '_rule_sym', hasSym, 'Pelo menos 1 símbolo (@ # $ % ! & *)');

    return hasLen && hasCase && hasNum && hasSym;
}

function setRuleState(elId, ok, text) {
    var el = document.getElementById(elId);
    if (!el) return;
    if (ok) {
        el.className = 'text-emerald-700 font-bold flex items-center gap-1.5';
        el.innerHTML = '<i class="fa-solid fa-circle-check text-emerald-600"></i> ' + text;
    } else {
        el.className = 'text-slate-500 flex items-center gap-1.5';
        el.innerHTML = '<i class="fa-regular fa-circle"></i> ' + text;
    }
}

function generateStrongPassword(inputId) {
    var upper = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
    var lower = 'abcdefghijkmnpqrstuvwxyz';
    var nums  = '23456789';
    var syms  = '@#$%!&*';
    var pass  = '';
    pass += upper.charAt(Math.floor(Math.random() * upper.length));
    pass += upper.charAt(Math.floor(Math.random() * upper.length));
    pass += lower.charAt(Math.floor(Math.random() * lower.length));
    pass += lower.charAt(Math.floor(Math.random() * lower.length));
    pass += lower.charAt(Math.floor(Math.random() * lower.length));
    pass += syms.charAt(Math.floor(Math.random() * syms.length));
    pass += nums.charAt(Math.floor(Math.random() * nums.length));
    pass += nums.charAt(Math.floor(Math.random() * nums.length));
    pass += nums.charAt(Math.floor(Math.random() * nums.length));

    var inp = document.getElementById(inputId);
    if (inp) {
        inp.value = pass;
        checkPasswordRules(pass, 'reg');
    }
}

var re9AfterLoginUrl = <?php echo json_encode(!empty($_SESSION['re9_shop_return']) ? $_SESSION['re9_shop_return'] : ''); ?>;

document.getElementById('loginForm').addEventListener('submit', async function(e) {
    e.preventDefault();
    var btn = document.getElementById('btnLogin');
    var err = document.getElementById('loginError');
    err.classList.add('hidden');
    btn.disabled = true;
    btn.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i> Autenticando...';
    try {
        var loginUserField = document.getElementById('loginEmailUser');
        var defaultLoginDomain = <?php echo json_encode('@' . get_val($APP_CONFIG, 'domain_name', 're9.rio.br')); ?>;
        var loginUser = (loginUserField.value || '').trim().toLowerCase();
        // Identifica automaticamente o domínio pelo endereço informado. O atalho sem
        // domínio continua exclusivo do domínio RE9; os demais usam o e-mail completo.
        if (loginUser.indexOf('@') < 0) {
            loginUser = loginUser + defaultLoginDomain.toLowerCase();
        }
        if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(loginUser) || loginUser.length > 254) {
            throw new Error('Informe um endereço de e-mail válido. Use o domínio completo da sua caixa corporativa.');
        }
        loginUserField.value = loginUser;
        var res = await fetch('?api=login', { method: 'POST', body: new FormData(e.target), credentials:'same-origin', cache:'no-store' });
        var data = await res.json();
        if (data.status === 'ok') { window.location.href = re9AfterLoginUrl || window.location.href; }
        else {
            err.textContent = data.msg || 'Erro de login.';
            err.classList.remove('hidden');
            btn.disabled = false;
            btn.innerHTML = '<span>Acessar Webmail</span><i class="fa-solid fa-arrow-right"></i>';
        }
    } catch (ex) {
        var loginUserField = document.getElementById('loginEmailUser');
        err.textContent = ex && ex.message ? ex.message : 'Erro de comunicação com o servidor.';
        err.classList.remove('hidden');
        btn.disabled = false;
    }
});

async function submitStep1(e) {
    e.preventDefault();
    var btn = document.getElementById('btnSendCode');
    var msg = document.getElementById('step1Msg');
    var user = document.getElementById('newEmailUser').value.trim();
    var displayName = document.getElementById('newEmailDisplayName').value.trim();
    var pass = document.getElementById('newEmailPass').value;
    var phone = document.getElementById('newEmailPhone').value.trim();
    var recoveryEmail = document.getElementById('newEmailRecovery').value.trim();
    var cpf = document.getElementById('newEmailCpf').value.replace(/\D/g, '');
    var consent = document.getElementById('newEmailConsent').checked;

    if (cpf.length !== 11) {
        msg.textContent = 'Informe um CPF com 11 números.';
        msg.className = 'p-3 rounded-lg text-xs font-bold bg-red-50 text-red-600 border border-red-200';
        msg.classList.remove('hidden');
        return;
    }
    if (!consent) {
        msg.textContent = 'Autorize a validação dos dados para continuar.';
        msg.className = 'p-3 rounded-lg text-xs font-bold bg-red-50 text-red-600 border border-red-200';
        msg.classList.remove('hidden');
        return;
    }
    if (!checkPasswordRules(pass, 'reg')) {
        msg.textContent = 'Por favor, atenda a todos os itens da Senha Forte acima (ou clique em "Sugerir Senha Forte").';
        msg.className = 'p-3 rounded-lg text-xs font-bold bg-red-50 text-red-600 border border-red-200';
        msg.classList.remove('hidden');
        return;
    }

    btn.disabled = true;
    btn.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i> Validando CPF e nome...';
    msg.classList.add('hidden');

    var fd = new FormData();
    fd.append('new_user', user);
    fd.append('display_name', displayName);
    fd.append('new_pass', pass);
    fd.append('new_phone', phone);
    fd.append('recovery_email', recoveryEmail);
    fd.append('new_cpf', cpf);
    fd.append('identity_consent', consent ? '1' : '0');

    try {
        var res = await fetch('?api=request_email_code', { method: 'POST', body: fd });
        var data = await res.json();
        btn.disabled = false;
        btn.innerHTML = '<span>Conferir CPF e continuar</span><i class="fa-solid fa-arrow-right ml-1"></i>';

        if (data.status === 'ok') {
            document.getElementById('displayPhone').textContent = phone;
            document.getElementById('step1Form').classList.add('hidden');
            document.getElementById('step2Form').classList.remove('hidden');
        } else {
            msg.textContent = data.msg || 'Erro ao validar celular.';
            msg.className = 'p-3 rounded-lg text-xs font-bold bg-red-50 text-red-600 border border-red-200';
            msg.classList.remove('hidden');
        }
    } catch(ex) {
        btn.disabled = false;
        btn.innerHTML = '<span>Conferir CPF e continuar</span><i class="fa-solid fa-arrow-right ml-1"></i>';
        msg.textContent = 'Erro de conexão.';
        msg.classList.remove('hidden');
    }
}

async function submitStep2(e) {
    e.preventDefault();
    var btn = document.getElementById('btnConfirmCode');
    var msg = document.getElementById('step2Msg');
    btn.disabled = true; btn.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i> Criando caixa...'; msg.classList.add('hidden');
    var fd = new FormData();
    try {
        var res = await fetch('?api=confirm_email_code', { method: 'POST', body: fd, credentials:'same-origin' });
        var data = await res.json();
        if (data.status === 'ok') {
            msg.textContent = data.msg || ('Conta ' + data.email + ' criada. Aguarde a conferência manual.');
            msg.className = 'p-3 rounded-lg text-xs font-bold bg-amber-50 text-amber-800 border border-amber-300'; msg.classList.remove('hidden');
            setTimeout(function() { window.location.href = re9AfterLoginUrl || window.location.href; }, 1200);
        } else { throw new Error(data.msg || 'Não foi possível criar a caixa.'); }
    } catch(ex) {
        btn.disabled = false; btn.innerHTML = '<i class="fa-solid fa-check mr-1"></i> Criar minha caixa';
        msg.textContent = ex.message || 'Erro de comunicação.'; msg.className = 'p-3 rounded-lg text-xs font-bold bg-red-50 text-red-600 border border-red-300'; msg.classList.remove('hidden');
    }
}

function backToStep1() {
    document.getElementById('step2Form').classList.add('hidden');
    document.getElementById('step1Form').classList.remove('hidden');
}
</script>

<?php else: ?>
<!-- =========================================================================
     ÁREA LOGADA DO WEBMAIL (COM MINI-CARDS DE ANÚNCIO, IMPORTADOR EXTERNO E ROBÔ)
     ========================================================================= -->
<div id="newMailToast" onclick="loadEmails('INBOX'); hideToast();"
     class="fixed top-16 right-3 z-50 hidden cursor-pointer bg-[#00152b] text-white border-l-4 border-[#475569] px-4 py-3.5 rounded-xl shadow-2xl items-center gap-3 max-w-xs sm:max-w-sm animate-bounce">
    <div class="w-10 h-10 rounded-full bg-[#990000] text-white flex items-center justify-center shrink-0 font-bold text-base unread-badge-pulse">
        <i class="fa-solid fa-bell"></i>
    </div>
    <div class="flex-1 min-w-0">
        <div class="font-extrabold text-xs text-[#cbd5e1] uppercase tracking-wider">Chegou Nova Mensagem!</div>
        <div id="toastSender" class="text-sm font-bold truncate">Remetente</div>
        <div id="toastSubject" class="text-xs text-slate-300 truncate">Assunto</div>
    </div>
    <button onclick="event.stopPropagation(); hideToast();" class="text-slate-400 hover:text-white p-1">
        <i class="fa-solid fa-xmark"></i>
    </button>
</div>

<!-- TOPO DO WEBMAIL -->
<header id="re9FixedTopBar" class="min-h-[5.5rem] h-auto bg-navy text-white px-2.5 sm:px-5 py-2 flex flex-wrap items-center justify-between gap-y-2 shadow-lg border-b-2 border-[#475569] z-[80] shrink-0" style="position:sticky;top:0;">
    <div class="flex items-center gap-2 sm:gap-4">
        <button onclick="toggleMobileSidebar()" class="p-2.5 rounded-lg bg-white/10 hover:bg-white/20 text-white relative" title="Menu de Pastas">
            <i class="fa-solid fa-bars text-lg"></i>
            <span id="mobileMenuUnreadDot" class="hidden absolute -top-1 -right-1 w-5 h-5 rounded-full bg-[#990000] text-white text-[10px] font-bold flex items-center justify-center">0</span>
        </button>

        <div class="flex items-center gap-2 min-w-0">
            <img id="topHeaderLogo" src="<?php echo htmlspecialchars($logo_src, ENT_QUOTES, 'UTF-8'); ?>" referrerpolicy="strict-origin-when-cross-origin" alt="Logomarca" onerror="this.onerror=null;this.src='<?php echo htmlspecialchars((isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '/index.php') . '?pwa=logo_horizontal', ENT_QUOTES, 'UTF-8'); ?>';"
                 class="h-9 sm:h-11 max-w-[125px] sm:max-w-[200px] object-contain bg-white/5 px-1.5 py-0.5 rounded-lg border border-white/10">
            <div class="re9-top-date-time" aria-label="Data e hora de Brasília">
                <span id="re9LiveDate" class="font-semibold capitalize">Carregando data...</span>
                <span class="re9-top-clock-time font-extrabold tabular-nums" id="re9LiveTime">--:--:--</span>
            </div>
        </div>
    </div>

    <div class="flex items-center gap-1.5 sm:gap-2.5">
        <button onclick="openComposeModal()" class="px-2.5 sm:px-3.5 py-2 rounded-lg btn-chrome text-xs sm:text-sm font-bold flex items-center gap-1.5 shadow whitespace-nowrap">
            <i class="fa-solid fa-pen-to-square text-white"></i>
            <span>Enviar</span>
        </button>

        <button onclick="loadEmails('INBOX')" title="Mensagens Não Lidas"
                class="relative px-2.5 sm:px-3 py-2 rounded-lg bg-white/10 hover:bg-white/20 text-xs sm:text-sm flex items-center gap-1.5 transition">
            <i class="fa-regular fa-envelope text-[#cbd5e1]"></i>
            <span id="topUnreadBadge" class="hidden px-1.5 py-0.5 rounded-full bg-[#990000] text-white font-extrabold text-xs unread-badge-pulse">0</span>
        </button>

        <div class="hidden xl:flex flex-col items-end justify-center gap-0.5 bg-black/25 px-3 py-1.5 rounded-lg border border-white/10 max-w-[270px] min-w-0" aria-label="Conta conectada">
            <span class="flex items-center gap-1.5 text-[12px] font-extrabold leading-tight text-white truncate max-w-full">
                <i class="fa-regular fa-circle-user text-[#f8a45f] shrink-0"></i>
                <span class="truncate">Olá, <?php echo htmlspecialchars($logged_user_first_name, ENT_QUOTES, 'UTF-8'); ?></span>
            </span>
            <span class="flex items-center gap-1 text-[11px] font-semibold leading-tight text-slate-300 truncate max-w-full" title="<?php echo htmlspecialchars($_SESSION['wm_email'], ENT_QUOTES, 'UTF-8'); ?>">
                <i class="fa-regular fa-envelope shrink-0"></i>
                <span class="truncate"><?php echo htmlspecialchars($_SESSION['wm_email'], ENT_QUOTES, 'UTF-8'); ?></span>
            </span>
        </div>
    </div>

    <!-- FAIXA DE NOTÍCIAS COM LARGURA AMPLIADA; DATA/HORA AO LADO DA LOGOMARCA -->
    <div class="w-full flex items-center gap-2 border-t border-white/15 pt-2 text-sm sm:text-base min-w-0">
        <div class="flex items-center gap-2 min-w-0 flex-1 overflow-hidden rounded-md bg-black/15 px-3 py-2 text-sm sm:text-base">
            <span class="shrink-0 text-orange-300" aria-label="Notícias" title="Notícias"><i class="fa-solid fa-newspaper"></i></span>
            <div class="re9-news-window min-w-0 flex-1 overflow-hidden" aria-label="Principais notícias">
                <div class="re9-news-track" id="re9NewsTrack">
                    <a href="https://loqueestapasando.com/pt/pais/brasil/" target="_blank" rel="noopener noreferrer">Brasil e mundo: acompanhe as principais notícias deste sábado</a>
                    <span class="re9-news-separator">✦</span>
                    <a href="https://noticias.uol.com.br/ultimas-noticias/redacao/2026/11/13/senado-aprova-projeto-do-governo-para-cortar-gastos-e-poupar-ate-r-60-bilhoes.ghtm" target="_blank" rel="noopener noreferrer">Senado aprova texto-base de pacote de ajuste fiscal</a>
                    <span class="re9-news-separator">✦</span>
                    <a href="https://loqueestapasando.com/pt/pais/brasil/" target="_blank" rel="noopener noreferrer">Enem: orientações e cuidados para o segundo dia de provas</a>
                    <span class="re9-news-separator">✦</span>
                    <a href="https://loqueestapasando.com/pt/pais/brasil/" target="_blank" rel="noopener noreferrer">Acompanhe as atualizações sobre voos e transporte internacional</a>
                    <span class="re9-news-separator">✦</span>
                    <a href="https://loqueestapasando.com/pt/pais/brasil/" target="_blank" rel="noopener noreferrer">Brasil x Japão: notícias e cobertura do amistoso da Seleção</a>
                    <span class="re9-news-separator">✦</span>
                </div>
            </div>
        </div>
    </div>
    <style>
      @keyframes re9NewsScroll { from { transform:translateX(0); } to { transform:translateX(-50%); } }
      .re9-news-track { display:flex; align-items:center; width:max-content; white-space:nowrap; gap:1.5rem; animation:re9NewsScroll 95s linear infinite; }
      .re9-news-track a { color:#f8fafc; text-decoration:none; transition:color .2s; }
      .re9-news-track a:hover { color:#fdba74; text-decoration:underline; }
      .re9-news-separator { color:#f28c38; }
      .re9-news-window:hover .re9-news-track, .re9-news-window:focus-within .re9-news-track { animation-play-state:paused; }
      @media (prefers-reduced-motion: reduce) { .re9-news-track { animation:none; white-space:normal; flex-wrap:wrap; } }
    </style>
    <script>
      (function(){
        var dateEl=document.getElementById('re9LiveDate');
        var timeEl=document.getElementById('re9LiveTime');
        var newsTrack=document.getElementById('re9NewsTrack');
        if(newsTrack && !newsTrack.getAttribute('data-loop-ready')){newsTrack.innerHTML += newsTrack.innerHTML;newsTrack.setAttribute('data-loop-ready','1');}
        function updateRe9Clock(){
          var now=new Date();
          try {
            var isCompactDate = window.matchMedia && window.matchMedia('(max-width: 767px)').matches;
            var dateOptions = isCompactDate
              ? {timeZone:'America/Sao_Paulo',weekday:'short',day:'2-digit',month:'2-digit',year:'2-digit'}
              : {timeZone:'America/Sao_Paulo',weekday:'long',day:'2-digit',month:'long',year:'numeric'};
            dateEl.textContent=new Intl.DateTimeFormat('pt-BR',dateOptions).format(now);
            timeEl.textContent=new Intl.DateTimeFormat('pt-BR',{timeZone:'America/Sao_Paulo',hour:'2-digit',minute:'2-digit',second:'2-digit',hour12:false}).format(now);
          } catch(e) {
            dateEl.textContent=now.toLocaleDateString('pt-BR');
            timeEl.textContent=now.toLocaleTimeString('pt-BR');
          }
        }
        updateRe9Clock();
        window.setInterval(updateRe9Clock,1000);
      })();
    </script>
</header>

<!-- CORPO PRINCIPAL COM COMPRIMENTO EXPANDIDO PARA EXIBIR O CARD PUBLICITÁRIO INTEIRO -->
<div id="re9WorkArea" class="flex-1 flex relative min-h-[820px]">

    <div id="mobileDrawerBackdrop" onclick="toggleMobileSidebar()" class="fixed inset-0 bg-black/60 z-30 hidden"></div>

    <!-- 1. MENU LATERAL ESQUERDO COMPACTO -->
    <aside id="folderSidebar"
           class="fixed top-0 bottom-0 left-0 z-40 w-72 max-w-[88vw] h-screen max-h-screen bg-navy-dark text-slate-200 flex flex-col justify-start p-3.5 transform -translate-x-full transition-transform duration-200 ease-in-out border-r border-white/10 shadow-2xl overflow-y-auto overscroll-y-contain"
           style="height:calc(100dvh - var(--re9-header-height));overflow-y:scroll;overscroll-behavior-y:contain;-webkit-overflow-scrolling:touch;touch-action:pan-y;">
        
        <div class="flex items-center justify-between pb-2.5 mb-2 border-b border-white/10 shrink-0">
            <span class="text-xs font-extrabold text-[#cbd5e1] uppercase tracking-wider flex items-center gap-2">
                <i class="fa-solid fa-folder-open text-[#475569]"></i> Menu & Pastas
            </span>
            <button onclick="toggleMobileSidebar()" class="text-slate-400 hover:text-white px-2.5 py-1 rounded-lg bg-white/10">
                <i class="fa-solid fa-xmark text-sm"></i>
            </button>
        </div>

        <div class="mb-3 shrink-0 rounded-xl border border-white/10 bg-white/[0.06] p-2.5">
            <p class="px-2 pb-2 text-[11px] font-extrabold uppercase tracking-wider text-slate-400">Acesso rápido</p>
            <button onclick="closeMobileSidebar(); openAgendaModal();"
                    class="w-full flex items-center gap-3 rounded-lg px-3 py-3 text-left text-[15px] font-semibold text-white transition hover:bg-white/10">
                <span class="flex h-9 w-9 items-center justify-center rounded-lg bg-[#f28c38]/15 text-[#f8a45f]"><i class="fa-regular fa-calendar-check"></i></span>
                <span>Agenda</span><i class="fa-solid fa-chevron-right ml-auto text-xs text-slate-500"></i>
            </button>
            <button onclick="closeMobileSidebar(); openContactsModal();"
                    class="w-full flex items-center gap-3 rounded-lg px-3 py-3 text-left text-[15px] font-semibold text-white transition hover:bg-white/10">
                <span class="flex h-9 w-9 items-center justify-center rounded-lg bg-white/10 text-slate-200"><i class="fa-solid fa-address-book"></i></span>
                <span>Contatos</span>
                <span id="privateUnreadContactsBadge" class="hidden ml-auto min-w-6 rounded-full bg-[#b91c1c] px-2 py-0.5 text-center text-[11px] font-black text-white shadow-lg" aria-label="Mensagens privadas não lidas">0</span>
                <i class="fa-solid fa-chevron-right text-xs text-slate-500"></i>
            </button>
            <button id="privateMessagesQuickLink" onclick="closeMobileSidebar(); openPrivateMessagesFromMenu();"
                    class="w-full flex items-center gap-3 rounded-lg px-3 py-3 text-left text-[15px] font-semibold text-white transition hover:bg-white/10">
                <span class="flex h-9 w-9 items-center justify-center rounded-lg bg-[#990000]/25 text-red-200"><i class="fa-solid fa-message"></i></span>
                <span>Mensagens privadas</span>
                <span id="privateUnreadMenuBadge" class="hidden ml-auto min-w-6 rounded-full bg-[#b91c1c] px-2 py-0.5 text-center text-[11px] font-black text-white shadow-lg" aria-label="Mensagens privadas não lidas">0</span>
                <i class="fa-solid fa-chevron-right text-xs text-slate-500"></i>
            </button>
            <a href="<?php echo htmlspecialchars($_SERVER['SCRIPT_NAME'], ENT_QUOTES, 'UTF-8'); ?>?loja=1"
               class="w-full flex items-center gap-3 rounded-lg px-3 py-3 text-left text-[15px] font-semibold text-white transition hover:bg-white/10">
                <span class="flex h-9 w-9 items-center justify-center rounded-lg bg-emerald-500/15 text-emerald-300"><i class="fa-solid fa-store"></i></span>
                <span>Loja RE9</span><i class="fa-solid fa-arrow-up-right-from-square ml-auto text-xs text-slate-500"></i>
            </a>
        </div>

        <nav class="space-y-1 text-sm shrink-0 pb-2">
            <button onclick="loadEmails('INBOX', this, 'CAIXA DE ENTRADA')"
                    class="folder-btn w-full flex items-center justify-between px-3 py-2.5 rounded-xl bg-[#002244] border-l-4 border-[#475569] text-white font-semibold transition">
                <span class="flex items-center gap-2.5 whitespace-nowrap">
                    <i class="fa-solid fa-inbox text-[#cbd5e1] w-4 text-center"></i>
                    <span>Caixa de Entrada</span>
                </span>
                <div class="flex items-center gap-1 shrink-0 ml-1">
                    <span id="unreadRedBall" class="hidden px-1.5 py-0.5 rounded-full bg-[#990000] text-white font-extrabold text-[11px] shadow unread-badge-pulse">0</span>
                    <span id="badgeCount" class="text-[11px] bg-white/10 text-slate-300 px-1.5 py-0.5 rounded">0</span>
                </div>
            </button>

            <button onclick="loadEmails('INBOX.Sent', this, 'ENVIADOS')"
                    class="folder-btn w-full flex items-center gap-2.5 px-3 py-2.5 rounded-xl hover:bg-white/5 transition whitespace-nowrap">
                <i class="fa-regular fa-paper-plane text-[#cbd5e1] w-4 text-center"></i>
                <span>Enviados</span>
            </button>

            <button onclick="loadEmails('INBOX.Drafts', this, 'RASCUNHOS')"
                    class="folder-btn w-full flex items-center gap-2.5 px-3 py-2.5 rounded-xl hover:bg-white/5 transition whitespace-nowrap">
                <i class="fa-regular fa-file-lines text-[#cbd5e1] w-4 text-center"></i>
                <span>Rascunhos</span>
            </button>

            <button onclick="loadEmails('INBOX.spam', this, 'SPAM / LIXO')"
                    class="folder-btn w-full flex items-center gap-2.5 px-3 py-2.5 rounded-xl hover:bg-white/5 transition whitespace-nowrap">
                <i class="fa-solid fa-shield-halved text-[#990000] w-4 text-center"></i>
                <span>Spam</span>
            </button>

            <button onclick="loadEmails('INBOX.Trash', this, 'LIXEIRA')"
                    class="folder-btn w-full flex items-center gap-2.5 px-3 py-2.5 rounded-xl hover:bg-white/5 transition whitespace-nowrap">
                <i class="fa-regular fa-trash-can text-[#990000] w-4 text-center"></i>
                <span>Lixeira</span>
            </button>
        </nav>

        <div class="shrink-0 border-t border-white/15 pt-3 mt-3 space-y-2 text-xs">
            <div class="px-3 py-2 rounded-lg bg-black/30 text-[#cbd5e1] truncate flex items-center gap-2 border border-white/5">
                <i class="fa-regular fa-circle-user shrink-0"></i>
                <span class="truncate"><?php echo htmlspecialchars($_SESSION['wm_email']); ?></span>
            </div>

            <button onclick="closeMobileSidebar(); openModal('extAccountsModal');"
                    class="w-full text-left px-3 py-2.5 rounded-xl bg-blue-500/20 border border-blue-400/30 hover:bg-blue-500/30 text-white font-bold flex items-center gap-2.5 transition">
                <i class="fa-solid fa-cloud-arrow-down text-[#f28c38] w-4 text-center"></i>
                <span>Conectar E-mails</span>
            </button>

            <button onclick="closeMobileSidebar(); openModal('sigModal');"
                    class="w-full text-left px-3 py-2.5 rounded-xl bg-white/10 hover:bg-white/15 text-white font-semibold flex items-center gap-2.5 transition">
                <i class="fa-solid fa-id-card text-[#f28c38] w-4 text-center"></i>
                <span>Pesonalizar Assinatura</span>
            </button>

            <?php if ($is_admin): ?>
            <button onclick="closeMobileSidebar(); openModal('onlineUsersModal'); refreshOnlineUsers();"
                    class="w-full text-left px-3 py-2.5 rounded-xl bg-emerald-600/20 border border-emerald-500/30 hover:bg-emerald-600/30 text-white font-semibold flex items-center gap-2.5 transition">
                <i class="fa-solid fa-users text-emerald-300 w-4 text-center"></i>
                <span>Usuários on-line (<?php echo (int)$initial_vps_data['online_count']; ?>)</span>
            </button>
            <button onclick="closeMobileSidebar(); openModal('brandModal');"
                    class="w-full text-left px-3 py-2.5 rounded-xl bg-red-700/20 border border-red-500/30 hover:bg-red-700/30 text-white font-semibold flex items-center gap-2.5 transition">
                <i class="fa-solid fa-sliders text-red-300 w-4 text-center"></i>
                <span>Administração / Anúncios</span>
            </button>
            <?php endif; ?>

            <button onclick="closeMobileSidebar(); showInstallBannerManual();"
                    class="w-full text-left px-3 py-2.5 rounded-xl bg-[#f28c38]/20 border border-[#f28c38]/40 hover:bg-[#f28c38]/30 text-[#f28c38] font-bold flex items-center gap-2.5 transition">
                <i class="fa-solid fa-mobile-screen-button w-4 text-center"></i>
                <span>Instalar App</span>
            </button>

            <button onclick="closeMobileSidebar(); openModal('changePasswordModal');"
                    class="w-full text-left px-3 py-2.5 rounded-xl bg-white/10 hover:bg-white/15 text-white font-semibold flex items-center gap-2.5 transition">
                <i class="fa-solid fa-key text-[#cbd5e1] w-4 text-center"></i>
                <span>Trocar Senha</span>
            </button>

            <button onclick="logoutWebmail()"
                    class="w-full text-left px-3 py-2.5 rounded-xl btn-blood font-bold flex items-center gap-2.5 shadow transition">
                <i class="fa-solid fa-power-off w-4 text-center"></i>
                <span>Sair do Webmail</span>
            </button>
        </div>
    </aside>

    <!-- 2. COLUNA DE MENSAGENS COM MINI-CARDS DE ANÚNCIOS PATROCINADOS COM AÇÃO COMPRAR -->
    <section id="emailListSection" class="w-full md:w-96 lg:w-[420px] bg-white border-r border-slate-200 flex flex-col shrink-0 transition-all duration-200">
        <div class="px-4 py-3 border-b border-slate-200 flex items-center justify-between bg-slate-50 text-xs sm:text-sm font-extrabold text-[#002244]">
            <div class="flex items-center gap-2">
                <span id="currentFolderTitle">CAIXA DE ENTRADA</span>
                <span id="mobileInlineUnread" class="hidden px-2 py-0.5 rounded-full bg-[#990000] text-white text-xs font-bold">0 novas</span>
            </div>
            <div class="flex items-center gap-1.5">
                <button onclick="loadEmails(currentFolder)" title="Sincronizar agora" class="hover:text-[#475569] p-1">
                    <i id="refreshIcon" class="fa-solid fa-rotate text-base"></i>
                </button>
            </div>
        </div>

        <div class="px-3.5 py-2.5 bg-slate-100 border-b border-slate-200 flex items-center justify-between text-xs sm:text-sm">
            <label class="flex items-center gap-2.5 cursor-pointer font-bold text-slate-700">
                <input type="checkbox" id="selectAllCheckbox" onchange="toggleSelectAll(this)" class="w-4 h-4 rounded text-[#475569] focus:ring-0 cursor-pointer">
                <span>Selecionar Todas</span>
            </label>

            <div id="batchActionArea">
                <button id="btnDeleteSelected" onclick="deleteSelectedEmails()" class="hidden px-3 py-1.5 bg-red-600 hover:bg-red-700 text-white rounded-lg font-bold text-xs shadow-sm flex items-center gap-1.5">
                    <i class="fa-regular fa-trash-can"></i> Excluir (<span id="selectedCount">0</span>)
                </button>
                <button id="btnEmptyTrash" onclick="emptyTrashFolder()" class="hidden px-3 py-1.5 bg-slate-700 hover:bg-slate-800 text-white rounded-lg font-bold text-xs shadow-sm flex items-center gap-1.5">
                    <i class="fa-solid fa-bomb"></i> Esvaziar Lixeira
                </button>
            </div>
        </div>

        <div id="emailListContainer" class="flex-1 overflow-y-auto divide-y divide-slate-100 max-h-[720px]"></div>
    </section>

    <!-- 3. PAINEL CENTRAL DE LEITURA EXPANSÍVEL + BANNER COMPACTO DO ROBÔ DE SEGURANÇA -->
    <main id="emailReaderSection" class="hidden md:flex flex-1 bg-slate-100/80 flex-col overflow-hidden transition-all duration-200 min-h-[820px]">
        <div id="emptyReader" class="flex-1 flex flex-col items-center justify-center p-8 text-center text-slate-400 bg-slate-50">
            <img src="<?php echo htmlspecialchars($logo_src, ENT_QUOTES, 'UTF-8'); ?>" referrerpolicy="strict-origin-when-cross-origin" alt="Logo" onerror="this.onerror=null;this.src='<?php echo htmlspecialchars((isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '/index.php') . '?pwa=logo_horizontal', ENT_QUOTES, 'UTF-8'); ?>';" class="h-14 opacity-40 mb-3 object-contain rounded-lg">
            <p class="text-base font-semibold text-[#002244]">Selecione uma mensagem na lista para ler</p>
            <p class="text-xs text-slate-400 mt-1"><i class="fa-solid fa-robot text-emerald-600 mr-1"></i>Robô Anti-Phishing inspecionando links e mensagens em tempo real.</p>
        </div>

        <div id="emailReader" class="hidden flex-1 flex flex-col overflow-hidden bg-white">
            <!-- BARRA SUPERIOR DE AÇÕES E NAVEGAÇÃO -->
            <div class="px-4 py-3 border-b border-slate-200 shrink-0 bg-slate-50/90 flex flex-wrap items-center justify-between gap-2">
                <div class="flex items-center gap-2">
                    <button type="button" onclick="backToMobileList()" class="px-2 py-1.5 rounded-lg bg-[#002244] hover:bg-[#00152b] text-white font-bold text-[11px] flex items-center gap-1 transition shadow-xs" title="Voltar para a lista de mensagens" aria-label="Voltar">
                        <i class="fa-solid fa-arrow-left"></i>
                        <span>Voltar</span>
                    </button>
                    <button type="button" onclick="toggleEmailListCollapse()" class="hidden md:inline-flex px-3 py-2 rounded-lg bg-white hover:bg-slate-100 text-[#002244] border border-slate-300 font-bold text-xs items-center gap-1.5 transition" title="Mostrar ou recolher coluna de mensagens">
                        <i id="toggleListIcon" class="fa-solid fa-table-columns text-[#475569]"></i>
                        <span id="toggleListLabel">Mostrar Lista Lateral</span>
                    </button>
                </div>

                <div id="emailReaderActionButtons" class="flex items-center gap-1 sm:gap-1.5 ml-auto flex-nowrap">
                    <button type="button" onclick="replyCurrentEmail()" title="Responder esta mensagem" aria-label="Responder esta mensagem" class="re9-message-action-btn bg-navy text-white inline-flex items-center justify-center hover:opacity-95 shadow-xs transition" style="flex:0 0 auto">
                        <i class="fa-solid fa-reply re9-message-action-icon" aria-hidden="true"></i>
                    </button>
                    <button type="button" onclick="forwardCurrentEmail()" title="Encaminhar esta mensagem" aria-label="Encaminhar esta mensagem" class="re9-message-action-btn bg-[#475569] hover:bg-[#334155] text-white inline-flex items-center justify-center shadow-xs transition" style="flex:0 0 auto">
                        <i class="fa-solid fa-share re9-message-action-icon" aria-hidden="true"></i>
                    </button>
                    <button type="button" onclick="blockAndDestroyCurrentEmail()" title="Bloquear membro/remetente" aria-label="Bloquear membro" class="w-8 h-8 sm:w-9 sm:h-9 p-0 rounded-md bg-red-700 hover:bg-red-800 text-white text-[11px] font-bold inline-flex items-center justify-center shadow-xs transition" style="flex:0 0 auto"><i class="fa-solid fa-ban"></i></button>
                    <button type="button" onclick="deleteCurrentEmail()" title="Mover para Lixeira" aria-label="Excluir mensagem" class="w-8 h-8 sm:w-9 sm:h-9 p-0 rounded-md btn-blood text-[11px] inline-flex items-center justify-center shadow-xs transition" style="flex:0 0 auto">
                        <i class="fa-regular fa-trash-can"></i>
                    </button>
                </div>
            </div>

            <!-- CABEÇALHO DA MENSAGEM ELEVADO (ASSUNTO, AVATAR, REMETENTE E DATA) -->
            <div class="px-4 sm:px-6 py-4 border-b border-slate-200 shrink-0 bg-white">
                <div class="max-w-5xl mx-auto">
                    <div class="flex flex-wrap items-center gap-2 mb-3">
                        <span id="trustedSenderBadge" class="hidden px-2.5 py-0.5 rounded-full bg-emerald-100 text-emerald-800 font-bold text-[11px] shrink-0">
                            <i class="fa-solid fa-circle-check mr-1"></i>Remetente Confiável
                        </span>
                        <h2 id="readSubject" class="text-lg sm:text-xl font-extrabold text-[#002244] leading-snug"></h2>
                    </div>

                    <div class="flex items-center justify-between gap-3">
                        <div class="flex items-center gap-3 min-w-0">
                            <div id="readSenderAvatar" class="w-10 h-10 rounded-full bg-[#002244] text-white flex items-center justify-center font-extrabold text-sm shrink-0 shadow-xs">
                                @
                            </div>
                            <div class="min-w-0 text-xs sm:text-sm">
                                <div class="font-bold text-[#990000] truncate" id="readFrom"></div>
                                <div class="text-xs text-slate-500 truncate">Para: <span id="readTo" class="text-slate-700 font-medium"></span></div>
                            </div>
                        </div>
                        <span id="readDate" class="text-xs font-semibold text-slate-500 bg-slate-100 px-2.5 py-1 rounded-lg border border-slate-200 shrink-0"></span>
                    </div>
                </div>
            </div>

            <!-- AVISO COMPACTO DO ROBÔ DE SEGURANÇA -->
            <div id="securityBotWarningBanner" class="hidden bg-slate-900 text-white p-3 border-b-4 border-red-600 shrink-0 space-y-2 shadow-inner">
                <div class="max-w-5xl mx-auto space-y-2">
                    <div class="flex items-center gap-2.5">
                        <div class="w-8 h-8 rounded-lg bg-red-600 text-white flex items-center justify-center shrink-0 text-sm font-black unread-badge-pulse">
                            <i class="fa-solid fa-triangle-exclamation"></i>
                        </div>
                        <div class="flex-1 min-w-0">
                            <div class="text-[10px] font-extrabold uppercase tracking-wider text-amber-400 flex items-center gap-1">
                                <i class="fa-solid fa-robot"></i> Alerta do Robô de Segurança: E-mail Suspeito
                            </div>
                            <p class="text-xs text-slate-200 mt-0.5 leading-snug">
                                Você estava aguardando este e-mail de <strong id="warnSenderHighlight" class="text-amber-300 font-bold underline">Remetente</strong>? Links e imagens remotas foram protegidos por segurança.
                            </p>
                            <p id="warnReasonText" class="text-xs text-amber-200 mt-1 leading-snug font-semibold"></p>
                        </div>
                    </div>

                    <div class="flex flex-wrap items-center justify-between gap-2 pt-1.5 border-t border-slate-800 text-[11px]">
                        <div class="text-slate-400 truncate max-w-[280px]">
                            <span id="warnIpText">IP: -</span>
                        </div>
                        <div class="flex items-center gap-2">
                            <button type="button" onclick="trustCurrentEmailSender()"
                                    class="px-3 py-1.5 rounded-lg bg-emerald-600 hover:bg-emerald-500 text-white font-bold flex items-center gap-1 shadow">
                                <i class="fa-solid fa-shield-heart"></i>
                                <span>Estou Aguardando (Liberar)</span>
                            </button>
                            <button type="button" onclick="blockAndDestroyCurrentEmail()"
                                    class="px-3 py-1.5 rounded-lg bg-red-600 hover:bg-red-500 text-white font-bold flex items-center gap-1 shadow">
                                <i class="fa-solid fa-ban"></i>
                                <span>Excluir e Bloquear</span>
                            </button>
                        </div>
                    </div>
                </div>
            </div>

            <!-- CORPO EXPANDIDO DA MENSAGEM -->
            <div class="flex-1 p-2 sm:p-5 bg-slate-100/70 overflow-y-auto">
                <div class="max-w-5xl mx-auto bg-white rounded-xl border border-slate-200/90 shadow-xs p-2 sm:p-5 min-h-full flex flex-col">
                    <div id="remoteEmailImagesNotice" class="hidden mb-3 rounded-lg border border-amber-300 bg-amber-50 px-3 py-2 text-sm text-amber-950 flex flex-wrap items-center justify-between gap-2">
                        <span><i class="fa-solid fa-shield-halved mr-1"></i><strong>Imagens externas protegidas.</strong> Para preservar sua privacidade, elas não carregam sozinhas.</span>
                        <button type="button" id="loadRemoteEmailImagesBtn" onclick="loadRemoteEmailImages()" class="rounded-md bg-[#002244] px-3 py-2 text-white font-bold hover:bg-[#174a7a]">Carregar imagens</button>
                    </div>
                    <div id="readWelcomeContent" class="hidden w-full flex-1 min-h-[520px] overflow-y-auto rounded-lg bg-white p-3 sm:p-5" role="document" aria-label="Mensagem de boas-vindas"></div>
                    <iframe id="readBodyFrame" class="w-full flex-1 border-0 min-h-[520px]" sandbox="allow-popups allow-downloads"></iframe>
                </div>
            </div>
        </div>
    </main>

    <!-- 4. PAINEL DIREITO DE PUBLICIDADE (DESKTOP - ALTURA EXPANDIDA SEM CORTAR O BOTÃO SAIBA MAIS) -->
    <aside class="hidden xl:flex w-80 bg-slate-100 border-l border-slate-200 flex-col justify-between p-3.5 shrink-0 min-h-[820px]">
        <div class="space-y-3">
            <div class="flex items-center justify-between text-[11px] font-extrabold uppercase text-[#002244] px-1">
                <span class="flex items-center gap-1.5">
                    <span class="w-2 h-2 rounded-full bg-[#475569]"></span>
                    <span>Espaço Publicitário</span>
                </span>
                <div class="flex items-center gap-2">
                    <button onclick="rotateSingleSidebarAd()" title="Sortear outro cartaz" class="text-slate-400 hover:text-[#475569]">
                        <i class="fa-solid fa-shuffle"></i>
                    </button>
                    <?php if ($is_admin): ?>
                    <button onclick="openModal('brandModal');" class="text-[#990000] hover:text-[#475569]" title="Depositar Novos Cartazes">
                        <i class="fa-solid fa-plus-circle"></i>
                    </button>
                    <?php endif; ?>
                </div>
            </div>

            <div id="singleAdCard" class="bg-white rounded-2xl border-2 border-[#002244]/15 overflow-hidden shadow-md flex flex-col">
                <a id="singleAdUrl" href="#" target="_blank" class="flex flex-col flex-1">
                    <div class="px-3.5 py-2 bg-[#002244] text-white flex items-center justify-between">
                        <span id="singleAdSender" class="text-[11px] font-bold truncate">Anunciante</span>
                        <span id="singleAdBadge" class="px-2 py-0.5 rounded bg-[#475569] text-white font-extrabold text-[9px] uppercase">Destaque</span>
                    </div>

                    <div id="singleAdImgWrap" class="w-full bg-slate-900 flex items-center justify-center overflow-hidden">
                        <img id="singleAdImg" src="" referrerpolicy="strict-origin-when-cross-origin" alt="Cartaz Publicitário" class="w-full max-h-[380px] object-contain block">
                    </div>

                    <div class="p-4 border-t border-slate-100 bg-white">
                        <h4 id="singleAdTitle" class="font-extrabold text-sm text-[#002244] leading-snug mb-1.5"></h4>
                        <p id="singleAdDesc" class="text-xs text-slate-600 mb-3.5 leading-relaxed"></p>
                        <div id="singleAdCta" class="w-full py-2.5 px-3 text-center rounded-xl btn-chrome text-xs shadow font-extrabold">
                            Saiba Mais
                        </div>
                    </div>
                </a>
            </div>
        </div>

        <div class="text-center text-[10px] text-slate-400 pt-3 border-t border-slate-200 mt-4">
            Plataforma Corporativa • <strong class="text-[#002244]"><?php echo htmlspecialchars($APP_CONFIG['brand_name']); ?></strong>
        </div>
    </aside>
</div>

<!-- =========================================================================
     MODAL: RECEBER E-MAILS EXTERNOS (ABA 1: ENCAMINHAMENTO EM 1 MINUTO | ABA 2: IMAP)
     ========================================================================= -->
<div id="extAccountsModal" class="fixed inset-0 bg-slate-900/75 hidden items-center justify-center z-50 p-2 sm:p-4">
    <div class="bg-white w-full max-w-xl rounded-2xl shadow-2xl border-t-4 border-[#f28c38] flex flex-col max-h-[94vh] overflow-hidden">
        
        <div class="bg-navy text-white px-5 py-3.5 flex items-center justify-between">
            <h3 class="font-extrabold text-sm flex items-center gap-2">
                <i class="fa-solid fa-cloud-arrow-down text-[#f28c38]"></i>
                <span>Receber E-mails do Hotmail, Gmail e Outros Aqui</span>
            </h3>
            <button onclick="closeModal('extAccountsModal')" class="text-white/70 hover:text-white"><i class="fa-solid fa-xmark text-lg"></i></button>
        </div>

        <!-- ABAS DO MODAL EXTERNO -->
        <div class="flex border-b bg-slate-100 text-xs font-bold">
            <button type="button" id="tabBtnExtForward" onclick="switchExtTab('forward')"
                    class="flex-1 py-3 px-3 border-b-2 border-[#f28c38] text-[#002244] bg-white">
                <i class="fa-solid fa-bolt text-[#f28c38] mr-1"></i> 1. Encaminhamento em 1 Minuto (Recomendado)
            </button>
            <button type="button" id="tabBtnExtImap" onclick="switchExtTab('imap')"
                    class="flex-1 py-3 px-3 border-b-2 border-transparent text-slate-500 hover:text-[#002244]">
                <i class="fa-solid fa-key text-[#990000] mr-1"></i> 2. Conexão via Senha de App (IMAP)
            </button>
        </div>

        <div class="p-4 sm:p-5 overflow-y-auto flex-1 space-y-4 text-xs">

            <!-- ABA 1: GUIA PASSO A PASSO DE ENCAMINHAMENTO AUTOMÁTICO EM 1 MINUTO -->
            <div id="extForwardSection" class="space-y-4">
                <div class="p-3.5 rounded-xl bg-emerald-50 border border-emerald-200 flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3">
                    <div>
                        <span class="text-[10px] font-extrabold uppercase text-emerald-800 bg-emerald-200/70 px-2 py-0.5 rounded">100% Automático e Sem Bloqueio de Senha</span>
                        <div class="font-bold text-[#002244] text-xs mt-1">Copie o seu endereço abaixo e cole no encaminhamento do seu Hotmail ou Gmail:</div>
                        <div id="myCurrentWebmailAddr" class="font-mono font-extrabold text-sm text-[#990000] mt-0.5"><?php echo htmlspecialchars($_SESSION['wm_email']); ?></div>
                    </div>
                    <button type="button" onclick="copyMyWebmailAddress()" class="px-3.5 py-2 rounded-xl bg-[#002244] hover:bg-[#00152b] text-white font-bold text-xs flex items-center gap-1.5 shadow shrink-0">
                        <i class="fa-regular fa-copy text-[#f28c38]"></i>
                        <span id="btnCopyMyEmailText">Copiar Meu E-mail</span>
                    </button>
                </div>

                <!-- PASSO A PASSO HOTMAIL / OUTLOOK -->
                <div class="p-4 rounded-xl bg-slate-50 border border-slate-200 space-y-2">
                    <div class="flex items-center justify-between">
                        <div class="font-extrabold text-sm text-[#002244] flex items-center gap-2">
                            <i class="fa-brands fa-microsoft text-blue-600 text-base"></i>
                            <span>Como ativar no Hotmail / Outlook (Em 1 Minuto)</span>
                        </div>
                        <a href="https://outlook.live.com/mail/0/options/mail/forwarding" target="_blank"
                           class="px-3 py-1.5 rounded-lg bg-blue-600 hover:bg-blue-700 text-white font-bold text-[11px] flex items-center gap-1 shadow-xs">
                            <span>Abrir Encaminhamento Hotmail</span>
                            <i class="fa-solid fa-up-right-from-square text-[10px]"></i>
                        </a>
                    </div>
                    <ol class="list-decimal list-inside space-y-1 text-slate-700 leading-relaxed pl-1">
                        <li>Clique no botão azul acima (ou no Hotmail vá em <strong>Configurações ⚙️ &rarr; Email &rarr; Encaminhamento</strong>).</li>
                        <li>Marque a caixinha <strong>"Habilitar o encaminhamento"</strong>.</li>
                        <li>Cole o seu e-mail <strong><?php echo htmlspecialchars($_SESSION['wm_email']); ?></strong>, marque <em>"Manter uma cópia das mensagens encaminhadas"</em> e clique em <strong>Salvar</strong>. Pronto! Tudo que chegar lá cairá aqui no mesmo segundo.</li>
                    </ol>
                </div>

                <!-- PASSO A PASSO GMAIL -->
                <div class="p-4 rounded-xl bg-slate-50 border border-slate-200 space-y-2">
                    <div class="flex items-center justify-between">
                        <div class="font-extrabold text-sm text-[#002244] flex items-center gap-2">
                            <i class="fa-brands fa-google text-red-600 text-base"></i>
                            <span>Como ativar no Gmail (Em 1 Minuto)</span>
                        </div>
                        <a href="https://mail.google.com/mail/u/0/#settings/fwdandpop" target="_blank"
                           class="px-3 py-1.5 rounded-lg bg-[#990000] hover:bg-[#b30000] text-white font-bold text-[11px] flex items-center gap-1 shadow-xs">
                            <span>Abrir Encaminhamento Gmail</span>
                            <i class="fa-solid fa-up-right-from-square text-[10px]"></i>
                        </a>
                    </div>
                    <ol class="list-decimal list-inside space-y-1 text-slate-700 leading-relaxed pl-1">
                        <li>Clique no botão vermelho acima (ou no Gmail vá em <strong>Configurações ⚙️ &rarr; Ver todas as configurações &rarr; Encaminhamento e POP/IMAP</strong>).</li>
                        <li>Clique em <strong>"Adicionar um endereço de encaminhamento"</strong> e cole <strong><?php echo htmlspecialchars($_SESSION['wm_email']); ?></strong>.</li>
                        <li>O Google enviará um e-mail de confirmação para a sua Caixa de Entrada aqui do RE9 Webmail. Basta abrir o e-mail, clicar no link de confirmação e ativar a opção <strong>"Encaminhar uma cópia do e-mail de entrada"</strong> no Gmail!</li>
                    </ol>
                </div>
            </div>

            <!-- ABA 2: CONEXÃO VIA SENHA DE APLICATIVO (IMAP) -->
            <div id="extImapSection" class="hidden space-y-4">
                <form id="extAccountForm" onsubmit="submitAddExternalAccount(event)" class="space-y-3 bg-slate-50 p-4 rounded-xl border border-slate-200">
                    <div class="p-2.5 rounded-lg bg-amber-50 border border-amber-200 text-[11px] text-amber-900 leading-relaxed">
                        <strong>Nota sobre Senha de App:</strong> A Microsoft e o Google bloqueiam a senha normal em conexões externas. Para usar este modo, gere uma <strong>Senha de Aplicativo de 16 letras</strong> em
                        <a href="https://account.live.com/proofs/Manage" target="_blank" class="underline font-bold text-blue-700">Segurança Microsoft</a> ou
                        <a href="https://myaccount.google.com/apppasswords" target="_blank" class="underline font-bold text-red-700">Senhas de App Google</a>.
                    </div>

                    <div class="grid grid-cols-1 sm:grid-cols-2 gap-2.5">
                        <div class="sm:col-span-2">
                            <label class="block font-bold text-[#002244] mb-1">E-mail Externo</label>
                            <input type="email" id="extEmailInput" name="ext_email" required placeholder="ex: eliasvendas@hotmail.com ou eliasvendas9@gmail.com"
                                   oninput="autoFillImapHost(this.value)"
                                   class="w-full p-2.5 border rounded-lg bg-white outline-none focus:border-[#002244]">
                        </div>

                        <div class="sm:col-span-2">
                            <label class="block font-bold text-[#002244] mb-1">Senha de Aplicativo (ou Senha do E-mail)</label>
                            <input type="password" id="extPassInput" name="ext_pass" required placeholder="Cole aqui a Senha de Aplicativo gerada"
                                   class="w-full p-2.5 border rounded-lg bg-white outline-none focus:border-[#002244]">
                        </div>

                        <div>
                            <label class="block font-bold text-slate-700 mb-1">Servidor IMAP</label>
                            <input type="text" id="extHostInput" name="ext_host" required placeholder="imap-mail.outlook.com"
                                   class="w-full p-2 border rounded-lg bg-white font-mono text-[11px]">
                        </div>

                        <div>
                            <label class="block font-bold text-slate-700 mb-1">Porta SSL</label>
                            <input type="number" id="extPortInput" name="ext_port" value="993" required
                                   class="w-full p-2 border rounded-lg bg-white font-mono text-[11px]">
                        </div>
                    </div>

                    <div id="extAccountMsg" class="hidden p-2.5 rounded-lg text-xs font-bold"></div>

                    <div class="pt-2 flex justify-end gap-2">
                        <button type="submit" id="btnAddExtAccount" class="px-4 py-2.5 btn-chrome rounded-lg shadow text-xs">
                            <i class="fa-solid fa-plug-circle-check mr-1"></i> Conectar via IMAP
                        </button>
                    </div>
                </form>

                <div>
                    <div class="flex items-center justify-between mb-2">
                        <span class="font-extrabold text-xs text-[#002244] uppercase">Contas Conectadas via IMAP:</span>
                        <button type="button" onclick="syncExternalAccountsNow(false)" id="btnSyncExtModal"
                                class="px-3 py-1.5 rounded-lg bg-emerald-600 hover:bg-emerald-700 text-white font-bold text-xs flex items-center gap-1.5 shadow">
                            <i id="extSyncModalIcon" class="fa-solid fa-rotate"></i>
                            <span>Buscar Mensagens de Hoje</span>
                        </button>
                    </div>
                    <div id="extAccountsListContainer" class="space-y-2 max-h-40 overflow-y-auto pr-1"></div>
                </div>
            </div>

        </div>
    </div>
</div>

<!-- MODAL: TROCAR SENHA -->
<div id="changePasswordModal" class="fixed inset-0 bg-slate-900/75 hidden items-center justify-center z-50 p-3">
    <div class="bg-white w-full max-w-md rounded-2xl shadow-2xl p-6 border-t-4 border-[#002244]">
        <div class="flex items-center justify-between pb-3 border-b mb-4">
            <h3 class="font-extrabold text-base text-[#002244] flex items-center gap-2">
                <i class="fa-solid fa-key text-[#990000]"></i>
                <span>Trocar Senha da Conta</span>
            </h3>
            <button onclick="closeModal('changePasswordModal')" class="text-slate-400 hover:text-slate-700"><i class="fa-solid fa-xmark text-lg"></i></button>
        </div>

        <form onsubmit="submitChangePassword(event)" class="space-y-4 text-sm">
            <p class="text-xs text-slate-500">Crie uma nova senha forte para a conta <strong><?php echo htmlspecialchars($_SESSION['wm_email']); ?></strong>:</p>
            <div>
                <div class="flex items-center justify-between mb-1">
                    <label class="font-bold text-slate-700 text-xs uppercase">Nova Senha Forte</label>
                    <button type="button" onclick="generateStrongPasswordInChange()" class="text-[11px] font-bold text-[#990000] hover:underline">
                        <i class="fa-solid fa-wand-magic-sparkles"></i> Sugerir Senha
                    </button>
                </div>
                <input type="text" id="changePassNew" required placeholder="Ex: Re9@2026Forte"
                       oninput="checkPasswordRules(this.value, 'chg')"
                       class="w-full p-3 border rounded-lg bg-white text-base sm:text-sm font-mono">

                <div class="mt-2 p-2.5 rounded-lg bg-slate-50 border border-slate-200 text-[11px] space-y-1">
                    <div id="chg_rule_len" class="text-slate-500 flex items-center gap-1.5"><i class="fa-regular fa-circle"></i> Mínimo de 8 caracteres</div>
                    <div id="chg_rule_case" class="text-slate-500 flex items-center gap-1.5"><i class="fa-regular fa-circle"></i> Letras MAIÚSCULAS e minúsculas</div>
                    <div id="chg_rule_num" class="text-slate-500 flex items-center gap-1.5"><i class="fa-regular fa-circle"></i> Pelo menos 1 número (0-9)</div>
                    <div id="chg_rule_sym" class="text-slate-500 flex items-center gap-1.5"><i class="fa-regular fa-circle"></i> Pelo menos 1 símbolo (@ # $ % ! & *)</div>
                </div>
            </div>
            <div id="changePassResult" class="hidden p-3 rounded-lg text-xs font-semibold"></div>
            <div class="pt-2 border-t flex justify-end gap-2">
                <button type="button" onclick="closeModal('changePasswordModal')" class="px-4 py-2 text-slate-600">Cancelar</button>
                <button type="submit" id="btnUpdatePass" class="px-5 py-2.5 btn-chrome rounded-lg">Salvar Nova Senha</button>
            </div>
        </form>
    </div>
</div>

<!-- MODAL: NOVO E-MAIL -->
<div id="composeModal" class="fixed inset-0 bg-slate-900/70 hidden items-center justify-center z-50 p-2 sm:p-4">
    <div class="bg-white w-full max-w-2xl rounded-2xl shadow-2xl border-t-4 border-[#475569] flex flex-col max-h-[95vh] overflow-hidden">
        <div class="bg-navy text-white px-4 py-3 flex items-center justify-between">
            <h3 class="font-bold text-sm flex items-center gap-2">
                <i class="fa-solid fa-paper-plane text-[#cbd5e1]"></i> <span id="composeModalHeading">Nova Mensagem</span>
            </h3>
            <button onclick="closeModal('composeModal')"><i class="fa-solid fa-xmark text-lg"></i></button>
        </div>
        <div class="p-3 sm:p-4 space-y-2.5 flex-1 overflow-y-auto">
            <input type="email" id="compTo" placeholder="Para: destinatario@dominio.com.br" class="w-full p-3 border rounded-lg text-base sm:text-sm outline-none focus:border-[#475569]">
            <input type="text" id="compSubject" placeholder="Assunto da mensagem" class="w-full p-3 border rounded-lg text-base sm:text-sm outline-none focus:border-[#475569]">
            <div id="compForwardedAttsBox" class="hidden p-2.5 rounded-lg bg-slate-100 border border-slate-300 text-xs text-[#002244]"></div>
            <div id="compBodyEditor" contenteditable="true" class="w-full p-3 border rounded-lg text-base sm:text-sm min-h-[240px] outline-none overflow-y-auto"></div>
        </div>
        <div class="px-4 py-3 bg-slate-50 border-t flex justify-between items-center gap-2">
            <button onclick="saveAsDraft()" class="px-3 py-2 text-xs bg-slate-200 hover:bg-slate-300 text-[#002244] rounded-lg font-semibold">
                <i class="fa-regular fa-floppy-disk"></i> Rascunho
            </button>
            <div class="flex gap-2">
                <button onclick="closeModal('composeModal')" class="px-3 py-2 text-xs text-slate-600">Cancelar</button>
                <button id="btnSendMail" onclick="sendEmailNow()" class="px-5 py-2.5 btn-chrome text-xs sm:text-sm rounded-lg shadow">
                    <i class="fa-solid fa-paper-plane mr-1"></i> Enviar Agora
                </button>
            </div>
        </div>
    </div>
</div>

<!-- MODAL: ASSINATURA (FORMATO CARTÃO DE VISITA RETANGULAR PROFISSIONAL) -->
<div id="sigModal" class="fixed inset-0 bg-slate-900/75 hidden items-center justify-center z-50 p-3 sm:p-4">
    <div class="bg-white w-full max-w-xl rounded-2xl shadow-2xl border-t-4 border-[#f28c38] max-h-[94vh] overflow-y-auto flex flex-col">
        <div class="bg-navy text-white px-5 py-3.5 flex items-center justify-between shrink-0">
            <h3 class="font-extrabold text-sm flex items-center gap-2">
                <i class="fa-solid fa-id-card text-[#f28c38] text-base"></i>
                <span>Cartão de Visita Digital (Assinatura de E-mail)</span>
            </h3>
            <button onclick="closeModal('sigModal')" class="text-white/70 hover:text-white"><i class="fa-solid fa-xmark text-lg"></i></button>
        </div>

        <div class="p-5 space-y-4">
            <!-- PRÉVIA DO CARTÃO DE VISITA ATUAL -->
            <div class="p-3.5 rounded-xl bg-slate-100 border border-slate-200">
                <div class="text-[10px] font-extrabold uppercase tracking-wider text-slate-500 mb-2 flex items-center justify-between">
                    <span><i class="fa-solid fa-eye text-[#f28c38] mr-1"></i>Seu Cartão de Visita Atual:</span>
                    <span class="text-emerald-700">Enviado automaticamente nos e-mails</span>
                </div>
                <div id="sigLivePreviewBox" class="overflow-x-auto">
                    <?php echo $user_sig; ?>
                </div>
            </div>

            <form id="signatureCardForm" enctype="multipart/form-data" class="space-y-3.5 text-xs sm:text-sm">
                <div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
                    <div>
                        <label class="block font-bold text-[#002244] mb-1 text-xs uppercase">Seu Nome / Empresa</label>
                        <input type="text" name="sig_nome" required placeholder="Ex: Elias Santos" class="w-full p-2.5 border border-slate-300 rounded-lg bg-white outline-none focus:border-[#002244]">
                    </div>

                    <div>
                        <label class="block font-bold text-[#002244] mb-1 text-xs uppercase">Cargo / Especialidade</label>
                        <input type="text" name="sig_cargo" required placeholder="Ex: Desenvolvedor Full-Stack / Consultor TI" class="w-full p-2.5 border border-slate-300 rounded-lg bg-white outline-none focus:border-[#002244]">
                    </div>
                </div>

                <div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
                    <div>
                        <label class="block font-bold text-[#002244] mb-1 text-xs uppercase"><i class="fa-brands fa-whatsapp text-emerald-600 mr-1"></i>WhatsApp (Com DDD)</label>
                        <input type="text" name="sig_whatsapp" placeholder="Ex: (21) 98629-7787" class="w-full p-2.5 border border-slate-300 rounded-lg bg-white outline-none focus:border-[#002244]">
                    </div>
                    <div>
                        <label class="block font-bold text-[#002244] mb-1 text-xs uppercase"><i class="fa-solid fa-globe text-blue-600 mr-1"></i>Site / Link Corporativo</label>
                        <input type="text" name="sig_site" placeholder="www.re9seusite.com.br" class="w-full p-2.5 border border-slate-300 rounded-lg bg-white outline-none focus:border-[#002244]">
                    </div>
                </div>

                <div class="p-3.5 rounded-xl bg-amber-50/70 border border-amber-200">
                    <label class="block font-extrabold text-[#002244] mb-1 text-xs uppercase">
                        <i class="fa-solid fa-image text-[#f28c38] mr-1"></i>Logomarca ou Foto:
                    </label>
                    <input type="file" name="sig_logo_file" accept="image/*" class="w-full p-2 border border-slate-300 rounded-lg bg-white text-xs cursor-pointer">
                    <p class="text-[11px] text-slate-500 mt-1">A imagem é convertida para URL pública completa (HTTPS) automaticamente para abrir em qualquer e-mail.</p>
                </div>

                <div class="pt-3 border-t flex justify-end gap-2">
                    <button type="button" onclick="closeModal('sigModal')" class="px-4 py-2.5 text-xs font-semibold text-slate-600">Fechar</button>
                    <button type="submit" class="px-5 py-2.5 btn-chrome rounded-lg shadow text-xs sm:text-sm">
                        <i class="fa-solid fa-check mr-1"></i> Salvar Cartão de Visita
                    </button>
                </div>
            </form>
        </div>
    </div>
</div>

<?php if ($is_admin): ?>
<!-- MODAL ADMIN (LOGO & CPANEL | BANCO DE CARTAZES) -->
<div id="brandModal" class="fixed inset-0 bg-slate-900/75 hidden items-center justify-center z-50 p-2 sm:p-4">
    <div class="bg-white w-full max-w-5xl rounded-2xl shadow-2xl border-t-4 border-[#475569] flex flex-col max-h-[96vh] overflow-hidden">
        
        <div class="bg-navy text-white px-5 py-3.5 flex items-center justify-between">
            <h3 class="font-bold text-sm flex items-center gap-2">
                <i class="fa-solid fa-sliders text-[#cbd5e1]"></i>
                <span>Central Admin (VPS <?php echo htmlspecialchars($APP_CONFIG['cpanel_host']); ?>)</span>
            </h3>
            <?php if (!empty($RE9_IS_CENTRAL_HUB)): ?><a href="?central_admin=1" class="mr-3 rounded-lg bg-white/10 px-3 py-2 text-[11px] font-bold text-white hover:bg-white/20"><i class="fa-solid fa-network-wired mr-1"></i> Domínios clientes</a><?php endif; ?>
            <button onclick="closeModal('brandModal')" class="text-white/70 hover:text-white"><i class="fa-solid fa-xmark text-lg"></i></button>
        </div>

        <div class="flex flex-wrap border-b bg-slate-100 text-[11px] sm:text-xs font-bold overflow-visible">
            <button type="button" id="tabBtnLogo" onclick="switchAdminTab('logo')"
                    class="min-w-0 flex-1 basis-full sm:basis-1/3 py-3 px-2 sm:px-3 border-b-2 border-[#475569] text-[#002244] bg-white whitespace-normal leading-tight">
                <i class="fa-regular fa-image text-[#475569] mr-1"></i> 1. Logo & cPanel VPS
            </button>
            <button type="button" id="tabBtnAds" onclick="switchAdminTab('ads')"
                    class="min-w-0 flex-1 basis-full sm:basis-1/3 py-3 px-2 sm:px-3 border-b-2 border-transparent text-slate-500 hover:text-[#002244] whitespace-normal leading-tight">
                <i class="fa-solid fa-layer-group text-[#990000] mr-1"></i> 2. Banco de Cartazes (<span id="adPoolCount"><?php echo count($APP_CONFIG['ads_pool']); ?></span>)
            </button>
            <button type="button" id="tabBtnMailboxes" onclick="switchAdminTab('mailboxes')"
                    class="min-w-0 flex-1 basis-full sm:basis-1/3 py-3 px-2 sm:px-3 border-b-2 border-transparent text-slate-500 hover:text-[#002244] whitespace-normal leading-tight">
                <i class="fa-solid fa-users-gear text-emerald-700 mr-1"></i> 3. Contas de E-mail
            </button>
        </div>

        <div class="p-5 overflow-y-auto flex-1 space-y-4 text-xs">

            <!-- BLOCO 1: LOGO & INTEGRAÇÃO CPANEL PELO IP DA VPS -->
            <form id="brandLogoForm" enctype="multipart/form-data" class="space-y-4">
                <div class="p-4 rounded-xl bg-slate-50 border-2 border-dashed border-[#002244]/30 flex flex-col sm:flex-row items-center gap-4">
                    <div class="bg-[#002244] p-3 rounded-xl shrink-0 text-center">
                        <span class="block text-[10px] text-white/70 mb-1 uppercase">Logo Atual no Topo</span>
                        <img id="adminLogoPreview" src="<?php echo htmlspecialchars($logo_src, ENT_QUOTES, 'UTF-8'); ?>" referrerpolicy="strict-origin-when-cross-origin" alt="Preview Logo" onerror="this.onerror=null;this.src='<?php echo htmlspecialchars((isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '/index.php') . '?pwa=logo_horizontal', ENT_QUOTES, 'UTF-8'); ?>';" class="h-12 max-w-[180px] object-contain mx-auto">
                    </div>
                    <div class="flex-1 w-full space-y-2">
                        <label class="block font-extrabold text-[#002244] text-sm">Escolher Nova Logomarca para o Topo:</label>
                        <input type="file" name="brand_logo_file" accept="image/*"
                               onchange="previewSelectedLogo(this)"
                               class="w-full p-2 border border-slate-300 rounded-lg bg-white text-xs cursor-pointer">
                    </div>
                </div>

                <div class="p-4 rounded-xl bg-amber-50 border border-amber-200 space-y-2.5">
                    <div class="font-extrabold text-[#990000] uppercase flex items-center gap-1.5">
                        <i class="fa-solid fa-server"></i> Servidor VPS / cPanel (Criação de E-mails e Alteração de Senhas)
                    </div>
                    <div class="grid grid-cols-1 sm:grid-cols-3 gap-2.5">
                        <div>
                            <label class="block font-bold text-[#002244] mb-1">IP do Servidor VPS</label>
                            <input type="text" name="cpanel_host" value="<?php echo htmlspecialchars($APP_CONFIG['cpanel_host']); ?>" placeholder="162.240.100.87" class="w-full p-2.5 border rounded-lg bg-white font-mono">
                        </div>
                        <div>
                            <label class="block font-bold text-[#002244] mb-1">Usuário do cPanel</label>
                            <input type="text" name="cpanel_user" value="<?php echo htmlspecialchars($APP_CONFIG['cpanel_user']); ?>" placeholder="Ex: re9rio" class="w-full p-2.5 border rounded-lg bg-white">
                        </div>
                        <div>
                            <label class="block font-bold text-[#002244] mb-1">Senha cPanel / API Token</label>
                            <input type="password" name="cpanel_api_token" placeholder="<?php echo !empty($APP_CONFIG['cpanel_api_token']) ? '•••••••• (Salvo)' : 'Senha ou Token'; ?>" class="w-full p-2.5 border rounded-lg bg-white">
                        </div>
                    </div>
                </div>

                <div class="p-4 rounded-xl bg-slate-50 border border-slate-200 space-y-2.5">
                    <div class="font-bold text-[#002244] uppercase">Gateway de WhatsApp (Disparo do Código de 6 Dígitos)</div>
                    <div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
                        <div>
                            <label class="block font-bold text-slate-600 mb-1">URL Endpoint WhatsApp API</label>
                            <input type="text" name="whatsapp_api_url" value="<?php echo htmlspecialchars($wa_url_val); ?>" placeholder="https://api.../sendText" class="w-full p-2 border rounded bg-white">
                        </div>
                        <div>
                            <label class="block font-bold text-slate-600 mb-1">API Key / Token WhatsApp</label>
                            <input type="password" name="whatsapp_api_token" value="<?php echo htmlspecialchars($wa_tok_val); ?>" placeholder="Token da instância" class="w-full p-2 border rounded bg-white">
                        </div>
                    </div>
                </div>

                <div class="p-4 rounded-xl bg-blue-50 border border-blue-200 space-y-3">
                    <div class="font-extrabold text-[#002244] uppercase"><i class="fa-solid fa-id-card mr-1"></i> Validação oficial de identidade — Datavalid / Serpro V5</div>
                    <p class="text-xs text-slate-600">As credenciais são armazenadas no arquivo protegido do servidor. O cadastro só prossegue quando CPF e nome forem confirmados pela API. Para produção, é necessário contrato Serpro, credenciamento SENATRAN, GCC e template RFB válidos.</p>
                    <div class="grid grid-cols-1 sm:grid-cols-3 gap-2">
                        <div><label class="block font-bold text-slate-700 mb-1">Ambiente</label><select name="datavalid_environment" class="w-full p-2 border rounded bg-white"><option value="production" <?php echo get_val($APP_CONFIG,'datavalid_environment','production')==='production'?'selected':''; ?>>Produção</option><option value="demo" <?php echo get_val($APP_CONFIG,'datavalid_environment','production')==='demo'?'selected':''; ?>>Demonstração</option></select></div>
                        <div><label class="block font-bold text-slate-700 mb-1">ID do template RFB</label><input type="text" name="datavalid_template_id" value="<?php echo htmlspecialchars(get_val($APP_CONFIG,'datavalid_template_id')); ?>" class="w-full p-2 border rounded bg-white" placeholder="ID fornecido pelo Serpro"></div>
                        <div><label class="block font-bold text-slate-700 mb-1">CNPJ anuente (14 dígitos)</label><input type="text" name="datavalid_cnpj_anuente" value="<?php echo htmlspecialchars(get_val($APP_CONFIG,'datavalid_cnpj_anuente')); ?>" maxlength="18" class="w-full p-2 border rounded bg-white" placeholder="CNPJ da anuente"></div>
                    </div>
                    <div class="grid grid-cols-1 sm:grid-cols-2 gap-2">
                        <div><label class="block font-bold text-slate-700 mb-1">Consumer Key Serpro</label><input type="password" name="datavalid_consumer_key" class="w-full p-2 border rounded bg-white" placeholder="<?php echo !empty($APP_CONFIG['datavalid_consumer_key'])?'•••••••• (salva)':'Consumer Key'; ?>"></div>
                        <div><label class="block font-bold text-slate-700 mb-1">Consumer Secret Serpro</label><input type="password" name="datavalid_consumer_secret" class="w-full p-2 border rounded bg-white" placeholder="<?php echo !empty($APP_CONFIG['datavalid_consumer_secret'])?'•••••••• (salvo)':'Consumer Secret'; ?>"></div>
                    </div>
                    <div><label class="block font-bold text-slate-700 mb-1">Token de autorização da GCC (Datavalid V5)</label><textarea name="datavalid_gcc_token" rows="2" class="w-full p-2 border rounded bg-white font-mono text-xs" placeholder="<?php echo !empty($APP_CONFIG['datavalid_gcc_token'])?'Token salvo — deixe em branco para manter':'Cole aqui o token emitido pela GCC'; ?>"></textarea></div>
                </div>

                <div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
                    <div>
                        <label class="block font-bold text-[#002244] mb-1">Título / Nome do Webmail</label>
                        <input type="text" name="brand_name" value="<?php echo htmlspecialchars($APP_CONFIG['brand_name']); ?>"
                               class="w-full p-2.5 border rounded-lg">
                    </div>
                    <div>
                        <label class="block font-bold text-[#002244] mb-1">Intervalo de Anúncios (A cada X e-mails)</label>
                        <input type="number" name="mobile_ad_interval" min="5" max="50" value="<?php echo (int)$APP_CONFIG['mobile_ad_interval']; ?>"
                               class="w-full p-2.5 border rounded-lg">
                    </div>
                </div>

                <div class="pt-2 border-t flex flex-col sm:flex-row items-center justify-between gap-3">
                    <input type="password" name="admin_pass" required placeholder="Senha Admin do Webmail (admin123)"
                           class="w-full sm:w-64 p-2.5 border border-[#990000] rounded-lg">
                    <button type="submit" class="w-full sm:w-auto px-6 py-2.5 btn-chrome rounded-lg shadow">
                        <i class="fa-solid fa-upload mr-1"></i> Salvar Configurações
                    </button>
                </div>
            </form>

            <!-- BLOCO 2: BANCO DE CARTAZES -->
            <div id="adminAdsSection" class="hidden space-y-5">
                <form id="addAdPoolForm" enctype="multipart/form-data" class="bg-slate-100 p-4 rounded-xl border border-slate-300 space-y-3">
                    <input type="hidden" id="editAdId" name="ad_id" value="">
                    
                    <div class="font-extrabold text-[#002244] uppercase flex items-center justify-between">
                        <span id="formAdTitleMode"><i class="fa-solid fa-plus-circle text-[#475569] mr-1"></i> Depositar Novo Cartaz no Sorteio Randômico</span>
                        <button type="button" id="cancelEditBtn" onclick="resetAdForm()" class="hidden text-xs text-red-600 underline font-normal">Cancelar Edição</button>
                    </div>

                    <div class="grid grid-cols-1 sm:grid-cols-2 gap-2.5">
                        <div>
                            <label class="block font-bold text-slate-700 mb-1">Nome do Anunciante / Empresa</label>
                            <input type="text" id="inputAdSender" name="ad_sender" required placeholder="Ex: RE9 Internet" class="w-full p-2 border rounded-lg bg-white">
                        </div>
                        <div>
                            <label class="block font-bold text-slate-700 mb-1">Etiqueta (Badge)</label>
                            <input type="text" id="inputAdBadge" name="ad_badge" value="Patrocinado" placeholder="Ex: Oferta" class="w-full p-2 border rounded-lg bg-white">
                        </div>
                        <div class="sm:col-span-2">
                            <label class="block font-bold text-slate-700 mb-1">Título do Cartaz</label>
                            <input type="text" id="inputAdTitle" name="ad_title" required placeholder="Ex: Planos de Fibra" class="w-full p-2 border rounded-lg bg-white">
                        </div>
                        <div class="sm:col-span-2">
                            <label class="block font-bold text-slate-700 mb-1">Texto / Descrição</label>
                            <input type="text" id="inputAdDesc" name="ad_desc" required placeholder="Descrição curta" class="w-full p-2 border rounded-lg bg-white">
                        </div>
                        <div>
                            <label class="block font-bold text-slate-700 mb-1">Link externo do anúncio (opcional)</label>
                            <input type="text" id="inputAdUrl" name="ad_url" value="https://www.re9seusite.com.br" placeholder="Produtos da Loja abrem automaticamente no checkout RE9" class="w-full p-2 border rounded-lg bg-white">
                        </div>
                        <div>
                            <label class="block font-bold text-slate-700 mb-1">Texto do Botão (CTA)</label>
                            <input type="text" id="inputAdCta" name="ad_cta" value="Saiba Mais" class="w-full p-2 border rounded-lg bg-white">
                        </div>
                        <div class="sm:col-span-2 rounded-xl border border-emerald-200 bg-emerald-50 p-3 space-y-3">
                            <label class="flex items-center gap-2 font-extrabold text-emerald-900"><input type="checkbox" id="inputAdIsProduct" name="ad_is_product" value="1" class="h-4 w-4"> Definir preço fixo e dados de vendedor para o checkout da Loja RE9</label>
                            <div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
                                <label class="block font-bold text-slate-700">Preço (R$)<input type="number" id="inputAdPrice" name="ad_price" min="0.01" step="0.01" placeholder="Ex.: 149,90" class="mt-1 w-full rounded-lg border border-slate-300 p-2 bg-white"></label>
                                <label class="block font-bold text-slate-700">Categoria<input type="text" id="inputAdCategory" name="ad_category" maxlength="100" placeholder="Ex.: Eletrônicos, Serviços, Moda" class="mt-1 w-full rounded-lg border border-slate-300 p-2 bg-white"></label>
                                <label class="block font-bold text-slate-700">E-mail do anunciante<input type="email" id="inputAdSellerEmail" name="ad_seller_email" value="<?php echo htmlspecialchars($_SESSION['wm_email'], ENT_QUOTES, 'UTF-8'); ?>" placeholder="vendedor@seudominio.com.br" class="mt-1 w-full rounded-lg border border-slate-300 p-2 bg-white"></label>
                                <label class="block font-bold text-slate-700">Tipo de entrega<select id="inputAdFulfillment" name="ad_fulfillment" class="mt-1 w-full rounded-lg border border-slate-300 p-2 bg-white"><option value="digital">Produto digital / liberar acesso</option><option value="physical">Produto físico / enviar</option><option value="service">Serviço / agendamento</option><option value="made_to_order">Sob encomenda / confecção</option></select></label>
                            </div>
                            <p class="text-[11px] leading-relaxed text-emerald-800">Todos os anúncios ativos são exibidos automaticamente na Loja RE9. Cadastre um preço maior que zero para cada produto. O valor será exibido na loja e usado no checkout.</p>
                        </div>
                        <div class="sm:col-span-2">
                            <label class="block font-extrabold text-[#990000] mb-1">Enviar / Alterar Imagem do Cartaz:</label>
                            <input type="file" name="ad_image_file" accept="image/*" class="w-full p-2 border border-slate-300 rounded-lg bg-white">
                        </div>
                    </div>

                    <div class="pt-2 border-t border-slate-300 flex flex-col sm:flex-row items-center justify-between gap-2">
                        <input type="password" id="poolAdminPass" name="admin_pass" required placeholder="Senha Admin (admin123)"
                               class="w-full sm:w-56 p-2 border border-[#990000] rounded-lg bg-white">
                        <button type="submit" id="submitAdBtn" class="w-full sm:w-auto px-5 py-2.5 btn-chrome rounded-lg shadow">
                            <i class="fa-solid fa-plus mr-1"></i> Depositar no Sorteio
                        </button>
                    </div>
                </form>

                <div>
                    <div class="font-bold text-[#002244] mb-2 uppercase">Cartazes Ativos no Banco de Sorteio:</div>
                    <div id="adminAdsListContainer" class="space-y-2 max-h-60 overflow-y-auto pr-1"></div>
                </div>
            </div>

            <!-- BLOCO 3: GERENCIAMENTO DAS CONTAS DE E-MAIL DO CPANEL -->
            <div id="adminMailboxesSection" class="hidden space-y-4">
                <div class="rounded-2xl border border-slate-200 bg-gradient-to-r from-slate-50 to-emerald-50 p-4 shadow-sm">
                    <div class="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
                        <div><div class="text-base font-black text-slate-900"><i class="fa-solid fa-server mr-2 text-emerald-700"></i>Central de gerenciamento de e-mails</div><p class="mt-1 text-xs text-slate-600">Inventário central do cPanel • todos os domínios hospedados nesta conta • controle individual de acesso e conferência de celular.</p></div>
                        <button type="button" onclick="loadAdminMailboxes()" class="rounded-xl bg-emerald-700 px-4 py-2.5 text-xs font-extrabold text-white shadow"><i class="fa-solid fa-rotate mr-1"></i> Sincronizar com cPanel</button>
                    </div>
                    <div class="mt-4 grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-4">
                        <div class="rounded-xl border border-slate-200 bg-white p-3"><div class="text-[10px] font-bold uppercase tracking-wide text-slate-500">Total de contas</div><div id="adminMailboxCount" class="mt-1 text-2xl font-black text-slate-900">—</div></div>
                        <div class="rounded-xl border border-emerald-200 bg-white p-3"><div class="text-[10px] font-bold uppercase tracking-wide text-emerald-700">Ativas</div><div id="adminMailboxActiveCount" class="mt-1 text-2xl font-black text-emerald-700">—</div></div>
                        <div class="rounded-xl border border-red-200 bg-white p-3"><div class="text-[10px] font-bold uppercase tracking-wide text-red-700">Suspensas</div><div id="adminMailboxSuspendedCount" class="mt-1 text-2xl font-black text-red-700">—</div></div>
                        <div class="rounded-xl border border-amber-200 bg-white p-3"><div class="text-[10px] font-bold uppercase tracking-wide text-amber-700">Aguardando revisão</div><div id="adminMailboxPendingCount" class="mt-1 text-2xl font-black text-amber-700">—</div></div>
                    </div>
                </div>
                <div class="flex flex-col gap-2 sm:flex-row"><input type="search" id="adminMailboxSearch" oninput="renderAdminMailboxes()" placeholder="Pesquisar por nome ou endereço de e-mail..." class="min-w-0 flex-1 rounded-xl border border-slate-300 bg-white p-3 text-xs"><div class="rounded-xl bg-slate-100 px-3 py-3 text-[11px] font-semibold text-slate-600">Use “Abrir WhatsApp” para conversar manualmente. Depois de conversar com o cliente, clique em “Liberar” ao lado da conta. O botão também funciona para clientes antigos, sem solicitação pendente.</div></div>
                <div id="adminMailboxDomainStatus" class="rounded-lg border border-blue-200 bg-blue-50 px-3 py-2 text-[11px] leading-relaxed text-blue-900">O inventário será consultado em todos os domínios reconhecidos pelo cPanel.</div>
                <div id="adminMailboxesList" class="space-y-2"><div class="rounded-lg bg-slate-50 p-6 text-center text-xs text-slate-500">Clique em Atualizar lista para consultar o cPanel.</div></div>
                <div class="rounded-xl border border-amber-200 bg-amber-50 p-3 text-[11px] leading-relaxed text-amber-900"><b>Atenção:</b> excluir uma conta remove a caixa e suas mensagens no servidor. A exclusão é permanente e exige confirmação e senha administrativa.</div>
            </div>

        </div>
    </div>
</div>

<!-- JANELA INDEPENDENTE: CAIXAS CONECTADAS ONLINE (ABRE AUTOMATICAMENTE PARA O ADMIN) -->
<div id="onlineUsersModal" role="dialog" aria-modal="true" aria-labelledby="onlineUsersModalTitle" tabindex="-1" class="fixed inset-0 bg-slate-900/80 hidden items-center justify-center z-50 p-2 sm:p-4">
    <div class="bg-white w-full max-w-5xl h-[92vh] rounded-2xl shadow-2xl border-t-4 border-emerald-500 flex flex-col overflow-hidden">
        
        <div class="bg-slate-900 text-white px-5 py-3.5 flex flex-wrap items-center justify-between gap-3 shrink-0">
            <div class="flex items-center gap-2.5">
                <span class="w-3 h-3 rounded-full bg-emerald-400 animate-ping"></span>
                <h3 class="font-extrabold text-sm sm:text-base flex items-center gap-2">
                    <span id="onlineUsersModalTitle">Caixas de E-mail Conectadas Online Agora</span>
                    <span id="vpsOnlineCountHeader" class="px-2.5 py-0.5 rounded-full bg-emerald-500 text-slate-950 text-xs font-black"><?php echo (int)$initial_vps_data['online_count']; ?> online</span>
                </h3>
            </div>
            <div class="flex items-center gap-2">
                <button type="button" onclick="refreshOnlineUsers()" class="px-3.5 py-1.5 rounded-lg bg-[#f28c38] hover:bg-[#e07b27] text-[#00152b] font-extrabold text-xs flex items-center gap-1.5 shadow">
                    <i id="onlineRefreshIcon" class="fa-solid fa-rotate"></i> Atualizar Agora
                </button>
                <button type="button" onclick="closeModal('onlineUsersModal')" class="re9-online-modal-close" title="Fechar janela e liberar o webmail" aria-label="Fechar janela e liberar o webmail">
                    <i class="fa-solid fa-xmark"></i><span class="ml-2 text-sm font-extrabold">FECHAR</span>
                </button>
            </div>
        </div>

        <div class="px-4 py-3 bg-slate-100 border-b border-slate-200 flex flex-col sm:flex-row items-center justify-between gap-2 shrink-0">
            <div class="relative w-full sm:max-w-md">
                <i class="fa-solid fa-magnifying-glass text-slate-400 absolute left-3 top-1/2 -translate-y-1/2 text-xs"></i>
                <input type="text" id="onlineSearchInput" oninput="renderOnlineUsersList()" placeholder="Filtrar por e-mail, IP ou dispositivo (PC/Celular)..."
                       class="w-full pl-8 pr-3 py-2 rounded-lg border border-slate-300 bg-white text-xs outline-none focus:border-emerald-600">
            </div>
            <div class="text-[11px] text-slate-500 font-semibold text-center sm:text-right">
                Atualização automática a cada 10s • Rolagem contínua
                <div id="re9InstancesSummary" class="mt-1 font-bold text-[#002244]">Instalações compartilhadas: identificando domínios...</div>
            </div>
        </div>

        <div id="adminOnlineUsersList" class="flex-1 overflow-y-auto p-4 space-y-2 bg-slate-50"></div>
    </div>
</div>
<?php endif; ?>

<!-- MODAL AGENDA RE9 -->
<div id="agendaModal" class="fixed inset-0 z-[100] hidden items-center justify-center bg-slate-950/70 p-3 sm:p-6">
 <div class="w-full max-w-4xl max-h-[94vh] overflow-y-auto rounded-2xl bg-white shadow-2xl">
  <div class="sticky top-0 z-10 flex items-center justify-between bg-[#002244] px-5 py-4 text-white"><div><h2 class="text-lg font-extrabold"><i class="fa-regular fa-calendar-check mr-2 text-[#f28c38]"></i>Minha agenda</h2><p class="text-xs text-slate-300">Organize seus compromissos no RE9 EMAIL</p></div><button onclick="closeAgendaModal()" class="rounded-lg bg-white/10 px-3 py-2"><i class="fa-solid fa-xmark"></i></button></div>
  <div class="grid gap-5 p-4 sm:p-5 lg:grid-cols-[minmax(0,1fr)_minmax(0,1.1fr)]">
   <form id="agendaForm" class="space-y-3 rounded-xl border border-slate-200 p-4" onsubmit="saveAgendaEvent(event)">
    <input type="hidden" id="agendaId">
    <h3 id="agendaFormTitle" class="font-extrabold text-[#002244]">Novo agendamento</h3>
    <div class="grid grid-cols-2 gap-3"><label class="text-xs font-bold text-slate-600">Data<input required type="date" id="agendaDate" class="mt-1 w-full rounded-lg border border-slate-300 p-2 text-sm"></label><label class="text-xs font-bold text-slate-600">Horário do compromisso<span class="relative mt-1 block w-full min-w-0"><input required type="text" id="agendaTime" readonly inputmode="none" autocomplete="off" data-time-label="Horário do compromisso" onclick="openRe9TimePicker('agendaTime')" onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();openRe9TimePicker('agendaTime')}" class="re9-time-field w-full min-w-0 box-border rounded-lg border border-slate-300 p-2 pr-11 text-sm"><button type="button" onclick="openRe9TimePicker('agendaTime')" class="absolute right-1 top-1/2 -translate-y-1/2 flex h-9 w-9 items-center justify-center rounded-lg text-[#002244] hover:bg-slate-100" aria-label="Selecionar horário do compromisso"><i class="fa-regular fa-clock"></i></button></span></label></div>
    <label class="block rounded-xl border-2 border-[#f28c38] bg-orange-50 p-3 text-sm font-extrabold text-[#7c2d12]"> <i class="fa-regular fa-bell mr-1"></i> Horário para receber o lembrete por e-mail *
     <span class="relative mt-2 block w-full min-w-0"><input required type="text" id="agendaReminderTime" readonly inputmode="none" autocomplete="off" data-time-label="Horário para receber o lembrete" onclick="openRe9TimePicker('agendaReminderTime')" onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();openRe9TimePicker('agendaReminderTime')}" class="re9-time-field w-full min-w-0 box-border rounded-lg border border-orange-300 bg-white p-3 pr-12 text-lg font-bold text-slate-800 focus:border-[#f28c38] focus:outline-none focus:ring-2 focus:ring-orange-200"><button type="button" onclick="openRe9TimePicker('agendaReminderTime')" class="absolute right-1 top-1/2 -translate-y-1/2 flex h-10 w-10 items-center justify-center rounded-lg text-[#9a3412] hover:bg-orange-50" aria-label="Selecionar horário do lembrete"><i class="fa-regular fa-clock"></i></button></span>
     <span class="mt-1 block text-xs font-normal text-orange-900">Escolha quando deseja receber o aviso. Exemplo: compromisso às 16:00, lembrete às 15:30. O sistema sugere 30 minutos antes, mas você pode alterar.</span>
    </label>
    <label class="block text-sm font-bold text-slate-700">Assunto<input required maxlength="180" id="agendaSubject" placeholder="Ex.: Reunião com cliente" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-base"></label>
    <div class="grid grid-cols-2 gap-3"><label class="text-xs font-bold text-slate-600">Tipo de compromisso<input maxlength="100" id="agendaType" placeholder="Reunião, consulta..." class="mt-1 w-full rounded-lg border border-slate-300 p-2 text-sm"></label><label class="text-xs font-bold text-slate-600">Pessoa<input maxlength="180" id="agendaPerson" placeholder="Nome da pessoa" class="mt-1 w-full rounded-lg border border-slate-300 p-2 text-sm"></label></div>
    <div class="grid grid-cols-2 gap-3"><label class="text-xs font-bold text-slate-600">Horário de chegada<span class="relative mt-1 block w-full min-w-0"><input type="text" id="agendaArrival" readonly inputmode="none" autocomplete="off" data-time-label="Horário de chegada" onclick="openRe9TimePicker('agendaArrival')" onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();openRe9TimePicker('agendaArrival')}" class="re9-time-field w-full min-w-0 box-border rounded-lg border border-slate-300 p-2 pr-11 text-sm"><button type="button" onclick="openRe9TimePicker('agendaArrival')" class="absolute right-1 top-1/2 -translate-y-1/2 flex h-9 w-9 items-center justify-center rounded-lg text-[#002244] hover:bg-slate-100" aria-label="Selecionar horário de chegada"><i class="fa-regular fa-clock"></i></button></span></label><label class="text-xs font-bold text-slate-600">Local<input maxlength="250" id="agendaLocation" placeholder="Endereço ou sala" class="mt-1 w-full rounded-lg border border-slate-300 p-2 text-sm"></label></div>
    <label class="block text-sm font-bold text-slate-700">Observações<textarea maxlength="2000" id="agendaNotes" rows="3" placeholder="Informações adicionais..." class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-base"></textarea></label>
    <div class="flex gap-2"><button id="agendaSaveButton" type="submit" class="flex-1 rounded-lg bg-[#002244] px-4 py-2.5 text-sm font-extrabold text-white hover:bg-[#003568]">Salvar agendamento</button><button type="button" onclick="resetAgendaForm()" class="rounded-lg border border-slate-300 px-4 py-2.5 text-sm font-bold text-slate-600">Limpar</button></div>
    <p id="agendaFeedback" class="text-xs text-slate-500" aria-live="polite"></p>
   </form>
   <section><div class="mb-3 flex items-center justify-between"><h3 class="font-extrabold text-[#002244]">Compromissos</h3><button onclick="loadAgendaEvents()" class="text-xs font-bold text-blue-700"><i class="fa-solid fa-rotate mr-1"></i>Atualizar</button></div><div id="agendaEventsList" class="space-y-2"><p class="text-sm text-slate-500">Carregando agenda...</p></div><div class="mt-4 rounded-xl bg-amber-50 p-3 text-xs leading-relaxed text-amber-900"><strong>Lembrete por e-mail:</strong> cada compromisso será enviado para esta própria caixa no horário escolhido no campo destacado. Por exemplo, um compromisso às 16:00 pode gerar o aviso às 15:30. O Cron verifica os horários a cada minuto; se uma execução atrasar, o lembrete pendente será enviado na próxima verificação.</div>
   <?php
   $agenda_is_cron_admin = false;
   $agenda_admin_list = isset($APP_CONFIG['admin_emails']) && is_array($APP_CONFIG['admin_emails']) ? $APP_CONFIG['admin_emails'] : array();
   $agenda_session_email = strtolower(trim((string)get_val($_SESSION, 'wm_email')));
   foreach ($agenda_admin_list as $agenda_admin_email) {
       if (strtolower(trim((string)$agenda_admin_email)) === $agenda_session_email && $agenda_session_email !== '') {
           $agenda_is_cron_admin = true;
           break;
       }
   }
   if ($agenda_is_cron_admin):
       $agenda_cron_url = get_webmail_base_url() . basename(isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : 'index.php') . '?cron_agenda=' . rawurlencode((string)get_val($APP_CONFIG, 'agenda_cron_key'));
       $agenda_cron_command = "curl -fsS '" . $agenda_cron_url . "' >/dev/null 2>&1";
   ?>
   <div class="mt-3 rounded-xl border border-blue-200 bg-blue-50 p-3 text-xs leading-relaxed text-blue-950">
    <strong class="block mb-1">Configuração do Cron (administrador)</strong>
    <p class="mb-2">No cPanel, abra <strong>Cron Jobs</strong> e configure a tarefa para executar a cada minuto. O sistema compara cada lembrete com o horário de São Paulo e só envia os compromissos cujo horário personalizado já chegou.</p>
    <code id="agendaCronCommand" class="block break-all rounded bg-white p-2 text-[11px]"><?php echo htmlspecialchars($agenda_cron_command, ENT_QUOTES, 'UTF-8'); ?></code>
    <button type="button" onclick="copyAgendaCronCommand()" class="mt-2 rounded-lg bg-[#002244] px-3 py-2 font-bold text-white">Copiar comando do Cron</button>
    <p class="mt-2">No cPanel, defina Minuto, Hora, Dia, Mês e Dia da semana como <strong>*</strong> (a cada minuto). A rotina verifica os lembretes durante todo o dia e envia cada um no horário selecionado pelo usuário (fuso America/Sao_Paulo). O comando completo acima já inclui o endereço deste arquivo e a chave de segurança desta instalação.</p>
   </div>
   <?php endif; ?></section>
  </div>
 </div>
</div>

<!-- Seletor de horário RE9: evita o popup nativo cortado em telas menores -->
<div id="re9TimePicker" class="fixed inset-0 z-[12000] hidden items-center justify-center bg-slate-950/65 p-4" role="presentation" onclick="if(event.target===this)closeRe9TimePicker()">
 <div class="w-full max-w-sm max-h-[90dvh] overflow-y-auto rounded-2xl bg-white p-5 shadow-2xl" role="dialog" aria-modal="true" aria-labelledby="re9TimePickerTitle">
  <div class="mb-4 flex items-center gap-3">
   <span class="flex h-11 w-11 items-center justify-center rounded-full bg-blue-50 text-[#002244]"><i class="fa-regular fa-clock text-xl"></i></span>
   <div class="min-w-0"><h3 id="re9TimePickerTitle" class="text-base font-extrabold text-[#002244]">Selecionar horário</h3><p class="text-xs text-slate-500">Escolha a hora e os minutos.</p></div>
  </div>
  <div class="grid grid-cols-2 gap-3">
   <label class="block min-w-0 text-xs font-bold text-slate-600">Hora (24h)<select id="re9TimeHour" class="mt-1 w-full min-w-0 rounded-xl border border-slate-300 bg-white p-3 text-lg font-bold text-slate-900 focus:border-[#002244] focus:outline-none focus:ring-2 focus:ring-blue-100"></select></label>
   <label class="block min-w-0 text-xs font-bold text-slate-600">Minutos<select id="re9TimeMinute" class="mt-1 w-full min-w-0 rounded-xl border border-slate-300 bg-white p-3 text-lg font-bold text-slate-900 focus:border-[#002244] focus:outline-none focus:ring-2 focus:ring-blue-100"></select></label>
  </div>
  <div class="mt-5 grid grid-cols-2 gap-3">
   <button type="button" onclick="closeRe9TimePicker()" class="min-w-0 rounded-xl border border-slate-300 bg-white px-3 py-3 text-sm font-extrabold text-slate-700 hover:bg-slate-50">Cancelar</button>
   <button type="button" onclick="confirmRe9TimePicker()" class="min-w-0 rounded-xl bg-[#002244] px-3 py-3 text-sm font-extrabold text-white hover:bg-[#003568]">Definir horário</button>
  </div>
 </div>
</div>

<!-- CONTATOS RE9 -->
<div id="contactsModal" class="fixed inset-0 z-[105] hidden items-center justify-center bg-slate-950/75 p-3 sm:p-6">
 <div class="w-full max-w-5xl max-h-[94vh] overflow-y-auto rounded-2xl bg-white shadow-2xl">
  <div class="sticky top-0 z-10 flex items-center justify-between bg-[#002244] px-5 py-4 text-white"><div><h2 class="text-lg font-extrabold"><i class="fa-solid fa-address-book mr-2 text-[#f28c38]"></i>Central de contatos</h2><p class="text-xs text-slate-300">Sua lista profissional, organizada e vinculada à sua caixa</p></div><button onclick="closeContactsModal()" class="rounded-lg bg-white/10 px-3 py-2"><i class="fa-solid fa-xmark"></i></button></div>
  <div class="grid gap-5 p-4 sm:p-5 lg:grid-cols-[minmax(280px,.85fr)_minmax(0,1.15fr)]">
   <form id="contactForm" class="space-y-3 rounded-xl border border-slate-200 p-4" onsubmit="saveContact(event)"><input type="hidden" id="contactId"><h3 class="font-extrabold text-[#002244]">Cadastrar contato</h3>
    <label class="block text-sm font-bold text-slate-700">Nome completo *<input required maxlength="160" id="contactName" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-base" placeholder="Nome da pessoa"></label>
    <label class="block text-sm font-bold text-slate-700">Telefone / WhatsApp<input maxlength="30" id="contactPhone" type="tel" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-base" placeholder="+55 (21) 99999-9999"></label>
    <label class="block text-sm font-bold text-slate-700">E-mail<input maxlength="180" id="contactEmail" type="email" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-base" placeholder="usuario@re9.rio.br"><span class="mt-1 block text-xs font-normal text-slate-500">Para mensagens privadas, informe o e-mail de uma conta ativa hospedada na plataforma.</span></label>
    <label class="block text-sm font-bold text-slate-700">Empresa / Organização<input maxlength="160" id="contactCompany" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-base" placeholder="Nome da empresa"></label>
    <label class="block text-sm font-bold text-slate-700">Observações<textarea maxlength="1200" id="contactNotes" rows="3" class="mt-1 w-full rounded-lg border border-slate-300 p-3 text-base" placeholder="Cargo, contexto ou outras informações"></textarea></label>
    <div class="flex gap-2"><button type="submit" class="flex-1 rounded-lg bg-[#002244] px-4 py-2.5 text-sm font-extrabold text-white hover:bg-[#003568]">Salvar contato</button><button type="button" onclick="resetContactForm()" class="rounded-lg border border-slate-300 px-4 py-2.5 text-sm font-bold text-slate-600">Limpar</button></div><p id="contactFeedback" class="text-xs text-slate-500" aria-live="polite"></p>
   </form>
   <section>
    <div class="mb-4 rounded-2xl border-2 border-[#f28c38] bg-orange-50 p-4 shadow-sm">
     <label for="contactsSearch" class="mb-1 block text-base font-extrabold text-[#002244]"><i class="fa-solid fa-magnifying-glass mr-2 text-[#d97706]"></i>Encontre pessoas na plataforma</label>
     <p class="mb-3 text-xs leading-relaxed text-slate-700">Pesquise pelo nome ou pelo endereço de e-mail para localizar usuários cadastrados na rede e adicioná-los à sua lista.</p>
     <input id="contactsSearch" oninput="renderContacts(); searchRe9DirectoryDebounced();" placeholder="Digite o nome ou e-mail do usuário da plataforma..." class="w-full rounded-xl border-2 border-[#f28c38] bg-white p-4 text-base font-semibold text-slate-800 shadow-sm outline-none placeholder:font-normal placeholder:text-slate-400 focus:border-[#002244] focus:ring-2 focus:ring-orange-200">
     <p class="mt-2 px-1 text-xs font-semibold text-orange-900">Digite pelo menos 2 caracteres. Nos resultados da rede, toque em <strong>Adicionar</strong> para salvar a pessoa nos seus contatos.</p>
    </div>
    <div id="re9DirectoryResults" class="mb-3 space-y-2"></div>
    <div id="privateUnreadConversations" class="mb-4 hidden" aria-live="polite"></div>
    <div class="mb-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between"><h3 class="font-extrabold text-[#002244]">Meus contatos salvos</h3><button onclick="loadContacts()" class="text-xs font-bold text-blue-700"><i class="fa-solid fa-rotate mr-1"></i>Atualizar</button></div><div id="contactsList" class="space-y-2"><p class="text-sm text-slate-500">Carregando contatos...</p></div>
    <div class="mt-4 rounded-xl border border-emerald-200 bg-emerald-50 p-4 text-sm leading-relaxed text-emerald-950"><strong><i class="fa-solid fa-envelope mr-1"></i> Mensagens privadas RE9:</strong> envie mensagens para qualquer contato com e-mail válido que você adicionou à sua lista, mesmo que use outro domínio hospedado nesta VPS. O destinatário pode estar online ou offline: a mensagem fica salva e aparece quando ele voltar ao webmail.</div>
   </section>
  </div>
 </div>
</div>

<!-- MODAL DE MENSAGENS PRIVADAS RE9 -->
<div id="privateMessageModal" role="dialog" aria-modal="true" aria-labelledby="privateMessageTitle" tabindex="-1" class="fixed inset-0 z-[130] hidden items-center justify-center bg-slate-950/85 p-4">
 <div class="w-full max-w-md max-h-[88vh] overflow-hidden rounded-2xl bg-white shadow-2xl flex flex-col">
  <div class="bg-[#002244] px-5 py-4 text-white shrink-0">
   <div class="flex items-start justify-between gap-3">
    <div class="min-w-0 flex-1"><p class="text-xs font-bold uppercase tracking-widest text-orange-300">MENSAGENS PRIVADAS</p><h2 id="privateMessageTitle" class="text-lg font-extrabold leading-snug">Conversa privada</h2></div>
    <div class="flex shrink-0 items-center gap-2">
     <span id="privateMessageState" class="rounded-full bg-white/10 px-3 py-1.5 text-xs font-bold">Offline</span>
     <button type="button" onclick="closePrivateMessageModal()" aria-label="Fechar janela da conversa" title="Fechar conversa" class="inline-flex items-center gap-1.5 rounded-lg border border-red-300/70 bg-[#990000] px-3 py-2 text-xs font-extrabold text-white shadow-md transition hover:bg-red-800 focus:outline-none focus:ring-2 focus:ring-white"><i class="fa-solid fa-xmark text-base"></i><span>Fechar</span></button>
    </div>
   </div>
   <p id="privateMessagePeer" class="mt-1 break-all text-xs text-slate-300"></p>
  </div>
  <div id="privateMessageHint" class="border-b border-blue-100 bg-blue-50 px-4 py-2 text-xs leading-relaxed text-blue-900">Você pode enviar mensagens mesmo quando o contato estiver offline.</div>
  <div id="privateMessageHistory" class="min-h-[220px] flex-1 overflow-y-auto bg-slate-100 p-4 space-y-3">
   <div class="py-8 text-center text-xs text-slate-400">Selecione um contato para começar.</div>
  </div>
  <form id="privateMessageForm" onsubmit="sendPrivateMessage(event)" class="shrink-0 border-t border-slate-200 bg-white p-3">
   <div class="flex items-end gap-2">
    <textarea id="privateMessageInput" maxlength="2000" rows="2" placeholder="Escreva sua mensagem privada..." class="min-h-[44px] max-h-28 flex-1 resize-y rounded-xl border border-slate-300 p-3 text-sm outline-none focus:border-[#002244]" disabled></textarea>
    <button id="privateMessageSend" type="submit" class="rounded-xl bg-[#002244] px-4 py-3 text-sm font-extrabold text-white hover:bg-[#003568] disabled:cursor-not-allowed disabled:opacity-50" disabled><i class="fa-solid fa-paper-plane mr-1"></i>Enviar</button>
   </div>
   <div class="mt-2 flex items-center justify-between"><span class="text-[10px] text-slate-400">Enter envia · Shift+Enter cria uma nova linha · Até 2.000 caracteres</span></div>
  </form>
 </div>
</div>
<div id="privateMessageToast" onclick="openPrivateMessageFromToast()" class="fixed left-1/2 top-4 z-[150] hidden w-[min(94vw,460px)] -translate-x-1/2 cursor-pointer rounded-xl border border-orange-200 bg-white p-4 text-slate-800 shadow-2xl ring-1 ring-orange-100">
 <div class="mb-1 flex items-center justify-between gap-3"><strong class="text-sm text-[#002244]"><i class="fa-solid fa-envelope-open-text mr-1.5 text-[#d97706]"></i>Mensagem privada recebida</strong><button type="button" onclick="event.stopPropagation();hidePrivateMessageToast()" aria-label="Fechar aviso" title="Fechar aviso" class="rounded-md px-2 py-1 text-slate-500 hover:bg-slate-100 hover:text-slate-900"><i class="fa-solid fa-xmark text-base"></i></button></div>
 <div id="privateMessageToastText" class="text-xs leading-relaxed text-slate-700"></div>
 <div class="mt-2 text-[10px] font-bold text-blue-700">Clique para abrir a conversa</div>
</div>

<script>
var currentFolder               = 'INBOX';
var currentEmails               = [];
var openedEmail                 = null;
var currentForwardedAttachments = [];
var userSignature               = <?php echo json_encode($user_sig); ?>;
var lastKnownTopUid             = null;
var brandBaseTitle              = <?php echo json_encode($APP_CONFIG['brand_name']); ?>;
var mobileAdInterval            = <?php echo (int)$APP_CONFIG['mobile_ad_interval']; ?>;
<?php $ads_pool_public = array_values($APP_CONFIG['ads_pool']); foreach ($ads_pool_public as &$public_ad_item) { if (!empty($public_ad_item['image'])) $public_ad_item['image'] = re9_public_image_url($public_ad_item['image']); } unset($public_ad_item); ?>
var adsPool                     = <?php echo json_encode($ads_pool_public, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT); ?>;
<?php $re9WelcomeNoticeForUi = re9_central_get_welcome_notice(); ?>
var re9WelcomeNotice            = <?php echo json_encode($re9WelcomeNoticeForUi, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT); ?>;
var re9WelcomeReaderOpen         = false;
var re9CentralConnected          = <?php echo re9_central_is_client_connected() ? 'true' : 'false'; ?>;
async function re9RefreshWelcomeNotice(){
    if(!re9CentralConnected)return;
    try{
        var response=await fetch('?api=central_refresh_public',{credentials:'same-origin',cache:'no-store'});
        var data=await response.json();
        if(!response.ok||data.status!=='ok'||!data.welcome_notice)return;
        var nextNotice=data.welcome_notice;
        if(JSON.stringify(nextNotice)!==JSON.stringify(re9WelcomeNotice)){
            re9WelcomeNotice=nextNotice;
            if(String(currentFolder||'').toUpperCase()==='INBOX' && typeof renderList==='function')renderList(currentEmails||[]);
            if(re9WelcomeReaderOpen){if(re9WelcomeNotice.active)openWelcomeNotice();else backToMobileList();}
        }
        if(Array.isArray(data.ads_pool)&&data.ads_pool.length){adsPool=data.ads_pool;}
    }catch(ignoreCentralRefresh){}
}
if(re9CentralConnected){setInterval(re9RefreshWelcomeNotice,60000);}
var onlineUsersData             = <?php echo json_encode(array_values($initial_vps_data['users'])); ?>;
var userExternalAccounts        = <?php echo json_encode(array_values($user_ext_accounts_public)); ?>;
var currentSidebarAdIx          = -1;
var currentInboxTopAd           = null; // anúncio exibido como primeiro item da lista da caixa de entrada

function re9ResolveImageUrl(value) {
    var raw = String(value || '').trim();
    if (!raw) return '';
    if (raw.toLowerCase().indexOf('data:image/') === 0) return raw;

    var appPath = window.location.pathname || '/index.php';
    var path = raw;
    try {
        if (raw.indexOf('http://') === 0 || raw.indexOf('https://') === 0) {
            var parsed = new URL(raw, window.location.href);
            if (parsed.hostname.toLowerCase() !== window.location.hostname.toLowerCase()) return raw;
            path = parsed.pathname;
        }
    } catch (e) {}

    try { path = decodeURIComponent(path); } catch (e) {}
    path = path.split('?')[0].replace(/\\/g, '/');
    var lowerPath = path.toLowerCase();
    var marker = '/webmail_uploads/';
    var markerAt = lowerPath.lastIndexOf(marker);
    if (markerAt >= 0 || lowerPath.indexOf('webmail_uploads/') === 0) {
        var fileName = path.substring(path.lastIndexOf('/') + 1);
        if (/^[a-z0-9][a-z0-9._-]{0,180}\.(jpg|jpeg|png|gif|webp|bmp)$/i.test(fileName)) {
            return appPath + '?re9_asset=' + encodeURIComponent(fileName);
        }
    }
    if (path.indexOf('/') === -1 && /^[a-z0-9][a-z0-9._-]{0,180}\.(jpg|jpeg|png|gif|webp|bmp)$/i.test(path)) {
        return appPath + '?re9_asset=' + encodeURIComponent(path);
    }
    return raw;
}

// Converte qualquer imagem local de webmail_uploads/ para URL completa com https:// antes de enviar
function makeAbsoluteEmailImages(htmlStr) {
    if (!htmlStr) return '';
    return htmlStr.replace(/src=(["'])([^"']*webmail_uploads\/[^"']+)\1/gi, function(match, quote, imagePath) {
        return 'src=' + quote + re9ResolveImageUrl(imagePath) + quote;
    });
}

userSignature = makeAbsoluteEmailImages(userSignature);

// Alterna entre a Aba 1 (Encaminhamento em 1 Minuto) e Aba 2 (Conexão IMAP)
function switchExtTab(tab) {
    var secFwd  = document.getElementById('extForwardSection');
    var secImap = document.getElementById('extImapSection');
    var btnFwd  = document.getElementById('tabBtnExtForward');
    var btnImap = document.getElementById('tabBtnExtImap');

    if (tab === 'forward') {
        secFwd.classList.remove('hidden');
        secImap.classList.add('hidden');
        btnFwd.className  = 'flex-1 py-3 px-3 border-b-2 border-[#f28c38] text-[#002244] bg-white';
        btnImap.className = 'flex-1 py-3 px-3 border-b-2 border-transparent text-slate-500 hover:text-[#002244]';
    } else {
        secFwd.classList.add('hidden');
        secImap.classList.remove('hidden');
        btnImap.className = 'flex-1 py-3 px-3 border-b-2 border-[#f28c38] text-[#002244] bg-white';
        btnFwd.className  = 'flex-1 py-3 px-3 border-b-2 border-transparent text-slate-500 hover:text-[#002244]';
    }
}

function copyMyWebmailAddress() {
    var addr = document.getElementById('myCurrentWebmailAddr').textContent.trim();
    if (navigator.clipboard) {
        navigator.clipboard.writeText(addr);
    }
    var btnTxt = document.getElementById('btnCopyMyEmailText');
    if (btnTxt) {
        btnTxt.textContent = 'Copiado!';
        setTimeout(function() { btnTxt.textContent = 'Copiar Meu E-mail'; }, 2000);
    }
}

function autoFillImapHost(emailVal) {
    var v = (emailVal || '').toLowerCase();
    var hostInp = document.getElementById('extHostInput');
    if (!hostInp) return;
    if (v.indexOf('@gmail.com') !== -1 || v.indexOf('@googlemail.com') !== -1) {
        hostInp.value = 'imap.gmail.com';
    } else if (v.indexOf('@hotmail.') !== -1 || v.indexOf('@outlook.') !== -1 || v.indexOf('@live.') !== -1 || v.indexOf('@msn.') !== -1) {
        hostInp.value = 'imap-mail.outlook.com';
    } else if (v.indexOf('@yahoo.') !== -1) {
        hostInp.value = 'imap.mail.yahoo.com';
    } else if (v.indexOf('@icloud.com') !== -1) {
        hostInp.value = 'imap.mail.me.com';
    } else if (v.indexOf('@') !== -1) {
        var dom = v.split('@')[1];
        if (dom) hostInp.value = 'mail.' + dom;
    }
}

function renderExternalAccountsList() {
    var container = document.getElementById('extAccountsListContainer');
    if (!container) return;

    if (!userExternalAccounts || !userExternalAccounts.length) {
        container.innerHTML = '<div class="p-4 text-center text-slate-400 text-xs border rounded-xl bg-slate-50">Nenhuma conta conectada via IMAP ainda.</div>';
        return;
    }

    container.innerHTML = userExternalAccounts.map(function(acc) {
        return '<div class="p-3 bg-slate-50 rounded-xl border border-slate-200 flex items-center justify-between gap-2">'
             + '  <div class="min-w-0">'
             + '    <div class="font-extrabold text-xs text-[#002244] truncate"><i class="fa-regular fa-envelope mr-1.5 text-[#f28c38]"></i>' + escapeHtml(acc.email) + '</div>'
             + '    <div class="text-[10px] text-slate-500 truncate mt-0.5">' + escapeHtml(acc.host) + ' • ' + escapeHtml(acc.last_sync || '') + '</div>'
             + '  </div>'
             + '  <button type="button" onclick="deleteExternalAccount(\'' + escapeHtml(acc.email) + '\')" class="px-2.5 py-1.5 rounded-lg btn-blood text-[11px] shrink-0" title="Remover Conta">'
             + '    <i class="fa-regular fa-trash-can"></i>'
             + '  </button>'
             + '</div>';
    }).join('');
}

async function submitAddExternalAccount(e) {
    e.preventDefault();
    var btn = document.getElementById('btnAddExtAccount');
    var msg = document.getElementById('extAccountMsg');
    var fd  = new FormData(e.target);

    btn.disabled = true;
    btn.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin mr-1"></i> Testando conexão IMAP...';
    msg.classList.add('hidden');

    try {
        var res = await fetch('?api=add_external_account', { method: 'POST', body: fd });
        var data = await res.json();
        btn.disabled = false;
        btn.innerHTML = '<i class="fa-solid fa-plug-circle-check mr-1"></i> Conectar via IMAP';

        if (data.status === 'ok') {
            userExternalAccounts = data.accounts || [];
            renderExternalAccountsList();
            e.target.reset();
            msg.textContent = 'Conta conectada com sucesso! Buscando mensagens de hoje...';
            msg.className = 'p-2.5 rounded-lg text-xs font-bold bg-emerald-50 text-emerald-700 border border-emerald-300';
            msg.classList.remove('hidden');
            syncExternalAccountsNow(false);
        } else {
            msg.textContent = data.msg || 'Erro ao conectar conta externa.';
            msg.className = 'p-2.5 rounded-lg text-xs font-bold bg-red-50 text-red-600 border border-red-300';
            msg.classList.remove('hidden');
        }
    } catch (ex) {
        btn.disabled = false;
        btn.innerHTML = '<i class="fa-solid fa-plug-circle-check mr-1"></i> Conectar via IMAP';
        alert('Erro de comunicação.');
    }
}

async function deleteExternalAccount(extEmail) {
    if (!confirm('Remover a importação da conta ' + extEmail + '?')) return;
    var fd = new FormData();
    fd.append('ext_email', extEmail);
    var res = await fetch('?api=delete_external_account', { method: 'POST', body: fd });
    var data = await res.json();
    if (data.status === 'ok') {
        userExternalAccounts = data.accounts || [];
        renderExternalAccountsList();
    }
}

async function syncExternalAccountsNow(silentMode) {
    if (!userExternalAccounts || userExternalAccounts.length === 0) {
        if (!silentMode) {
            openModal('extAccountsModal');
        }
        return;
    }

    var miniIcon  = document.getElementById('extSyncMiniIcon');
    var modalIcon = document.getElementById('extSyncModalIcon');
    if (miniIcon) miniIcon.classList.add('fa-spin');
    if (modalIcon) modalIcon.classList.add('fa-spin');

    try {
        var res = await fetch('?api=sync_external_accounts', { method: 'POST' });
        var data = await res.json();
        if (miniIcon) miniIcon.classList.remove('fa-spin');
        if (modalIcon) modalIcon.classList.remove('fa-spin');

        if (data.status === 'ok') {
            userExternalAccounts = data.accounts || [];
            renderExternalAccountsList();
            if (data.imported_count > 0) {
                loadEmails('INBOX');
                if (!silentMode) {
                    alert(data.imported_count + ' nova(s) mensagem(ns) de hoje trazida(s) para sua Caixa de Entrada!');
                }
            } else if (!silentMode) {
                alert('Sincronização concluída! Nenhuma mensagem nova de hoje pendente.');
            }
        }
    } catch (e) {
        if (miniIcon) miniIcon.classList.remove('fa-spin');
        if (modalIcon) modalIcon.classList.remove('fa-spin');
    }
}

function checkPasswordRules(val, prefix) {
    var hasLen  = val.length >= 8;
    var hasCase = /[A-Z]/.test(val) && /[a-z]/.test(val);
    var hasNum  = /[0-9]/.test(val);
    var hasSym  = /[^a-zA-Z0-9]/.test(val);

    setRuleState(prefix + '_rule_len', hasLen, 'Mínimo de 8 caracteres');
    setRuleState(prefix + '_rule_case', hasCase, 'Letras MAIÚSCULAS e minúsculas');
    setRuleState(prefix + '_rule_num', hasNum, 'Pelo menos 1 número (0-9)');
    setRuleState(prefix + '_rule_sym', hasSym, 'Pelo menos 1 símbolo (@ # $ % ! & *)');

    return hasLen && hasCase && hasNum && hasSym;
}

function setRuleState(elId, ok, text) {
    var el = document.getElementById(elId);
    if (!el) return;
    if (ok) {
        el.className = 'text-emerald-700 font-bold flex items-center gap-1.5';
        el.innerHTML = '<i class="fa-solid fa-circle-check text-emerald-600"></i> ' + text;
    } else {
        el.className = 'text-slate-500 flex items-center gap-1.5';
        el.innerHTML = '<i class="fa-regular fa-circle"></i> ' + text;
    }
}

function generateStrongPasswordInChange() {
    var upper = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
    var lower = 'abcdefghijkmnpqrstuvwxyz';
    var nums  = '23456789';
    var syms  = '@#$%!&*';
    var pass  = '';
    pass += upper.charAt(Math.floor(Math.random() * upper.length));
    pass += upper.charAt(Math.floor(Math.random() * upper.length));
    pass += lower.charAt(Math.floor(Math.random() * lower.length));
    pass += lower.charAt(Math.floor(Math.random() * lower.length));
    pass += lower.charAt(Math.floor(Math.random() * lower.length));
    pass += syms.charAt(Math.floor(Math.random() * syms.length));
    pass += nums.charAt(Math.floor(Math.random() * nums.length));
    pass += nums.charAt(Math.floor(Math.random() * nums.length));
    pass += nums.charAt(Math.floor(Math.random() * nums.length));

    var inp = document.getElementById('changePassNew');
    if (inp) {
        inp.value = pass;
        checkPasswordRules(pass, 'chg');
    }
}

function shuffleArray(arr) {
    var copy = arr.slice();
    for (var i = copy.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = copy[i];
        copy[i] = copy[j];
        copy[j] = temp;
    }
    return copy;
}

function pickRandomAd(excludeIndex) {
    if (!adsPool || adsPool.length === 0) return null;
    if (adsPool.length === 1) return adsPool[0];
    var idx = Math.floor(Math.random() * adsPool.length);
    if (idx === excludeIndex) {
        idx = (idx + 1) % adsPool.length;
    }
    currentSidebarAdIx = idx;
    return adsPool[idx];
}


function re9ResolveAdClickUrl(ad) {
    ad = ad || {};
    var currentPath = window.location.pathname || '/webmail9/index.php';
    var storeHome = currentPath + '?loja=1';
    var productId = String(ad.id || ad.ad_id || '').trim();
    var savedUrl = String(ad.url || '').trim();
    var isProduct = ad.is_product === true || ad.is_product === 1 || String(ad.is_product || '') === '1';
    try {
        var savedTarget = new URL(savedUrl, window.location.href);
        if (isProduct || (savedTarget.searchParams && savedTarget.searchParams.get('loja') === 'checkout')) {
            var savedId = productId || String(savedTarget.searchParams.get('id') || '').trim();
            return savedId ? currentPath + '?loja=checkout&id=' + encodeURIComponent(savedId) : storeHome;
        }
    } catch (ignoreSavedUrl) {
        if (isProduct) return productId ? currentPath + '?loja=checkout&id=' + encodeURIComponent(productId) : storeHome;
    }

    var raw = String(ad.external_url || savedUrl || '').trim();
    if (!raw || raw === '#') return storeHome;
    if (/re9seusite\.com\.br/i.test(raw)) return storeHome;
    if (/^(?:javascript|data|vbscript):/i.test(raw)) return storeHome;
    try {
        var resolved = new URL(raw, window.location.href);
        if (resolved.searchParams && resolved.searchParams.get('loja') === 'checkout') {
            var targetId = productId || String(resolved.searchParams.get('id') || '').trim();
            if (targetId) return currentPath + '?loja=checkout&id=' + encodeURIComponent(targetId);
        }
        if (resolved.protocol !== 'http:' && resolved.protocol !== 'https:') return storeHome;
        if (/^(?:www\.)?re9seusite\.com\.br$/i.test(resolved.hostname)) return storeHome;
        return resolved.href;
    } catch (e) {
        return storeHome;
    }
}

function buildWelcomeMessageRow() {
    if (!re9WelcomeNotice || !re9WelcomeNotice.active) return '';
    var title = String(re9WelcomeNotice.title || 'Bem-vindo ao seu Webmail');
    var body = String(re9WelcomeNotice.body || '').replace(/\s+/g, ' ').trim();
    if (body.length > 170) body = body.slice(0, 167) + '...';
    return '<button type="button" onclick="openWelcomeNotice()" class="w-full text-left border-b border-slate-200 bg-slate-50 hover:bg-slate-100 transition px-3.5 py-3 border-l-2 border-l-[#a33a47]" aria-label="Abrir mensagem fixa de boas-vindas">'
         + '<span class="flex flex-wrap items-center gap-2 mb-1"><span class="rounded-full bg-slate-100 px-2 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-slate-600">Mensagem fixa</span><span class="text-[10px] font-medium uppercase tracking-wider text-slate-500">Comunicado oficial</span><i class="fa-solid fa-thumbtack ml-auto text-[#a33a47]"></i></span>'
         + '<strong class="block text-sm font-semibold text-slate-700">' + escapeHtml(title) + '</strong>'
         + '<span class="mt-0.5 block text-[11px] leading-relaxed font-normal text-slate-500">' + escapeHtml(body) + '</span>'
         + '<span class="mt-1 block text-[10px] font-medium text-blue-700">Clique para conhecer todos os recursos disponíveis</span>'
         + '</button>';
}

function buildInboxFirstAdRow(ad) {
    if (!ad) return '';
    var adHref = re9ResolveAdClickUrl(ad);
    if (/^(?:javascript|data|vbscript):/i.test(adHref)) adHref = '#';
    var advertiserText = cleanAdDisplayText(ad.sender || 'Anunciante RE9');
    var titleText = cleanAdDisplayText(ad.title || '');
    var descriptionText = cleanAdDisplayText(ad.description || '');

    return '<div class="re9-inbox-first-ad-row w-full border-b border-slate-100 bg-white">'
         + '  <a id="re9InboxFirstAdLink" href="' + escapeHtml(adHref) + '" target="_blank" rel="noopener noreferrer" '
         + '     class="flex items-center gap-3 px-3.5 py-3 bg-white hover:bg-orange-50/40 transition" aria-label="Anúncio patrocinado: comprar ou conhecer oferta de ' + escapeHtml(advertiserText) + '">'
         + '    <span class="re9-inbox-ad-cta shrink-0 text-center font-extrabold uppercase" aria-label="Comprar">COMPRAR</span>'
         + '    <span class="flex-1 min-w-0">'
         + '      <span class="re9-inbox-ad-sponsored block text-[10px] font-extrabold uppercase tracking-wider text-orange-700 leading-none mb-1">Patrocinado</span>'
         + '      <span id="re9InboxFirstAdTitle" class="block font-extrabold text-xs text-[#002244] truncate mb-0.5">' + escapeHtml(titleText) + '</span>'
         + '      <span class="block text-[11px] text-slate-500 truncate">'
         + '        <span id="re9InboxFirstAdSender">' + escapeHtml(advertiserText) + '</span>'
         + '        <span class="mx-1">•</span>'
         + '        <span id="re9InboxFirstAdDesc">' + escapeHtml(descriptionText) + '</span>'
         + '      </span>'
         + '    </span>'
         + '  </a>'
         + '</div>';
}

function updateInboxFirstAdCard(ad) {
    if (!ad) return;
    var link = document.getElementById('re9InboxFirstAdLink');
    if (!link) return; // o anúncio será inserido na próxima renderização da lista
    var adHref = re9ResolveAdClickUrl(ad);
    if (/^(?:javascript|data|vbscript):/i.test(adHref)) adHref = '#';
    link.href = adHref;
    var sender = document.getElementById('re9InboxFirstAdSender');
    var title = document.getElementById('re9InboxFirstAdTitle');
    var desc = document.getElementById('re9InboxFirstAdDesc');
    if (sender) sender.textContent = cleanAdDisplayText(ad.sender || 'Anunciante RE9');
    if (title) title.textContent = cleanAdDisplayText(ad.title || '');
    if (desc) desc.textContent = cleanAdDisplayText(ad.description || '');
}

function rotateSingleSidebarAd() {
    var ad = pickRandomAd(currentSidebarAdIx);
    if (!ad) return;

    var urlEl = document.getElementById('singleAdUrl');
    if (urlEl) {
        urlEl.href = re9ResolveAdClickUrl(ad);
        document.getElementById('singleAdSender').textContent = ad.sender || 'Patrocinado';
        document.getElementById('singleAdBadge').textContent  = ad.badge || 'Anúncio';
        document.getElementById('singleAdTitle').textContent  = ad.title || '';
        document.getElementById('singleAdDesc').textContent   = ad.description || '';
        document.getElementById('singleAdCta').textContent    = ad.cta_text || 'Saiba Mais';

        var imgWrap = document.getElementById('singleAdImgWrap');
        var imgEl   = document.getElementById('singleAdImg');
        if (ad.image && ad.image !== '') {
            imgEl.src = re9ResolveImageUrl(ad.image);
            imgWrap.classList.remove('hidden');
        } else {
            imgEl.src = 'https://via.placeholder.com/320x220/002244/475569?text=' + encodeURIComponent(ad.sender || 'PUBLICIDADE');
            imgWrap.classList.remove('hidden');
        }
    }

    var topAd = pickRandomAd(currentSidebarAdIx);
    if (topAd) {
        currentInboxTopAd = topAd;
        updateInboxFirstAdCard(topAd);
    }
}

window.addEventListener('DOMContentLoaded', function() {
    var previewBox = document.getElementById('sigLivePreviewBox');
    if (previewBox) {
        previewBox.innerHTML = userSignature;
    }

    rotateSingleSidebarAd();
    if (<?php echo !empty($_SESSION['wm_email']) ? 'true' : 'false'; ?>) {
        pingSharedPresence();
        setInterval(pingSharedPresence, 15000);
    }
    renderAdminAdsPoolList();
    renderOnlineUsersList();
    renderExternalAccountsList();
    loadEmails('INBOX');

    if ("Notification" in window && Notification.permission === "default") {
        Notification.requestPermission();
    }
    setInterval(checkNewEmailsRealtime, 12000);
    setInterval(rotateSingleSidebarAd, 30000);
    setInterval(function() {
        if (userExternalAccounts && userExternalAccounts.length > 0) {
            syncExternalAccountsNow(true);
        }
    }, 120000);

    // Abre automaticamente a janela independente de Caixas Conectadas assim que o Admin entra
    if (document.getElementById('onlineUsersModal')) {
        openModal('onlineUsersModal');
        refreshOnlineUsers();
        setInterval(refreshOnlineUsers, 10000);
    }
});

async function submitChangePassword(e) {
    e.preventDefault();
    var newPass = document.getElementById('changePassNew').value;
    var resDiv  = document.getElementById('changePassResult');
    var btn     = document.getElementById('btnUpdatePass');

    if (!checkPasswordRules(newPass, 'chg')) {
        resDiv.textContent = 'Atenda a todos os itens da Senha Forte acima antes de salvar.';
        resDiv.className = 'p-3 rounded-lg bg-red-50 border border-red-300 text-red-600 text-xs font-bold';
        resDiv.classList.remove('hidden');
        return;
    }

    var fd = new FormData();
    fd.append('new_pass', newPass);

    btn.disabled = true;
    btn.textContent = 'Atualizando...';
    resDiv.classList.add('hidden');

    try {
        var res = await fetch('?api=update_password', { method: 'POST', body: fd });
        var data = await res.json();
        btn.disabled = false;
        btn.textContent = 'Salvar Nova Senha';

        if (data.status === 'ok') {
            resDiv.textContent = 'Senha alterada com sucesso!';
            resDiv.className = 'p-3 rounded-lg bg-emerald-50 border border-emerald-300 text-emerald-700 text-xs font-bold';
            resDiv.classList.remove('hidden');
            setTimeout(function() { closeModal('changePasswordModal'); resDiv.classList.add('hidden'); }, 2000);
        } else {
            resDiv.textContent = data.msg || 'Erro ao alterar senha.';
            resDiv.className = 'p-3 rounded-lg bg-red-50 border border-red-300 text-red-600 text-xs font-bold';
            resDiv.classList.remove('hidden');
        }
    } catch(ex) {
        btn.disabled = false;
        btn.textContent = 'Salvar Nova Senha';
        alert('Erro de conexão.');
    }
}

function playNotificationSound() {
    try {
        var ctx = new (window.AudioContext || window.webkitAudioContext)();
        var osc = ctx.createOscillator();
        var gain = ctx.createGain();
        osc.type = 'sine';
        osc.frequency.setValueAtTime(587.33, ctx.currentTime);
        osc.frequency.setValueAtTime(880.00, ctx.currentTime + 0.12);
        gain.gain.setValueAtTime(0.2, ctx.currentTime);
        gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 0.45);
        osc.connect(gain);
        gain.connect(ctx.destination);
        osc.start();
        osc.stop(ctx.currentTime + 0.45);
    } catch (e) {}
}

function updateUnreadCounters(unseenCount) {
    var count = parseInt(unseenCount || 0, 10);
    var redBall      = document.getElementById('unreadRedBall');
    var topBadge     = document.getElementById('topUnreadBadge');
    var mobileDot    = document.getElementById('mobileMenuUnreadDot');
    var mobileInline = document.getElementById('mobileInlineUnread');

    if (count > 0) {
        redBall.textContent      = count;
        topBadge.textContent     = count;
        mobileDot.textContent    = count;
        mobileInline.textContent = count + (count === 1 ? ' nova' : ' novas');

        redBall.classList.remove('hidden');
        topBadge.classList.remove('hidden');
        mobileDot.classList.remove('hidden');
        mobileInline.classList.remove('hidden');
        document.title = '(' + count + ') ' + brandBaseTitle;
    } else {
        redBall.classList.add('hidden');
        topBadge.classList.add('hidden');
        mobileDot.classList.add('hidden');
        mobileInline.classList.add('hidden');
        document.title = brandBaseTitle;
    }
}

async function checkNewEmailsRealtime() {
    try {
        var res = await fetch('?api=list_emails&folder=INBOX');
        var data = await res.json();
        if (data.status !== 'ok') return;

        updateUnreadCounters(data.unseen);
        document.getElementById('badgeCount').textContent = data.total;

        if (data.emails && data.emails.length > 0) {
            var newest = data.emails[0];
            if (lastKnownTopUid !== null && newest.uid > lastKnownTopUid) {
                playNotificationSound();
                showNewMailAlert(newest.from_label || newest.from, newest.subject);
                if (currentFolder === 'INBOX') {
                    currentEmails = data.emails;
                    renderList(currentEmails);
                }
            }
            lastKnownTopUid = newest.uid;
        }
    } catch (e) {}
}

function showNewMailAlert(sender, subject) {
    document.getElementById('toastSender').textContent  = sender;
    document.getElementById('toastSubject').textContent = subject;
    var toast = document.getElementById('newMailToast');
    toast.classList.remove('hidden');
    toast.classList.add('flex');

    if ("Notification" in window && Notification.permission === "granted") {
        new Notification("Novo E-mail: " + sender, { body: subject });
    }
    setTimeout(hideToast, 8000);
}

function hideToast() {
    var toast = document.getElementById('newMailToast');
    toast.classList.add('hidden');
    toast.classList.remove('flex');
}

async function loadEmails(folder, btn, titleText) {
    currentFolder = folder || 'INBOX';
    if (btn) {
        document.querySelectorAll('.folder-btn').forEach(function(b) {
            b.classList.remove('bg-[#002244]', 'border-l-4', 'border-[#475569]', 'text-white', 'font-semibold');
        });
        btn.classList.add('bg-[#002244]', 'border-l-4', 'border-[#475569]', 'text-white', 'font-semibold');
    }
    if (titleText) {
        document.getElementById('currentFolderTitle').textContent = titleText;
    }
    closeMobileSidebar();
    backToMobileList();

    var btnDelSel = document.getElementById('btnDeleteSelected');
    var btnEmpty  = document.getElementById('btnEmptyTrash');
    if (currentFolder.toUpperCase() === 'INBOX.TRASH') {
        btnDelSel.classList.add('hidden');
        btnEmpty.classList.remove('hidden');
    } else {
        btnEmpty.classList.add('hidden');
    }

    document.getElementById('selectAllCheckbox').checked = false;
    updateSelectedCount();

    var icon = document.getElementById('refreshIcon');
    if (icon) icon.classList.add('fa-spin');

    var container = document.getElementById('emailListContainer');
    container.innerHTML = '<div class="p-8 text-center text-sm text-slate-400"><i class="fa-solid fa-circle-notch fa-spin text-xl mb-2 text-[#475569]"></i><p>Robô inspecionando e carregando mensagens...</p></div>';

    try {
        var res = await fetch('?api=list_emails&folder=' + encodeURIComponent(currentFolder));
        var data = await res.json();
        if (icon) icon.classList.remove('fa-spin');

        if (data.status === 'ok') {
            currentEmails = data.emails;
            updateUnreadCounters(data.unseen);
            if (currentFolder === 'INBOX') {
                document.getElementById('badgeCount').textContent = data.total;
                if (data.emails.length > 0) {
                    lastKnownTopUid = data.emails[0].uid;
                }
            }
            renderList(currentEmails);
        } else {
            container.innerHTML = '<div class="p-8 text-center text-sm text-slate-400">Nenhum e-mail nesta pasta.</div>';
        }
    } catch (e) {
        if (icon) icon.classList.remove('fa-spin');
        container.innerHTML = '<div class="p-8 text-center text-sm text-[#990000]">Erro de comunicação.</div>';
    }
}

function renderList(list) {
    var container = document.getElementById('emailListContainer');
    var html = '';

    // O anúncio principal entra após a terceira mensagem real da Caixa de Entrada.
    // A mensagem fixa de boas-vindas não conta como mensagem recebida.
    var inboxFirstAdInserted = false;

    var showWelcomeNotice = String(currentFolder || '').toUpperCase() === 'INBOX' && re9WelcomeNotice && re9WelcomeNotice.active;
    if (!list || !list.length) {
        if (showWelcomeNotice) {
            html += buildWelcomeMessageRow();
            html += '<div class="p-8 text-center text-sm text-slate-400"><i class="fa-regular fa-folder-open text-3xl mb-2 block text-[#002244]"></i>Nenhuma outra mensagem nesta pasta.</div>';
        } else {
            html += '<div class="p-10 text-center text-sm text-slate-400"><i class="fa-regular fa-folder-open text-3xl mb-2 block text-[#002244]"></i>Pasta vazia.</div>';
        }
        container.innerHTML = html;
        return;
    }

    var shuffledAds = shuffleArray(adsPool);
    var adPtr = 0;
    var lastGroup = '';
    var groupIndex = -1;
    var welcomeNoticeInserted = false;

    for (var i = 0; i < list.length; i++) {
        var m = list[i];
        var grp = m.date_group || 'Mensagens';

        if (grp !== lastGroup) {
            lastGroup = grp;
            groupIndex++;
            var badgeBg = (grp === 'Hoje') ? 'bg-[#002244] text-white' : 'bg-slate-200 text-[#002244]';
            html += '<div class="px-4 py-2 ' + badgeBg + ' text-xs font-extrabold uppercase tracking-wider flex items-center justify-between sticky top-0 z-10 shadow-xs">'
                  + '  <span><i class="fa-regular fa-calendar-days mr-1.5"></i>' + escapeHtml(grp) + '</span>'
                  + '  <label class="flex items-center gap-1.5 normal-case font-semibold cursor-pointer select-none" title="Selecionar todas as mensagens de ' + escapeHtml(grp) + '">'
                  + '    <span>Selecionar todas</span>'
                  + '    <input type="checkbox" class="group-checkbox w-4 h-4 rounded cursor-pointer accent-slate-600" data-group-key="' + groupIndex + '" aria-label="Selecionar todas as mensagens de ' + escapeHtml(grp) + '" onchange="toggleSelectGroup(this)">'
                  + '  </label>'
                  + '</div>';

            // Comunicado de boas-vindas fixo aparece uma única vez no topo da Caixa de Entrada.
            if (!welcomeNoticeInserted && showWelcomeNotice) {
                html += buildWelcomeMessageRow();
                welcomeNoticeInserted = true;
            }
        }

        var unreadClass = m.seen
            ? 'bg-white text-slate-600 border-l-4 border-transparent'
            : 'bg-slate-50 font-bold text-[#002244] border-l-4 border-[#990000]';

        if (m.suspicious) {
            unreadClass = 'bg-red-50/80 font-bold text-red-950 border-l-4 border-red-600';
        }

        var redDot = m.seen
            ? ''
            : '<span class="inline-block w-2.5 h-2.5 rounded-full bg-[#990000] mr-2 shrink-0" title="Não lida"></span>';

        var botBadge = '';
        if (m.suspicious) {
            botBadge = '<span class="px-1.5 py-0.5 rounded bg-red-600 text-white font-extrabold text-[10px] uppercase mr-1.5 shrink-0 unread-badge-pulse"><i class="fa-solid fa-triangle-exclamation mr-0.5"></i>E-mail Duvidoso</span>';
        } else if (m.trusted) {
            botBadge = '<i class="fa-solid fa-shield-check text-emerald-600 mr-1.5 shrink-0" title="Remetente Válido"></i>';
        }

        html += '<div class="mobile-touch-row flex items-center px-3.5 py-3 hover:bg-slate-50 transition border-b border-slate-100 ' + unreadClass + '">'
              + '  <div class="pr-3.5 shrink-0">'
              + '    <input type="checkbox" class="row-checkbox w-5 h-5 sm:w-4 sm:h-4 rounded text-[#475569] focus:ring-0 cursor-pointer" data-group-key="' + groupIndex + '" value="' + m.uid + '" onchange="updateSelectedCount()">'
              + '  </div>'
              + '  <div class="flex-1 min-w-0 cursor-pointer" onclick="readEmail(' + m.uid + ')">'
              + '    <div class="flex items-center justify-between mb-1">'
              + '      <div class="mobile-email-sender flex items-center text-xs truncate max-w-[210px] sm:max-w-[190px]">' + redDot + botBadge + '<span class="truncate">' + escapeHtml(m.from_label || m.from) + '</span></div>'
              + '      <span class="mobile-email-date text-[11px] text-slate-500 font-semibold shrink-0 ml-2">' + m.date + '</span>'
              + '    </div>'
              + '    <div class="mobile-email-subject text-xs text-slate-800 truncate">' + escapeHtml(m.subject) + '</div>'
              + (m.suspicious ? '<div class="text-[11px] text-red-700 font-bold mt-0.5 truncate">⚠️ Robô de Segurança: Não clique em links!</div>' : '')
              + '  </div>'
              + '</div>';

        // O anúncio principal entra somente depois da terceira mensagem real recebida.
        // A mensagem fixa de boas-vindas não conta como uma das três mensagens.
        var topAdInsertedAfterThisMessage = false;
        if (!inboxFirstAdInserted && String(currentFolder).toUpperCase() === 'INBOX' && currentInboxTopAd && (i + 1) >= 3) {
            html += buildInboxFirstAdRow(currentInboxTopAd);
            inboxFirstAdInserted = true;
            topAdInsertedAfterThisMessage = true;
        }

        // MINI-CARD PATROCINADO INTERCALADO NA LISTA COM AÇÃO COMPRAR.
        // Evita publicidade antes da terceira mensagem e evita duplicar o anúncio principal na mesma posição.
        if (!topAdInsertedAfterThisMessage && (i + 1) > 3 && shuffledAds.length > 0 && (i + 1) % Math.max(3, Number(mobileAdInterval) || 5) === 0) {
            var adObj = shuffledAds[adPtr % shuffledAds.length];
            adPtr++;

            var advertiserText = cleanAdDisplayText(adObj.sender || 'Anunciante RE9');
            var titleText = cleanAdDisplayText(adObj.title || '');
            var descriptionText = cleanAdDisplayText(adObj.description || '');

            html += '<div class="p-2 bg-white border-b border-slate-100">'
                  + '  <a href="' + escapeHtml(re9ResolveAdClickUrl(adObj)) + '" target="_blank" rel="noopener noreferrer" aria-label="Comprar ou conhecer oferta de ' + escapeHtml(advertiserText) + '" '
                  + '     class="re9-message-ad-card block rounded-xl border border-orange-200/90 bg-slate-50 p-3 transition hover:bg-orange-50">'
                  + '    <div class="mb-1.5"><span class="re9-message-ad-sponsored inline-flex rounded-full bg-orange-100 px-2.5 py-1 font-extrabold uppercase tracking-wider text-orange-800">PATROCINADO</span></div>'
                  + '    <div class="truncate text-sm font-extrabold text-[#002244]">' + escapeHtml(advertiserText) + '</div>'
                  + (titleText ? '    <div class="re9-message-ad-text mt-1 font-bold text-slate-800">' + escapeHtml(titleText) + '</div>' : '')
                  + (descriptionText ? '    <div class="re9-message-ad-text mt-0.5 leading-relaxed text-slate-600">' + escapeHtml(descriptionText) + '</div>' : '')
                  + '    <div class="mt-2 flex justify-end"><span class="re9-message-ad-buy inline-flex items-center font-extrabold uppercase" aria-label="Comprar"><i class="fa-solid fa-cart-shopping" aria-hidden="true"></i>COMPRAR</span></div>'
                  + '  </a>'
                  + '</div>';
        }
    }

    // Se a caixa tiver menos de três mensagens, mantém o anúncio depois das mensagens disponíveis,
    // nunca antes delas. Quando chegar a terceira mensagem, a próxima renderização o posiciona ali.
    if (!inboxFirstAdInserted && String(currentFolder).toUpperCase() === 'INBOX' && currentInboxTopAd && list.length > 0) {
        html += buildInboxFirstAdRow(currentInboxTopAd);
        inboxFirstAdInserted = true;
    }

    container.innerHTML = html;
    updateSelectedCount();
}

function toggleSelectAll(masterCheckbox) {
    var checkboxes = document.querySelectorAll('.row-checkbox');
    for (var i = 0; i < checkboxes.length; i++) {
        checkboxes[i].checked = masterCheckbox.checked;
    }
    updateSelectedCount();
}

function toggleSelectGroup(groupCheckbox) {
    if (!groupCheckbox) return;
    var groupKey = groupCheckbox.getAttribute('data-group-key');
    var checkboxes = document.querySelectorAll('.row-checkbox[data-group-key="' + groupKey + '"]');
    for (var i = 0; i < checkboxes.length; i++) {
        checkboxes[i].checked = groupCheckbox.checked;
    }
    updateSelectedCount();
}

function updateSelectedCount() {
    var checkboxes = document.querySelectorAll('.row-checkbox');
    var count = 0;
    for (var i = 0; i < checkboxes.length; i++) {
        if (checkboxes[i].checked) count++;
    }

    // Atualiza o estado de cada grupo (Hoje, Ontem, Esta Semana etc.).
    var groupCheckboxes = document.querySelectorAll('.group-checkbox');
    for (var g = 0; g < groupCheckboxes.length; g++) {
        var groupKey = groupCheckboxes[g].getAttribute('data-group-key');
        var groupRows = document.querySelectorAll('.row-checkbox[data-group-key="' + groupKey + '"]');
        var groupChecked = 0;
        for (var r = 0; r < groupRows.length; r++) {
            if (groupRows[r].checked) groupChecked++;
        }
        groupCheckboxes[g].checked = (groupRows.length > 0 && groupChecked === groupRows.length);
        groupCheckboxes[g].indeterminate = (groupChecked > 0 && groupChecked < groupRows.length);
    }

    // Mantém sincronizada a caixa geral "Selecionar Todas".
    var masterCheckbox = document.getElementById('selectAllCheckbox');
    if (masterCheckbox) {
        masterCheckbox.checked = (checkboxes.length > 0 && count === checkboxes.length);
        masterCheckbox.indeterminate = (count > 0 && count < checkboxes.length);
    }

    var btnDel = document.getElementById('btnDeleteSelected');
    var countSpan = document.getElementById('selectedCount');
    if (countSpan) countSpan.textContent = count;
    if (btnDel && currentFolder.toUpperCase() !== 'INBOX.TRASH') {
        if (count > 0) {
            btnDel.classList.remove('hidden');
        } else {
            btnDel.classList.add('hidden');
        }
    }
}

async function deleteSelectedEmails() {
    var checkboxes = document.querySelectorAll('.row-checkbox:checked');
    if (checkboxes.length === 0) return;

    if (!confirm('Deseja mover as ' + checkboxes.length + ' mensagens selecionadas para a Lixeira?')) return;

    var uids = [];
    for (var i = 0; i < checkboxes.length; i++) {
        uids.push(checkboxes[i].value);
    }

    var fd = new FormData();
    fd.append('folder', currentFolder);
    fd.append('uids', uids.join(','));

    var res = await fetch('?api=delete_email', { method: 'POST', body: fd });
    var data = await res.json();
    if (data.status === 'ok') {
        document.getElementById('emailReader').classList.add('hidden');
        document.getElementById('emptyReader').classList.remove('hidden');
        backToMobileList();
        loadEmails(currentFolder);
    } else {
        alert(data.msg || 'Erro ao excluir mensagens.');
    }
}

async function emptyTrashFolder() {
    if (!confirm('ATENÇÃO: Tem certeza que deseja esvaziar a Lixeira permanentemente?')) return;
    var res = await fetch('?api=empty_trash', { method: 'POST' });
    var data = await res.json();
    if (data.status === 'ok') {
        loadEmails('INBOX.Trash', null, 'LIXEIRA');
    } else {
        alert(data.msg || 'Erro ao esvaziar lixeira.');
    }
}

var openedEmailImagesAllowed = false;

function buildEmailReaderSrcdoc(bodyHtml, lockLinks) {
    var linkLockCss = lockLinks ? 'a { pointer-events:none !important; cursor:not-allowed !important; color:#990000 !important; text-decoration:line-through !important; background:#fee2e2 !important; padding:2px 4px; border-radius:4px; }' : '';
    return '<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><style>body{font-family:-apple-system,Segoe UI,sans-serif;font-size:16px;line-height:1.55;color:#1e293b;padding:10px;margin:0;word-wrap:break-word;}img{max-width:100%;height:auto;}@media(max-width:767px){body{font-size:16.5px;line-height:1.55;}}' + linkLockCss + '</style></head><body>' + (bodyHtml || '') + '</body></html>';
}

function renderOpenedEmailBody() {
    if (!openedEmail) return;
    var bodyHtml = openedEmail.body || '';
    if (openedEmailImagesAllowed) {
        bodyHtml = bodyHtml.replace(/\sdata-re9-remote-src=(['"])(https?:\/\/[^'"]+)\1/gi, function(match, quote, url) {
            return ' src=' + quote + url + quote + ' referrerpolicy="strict-origin-when-cross-origin" loading="lazy" decoding="async"';
        });
    }
    var frame = document.getElementById('readBodyFrame');
    if (frame) frame.srcdoc = buildEmailReaderSrcdoc(bodyHtml, !!openedEmail.suspicious);
}

function updateRemoteEmailImagesNotice() {
    var notice = document.getElementById('remoteEmailImagesNotice');
    var button = document.getElementById('loadRemoteEmailImagesBtn');
    if (!notice || !button) return;
    var bodyHtml = openedEmail && openedEmail.body ? openedEmail.body : '';
    var count = (bodyHtml.match(/data-re9-remote-src=/gi) || []).length;
    if (count > 0 && !openedEmailImagesAllowed) {
        notice.classList.remove('hidden');
        button.textContent = 'Carregar ' + count + (count === 1 ? ' imagem' : ' imagens');
    } else {
        notice.classList.add('hidden');
    }
}

function loadRemoteEmailImages() {
    if (!openedEmail) return;
    openedEmailImagesAllowed = true;
    renderOpenedEmailBody();
    updateRemoteEmailImagesNotice();
}

function openWelcomeNotice() {
    if (!re9WelcomeNotice || !re9WelcomeNotice.active) return;
    re9WelcomeReaderOpen = true;
    openedEmail = null;
    openedEmailImagesAllowed = false;

    var listSec = document.getElementById('emailListSection');
    var readerSec = document.getElementById('emailReaderSection');
    var emptyReader = document.getElementById('emptyReader');
    var reader = document.getElementById('emailReader');
    var actions = document.getElementById('emailReaderActionButtons');
    var warning = document.getElementById('securityBotWarningBanner');
    var trusted = document.getElementById('trustedSenderBadge');
    var remoteNotice = document.getElementById('remoteEmailImagesNotice');
    var welcomeContent = document.getElementById('readWelcomeContent');
    var frame = document.getElementById('readBodyFrame');

    // Guarda o layout em um estado único: lista oculta e leitor visível.
    if (listSec) {
        listSec.classList.add('hidden');
        listSec.classList.remove('flex');
        listSec.style.display = 'none';
    }
    if (readerSec) {
        readerSec.classList.remove('hidden');
        readerSec.classList.add('flex');
        readerSec.style.display = 'flex';
    }
    if (emptyReader) {
        emptyReader.classList.add('hidden');
        emptyReader.style.display = 'none';
    }
    if (reader) {
        reader.classList.remove('hidden');
        reader.classList.add('flex');
        reader.style.display = 'flex';
    }
    // Ações só aparecem em mensagens reais; não devem migrar para a área da logomarca.
    if (actions) {
        actions.classList.add('hidden');
        actions.style.display = 'none';
    }
    if (warning) warning.classList.add('hidden');
    if (trusted) trusted.classList.add('hidden');
    if (remoteNotice) remoteNotice.classList.add('hidden');

    var title = String(re9WelcomeNotice.title || 'Bem-vindo ao seu Webmail');
    var body = String(re9WelcomeNotice.body || '');
    body = body.replace(/\{\{NOME\}\}/g, String((typeof re9WelcomeUserName !== 'undefined' && re9WelcomeUserName) ? re9WelcomeUserName : 'seja muito bem-vindo(a)'));
    body = body.replace(/\{\{EMAIL\}\}/g, String((typeof re9WelcomeUserEmail !== 'undefined' && re9WelcomeUserEmail) ? re9WelcomeUserEmail : ''));
    var safeBody = escapeHtml(body).split(String.fromCharCode(13)).join('').split(String.fromCharCode(10)).join('<br>');
    var published = Number(re9WelcomeNotice.published_at || re9WelcomeNotice.updated_at || 0);

    var subjectEl = document.getElementById('readSubject'); if (subjectEl) subjectEl.textContent = title;
    var fromEl = document.getElementById('readFrom'); if (fromEl) fromEl.textContent = (brandBaseTitle || 'Webmail') + ' — comunicado oficial';
    var toEl = document.getElementById('readTo'); if (toEl) toEl.textContent = 'Todas as caixas desta instalação';
    var dateEl = document.getElementById('readDate'); if (dateEl) dateEl.textContent = published > 0 ? new Date(published * 1000).toLocaleString('pt-BR') : 'Mensagem fixa';
    var avatar = document.getElementById('readSenderAvatar'); if (avatar) avatar.textContent = 'R';

    // O comunicado é renderizado fora do iframe dos e-mails comuns.
    // Recria o conteúdo em todas as aberturas e deixa o iframe explicitamente desligado.
    if (welcomeContent) {
        welcomeContent.innerHTML = '<div class="mx-auto w-full max-w-4xl text-slate-700">'
            + '<div class="mb-4 inline-flex items-center gap-2 rounded-full border border-slate-200 bg-slate-50 px-3 py-1.5 text-[11px] font-medium uppercase tracking-wide text-slate-600"><i class="fa-solid fa-thumbtack text-[#a33a47]"></i>Mensagem oficial fixada</div>'
            + '<h1 class="mb-4 text-xl sm:text-2xl font-semibold text-[#426789]">' + escapeHtml(title) + '</h1>'
            + '<div class="text-[15px] font-normal leading-7 whitespace-normal break-words text-slate-600">' + safeBody + '</div>'
            + '<hr class="my-6 border-slate-200"><p class="text-xs font-normal text-slate-400">Este comunicado permanece fixado na Caixa de Entrada para consulta.</p>'
            + '</div>';
        welcomeContent.classList.remove('hidden');
        welcomeContent.style.display = 'block';
    }
    if (frame) {
        frame.classList.add('hidden');
        frame.style.display = 'none';
    }
    var toggleLbl = document.getElementById('toggleListLabel');
    if (toggleLbl) toggleLbl.textContent = 'Mostrar Lista Lateral';
}


async function readEmail(uid) {
    re9WelcomeReaderOpen = false;
    var actionButtons = document.getElementById('emailReaderActionButtons');
    if (actionButtons) { actionButtons.classList.remove('hidden'); actionButtons.style.display = 'flex'; }
    var welcomeContent = document.getElementById('readWelcomeContent');
    if (welcomeContent) { welcomeContent.classList.add('hidden'); welcomeContent.style.display = 'none'; welcomeContent.innerHTML = ''; }
    var normalBodyFrame = document.getElementById('readBodyFrame');
    if (normalBodyFrame) { normalBodyFrame.classList.remove('hidden'); normalBodyFrame.style.display = 'block'; }

    var listSec = document.getElementById('emailListSection');
    var readerSec = document.getElementById('emailReaderSection');
    var emptyReader = document.getElementById('emptyReader');
    var emailReaderEl = document.getElementById('emailReader');
    if (listSec) { listSec.classList.add('hidden'); listSec.classList.remove('flex'); listSec.style.display = 'none'; }
    if (readerSec) { readerSec.classList.remove('hidden'); readerSec.classList.add('flex'); readerSec.style.display = 'flex'; }
    if (emptyReader) { emptyReader.classList.add('hidden'); emptyReader.style.display = 'none'; }
    if (emailReaderEl) { emailReaderEl.classList.remove('hidden'); emailReaderEl.classList.add('flex'); emailReaderEl.style.display = 'flex'; }

    var toggleLbl = document.getElementById('toggleListLabel');
    if (toggleLbl) toggleLbl.textContent = 'Mostrar Lista Lateral';
    var subjectEl = document.getElementById('readSubject'); if (subjectEl) subjectEl.textContent = 'Robô verificando segurança da mensagem...';
    var warningEl = document.getElementById('securityBotWarningBanner'); if (warningEl) warningEl.classList.add('hidden');
    var trustedEl = document.getElementById('trustedSenderBadge'); if (trustedEl) trustedEl.classList.add('hidden');

    try {
        var res = await fetch('?api=read_email&folder=' + encodeURIComponent(currentFolder) + '&uid=' + uid, {credentials:'same-origin'});
        if (!res.ok) throw new Error('HTTP ' + res.status);
        var data = await res.json();
        if (data.status === 'ok') {
            openedEmail = data;
            openedEmailImagesAllowed = false;
            var readSubject = document.getElementById('readSubject'); if (readSubject) readSubject.textContent = data.subject;
            var readFrom = document.getElementById('readFrom'); if (readFrom) readFrom.textContent = data.from_label || data.from;
            var readTo = document.getElementById('readTo'); if (readTo) readTo.textContent = data.to;
            var readDate = document.getElementById('readDate'); if (readDate) readDate.textContent = data.date;
            var avatarEl = document.getElementById('readSenderAvatar');
            if (avatarEl) {
                var cleanLabel = (data.from_label || data.from || '@').replace(/[^a-zA-Z0-9À-ÿ]/g, '').trim();
                avatarEl.textContent = cleanLabel ? cleanLabel.charAt(0).toUpperCase() : '@';
            }
            var warnBanner = document.getElementById('securityBotWarningBanner');
            var trustedBadge = document.getElementById('trustedSenderBadge');
            if (data.suspicious) {
                if (warnBanner) warnBanner.classList.remove('hidden');
                var senderHighlight = document.getElementById('warnSenderHighlight'); if (senderHighlight) senderHighlight.textContent = data.from || 'Remetente';
                var ipText = document.getElementById('warnIpText'); if (ipText) ipText.textContent = 'IP de Origem: ' + (data.sender_ip ? data.sender_ip + ' (' + (data.sender_server || 'Externo') + ')' : 'Não rastreado');
                var reasonEl = document.getElementById('warnReasonText');
                if (reasonEl) reasonEl.textContent = 'Motivos: ' + ((data.bot_reasons || []).join(' • ') || 'Padrões de risco identificados pelo robô.');
            } else {
                if (warnBanner) warnBanner.classList.add('hidden');
                if (data.trusted && trustedBadge) trustedBadge.classList.remove('hidden');
            }
            renderOpenedEmailBody();
            updateRemoteEmailImagesNotice();
            for (var i = 0; i < currentEmails.length; i++) if (currentEmails[i].uid == uid) currentEmails[i].seen = true;
            renderList(currentEmails);
            if (typeof data.unseen !== 'undefined') updateUnreadCounters(data.unseen);
        } else {
            throw new Error(data.message || data.msg || 'Não foi possível abrir esta mensagem.');
        }
    } catch (err) {
        if (subjectEl) subjectEl.textContent = 'Não foi possível abrir a mensagem';
        var frameErr = document.getElementById('readBodyFrame');
        if (frameErr) { frameErr.classList.remove('hidden'); frameErr.style.display = 'block'; frameErr.srcdoc = '<div style="font-family:Arial,sans-serif;padding:18px;color:#991b1b">' + escapeHtml(err && err.message ? err.message : 'Erro ao abrir mensagem') + '</div>'; }
    }
}


function toggleEmailListCollapse() {
    var listSec   = document.getElementById('emailListSection');
    var toggleLbl = document.getElementById('toggleListLabel');
    if (!listSec) return;

    if (listSec.style.display === 'none' || listSec.classList.contains('hidden')) {
        listSec.classList.remove('hidden');
        listSec.classList.add('flex');
        listSec.style.display = 'flex';
        if (toggleLbl) toggleLbl.textContent = 'Recolher Lista Lateral';
    } else {
        listSec.classList.add('hidden');
        listSec.classList.remove('flex');
        listSec.style.display = 'none';
        if (toggleLbl) toggleLbl.textContent = 'Mostrar Lista Lateral';
    }
}

async function trustCurrentEmailSender() {
    if (!openedEmail) return;
    var fd = new FormData();
    fd.append('sender_email', openedEmail.clean_from || openedEmail.from);

    var res = await fetch('?api=trust_sender', { method: 'POST', credentials: 'same-origin', headers: {'X-RE9-CSRF': RE9_PRIVATE_CSRF}, body: fd });
    var data = await res.json();
    if (data.status === 'ok') {
        document.getElementById('securityBotWarningBanner').classList.add('hidden');
        document.getElementById('trustedSenderBadge').classList.remove('hidden');
        renderOpenedEmailBody();
        updateRemoteEmailImagesNotice();

        for (var i = 0; i < currentEmails.length; i++) {
            if (currentEmails[i].clean_from === openedEmail.clean_from) {
                currentEmails[i].suspicious = false;
                currentEmails[i].trusted = true;
            }
        }
        renderList(currentEmails);
        alert('Remetente (' + (openedEmail.clean_from || openedEmail.from) + ') salvo como E-mail Válido! Os próximos e-mails dele serão recebidos normalmente.');
    }
}

async function blockAndDestroyCurrentEmail() {
    if (!openedEmail) return;
    var info = (openedEmail.clean_from || openedEmail.from);
    if (openedEmail.sender_ip) {
        info += ' (IP: ' + openedEmail.sender_ip + ')';
    }
    if (!confirm('Deseja bloquear este endereço de e-mail e mover a mensagem atual para a Lixeira? As próximas mensagens deste mesmo endereço serão retiradas automaticamente da Entrada. O bloqueio não atinge todo o domínio.')) {
        return;
    }

    var fd = new FormData();
    fd.append('uid', openedEmail.uid);
    fd.append('folder', currentFolder);
    fd.append('sender_email', openedEmail.clean_from || openedEmail.from);
    fd.append('sender_ip', openedEmail.sender_ip || '');
    fd.append('sender_server', openedEmail.sender_server || '');

    var res = await fetch('?api=block_and_delete_sender', { method: 'POST', credentials: 'same-origin', headers: {'X-RE9-CSRF': RE9_PRIVATE_CSRF}, body: fd });
    var data = await res.json();
    if (data.status === 'ok') {
        alert(data.msg || 'Bloqueio ativado! A mensagem atual foi movida para a Lixeira. As próximas mensagens deste endereço serão retiradas automaticamente da Entrada.');
        document.getElementById('emailReader').classList.add('hidden');
        document.getElementById('emptyReader').classList.remove('hidden');
        backToMobileList();
        loadEmails(currentFolder);
    }
}

function backToMobileList() {
    // Restaura o layout original da caixa. Os estilos inline são limpos explicitamente,
    // porque display:flex inline prevalece sobre a classe Tailwind .hidden.
    re9WelcomeReaderOpen = false;
    openedEmail = null;
    openedEmailImagesAllowed = false;

    var welcomeContent = document.getElementById('readWelcomeContent');
    if (welcomeContent) {
        welcomeContent.classList.add('hidden');
        welcomeContent.style.display = 'none';
        welcomeContent.innerHTML = '';
    }
    var frame = document.getElementById('readBodyFrame');
    if (frame) {
        frame.classList.add('hidden');
        frame.style.display = 'none';
        frame.srcdoc = '';
    }
    var actionButtons = document.getElementById('emailReaderActionButtons');
    if (actionButtons) {
        actionButtons.classList.add('hidden');
        actionButtons.style.display = 'none';
    }
    var warning = document.getElementById('securityBotWarningBanner'); if (warning) warning.classList.add('hidden');
    var trusted = document.getElementById('trustedSenderBadge'); if (trusted) trusted.classList.add('hidden');
    var remoteNotice = document.getElementById('remoteEmailImagesNotice'); if (remoteNotice) remoteNotice.classList.add('hidden');

    var listSec = document.getElementById('emailListSection');
    var readerSec = document.getElementById('emailReaderSection');
    var emailReaderEl = document.getElementById('emailReader');
    var emptyReaderEl = document.getElementById('emptyReader');

    if (listSec) {
        listSec.classList.remove('hidden');
        listSec.classList.add('flex');
        listSec.style.display = 'flex';
    }
    if (emailReaderEl) {
        emailReaderEl.classList.add('hidden');
        emailReaderEl.classList.remove('flex');
        emailReaderEl.style.display = 'none';
    }
    if (emptyReaderEl) {
        emptyReaderEl.classList.remove('hidden');
        emptyReaderEl.style.display = 'flex';
    }
    if (readerSec) {
        if (window.innerWidth < 768) {
            readerSec.classList.add('hidden');
            readerSec.classList.remove('flex');
            readerSec.style.display = 'none';
        } else {
            readerSec.classList.remove('hidden');
            readerSec.classList.add('flex');
            readerSec.style.display = 'flex';
        }
    }
    var toggleLbl = document.getElementById('toggleListLabel');
    if (toggleLbl) toggleLbl.textContent = 'Mostrar Lista Lateral';
}


function toggleMobileSidebar() {
    var sb = document.getElementById('folderSidebar');
    var bd = document.getElementById('mobileDrawerBackdrop');
    if (sb.classList.contains('-translate-x-full')) {
        sb.classList.remove('-translate-x-full');
        bd.classList.remove('hidden');
    } else {
        closeMobileSidebar();
    }
}

function closeMobileSidebar() {
    var sb = document.getElementById('folderSidebar');
    var bd = document.getElementById('mobileDrawerBackdrop');
    if (sb) sb.classList.add('-translate-x-full');
    if (bd) bd.classList.add('hidden');
}
function re9UpdateHeaderOffset() {
    var header = document.getElementById('re9FixedTopBar');
    if (!header) return;
    var h = Math.ceil(header.getBoundingClientRect().height || header.offsetHeight || 150);
    document.documentElement.style.setProperty('--re9-header-height', h + 'px');
}
window.addEventListener('load', re9UpdateHeaderOffset, {passive:true});
window.addEventListener('resize', re9UpdateHeaderOffset, {passive:true});
window.addEventListener('orientationchange', function(){ setTimeout(re9UpdateHeaderOffset, 180); }, {passive:true});
(function(){
    var header = document.getElementById('re9FixedTopBar');
    if (header && window.ResizeObserver && !header.dataset.re9ResizeObserved) {
        header.dataset.re9ResizeObserved = '1';
        var observer = new ResizeObserver(function(){ re9UpdateHeaderOffset(); });
        observer.observe(header);
    }
})();
document.addEventListener('keydown', function(e) {
    if (e.key === 'Escape') {
        var online = document.getElementById('onlineUsersModal');
        if (online && !online.classList.contains('hidden')) closeModal('onlineUsersModal');
    }
});

function renderForwardedAttsBox() {
    var attBox = document.getElementById('compForwardedAttsBox');
    if (!attBox) return;

    if (currentForwardedAttachments && currentForwardedAttachments.length > 0) {
        var itemsHtml = currentForwardedAttachments.map(function(a, idx) {
            return '<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-lg bg-white border border-slate-300 font-bold text-[11px] mr-1.5 mb-1 shadow-2xs">'
                 + '<i class="fa-solid fa-paperclip text-[#f28c38]"></i>'
                 + '<span>' + escapeHtml(a.filename) + (a.size ? ' (' + escapeHtml(a.size) + ')' : '') + '</span>'
                 + '<button type="button" onclick="removeForwardedAttachment(' + idx + ')" class="text-slate-400 hover:text-red-600 ml-1" title="Remover anexo"><i class="fa-solid fa-xmark"></i></button>'
                 + '</span>';
        }).join('');
        attBox.innerHTML = '<div class="font-extrabold mb-1 text-[11px] uppercase text-emerald-800"><i class="fa-solid fa-check-circle mr-1"></i>Anexos originais incluídos no encaminhamento:</div><div>' + itemsHtml + '</div>';
        attBox.classList.remove('hidden');
    } else {
        attBox.innerHTML = '';
        attBox.classList.add('hidden');
    }
}

function removeForwardedAttachment(index) {
    if (!currentForwardedAttachments) return;
    currentForwardedAttachments.splice(index, 1);
    renderForwardedAttsBox();
}

function openComposeModal(to, subject, quote, forwardedAtts, composeMode) {
    var heading = document.getElementById('composeModalHeading');
    if (heading) heading.textContent = composeMode === 'reply' ? 'Responder esta mensagem' : (composeMode === 'forward' ? 'Encaminhar esta mensagem' : 'Nova Mensagem');
    document.getElementById('compTo').value = to || '';
    document.getElementById('compSubject').value = subject || '';
    var cleanSig = makeAbsoluteEmailImages(userSignature);
    document.getElementById('compBodyEditor').innerHTML = '<p><br></p>' + cleanSig + (quote || '');
    currentForwardedAttachments = Array.isArray(forwardedAtts) ? forwardedAtts.slice() : [];
    renderForwardedAttsBox();
    openModal('composeModal');
}

function replyCurrentEmail() {
    if (!openedEmail) return;
    var match = openedEmail.from.match(/<([^>]+)>/);
    var replyTo = match ? match[1] : openedEmail.from;
    var subj = openedEmail.subject.indexOf('Re:') === 0 ? openedEmail.subject : 'Re: ' + openedEmail.subject;
    var quote = '<br><hr><div style="font-size:13px;color:#64748b;">Em ' + openedEmail.date + ', <strong>' + escapeHtml(openedEmail.from) + '</strong> escreveu:<br>' + openedEmail.body + '</div>';
    openComposeModal(replyTo, subj, quote, [], 'reply');
}

function forwardCurrentEmail() {
    if (!openedEmail) return;
    var subj = /^(Enc:|Fwd:|Fw:)/i.test(openedEmail.subject) ? openedEmail.subject : 'Enc: ' + openedEmail.subject;
    var forwardHeader = '<br><br><div style="font-family:-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:13px;color:#334155;border-top:1px solid #cbd5e1;padding-top:12px;margin-top:12px;">'
                      + '<strong>---------- Mensagem encaminhada ----------</strong><br>'
                      + '<strong>De:</strong> ' + escapeHtml(openedEmail.from) + '<br>'
                      + '<strong>Data:</strong> ' + escapeHtml(openedEmail.date) + '<br>'
                      + '<strong>Assunto:</strong> ' + escapeHtml(openedEmail.subject) + '<br>'
                      + '<strong>Para:</strong> ' + escapeHtml(openedEmail.to) + '<br><br>'
                      + openedEmail.body
                      + '</div>';
    openComposeModal('', subj, forwardHeader, openedEmail.attachments || [], 'forward');
}

async function deleteCurrentEmail() {
    if (!openedEmail || !confirm('Mover esta mensagem para a Lixeira?')) return;
    var fd = new FormData();
    fd.append('uids', openedEmail.uid);
    fd.append('folder', currentFolder);
    await fetch('?api=delete_email', { method: 'POST', body: fd });
    document.getElementById('emailReader').classList.add('hidden');
    document.getElementById('emptyReader').classList.remove('hidden');
    backToMobileList();
    loadEmails(currentFolder);
}

async function saveAsDraft() {
    var fd = new FormData();
    fd.append('to', document.getElementById('compTo').value.trim());
    fd.append('subject', document.getElementById('compSubject').value.trim());
    fd.append('body', makeAbsoluteEmailImages(document.getElementById('compBodyEditor').innerHTML));
    fd.append('forwarded_attachments', JSON.stringify(currentForwardedAttachments || []));
    var res = await fetch('?api=save_draft', { method: 'POST', body: fd });
    var data = await res.json();
    if (data.status === 'ok') {
        closeModal('composeModal');
        alert('Salvo na pasta Rascunhos!');
    } else {
        alert(data.msg || 'Erro ao salvar rascunho.');
    }
}

async function sendEmailNow() {
    var btn = document.getElementById('btnSendMail');
    var to = document.getElementById('compTo').value.trim();
    if (!to) { alert('Informe o destinatário.'); return; }
    btn.disabled = true;
    btn.textContent = 'Enviando...';

    var bodyHtmlWithAbsoluteImgs = makeAbsoluteEmailImages(document.getElementById('compBodyEditor').innerHTML);

    var fd = new FormData();
    fd.append('to', to);
    fd.append('subject', document.getElementById('compSubject').value.trim());
    fd.append('body', bodyHtmlWithAbsoluteImgs);
    fd.append('forwarded_attachments', JSON.stringify(currentForwardedAttachments || []));

    var res = await fetch('?api=send_email', { method: 'POST', body: fd });
    var data = await res.json();
    btn.disabled = false;
    btn.innerHTML = '<i class="fa-solid fa-paper-plane mr-1"></i> Enviar Agora';

    if (data.status === 'ok') {
        currentForwardedAttachments = [];
        closeModal('composeModal');
        alert('E-mail enviado com sucesso!');
    } else {
        alert(data.msg || 'Erro ao enviar.');
    }
}

function switchAdminTab(tab) {
    var sections = {logo:document.getElementById('brandLogoForm'),ads:document.getElementById('adminAdsSection'),mailboxes:document.getElementById('adminMailboxesSection')};
    var buttons = {logo:document.getElementById('tabBtnLogo'),ads:document.getElementById('tabBtnAds'),mailboxes:document.getElementById('tabBtnMailboxes')};
    var activeCls = 'min-w-0 flex-1 basis-full sm:basis-1/3 py-3 px-2 sm:px-3 border-b-2 border-[#475569] text-[#002244] bg-white whitespace-normal leading-tight';
    var inactiveCls = 'min-w-0 flex-1 basis-full sm:basis-1/3 py-3 px-2 sm:px-3 border-b-2 border-transparent text-slate-500 hover:text-[#002244] whitespace-normal leading-tight';
    Object.keys(sections).forEach(function(key){ if(sections[key]) sections[key].classList.add('hidden'); if(buttons[key]) buttons[key].className=inactiveCls; });
    if(sections[tab]) sections[tab].classList.remove('hidden');
    if(buttons[tab]) buttons[tab].className=activeCls;
    if(tab === 'mailboxes') loadAdminMailboxes();
}

var adminMailboxesCache = [];
async function loadAdminMailboxes() {
    var box = document.getElementById('adminMailboxesList');
    if (!box) return;
    box.innerHTML = '<div class="rounded-lg bg-slate-50 p-6 text-center text-xs text-slate-500"><i class="fa-solid fa-circle-notch fa-spin mr-1"></i> Consultando contas no cPanel...</div>';
    try {
        var response = await fetch('?api=admin_mailboxes_list',{credentials:'same-origin',cache:'no-store'});
        var data = await response.json();
        if (!response.ok || data.status !== 'ok') throw new Error(data.msg || 'Falha ao consultar contas.');
        adminMailboxesCache = data.accounts || [];
        var domainStatus = document.getElementById('adminMailboxDomainStatus');
        if (domainStatus) {
            var checkedDomains = data.domains || [];
            var failedDomains = data.failed_domains || [];
            domainStatus.textContent = 'Domínios consultados: ' + (checkedDomains.length ? checkedDomains.join(' • ') : 'nenhum confirmado') + (failedDomains.length ? ' | ATENÇÃO: falha ao consultar: ' + failedDomains.join(', ') : ' | Todos os domínios reconhecidos foram consultados.');
            domainStatus.className = failedDomains.length ? 'rounded-lg border border-amber-300 bg-amber-50 px-3 py-2 text-[11px] leading-relaxed text-amber-900' : 'rounded-lg border border-emerald-200 bg-emerald-50 px-3 py-2 text-[11px] leading-relaxed text-emerald-900';
        }
        var active = adminMailboxesCache.filter(function(a){return !a.suspended;}).length;
        document.getElementById('adminMailboxCount').textContent = data.count || 0;
        document.getElementById('adminMailboxActiveCount').textContent = active;
        document.getElementById('adminMailboxSuspendedCount').textContent = adminMailboxesCache.length-active;
        document.getElementById('adminMailboxPendingCount').textContent = adminMailboxesCache.filter(function(a){return !!a.pending_review;}).length;
        renderAdminMailboxes();
    } catch(error) {
        box.innerHTML = '<div class="rounded-lg border border-red-200 bg-red-50 p-4 text-xs text-red-700">'+escapeHtml(error.message)+'</div>';
    }
}
function renderAdminMailboxes() {
    var box = document.getElementById('adminMailboxesList'); if (!box) return;
    var q = (document.getElementById('adminMailboxSearch') || {}).value || ''; q=q.toLowerCase().trim();
    var rows = adminMailboxesCache.filter(function(a){return !q || String(a.email).toLowerCase().indexOf(q)>=0 || String(a.name||'').toLowerCase().indexOf(q)>=0;});
    if (!rows.length) { box.innerHTML='<div class="rounded-lg border border-dashed border-slate-300 p-6 text-center text-xs text-slate-500">Nenhuma conta encontrada para esta pesquisa.</div>'; return; }
    box.innerHTML = rows.map(function(a){
        var suspended = !!a.suspended;
        var email = escapeHtml(a.email);
        var name = escapeHtml(a.name || 'Usuário sem nome cadastrado');
        var status = suspended ? '<span class="rounded-full bg-red-100 px-2 py-1 text-[10px] font-extrabold text-red-700">SUSPENSA</span>' : '<span class="rounded-full bg-emerald-100 px-2 py-1 text-[10px] font-extrabold text-emerald-700">ATIVA</span>';
        var phoneStatus = a.manual_release ? '<span class="rounded-full bg-emerald-100 px-2 py-1 text-[10px] font-bold text-emerald-700">LIBERADA PELO SUPORTE</span>' : (a.phone_verified_at ? '<span class="rounded-full bg-emerald-100 px-2 py-1 text-[10px] font-bold text-emerald-700">TELEFONE CONFERIDO • '+escapeHtml(a.phone_last4 || '****')+'</span>' : (a.pending_review ? '<span class="rounded-full bg-amber-100 px-2 py-1 text-[10px] font-bold text-amber-800">AGUARDANDO REVISÃO MANUAL</span>' : '<span class="rounded-full bg-slate-100 px-2 py-1 text-[10px] font-bold text-slate-600">SEM DADOS DE CONFERÊNCIA</span>'));
        var action = suspended ? '<button type="button" data-email="'+email+'" onclick="manageAdminMailbox(this.dataset.email, \'unsuspend\')" class="rounded-lg bg-emerald-700 px-3 py-2 text-[11px] font-bold text-white">Reativar</button>' : '<button type="button" data-email="'+email+'" onclick="manageAdminMailbox(this.dataset.email, \'suspend\')" class="rounded-lg bg-amber-500 px-3 py-2 text-[11px] font-bold text-white">Suspender</button>';
        var phone = String(a.phone||'').replace(/\D/g,'');
        var phoneText = phone ? escapeHtml(phone) : 'Telefone não cadastrado';
        var manualButtons = a.pending_review && phone ? '<button type="button" data-email="'+email+'" onclick="copyAdminPhone(this.dataset.email)" class="rounded-lg border border-slate-300 px-3 py-2 text-[11px] font-bold text-slate-700">Copiar telefone</button><button type="button" data-email="'+email+'" onclick="openAdminWhatsApp(this.dataset.email)" class="rounded-lg bg-green-700 px-3 py-2 text-[11px] font-bold text-white"><i class="fa-brands fa-whatsapp mr-1"></i>Abrir WhatsApp</button>' : '';
        var releaseButton = (a.released || a.phone_verified_at) ? '<span class="rounded-lg bg-emerald-100 px-3 py-2 text-[11px] font-bold text-emerald-800">Liberado</span>' : '<button type="button" data-email="'+email+'" onclick="approveAdminIdentity(this.dataset.email)" class="rounded-lg bg-sky-700 px-3 py-2 text-[11px] font-bold text-white">Liberar</button>';
        return '<div class="flex flex-col gap-3 rounded-xl border border-slate-200 bg-white p-4 shadow-sm xl:flex-row xl:items-center xl:justify-between"><div class="min-w-0 flex-1"><div class="flex flex-wrap items-center gap-2">'+status+'<span class="break-all text-sm font-extrabold text-[#002244]">'+email+'</span></div><div class="mt-1 text-[11px] text-slate-500">'+name+'</div><div class="mt-2">'+phoneStatus+'</div><div class="mt-1 text-xs font-semibold text-slate-700">Telefone: '+phoneText+'</div></div><div class="flex shrink-0 flex-wrap gap-2">'+manualButtons+action+releaseButton+'<button type="button" data-email="'+email+'" onclick="manageAdminMailbox(this.dataset.email, \'delete\')" class="rounded-lg bg-red-700 px-3 py-2 text-[11px] font-bold text-white">Excluir</button></div></div>';
    }).join('');
}
function getAdminAccount(email) { return adminMailboxesCache.find(function(a){return String(a.email).toLowerCase()===String(email).toLowerCase();}) || null; }
async function copyAdminPhone(email) {
    var a=getAdminAccount(email); if(!a || !a.phone) return alert('Telefone não encontrado.');
    try { await navigator.clipboard.writeText(String(a.phone)); alert('Telefone copiado: '+a.phone); }
    catch(e) { window.prompt('Copie o telefone:',String(a.phone)); }
}
function openAdminWhatsApp(email) {
    var a=getAdminAccount(email); if(!a || !a.phone) return alert('Telefone não encontrado.');
    var phone=String(a.phone).replace(/\D/g,''); if(phone.length===10 || phone.length===11) phone='55'+phone;
    var message='Olá! Aqui é da equipe RE9. Estamos realizando uma conferência manual dos dados da sua conta '+email+'. Por favor, confirme se este é seu número de telefone e informe seu nome completo para concluirmos a liberação da sua caixa de e-mail.';
    var url='https://web.whatsapp.com/send?phone='+encodeURIComponent(phone)+'&text='+encodeURIComponent(message);
    window.open(url,'_blank','noopener');
}
async function approveAdminIdentity(email) {
    if(!confirm('Você conversou com a pessoa e conferiu manualmente o telefone '+(getAdminAccount(email)||{}).phone+'?\n\nA conta será liberada para uso completo.')) return;
    var password=window.prompt('Digite a senha administrativa para liberar esta conta:'); if(password===null || password==='') return;
    var body=new URLSearchParams({email:email,admin_pass:password,csrf:RE9_PRIVATE_CSRF});
    try {
        var response=await fetch('?api=admin_identity_review',{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application/x-www-form-urlencoded','X-RE9-CSRF':RE9_PRIVATE_CSRF},body:body.toString()});
        var data=await response.json(); if(!response.ok || data.status!=='ok') throw new Error(data.msg||'Não foi possível liberar a conta.');
        alert(data.msg); await loadAdminMailboxes();
    } catch(e) { alert(e.message||'Falha ao liberar conta.'); }
}

async function manageAdminMailbox(email, operation) {
    var label = operation === 'delete' ? 'EXCLUIR PERMANENTEMENTE a caixa e todas as mensagens de' : (operation === 'suspend' ? 'SUSPENDER o acesso à conta' : 'REATIVAR o acesso à conta');
    if (!confirm(label+' '+email+'?')) return;
    var password = window.prompt('Digite a senha administrativa para confirmar a operação:');
    if (password === null || password === '') return;
    var body = new URLSearchParams({email:email,operation:operation,admin_pass:password,csrf:RE9_PRIVATE_CSRF});
    try {
        var response = await fetch('?api=admin_mailbox_manage',{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application/x-www-form-urlencoded','X-RE9-CSRF':RE9_PRIVATE_CSRF},body:body.toString()});
        var data = await response.json();
        if (!response.ok || data.status !== 'ok') throw new Error(data.msg || 'O cPanel não confirmou a operação.');
        alert(data.msg || 'Operação concluída.');
        await loadAdminMailboxes();
    } catch(error) { alert(error.message || 'Erro ao gerenciar a conta.'); }
}

async function pingSharedPresence() {
    try {
        var response = await fetch('?api=presence_ping', {credentials:'same-origin', cache:'no-store'});
        var data = await response.json();
        if (data && data.status === 'ok') {
            if (Array.isArray(data.ads_pool) && data.ads_pool.length) { adsPool = data.ads_pool; if (typeof rotateSingleSidebarAd === 'function') rotateSingleSidebarAd(); }
            if (data.brand_logo) { var topLogo = document.getElementById('topHeaderLogo'); if (topLogo) topLogo.src = data.brand_logo; }
            if (data.brand_name) { var title = document.getElementById('pageTitle'); if (title) title.textContent = data.brand_name; }
        }
    } catch (e) {}
}

async function refreshOnlineUsers() {
    var icon = document.getElementById('onlineRefreshIcon');
    if (icon) icon.classList.add('fa-spin');
    try {
        var res = await fetch('?api=get_online_users');
        var data = await res.json();
        if (icon) icon.classList.remove('fa-spin');
        if (data.status === 'ok') {
            onlineUsersData = data.users || [];
            var instancesSummary = document.getElementById('re9InstancesSummary');
            if (instancesSummary) {
                var hosts = (data.instances || []).map(function(item){ return item.host; }).filter(Boolean);
                instancesSummary.textContent = hosts.length ? ('Domínios usando a central: ' + hosts.join(' • ')) : 'Nenhum domínio secundário identificado ainda.';
                if (data.shared_storage_ready === false) instancesSummary.textContent += ' • ATENÇÃO: armazenamento central sem permissão de gravação.';
            }
            var countVal = data.online_count || 0;
            var topBadge = document.getElementById('topOnlineCountBadge');
            var hOn      = document.getElementById('vpsOnlineCountHeader');
            if (topBadge) topBadge.textContent = countVal;
            if (hOn) hOn.textContent = countVal + ' online';
            renderOnlineUsersList();
        }
    } catch (e) {
        if (icon) icon.classList.remove('fa-spin');
    }
}

function renderOnlineUsersList() {
    var container = document.getElementById('adminOnlineUsersList');
    if (!container) return;

    var searchInp = document.getElementById('onlineSearchInput');
    var term = searchInp ? searchInp.value.toLowerCase().trim() : '';

    var filtered = (onlineUsersData || []).filter(function(u) {
        if (!term) return true;
        return (u.email || '').toLowerCase().indexOf(term) !== -1 ||
               (u.ip || '').toLowerCase().indexOf(term) !== -1 ||
               (u.device || '').toLowerCase().indexOf(term) !== -1 ||
               (u.access_host || '').toLowerCase().indexOf(term) !== -1;
    });

    if (!filtered.length) {
        container.innerHTML = '<div class="p-8 text-center text-slate-400 text-xs">' + (term ? 'Nenhuma caixa conectada corresponde à busca.' : 'Nenhum usuário conectado com a caixa aberta neste momento.') + '</div>';
        return;
    }

    container.innerHTML = filtered.map(function(u, idx) {
        var devIcon = (u.device === 'Celular') ? 'fa-mobile-screen-button' : 'fa-desktop';
        return '<div class="p-3 bg-white border-emerald-200 rounded-xl border flex items-center justify-between gap-3 shadow-2xs">'
             + '  <div class="flex items-center gap-3 min-w-0">'
             + '    <span class="text-[11px] font-black text-slate-400 w-8 text-right shrink-0">#' + (idx + 1) + '</span>'
             + '    <div class="w-9 h-9 rounded-full bg-[#002244] text-white flex items-center justify-center font-bold text-xs shrink-0 relative">'
             + '      <i class="fa-regular fa-envelope-open"></i>'
             + '      <span class="w-2.5 h-2.5 rounded-full bg-emerald-500 border-2 border-white absolute -bottom-0.5 -right-0.5"></span>'
             + '    </div>'
             + '    <div class="min-w-0">'
             + '      <div class="font-extrabold text-xs sm:text-sm text-[#002244] truncate">' + escapeHtml(u.email) + '</div>'
             + '      <div class="text-[11px] text-slate-600 flex flex-wrap items-center gap-1.5 mt-0.5">'
             + '        <span><i class="fa-solid ' + devIcon + ' mr-1 text-[#002244]"></i>' + escapeHtml(u.device) + '</span>'
             + '        <span>•</span>'
             + '        <span>IP: ' + escapeHtml(u.ip) + '</span>'
             + '        <span>•</span>'
             + '        <span>Acesso por: <b>' + escapeHtml(u.access_host || 'Webmail RE9') + '</b></span>'
             + '      </div>'
             + '    </div>'
             + '  </div>'
             + '  <div class="text-right shrink-0">'
             + '    <span class="inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full bg-emerald-100 text-emerald-800 font-extrabold text-[10px]">'
             + '      <span class="w-1.5 h-1.5 rounded-full bg-emerald-600"></span>CAIXA ABERTA'
             + '    </span>'
             + '    <div class="text-[10px] text-slate-500 mt-1">' + escapeHtml(u.last_seen_fmt || '') + '</div>'
             + '  </div>'
             + '</div>';
    }).join('');
}

function previewSelectedLogo(input) {
    if (input.files && input.files[0]) {
        var reader = new FileReader();
        reader.onload = function(e) {
            document.getElementById('adminLogoPreview').src = e.target.result;
        };
        reader.readAsDataURL(input.files[0]);
    }
}

function renderAdminAdsPoolList() {
    var container = document.getElementById('adminAdsListContainer');
    var countEl   = document.getElementById('adPoolCount');
    if (countEl) countEl.textContent = adsPool.length;
    if (!container) return;

    container.innerHTML = adsPool.map(function(ad) {
        var thumb = ad.image ? '<img src="' + escapeHtml(re9ResolveImageUrl(ad.image)) + '" referrerpolicy="strict-origin-when-cross-origin" class="w-12 h-12 object-cover rounded border">' : '<div class="w-12 h-12 rounded bg-[#002244] text-[#cbd5e1] flex items-center justify-center font-bold text-[10px]">TXT</div>';
        var productInfo = '<div class="mt-1 flex flex-wrap items-center gap-1.5"><label class="text-[10px] font-bold text-emerald-800">Preço R$ <input type="number" min="0.01" step="0.01" id="storePrice_' + escapeHtml(ad.id) + '" value="' + (Number(ad.price || ad.ad_price || 0) > 0 ? Number(ad.price || ad.ad_price).toFixed(2) : '') + '" placeholder="0,00" class="w-24 rounded border border-emerald-300 bg-white px-1.5 py-1 text-xs"></label><button type="button" onclick="saveStoreProductPrice(' + JSON.stringify(String(ad.id)) + ')" class="rounded bg-emerald-700 px-2 py-1 text-[10px] font-bold text-white">Salvar valor</button></div>' + (ad.is_product ? '<a class="text-[10px] text-blue-700 underline" target="_blank" href="' + escapeHtml((window.location.pathname || '') + '?loja=checkout&id=' + encodeURIComponent(ad.id)) + '">Abrir checkout do produto</a>' : '<div class="text-[10px] text-slate-400">Informe o valor para cadastrar este anúncio como produto da loja</div>');
        return '<div class="p-2.5 bg-slate-50 rounded-lg border flex items-center justify-between gap-3">'
             + '  <div class="flex items-center gap-3 min-w-0">'
             +      thumb
             + '    <div class="min-w-0">'
             + '      <div class="font-bold text-xs text-[#002244] truncate">' + escapeHtml(ad.title) + '</div>'
             + '      <div class="text-[11px] text-slate-500 truncate">' + escapeHtml(ad.sender) + '</div>'
             + '      ' + productInfo
             + '    </div>'
             + '  </div>'
             + '  <div class="flex items-center gap-1.5 shrink-0">'
             + '    <button type="button" onclick="editAdInPool(\'' + ad.id + '\')" class="px-2.5 py-1.5 rounded bg-[#475569] hover:bg-[#334155] text-white text-[11px]" title="Editar Anúncio">'
             + '      <i class="fa-solid fa-pen"></i>'
             + '    </button>'
             + '    <button type="button" onclick="deleteAdFromPool(\'' + ad.id + '\')" class="px-2.5 py-1.5 rounded btn-blood text-[11px]" title="Excluir Anúncio">'
             + '      <i class="fa-regular fa-trash-can"></i>'
             + '    </button>'
             + '  </div>'
             + '</div>';
    }).join('');
}

async function saveStoreProductPrice(adId) {
    var priceInput = document.getElementById('storePrice_' + adId);
    var priceValue = priceInput ? String(priceInput.value || '').replace(',', '.') : '';
    if (!priceValue || !isFinite(Number(priceValue)) || Number(priceValue) <= 0) {
        alert('Digite o preço do produto, maior que zero.');
        if (priceInput) priceInput.focus();
        return;
    }
    var pass = document.getElementById('poolAdminPass').value || prompt('Digite a senha de Admin:');
    if (!pass) return;
    var fd = new FormData();
    fd.append('ad_id', adId);
    fd.append('price', priceValue);
    fd.append('admin_pass', pass);
    try {
        var response = await fetch('?api=save_store_product_price', {method:'POST', body:fd});
        var data = await response.json();
        if (data.status === 'ok') {
            adsPool = data.ads_pool || adsPool;
            renderAdminAdsPoolList();
            alert('Preço salvo! O valor atualizado já está cadastrado para a Loja RE9.');
        } else {
            alert(data.msg || 'Não foi possível salvar o preço.');
        }
    } catch (err) {
        alert('Falha de comunicação ao salvar o preço.');
    }
}

function editAdInPool(adId) {
    var ad = adsPool.find(function(item) { return item.id === adId; });
    if (!ad) return;

    document.getElementById('editAdId').value          = ad.id;
    document.getElementById('inputAdSender').value     = ad.sender || '';
    document.getElementById('inputAdBadge').value      = ad.badge || '';
    document.getElementById('inputAdTitle').value      = ad.title || '';
    document.getElementById('inputAdDesc').value       = ad.description || '';
    document.getElementById('inputAdUrl').value        = ad.external_url || ad.url || '';
    document.getElementById('inputAdCta').value        = ad.cta_text || '';
    document.getElementById('inputAdIsProduct').checked = !!Number(ad.is_product || 0);
    document.getElementById('inputAdPrice').value = ad.price || '';
    document.getElementById('inputAdCategory').value = ad.category || '';
    document.getElementById('inputAdSellerEmail').value = ad.seller_email || '';
    document.getElementById('inputAdFulfillment').value = ad.fulfillment || 'digital';

    document.getElementById('formAdTitleMode').innerHTML = '<i class="fa-solid fa-pen text-[#475569] mr-1"></i> Editando Cartaz ID: ' + ad.id;
    document.getElementById('cancelEditBtn').classList.remove('hidden');
    document.getElementById('submitAdBtn').innerHTML = '<i class="fa-solid fa-check mr-1"></i> Atualizar Cartaz';
}

function resetAdForm() {
    document.getElementById('addAdPoolForm').reset();
    document.getElementById('editAdId').value = '';
    document.getElementById('formAdTitleMode').innerHTML = '<i class="fa-solid fa-plus-circle text-[#475569] mr-1"></i> Depositar Novo Cartaz no Sorteio Randômico';
    document.getElementById('cancelEditBtn').classList.add('hidden');
    document.getElementById('submitAdBtn').innerHTML = '<i class="fa-solid fa-plus mr-1"></i> Depositar no Sorteio';
}

var brandLogoFormEl = document.getElementById('brandLogoForm');
if (brandLogoFormEl) {
    brandLogoFormEl.addEventListener('submit', async function(e) {
        e.preventDefault();
        var res = await fetch('?api=save_branding', { method: 'POST', body: new FormData(e.target) });
        var data = await res.json();
        if (data.status === 'ok') {
            alert('Configurações salvas com sucesso!');
            window.location.reload();
        } else {
            alert(data.msg || 'Erro ao salvar.');
        }
    });
}

var signatureCardFormEl = document.getElementById('signatureCardForm');
if (signatureCardFormEl) {
    signatureCardFormEl.addEventListener('submit', async function(e) {
        e.preventDefault();
        var btn = e.target.querySelector('button[type="submit"]');
        btn.disabled = true;
        btn.textContent = 'Salvando cartão...';

        var fd = new FormData(e.target);
        try {
            var res = await fetch('?api=save_signature_card', { method: 'POST', body: fd });
            var data = await res.json();
            btn.disabled = false;
            btn.innerHTML = '<i class="fa-solid fa-check mr-1"></i> Salvar Cartão de Visita';
            if (data.status === 'ok') {
                alert('Cartão de visita salvo com sucesso!');
                window.location.reload();
            } else {
                alert(data.msg || 'Erro ao salvar assinatura.');
            }
        } catch (ex) {
            btn.disabled = false;
            btn.innerHTML = '<i class="fa-solid fa-check mr-1"></i> Salvar Cartão de Visita';
            alert('Erro de comunicação ao salvar assinatura.');
        }
    });
}

var addAdPoolFormEl = document.getElementById('addAdPoolForm');
if (addAdPoolFormEl) {
    addAdPoolFormEl.addEventListener('submit', async function(e) {
        e.preventDefault();
        var res = await fetch('?api=save_ad_pool', { method: 'POST', body: new FormData(e.target) });
        var data = await res.json();
        if (data.status === 'ok') {
            adsPool = data.ads_pool;
            renderAdminAdsPoolList();
            rotateSingleSidebarAd();
            resetAdForm();
            alert('Cartaz salvo com sucesso no sorteio randômico!');
        } else {
            alert(data.msg || 'Erro ao salvar anúncio.');
        }
    });
}

async function deleteAdFromPool(adId) {
    var pass = document.getElementById('poolAdminPass').value || prompt('Digite a senha de Admin (padrão: admin123):');
    if (!pass) return;
    var fd = new FormData();
    fd.append('ad_id', adId);
    fd.append('admin_pass', pass);
    var res = await fetch('?api=delete_ad_pool', { method: 'POST', body: fd });
    var data = await res.json();
    if (data.status === 'ok') {
        adsPool = data.ads_pool;
        renderAdminAdsPoolList();
        rotateSingleSidebarAd();
    } else {
        alert(data.msg || 'Erro ao remover.');
    }
}

async function logoutWebmail() {
    await fetch('?api=logout');
    window.location.reload();
}

function openModal(id) {
    var el = document.getElementById(id);
    if (el) { el.classList.remove('hidden'); el.classList.add('flex'); }
}
function closeModal(id) {
    var el = document.getElementById(id);
    if (el) { el.classList.add('hidden'); el.classList.remove('flex'); }
}
function escapeHtml(t) {
    var d = document.createElement('div');
    d.textContent = t || '';
    return d.innerHTML;
}
function cleanAdDisplayText(value) {
    var text = String(value || '');
    // Oculta endereços web, e-mails e telefones na apresentação ao cliente.
    text = text.replace(/(?:https?:\/\/|www\.)[^\s<]+/gi, ' ');
    text = text.replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, ' ');
    text = text.replace(/(?:\+?\d{1,3}[\s().-]*)?(?:\(?\d{2,3}\)?[\s.-]*)?\d{4,5}[\s.-]?\d{4}\b/g, ' ');
    return text.replace(/\s{2,}/g, ' ').trim();
}
</script>
<?php endif; ?>

<!-- SCRIPT GLOBAL DO PWA -->
<script>
var deferredPwaPrompt = null;

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
        navigator.serviceWorker.register('?pwa=sw').catch(function() {});
    });
}

function isRunningStandalone() {
    return (window.matchMedia('(display-mode: standalone)').matches) || (window.navigator.standalone === true);
}

function isIosDevice() {
    return /iphone|ipad|ipod/i.test(window.navigator.userAgent);
}

window.addEventListener('beforeinstallprompt', function(e) {
    e.preventDefault();
    deferredPwaPrompt = e;
    if (!isRunningStandalone() && !sessionStorage.getItem('pwa_dismissed')) {
        showInstallBannerManual();
    }
});

window.addEventListener('DOMContentLoaded', function() {
    if (!isRunningStandalone() && !sessionStorage.getItem('pwa_dismissed')) {
        setTimeout(function() {
            var banner = document.getElementById('pwaInstallBanner');
            if (banner && banner.classList.contains('hidden')) {
                showInstallBannerManual();
            }
        }, 1500);
    }
});

function showInstallBannerManual() {
    var banner = document.getElementById('pwaInstallBanner');
    if (!banner) return;
    banner.classList.remove('hidden');
    banner.classList.add('flex');

    if (isIosDevice() && !deferredPwaPrompt) {
        document.getElementById('iosInstallHint').classList.remove('hidden');
    }
}

function dismissPwaBanner() {
    sessionStorage.setItem('pwa_dismissed', '1');
    var banner = document.getElementById('pwaInstallBanner');
    if (banner) {
        banner.classList.add('hidden');
        banner.classList.remove('flex');
    }
}

async function triggerPwaInstall() {
    if (deferredPwaPrompt) {
        deferredPwaPrompt.prompt();
        var choice = await deferredPwaPrompt.userChoice;
        if (choice.outcome === 'accepted') {
            dismissPwaBanner();
        }
        deferredPwaPrompt = null;
    } else if (isIosDevice()) {
        document.getElementById('iosInstallHint').classList.remove('hidden');
        alert('No iPhone/iPad: Toque no botão "Compartilhar" do Safari na barra inferior e escolha "Adicionar à Tela de Início".');
    } else {
        alert('Para instalar o aplicativo na tela inicial: toque nos 3 pontinhos do navegador no canto superior direito e selecione "Instalar aplicativo" ou "Adicionar à tela inicial".');
    }
}

// ================= AGENDA RE9 =================
function openAgendaModal(){var m=document.getElementById('agendaModal');m.classList.remove('hidden');m.classList.add('flex');loadAgendaEvents();}
function closeAgendaModal(){var m=document.getElementById('agendaModal');m.classList.add('hidden');m.classList.remove('flex');}
function resetAgendaForm(){document.getElementById('agendaForm').reset();document.getElementById('agendaId').value='';document.getElementById('agendaFeedback').textContent='';var title=document.getElementById('agendaFormTitle');if(title)title.textContent='Novo agendamento';var saveButton=document.getElementById('agendaSaveButton');if(saveButton)saveButton.textContent='Salvar agendamento';}
async function agendaRequest(action,data){var body=new URLSearchParams(data||{});var response=await fetch('?api='+action,{method:action==='agenda_list'?'GET':'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body:action==='agenda_list'?undefined:body.toString(),credentials:'same-origin'});return await response.json();}
function agendaEscape(s){return String(s||'').replace(/[&<>"']/g,function(c){return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c];});}
function agendaDefaultReminderTime(appointmentTime){var m=/^([01]\d|2[0-3]):([0-5]\d)$/.exec(String(appointmentTime||''));if(!m)return '06:00';var total=Math.max(0,(parseInt(m[1],10)*60+parseInt(m[2],10))-30);return String(Math.floor(total/60)).padStart(2,'0')+':'+String(total%60).padStart(2,'0');}
function setDefaultAgendaReminderTime(){var appointment=document.getElementById('agendaTime');var reminder=document.getElementById('agendaReminderTime');if(appointment&&reminder&&appointment.value&&!reminder.value){reminder.value=agendaDefaultReminderTime(appointment.value);}}

var re9TimePickerTarget = null;
function re9InitTimePickerOptions(){
    var hour=document.getElementById('re9TimeHour');
    var minute=document.getElementById('re9TimeMinute');
    if(!hour||!minute||hour.options.length) return;
    for(var h=0;h<24;h++){var ho=document.createElement('option');ho.value=String(h).padStart(2,'0');ho.textContent=ho.value;hour.appendChild(ho);}
    for(var m=0;m<60;m++){var mo=document.createElement('option');mo.value=String(m).padStart(2,'0');mo.textContent=mo.value;minute.appendChild(mo);}
}
function openRe9TimePicker(inputId){
    var input=document.getElementById(inputId);
    var picker=document.getElementById('re9TimePicker');
    var hour=document.getElementById('re9TimeHour');
    var minute=document.getElementById('re9TimeMinute');
    if(!input||!picker||!hour||!minute) return;
    re9InitTimePickerOptions();
    re9TimePickerTarget=inputId;
    var match=/^([01]\d|2[0-3]):([0-5]\d)$/.exec(String(input.value||''));
    var initial=match?match:['','09','00'];
    hour.value=initial[1];
    minute.value=initial[2];
    var title=document.getElementById('re9TimePickerTitle');
    if(title) title.textContent=input.getAttribute('data-time-label')||'Selecionar horário';
    picker.classList.remove('hidden');picker.classList.add('flex');
    document.body.classList.add('re9-timepicker-open');
    window.setTimeout(function(){hour.focus();},30);
}
function closeRe9TimePicker(){
    var picker=document.getElementById('re9TimePicker');
    if(picker){picker.classList.add('hidden');picker.classList.remove('flex');}
    document.body.classList.remove('re9-timepicker-open');
    var target=re9TimePickerTarget;re9TimePickerTarget=null;
    var input=target?document.getElementById(target):null;if(input){try{input.focus({preventScroll:true});}catch(e){input.focus();}}
}
function confirmRe9TimePicker(){
    var hour=document.getElementById('re9TimeHour');
    var minute=document.getElementById('re9TimeMinute');
    var target=re9TimePickerTarget;
    var input=target?document.getElementById(target):null;
    if(!input||!hour||!minute)return;
    input.value=String(hour.value).padStart(2,'0')+':'+String(minute.value).padStart(2,'0');
    input.dispatchEvent(new Event('input',{bubbles:true}));
    input.dispatchEvent(new Event('change',{bubbles:true}));
    if(target==='agendaTime') setDefaultAgendaReminderTime();
    closeRe9TimePicker();
}
document.addEventListener('keydown',function(event){if(event.key==='Escape'){var picker=document.getElementById('re9TimePicker');if(picker&&!picker.classList.contains('hidden')){event.preventDefault();closeRe9TimePicker();}}});
async function loadAgendaEvents() {
    var box = document.getElementById('agendaEventsList');
    if (!box) return;
    box.innerHTML = '<p class="text-sm text-slate-500">Carregando...</p>';
    try {
        var r = await agendaRequest('agenda_list');
        if (!r || r.status !== 'ok') throw new Error((r && r.msg) || 'Não foi possível carregar a agenda.');
        var items = Array.isArray(r.items) ? r.items : [];
        if (!items.length) {
            box.innerHTML = '<p class="rounded-lg border border-dashed border-slate-300 p-5 text-center text-sm text-slate-500">Nenhum compromisso cadastrado.</p>';
            return;
        }
        box.innerHTML = items.map(function(a) {
            var id = agendaEscape(a.id || '');
            var rawDate = String(a.date || '');
            var dateLabel = rawDate.indexOf('-') !== -1 ? rawDate.split('-').reverse().join('/') : rawDate;
            return '<article class="rounded-xl border border-slate-200 p-3">'
                 + '<div class="flex items-start justify-between gap-2">'
                 + '<div class="min-w-0">'
                 + '<p class="text-xs font-bold text-[#990000]">' + agendaEscape(dateLabel) + ' • ' + agendaEscape(a.time || '') + '</p>'
                 + '<p class="mt-1 text-xs font-bold text-orange-700"><i class="fa-regular fa-bell mr-1"></i>Lembrete por e-mail: ' + agendaEscape(a.reminder_time || agendaDefaultReminderTime(a.time)) + '</p>'
                 + '<h4 class="mt-1 font-extrabold text-slate-800">' + agendaEscape(a.subject || '') + '</h4>'
                 + '<p class="text-xs text-slate-500">' + agendaEscape(a.type || '') + (a.person ? ' • ' + agendaEscape(a.person) : '') + '</p>'
                 + '</div>'
                 + '<div class="flex shrink-0 gap-1">'
                 + '<button type="button" data-agenda-action="edit" data-agenda-id="' + id + '" class="rounded-md bg-slate-100 px-2 py-1 text-xs text-blue-800 hover:bg-blue-100" title="Editar compromisso"><i class="fa-solid fa-pen"></i></button>'
                 + '<button type="button" data-agenda-action="delete" data-agenda-id="' + id + '" class="rounded-md bg-red-50 px-2 py-1 text-xs text-red-700 hover:bg-red-100" title="Excluir compromisso"><i class="fa-solid fa-trash"></i></button>'
                 + '</div></div>'
                 + (a.arrival ? '<p class="mt-2 text-xs text-slate-600">Chegar às: ' + agendaEscape(a.arrival) + '</p>' : '')
                 + (a.location ? '<p class="text-xs text-slate-600">Local: ' + agendaEscape(a.location) + '</p>' : '')
                 + (a.notes ? '<p class="mt-1 whitespace-pre-wrap text-xs text-slate-600">' + agendaEscape(a.notes) + '</p>' : '')
                 + '</article>';
        }).join('');

        // Delegação de eventos evita aspas quebradas em onclick e mantém os botões funcionais após atualizar a lista.
        box.onclick = function(event) {
            var target = event.target;
            while (target && target !== box && !(target.getAttribute && target.getAttribute('data-agenda-action'))) {
                target = target.parentNode;
            }
            if (!target || target === box) return;
            var action = target.getAttribute('data-agenda-action');
            var id = target.getAttribute('data-agenda-id');
            if (!id) return;
            if (action === 'edit') editAgendaEvent(id);
            if (action === 'delete') deleteAgendaEvent(id);
        };
    } catch (e) {
        box.innerHTML = '<p class="text-sm text-red-600">' + agendaEscape(e.message || 'Erro ao carregar a agenda.') + '</p>';
    }
}
async function saveAgendaEvent(e) {
    e.preventDefault();
    var data = {
        id: document.getElementById('agendaId').value,
        date: document.getElementById('agendaDate').value,
        time: document.getElementById('agendaTime').value,
        reminder_time: document.getElementById('agendaReminderTime').value,
        subject: document.getElementById('agendaSubject').value,
        type: document.getElementById('agendaType').value,
        person: document.getElementById('agendaPerson').value,
        arrival: document.getElementById('agendaArrival').value,
        location: document.getElementById('agendaLocation').value,
        notes: document.getElementById('agendaNotes').value
    };
    var feedback = document.getElementById('agendaFeedback');
    try {
        var r = await agendaRequest('agenda_save', data);
        if (!r || r.status !== 'ok') throw new Error((r && r.msg) || 'Erro ao salvar o agendamento.');
        feedback.textContent = 'Agendamento salvo com sucesso.';
        resetAgendaForm();
        await loadAgendaEvents();
    } catch (err) {
        feedback.textContent = err.message || 'Não foi possível salvar o agendamento.';
    }
}
async function editAgendaEvent(id) {
    var feedback = document.getElementById('agendaFeedback');
    try {
        var r = await agendaRequest('agenda_list');
        if (!r || r.status !== 'ok') throw new Error((r && r.msg) || 'Não foi possível abrir o compromisso.');
        var items = Array.isArray(r.items) ? r.items : [];
        var a = null;
        for (var i = 0; i < items.length; i++) {
            if (String(items[i].id) === String(id)) { a = items[i]; break; }
        }
        if (!a) throw new Error('O compromisso selecionado não foi encontrado. Atualize a agenda.');
        document.getElementById('agendaId').value = a.id || '';
        ['date','time','subject','type','person','arrival','location','notes'].forEach(function(k) {
            var el = document.getElementById('agenda' + k.charAt(0).toUpperCase() + k.slice(1));
            if (el) el.value = a[k] || '';
        });
        document.getElementById('agendaReminderTime').value = a.reminder_time || agendaDefaultReminderTime(a.time);
        feedback.textContent = 'Editando compromisso selecionado. Altere os dados e clique em Atualizar agendamento.';
        var title = document.getElementById('agendaFormTitle');
        if (title) title.textContent = 'Editar agendamento';
        var saveButton = document.getElementById('agendaSaveButton');
        if (saveButton) saveButton.textContent = 'Atualizar agendamento';
        document.getElementById('agendaForm').scrollIntoView({behavior:'smooth', block:'start'});
    } catch (err) {
        feedback.textContent = err.message || 'Erro ao editar o compromisso.';
    }
}
async function deleteAgendaEvent(id) {
    if (!confirm('Deseja excluir este agendamento?')) return;
    try {
        var r = await agendaRequest('agenda_delete', {id:id});
        if (!r || r.status !== 'ok') throw new Error((r && r.msg) || 'Erro ao excluir o agendamento.');
        document.getElementById('agendaFeedback').textContent = 'Agendamento excluído.';
        await loadAgendaEvents();
        if (document.getElementById('agendaId').value === String(id)) resetAgendaForm();
    } catch (e) {
        alert(e.message || 'Não foi possível excluir o agendamento.');
    }
}

// ================= CONTATOS RE9 =================
var re9ContactsCache = [];
function openContactsModal(){var m=document.getElementById('contactsModal');m.classList.remove('hidden');m.classList.add('flex');loadContacts();}
function closeContactsModal(){var m=document.getElementById('contactsModal');m.classList.add('hidden');m.classList.remove('flex');}
function contactEscape(s){return String(s||'').replace(/[&<>"']/g,function(c){return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c];});}
async function contactsRequest(action,data){var method=action==='contacts_list'?'GET':'POST';var body=new URLSearchParams(data||{});var headers={'Content-Type':'application/x-www-form-urlencoded'};if(method==='POST'){headers['X-RE9-CSRF']=RE9_PRIVATE_CSRF||'';body.set('csrf',RE9_PRIVATE_CSRF||'');}var response=await fetch('?api='+encodeURIComponent(action),{method:method,headers:headers,body:method==='POST'?body.toString():undefined,credentials:'same-origin',cache:'no-store'});var result=await response.json();if(!response.ok||result.status==='error'||result.status==='pending_review')throw new Error(result.msg||'Não foi possível concluir a operação.');return result;}
var re9AutoChatPeer = <?php echo json_encode(strtolower(trim((string)get_val($_GET, 'chat_with', '')))); ?>;
var re9AutoChatOpened = false;
async function loadContacts(){var box=document.getElementById('contactsList');if(box)box.innerHTML='<p class="text-sm text-slate-500">Carregando...</p>';try{var r=await contactsRequest('contacts_list');if(r.status!=='ok')throw new Error(r.msg||'Não foi possível carregar os contatos.');re9ContactsCache=r.items||[];renderContacts();if(re9AutoChatPeer&&!re9AutoChatOpened){var peer=re9ContactsCache.find(function(c){return String(c.email||'').toLowerCase()===re9AutoChatPeer;});if(peer){re9AutoChatOpened=true;openPrivateMessageFor(re9AutoChatPeer,peer.name||re9AutoChatPeer);}}}catch(e){if(box)box.innerHTML='<p class="text-sm text-red-600">'+contactEscape(e.message)+'</p>';}}
var re9DirectoryTimer = null;
var re9DirectoryLastQuery = '';
function searchRe9DirectoryDebounced(){
 clearTimeout(re9DirectoryTimer);
 var input=document.getElementById('contactsSearch');var q=input?input.value.trim():'';
 var box=document.getElementById('re9DirectoryResults');if(!box)return;
 if(q.length<2){box.innerHTML='';re9DirectoryLastQuery='';return;}
 re9DirectoryTimer=setTimeout(function(){searchRe9Directory(q);},450);
}
async function searchRe9Directory(q){
 var box=document.getElementById('re9DirectoryResults');if(!box)return;
 if(!box.dataset.actionsBound){box.dataset.actionsBound='1';box.addEventListener('click',async function(ev){var btn=ev.target.closest('button[data-directory-email]');if(!btn)return;btn.disabled=true;btn.classList.add('opacity-60');try{await addRe9DirectoryContact(btn.getAttribute('data-directory-email'),btn.getAttribute('data-directory-name'));}catch(err){alert(err.message||'Não foi possível adicionar.');btn.disabled=false;btn.classList.remove('opacity-60');}});}
 re9DirectoryLastQuery=q;box.innerHTML='<p class="px-1 py-2 text-sm text-slate-500"><i class="fa-solid fa-spinner fa-spin mr-2"></i>Buscando contas corporativas na VPS...</p>';
 try{
  var res=await fetch('?api=re9_directory_search&q='+encodeURIComponent(q),{credentials:'same-origin'});var data=await res.json();
  if(re9DirectoryLastQuery!==q)return;
  if(data.status!=='ok')throw new Error(data.msg||'Não foi possível consultar o diretório.');
  var existing={};re9ContactsCache.forEach(function(c){if(c.email)existing[String(c.email).toLowerCase()]=true;});
  var items=(data.items||[]).filter(function(x){return !existing[String(x.email||'').toLowerCase()];});
  if(!items.length){box.innerHTML='<div class="rounded-lg border border-dashed border-slate-300 p-3 text-sm text-slate-500">'+((data.items||[]).length?'Todas as contas encontradas já estão na sua lista.':'Nenhuma outra conta corporativa encontrada para esta pesquisa.')+'</div>';return;}
  box.innerHTML='<div class="rounded-xl border border-blue-200 bg-blue-50/60 p-3"><div class="mb-2 text-sm font-extrabold text-[#002244]"><i class="fa-solid fa-globe mr-1 text-blue-600"></i> Contas corporativas encontradas</div>'+items.map(function(x){return '<button type="button" data-directory-email="'+contactEscape(x.email)+'" data-directory-name="'+contactEscape(x.name)+'" class="mb-2 flex w-full items-center gap-3 rounded-lg border border-blue-100 bg-white p-3 text-left transition hover:border-blue-300 hover:bg-blue-50"><span class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-[#002244] text-white"><i class="fa-solid fa-user"></i></span><span class="min-w-0 flex-1"><strong class="block truncate text-sm text-slate-800">'+contactEscape(x.name)+'</strong><span class="block truncate text-xs text-slate-500">'+contactEscape(x.email)+'</span></span><span class="shrink-0 rounded-lg bg-[#002244] px-3 py-2 text-xs font-bold text-white"><i class="fa-solid fa-plus mr-1"></i>Adicionar</span></button>';}).join('')+'</div>';
 }catch(e){if(re9DirectoryLastQuery===q)box.innerHTML='<p class="rounded-lg border border-amber-200 bg-amber-50 p-3 text-sm text-amber-800">'+contactEscape(e.message)+'</p>';}
}
async function addRe9DirectoryContact(email,name){
 email=String(email||'').toLowerCase().trim();if(!email)return;
 if(re9ContactsCache.some(function(c){return String(c.email||'').toLowerCase()===email;})){alert('Esse usuário já está na sua lista de contatos.');return;}
 var r=await contactsRequest('contacts_save',{name:name||email.split('@')[0],email:email,company:'Conta corporativa',phone:'',notes:'Adicionado pelo diretório corporativo da VPS.'});
 if(r.status!=='ok')throw new Error(r.msg||'Não foi possível adicionar o contato.');
 await loadContacts();searchRe9DirectoryDebounced();
}

function renderContacts(){
 var box=document.getElementById('contactsList');if(!box)return;
 renderPrivateUnreadConversations();
 var search=document.getElementById('contactsSearch');var q=(search&&search.value?search.value:'').toLowerCase();
 var rows=re9ContactsCache.filter(function(c){return [c.name,c.phone,c.email,c.company,c.notes].join(' ').toLowerCase().indexOf(q)!==-1;});
 if(!rows.length){box.innerHTML='<p class="rounded-lg border border-dashed border-slate-300 p-5 text-center text-sm text-slate-500">'+(re9ContactsCache.length?'Nenhum contato corresponde à busca.':'Nenhum contato cadastrado ainda.')+'</p>';return;}
 box.innerHTML=rows.map(function(c){
  var id=contactEscape(c.id);var phoneText=c.phone?'<p class="mt-1 text-sm text-slate-700"><i class="fa-solid fa-phone mr-2 text-slate-400"></i>'+contactEscape(c.phone)+'</p>':'';
  var emailText=c.email?'<p class="text-xs text-slate-500"><i class="fa-regular fa-envelope mr-2"></i>'+contactEscape(c.email)+'</p>':'';
  var companyText=c.company?'<p class="text-xs text-slate-500">'+contactEscape(c.company)+'</p>':'';
  var notesText=c.notes?'<p class="mt-2 whitespace-pre-wrap text-xs text-slate-500">'+contactEscape(c.notes)+'</p>':'';
  var actions='<div class="flex shrink-0 gap-1"><button type="button" data-contact-action="edit" data-contact-id="'+id+'" class="rounded-md bg-slate-100 px-2 py-1 text-xs text-blue-800" title="Editar"><i class="fa-solid fa-pen"></i></button><button type="button" data-contact-action="delete" data-contact-id="'+id+'" class="rounded-md bg-red-50 px-2 py-1 text-xs text-red-700" title="Excluir"><i class="fa-solid fa-trash"></i></button></div>';
  var contactEmail=String(c.email||'').toLowerCase().trim();
  var contactDomain=contactEmail.indexOf('@')>-1?contactEmail.split('@').pop().trim().replace(/^@+/, ''):'';
  var contactUnread=Math.max(0,Number(privateUnreadBySender[contactEmail]||0));
  var messageButton=contactEmail?'<button type="button" data-contact-action="message" data-contact-id="'+id+'" data-contact-email="'+contactEscape(contactEmail)+'" data-contact-name="'+contactEscape(c.name||contactEmail)+'" aria-label="Abrir mensagem privada com '+contactEscape(c.name||contactEmail)+'; '+contactUnread+' mensagens não lidas" class="rounded-lg bg-[#002244] px-3 py-2 text-xs font-bold text-white hover:bg-[#003568]"><i class="fa-regular fa-comments mr-1"></i> Mensagem privada'+(contactUnread?'<span class="ml-2 inline-flex min-w-5 items-center justify-center rounded-full bg-[#b91c1c] px-1.5 py-0.5 text-[10px] font-black text-white">'+contactUnread+'</span>':'')+'</button>':'';
  var copyButton=c.phone?'<button type="button" data-contact-action="copy" data-contact-id="'+id+'" class="rounded-lg border border-slate-200 px-3 py-2 text-xs font-bold text-slate-600"><i class="fa-regular fa-copy mr-1"></i> Copiar telefone</button>':'';
  return '<article class="rounded-xl border border-slate-200 p-3"><div class="flex items-start justify-between gap-3"><div class="flex min-w-0 gap-3"><div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-blue-50 text-[#002244] font-black">'+contactEscape((c.name||'?').trim().charAt(0).toUpperCase())+'</div><div class="min-w-0"><h4 class="font-extrabold text-slate-800">'+contactEscape(c.name)+'</h4>'+companyText+phoneText+emailText+notesText+'</div></div>'+actions+'</div>'+((messageButton||copyButton)?'<div class="mt-3 flex flex-wrap gap-2">'+messageButton+copyButton+'</div>':'')+'</article>';
 }).join('');
 if(!box.dataset.actionsBound){box.dataset.actionsBound='1';box.addEventListener('click',async function(ev){var btn=ev.target.closest('button[data-contact-action]');if(!btn)return;var action=btn.getAttribute('data-contact-action');if(action==='message'){var targetEmail=String(btn.getAttribute('data-contact-email')||'').toLowerCase().trim();var targetName=btn.getAttribute('data-contact-name')||targetEmail;if(!targetEmail){alert('Este contato não possui um e-mail válido para a mensagem privada.');return;}openPrivateMessageFor(targetEmail,targetName);return;}var contact=re9ContactsCache.find(function(x){return String(x.id)===btn.getAttribute('data-contact-id');});if(!contact)return;if(action==='edit')editContact(contact.id);else if(action==='delete')deleteContact(contact.id);else if(action==='copy'){try{if(navigator.clipboard&&navigator.clipboard.writeText){await navigator.clipboard.writeText(contact.phone||'');alert('Telefone copiado.');}else{var temp=document.createElement('textarea');temp.value=contact.phone||'';document.body.appendChild(temp);temp.select();document.execCommand('copy');temp.remove();alert('Telefone copiado.');}}catch(err){alert('Não foi possível copiar o telefone neste navegador.');}}});}

}
function resetContactForm(){document.getElementById('contactForm').reset();document.getElementById('contactId').value='';document.getElementById('contactFeedback').textContent='';}
async function saveContact(e){e.preventDefault();var data={id:document.getElementById('contactId').value,name:document.getElementById('contactName').value,phone:document.getElementById('contactPhone').value,email:document.getElementById('contactEmail').value,company:document.getElementById('contactCompany').value,notes:document.getElementById('contactNotes').value};var feedback=document.getElementById('contactFeedback');try{var r=await contactsRequest('contacts_save',data);if(r.status!=='ok')throw new Error(r.msg||'Não foi possível salvar.');feedback.textContent='Contato salvo com sucesso.';resetContactForm();loadContacts();}catch(err){feedback.textContent=err.message;}}
function editContact(id){var c=re9ContactsCache.find(function(x){return x.id===id;});if(!c)return;document.getElementById('contactId').value=c.id;document.getElementById('contactName').value=c.name||'';document.getElementById('contactPhone').value=c.phone||'';document.getElementById('contactEmail').value=c.email||'';document.getElementById('contactCompany').value=c.company||'';document.getElementById('contactNotes').value=c.notes||'';document.getElementById('contactFeedback').textContent='Editando contato selecionado.';document.getElementById('contactForm').scrollIntoView({behavior:'smooth',block:'start'});}
async function deleteContact(id){if(!confirm('Deseja excluir este contato?'))return;try{var r=await contactsRequest('contacts_delete',{id:id});if(r.status!=='ok')throw new Error(r.msg||'Não foi possível excluir.');loadContacts();}catch(e){alert(e.message);}}
// ================= RE9 MENSAGENS PRIVADAS: ENVIO ONLINE E OFFLINE =================
var RE9_DOMAIN = <?php echo json_encode(strtolower((string)get_val($APP_CONFIG,'domain_name','re9.rio.br'))); ?>;
var RE9_PRIVATE_CSRF = <?php echo json_encode((string)get_val($_SESSION,'re9_private_csrf','')); ?>;
var RE9_ME = <?php echo json_encode(strtolower((string)get_val($_SESSION,'wm_email',''))); ?>;
var privateActivePeer = '';
var privateActivePeerName = '';
var privateMessageTimer = null;
var privateMessagePollTimer = null;
var privateUnreadBySender = {};
var privateUnreadConversations = [];
var privateUnreadTotal = 0;
var privateMessageSeen = {};
var privateToastPeer = '';

function setPrivateUnreadBadge(id, count) {
    var badge = document.getElementById(id);
    if (!badge) return;
    var value = Math.max(0, Number(count || 0));
    badge.textContent = value > 99 ? '99+' : String(value);
    badge.classList.toggle('hidden', value < 1);
    badge.setAttribute('aria-label', value + (value === 1 ? ' mensagem privada não lida' : ' mensagens privadas não lidas'));
}

function applyPrivateUnreadData(data) {
    data = data || {};
    privateUnreadBySender = data.unread_by_sender || {};
    privateUnreadConversations = Array.isArray(data.unread_conversations) ? data.unread_conversations : [];
    privateUnreadTotal = Math.max(0, Number(data.unread_count || 0));
    setPrivateUnreadBadge('privateUnreadContactsBadge', privateUnreadTotal);
    setPrivateUnreadBadge('privateUnreadMenuBadge', privateUnreadTotal);
    var quickLink = document.getElementById('privateMessagesQuickLink');
    if (quickLink) quickLink.setAttribute('aria-label', 'Mensagens privadas. ' + privateUnreadTotal + ' mensagens não lidas.');
    var contactsButton = document.querySelector('#folderSidebar button[onclick*="openContactsModal"]');
    if (contactsButton) contactsButton.setAttribute('aria-label', 'Contatos. ' + privateUnreadTotal + ' mensagens privadas não lidas.');
    renderPrivateUnreadConversations();
}

function renderPrivateUnreadConversations() {
    var box = document.getElementById('privateUnreadConversations');
    if (!box) return;
    if (!privateUnreadTotal || !privateUnreadConversations.length) {
        box.innerHTML = '';
        box.classList.add('hidden');
        return;
    }
    box.classList.remove('hidden');
    var cards = privateUnreadConversations.map(function(item) {
        var email = String(item.email || '').toLowerCase();
        var name = String(item.name || email || 'Contato');
        var count = Math.max(0, Number(item.count || 0));
        var preview = String(item.latest_message || '').replace(/\s+/g, ' ').trim();
        if (preview.length > 100) preview = preview.substring(0, 97) + '...';
        var created = item.latest_created ? new Date(Number(item.latest_created) * 1000).toLocaleString('pt-BR') : '';
        return '<button type="button" data-unread-peer="' + contactEscape(email) + '" data-unread-name="' + contactEscape(name) + '" class="flex w-full items-center gap-3 rounded-xl border border-red-200 bg-white p-3 text-left shadow-sm transition hover:border-red-400 hover:bg-red-50">' +
            '<span class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-red-50 text-red-700"><i class="fa-solid fa-envelope"></i></span>' +
            '<span class="min-w-0 flex-1"><strong class="block truncate text-sm text-slate-800">' + contactEscape(name) + '</strong><span class="block truncate text-[11px] text-slate-500">' + contactEscape(email) + '</span><span class="mt-1 block truncate text-xs text-slate-600">' + contactEscape(preview || 'Nova mensagem privada') + '</span>' + (created ? '<span class="mt-1 block text-[10px] text-slate-400">' + contactEscape(created) + '</span>' : '') + '</span>' +
            '<span class="min-w-7 shrink-0 rounded-full bg-[#b91c1c] px-2 py-1 text-center text-xs font-black text-white">' + count + '</span></button>';
    }).join('');
    box.innerHTML = '<div class="mb-2 flex items-center justify-between gap-2"><h3 class="text-sm font-extrabold text-red-800"><i class="fa-solid fa-envelope-open-text mr-1.5"></i>Mensagens aguardando leitura</h3><span class="rounded-full bg-red-700 px-2.5 py-1 text-xs font-black text-white">' + privateUnreadTotal + '</span></div><div class="space-y-2">' + cards + '</div>';
    if (box.dataset.unreadActionsBound !== '1') {
        box.dataset.unreadActionsBound = '1';
        box.addEventListener('click', function(event) {
            var button = event.target.closest('button[data-unread-peer]');
            if (!button) return;
            var peer = String(button.getAttribute('data-unread-peer') || '').toLowerCase();
            var name = button.getAttribute('data-unread-name') || peer;
            if (!peer) return;
            openPrivateMessageFor(peer, name);
        });
    }
}

function openPrivateMessagesFromMenu() {
    openContactsModal();
    window.setTimeout(function() {
        var target = document.getElementById('privateUnreadConversations');
        if (!target || target.classList.contains('hidden')) target = document.getElementById('contactsList');
        if (target && typeof target.scrollIntoView === 'function') target.scrollIntoView({behavior:'smooth', block:'start'});
    }, 220);
}

async function refreshPrivateUnreadIndicators() {
    if (!RE9_ME) return;
    try {
        var data = await privateMessageRequest('private_message_poll', null, 'GET');
        applyPrivateUnreadData(data);
        var contactsModal = document.getElementById('contactsModal');
        if (contactsModal && !contactsModal.classList.contains('hidden')) renderContacts();
    } catch (error) {
        // O indicador conserva a última contagem válida se a conexão oscilar.
    }
}

async function privateMessageRequest(action, data, method) {
    method = method || (data ? 'POST' : 'GET');
    var query = '?api=' + encodeURIComponent(action);
    var options = {method:method, credentials:'same-origin', cache:'no-store', headers:{'Cache-Control':'no-cache'}};
    if (method === 'POST') {
        var body = new URLSearchParams(data || {});
        options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
        options.headers['X-RE9-CSRF'] = RE9_PRIVATE_CSRF;
        options.body = body.toString();
    } else if (data) {
        query += '&' + new URLSearchParams(data).toString();
    }
    var response = await fetch(query, options);
    var json = await response.json();
    if (!response.ok || json.status === 'error') throw new Error(json.msg || 'Falha na comunicação com o servidor.');
    return json;
}

function privateMessageEscape(value) {
    return String(value == null ? '' : value).replace(/[&<>"']/g, function(ch) {
        return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#039;'}[ch];
    });
}

function openPrivateMessage(contactId) {
    var contact = re9ContactsCache.find(function(item) { return String(item.id) === String(contactId) || String(item.email||'').toLowerCase().trim() === String(contactId||'').toLowerCase().trim(); });
    if (!contact || !contact.email) { alert('Este contato precisa ter um e-mail cadastrado para receber mensagens privadas.'); return; }
    var email = String(contact.email).toLowerCase().trim();
    if (email === RE9_ME) { alert('Este é o seu próprio endereço de e-mail.'); return; }
    openPrivateMessageFor(email, contact.name || email);
}

function openPrivateMessageFor(email, name) {
    var candidate = String(email || '').toLowerCase().trim();
    if (!candidate || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(candidate)) {
        alert('Não foi possível identificar o e-mail deste contato. Atualize sua lista de contatos e tente novamente.');
        return;
    }
    if (candidate === RE9_ME) {
        alert('Este é o seu próprio endereço de e-mail.');
        return;
    }
    privateActivePeer = candidate;
    privateActivePeerName = String(name || privateActivePeer);
    document.getElementById('privateMessageTitle').textContent = 'Conversando com ' + privateActivePeerName;
    document.getElementById('privateMessagePeer').textContent = privateActivePeer;
    document.getElementById('privateMessageHistory').innerHTML = '<div class="py-8 text-center text-xs text-slate-400"><i class="fa-solid fa-circle-notch fa-spin mr-1"></i>Carregando conversa...</div>';
    document.getElementById('privateMessageInput').disabled = false;
    document.getElementById('privateMessageSend').disabled = false;
    var modal = document.getElementById('privateMessageModal');
    modal.classList.remove('hidden');
    modal.classList.add('flex');
    document.body.classList.add('re9-private-chat-open');
    if (typeof re9SyncModalScrollLock === 'function') re9SyncModalScrollLock();
    loadPrivateMessageHistory(false);
    var input = document.getElementById('privateMessageInput');
    if (input) input.focus();
    if (privateMessageTimer) clearInterval(privateMessageTimer);
    privateMessageTimer = setInterval(function() {
        if (privateActivePeer && !document.getElementById('privateMessageModal').classList.contains('hidden')) loadPrivateMessageHistory(true);
        else clearInterval(privateMessageTimer);
    }, 3500);
}

function closePrivateMessageModal() {
    if (privateMessageTimer) clearInterval(privateMessageTimer);
    privateMessageTimer = null;
    privateActivePeer = '';
    privateActivePeerName = '';
    var modal = document.getElementById('privateMessageModal');
    modal.classList.add('hidden');
    modal.classList.remove('flex');
    document.body.classList.remove('re9-private-chat-open');
    if (typeof re9SyncModalScrollLock === 'function') re9SyncModalScrollLock();
    refreshPrivateUnreadIndicators();
}

async function loadPrivateMessageHistory(silent) {
    if (!privateActivePeer) return;
    var box = document.getElementById('privateMessageHistory');
    var wasNearBottom = box.scrollHeight - box.scrollTop - box.clientHeight < 90;
    try {
        var data = await privateMessageRequest('private_message_history', {peer:privateActivePeer}, 'GET');
        if (data.peer_name) {
            privateActivePeerName = String(data.peer_name);
            document.getElementById('privateMessageTitle').textContent = 'Conversando com ' + privateActivePeerName;
        }
        var online = !!data.peer_online;
        document.getElementById('privateMessageState').textContent = online ? 'Online' : 'Offline';
        document.getElementById('privateMessageState').className = 'rounded-full px-3 py-1 text-xs ' + (online ? 'bg-emerald-500/20 text-emerald-200' : 'bg-white/10 text-slate-200');
        document.getElementById('privateMessageHint').textContent = online
            ? 'Contato online. A conversa é atualizada automaticamente.'
            : 'Contato offline. Sua mensagem fica salva e será exibida quando ele voltar ao webmail.';
        renderPrivateMessageHistory(data.messages || [], wasNearBottom || !silent);
        if (!silent) refreshPrivateUnreadIndicators();
    } catch (error) {
        if (!silent) {
            box.innerHTML = '<div class="mx-auto max-w-lg rounded-xl border border-red-200 bg-white p-5 text-center text-sm text-red-700"><i class="fa-solid fa-circle-exclamation mb-2 block text-xl"></i><strong class="mb-1 block">Não foi possível carregar esta conversa</strong>' + privateMessageEscape(error.message) + '<button type="button" onclick="loadPrivateMessageHistory(false)" class="mt-3 rounded-lg bg-[#002244] px-4 py-2 text-xs font-bold text-white">Tentar novamente</button></div>';
        }
    }
}

function renderPrivateMessageHistory(messages, scrollBottom) {
    var box = document.getElementById('privateMessageHistory');
    if (!box) return;
    if (!messages.length) {
        box.innerHTML = '<div class="rounded-xl border border-dashed border-slate-300 bg-white p-6 py-10 text-center text-xs text-slate-400"><i class="fa-regular fa-comments mb-2 block text-2xl text-[#f28c38]"></i><strong class="mb-1 block text-sm text-[#002244]">Conversa privada</strong>Envie a primeira mensagem. Ela poderá ser recebida mesmo que o contato esteja offline.</div>';
        return;
    }
    box.innerHTML = messages.map(function(item) {
        var mine = String(item.from || '').toLowerCase() === RE9_ME;
        var body = privateMessageEscape(item.message || '').replace(/\r?\n/g, '<br>');
        var date = item.created ? new Date(Number(item.created) * 1000).toLocaleString('pt-BR') : '';
        return '<div class="flex ' + (mine ? 'justify-end' : 'justify-start') + '"><div class="max-w-[88%] rounded-2xl px-3.5 py-2.5 shadow-sm ' + (mine ? 'rounded-br-sm bg-[#002244] text-white' : 'rounded-bl-sm border border-slate-200 bg-white text-slate-800') + '"><div class="mb-1 text-[10px] font-bold ' + (mine ? 'text-blue-200' : 'text-slate-500') + '">' + (mine ? 'Você' : privateMessageEscape(privateActivePeerName)) + '</div><div class="whitespace-normal break-words text-sm leading-relaxed">' + body + '</div><div class="mt-1 text-right text-[9px] ' + (mine ? 'text-blue-200' : 'text-slate-400') + '">' + privateMessageEscape(date) + '</div></div></div>';
    }).join('');
    if (scrollBottom) box.scrollTop = box.scrollHeight;
}

async function sendPrivateMessage(event) {
    event.preventDefault();
    var input = document.getElementById('privateMessageInput');
    var button = document.getElementById('privateMessageSend');
    var message = input.value.trim();
    if (!privateActivePeer || !message) return;
    button.disabled = true;
    try {
        var result = await privateMessageRequest('private_message_send', {to:privateActivePeer, message:message}, 'POST');
        input.value = '';
        document.getElementById('privateMessageHint').textContent = result.peer_online
            ? 'Mensagem enviada. O contato está online.'
            : 'Mensagem salva e enviada. O contato está offline e receberá quando voltar ao webmail.';
        await loadPrivateMessageHistory(true);
        refreshPrivateUnreadIndicators();
        var box = document.getElementById('privateMessageHistory');
        box.scrollTop = box.scrollHeight;
        pollPrivateMessages();
    } catch (error) {
        alert(error.message || 'Não foi possível enviar a mensagem.');
    } finally {
        button.disabled = false;
    }
}

function showPrivateMessageToast(item) {
    privateToastPeer = item.from || '';
    var savedContact = re9ContactsCache.find(function(contact) {
        return String(contact.email || '').toLowerCase() === String(item.from || '').toLowerCase();
    });
    var senderName = item.from_name || (savedContact && savedContact.name) || item.from || 'Contato da rede';
    var preview = String(item.message || '').replace(/\s+/g, ' ').trim();
    if (preview.length > 110) preview = preview.substring(0, 107) + '...';
    var alertText = item.was_offline === false
        ? 'Você tem uma nova mensagem privada não lida de ' + senderName + '.'
        : 'Você tem uma mensagem privada offline de ' + senderName + '.';
    document.getElementById('privateMessageToastText').textContent = alertText + (preview ? ' Prévia: ' + preview : '');
    var toast = document.getElementById('privateMessageToast');
    toast.classList.remove('hidden');
    // O aviso permanece no topo até o usuário abrir a conversa ou fechá-lo manualmente.
}

function hidePrivateMessageToast() {
    var toast = document.getElementById('privateMessageToast');
    if (toast) toast.classList.add('hidden');
}

function openPrivateMessageFromToast() {
    if (!privateToastPeer) return;
    var peer = privateToastPeer;
    var contact = re9ContactsCache.find(function(item) { return String(item.email || '').toLowerCase() === peer; });
    hidePrivateMessageToast();
    openPrivateMessageFor(peer, contact ? contact.name : peer);
}

async function pollPrivateMessages() {
    if (!RE9_ME) return;
    try {
        var data = await privateMessageRequest('private_message_poll', null, 'GET');
        applyPrivateUnreadData(data);
        if (document.getElementById('contactsModal') && !document.getElementById('contactsModal').classList.contains('hidden')) renderContacts();
        (data.unread_messages || []).forEach(function(item) {
            if (!item.id || privateMessageSeen[item.id]) return;
            privateMessageSeen[item.id] = true;
            if (item.from !== privateActivePeer) showPrivateMessageToast(item);
        });
        if (privateActivePeer && !document.getElementById('privateMessageModal').classList.contains('hidden')) {
            loadPrivateMessageHistory(true);
        }
    } catch (error) {
        // Falhas transitórias de rede não interrompem o webmail.
    }
}

(function bindPrivateMessageEnterKey() {
    var input = document.getElementById('privateMessageInput');
    var form = document.getElementById('privateMessageForm');
    if (!input || !form || input.dataset.enterToSendBound === '1') return;
    input.dataset.enterToSendBound = '1';
    input.addEventListener('keydown', function(event) {
        if (event.key === 'Enter' && !event.shiftKey && !event.isComposing) {
            event.preventDefault();
            var sendButton = document.getElementById('privateMessageSend');
            if (!sendButton || sendButton.disabled) return;
            if (typeof form.requestSubmit === 'function') form.requestSubmit();
            else sendPrivateMessage(event);
        }
    });
})();

if (RE9_ME) {
    setTimeout(pollPrivateMessages, 1400);
    if (privateMessagePollTimer) clearInterval(privateMessagePollTimer);
    privateMessagePollTimer = setInterval(pollPrivateMessages, 5000);
    window.addEventListener('focus', pollPrivateMessages);
}

function copyAgendaCronCommand(){
    var el=document.getElementById('agendaCronCommand');
    if(!el)return;
    var command=el.textContent.trim();
    if(navigator.clipboard&&navigator.clipboard.writeText){
        navigator.clipboard.writeText(command).then(function(){alert('Comando do Cron copiado.');}).catch(function(){window.prompt('Copie o comando do Cron:',command);});
    }else{
        window.prompt('Copie o comando do Cron:',command);
    }
}

if (RE9_ME && re9AutoChatPeer) {
    openContactsModal();
    loadContacts();
}

</script>

<?php if (empty($RE9_IS_CENTRAL_HUB) && re9_central_is_client_connected() && !empty($_SESSION['wm_email'])): ?>
<script>
(function(){
    var re9UpdateCheckBusy = false;
    function re9CheckClientRelease(){
        if (re9UpdateCheckBusy || document.hidden) return;
        re9UpdateCheckBusy = true;
        fetch('?api=client_check_release', {credentials:'same-origin', cache:'no-store', headers:{'Accept':'application/json'}})
            .then(function(response){ return response.json(); })
            .then(function(data){
                if (!data || data.status !== 'ok' || data.update_applied !== true) return;
                var notice = document.createElement('div');
                notice.setAttribute('role','status');
                notice.style.cssText = 'position:fixed;z-index:12000;left:12px;right:12px;bottom:18px;max-width:560px;margin:auto;padding:14px 16px;border:1px solid #bfdbfe;border-radius:14px;background:#eff6ff;color:#1e3a8a;box-shadow:0 10px 30px rgba(15,23,42,.18);font:600 14px/1.45 Arial,sans-serif';
                notice.textContent = data.message || 'Uma atualização foi instalada. Recarregue o webmail quando terminar seu trabalho.';
                var close = document.createElement('button');
                close.type = 'button'; close.textContent = 'Fechar';
                close.style.cssText = 'display:block;margin-top:8px;border:0;background:transparent;color:#1e40af;font-weight:800;padding:4px 0';
                close.onclick = function(){ if (notice.parentNode) notice.parentNode.removeChild(notice); };
                notice.appendChild(close); document.body.appendChild(notice);
            })
            .catch(function(){})
            .then(function(){ re9UpdateCheckBusy = false; }, function(){ re9UpdateCheckBusy = false; });
    }
    window.setInterval(re9CheckClientRelease, 300000);
    window.addEventListener('focus', re9CheckClientRelease);
})();
</script>
<?php endif; ?>

</body>
</html>
