<?php

require_once(dirname(__DIR__) . '/config/db.php');
require_once __DIR__ . '/home_service.php';
require_once __DIR__ . '/home_consolidado_helper.php';
require_once(dirname(__DIR__) . '/views/card.php');
require_once(dirname(__DIR__) . '/lib/SimpleCache.php');

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);

// ============================
// LIMPAR FILTROS (se parâmetro limpar_filtros=1)
// ============================
if (isset($_GET['limpar_filtros']) && (string)$_GET['limpar_filtros'] === '1') {
    $_SESSION['filtros_dashboard'] = [];
    // Redirecionar para home limpo
    header('Location: ?');
    exit;
}

// ============================
// FILTROS GLOBAIS
// ============================
$cdpessoa = (int)($_SESSION['usuario']['id'] ?? $_SESSION['cdpessoa'] ?? 0);
$cdempresaSessao = (int)($_SESSION['cdempresa'] ?? 0);

// Inicializar filtros na SESSION se não existirem
if (!isset($_SESSION['filtros_dashboard'])) {
    $_SESSION['filtros_dashboard'] = [];
}

// Guardar país anterior (para detectar quando o usuário mudou o país explicitamente)
$cdpaisAnteriorSessao = (int)($_SESSION['filtros_dashboard']['cdpais'] ?? 0);

// ============================
// VERIFICAR SE FILTROS FORAM APLICADOS (GET params presentes)
// ============================
$filtrosAplicados = isset($_GET['ano']) || isset($_GET['cdpais']) || isset($_GET['cdempresa']) || 
                    isset($_GET['cdcentrocusto']) || isset($_GET['trimestre']) || isset($_GET['mes']) || isset($_GET['cdmoeda']);

// ============================
// VISÃO DO DASHBOARD
// - default: por variável
// - auto: ao consolidar (multi-empresa) e se o usuário não tiver escolhido explicitamente
// ============================
function urlComVisaoDashboard(string $visao): string {
    $params = $_GET;
    $params['visao'] = $visao;
    $qs = http_build_query($params);
    return $qs ? ('?' . $qs) : '?';
}

// ============================
// PERMISSÕES DE VISÃO DO DASHBOARD (por pessoa)
// Mapeia: variavel = Detalhado, modelo = Consolidado, percentual = Percentual, planilha = Planilha
// ============================
$visoesPermitidas = ['variavel', 'modelo', 'percentual', 'planilha'];
$visoesUsuario = $visoesPermitidas; // fallback: todas
try {
    $stVisoes = $pdo->prepare("SELECT fl_visao_detalhado, fl_visao_consolidado, fl_visao_percentual, fl_visao_planilha, visao_padrao FROM back.pessoa WHERE cdpessoa = :id LIMIT 1");
    $stVisoes->execute([':id' => $cdpessoa]);
    $flagsVisao = $stVisoes->fetch(PDO::FETCH_ASSOC);
    if ($flagsVisao) {
        $visoesUsuario = [];
        if ($flagsVisao['fl_visao_detalhado'])   $visoesUsuario[] = 'variavel';
        if ($flagsVisao['fl_visao_consolidado']) $visoesUsuario[] = 'modelo';
        if ($flagsVisao['fl_visao_percentual'])  $visoesUsuario[] = 'percentual';
        if ($flagsVisao['fl_visao_planilha'])    $visoesUsuario[] = 'planilha';
        // Se nenhuma visão habilitada, liberar todas (safety)
        if (empty($visoesUsuario)) $visoesUsuario = $visoesPermitidas;
        // Mapear visao_padrao do banco para nome interno
        $mapVisaoPadrao = ['detalhado'=>'variavel','consolidado'=>'modelo','percentual'=>'percentual','planilha'=>'planilha'];
        $visaoPadraoUsuario = $mapVisaoPadrao[$flagsVisao['visao_padrao'] ?? ''] ?? null;
        if ($visaoPadraoUsuario && in_array($visaoPadraoUsuario, $visoesUsuario, true)) {
            $_SESSION['visao_padrao'] = $visaoPadraoUsuario;
        }
    }
} catch (Throwable $e) {
    $visoesUsuario = $visoesPermitidas;
}

$visaoParam = isset($_GET['visao']) ? strtolower(trim((string)$_GET['visao'])) : null;
if ($visaoParam && in_array($visaoParam, $visoesUsuario, true)) {
    $_SESSION['dashboard_visao'] = $visaoParam;
    $_SESSION['dashboard_visao_explicit'] = true;
}

$visaoPadraoFallback = $_SESSION['visao_padrao'] ?? ($visoesUsuario[0] ?? 'variavel');
$visaoDashboard = (string)($_SESSION['dashboard_visao'] ?? $visaoPadraoFallback);
if (!in_array($visaoDashboard, $visoesUsuario, true)) {
    $visaoDashboard = $visaoPadraoFallback;
    if (!in_array($visaoDashboard, $visoesUsuario, true)) {
        $visaoDashboard = $visoesUsuario[0] ?? 'variavel';
    }
}
$modoPercentual = ($visaoDashboard === 'percentual');

// Obter filtros da requisição (GET parameters) ou da SESSION
$empresasFiltro = obterEmpresasPessoa($pdo, $cdpessoa);
$empresasFiltroOriginal = $empresasFiltro; // Cópia antes de filtrar por país/moeda (para planilha)

// ============================
// FILTRO DE MOEDA
// ============================
$moedasFiltro = obterMoedasAtivas($pdo);

// Moeda padrão: moeda da empresa ativa (logada)
$cdmoedaSessao = 0;
if ($cdempresaSessao > 0) {
    try {
        $stMoeda = $pdo->prepare('SELECT cdmoeda FROM back.empresa WHERE cdempresa = :emp LIMIT 1');
        $stMoeda->execute([':emp' => $cdempresaSessao]);
        $cdmoedaSessao = (int)($stMoeda->fetchColumn() ?: 0);
    } catch (Throwable $e) {
        $cdmoedaSessao = 0;
    }
}

$cdmoedaFiltro = (int)($filtrosAplicados && isset($_GET['cdmoeda']) ? $_GET['cdmoeda'] : ($_SESSION['filtros_dashboard']['cdmoeda'] ?? $cdmoedaSessao));

// Validar moeda selecionada
$moedasAcessiveis = array_map(fn($m) => (int)$m['cdmoeda'], $moedasFiltro);
if ($cdmoedaFiltro > 0 && !in_array($cdmoedaFiltro, $moedasAcessiveis, true)) {
    $cdmoedaFiltro = $cdmoedaSessao;
}

// Multi-select de empresas (por padrão, NENHUMA SELECIONADA)
// IMPORTANTE: GET['cdempresa[]'] vem como array quando múltiplos valores via URL
// 1. Se GET tem cdempresa[] (array) → usar GET
// 2. Senão, se SESSION tem cdempresa → usar SESSION
// 3. Senão → usar array vazio []
$empresasSelecionadas = [];

if (isset($_GET['cdempresa'])) {
    // GET com cdempresa[] vem como array do JavaScript/form
    $empresasSelecionadas = $_GET['cdempresa'];
} elseif (isset($_SESSION['filtros_dashboard']['cdempresa']) && !empty($_SESSION['filtros_dashboard']['cdempresa'])) {
    // Se GET não tem, mas SESSION tem → usar SESSION
    $empresasSelecionadas = $_SESSION['filtros_dashboard']['cdempresa'];
}

// Garantir que é um array (pode vir como string se vazio ou único valor)
if (!is_array($empresasSelecionadas)) {
    $empresasSelecionadas = !empty($empresasSelecionadas) ? [$empresasSelecionadas] : [];
}

error_log("[FILTROS-ARRAY] Após garantir array: " . json_encode($empresasSelecionadas), 0);

// Converter para inteiros e remover vazios e duplicatas
$empresasSelecionadas = array_unique(array_map('intval', array_filter($empresasSelecionadas, function($v) {
    return !empty($v) && (int)$v > 0;
})));

error_log("[FILTROS-INTEIROS] Após filtrar inteiros: " . json_encode($empresasSelecionadas), 0);

// ====== NOTA: Validação de empresas acessíveis será feita DEPOIS de filtrar por país ======

// Obter todos os centros de custo (não filtrados por empresa)
$centrosCustoFiltro = obterCentrosCusto($pdo);
$cdcentrocustoFiltro = (int)($filtrosAplicados && isset($_GET['cdcentrocusto']) ? $_GET['cdcentrocusto'] : ($_SESSION['filtros_dashboard']['cdcentrocusto'] ?? 0));

// Filtro de ano (consolidando anos dos exercícios) - PADRÃO PARA ANO CORRENTE
$anosFiltro = obterExercicios($pdo);
$anoFiltro = (int)($filtrosAplicados && isset($_GET['ano']) ? $_GET['ano'] : ($_SESSION['filtros_dashboard']['ano'] ?? date('Y')));

// Se ano não encontrado nos exercícios, usar ano corrente
if (!array_filter($anosFiltro, fn($a) => (int)$a['anoref'] === $anoFiltro)) {
    $anoFiltro = (int)date('Y');
}

// Filtro de mês (1-12) - MULTI-SELEÇÃO
// Aceita GET mes[] (array) ou mes (string única). Se vazio, usa SESSION; se ainda vazio, mês corrente.
$mesesSelecionados = [];
if (isset($_GET['mes'])) {
    $mesesSelecionados = $_GET['mes'];
} elseif (isset($_SESSION['filtros_dashboard']['mes']) && !empty($_SESSION['filtros_dashboard']['mes'])) {
    $mesesSelecionados = $_SESSION['filtros_dashboard']['mes'];
}
if (!is_array($mesesSelecionados)) {
    $mesesSelecionados = !empty($mesesSelecionados) ? [$mesesSelecionados] : [];
}
$mesesSelecionados = array_unique(array_map('intval', array_filter($mesesSelecionados, function ($v) {
    $iv = (int)$v;
    return $iv >= 1 && $iv <= 12;
})));
sort($mesesSelecionados);
if (empty($mesesSelecionados)) {
    $mesesSelecionados = [(int)date('n')];
}

$trimestresFiltro = obterTrimestres();
$trimestreFiltro = (int)($filtrosAplicados && isset($_GET['trimestre']) ? $_GET['trimestre'] : ($_SESSION['filtros_dashboard']['trimestre'] ?? 0));
// Default: 0 = Todos (sem filtrar por trimestre)
if ($trimestreFiltro < 0 || $trimestreFiltro > 4) {
    $trimestreFiltro = 0;
}

// Filtro de país (países das empresas que o usuário tem acesso)
$paisesFiltro = obterPaisesAcessiveis($pdo, $cdpessoa);
$cdpaisFiltro = (int)($filtrosAplicados && isset($_GET['cdpais']) ? $_GET['cdpais'] : ($_SESSION['filtros_dashboard']['cdpais'] ?? 0));

// Validar se país selecionado está acessível
$paisesAcessiveis = array_map(fn($p) => (int)$p['cdpais'], $paisesFiltro);
if ($cdpaisFiltro > 0 && !in_array($cdpaisFiltro, $paisesAcessiveis)) {
    $cdpaisFiltro = 0;
}

// SE há filtro de país, filtrar as empresas para apenas aquelas do país selecionado
if ($cdpaisFiltro > 0) {
    $empresasFiltro = array_filter($empresasFiltro, fn($emp) => (int)($emp['cdpais'] ?? 0) === $cdpaisFiltro);
    error_log("[FILTROS-PAÍS] Filtrando empresas pelo país: cdpais=" . $cdpaisFiltro . " | empresas restantes: " . json_encode(array_map(fn($e) => (int)$e['cdempresa'], $empresasFiltro)), 0);
}

// SE há filtro de moeda, filtrar as empresas para apenas aquelas da moeda selecionada
if ($cdmoedaFiltro > 0) {
    $empresasFiltro = array_filter($empresasFiltro, fn($emp) => (int)($emp['cdmoeda'] ?? 0) === $cdmoedaFiltro);
    error_log("[FILTROS-MOEDA] Filtrando empresas pela moeda: cdmoeda=" . $cdmoedaFiltro . " | empresas restantes: " . json_encode(array_map(fn($e) => (int)$e['cdempresa'], $empresasFiltro)), 0);
}

// AGORA: Validar se todas as empresas selecionadas estão acessíveis (APÓS filtro de país)
$empresasAcessiveis = array_map(fn($e) => (int)$e['cdempresa'], $empresasFiltro);
$empresasSelecionadas = array_intersect($empresasSelecionadas, $empresasAcessiveis);

// Se o usuário interagiu explicitamente com o filtro de país (mesmo escolhendo o mesmo valor),
// OU se mudou o país em relação ao anterior, marcar automaticamente TODAS as empresas do filtro atual.
// Isso garante o comportamento desejado ao escolher "Todos" já no primeiro carregamento.
$paisExplicit = isset($_GET['pais_explicit']) && (string)$_GET['pais_explicit'] === '1';
if (array_key_exists('cdpais', $_GET) && ($paisExplicit || $cdpaisFiltro !== $cdpaisAnteriorSessao)) {
    $empresasSelecionadas = $empresasAcessiveis;
}

// Se a seleção ficou vazia, definir um padrão coerente:
// - Se há filtro de país: usar TODAS as empresas restantes (do país)
// - Caso contrário: usar a empresa ativa da sessão como padrão (primeira carga / sem seleção explícita)
if (empty($empresasSelecionadas)) {
    if ($cdpaisFiltro > 0) {
        $empresasSelecionadas = $empresasAcessiveis;
    } elseif ($cdempresaSessao > 0 && in_array($cdempresaSessao, $empresasAcessiveis, true)) {
        $empresasSelecionadas = [$cdempresaSessao];
    } else {
        $empresasSelecionadas = [];
    }
}

// ============================
// SALVAR FILTROS NA SESSION IMEDIATAMENTE
// (ANTES de verificar/usar cache)
// ============================
// Garantir que empresas selecionadas é sempre um array
$empresasSelecionadasSessao = is_array($empresasSelecionadas) ? $empresasSelecionadas : [];
$_SESSION['filtros_dashboard']['cdempresa'] = $empresasSelecionadasSessao;
$_SESSION['filtros_dashboard']['cdcentrocusto'] = $cdcentrocustoFiltro;
$_SESSION['filtros_dashboard']['ano'] = $anoFiltro;
$_SESSION['filtros_dashboard']['trimestre'] = $trimestreFiltro;
$_SESSION['filtros_dashboard']['mes'] = $mesesSelecionados;
$_SESSION['filtros_dashboard']['cdpais'] = $cdpaisFiltro;
$_SESSION['filtros_dashboard']['cdmoeda'] = $cdmoedaFiltro;

// DEBUG: Mostrar estado dos filtros no erro_log
error_log("[FILTROS] filtrosAplicados=" . ($filtrosAplicados ? 'SIM' : 'NÃO') . 
    " | GET[cdempresa]=" . json_encode($_GET['cdempresa'] ?? null) . 
    " | empresasSelecionadas (PRÉ-VALIDAÇÃO)=" . json_encode($empresasSelecionadas) . 
    " | SESSION[cdempresa]=" . json_encode($_SESSION['filtros_dashboard']['cdempresa'] ?? null), 0);

// DEBUG: Log após validação
error_log("[FILTROS-VALIDAÇÃO] empresasSelecionadas (PÓS)=" . json_encode($empresasSelecionadas) . 
    " | empresasAcessiveis=" . json_encode($empresasAcessiveis) . 
    " | count(empresasSelecionadas)=" . count($empresasSelecionadas), 0);

// ============================
// OTIMIZADO: Cache pesado do dashboard (principal)
// ⚠️ CACHE DESABILITADO - Sempre recalcula para garantir filtros corretos
// Usar empresa selecionada ou empresa da sessão para cache key
$empresaForCache = !empty($empresasSelecionadas) ? reset($empresasSelecionadas) : $cdempresaSessao;
$empresasHashCache = !empty($empresasSelecionadas) ? md5(implode(',', $empresasSelecionadas)) : 'none';
$mesesHashCache = !empty($mesesSelecionados) ? md5(implode(',', $mesesSelecionados)) : 'none';
$cacheKeyHeavy = "dashboard_heavy_{$empresasHashCache}_{$cdcentrocustoFiltro}_{$anoFiltro}_{$trimestreFiltro}_{$mesesHashCache}_{$cdpaisFiltro}_v3";
$isWarm = isset($_GET['warm']) && (string)$_GET['warm'] === '1';

// ⚠️ CACHE DESABILITADO - Forçar sempre null para recalcular
$dados = null;

if ($dados === null || !is_array($dados) || !($dados['ok'] ?? false)) {
    // Usar empresa selecionada para cálculos, mas empresa da sessão para exibição
    $empresaParaDados = !empty($empresasSelecionadas) ? $empresasSelecionadas : [$cdempresaSessao];

    // Se a empresa da sessão não estiver na seleção (ex: filtro de moeda/país),
    // usar a primeira empresa selecionada para exibição/moeda, evitando inconsistência.
    $cdempresaExibicao = $cdempresaSessao;
    if (!empty($empresaParaDados) && $cdempresaExibicao > 0 && !in_array($cdempresaExibicao, $empresaParaDados, true)) {
        $cdempresaExibicao = (int)$empresaParaDados[0];
    }
    
    // DEBUG: Log das empresas que serão usadas
    error_log("[DEBUG FILTROS] Chamando obterDadosDashboard com empresas: " . json_encode($empresaParaDados) . ", $filtrosAplicados=" . ($filtrosAplicados ? 'SIM' : 'NÃO'), 0);
    
    $dados = obterDadosDashboard($pdo, 0, $cdcentrocustoFiltro, $anoFiltro, $trimestreFiltro, $mesesSelecionados, $empresaParaDados, $cdempresaExibicao, $cdpaisFiltro);
    // ⚠️ CACHE DESABILITADO - Não salva em cache
    // if ($dados['ok'] ?? false) {
    //     SimpleCache::set($cacheKeyHeavy, $dados, 30);
    // }
}

if (!($dados['ok'] ?? false)) {
    $mensagem = htmlspecialchars((string)($dados['msg'] ?? 'Falha ao calcular Dashboard.'), ENT_QUOTES, 'UTF-8');
    echo "<div class='alert alert-danger'>" . $mensagem . "</div>";
    return;
}

// Profiling opcional via ?profile=1
$mostrarProfile = isset($_GET['profile']) && (string)$_GET['profile'] === '1';
$profileSteps = $dados['profile'] ?? [];

// Buscar última sincronização bem-sucedida
$ultimaSincronizacao = obterUltimaSincronizacao($pdo, $cdempresaSessao);

$cdempresa  = (int)$dados['empresa'];
$dsempresa  = (string)($dados['dsempresa'] ?? '');
$anoref     = (int)$dados['anoref'];
$mesAtual   = (int)$dados['mesAtual'];
$moeda      = $dados['moeda'];
$dashboards = $dados['dashboards'];
$serieYtd   = $dados['serieYtd'] ?? null;
$valoresRealizadosMensais = $dados['valoresRealizadosMensais'] ?? [];
$valoresOrcadosMensais    = $dados['valoresOrcadosMensais'] ?? [];

// ============================
// DADOS DE ORIGEM VINCULADOS A VARIÁVEIS (fl_origem = true)
// Busca valores de back.origem_dados para integrations vinculadas
// ============================
$origemPorVariavel = []; // [cdvariavel => ['dsintegracao'=>..., 'valor_total'=>..., 'valor_hoje'=>..., 'valores_por_dia'=>[dia=>valor]]]
$integracoesOrigem = []; // [cdintegracao => [cdvariavel, cdvariavel, ...]]
foreach ($dashboards as $dash) {
    if (!empty($dash['fl_origem']) && !empty($dash['cdintegracao'])) {
        $integracoesOrigem[(int)$dash['cdintegracao']][] = (int)$dash['cdvariavel'];
    }
}
if (!empty($integracoesOrigem)) {
    $empsFiltro = !empty($empresasSelecionadas) ? $empresasSelecionadas : [$cdempresaSessao];
    $empsFiltro = array_filter(array_map('intval', $empsFiltro), fn($e) => $e > 0);

    // Buscar nomes das integrações
    $idsInteg = array_keys($integracoesOrigem);
    $phInteg = implode(',', array_fill(0, count($idsInteg), '?'));
    $stNomes = $pdo->prepare("SELECT cdintegracao, dsintegracao FROM back.integracao WHERE cdintegracao IN ($phInteg)");
    $stNomes->execute(array_values($idsInteg));
    $nomesInteg = [];
    foreach ($stNomes->fetchAll(PDO::FETCH_ASSOC) as $ni) {
        $nomesInteg[(int)$ni['cdintegracao']] = $ni['dsintegracao'];
    }

    // Buscar soma total e soma por dia do mês corrente
    foreach ($integracoesOrigem as $cdinteg => $cdvars) {
        $origemInfo = [
            'dsintegracao'   => $nomesInteg[$cdinteg] ?? 'Origem #' . $cdinteg,
            'valor_total'    => 0.0,
            'valor_hoje'     => 0.0,
            'valor_raw'      => null,
            'valores_por_dia'=> [],
        ];

        if (!empty($empsFiltro)) {
            $phEmps = implode(',', array_fill(0, count($empsFiltro), '?'));
            // Total: apenas o ÚLTIMO registro por empresa (posição mais recente)
            $sqlTotal = "WITH ultimo_por_empresa AS (
                            SELECT cdempresa, valor,
                                   ROW_NUMBER() OVER (PARTITION BY cdempresa ORDER BY dtimportacao DESC) AS rn
                              FROM back.origem_dados
                             WHERE cdintegracao = ?
                               AND cdempresa IN ($phEmps)
                        )
                        SELECT COALESCE(SUM(CASE WHEN valor ~ '^-?[0-9]+(\\.[0-9]+)?$' THEN CAST(REPLACE(valor, ',', '.') AS NUMERIC) ELSE 0 END), 0) AS total
                          FROM ultimo_por_empresa
                         WHERE rn = 1";
            $paramsTotal = array_merge([$cdinteg], array_values($empsFiltro));
            $stTotal = $pdo->prepare($sqlTotal);
            $stTotal->execute($paramsTotal);
            $origemInfo['valor_total'] = (float)$stTotal->fetchColumn();

            // Por dia (usa dtimportacao para agrupar) - pega apenas o ÚLTIMO registro por dia/empresa
            $sqlDia = "WITH ultimo_por_dia AS (
                            SELECT EXTRACT(DAY FROM dtimportacao)::int AS dia,
                                   cdempresa,
                                   valor,
                                   ROW_NUMBER() OVER (PARTITION BY cdempresa, EXTRACT(DAY FROM dtimportacao)::int ORDER BY dtimportacao DESC) AS rn
                              FROM back.origem_dados
                             WHERE cdintegracao = ?
                               AND cdempresa IN ($phEmps)
                               AND EXTRACT(YEAR FROM dtimportacao) = ?
                               AND EXTRACT(MONTH FROM dtimportacao) = ?
                        )
                        SELECT dia,
                               COALESCE(SUM(CASE WHEN valor ~ '^-?[0-9]+(\\.[0-9]+)?$' THEN CAST(REPLACE(valor, ',', '.') AS NUMERIC) ELSE 0 END), 0) AS total
                          FROM ultimo_por_dia
                         WHERE rn = 1
                      GROUP BY dia
                      ORDER BY dia";
            $paramsDia = array_merge([$cdinteg], array_values($empsFiltro), [$anoFiltro, $mesAtual]);
            $stDia = $pdo->prepare($sqlDia);
            $stDia->execute($paramsDia);
            foreach ($stDia->fetchAll(PDO::FETCH_ASSOC) as $rowDia) {
                $origemInfo['valores_por_dia'][(int)$rowDia['dia']] = (float)$rowDia['total'];
            }

            // Valor de hoje (antes das 6h: tenta dia real primeiro, senão dia anterior)
            $_h6 = (int)date('G');
            if ($_h6 < 6) {
                $_dReal = (int)date('j');
                $_dOntem = (int)date('j', strtotime('-1 day'));
                $origemInfo['valor_hoje'] = $origemInfo['valores_por_dia'][$_dReal]
                    ?? $origemInfo['valores_por_dia'][$_dOntem]
                    ?? 0.0;
            } else {
                $origemInfo['valor_hoje'] = $origemInfo['valores_por_dia'][(int)date('j')] ?? 0.0;
            }

            // Buscar valor bruto mais recente (para exibir sem formatação quando não numérico)
            $sqlRaw = "SELECT valor FROM back.origem_dados
                        WHERE cdintegracao = ? AND cdempresa IN ($phEmps)
                     ORDER BY dtimportacao DESC LIMIT 1";
            $paramsRaw = array_merge([$cdinteg], array_values($empsFiltro));
            $stRaw = $pdo->prepare($sqlRaw);
            $stRaw->execute($paramsRaw);
            $origemInfo['valor_raw'] = $stRaw->fetchColumn() ?: null;
        }

        // Atribuir a mesma origemInfo para todas as variáveis vinculadas a esta integração
        foreach ($cdvars as $cdvar) {
            $origemPorVariavel[$cdvar] = $origemInfo;
        }
    }
}

// Auto-switch: quando consolidar empresas via filtro (multi-seleção)
// Só faz auto-switch para 'modelo' se o usuário tiver permissão
if (!$visaoParam && !((bool)($_SESSION['dashboard_visao_explicit'] ?? false))) {
    if (is_array($empresasSelecionadas) && count($empresasSelecionadas) > 1) {
        if (in_array('modelo', $visoesUsuario, true)) {
            $visaoDashboard = 'modelo';
            $_SESSION['dashboard_visao'] = 'modelo';
            $modoPercentual = false;
        }
    }
}

// ============================
// MOSTRAR ALERTA SE FILTROS FORAM APLICADOS
// ============================
if ($filtrosAplicados) {
    $empresasNomes = [];
    foreach ($empresasSelecionadas as $empId) {
        foreach ($empresasFiltro as $emp) {
            if ((int)$emp['cdempresa'] === $empId) {
                $empresasNomes[] = $emp['dsapelido'];
                break;
            }
        }
    }
    
    // Encontrar nome do centro de custo
    $centroCustoNome = 'Todos';
    if ($cdcentrocustoFiltro > 0) {
        foreach ($centrosCustoFiltro as $cc) {
            if ((int)$cc['cdcentrocusto'] === $cdcentrocustoFiltro) {
                $centroCustoNome = $cc['dscentro'];
                break;
            }
        }
    }
    
    // Encontrar nome do país
    $paisNome = 'Todos';
    if ($cdpaisFiltro > 0) {
        foreach ($paisesFiltro as $p) {
            if ((int)$p['cdpais'] === $cdpaisFiltro) {
                $paisNome = $p['dspais'];
                break;
            }
        }
    }
    
    // Encontrar nome do trimestre
    $trimestreNome = 'Todos';
    foreach ($trimestresFiltro as $t) {
        if ((int)$t['numero'] === $trimestreFiltro) {
            $trimestreNome = $t['descricao'];
            break;
        }
    }
    
    // Encontrar nome da moeda
    $moedaNome = '';
    foreach ($moedasFiltro as $m) {
        if ((int)$m['cdmoeda'] === $cdmoedaFiltro) {
            $moedaNome = $m['simbolo'];
            break;
        }
    }
}

// Dados auxiliares para gráficos (um por variável de dashboard)
$chartData = [];
foreach ($dashboards as $dash) {
    $labels        = [];
    $anoOrcado     = [];
    $anoReal       = [];
    $anoRealAnt    = [];
    $mesOrcado     = [];
    $mesReal       = [];
    $mesRealAnt    = [];

    foreach ($dash['secoes'] as $sec) {
        $labels[]     = $sec['titulo'];
        $anoOrcado[]  = (float)$sec['ano']['orcado'];
        $anoReal[]    = (float)$sec['ano']['realizado'];
        $anoRealAnt[] = (float)$sec['ano']['realizadoAnterior'];
        $mesOrcado[]  = (float)$sec['mes']['orcado'];
        $mesReal[]    = (float)$sec['mes']['realizado'];
        $mesRealAnt[] = (float)$sec['mes']['realizadoAnterior'];
    }

    $chartData[] = [
        'id'     => (int)$dash['cdvariavel'],
        'nome'   => $dash['nome'],
        'labels' => $labels,
        'ano'    => [
            'orcado'            => $anoOrcado,
            'realizado'         => $anoReal,
            'realizadoAnterior' => $anoRealAnt,
        ],
        'mes'    => [
            'orcado'            => $mesOrcado,
            'realizado'         => $mesReal,
            'realizadoAnterior' => $mesRealAnt,
        ],
    ];
}

function formatarValorDashboard(float $v, string $mascara, array $moeda): string {
    if ($mascara === 'percentual') {
        return number_format($v * 100, 2, ',', '.') . ' %';
    }

    $simbolo = $moeda['simbolo'] ?? 'R$';
    $formato = $moeda['formato'] ?? 'decimal';
    $casas   = ($formato === 'inteiro') ? 0 : 2;

    return $simbolo . ' ' . number_format($v, $casas, ',', '.');
}

function formatarPercentDashboard(float $v): string {
    return number_format($v * 100, 1, ',', '.') . ' %';
}

/**
 * Pesos padrão por dia da semana para restaurantes.
 * Índice: 0=Domingo, 1=Segunda, 2=Terça, 3=Quarta, 4=Quinta, 5=Sexta, 6=Sábado
 * Definido em home_service.php; guard para evitar redeclaração.
 */
if (!function_exists('obterPesosPadraoDiaSemana')) {
    function obterPesosPadraoDiaSemana(): array {
        return [
            0 => 1.3,  // Domingo
            1 => 0.8,  // Segunda
            2 => 0.9,  // Terça
            3 => 1.0,  // Quarta
            4 => 1.1,  // Quinta
            5 => 1.3,  // Sexta
            6 => 1.6,  // Sábado
        ];
    }
}

/**
 * Calcula a meta diária para um dia específico do mês.
 * Se $usarPeso = true, distribui proporcionalmente pelos pesos do dia da semana.
 * Se $usarPeso = false, distribui linearmente (orcMes / diasMes).
 *
 * @param float $orcMes  Meta/orçamento total do mês
 * @param int   $dia     Dia do mês (1-31)
 * @param int   $mes     Mês (1-12)
 * @param int   $ano     Ano
 * @param bool  $usarPeso Se deve usar pesos por dia da semana
 * @return float Meta proporcional para aquele dia
 */
function calcularMetaDiaria(float $orcMes, int $dia, int $mes, int $ano, bool $usarPeso): float {
    if ($orcMes == 0.0) return 0.0;
    $ultimoDia = (int)date('t', mktime(0, 0, 0, $mes, 1, $ano));
    if ($ultimoDia <= 0) return 0.0;

    if (!$usarPeso) {
        return $orcMes / $ultimoDia;
    }

    $pesos = obterPesosPadraoDiaSemana();
    $somaPesos = 0.0;
    for ($d = 1; $d <= $ultimoDia; $d++) {
        $dow = (int)date('w', mktime(0, 0, 0, $mes, $d, $ano));
        $somaPesos += ($pesos[$dow] ?? 1.0);
    }
    if ($somaPesos <= 0.0) return $orcMes / $ultimoDia;

    $dowDia = (int)date('w', mktime(0, 0, 0, $mes, $dia, $ano));
    return ($orcMes * ($pesos[$dowDia] ?? 1.0)) / $somaPesos;
}

/**
 * Retorna a classe de cor CSS baseada na projeção.
 * - Para metas: Verde (>=100%), Amarelo (95-99.99%), Vermelho (<95%)
 * - Para orçamento: Verde (<=80%), Amarelo (<=90%), Vermelho (>90%)
 */
function obterClasseCorProjecao(?float $projPerc, ?string $modelo = null): string {
    $m = strtolower(trim((string)$modelo));
    $v = ($projPerc === null) ? 0.0 : abs((float)$projPerc); // Usar valor absoluto para suportar orçamentos negativos

    if ($m === 'orcamento') {
        if ($v <= 0.80) return 'text-success';
        if ($v <= 0.90) return 'text-warning';
        return 'text-danger';
    }

    if ($v >= 1.0) return 'text-success';
    if ($v >= 0.95) return 'text-warning';
    return 'text-danger';
}

/**
 * Retorna a cor HEX baseada na projeção.
 * - Para metas: Verde (>=100%), Amarelo (95-99.99%), Vermelho (<95%)
 * - Para orçamento: Verde (<=80%), Amarelo (<=90%), Vermelho (>90%)
 */
function obterCorHexProjecao(?float $projPerc, ?string $modelo = null): string {
    $m = strtolower(trim((string)$modelo));
    $v = ($projPerc === null) ? 0.0 : abs((float)$projPerc); // Usar valor absoluto para suportar orçamentos negativos

    if ($m === 'orcamento') {
        if ($v <= 0.80) return '#16a34a';
        if ($v <= 0.90) return '#f59e0b';
        return '#dc2626';
    }

    if ($v >= 1.0) return '#16a34a';
    if ($v >= 0.95) return '#f59e0b';
    return '#dc2626';
}

/**
 * Retorna dicionário de linguagem baseado no modelo da variável
 * @param string $modelo 'meta' ou 'orcamento'
 * @return array Dicionário com labels de linguagem
 */
function obterLinguagem(string $modelo): array {
    $modeloNorm = strtolower(trim($modelo));
    
    // Para qualquer modelo diferente de 'orcamento', usa linguagem de "Meta"
    // (inclui: meta, submeta, resultado e futuros modelos).
    if ($modeloNorm !== 'orcamento') {
        $descricao = match ($modeloNorm) {
            'submeta' => 'SubMeta',
            'meta' => 'Metas',
            'resultado' => 'Resultado',
            default => ucfirst($modeloNorm),
        };

        return [
            'planejado'        => 'Meta',
            'realizado'        => 'Realizado',
            'percentual_label' => 'Realizado',
            'restante'         => 'A Realizar',
            'percentual_desc'  => '% Realizado',
            'restante_desc'    => '% que Resta',
            'vs_anterior'      => 'Sob o Ano Anterior',
            'projecao'         => 'Projeção',
            'descricao'        => $descricao,
        ];
    }
    
    // Padrão para 'orcamento'
    return [
        'planejado'        => 'Orçamento',
        'realizado'        => 'Gasto Realizado',
        'percentual_label' => 'Consumido',
        'restante'         => 'Disponivel',
        'percentual_desc'  => '% do orçamento consumido',
        'restante_desc'    => '% de saldo disponível',
        'vs_anterior'      => 'Vs Período Anterior',
        'projecao'         => 'Projeção de Gasto',
        'descricao'        => 'Orçamento',
    ];
}

function boolFromDb($v): bool {
    if (is_bool($v)) {
        return $v;
    }
    if (is_int($v)) {
        return $v === 1;
    }
    $s = strtolower(trim((string)$v));
    return in_array($s, ['1', 'true', 't', 'yes', 'on'], true);
}

$nomesMes      = ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'];
$nomeMesAtual  = $nomesMes[$mesAtual-1] ?? '';

// Dados de calendário (sem cache)
$anoCorrente  = (int)date('Y');
$mesCorrente  = (int)date('n');
$diaCorrente  = (int)date('j');

// "Hoje" para fins de exibição: antes das 6h considera o dia anterior
$horaAtual = (int)date('G'); // 0-23
if ($horaAtual < 6) {
    $tsOntem   = strtotime('-1 day');
    $diaHoje   = (int)date('j', $tsOntem);
    $mesHoje   = (int)date('n', $tsOntem);
    $anoHoje   = (int)date('Y', $tsOntem);
} else {
    $diaHoje   = $diaCorrente;
    $mesHoje   = $mesCorrente;
    $anoHoje   = $anoCorrente;
}

// Data "hoje" ajustada (antes das 6h = ontem) — usar em todo cálculo de realizado/aberto
$hojeStr6h = sprintf('%04d-%02d-%02d', $anoHoje, $mesHoje, $diaHoje);

$ultimoDia = (int)date('t', mktime(0, 0, 0, $mesCorrente, 1, $anoCorrente));

// Calcula fins de semana restantes (mês inteiro)
$finsSemanaRestantes = 0;
for ($d = 1; $d <= $ultimoDia; $d++) {
    $ts = mktime(0, 0, 0, $mesCorrente, $d, $anoCorrente);
    $w  = (int)date('w', $ts);
    if ($w === 6) { $finsSemanaRestantes++; }
}

// Busca feriados do mês inteiro (sem projeção)
$feriadosBase = obterFeriadosMesBase($pdo, $mesCorrente, $anoCorrente, 1);
$feriadosData = [
    'qtd' => count($feriadosBase),
    'lista' => $feriadosBase,
];
$feriadoDiaUtil = obterFeriadoDiaUtil($pdo);

// Parâmetro: usar peso por dia da semana na meta diária?
$usarPesoDia = obterParametroUsarPesoDia($pdo);

// Recalcula valores que dependem do dia corrente
$diasRestantesMesCorrente = max(0, $ultimoDia - $diaCorrente + 1);

// Filtra feriados restantes a partir do dia corrente
$feriadosBaseTodos = $feriadosData['lista'] ?? [];
$feriadosRestantes = array_filter($feriadosBaseTodos, function($f) use ($diaCorrente, $mesCorrente) {
    $parts = explode('/', $f['data']);
    return count($parts) === 2 && (int)$parts[0] >= $diaCorrente;
});
$feriadosRestantes = array_values($feriadosRestantes);
$qtdFeriadosRestantes = count($feriadosRestantes);

// Recalcula fins de semana restantes
$finsSemanaRestantes = 0;
for ($d = $diaCorrente; $d <= $ultimoDia; $d++) {
    $ts = mktime(0, 0, 0, $mesCorrente, $d, $anoCorrente);
    $w  = (int)date('w', $ts);
    if ($w === 6) { $finsSemanaRestantes++; }
}



// Dias restantes do ano (usado nas telas)
$diaAnoAtualGlobal = (int)date('z') + 1; // 1 a 366
$diasAnoAnteriorGlobal = date('L') ? 366 : 365;
$diasRestantesAno = $diasAnoAnteriorGlobal - $diaAnoAtualGlobal;

// Percentual de projeção de feriados (busca única)
$percentualProjecaoFeriado = obterPercentualProjecaoFeriado($pdo);

    // Pré-calcula contas por variável usando fórmulas já carregadas
    $contasPorVariavel = [];
    // Conjunto total de contas usadas no dashboard
    $contasDashboard = [];
    foreach ($dashboards as $dash) {
        $contasUsadas = [];
        foreach ($dash['secoes'] as $sec) {
            if (!empty($sec['formula'])) {
                preg_match_all('/\d+/', $sec['formula'], $m);
                foreach ($m[0] as $cd) {
                    $contasUsadas[(int)$cd] = true;
                    $contasDashboard[(int)$cd] = true;
                }
            }
        }
        $contasPorVariavel[(int)$dash['cdvariavel']] = array_keys($contasUsadas);
    }

    $contasDashboard = array_keys($contasDashboard);
    // Mapa [conta][dia] => valor do ano anterior (mês corrente)
    $mapContaDiaMes = obterValoresContasDiasAnoAnteriorMes($pdo, $cdempresa, $mesCorrente, $contasDashboard);
    
    // Mapa [conta][dia] => valor do mês atual - CONSOLIDADO para múltiplas empresas
    $mapContaDiaMesAtual = [];
    $mapContaDiaMesAtualPorEmpresa = []; // [cdempresa][conta][dia] => valor (para tendência por empresa)
    $empresasParaDadosDias = !empty($empresaParaDados) ? $empresaParaDados : [$cdempresa];
    foreach ($empresasParaDadosDias as $cdempEmp) {
        $mapEmp = obterValoresContasDiasMesAtual($pdo, (int)$cdempEmp, $mesCorrente, $anoCorrente, $contasDashboard);
        $mapContaDiaMesAtualPorEmpresa[(int)$cdempEmp] = $mapEmp;
        // Consolida os valores por dia
        foreach ($mapEmp as $conta => $diasValores) {
            if (!isset($mapContaDiaMesAtual[$conta])) {
                $mapContaDiaMesAtual[$conta] = [];
            }
            foreach ($diasValores as $dia => $valor) {
                $mapContaDiaMesAtual[$conta][$dia] = ($mapContaDiaMesAtual[$conta][$dia] ?? 0.0) + $valor;
            }
        }
    }

    // Mapa [conta]['YYYY-MM-DD'] => valor do dia - ÚLTIMOS 7 DIAS (cruza meses)
    // Consolidado para múltiplas empresas
    $mapContaUltimos7Dias = [];
    foreach ($empresasParaDadosDias as $cdempEmp) {
        $mapEmp7 = obterValoresContasUltimosDias($pdo, (int)$cdempEmp, 7, $contasDashboard);
        foreach ($mapEmp7 as $conta => $datasValores) {
            if (!isset($mapContaUltimos7Dias[$conta])) {
                $mapContaUltimos7Dias[$conta] = [];
            }
            foreach ($datasValores as $dataStr => $valor) {
                $mapContaUltimos7Dias[$conta][$dataStr] = ($mapContaUltimos7Dias[$conta][$dataStr] ?? 0.0) + $valor;
            }
        }
    }

    // KPIs por variável (cada dashboard como âncora)
    $kpisVariaveis      = [];
    $mascaraPorVariavel = [];
    $modeloPorVariavel  = [];
    $metaOrcAnoTotal = 0.0;
    $metaRealAnoTotal = 0.0;
    $metaOrcMesTotal = 0.0;
    $metaRealMesTotal = 0.0;
    $metaOrcTrimTotal = 0.0;
    $metaRealTrimTotal = 0.0;
    foreach ($dashboards as $dash) {
        if (empty($dash['secoes'])) {
            continue;
        }

        $vid = (int)$dash['cdvariavel'];
        $modelo = $dash['modelo'] ?? 'orcamento';
        $isOrcamento = (strtolower(trim((string)$modelo)) === 'orcamento');
        $modeloPorVariavel[$vid] = $modelo;

        $orcAnoTotal     = 0.0;
        $realAnoTotal    = 0.0;
        $realAnoAntTotal = 0.0;
        $projAnoTotal    = 0.0;
        $orcMesTotal     = 0.0;
        $realMesTotal    = 0.0;
        $realMesAntTotal = 0.0;
        $projMesTotal    = 0.0;
        $orcTrimTotal    = 0.0;
        $realTrimTotal   = 0.0;
        $realTrimAntTotal = 0.0;
        $projTrimTotal   = 0.0;

        foreach ($dash['secoes'] as $secResumo) {
            $anoResumo = $secResumo['ano'];
            $orcAnoTotal     += (float)$anoResumo['orcado'];
            $realAnoTotal    += (float)$anoResumo['realizado'];
            $realAnoAntTotal += (float)$anoResumo['realizadoAnterior'];
            $projAnoTotal    += (float)$anoResumo['projValor'];
            
            $mesResumo = $secResumo['mes'];
            $orcMesTotal     += (float)$mesResumo['orcado'];
            $realMesTotal    += (float)$mesResumo['realizado'];
            $realMesAntTotal += (float)($mesResumo['realizadoAnterior'] ?? 0.0);
            $projMesTotal    += (float)($mesResumo['projValor'] ?? 0.0);
            
            $trimResumo = $secResumo['trimestre'];
            $orcTrimTotal    += (float)$trimResumo['orcado'];
            $realTrimTotal   += (float)$trimResumo['realizado'];
            $realTrimAntTotal += (float)($trimResumo['realizadoAnterior'] ?? 0.0);
            $projTrimTotal   += (float)$trimResumo['projValor'];

            // Acúmulo para resumo das variáveis do tipo 'meta'
            if (($modelo ?? 'orcamento') === 'meta') {
                $metaOrcAnoTotal  += (float)$anoResumo['orcado'];
                $metaRealAnoTotal += (float)$anoResumo['realizado'];
                $metaOrcMesTotal  += (float)$mesResumo['orcado'];
                $metaRealMesTotal += (float)$mesResumo['realizado'];
                $metaOrcTrimTotal += (float)$trimResumo['orcado'];
                $metaRealTrimTotal += (float)$trimResumo['realizado'];
            }
        }

        // Modelo ORÇAMENTO: normaliza sinal (débito pode vir negativo)
        if ($isOrcamento) {
            $orcAnoTotal = abs($orcAnoTotal);
            $realAnoTotal = abs($realAnoTotal);
            $realAnoAntTotal = abs($realAnoAntTotal);
            $projAnoTotal = abs($projAnoTotal);
            $orcMesTotal = abs($orcMesTotal);
            $realMesTotal = abs($realMesTotal);
            $realMesAntTotal = abs($realMesAntTotal);
            $orcTrimTotal = abs($orcTrimTotal);
            $realTrimTotal = abs($realTrimTotal);
            $realTrimAntTotal = abs($realTrimAntTotal);
            $projTrimTotal = abs($projTrimTotal);
        }

        // Para ORÇAMENTO: atingPerc = consumo/realizado %; para META/SUBMETA: atingPerc = alcance%
        if ($isOrcamento) {
            // Orçamento: usa período (mes) para o cálculo principal
            $atingidoPerc   = ($orcMesTotal != 0.0) ? ($realMesTotal / $orcMesTotal) : 0.0;
        } else {
            // Meta/Submeta: usa ano para o cálculo principal (consolidado)
            $atingidoPerc   = ($orcAnoTotal != 0.0) ? ($realAnoTotal / $orcAnoTotal) : 0.0;
        }
        $restantePerc   = max(0.0, 1.0 - $atingidoPerc);
        
        // Obter valores do período anterior já calculados no loop
        $realMesAntPeriodo = $realMesAntTotal;
        $realAnoAntPeriodo = $realAnoAntTotal;
        
        // Calcula variações
        $varMesAnterior = ($realMesAntPeriodo != 0.0) ? (($realMesTotal - $realMesAntPeriodo) / abs($realMesAntPeriodo)) : null;
        $varAnoAnterior = ($realAnoAntPeriodo != 0.0) ? (($realAnoTotal - $realAnoAntPeriodo) / abs($realAnoAntPeriodo)) : null;
        
        // Projeções: usar os valores já calculados no serviço (respeita multi-mês e regras de período)
        $projMesValor = (float)$projMesTotal;
        $projMesPerc  = ($orcMesTotal != 0.0) ? ($projMesValor / $orcMesTotal) : 0.0;
        
        $projTrimValor = (float)$projTrimTotal;
        $projTrimPerc  = ($orcTrimTotal != 0.0) ? ($projTrimValor / $orcTrimTotal) : 0.0;
        
        $projAnoValor = (float)$projAnoTotal;
        $projAnoPerc  = ($orcAnoTotal != 0.0) ? ($projAnoValor / $orcAnoTotal) : 0.0;
        
        // Variações vs. período anterior
        $varTrimAnterior = null;
        if ($realTrimAntTotal != 0.0) {
            $varTrimAnterior = (($realTrimTotal - $realTrimAntTotal) / abs($realTrimAntTotal));
        }

        $kpisVariaveis[] = [
            'id'            => (int)$dash['cdvariavel'],
            'nome'          => $dash['nome'],
            'modelo'        => $modelo,
            'grafico'       => $dash['grafico'] ?? false,
            'fl_origem'       => $dash['fl_origem'] ?? false,
            'cdintegracao'    => $dash['cdintegracao'] ?? null,
            'fl_agregar_calc' => $dash['fl_agregar_calc'] ?? false,
            'orcAno'        => $orcAnoTotal,
            'realAno'       => $realAnoTotal,
            'realAnoAnt'    => $realAnoAntPeriodo,
            'atingPerc'     => $atingidoPerc,
            'restantePerc'  => $restantePerc,
            'varAno'        => $varAnoAnterior,
            'projAnoValor'  => $projAnoValor,
            'projAnoPerc'   => $projAnoPerc,
            'orcMes'        => $orcMesTotal,
            'realMes'       => $realMesTotal,
            'realMesAnt'    => $realMesAntPeriodo,
            'varMes'        => $varMesAnterior,
            'projMesValor'  => $projMesValor,
            'projMesPerc'   => $projMesPerc,
            'orcTrim'       => $orcTrimTotal,
            'realTrim'      => $realTrimTotal,
            'realTrimAnt'   => $realTrimAntTotal,
            'varTrim'       => $varTrimAnterior,
            'projTrimValor' => $projTrimValor,
            'projTrimPerc'  => $projTrimPerc,
        ];

        $mascaraPorVariavel[(int)$dash['cdvariavel']] = $dash['secoes'][0]['mascara'] ?? 'moeda';
    }

    // Ordenar kpisVariaveis: primeiro pela ordem do modelo (meta > submeta > orcamento),
    // depois pela pior performance dentro de cada modelo
    $_ordemModelo = ['meta' => 1, 'submeta' => 2, 'orcamento' => 3, 'resultado' => 4];
    usort($kpisVariaveis, function ($a, $b) use ($modeloPorVariavel, $_ordemModelo) {
        $modA = strtolower(trim((string)($modeloPorVariavel[$a['id']] ?? 'orcamento')));
        $modB = strtolower(trim((string)($modeloPorVariavel[$b['id']] ?? 'orcamento')));
        $ordA = $_ordemModelo[$modA] ?? 99;
        $ordB = $_ordemModelo[$modB] ?? 99;
        if ($ordA !== $ordB) return $ordA - $ordB;
        // Dentro do mesmo modelo: pior performance primeiro
        $percA = abs((float)($a['projMesPerc'] ?? 0));
        $percB = abs((float)($b['projMesPerc'] ?? 0));
        if ($modA === 'orcamento') {
            // Orçamento: pior = maior % (mais estourado)
            return $percB <=> $percA;
        }
        // Meta/submeta: pior = menor % (mais abaixo da meta)
        return $percA <=> $percB;
    });

    // Resumo BI usa a primeira variável como principal
    $kpiResumo = $kpisVariaveis[0] ?? null;
    $mascaraPrincipal = null;
    $modeloPrincipal = 'orcamento';
    if ($kpiResumo) {
        $mascaraPrincipal = $mascaraPorVariavel[$kpiResumo['id']] ?? 'moeda';
        $modeloPrincipal = $modeloPorVariavel[$kpiResumo['id']] ?? 'orcamento';
    }

    // Dados dos gráficos (cards do topo): apenas variáveis com grafico = true
    $metasCharts = [];
    foreach ($kpisVariaveis as $kv) {
        if (!boolFromDb($kv['grafico'] ?? false)) {
            continue;
        }

        $modelo = $modeloPorVariavel[$kv['id']] ?? 'orcamento';
        
        // Obter dados diários para esta variável (últimos 7 dias - cruza meses)
        $diasHistorico = []; // chave = 'YYYY-MM-DD'
        $contasVar = $contasPorVariavel[(int)$kv['id']] ?? [];
        if (!empty($contasVar) && !empty($mapContaUltimos7Dias)) {
            // Pega os últimos 7 dias usando mapa cross-month
            $diasDisponibles = [];
            foreach ($contasVar as $conta) {
                if (isset($mapContaUltimos7Dias[$conta])) {
                    foreach ($mapContaUltimos7Dias[$conta] as $dataStr => $valor) {
                        $diasDisponibles[$dataStr] = ($diasDisponibles[$dataStr] ?? 0.0) + $valor;
                    }
                }
            }
            // Ordena decrescente (últimos dias primeiro) - chaves YYYY-MM-DD ordenam naturalmente
            krsort($diasDisponibles);
            $diasHistorico = array_slice($diasDisponibles, 0, 7, true);
        }

        // Se fl_agregar_calc = true, somar origem apenas no dia corrente dentro do histórico
        $origemVar = $origemPorVariavel[$kv['id']] ?? null;
        $hojeStr = $hojeStr6h; // antes das 6h = dia anterior
        $_origemBreakdownStrip = null;
        if (!empty($kv['fl_agregar_calc']) && $origemVar && isset($diasHistorico[$hojeStr])) {
            $_contasFechadasStrip = (float)$diasHistorico[$hojeStr];
            $_valorOrigemStrip = (float)($origemVar['valor_hoje'] ?? 0.0);
            $diasHistorico[$hojeStr] += $_valorOrigemStrip;
            if ($_valorOrigemStrip != 0) {
                $_origemBreakdownStrip = [
                    'f'  => $_contasFechadasStrip,
                    'a'  => $_valorOrigemStrip,
                    'on' => $origemVar['dsintegracao'] ?? 'Contas Abertas',
                ];
            }
        }

        $metasCharts[] = [
            'id'     => $kv['id'],
            'nome'   => $kv['nome'],
            'modelo' => $modelo,
            'orcAno' => $kv['orcAno'],
            'realAno'=> $kv['realAno'],
            'orcMes' => $kv['orcMes'],
            'realMes'=> $kv['realMes'],
            'projAnoPerc' => $kv['projAnoPerc'],
            'projMesPerc' => $kv['projMesPerc'],
            'restantePerc' => $kv['restantePerc'] ?? 0.0,
            'diasHistorico' => $diasHistorico,
            'fl_origem'       => $kv['fl_origem'] ?? false,
            'fl_agregar_calc' => $kv['fl_agregar_calc'] ?? false,
            'origemBreakdownStrip' => $_origemBreakdownStrip,
        ];
    }

    // Visão consolidada por modelo (variáveis do tipo Dashboard)
    $visaoConsolidadaPorModelo = montarVisaoConsolidadaPorModelo($kpisVariaveis);

    // ==== ORÇAMENTO CONSOLIDADO ====
    // Agrupa TODOS os valores de orçamento (variáveis com modelo = 'orcamento')
    $orcamentoConsolidado = [
        'orcMes'        => 0.0,
        'realMes'       => 0.0,
        'projMesValor'  => 0.0,
        'orcTrim'       => 0.0,
        'realTrim'      => 0.0,
        'projTrimValor' => 0.0,
        'orcAno'        => 0.0,
        'realAno'       => 0.0,
        'projAnoValor'  => 0.0,
        'projMesPerc'   => 0.0,
        'projTrimPerc'  => 0.0,
        'projAnoPerc'   => 0.0,
    ];
    $orcamentoVariavelIds = [];
    
    foreach ($kpisVariaveis as $kv) {
        if ((strtolower(trim((string)($modeloPorVariavel[$kv['id']] ?? 'orcamento'))) === 'orcamento')) {
            $orcamentoVariavelIds[] = (int)$kv['id'];
            $orcamentoConsolidado['orcMes']        += (float)($kv['orcMes'] ?? 0.0);
            $orcamentoConsolidado['realMes']       += (float)($kv['realMes'] ?? 0.0);
            $orcamentoConsolidado['projMesValor']  += (float)($kv['projMesValor'] ?? 0.0);
            $orcamentoConsolidado['orcTrim']       += (float)($kv['orcTrim'] ?? 0.0);
            $orcamentoConsolidado['realTrim']      += (float)($kv['realTrim'] ?? 0.0);
            $orcamentoConsolidado['projTrimValor'] += (float)($kv['projTrimValor'] ?? 0.0);
            $orcamentoConsolidado['orcAno']        += (float)($kv['orcAno'] ?? 0.0);
            $orcamentoConsolidado['realAno']       += (float)($kv['realAno'] ?? 0.0);
            $orcamentoConsolidado['projAnoValor']  += (float)($kv['projAnoValor'] ?? 0.0);
        }
    }
    
    // Calcular percentuais do consolidado com base na projeção (não apenas realizado)
    if ($orcamentoConsolidado['orcMes'] > 0) {
        $orcamentoConsolidado['projMesPerc'] = $orcamentoConsolidado['projMesValor'] / $orcamentoConsolidado['orcMes'];
    }
    if ($orcamentoConsolidado['orcTrim'] > 0) {
        $orcamentoConsolidado['projTrimPerc'] = $orcamentoConsolidado['projTrimValor'] / $orcamentoConsolidado['orcTrim'];
    }
    if ($orcamentoConsolidado['orcAno'] > 0) {
        $orcamentoConsolidado['projAnoPerc'] = $orcamentoConsolidado['projAnoValor'] / $orcamentoConsolidado['orcAno'];
    }

    // Visão consolidada POR EMPRESA: ao consolidar (multi-empresa), gera um dataset por empresa selecionada
    $visaoConsolidadaEmpresas = [];
    $valRealizadosMensaisEmp = []; // [cdempresa][mes][conta] => valor (para tendência por empresa)
    $valOrcadosMensaisEmp    = []; // [cdempresa][mes][conta] => valor
    {
        // Mapa de nomes para fallback (lista acessível já filtrada)
        $mapNomeEmpresa = [];
        foreach ($empresasFiltro as $emp) {
            $eid = (int)($emp['cdempresa'] ?? 0);
            if ($eid <= 0) continue;
            $mapNomeEmpresa[$eid] = (string)($emp['dsapelido'] ?? $emp['dsempresa'] ?? ('Empresa ' . $eid));
        }

        // Se não houver empresas selecionadas por algum motivo, usa empresa exibida
        $empresasParaConsolidar = $empresasSelecionadas;
        if (empty($empresasParaConsolidar) && $cdempresaSessao > 0) {
            $empresasParaConsolidar = [$cdempresaSessao];
        }

        // Se for 1 empresa, reutiliza o KPI já calculado (mais completo)
        if (is_array($empresasParaConsolidar) && count($empresasParaConsolidar) === 1) {
            $eid = (int)$empresasParaConsolidar[0];
            $valRealizadosMensaisEmp[$eid] = $valoresRealizadosMensais;
            $valOrcadosMensaisEmp[$eid]    = $valoresOrcadosMensais;
            $visaoConsolidadaEmpresas[] = [
                'cdempresa' => $eid,
                'dsempresa' => (string)($dsempresa ?: ($mapNomeEmpresa[$eid] ?? ('Empresa ' . $eid))),
                'modelos'   => $visaoConsolidadaPorModelo,
            ];
        } else {
            foreach ($empresasParaConsolidar as $eidRaw) {
                $eid = (int)$eidRaw;
                if ($eid <= 0) continue;

                $dadosEmp = obterDadosDashboard($pdo, 0, $cdcentrocustoFiltro, $anoFiltro, $trimestreFiltro, $mesesSelecionados, [$eid], $eid, $cdpaisFiltro);
                if (!($dadosEmp['ok'] ?? false)) {
                    continue;
                }

                $dashEmp = $dadosEmp['dashboards'] ?? [];
                $anorefEmp = (int)($dadosEmp['anoref'] ?? $anoref);
                $mesAtualEmp = (int)($dadosEmp['mesAtual'] ?? $mesAtual);

                // Capturar valores mensais por empresa (para tendência por empresa)
                $valRealizadosMensaisEmp[$eid] = $dadosEmp['valoresRealizadosMensais'] ?? [];
                $valOrcadosMensaisEmp[$eid]    = $dadosEmp['valoresOrcadosMensais'] ?? [];

                // KPIs mínimos para consolidação/gráfico (mantém projeção se disponível)
                $kpisEmp = montarKpisBasicosFromDashboards(
                    $dashEmp,
                    $mesAtualEmp,
                    $anorefEmp,
                    $mesesSelecionados,
                    $mesCorrente,
                    $anoCorrente,
                    (int)$trimestreFiltro,
                    $diaCorrente,
                    $ultimoDia,
                    $diasRestantesMesCorrente,
                    $diaAnoAtualGlobal,
                    $diasRestantesAno,
                    (int)($feriadosData['qtd'] ?? 0),
                    (bool)$feriadoDiaUtil
                );

                $visaoConsolidadaEmpresas[] = [
                    'cdempresa' => $eid,
                    'dsempresa' => (string)($dadosEmp['dsempresa'] ?? ($mapNomeEmpresa[$eid] ?? ('Empresa ' . $eid))),
                    'modelos'   => montarVisaoConsolidadaPorModelo($kpisEmp),
                ];
            }
        }
    }

    // Payload comparativo: por MODELO/PERÍODO, lista empresas (para gráfico único por modelo)
    $dashboardConsolidadoComparativo = [];
    {
        $ordemModelosComparativo = ['meta', 'submeta', 'resultado', 'orcamento'];
        $periodosComparativo = ['mes', 'trimestre', 'ano'];

        foreach ($ordemModelosComparativo as $modeloComp) {
            foreach ($periodosComparativo as $periodoComp) {
                $empresasArr = [];
                $hasProj = false;

                foreach (($visaoConsolidadaEmpresas ?? []) as $empBucket) {
                    $eid = (int)($empBucket['cdempresa'] ?? 0);
                    if ($eid <= 0) continue;
                    $nomeEmp = (string)($empBucket['dsempresa'] ?? ('Empresa ' . $eid));

                    $mData = $empBucket['modelos'][$modeloComp][$periodoComp] ?? null;
                    if (!$mData) continue;

                    $totalReal = (float)($mData['total_real'] ?? 0);
                    $totalOrc  = (float)($mData['total_orc'] ?? 0);
                    $percTotal = (float)($mData['perc_total'] ?? 0);

                    $projTotal = null;
                    $vars = $mData['vars'] ?? [];
                    if (is_array($vars) && !empty($vars)) {
                        $sumProj = 0.0;
                        $temProj = false;
                        foreach ($vars as $v) {
                            if (array_key_exists('proj_valor', $v) && $v['proj_valor'] !== null) {
                                $sumProj += (float)$v['proj_valor'];
                                $temProj = true;
                            }
                        }
                        if ($temProj) {
                            $projTotal = $sumProj;
                            $hasProj = true;
                        }
                    }

                    $projPerc = null;
                    if ($projTotal !== null && $totalOrc != 0.0) {
                        $projPerc = ((float)$projTotal / (float)$totalOrc);
                    }

                    // Não incluir empresas sem qualquer valor (evita cards vazios como RESULTADO = 0)
                    if ($totalOrc == 0.0 && $totalReal == 0.0 && ($projTotal === null || $projTotal == 0.0)) {
                        continue;
                    }

                    $empresasArr[] = [
                        'cdempresa'  => $eid,
                        'dsempresa'  => $nomeEmp,
                        'total_real' => $totalReal,
                        'total_orc'  => $totalOrc,
                        'perc_total' => $percTotal,
                        'proj_total' => $projTotal,
                        'proj_perc'  => $projPerc,
                    ];
                }

                $dashboardConsolidadoComparativo[$modeloComp][$periodoComp] = [
                    'empresas' => $empresasArr,
                    'hasProj'  => $hasProj,
                ];
            }
        }
    }

    // Termômetro financeiro (somado entre empresas) para o modelo ORÇAMENTO
    $orcamentoTermometro = [];
    if ($visaoDashboard === 'modelo') {
        $orcVars = array_values(array_filter(($kpisVariaveis ?? []), function($kv) use ($modeloPorVariavel) {
            $id = (int)($kv['id'] ?? 0);
            $m = strtolower(trim((string)($modeloPorVariavel[$id] ?? ($kv['modelo'] ?? ''))));
            return $m === 'orcamento';
        }));

        $buildRanking = function(string $orcKey, string $realKey) use ($orcVars) {
            $items = [];
            foreach ($orcVars as $kv) {
                $orcV = (float)($kv[$orcKey] ?? 0.0);
                $realV = (float)($kv[$realKey] ?? 0.0);
                if ($orcV <= 0.0) continue;
                $items[] = [
                    'nome' => (string)($kv['nome'] ?? ''),
                    'perc' => ($realV / $orcV),
                ];
            }
            if (empty($items)) {
                return ['maior' => null, 'menor' => null];
            }
            usort($items, fn($a, $b) => ($b['perc'] <=> $a['perc']));
            return [
                'maior' => $items[0] ?? null,
                'menor' => $items[count($items) - 1] ?? null,
            ];
        };

        $sumBucket = function(string $periodo) use ($dashboardConsolidadoComparativo) {
            $empresas = $dashboardConsolidadoComparativo['orcamento'][$periodo]['empresas'] ?? [];
            $orc = 0.0;
            $real = 0.0;
            $hasProj = false;
            $projSum = 0.0;
            foreach ($empresas as $e) {
                $orc += (float)($e['total_orc'] ?? 0.0);
                $real += (float)($e['total_real'] ?? 0.0);
                if (array_key_exists('proj_total', $e) && $e['proj_total'] !== null) {
                    $projSum += (float)$e['proj_total'];
                    $hasProj = true;
                }
            }
            return [
                'orc' => $orc,
                'real' => $real,
                'proj' => $hasProj ? $projSum : null,
            ];
        };

        foreach (['mes', 'trimestre', 'ano'] as $p) {
            $tot = $sumBucket($p);
            $orc = (float)($tot['orc'] ?? 0.0);
            $real = (float)($tot['real'] ?? 0.0);
            $proj = $tot['proj'];
            $saldo = max(0.0, $orc - $real);
            $consumoPerc = ($orc != 0.0) ? ($real / $orc) : 0.0;
            $projPerc = ($proj !== null && $orc != 0.0) ? (((float)$proj) / $orc) : null;

            $rank = match ($p) {
                'mes' => $buildRanking('orcMes', 'realMes'),
                'trimestre' => $buildRanking('orcTrim', 'realTrim'),
                default => $buildRanking('orcAno', 'realAno'),
            };

            $orcamentoTermometro[$p] = [
                'orc' => $orc,
                'real' => $real,
                'saldo' => $saldo,
                'proj' => $proj,
                'consumoPerc' => $consumoPerc,
                'projPerc' => $projPerc,
                'ranking' => $rank,
            ];
        }
    }

    // ============================
    // PREPARAÇÃO DE DADOS PARA VISÃO PLANILHA
    // ============================
    $visaoPlanilhaEmpresas = [];
    $_planilhaModelosDisponiveis = [];
    if ($visaoDashboard === 'planilha') {
        // Mapa de nomes para fallback (usando lista original sem filtro de país/moeda)
        $mapNomeEmpresa = [];
        foreach ($empresasFiltroOriginal as $emp) {
            $eid = (int)($emp['cdempresa'] ?? 0);
            if ($eid <= 0) continue;
            $mapNomeEmpresa[$eid] = (string)($emp['dsapelido'] ?? $emp['dsempresa'] ?? ('Empresa ' . $eid));
        }

        // Na visão planilha, traz TODAS as empresas independente do país/moeda
        $empresasParaPlanilha = array_map(function($emp) {
            return (int)($emp['cdempresa'] ?? 0);
        }, $empresasFiltroOriginal);
        $empresasParaPlanilha = array_filter($empresasParaPlanilha, fn($id) => $id > 0);

        // Coletar todas as datas com dados para alinhar colunas
        $_planilhaTodasDatas = []; // será preenchido após o loop
        $_diasSemNomes = ['dom','seg','ter','qua','qui','sex','sab'];

        // Construir dados para cada empresa
        foreach ($empresasParaPlanilha as $eidRaw) {
            $eid = (int)$eidRaw;
            if ($eid <= 0) continue;

            $dadosEmp = obterDadosDashboard($pdo, 0, $cdcentrocustoFiltro, $anoFiltro, $trimestreFiltro, $mesesSelecionados, [$eid], $eid, 0);
            if (!($dadosEmp['ok'] ?? false)) {
                continue;
            }

            // Moeda da empresa
            $moedaEmp = $dadosEmp['moeda'] ?? ['simbolo' => 'R$', 'formato' => 'decimal'];

            $dashEmp = $dadosEmp['dashboards'] ?? [];
            $anorefEmp = (int)($dadosEmp['anoref'] ?? $anoref);
            $mesAtualEmp = (int)($dadosEmp['mesAtual'] ?? $mesAtual);

            // Montar KPIs
            $kpisEmp = montarKpisBasicosFromDashboards(
                $dashEmp, $mesAtualEmp, $anorefEmp, $mesesSelecionados,
                $mesCorrente, $anoCorrente, (int)$trimestreFiltro,
                $diaCorrente, $ultimoDia, $diasRestantesMesCorrente,
                $diaAnoAtualGlobal, $diasRestantesAno,
                (int)($feriadosData['qtd'] ?? 0), (bool)$feriadoDiaUtil
            );

            // Obter dados de últimos 7 dias para esta empresa
            // Extrair contas das fórmulas das seções (mesmo padrão do dashboard principal)
            $contasEmpresa = [];
            $contasPorVarEmp = [];
            foreach ($dashEmp as $d) {
                $cdvar = (int)($d['cdvariavel'] ?? 0);
                if ($cdvar <= 0) continue;
                $contasVar = [];
                foreach (($d['secoes'] ?? []) as $sec) {
                    if (!empty($sec['formula'])) {
                        preg_match_all('/\d+/', $sec['formula'], $m);
                        foreach ($m[0] as $cd) {
                            $contasVar[(int)$cd] = true;
                            $contasEmpresa[(int)$cd] = true;
                        }
                    }
                }
                if (!empty($contasVar)) {
                    $contasPorVarEmp[$cdvar] = array_keys($contasVar);
                }
            }
            $contasEmpresa = array_keys($contasEmpresa);
            $mapUlt7Emp = !empty($contasEmpresa) ? obterValoresContasUltimosDias($pdo, $eid, 7, $contasEmpresa) : [];

            // Origem dados para esta empresa (contas abertas/fechadas no dia atual)
            $origemHojeEmp = []; // cdvariavel => ['nome'=>..., 'valor'=>float]
            $varOrigemFlags = [];
            foreach ($dashEmp as $_dOrig) {
                $_cvOrig = (int)($_dOrig['cdvariavel'] ?? 0);
                if ($_cvOrig <= 0) continue;
                if (!empty($_dOrig['fl_agregar_calc']) && !empty($_dOrig['cdintegracao'])) {
                    $varOrigemFlags[$_cvOrig] = (int)$_dOrig['cdintegracao'];
                }
            }
            if (!empty($varOrigemFlags)) {
                $_integIds = array_unique(array_values($varOrigemFlags));
                $_phI = implode(',', array_fill(0, count($_integIds), '?'));
                // Nomes das integrações
                $_stN = $pdo->prepare("SELECT cdintegracao, dsintegracao FROM back.integracao WHERE cdintegracao IN ($_phI)");
                $_stN->execute(array_values($_integIds));
                $_nomesI = [];
                foreach ($_stN->fetchAll(PDO::FETCH_ASSOC) as $_ni) $_nomesI[(int)$_ni['cdintegracao']] = $_ni['dsintegracao'];
                // Valor de hoje por integração para esta empresa (desde 6h do dia útil até agora)
                $_hojeDate = $hojeStr6h;
                $_sqlOH = "WITH ultimo AS (
                    SELECT cdintegracao, valor,
                           ROW_NUMBER() OVER (PARTITION BY cdintegracao ORDER BY dtimportacao DESC) AS rn
                      FROM back.origem_dados
                     WHERE cdintegracao IN ($_phI)
                       AND cdempresa = ?
                       AND dtimportacao >= ?::date + interval '6 hours'
                ) SELECT cdintegracao,
                         COALESCE(SUM(CASE WHEN valor ~ '^-?[0-9]+(\\.[0-9]+)?$' THEN CAST(REPLACE(valor,',','.') AS NUMERIC) ELSE 0 END),0) AS total
                    FROM ultimo WHERE rn = 1 GROUP BY cdintegracao";
                $_parOH = array_merge(array_values($_integIds), [$eid, $_hojeDate]);
                $_stOH = $pdo->prepare($_sqlOH);
                $_stOH->execute($_parOH);
                $_valsInteg = [];
                foreach ($_stOH->fetchAll(PDO::FETCH_ASSOC) as $_ro) $_valsInteg[(int)$_ro['cdintegracao']] = (float)$_ro['total'];
                // Mapear para variáveis
                foreach ($varOrigemFlags as $_cvO => $_ciO) {
                    $origemHojeEmp[$_cvO] = [
                        'nome' => $_nomesI[$_ciO] ?? ('Origem #' . $_ciO),
                        'valor' => $_valsInteg[$_ciO] ?? 0.0,
                    ];
                }
            }

            // Origem dados POR EMPRESA para exibição na planilha (valor_raw)
            $origemPorVarEmp = [];
            $_varOrigemInfoFlags = [];
            foreach ($dashEmp as $_dOI) {
                $_cvOI = (int)($_dOI['cdvariavel'] ?? 0);
                if ($_cvOI <= 0) continue;
                if (!empty($_dOI['fl_origem']) && !empty($_dOI['cdintegracao']) && empty($_dOI['fl_agregar_calc'])) {
                    $_varOrigemInfoFlags[$_cvOI] = (int)$_dOI['cdintegracao'];
                }
            }
            if (!empty($_varOrigemInfoFlags)) {
                $_oiIntegIds = array_unique(array_values($_varOrigemInfoFlags));
                $_oiPh = implode(',', array_fill(0, count($_oiIntegIds), '?'));
                $_oiStN = $pdo->prepare("SELECT cdintegracao, dsintegracao FROM back.integracao WHERE cdintegracao IN ($_oiPh)");
                $_oiStN->execute(array_values($_oiIntegIds));
                $_oiNomes = [];
                foreach ($_oiStN->fetchAll(PDO::FETCH_ASSOC) as $_oiN) $_oiNomes[(int)$_oiN['cdintegracao']] = $_oiN['dsintegracao'];
                // Buscar valor_raw mais recente POR integração para ESTA empresa
                foreach ($_oiIntegIds as $_oiCdInteg) {
                    $_oiSqlRaw = "SELECT valor FROM back.origem_dados WHERE cdintegracao = ? AND cdempresa = ? ORDER BY dtimportacao DESC LIMIT 1";
                    $_oiStRaw = $pdo->prepare($_oiSqlRaw);
                    $_oiStRaw->execute([$_oiCdInteg, $eid]);
                    $_oiRawVal = $_oiStRaw->fetchColumn() ?: null;
                    $_oiData = ['dsintegracao' => $_oiNomes[$_oiCdInteg] ?? '', 'valor_raw' => $_oiRawVal];
                    foreach ($_varOrigemInfoFlags as $_oiCv => $_oiCi) {
                        if ($_oiCi === $_oiCdInteg) $origemPorVarEmp[$_oiCv] = $_oiData;
                    }
                }
            }

            // Todas as variáveis com dados completos
            $todasVarsEmp = [];
            foreach ($kpisEmp as $kpi) {
                $modelo = strtolower(trim((string)($kpi['modelo'] ?? 'meta')));
                $nomeVar = (string)($kpi['nome'] ?? 'Variável');
                $cdvar = (int)($kpi['id'] ?? 0);

                // Projeção % (proj/orc)
                $projMesPerc = (float)($kpi['projMesPerc'] ?? 0);
                $projTrimPerc = (float)($kpi['projTrimPerc'] ?? 0);
                $projAnoPerc = (float)($kpi['projAnoPerc'] ?? 0);

                // Últimos 7 dias para esta variável
                $diasHist = [];
                $contasVar = $contasPorVarEmp[$cdvar] ?? [];
                foreach ($contasVar as $conta) {
                    if (isset($mapUlt7Emp[$conta])) {
                        foreach ($mapUlt7Emp[$conta] as $dataStr => $valor) {
                            $diasHist[$dataStr] = ($diasHist[$dataStr] ?? 0.0) + $valor;
                        }
                    }
                }
                krsort($diasHist);
                $diasHist = array_slice($diasHist, 0, 7, true);

                // Agregar origem (contas abertas) no dia atual e guardar breakdown
                $_origemHojeVar = $origemHojeEmp[$cdvar] ?? null;
                $_hojeStrPlan = $hojeStr6h; // antes das 6h = dia anterior
                $_origemBreakdown = null;
                if ($_origemHojeVar && $_origemHojeVar['valor'] != 0) {
                    $_contasFechadas = (float)($diasHist[$_hojeStrPlan] ?? 0.0);
                    // Agregar no dia atual (criar entrada se não existir)
                    $diasHist[$_hojeStrPlan] = $_contasFechadas + $_origemHojeVar['valor'];
                    $_origemBreakdown = [
                        'f' => $_contasFechadas,
                        'a' => $_origemHojeVar['valor'],
                        'on' => $_origemHojeVar['nome'],
                    ];
                }

                $real7d = array_sum($diasHist);

                // Guardar diasHist bruto (será remapeado após definir datas finais)
                $orcMesVar = (float)($kpi['orcMes'] ?? 0);
                // Registrar datas com dados no pool global
                foreach ($diasHist as $_dt => $_vl) {
                    $_planilhaTodasDatas[$_dt] = true;
                }

                $todasVarsEmp[] = [
                    'nome' => $nomeVar,
                    'modelo' => $modelo,
                    'orcMes' => $orcMesVar,
                    'realMes' => (float)($kpi['realMes'] ?? 0),
                    'projMes' => (float)($kpi['projMesValor'] ?? 0),
                    'projMesPerc' => $projMesPerc,
                    'orcTrim' => (float)($kpi['orcTrim'] ?? 0),
                    'realTrim' => (float)($kpi['realTrim'] ?? 0),
                    'projTrim' => (float)($kpi['projTrimValor'] ?? 0),
                    'projTrimPerc' => $projTrimPerc,
                    'orcAno' => (float)($kpi['orcAno'] ?? 0),
                    'realAno' => (float)($kpi['realAno'] ?? 0),
                    'projAno' => (float)($kpi['projAnoValor'] ?? 0),
                    'projAnoPerc' => $projAnoPerc,
                    'real7d' => $real7d,
                    'diasHistorico' => $diasHist,
                    'orcMesVar' => $orcMesVar,
                    'origemBreakdown' => $_origemBreakdown,
                    'origemInfo' => (function() use ($cdvar, $kpi, $origemPorVarEmp, $mascaraPrincipal, $moeda) {
                        if (empty($kpi['fl_origem']) || empty($origemPorVarEmp[$cdvar]) || !empty($kpi['fl_agregar_calc'])) return null;
                        $_od = $origemPorVarEmp[$cdvar];
                        $_raw = $_od['valor_raw'];
                        if ($_raw === null) return null;
                        $_nome = $_od['dsintegracao'] ?? '';
                        if (preg_match('/^\d{4}-\d{2}-\d{2}/', trim($_raw))) {
                            $_dt = date_create(trim($_raw));
                            $_disp = $_dt ? $_dt->format('d/m/Y') : trim($_raw);
                        } elseif (preg_match('/^-?[0-9]+(\.[0-9]+)?$/', str_replace(',', '.', trim($_raw)))) {
                            $_disp = formatarValorDashboard((float)str_replace(',', '.', $_raw), $mascaraPrincipal, $moeda);
                        } else {
                            $_disp = trim($_raw);
                        }
                        return ['nome' => $_nome, 'valor' => $_disp];
                    })(),
                ];

                $_planilhaModelosDisponiveis[$modelo] = true;
            }

            if (!empty($todasVarsEmp)) {
                $visaoPlanilhaEmpresas[] = [
                    'cdempresa' => $eid,
                    'dsempresa' => (string)($dadosEmp['dsempresa'] ?? ($mapNomeEmpresa[$eid] ?? ('Empresa ' . $eid))),
                    'dsapelido' => (string)($mapNomeEmpresa[$eid] ?? $dadosEmp['dsempresa'] ?? ('Empresa ' . $eid)),
                    'moeda' => $moedaEmp,
                    'variaveis' => $todasVarsEmp,
                ];
            }
        }
    }

    // Definir datas finais para colunas de 7 dias (só datas com dados, mais recentes primeiro)
    if (!isset($_planilhaTodasDatas) || !is_array($_planilhaTodasDatas)) $_planilhaTodasDatas = [];
    krsort($_planilhaTodasDatas);
    $_planilha7Datas = array_slice(array_keys($_planilhaTodasDatas), 0, 7);
    $_planilha7Labels = [];
    if (!isset($_diasSemNomes)) $_diasSemNomes = ['dom','seg','ter','qua','qui','sex','sab'];
    foreach ($_planilha7Datas as $_dtStr) {
        $_dtObj = DateTime::createFromFormat('Y-m-d', $_dtStr);
        if ($_dtObj) {
            $_dow = (int)$_dtObj->format('w');
            $_planilha7Labels[] = $_diasSemNomes[$_dow] . ' ' . (int)$_dtObj->format('j') . '/' . str_pad((int)$_dtObj->format('n'), 2, '0', STR_PAD_LEFT);
        } else {
            $_planilha7Labels[] = $_dtStr;
        }
    }

    // Índice do dia atual no array de 7 dias (antes das 6h = dia anterior)
    $_hojeStrPlan7 = $hojeStr6h;
    $_hojeIdx7d = array_search($_hojeStrPlan7, $_planilha7Datas);
    if ($_hojeIdx7d === false) $_hojeIdx7d = -1;

    // Remapear diasDetalhado para cada variável usando as datas finais
    if (!isset($visaoPlanilhaEmpresas)) $visaoPlanilhaEmpresas = [];
    foreach ($visaoPlanilhaEmpresas as &$_empRef) {
        foreach ($_empRef['variaveis'] as &$_varRef) {
            $diasDetalhado = [];
            $_dh = $_varRef['diasHistorico'];
            $_om = $_varRef['orcMesVar'];
            $_obk = $_varRef['origemBreakdown'] ?? null;
            foreach ($_planilha7Datas as $_idxDia => $_dataFixa) {
                if (isset($_dh[$_dataFixa]) && $_dh[$_dataFixa] != 0) {
                    $_valDia = (float)$_dh[$_dataFixa];
                    $_dp = explode('-', $_dataFixa);
                    $_metaDia = calcularMetaDiaria($_om, (int)$_dp[2], (int)$_dp[1], (int)$_dp[0], $usarPesoDia);
                    $_percDia = ($_metaDia > 0) ? ($_valDia / $_metaDia) : 0;
                    $_deltaDia = max(0, 1 - $_percDia);
                    $_entry = [
                        'v' => $_valDia,
                        'p' => round($_percDia * 100, 1),
                        'd' => round($_deltaDia * 100, 1),
                        't' => 1,
                    ];
                    // Incluir breakdown de origem no dia atual
                    if ($_idxDia === $_hojeIdx7d && $_obk) {
                        $_entry['f']  = $_obk['f'];   // contas fechadas
                        $_entry['a']  = $_obk['a'];   // contas abertas (origem)
                        $_entry['on'] = $_obk['on'];  // nome da origem
                    }
                    $diasDetalhado[] = $_entry;
                } else {
                    $diasDetalhado[] = ['v' => 0, 'p' => 0, 'd' => 0, 't' => 0];
                }
            }
            $_varRef['diasDetalhado'] = $diasDetalhado;
            unset($_varRef['diasHistorico'], $_varRef['orcMesVar'], $_varRef['origemBreakdown']);
        }
        unset($_varRef);
    }
    unset($_empRef);

    // Ordem de prioridade para modelos
    $_ordemModelos = ['meta' => 0, 'submeta' => 1, 'resultado' => 2, 'orcamento' => 3];
    $_planilhaModelosOrdenados = [];
    if (!isset($_planilhaModelosDisponiveis)) $_planilhaModelosDisponiveis = [];
    foreach ($_ordemModelos as $m => $ord) {
        if (isset($_planilhaModelosDisponiveis[$m])) $_planilhaModelosOrdenados[] = $m;
    }


if ($isWarm) {
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode(['ok' => true]);
    return;
}

?>

<!-- Alerta de Filtros Aplicados -->
<?php if ($filtrosAplicados): ?>
    <div class="alert alert-info alert-dismissible fade show mb-3 py-2 px-3" role="alert">
        <small class="d-block d-md-inline">
            📅 <strong><?= htmlspecialchars((string)$anoFiltro) ?></strong> |
            🗓️ <strong><?= htmlspecialchars((string)$nomeMesAtual) ?></strong> |
            🌍 <strong><?= htmlspecialchars($paisNome) ?></strong> |
            💱 <strong><?= htmlspecialchars($moedaNome) ?></strong> |
            🏢 <strong><?= htmlspecialchars(count($empresasNomes) > 0 ? implode(', ', $empresasNomes) : 'Nenhuma') ?></strong> |
            📍 <strong><?= htmlspecialchars($centroCustoNome) ?></strong> |
            📊 <strong><?= htmlspecialchars($trimestreNome) ?></strong>
        </small>
        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
    </div>
    
    <!-- DEBUG: Mostrar dados do filtro -->
    <?php if (isset($_GET['debug_filtros']) && $_GET['debug_filtros'] === '1'): ?>
        <div class="alert alert-warning mb-3 p-3" style="font-family: monospace; font-size: 11px; line-height: 1.6;">
            <strong style="font-size: 13px; display: block; margin-bottom: 10px;">🔍 DEBUG - FILTROS</strong>
            
            <table style="width: 100%; border-collapse: collapse;">
                <tr>
                    <td style="border: 1px solid #ddd; padding: 5px;"><strong>Parâmetro</strong></td>
                    <td style="border: 1px solid #ddd; padding: 5px;"><strong>Valor</strong></td>
                </tr>
                <tr>
                    <td style="border: 1px solid #ddd; padding: 5px;">filtrosAplicados</td>
                    <td style="border: 1px solid #ddd; padding: 5px;"><?= $filtrosAplicados ? '✅ SIM' : '❌ NÃO' ?></td>
                </tr>
                <tr>
                    <td style="border: 1px solid #ddd; padding: 5px;">GET[cdempresa]</td>
                    <td style="border: 1px solid #ddd; padding: 5px;"><code><?= json_encode($_GET['cdempresa'] ?? null) ?></code></td>
                </tr>
                <tr>
                    <td style="border: 1px solid #ddd; padding: 5px;">SESSION[cdempresa]</td>
                    <td style="border: 1px solid #ddd; padding: 5px;"><code><?= json_encode($_SESSION['filtros_dashboard']['cdempresa'] ?? null) ?></code></td>
                </tr>
                <tr>
                    <td style="border: 1px solid #ddd; padding: 5px;">empresasSelecionadas</td>
                    <td style="border: 1px solid #ddd; padding: 5px;"><code><?= json_encode($empresasSelecionadas) ?></code></td>
                </tr>
                <tr>
                    <td style="border: 1px solid #ddd; padding: 5px;">empresaParaDados</td>
                    <td style="border: 1px solid #ddd; padding: 5px;"><code><?= json_encode($empresaParaDados ?? []) ?></code></td>
                </tr>
                <tr>
                    <td style="border: 1px solid #ddd; padding: 5px;">cdcentrocustoFiltro</td>
                    <td style="border: 1px solid #ddd; padding: 5px;"><code><?= (int)$cdcentrocustoFiltro ?></code></td>
                </tr>
                <tr>
                    <td style="border: 1px solid #ddd; padding: 5px;">anoFiltro</td>
                    <td style="border: 1px solid #ddd; padding: 5px;"><code><?= (int)$anoFiltro ?></code></td>
                </tr>
                <tr>
                    <td style="border: 1px solid #ddd; padding: 5px;">mesFiltro</td>
                    <td style="border: 1px solid #ddd; padding: 5px;"><code><?= json_encode($mesesSelecionados ?? []) ?></code></td>
                </tr>
                <tr>
                    <td style="border: 1px solid #ddd; padding: 5px;">trimestreFiltro</td>
                    <td style="border: 1px solid #ddd; padding: 5px;"><code><?= (int)$trimestreFiltro ?></code></td>
                </tr>
                <tr>
                    <td style="border: 1px solid #ddd; padding: 5px;">cdpaisFiltro</td>
                    <td style="border: 1px solid #ddd; padding: 5px;"><code><?= (int)$cdpaisFiltro ?></code></td>
                </tr>
            </table>
            
            <div style="margin-top: 10px; border-top: 1px solid #ddd; padding-top: 10px;">
                <strong>📋 Empresas Acessíveis:</strong>
                <br><code><?= json_encode(array_map(fn($e) => ['id' => (int)$e['cdempresa'], 'nome' => $e['dsapelido']], $empresasFiltro)) ?></code>
            </div>
        </div>
    <?php endif; ?>
<?php endif; ?>


<!-- Mobile: barra compacta (data sync + filtro) -->
<?php
    $_syncDt = null; $_syncFormatada = ''; $_syncRecente = true;
    if ($ultimaSincronizacao) {
        $_syncDt = new DateTime($ultimaSincronizacao);
        $_syncFormatada = $_syncDt->format('d/m/Y H:i:s');
        $_syncRecente = ((time() - $_syncDt->getTimestamp()) / 3600) <= 24;
    }
?>

<?php
// ========== BARRA FIXA: LETREIRO + PREVISÃO DO TEMPO ==========
$_tickerItems = [];

// Feriados restantes no mês
if ($qtdFeriadosRestantes > 0) {
    foreach ($feriadosRestantes as $_fer) {
        $_ferParts = explode('/', $_fer['data']);
        $_ferDia = (int)$_ferParts[0];
        $_ferDow = date('D', mktime(0,0,0, $mesCorrente, $_ferDia, $anoCorrente));
        $_dowPt = ['Mon'=>'Seg','Tue'=>'Ter','Wed'=>'Qua','Thu'=>'Qui','Fri'=>'Sex','Sat'=>'Sáb','Sun'=>'Dom'];
        $_ferDowPt = $_dowPt[$_ferDow] ?? $_ferDow;
        $_tickerItems[] = '<i class="bi bi-calendar-event text-danger"></i> '
            . htmlspecialchars($_fer['desc']) . ' — '
            . str_pad($_ferDia, 2, '0', STR_PAD_LEFT) . '/' . str_pad($mesCorrente, 2, '0', STR_PAD_LEFT)
            . ' (' . $_ferDowPt . ')';
    }
} else {
    $_tickerItems[] = '<i class="bi bi-calendar-check text-success"></i> Nenhum feriado restante no mês';
}

if ($finsSemanaRestantes > 0) {
    $_tickerItems[] = '<i class="bi bi-calendar2-week text-primary"></i> '
        . $finsSemanaRestantes . ' fim(ns) de semana restante(s) em '
        . ['','Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'][$mesCorrente];
} else {
    $_tickerItems[] = '<i class="bi bi-calendar2-week text-muted"></i> Nenhum fim de semana restante no mês';
}

$_diasUteisRest = 0;
for ($_du = $diaCorrente; $_du <= $ultimoDia; $_du++) {
    $_duW = (int)date('w', mktime(0,0,0, $mesCorrente, $_du, $anoCorrente));
    if ($_duW !== 0 && $_duW !== 6) $_diasUteisRest++;
}
$_diasUteisRest = max(0, $_diasUteisRest - $qtdFeriadosRestantes);
if (!$feriadoDiaUtil) {
    $_tickerItems[] = '<i class="bi bi-briefcase text-secondary"></i> '
        . $_diasUteisRest . ' dia(s) útil(eis) restante(s) no mês';
}

$_tickerItems[] = '<i class="bi bi-hourglass-split text-warning"></i> '
    . $diasRestantesMesCorrente . ' dia(s) para fechar '
    . ['','Janeiro','Fevereiro','Março','Abril','Maio','Junho','Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'][$mesCorrente];

$_tickerJson = json_encode($_tickerItems, JSON_UNESCAPED_UNICODE);
?>

<div class="dash-sticky-top" id="dashStickyTop">
  <div class="dash-sticky-inner">
    <!-- Linha 1: Previsão do tempo 7 dias -->
    <div class="dash-weather-bar" id="dashWeatherBar">
        <div class="dw-city-row" id="dwCityRow"></div>
        <div class="dash-weather-inner" id="dashWeatherInner"></div>
    </div>
    <!-- Linha 2: Letreiro ticker -->
    <div class="dash-ticker-row">
        <div class="dash-ticker-track" id="dashTickerTrack"></div>
    </div>
  </div>
</div>

<style>
/* ===== BARRA STICKY TOPO ===== */
.dash-sticky-top {
    position: sticky;
    top: 0;
    z-index: 100;
    background: #f8fafc;
    margin: -0.75rem -0.75rem 0.5rem -0.75rem;
    padding: 0;
}
@media (min-width: 769px) {
    .dash-sticky-top {
        margin: -1rem -1rem 0.6rem -1rem;
        padding: 6px 10px 4px;
    }
}
.dash-sticky-inner {
    border: 1px solid #e2e8f0;
    border-radius: 10px;
    overflow: hidden;
    box-shadow: 0 1px 4px rgba(0,0,0,0.05);
}
@media (max-width: 768px) {
    .dash-sticky-inner { border-radius: 0; border-left: 0; border-right: 0; }
}

/* Previsão do tempo */
.dash-weather-bar {
    display: none;
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
    background: linear-gradient(90deg, #f0f7ff 0%, #e8f4fd 50%, #f0f7ff 100%);
    padding: 0;
}
.dash-weather-bar::-webkit-scrollbar { display: none; }
.dash-weather-bar.visible { display: block; }
.dw-city-row {
    padding: 5px 12px 0;
    font-size: 0.78rem;
    font-weight: 700;
    color: #1e3a5f;
    display: flex;
    align-items: center;
    gap: 6px;
}
.dw-city-row .dw-city-sub {
    font-weight: 400;
    font-size: 0.68rem;
    color: #64748b;
}
@media (max-width: 768px) {
    .dw-city-row { font-size: 0.62rem; padding: 3px 8px 0; }
    .dw-city-row .dw-city-sub { font-size: 0.55rem; }
}
.dash-weather-inner {
    display: flex;
    align-items: stretch;
    justify-content: center;
    gap: 6px;
    min-width: max-content;
    padding: 5px 10px 6px;
}
@media (max-width: 768px) {
    .dash-weather-inner { justify-content: flex-start; gap: 4px; }
}
.dash-weather-day {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex-shrink: 0;
    padding: 4px 10px;
    line-height: 1.2;
    border-radius: 8px;
    background: rgba(255,255,255,0.6);
    min-width: 58px;
}
.dash-weather-day + .dash-weather-day { border-left: none; }
.dash-weather-day.today {
    background: rgba(59,130,246,0.1);
    font-weight: 600;
}
.dw-label { font-size: 0.68rem; text-transform: uppercase; color: #64748b; letter-spacing: 0.3px; margin-bottom: 1px; }
.dw-ico { font-size: 1.1rem; line-height: 1; margin: 2px 0; }
.dw-desc { font-size: 0.62rem; color: #1e3a5f; font-weight: 600; white-space: nowrap; }
.dw-temp { font-size: 0.72rem; color: #334155; white-space: nowrap; }
.dw-temp .dw-lo { color: #64748b; }
.dw-rain { font-size: 0.58rem; color: #3b82f6; white-space: nowrap; }
.dw-rain i { font-size: 0.52rem; }
@media (max-width: 768px) {
    .dash-weather-day { padding: 2px 5px; min-width: 46px; border-radius: 6px; }
    .dw-label { font-size: 0.5rem; }
    .dw-ico { font-size: 0.7rem; }
    .dw-desc { font-size: 0.48rem; }
    .dw-temp { font-size: 0.52rem; }
    .dw-rain { font-size: 0.46rem; }
}

/* Letreiro ticker */
.dash-ticker-row {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.4rem 1.5rem;
    padding: 5px 12px;
    font-size: 0.85rem;
    color: #475569;
    background: linear-gradient(90deg, #f8fafc 0%, #f1f5f9 50%, #f8fafc 100%);
    min-height: 28px;
    border-top: 1px solid #e2e8f0;
}
@media (max-width: 768px) {
    .dash-ticker-row {
        overflow: hidden;
        flex-wrap: nowrap;
        justify-content: flex-start;
        height: 20px;
        min-height: 20px;
        font-size: 0.63rem;
        padding: 0;
    }
}
.dash-ticker-track {
    display: flex;
    white-space: nowrap;
    gap: 1.5rem;
    align-items: center;
    flex-wrap: wrap;
    justify-content: center;
}
@media (max-width: 768px) {
    .dash-ticker-track {
        flex-wrap: nowrap;
        justify-content: flex-start;
        animation: tickerScroll var(--ticker-dur, 120s) linear infinite;
        gap: 0.8rem;
        padding-left: 100%;
    }
    .dash-ticker-track:hover { animation-play-state: paused; }
}
.dash-ticker-item {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex-shrink: 0;
    letter-spacing: 0.1px;
}
.dash-ticker-item i { font-size: 0.8rem; }
@media (max-width: 768px) {
    .dash-ticker-item i { font-size: 0.6rem; }
}
.dash-ticker-sep { color: #cbd5e1; flex-shrink: 0; user-select: none; }
@keyframes tickerScroll {
    0%   { transform: translateX(0); }
    100% { transform: translateX(calc(-100% - 100vw)); }
}
</style>

<script>
(function() {
    // Ticker
    var items = <?= $_tickerJson ?>;
    var track = document.getElementById('dashTickerTrack');
    if (track && items.length) {
        var isMobile = window.innerWidth <= 768;
        var html = '';
        var reps = isMobile ? 4 : 1;
        for (var i = 0; i < reps; i++) {
            items.forEach(function(item, idx) {
                if (i > 0 || idx > 0) html += '<span class="dash-ticker-sep">·</span>';
                html += '<span class="dash-ticker-item">' + item + '</span>';
            });
        }
        track.innerHTML = html;
        if (isMobile) {
            var dur = Math.max(80, items.length * 25);
            track.style.setProperty('--ticker-dur', dur + 's');
        }
    }

    // Weather
    var bar = document.getElementById('dashWeatherBar');
    var inner = document.getElementById('dashWeatherInner');
    if (!bar || !inner) return;
    var dias = ['Dom','Seg','Ter','Qua','Qui','Sex','S\u00e1b'];

    function wIcon(c) {
        if (c <= 1) return '\u2600\ufe0f';
        if (c <= 3) return '\u26c5';
        if (c <= 48) return '\ud83c\udf2b\ufe0f';
        if (c <= 55) return '\ud83c\udf26\ufe0f';
        if (c <= 67) return '\ud83c\udf27\ufe0f';
        if (c <= 77) return '\u2744\ufe0f';
        if (c <= 82) return '\ud83c\udf27\ufe0f';
        if (c <= 86) return '\ud83c\udf28\ufe0f';
        return '\u26c8\ufe0f';
    }
    function wDesc(c) {
        if (c === 0) return 'Limpo';
        if (c <= 2) return 'Parcial';
        if (c === 3) return 'Nublado';
        if (c <= 48) return 'N\u00e9voa';
        if (c <= 55) return 'Chuvisco';
        if (c <= 57) return 'Chuvisco';
        if (c <= 65) return 'Chuva';
        if (c <= 67) return 'Chuva';
        if (c <= 75) return 'Neve';
        if (c <= 77) return 'Granizo';
        if (c <= 82) return 'Pancada';
        if (c <= 86) return 'Neve';
        return 'Tempest.';
    }

    var cityRow = document.getElementById('dwCityRow');
    var _wCityName = '';

    function render(d) {
        if (!d || !d.daily || !d.daily.time) return;
        var h = '';
        var n = Math.min(7, d.daily.time.length);
        var pp = d.daily.precipitation_probability_max || [];
        for (var i = 0; i < n; i++) {
            var dt = new Date(d.daily.time[i] + 'T12:00:00');
            var dow = dias[dt.getDay()];
            var dd = dt.getDate();
            var mn = Math.round(d.daily.temperature_2m_min[i]);
            var mx = Math.round(d.daily.temperature_2m_max[i]);
            var wc = d.daily.weather_code[i];
            var ic = wIcon(wc);
            var ds = wDesc(wc);
            var rain = (pp[i] !== undefined && pp[i] !== null) ? pp[i] : null;
            var isToday = (i === 0) ? ' today' : '';
            var lbl = (i === 0) ? 'Hoje' : dow + '.';
            h += '<div class="dash-weather-day' + isToday + '">'
                + '<span class="dw-label">' + lbl + '</span>'
                + '<span class="dw-ico">' + ic + '</span>'
                + '<span class="dw-desc">' + ds + '</span>'
                + '<span class="dw-temp">' + mx + '\u00b0 <span class="dw-lo">' + mn + '\u00b0</span></span>'
                + (rain !== null ? '<span class="dw-rain"><i class="bi bi-droplet-fill"></i> ' + rain + '%</span>' : '')
                + '</div>';
        }
        if (d.current) {
            var ct = Math.round(d.current.temperature_2m);
            var cwc = d.current.weather_code;
            var ci = wIcon(cwc);
            var cd = wDesc(cwc);
            h = '<div class="dash-weather-day today" style="min-width:64px;">'
                + '<span class="dw-label">Agora</span>'
                + '<span class="dw-ico">' + ci + '</span>'
                + '<span class="dw-desc">' + cd + '</span>'
                + '<span class="dw-temp" style="font-weight:700;">' + ct + '\u00b0</span>'
                + '</div>' + h;
        }
        inner.innerHTML = h;
        if (cityRow && _wCityName) {
            cityRow.innerHTML = _wCityName + ' <span class="dw-city-sub">\u00b7 Pr\u00f3ximos 7 dias</span>';
        }
        bar.classList.add('visible');
    }

    function fetchW(lat, lon, cityName) {
        _wCityName = cityName || '';
        var url = 'https://api.open-meteo.com/v1/forecast?latitude=' + lat + '&longitude=' + lon
            + '&current=temperature_2m,weather_code'
            + '&daily=temperature_2m_max,temperature_2m_min,weather_code,precipitation_probability_max'
            + '&timezone=America%2FSao_Paulo&forecast_days=7';
        fetch(url).then(function(r){ return r.json(); }).then(render).catch(function(){});
    }

    function reverseGeo(lat, lon, cb) {
        fetch('https://nominatim.openstreetmap.org/reverse?lat=' + lat + '&lon=' + lon + '&format=json&zoom=10&accept-language=pt')
            .then(function(r){ return r.json(); })
            .then(function(d) {
                var city = (d.address && (d.address.city || d.address.town || d.address.municipality)) || '';
                cb(city);
            }).catch(function(){ cb(''); });
    }

    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function(pos) {
            var lt = pos.coords.latitude.toFixed(4);
            var ln = pos.coords.longitude.toFixed(4);
            reverseGeo(lt, ln, function(city) { fetchW(lt, ln, city); });
        }, function() {
            fetchW('-25.5163', '-54.5854', 'Foz do Igua\u00e7u');
        }, { timeout: 5000 });
    } else {
        fetchW('-25.5163', '-54.5854', 'Foz do Igua\u00e7u');
    }
})();
</script>

<div class="d-flex d-md-none align-items-center justify-content-between mb-1" style="gap: 0.5rem;">
    <?php if ($_syncDt): ?>
    <small class="d-flex align-items-center gap-1 <?= $_syncRecente ? 'text-success' : 'text-danger' ?>" style="font-size: 0.72rem;">
        <i class="bi bi-arrow-repeat"></i>
        <?= htmlspecialchars($_syncFormatada) ?>
    </small>
    <?php else: ?><span></span><?php endif; ?>
    <button class="btn btn-sm btn-outline-secondary d-flex align-items-center gap-1"
            type="button" data-bs-toggle="collapse" data-bs-target="#filtrosCollapseMobile"
            aria-expanded="false" style="font-size: 0.75rem; padding: 0.2rem 0.5rem;">
        <i class="bi bi-funnel" style="font-size: 0.75rem;"></i>
    </button>
</div>

<!-- Desktop: cabeçalho completo -->
<div class="d-none d-md-flex align-items-start justify-content-between mb-2 gap-2 flex-wrap">
    <div class="mb-0" style="min-width: 0;">
        <h4 class="d-flex align-items-center gap-2 mb-0">
            <i class="bi bi-speedometer2"></i>
            <span>Dashboard</span>
        </h4>
        <small class="text-muted d-block text-truncate" style="max-width: 100%; font-size: 0.85rem;">
            <?= htmlspecialchars($dsempresa) ?> (<?= (int)$cdempresa ?>) · Ano <?= htmlspecialchars((string)$anoref) ?>
        </small>
    </div>
    
    <div class="d-flex align-items-center gap-2 flex-shrink-0">
        <!-- Botão toggle filtros (desktop) -->
        <button class="btn btn-outline-secondary btn-sm d-inline-flex align-items-center gap-1"
                type="button" data-bs-toggle="collapse" data-bs-target="#filtrosCollapseDesktop"
                aria-expanded="false" aria-controls="filtrosCollapseDesktop"
                id="btnToggleFiltrosDesktop" title="Exibir/ocultar filtros">
            <i class="bi bi-funnel"></i>
            <span style="font-size: 0.8rem;">Filtros</span>
            <i class="bi bi-chevron-down" id="filtrosChevronDesktop" style="font-size: 0.65rem; transition: transform 0.3s;"></i>
        </button>

        <!-- Última sincronização (discreta) -->
        <?php if ($_syncDt): ?>
            <small class="d-flex align-items-center gap-1 px-2 py-1 border rounded <?= $_syncRecente ? 'border-success' : 'border-danger' ?>" style="font-size: 0.85rem;">
                <i class="bi bi-arrow-repeat <?= $_syncRecente ? 'text-success' : 'text-danger' ?>" style="font-size: 0.85rem;"></i>
                <span class="<?= $_syncRecente ? 'text-success' : 'text-danger' ?>">
                    <?= htmlspecialchars($_syncFormatada) ?>
                </span>
            </small>
        <?php endif; ?>
    </div>
</div>

<!-- Desktop: Filtros recolhíveis (fechado por padrão) -->
<div class="d-none d-md-block mb-4">
    <div class="collapse" id="filtrosCollapseDesktop">
        <div class="card border-0 shadow-sm">
            <div class="card-body">
                <form method="GET" id="filtrosFormDesktop" class="row g-2 align-items-end">
            <!-- Ano -->
            <div class="col-md-1">
                <label for="filtroAnoDesktop" class="form-label fw-semibold" style="font-size: 0.75rem;">📅 Ano</label>
                <select class="form-select form-select-sm" id="filtroAnoDesktop" name="ano">
                    <?php foreach ($anosFiltro as $ano): ?>
                        <option value="<?= (int)$ano['anoref'] ?>" <?= ((int)$ano['anoref'] === $anoFiltro) ? 'selected' : '' ?>>
                            <?= (int)$ano['anoref'] ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </div>

            <!-- Mês (Multi-select) -->
            <div class="col-md-2">
                <label class="form-label fw-semibold" style="font-size: 0.75rem;">🗓️ Mês</label>
                <div class="dropdown" data-bs-auto-close="outside">
                    <button class="btn btn-outline-secondary btn-sm w-100 text-start d-flex justify-content-between align-items-center" type="button" data-bs-toggle="dropdown" aria-expanded="false">
                        <span id="mesesLabelDesktop" style="font-size: 0.8rem;">Selecione</span>
                        <i class="bi bi-chevron-down" style="font-size: 0.8rem;"></i>
                    </button>
                    <ul class="dropdown-menu w-100" style="max-height: 250px; overflow-y: auto;">
                        <li>
                            <div class="dropdown-item">
                                <div class="form-check">
                                    <input class="form-check-input" type="checkbox" id="selecionarTodosMesesDesktop" onchange="toggleTodosMeses()" />
                                    <label class="form-check-label" for="selecionarTodosMesesDesktop">
                                        <small class="fw-bold">Selecionar Todos</small>
                                    </label>
                                </div>
                            </div>
                        </li>
                        <li><hr class="dropdown-divider"></li>
                        <?php $mesesNomes = ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez']; ?>
                        <?php foreach ($mesesNomes as $idx => $nomeMes): ?>
                            <?php $mesNum = $idx + 1; ?>
                            <li>
                                <div class="dropdown-item">
                                    <div class="form-check">
                                        <input class="form-check-input mes-checkbox" type="checkbox"
                                            id="mesDesktop_<?= (int)$mesNum ?>"
                                            name="mes[]"
                                            value="<?= (int)$mesNum ?>"
                                            onchange="atualizarLabelMeses()"
                                            <?= in_array((int)$mesNum, $mesesSelecionados, true) ? 'checked' : '' ?> />
                                        <label class="form-check-label" for="mesDesktop_<?= (int)$mesNum ?>">
                                            <small><?= htmlspecialchars((string)$nomeMes) ?></small>
                                        </label>
                                    </div>
                                </div>
                            </li>
                        <?php endforeach; ?>
                    </ul>
                </div>
            </div>
            
            <!-- País -->
            <div class="col-md-1">
                <label for="filtroPaisDesktop" class="form-label fw-semibold" style="font-size: 0.75rem;">🌍 País</label>
                <select class="form-select form-select-sm" id="filtroPaisDesktop" name="cdpais">
                    <option value="0">Todos</option>
                    <?php foreach ($paisesFiltro as $pais): ?>
                        <option value="<?= (int)$pais['cdpais'] ?>" <?= ((int)$pais['cdpais'] === $cdpaisFiltro) ? 'selected' : '' ?>>
                            <?= htmlspecialchars((string)$pais['dspais']) ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </div>

            <!-- Moeda -->
            <div class="col-md-1">
                <label for="filtroMoedaDesktop" class="form-label fw-semibold" style="font-size: 0.75rem;">💱 Moeda</label>
                <select class="form-select form-select-sm" id="filtroMoedaDesktop" name="cdmoeda">
                    <?php foreach ($moedasFiltro as $m): ?>
                        <option value="<?= (int)$m['cdmoeda'] ?>" <?= ((int)$m['cdmoeda'] === $cdmoedaFiltro) ? 'selected' : '' ?>>
                            <?= htmlspecialchars((string)($m['simbolo'] ?? '')) ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </div>

            <!-- Empresas (Multi-select com checkboxes em dropdown) -->
            <div class="col-md-2">
                <label class="form-label fw-semibold" style="font-size: 0.75rem;">🏢 Empresas</label>
                <div class="dropdown" data-bs-auto-close="outside">
                    <button class="btn btn-outline-secondary btn-sm w-100 text-start d-flex justify-content-between align-items-center" type="button" data-bs-toggle="dropdown" aria-expanded="false">
                        <span id="empresasLabelDesktop" style="font-size: 0.8rem;">Nenhuma</span>
                        <i class="bi bi-chevron-down" style="font-size: 0.8rem;"></i>
                    </button>
                    <ul class="dropdown-menu w-100" style="max-height: 250px; overflow-y: auto;">
                        <!-- Selecionar Todas -->
                        <li>
                            <div class="dropdown-item">
                                <div class="form-check">
                                    <input class="form-check-input" type="checkbox" id="selecionarTodasDesktop" 
                                        onchange="toggleTodasEmpresas()" />
                                    <label class="form-check-label" for="selecionarTodasDesktop">
                                        <small class="fw-bold">Selecionar Todas</small>
                                    </label>
                                </div>
                            </div>
                        </li>
                        <li><hr class="dropdown-divider"></li>
                        <!-- Checkboxes de empresas -->
                        <?php foreach ($empresasFiltro as $emp): ?>
                            <li>
                                <div class="dropdown-item">
                                    <div class="form-check">
                                        <input class="form-check-input empresa-checkbox" type="checkbox" 
                                            id="empresaDesktop_<?= (int)$emp['cdempresa'] ?>" 
                                            name="cdempresa[]" 
                                            value="<?= (int)$emp['cdempresa'] ?>"
                                            onchange="atualizarLabelEmpresas()"
                                            <?= in_array((int)$emp['cdempresa'], $empresasSelecionadas) ? 'checked' : '' ?> />
                                        <label class="form-check-label" for="empresaDesktop_<?= (int)$emp['cdempresa'] ?>">
                                            <small><?= htmlspecialchars((string)$emp['dsapelido']) ?></small>
                                        </label>
                                    </div>
                                </div>
                            </li>
                        <?php endforeach; ?>
                    </ul>
                </div>
            </div>

            <!-- Centro de Custo -->
            <div class="col-md-2">
                <label for="filtroCentroCustoDesktop" class="form-label fw-semibold" style="font-size: 0.75rem;">📍 Centro</label>
                <select class="form-select form-select-sm" id="filtroCentroCustoDesktop" name="cdcentrocusto">
                    <option value="0">Todos</option>
                    <?php foreach ($centrosCustoFiltro as $cc): ?>
                        <option value="<?= (int)$cc['cdcentrocusto'] ?>" <?= ((int)$cc['cdcentrocusto'] === $cdcentrocustoFiltro) ? 'selected' : '' ?>>
                            <?= htmlspecialchars((string)$cc['dscentro']) ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </div>

            <!-- Trimestre -->
            <div class="col-md-1">
                <label for="filtroTrimestreDesktop" class="form-label fw-semibold" style="font-size: 0.75rem;">📊 Trim.</label>
                <select class="form-select form-select-sm" id="filtroTrimestreDesktop" name="trimestre">
                    <option value="0" <?= ($trimestreFiltro === 0) ? 'selected' : '' ?>>Todos</option>
                    <?php foreach ($trimestresFiltro as $trim): ?>
                        <option value="<?= (int)$trim['numero'] ?>" <?= ((int)$trim['numero'] === $trimestreFiltro) ? 'selected' : '' ?>>
                            <?= htmlspecialchars((string)$trim['descricao']) ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </div>
            
            <!-- Botões (direita, discretos) -->
            <div class="col-md-2 d-flex gap-2">
                <button type="button" class="btn btn-outline-secondary btn-sm flex-grow-1" onclick="limparFiltros()" title="Limpar filtros">
                    <i class="bi bi-arrow-clockwise"></i>
                </button>
                <button type="button" class="btn btn-outline-primary btn-sm flex-grow-1" onclick="aplicarFiltros()" title="Aplicar filtros">
                    <i class="bi bi-search"></i>
                </button>
            </div>
        </form>
            </div>
        </div>
    </div>
</div>
<!-- Mobile: Filtros recolhíveis (sem card header, acionado pelo botão acima) -->
<div class="d-md-none mb-3">
    <div id="filtrosCollapseMobile" class="collapse">
    <div class="card border-0 shadow-sm">
        <div class="card-body">
            <form method="GET" id="filtrosForm" class="row g-3">
                <!-- Ano -->
                <div class="col-12">
                    <label for="filtroAno" class="form-label fw-semibold">Ano</label>
                    <select class="form-select form-select-sm" id="filtroAno" name="ano">
                        <?php foreach ($anosFiltro as $ano): ?>
                            <option value="<?= (int)$ano['anoref'] ?>" <?= ((int)$ano['anoref'] === $anoFiltro) ? 'selected' : '' ?>>
                                <?= (int)$ano['anoref'] ?>
                            </option>
                        <?php endforeach; ?>
                    </select>
                </div>

                <!-- Mês (Multi-select) -->
                <div class="col-12">
                    <label class="form-label fw-semibold">Mês</label>
                    <div class="border rounded p-2" style="max-height: 180px; overflow-y: auto;">
                        <div class="form-check mb-1">
                            <input class="form-check-input" type="checkbox" id="selecionarTodosMeses" onchange="toggleTodosMeses()" />
                            <label class="form-check-label" for="selecionarTodosMeses">
                                <small class="fw-bold">Selecionar Todos</small>
                            </label>
                        </div>
                        <hr class="my-1" />
                        <?php $mesesNomes = ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez']; ?>
                        <?php foreach ($mesesNomes as $idx => $nomeMes): ?>
                            <?php $mesNum = $idx + 1; ?>
                            <div class="form-check mb-1">
                                <input class="form-check-input mes-checkbox" type="checkbox"
                                    id="mes_<?= (int)$mesNum ?>"
                                    name="mes[]"
                                    value="<?= (int)$mesNum ?>"
                                    <?= in_array((int)$mesNum, $mesesSelecionados, true) ? 'checked' : '' ?> />
                                <label class="form-check-label" for="mes_<?= (int)$mesNum ?>">
                                    <small><?= htmlspecialchars((string)$nomeMes) ?></small>
                                </label>
                            </div>
                        <?php endforeach; ?>
                    </div>
                </div>
                
                <!-- País -->
                <div class="col-12">
                    <label for="filtroPais" class="form-label fw-semibold">País</label>
                    <select class="form-select form-select-sm" id="filtroPais" name="cdpais">
                        <option value="0">Todos</option>
                        <?php foreach ($paisesFiltro as $pais): ?>
                            <option value="<?= (int)$pais['cdpais'] ?>" <?= ((int)$pais['cdpais'] === $cdpaisFiltro) ? 'selected' : '' ?>>
                                <?= htmlspecialchars((string)$pais['dspais']) ?>
                            </option>
                        <?php endforeach; ?>
                    </select>
                </div>

                <!-- Moeda -->
                <div class="col-12">
                    <label for="filtroMoeda" class="form-label fw-semibold">Moeda</label>
                    <select class="form-select form-select-sm" id="filtroMoeda" name="cdmoeda">
                        <?php foreach ($moedasFiltro as $m): ?>
                            <option value="<?= (int)$m['cdmoeda'] ?>" <?= ((int)$m['cdmoeda'] === $cdmoedaFiltro) ? 'selected' : '' ?>>
                                <?= htmlspecialchars((string)($m['simbolo'] ?? '')) ?> - <?= htmlspecialchars((string)($m['dsmoeda'] ?? '')) ?>
                            </option>
                        <?php endforeach; ?>
                    </select>
                </div>

                <!-- Empresas (Multi-select com checkboxes) -->
                <div class="col-12">
                    <label class="form-label fw-semibold">Empresas</label>
                    <div class="border rounded p-2" style="max-height: 180px; overflow-y: auto;">
                        <!-- Selecionar Todas -->
                        <div class="form-check mb-1">
                            <input class="form-check-input" type="checkbox" id="selecionarTodas" 
                                onchange="toggleTodasEmpresas()" />
                            <label class="form-check-label" for="selecionarTodas">
                                <small class="fw-bold">Selecionar Todas</small>
                            </label>
                        </div>
                        <hr class="my-1" />
                        <!-- Checkboxes de empresas -->
                        <?php foreach ($empresasFiltro as $emp): ?>
                            <div class="form-check mb-1">
                                <input class="form-check-input empresa-checkbox" type="checkbox" 
                                    id="empresa_<?= (int)$emp['cdempresa'] ?>" 
                                    name="cdempresa[]" 
                                    value="<?= (int)$emp['cdempresa'] ?>"
                                    <?= in_array((int)$emp['cdempresa'], $empresasSelecionadas) ? 'checked' : '' ?> />
                                <label class="form-check-label" for="empresa_<?= (int)$emp['cdempresa'] ?>">
                                    <small><?= htmlspecialchars((string)$emp['dsapelido']) ?></small>
                                </label>
                            </div>
                        <?php endforeach; ?>
                    </div>
                </div>

                <!-- Centro de Custo -->
                <div class="col-12">
                    <label for="filtroCentroCusto" class="form-label fw-semibold">Centro de Custo</label>
                    <select class="form-select form-select-sm" id="filtroCentroCusto" name="cdcentrocusto">
                        <option value="0">Todos</option>
                        <?php foreach ($centrosCustoFiltro as $cc): ?>
                            <option value="<?= (int)$cc['cdcentrocusto'] ?>" <?= ((int)$cc['cdcentrocusto'] === $cdcentrocustoFiltro) ? 'selected' : '' ?>>
                                <?= htmlspecialchars((string)$cc['dscentro']) ?>
                            </option>
                        <?php endforeach; ?>
                    </select>
                </div>

                <!-- Trimestre -->
                <div class="col-12">
                    <label for="filtroTrimestre" class="form-label fw-semibold">Trimestre</label>
                    <select class="form-select form-select-sm" id="filtroTrimestre" name="trimestre">
                        <option value="0" <?= ($trimestreFiltro === 0) ? 'selected' : '' ?>>Todos</option>
                        <?php foreach ($trimestresFiltro as $trim): ?>
                            <option value="<?= (int)$trim['numero'] ?>" <?= ((int)$trim['numero'] === $trimestreFiltro) ? 'selected' : '' ?>>
                                <?= htmlspecialchars((string)$trim['descricao']) ?>
                            </option>
                        <?php endforeach; ?>
                    </select>
                </div>
                
                <!-- Botões (discretos) -->
                <div class="col-12 d-flex justify-content-end gap-2">
                    <button type="button" class="btn btn-outline-secondary btn-sm" onclick="limparFiltros()" title="Limpar filtros">
                        <i class="bi bi-arrow-clockwise"></i> Limpar
                    </button>
                    <button type="button" class="btn btn-outline-primary btn-sm" onclick="aplicarFiltros()" title="Aplicar filtros">
                        <i class="bi bi-search"></i> Filtrar
                    </button>
                </div>
            </form>
        </div>
    </div>
    </div>
</div>


<?php if ($mostrarProfile && !empty($profileSteps)): ?>
    <div class="alert alert-secondary py-2 px-3 small mb-3">
        <div class="fw-semibold mb-1">Profiling (ms)</div>
        <div class="d-flex flex-wrap gap-3">
            <?php foreach ($profileSteps as $p): ?>
                <div><strong><?= htmlspecialchars($p['label']) ?>:</strong> <?= number_format((float)$p['ms'], 2, ',', '.') ?></div>
            <?php endforeach; ?>
        </div>
    </div>
<?php endif; ?>

<!-- Toggle de Visão (pill buttons) -->
<?php if (count($visoesUsuario) > 1): ?>
<?php
$_modelosAtivos = [];
foreach ($modeloPorVariavel as $_vid => $_mod) {
    $_modNorm = strtolower(trim((string)$_mod));
    if (!in_array($_modNorm, $_modelosAtivos, true)) {
        $_modelosAtivos[] = $_modNorm;
    }
}
$_modelosToggle = ['meta', 'submeta', 'orcamento'];
$_modeloIcones = ['meta' => 'bi-bullseye', 'submeta' => 'bi-flag', 'resultado' => 'bi-clipboard-data', 'orcamento' => 'bi-briefcase'];
$_modeloLabelsToggle = ['meta' => 'Meta', 'submeta' => 'Submeta', 'resultado' => 'Resultado', 'orcamento' => 'Orçamento'];
if (in_array('resultado', $_modelosAtivos, true)) {
    array_splice($_modelosToggle, 2, 0, ['resultado']);
}
$_showModeloToggle = !empty($_modelosToggle) && $visaoDashboard !== 'planilha';
?>
<div class="dash-toggle-bar mb-2">
    <div class="dash-toggle-group" role="group" aria-label="Visão do Dashboard">
        <?php if (in_array('variavel', $visoesUsuario, true)): ?>
        <a href="<?= htmlspecialchars(urlComVisaoDashboard('variavel')) ?>" class="dash-toggle-btn <?= ($visaoDashboard === 'variavel' || $visaoDashboard === 'percentual') ? 'active' : '' ?>">
            <i class="bi bi-card-list"></i> <span>Detalhado</span>
        </a>
        <?php endif; ?>
        <?php if (in_array('modelo', $visoesUsuario, true)): ?>
        <a href="<?= htmlspecialchars(urlComVisaoDashboard('modelo')) ?>" class="dash-toggle-btn <?= $visaoDashboard === 'modelo' ? 'active' : '' ?>">
            <i class="bi bi-columns-gap"></i> <span>Consolidado</span>
        </a>
        <?php endif; ?>
        <?php if (in_array('percentual', $visoesUsuario, true)): ?>
        <a href="<?= htmlspecialchars(urlComVisaoDashboard('percentual')) ?>" class="dash-toggle-btn <?= $visaoDashboard === 'percentual' ? 'active' : '' ?>">
            <i class="bi bi-percent"></i> <span>Percentual</span>
        </a>
        <?php endif; ?>
        <?php if (in_array('planilha', $visoesUsuario, true)): ?>
        <a href="<?= htmlspecialchars(urlComVisaoDashboard('planilha')) ?>" class="dash-toggle-btn <?= $visaoDashboard === 'planilha' ? 'active' : '' ?>">
            <i class="bi bi-table"></i> <span>Planilha</span>
        </a>
        <?php endif; ?>
    </div>
    <?php if ($_showModeloToggle): ?>
    <div class="dash-modelo-group" role="group" aria-label="Tipo de Variável">
        <button type="button" class="dash-modelo-btn active" data-modelo-filter="todos">
            <i class="bi bi-grid-3x3-gap"></i> <span>Todos</span>
        </button>
        <?php foreach ($_modelosToggle as $_mi => $_mKey): ?>
        <button type="button" class="dash-modelo-btn" data-modelo-filter="<?= htmlspecialchars($_mKey) ?>">
            <i class="bi <?= $_modeloIcones[$_mKey] ?? 'bi-circle' ?>"></i> <span><?= $_modeloLabelsToggle[$_mKey] ?? ucfirst($_mKey) ?></span>
        </button>
        <?php endforeach; ?>
        <?php if ($visaoDashboard !== 'planilha'): ?>
        <span class="dash-modelo-sep"></span>
        <button type="button" class="dash-numerico-btn active" data-exibicao="compacta" title="Valores compactos">$</button>
        <button type="button" class="dash-numerico-btn" data-exibicao="completa" title="Valores completos">$$</button>
        <?php endif; ?>
    </div>
    <?php endif; ?>
</div>
<?php endif; ?>


<!-- ⚠️ Alerta de sincronização atrasada -->
<?php if ($ultimaSincronizacao): ?>
    <?php 
        $dt = new DateTime($ultimaSincronizacao);
        $horas_passadas = (time() - $dt->getTimestamp()) / 3600;
        if ($horas_passadas > 24):
    ?>
        <div class="alert alert-warning alert-dismissible fade show mb-3" role="alert">
            <i class="bi bi-exclamation-triangle-fill"></i>
            <strong>Sincronização atrasada!</strong>
            Os dados não são sincronizados há mais de 24 horas. 
            <a href="#" onclick="abrirSyncModal(event)" class="alert-link">Clique aqui para sincronizar agora</a>.
            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
        </div>
    <?php endif; ?>
<?php endif; ?>
<!-- Container da visão de gráficos/BI -->
<?php if ($visaoDashboard === 'planilha'): ?>
<!-- ================================ -->
<!-- VISÃO PLANILHA - Mobile-friendly -->
<!-- ================================ -->
<?php
$_modeloPadrao = $_planilhaModelosOrdenados[0] ?? 'meta';
$_modeloLabels = ['meta' => 'Meta', 'submeta' => 'Submeta', 'resultado' => 'Resultado', 'orcamento' => 'Orçamento'];
$_modeloBadge  = ['meta' => 'bg-primary', 'submeta' => 'bg-success', 'resultado' => 'bg-secondary', 'orcamento' => 'bg-info'];
?>
<div class="mb-4" id="planilhaContainer">
    <style>
    /* Desktop: fontes maiores */
    .planilha-desktop { display: block; }
    .planilha-mobile  { display: none; }
    .planilha-desktop .table-planilha { font-size: 1.16rem; }
    .planilha-desktop .table-planilha th { font-size: 1.16rem; padding: 0.65rem 0.55rem; }
    .planilha-desktop .table-planilha td { padding: 0.55rem; font-size: 1.16rem; vertical-align: middle; }
    .planilha-desktop .pv-empresa { font-size: 1.16rem !important; }
    .planilha-desktop .pv-variavel span { font-size: 1.16rem !important; }
    .planilha-desktop .pv-variavel .badge { font-size: 0.94rem !important; }
    .planilha-desktop .pv-origem-label { font-size: 0.82rem; color: #6c757d; margin-top: 2px; }
    .planilha-desktop .pv-origem-label i { font-size: 0.72rem; }
    /* Mobile: tabela com scroll horizontal e colunas fixas à esquerda */
    @media (max-width: 768px) {
        .planilha-desktop { display: none !important; }
        .planilha-mobile  { display: block !important; }
        .pv-mob-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; max-height: 75vh; overflow-y: auto; }
        .pv-mob-table { font-size: 0.96rem; border-collapse: separate; border-spacing: 0; white-space: nowrap; }
        .pv-mob-table thead th { position: sticky; top: 0; background: #f0f0f0; z-index: 20; padding: 0.4rem 0.5rem; font-size: 0.88rem; text-transform: uppercase; color: #495057; border-bottom: 2px solid #dee2e6; }
        .pv-mob-table .pvm-sticky { position: sticky; left: 0; background: #f8f9fa; z-index: 10; border-right: 2px solid #dee2e6; }
        .pv-mob-table thead .pvm-sticky { z-index: 30; }
        .pv-mob-table .pvm-empresa { min-width: 110px; max-width: 140px; white-space: normal; word-break: break-word; font-weight: 600; font-size: 0.94rem; padding: 0.35rem 0.4rem; }
        .pv-mob-table .pvm-variavel { min-width: 80px; max-width: 110px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 0.78rem; padding: 0.3rem 0.4rem; border-right: 2px solid #dee2e6; }
        .pv-mob-table .pvm-variavel .pvm-varname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        .pv-mob-table .pvm-variavel .pvm-origem { font-size: 0.68rem; color: #6c757d; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 1px; }
        .pv-mob-table .pvm-variavel .pvm-origem strong { color: #212529; }
        .pv-mob-table .pvm-val { padding: 0.35rem 0.5rem; min-width: 100px; text-align: right; font-size: 0.96rem; vertical-align: middle; }
        .pv-mob-table .pvm-val-perc { text-align: center; min-width: 65px; font-weight: 600; }
        .pv-mob-table tbody tr { border-bottom: 1px solid #eee; }
        .pv-mob-table tbody tr.pv-zebra-odd,
        .pv-mob-table tbody tr.pv-zebra-odd > td { background-color: #f0f2f6 !important; }
        .pv-mob-table tbody tr.pv-zebra-even,
        .pv-mob-table tbody tr.pv-zebra-even > td { background-color: #ffffff !important; }
        .pv-mob-table tbody tr.pv-zebra-odd .pvm-sticky { background-color: #e4e7ed !important; }
        .pv-mob-table tbody tr.pv-zebra-even .pvm-sticky { background-color: #f8f9fa !important; }

    }
    /* Planilha: pills responsivos mobile */
    @media (max-width: 768px) {
        .planilha-filter-bar { flex-direction: column; gap: 0.4rem !important; }
        .planilha-filter-bar .dash-modelo-group { width: 100%; }
        .planilha-filter-bar .dash-modelo-btn { flex: 1; justify-content: center; padding: 5px 4px; font-size: 0.72rem; }
        .planilha-filter-bar .dash-numerico-btn { padding: 4px 10px; font-size: 0.78rem; }
    }
    </style>

    <div class="card border-0 shadow-sm">
        <div class="card-header bg-light border-0" style="padding: 0.75rem 1rem;">
            <div class="d-flex justify-content-between align-items-center mb-2">
                <h6 class="mb-0 text-dark fw-bold">
                    <i class="bi bi-table"></i> Planilha
                </h6>
                <span class="badge bg-primary"><?= count($visaoPlanilhaEmpresas) ?> Empresa(s)</span>
            </div>

            <div class="d-flex flex-wrap align-items-center gap-2 planilha-filter-bar">
                <!-- Modelo + $/$$ -->
                <div class="dash-modelo-group" role="group">
                    <?php foreach ($_planilhaModelosOrdenados as $idx => $mdl): ?>
                    <button type="button"
                        class="dash-modelo-btn <?= ($idx === 0) ? 'active' : '' ?> planilha-modelo-btn"
                        data-modelo="<?= htmlspecialchars($mdl) ?>">
                        <?= $_modeloLabels[$mdl] ?? ucfirst($mdl) ?>
                    </button>
                    <?php endforeach; ?>
                    <span class="dash-modelo-sep"></span>
                    <?php $__valInicial = in_array($_modeloPadrao, ['submeta','orcamento']) ? 'integral' : 'abreviado'; ?>
                    <button type="button" class="dash-numerico-btn <?= $__valInicial === 'abreviado' ? 'active' : '' ?> planilha-valores-btn" data-valores="abreviado" title="Valores compactos">$</button>
                    <button type="button" class="dash-numerico-btn <?= $__valInicial === 'integral' ? 'active' : '' ?> planilha-valores-btn" data-valores="integral" title="Valores completos">$$</button>
                </div>
                <!-- Período -->
                <div class="dash-modelo-group" role="group">
                    <button type="button" class="dash-modelo-btn planilha-periodo-btn" data-periodo="7d">7 Dias</button>
                    <button type="button" class="dash-modelo-btn active planilha-periodo-btn" data-periodo="mes">Mês</button>
                    <button type="button" class="dash-modelo-btn planilha-periodo-btn" data-periodo="trim">Trimestre</button>
                    <button type="button" class="dash-modelo-btn planilha-periodo-btn" data-periodo="ano">Ano</button>
                </div>
            </div>

            <!-- Label da variável selecionada (mobile only) -->
            <div class="planilha-mobile mt-1" id="planilhaVarLabelWrap" style="display:none">
                <span id="planilhaVarLabel" style="font-size:0.82rem;color:#495057;font-weight:500"></span>
            </div>
        </div>

        <div class="card-body p-0">
            <!-- DESKTOP: Tabela -->
            <div class="planilha-desktop" style="overflow-x: auto;">
                <table class="table table-bordered mb-0 table-planilha" id="planilhaTable" style="font-size: 0.95rem;">
                    <thead id="planilhaThead" style="position: sticky; top: 0; background: #f8f9fa; z-index: 10;">
                        <tr id="planilhaTheadRow">
                            <th class="text-center" style="min-width: 160px; border-right: 2px solid #dee2e6;">Empresa</th>
                            <th class="text-center" style="min-width: 150px; border-right: 2px solid #dee2e6;">Variável</th>
                            <th class="text-end" style="min-width: 120px;">Realizado</th>
                            <th class="text-center" style="min-width: 70px;">% Real.</th>
                            <th class="text-end" style="min-width: 120px;">Diferença</th>
                            <th class="text-center" style="min-width: 70px;">% Dif.</th>
                            <th class="text-end" style="min-width: 120px;">Projeção</th>
                            <th class="text-center" style="min-width: 70px;">% Proj.</th>
                            <th class="text-end" style="min-width: 120px;">Orçado</th>
                        </tr>
                    </thead>
                    <tbody>
                        <?php foreach ($visaoPlanilhaEmpresas as $empIdx => $empresa):
                            $moedaEmp = $empresa['moeda'];
                            $simb = htmlspecialchars($moedaEmp['simbolo'] ?? 'R$');
                            $fmt = $moedaEmp['formato'] ?? 'decimal';
                            $variaveis = $empresa['variaveis'];
                            if (empty($variaveis)) continue;

                            foreach ($variaveis as $vIdx => $v):
                                $mdl = $v['modelo'];
                                $corMes = obterCorHexProjecao($v['projMesPerc'], $mdl);
                                $corTrim = obterCorHexProjecao($v['projTrimPerc'], $mdl);
                                $corAno = obterCorHexProjecao($v['projAnoPerc'], $mdl);
                                $pMes = formatarPercentDashboard($v['projMesPerc']);
                                $pTrim = formatarPercentDashboard($v['projTrimPerc']);
                                $pAno = formatarPercentDashboard($v['projAnoPerc']);
                                $r7d = $v['real7d'];
                                $diasJson = htmlspecialchars(json_encode($v['diasDetalhado'] ?? []), ENT_QUOTES, 'UTF-8');
                        ?>
                        <tr class="planilha-row" 
                            data-empresa="<?= $empIdx ?>"
                            data-modelo="<?= $mdl ?>"
                            data-orc-mes="<?= $v['orcMes'] ?>" data-real-mes="<?= $v['realMes'] ?>" data-proj-mes="<?= $v['projMes'] ?>" data-perc-mes="<?= $pMes ?>" data-cor-mes="<?= $corMes ?>"
                            data-orc-trim="<?= $v['orcTrim'] ?>" data-real-trim="<?= $v['realTrim'] ?>" data-proj-trim="<?= $v['projTrim'] ?>" data-perc-trim="<?= $pTrim ?>" data-cor-trim="<?= $corTrim ?>"
                            data-orc-ano="<?= $v['orcAno'] ?>" data-real-ano="<?= $v['realAno'] ?>" data-proj-ano="<?= $v['projAno'] ?>" data-perc-ano="<?= $pAno ?>" data-cor-ano="<?= $corAno ?>"
                            data-real-7d="<?= $r7d ?>"
                            data-dias-hist="<?= $diasJson ?>"
                            data-simbolo="<?= $simb ?>" data-formato="<?= $fmt ?>"
                            <?php if (!empty($v['origemInfo'])): ?>data-origem-nome="<?= htmlspecialchars($v['origemInfo']['nome']) ?>" data-origem-valor="<?= htmlspecialchars($v['origemInfo']['valor']) ?>"<?php endif; ?>>
                            <td class="align-middle fw-semibold pv-empresa" style="background: #f8f9fa; border-right: 2px solid #dee2e6; padding: 0.5rem;">
                                <?= htmlspecialchars($empresa['dsempresa']) ?>
                            </td>
                            <td class="align-middle pv-variavel" style="border-right: 2px solid #dee2e6; padding: 0.4rem 0.5rem;">
                                <div><span class="badge <?= $_modeloBadge[$mdl] ?? 'bg-secondary' ?>" style="margin-right: 4px; vertical-align: middle;"><?= $_modeloLabels[$mdl] ?? ucfirst($mdl) ?></span>
                                <span><?= htmlspecialchars($v['nome']) ?></span></div>
                                <?php if (!empty($v['origemInfo'])): ?>
                                <div class="pv-origem-label" style="font-size:0.82rem;color:#6c757d;margin-top:2px;"><i class="bi bi-database" style="font-size:0.72rem"></i> <strong style="color:#212529"><?= htmlspecialchars($v['origemInfo']['valor']) ?></strong></div>
                                <?php endif; ?>
                            </td>
                            <td class="text-end pv-val"></td>
                            <td class="text-center pv-val"></td>
                            <td class="text-end pv-val"></td>
                            <td class="text-center pv-val"></td>
                            <td class="text-end pv-val"></td>
                            <td class="text-center pv-val"></td>
                            <td class="text-end pv-val"></td>
                        </tr>
                        <?php endforeach; ?>
                        <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
            <div id="planilhaDeskLegenda" class="planilha-desktop text-muted px-2 py-1" style="font-size:0.76rem;display:none">
                <strong>Legenda:</strong> K = milhares &nbsp;|&nbsp; M = milhões &nbsp;|&nbsp; MM = bilhões
            </div>

            <!-- MOBILE: Tabela com scroll horizontal -->
            <div class="planilha-mobile" id="planilhaMobile">
                <div class="pv-mob-scroll">
                    <table class="table table-bordered mb-0 pv-mob-table" id="planilhaMobTable">
                        <thead>
                            <tr id="planilhaMobTheadRow">
                                <th class="pvm-sticky pvm-empresa">Empresa</th>
                                <th class="pvm-variavel" id="mobThVariavel" style="display:none">Variável</th>
                                <th class="pvm-val">Realizado</th>
                                <th class="pvm-val pvm-val-perc">% Real.</th>
                                <th class="pvm-val">Diferença</th>
                                <th class="pvm-val pvm-val-perc">% Dif.</th>
                                <th class="pvm-val">Projeção</th>
                                <th class="pvm-val pvm-val-perc">% Proj.</th>
                                <th class="pvm-val">Orçado</th>
                            </tr>
                        </thead>
                        <tbody>
                            <?php foreach ($visaoPlanilhaEmpresas as $empIdx => $empresa):
                                $moedaEmp = $empresa['moeda'];
                                $simb = htmlspecialchars($moedaEmp['simbolo'] ?? 'R$');
                                $fmt = $moedaEmp['formato'] ?? 'decimal';
                                $variaveis = $empresa['variaveis'];
                                if (empty($variaveis)) continue;
                                foreach ($variaveis as $v):
                                    $mdl = $v['modelo'];
                                    $corMes = obterCorHexProjecao($v['projMesPerc'], $mdl);
                                    $corTrim = obterCorHexProjecao($v['projTrimPerc'], $mdl);
                                    $corAno = obterCorHexProjecao($v['projAnoPerc'], $mdl);
                                    $pMes = formatarPercentDashboard($v['projMesPerc']);
                                    $pTrim = formatarPercentDashboard($v['projTrimPerc']);
                                    $pAno = formatarPercentDashboard($v['projAnoPerc']);
                                    $diasJson = htmlspecialchars(json_encode($v['diasDetalhado'] ?? []), ENT_QUOTES, 'UTF-8');
                            ?>
                            <tr class="mob-planilha-row"
                                data-empresa="<?= $empIdx ?>"
                                data-modelo="<?= $mdl ?>"
                                data-orc-mes="<?= $v['orcMes'] ?>" data-real-mes="<?= $v['realMes'] ?>" data-proj-mes="<?= $v['projMes'] ?>" data-perc-mes="<?= $pMes ?>" data-cor-mes="<?= $corMes ?>"
                                data-orc-trim="<?= $v['orcTrim'] ?>" data-real-trim="<?= $v['realTrim'] ?>" data-proj-trim="<?= $v['projTrim'] ?>" data-perc-trim="<?= $pTrim ?>" data-cor-trim="<?= $corTrim ?>"
                                data-orc-ano="<?= $v['orcAno'] ?>" data-real-ano="<?= $v['realAno'] ?>" data-proj-ano="<?= $v['projAno'] ?>" data-perc-ano="<?= $pAno ?>" data-cor-ano="<?= $corAno ?>"
                                data-real-7d="<?= $v['real7d'] ?>"
                                data-dias-hist="<?= $diasJson ?>"
                                data-simbolo="<?= $simb ?>" data-formato="<?= $fmt ?>"
                                data-varname="<?= htmlspecialchars($v['nome']) ?>"
                                <?php if (!empty($v['origemInfo'])): ?>data-origem-nome="<?= htmlspecialchars($v['origemInfo']['nome']) ?>" data-origem-valor="<?= htmlspecialchars($v['origemInfo']['valor']) ?>"<?php endif; ?>>
                                <td class="pvm-sticky pvm-empresa">
                                    <?= htmlspecialchars($empresa['dsapelido'] ?? $empresa['dsempresa']) ?>
                                </td>
                                <td class="pvm-variavel mob-variavel" style="display:none">
                                    <div class="pvm-varname"><?= htmlspecialchars($v['nome']) ?></div>
                                    <?php if (!empty($v['origemInfo'])): ?>
                                    <div class="pvm-origem"><i class="bi bi-database"></i> <strong><?= htmlspecialchars($v['origemInfo']['valor']) ?></strong></div>
                                    <?php endif; ?>
                                </td>
                                <td class="pvm-val mob-val"></td>
                                <td class="pvm-val pvm-val-perc mob-val"></td>
                                <td class="pvm-val mob-val"></td>
                                <td class="pvm-val pvm-val-perc mob-val"></td>
                                <td class="pvm-val mob-val"></td>
                                <td class="pvm-val pvm-val-perc mob-val"></td>
                                <td class="pvm-val mob-val"></td>
                            </tr>
                            <?php endforeach; ?>
                            <?php endforeach; ?>
                        </tbody>
                    </table>
                </div>
                <div id="planilhaMobLegenda" class="planilha-mobile text-muted px-2 py-1" style="font-size:0.76rem;display:none">
                    <strong>Legenda:</strong> K = Milhar &nbsp;|&nbsp; M = Milhões &nbsp;|&nbsp; MM = Mil Miliones
                </div>
            </div>
        </div>
    </div>
</div>

<script>
(function() {
    var periodoAtual = 'mes';
    var modeloAtual = <?= json_encode($_modeloPadrao) ?>;
    var mobValorIntegral = <?= in_array($_modeloPadrao, ['submeta','orcamento']) ? 'true' : 'false' ?>;
    var deskValorIntegral = <?= in_array($_modeloPadrao, ['submeta','orcamento']) ? 'true' : 'false' ?>;
    var modeloBadgeClasses = <?= json_encode($_modeloBadge) ?>;
    var diasLabels = <?= json_encode($_planilha7Labels) ?>;
    var NUM_DIAS = diasLabels.length;
    var HOJE_IDX_7D = <?= (int)$_hojeIdx7d ?>;

    var colsNormal = [
        {label: 'Empresa', cls: 'text-center', style: 'min-width:160px;border-right:2px solid #dee2e6'},
        {label: 'Vari\u00e1vel', cls: 'text-center', style: 'min-width:150px;border-right:2px solid #dee2e6'},
        {label: 'Realizado', cls: 'text-end', style: 'min-width:120px'},
        {label: '% Real.', cls: 'text-center', style: 'min-width:70px'},
        {label: 'Diferen\u00e7a', cls: 'text-end', style: 'min-width:120px'},
        {label: '% Dif.', cls: 'text-center', style: 'min-width:70px'},
        {label: 'Proje\u00e7\u00e3o', cls: 'text-end', style: 'min-width:120px'},
        {label: '% Proj.', cls: 'text-center', style: 'min-width:70px'},
        {label: 'Or\u00e7ado', cls: 'text-end', style: 'min-width:120px'}
    ];

    function montarThead(is7d) {
        var tr = document.getElementById('planilhaTheadRow');
        tr.innerHTML = '';
        var th1 = document.createElement('th');
        th1.className = 'text-center';
        th1.style.cssText = 'min-width:160px;border-right:2px solid #dee2e6';
        th1.textContent = 'Empresa';
        tr.appendChild(th1);
        var th2 = document.createElement('th');
        th2.className = 'text-center';
        th2.style.cssText = is7d ? 'min-width:120px;border-right:2px solid #dee2e6' : 'min-width:150px;border-right:2px solid #dee2e6';
        th2.textContent = 'Vari\u00e1vel';
        tr.appendChild(th2);
        if (is7d) {
            diasLabels.forEach(function(lb) {
                var th = document.createElement('th');
                th.className = 'text-center';
                th.style.cssText = 'min-width:110px;font-size:0.98rem;white-space:nowrap';
                th.textContent = lb;
                tr.appendChild(th);
            });
        } else {
            for (var c = 2; c < colsNormal.length; c++) {
                var th = document.createElement('th');
                th.className = colsNormal[c].cls;
                th.style.cssText = colsNormal[c].style;
                th.textContent = colsNormal[c].label;
                tr.appendChild(th);
            }
        }
    }

    function ajustarCelulasRow(row, is7d) {
        var vals = row.querySelectorAll('.pv-val');
        vals.forEach(function(td) { td.remove(); });
        if (is7d) {
            for (var d = 0; d < NUM_DIAS; d++) {
                var td = document.createElement('td');
                td.className = 'text-center pv-val pv-dia';
                td.style.cssText = 'padding:0.4rem;vertical-align:middle;line-height:1.3';
                row.appendChild(td);
            }
        } else {
            for (var c = 0; c < 7; c++) {
                var td = document.createElement('td');
                td.className = (c === 1 || c === 3 || c === 5 ? 'text-center' : 'text-end') + ' pv-val';
                row.appendChild(td);
            }
        }
    }

    function fmtVal(val, simbolo, formato) {
        val = parseFloat(val) || 0;
        var casas = (formato === 'inteiro') ? 0 : 2;
        var abs = Math.abs(val);
        var parts = abs.toFixed(casas).split('.');
        parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, '.');
        var formatted = casas > 0 ? parts.join(',') : parts[0];
        return (val < 0 ? '-' : '') + simbolo + ' ' + formatted;
    }

    function fmtValCompact(val, simbolo, formato) {
        val = parseFloat(val) || 0;
        var neg = val < 0 ? '-' : '';
        var abs = Math.abs(val);
        if (formato === 'inteiro') {
            // Inteiro: divide por 1.000.000, resultado < 1000 = "X M", >= 1000 = "X.XXXMM"
            if (abs >= 1e6) {
                var v = Math.floor(abs / 1e6);
                if (v >= 1000) {
                    var s = v.toString().replace(/\B(?=(\d{3})+(?!\d))/g, '.');
                    return neg + simbolo + ' ' + s + 'MM';
                }
                return neg + simbolo + ' ' + v + 'M';
            }
            var s = Math.round(abs).toString().replace(/\B(?=(\d{3})+(?!\d))/g, '.');
            return neg + simbolo + ' ' + s;
        } else {
            // Decimal: divide por 1000, resultado < 1000 = "XK", >= 1000 = "X.XXXM"
            if (abs >= 1e3) {
                var v = Math.floor(abs / 1e3);
                if (v >= 1000) {
                    var s = v.toString().replace(/\B(?=(\d{3})+(?!\d))/g, '.');
                    return neg + simbolo + ' ' + s + 'M';
                }
                return neg + simbolo + ' ' + v + 'K';
            }
            var s = abs.toFixed(2).replace('.', ',');
            return neg + simbolo + ' ' + s;
        }
    }

    function capitalizar(s) { return s.charAt(0).toUpperCase() + s.slice(1); }

    function corProjecao(perc, modelo) {
        var v = Math.abs(perc);
        if (modelo === 'orcamento') {
            if (v <= 0.80) return '#16a34a';
            if (v <= 0.90) return '#f59e0b';
            return '#dc2626';
        }
        if (v >= 1.0) return '#16a34a';
        if (v >= 0.95) return '#f59e0b';
        return '#dc2626';
    }

    var lastModo = null;

    function atualizarPlanilha() {
        var is7d = (periodoAtual === '7d');
        var modoMudou = (lastModo !== is7d);
        lastModo = is7d;

        // === DESKTOP TABLE ===
        var tbody = document.querySelector('#planilhaTable tbody');
        var rows = tbody.querySelectorAll('.planilha-row');

        if (modoMudou) montarThead(is7d);

        rows.forEach(function(row) {
            var mdl = row.dataset.modelo;
            if (mdl !== modeloAtual) { row.style.display = 'none'; return; }
            // Ocultar linhas sem valores
            if (!is7d) {
                var _suf = capitalizar(periodoAtual);
                var _orc = parseFloat(row.dataset['orc' + _suf]) || 0;
                var _real = parseFloat(row.dataset['real' + _suf]) || 0;
                var _proj = parseFloat(row.dataset['proj' + _suf]) || 0;
                if (_orc === 0 && _real === 0 && _proj === 0) { row.style.display = 'none'; return; }
            } else {
                var _realAno = parseFloat(row.dataset.realAno) || 0;
                if (_realAno === 0) { row.style.display = 'none'; return; }
            }
            row.style.display = '';
            if (modoMudou) ajustarCelulasRow(row, is7d);

            var simb = row.dataset.simbolo;
            var fmt = row.dataset.formato;
            var valCells = row.querySelectorAll('.pv-val');

            if (is7d) {
                var dias = [];
                try { dias = JSON.parse(row.dataset.diasHist || '[]'); } catch(e) {}
                for (var d = 0; d < NUM_DIAS; d++) {
                    var td = valCells[d];
                    if (!td) continue;
                    if (d < dias.length && dias[d].t) {
                        var dia = dias[d];
                        var corP = corProjecao(dia.p / 100, row.dataset.modelo);
                        var corD = (dia.d > 0) ? '#dc3545' : '#198754';
                        var html = '<div style="font-weight:600;color:#212529;font-size:1.02rem">' + fmtVal(dia.v, simb, fmt) + '</div>'
                            + '<div style="color:' + corP + ';font-size:0.92rem">' + dia.p.toFixed(1).replace('.', ',') + '%</div>'
                            + '<div style="color:' + corD + ';font-size:0.86rem">' + (dia.d > 0 ? '-' + dia.d.toFixed(1).replace('.', ',') + '%' : '&#10003;') + '</div>';
                        // Breakdown contas fechadas/abertas no dia atual
                        if (d === HOJE_IDX_7D && dia.f !== undefined) {
                            td.style.cursor = 'pointer';
                            html += '<div class="pv-origem-detalhe" style="display:none;margin-top:4px;padding:4px 6px;background:#f8f9fa;border:1px solid #dee2e6;border-radius:4px;font-size:0.84rem;">'
                                + '<div style="display:flex;justify-content:space-between"><span style="color:#6c757d">Contas Fechadas</span><span style="font-weight:600">' + fmtVal(dia.f, simb, fmt) + '</span></div>'
                                + '<div style="display:flex;justify-content:space-between"><span style="color:#6c757d">' + (dia.on || 'Contas Abertas') + '</span><span style="font-weight:600;color:#0d6efd">' + fmtVal(dia.a, simb, fmt) + '</span></div>'
                                + '<hr style="margin:2px 0">'
                                + '<div style="display:flex;justify-content:space-between"><span style="font-weight:700">Total</span><span style="font-weight:700">' + fmtVal(dia.v, simb, fmt) + '</span></div>'
                                + '</div>';
                        }
                        td.innerHTML = html;
                        if (d === HOJE_IDX_7D && dia.f !== undefined) {
                            td.onclick = function() {
                                var det = this.querySelector('.pv-origem-detalhe');
                                if (det) det.style.display = det.style.display === 'none' ? 'block' : 'none';
                            };
                        }
                    } else {
                        td.innerHTML = '<span style="color:#ccc">-</span>';
                    }
                }
            } else {
                var suf = capitalizar(periodoAtual);
                var vOrc = parseFloat(row.dataset['orc' + suf]) || 0;
                var vReal = parseFloat(row.dataset['real' + suf]) || 0;
                var vProj = parseFloat(row.dataset['proj' + suf]) || 0;
                var cor = row.dataset['cor' + suf];
                var pVal = row.dataset['perc' + suf];
                if (valCells.length >= 7) {
                    var fmtDesk = deskValorIntegral ? fmtVal : fmtValCompact;
                    // Realizado
                    valCells[0].textContent = fmtDesk(vReal, simb, fmt);
                    valCells[0].style.color = '#212529';
                    // % Realizado
                    var percReal = (vOrc > 0) ? ((vReal / vOrc) * 100) : 0;
                    valCells[1].textContent = percReal.toFixed(1).replace('.', ',') + '%';
                    valCells[1].style.color = cor;
                    // GAP (orçado - realizado)
                    var gapDesk = vOrc - vReal;
                    valCells[2].textContent = fmtDesk(gapDesk, simb, fmt);
                    valCells[2].style.color = '#212529';
                    // % GAP (% realizado - 100)
                    var percGapDesk = percReal - 100;
                    valCells[3].textContent = percGapDesk.toFixed(1).replace('.', ',') + '%';
                    valCells[3].style.color = cor;
                    // Projeção
                    valCells[4].textContent = fmtDesk(vProj, simb, fmt);
                    valCells[4].style.color = '#212529';
                    // % Projeção
                    valCells[5].textContent = pVal;
                    valCells[5].style.color = cor;
                    // Orçado
                    valCells[6].textContent = fmtDesk(vOrc, simb, fmt);
                    valCells[6].style.color = '#212529';
                }
            }
        });

        // Rowspans de empresa (desktop)
        rows.forEach(function(row) {
            var td = row.querySelector('.pv-empresa');
            if (td) { td.removeAttribute('rowspan'); td.style.display = ''; }
        });
        var visibleRows = [];
        rows.forEach(function(row) { if (row.style.display !== 'none') visibleRows.push(row); });

        // Ordenar por grupo de empresa (pior % Realizado do grupo) - desktop
        if (!is7d && visibleRows.length > 1) {
            var sufDesk = capitalizar(periodoAtual);
            // Agrupar rows por empresa
            var gruposDesk = {};
            var ordemDesk = [];
            visibleRows.forEach(function(row) {
                var emp = row.dataset.empresa;
                if (!gruposDesk[emp]) { gruposDesk[emp] = []; ordemDesk.push(emp); }
                gruposDesk[emp].push(row);
            });
            // Calcular pior % por grupo
            var percGrupoDesk = {};
            ordemDesk.forEach(function(emp) {
                var pior = Infinity;
                gruposDesk[emp].forEach(function(row) {
                    var orc = parseFloat(row.dataset['orc' + sufDesk]) || 0;
                    var real = parseFloat(row.dataset['real' + sufDesk]) || 0;
                    var perc = (orc > 0) ? (real / orc) : 0;
                    if (perc < pior) pior = perc;
                });
                percGrupoDesk[emp] = pior;
            });
            // Ordenar grupos
            ordemDesk.sort(function(a, b) { return percGrupoDesk[a] - percGrupoDesk[b]; });
            // Reordenar no DOM mantendo grupo junto
            visibleRows = [];
            ordemDesk.forEach(function(emp) {
                gruposDesk[emp].forEach(function(row) { tbody.appendChild(row); visibleRows.push(row); });
            });
        }

        var i = 0;
        while (i < visibleRows.length) {
            var emp = visibleRows[i].dataset.empresa;
            var startTd = visibleRows[i].querySelector('.pv-empresa');
            var span = 1, j = i + 1;
            while (j < visibleRows.length && visibleRows[j].dataset.empresa === emp) {
                var hideTd = visibleRows[j].querySelector('.pv-empresa');
                if (hideTd) hideTd.style.display = 'none';
                span++; j++;
            }
            if (startTd && span > 1) startTd.setAttribute('rowspan', span);
            visibleRows[i].style.borderTop = '2px solid #495057';
            i = j;
        }

        // Zebra striping por grupo de empresa (desktop) — alterna dentro do grupo
        (function() {
            var empIdx = 0, ci = 0;
            while (ci < visibleRows.length) {
                var ce = visibleRows[ci].dataset.empresa;
                var baseOdd = (empIdx % 2 === 0); // grupo cinza ou branco
                var rowInGroup = 0;
                while (ci < visibleRows.length && visibleRows[ci].dataset.empresa === ce) {
                    visibleRows[ci].classList.remove('pv-zebra-odd', 'pv-zebra-even');
                    var isOdd = (rowInGroup % 2 === 0) ? baseOdd : !baseOdd;
                    visibleRows[ci].classList.add(isOdd ? 'pv-zebra-odd' : 'pv-zebra-even');
                    ci++; rowInGroup++;
                }
                empIdx++;
            }
        })();

        // === MOBILE TABLE ===
        var mobTbody = document.querySelector('#planilhaMobTable tbody');
        var mobRows = mobTbody ? mobTbody.querySelectorAll('.mob-planilha-row') : [];
        var mobThead = document.getElementById('planilhaMobTheadRow');

        // Rebuild mobile thead when mode changes
        var isOrcamento = (modeloAtual === 'orcamento');
        var showVarCol = (modeloAtual === 'orcamento' || modeloAtual === 'submeta');
        if (modoMudou && mobThead) {
            var ths = mobThead.querySelectorAll('th');
            // Remove value headers (keep first 1: empresa + variavel th)
            while (ths.length > 2) { ths[ths.length - 1].remove(); ths = mobThead.querySelectorAll('th'); }
            if (is7d) {
                diasLabels.forEach(function(lb) {
                    var th = document.createElement('th');
                    th.className = 'pvm-val';
                    th.style.cssText = 'min-width:90px;font-size:0.68rem;white-space:nowrap;text-align:center';
                    th.textContent = lb;
                    mobThead.appendChild(th);
                });
            } else {
                ['Realizado','% Real.','Diferen\u00e7a','% Dif.','Proje\u00e7\u00e3o','% Proj.','Or\u00e7ado'].forEach(function(lb, idx) {
                    var th = document.createElement('th');
                    th.className = 'pvm-val' + ((idx === 1 || idx === 3 || idx === 5) ? ' pvm-val-perc' : '');
                    th.textContent = lb;
                    mobThead.appendChild(th);
                });
            }
        }

        // Toggle variável column visibility
        var mobThVar = document.getElementById('mobThVariavel');
        if (mobThVar) mobThVar.style.display = showVarCol ? '' : 'none';

        mobRows.forEach(function(row) {
            var mdl = row.dataset.modelo;
            if (mdl !== modeloAtual) { row.style.display = 'none'; return; }
            // Ocultar linhas sem valores
            if (!is7d) {
                var _suf = capitalizar(periodoAtual);
                var _orc = parseFloat(row.dataset['orc' + _suf]) || 0;
                var _real = parseFloat(row.dataset['real' + _suf]) || 0;
                var _proj = parseFloat(row.dataset['proj' + _suf]) || 0;
                if (_orc === 0 && _real === 0 && _proj === 0) { row.style.display = 'none'; return; }
            } else {
                var _realAno = parseFloat(row.dataset.realAno) || 0;
                if (_realAno === 0) { row.style.display = 'none'; return; }
            }
            row.style.display = '';

            // Toggle variável cell
            var varTd = row.querySelector('.mob-variavel');
            if (varTd) varTd.style.display = showVarCol ? '' : 'none';

            var simb = row.dataset.simbolo;
            var fmt = row.dataset.formato;

            // Rebuild value cells when mode changes
            if (modoMudou) {
                var oldVals = row.querySelectorAll('.mob-val');
                oldVals.forEach(function(td) { td.remove(); });
                if (is7d) {
                    for (var d = 0; d < NUM_DIAS; d++) {
                        var td = document.createElement('td');
                        td.className = 'pvm-val mob-val';
                        td.style.textAlign = 'center';
                        row.appendChild(td);
                    }
                } else {
                    for (var c = 0; c < 7; c++) {
                        var td = document.createElement('td');
                        td.className = 'pvm-val mob-val' + ((c === 1 || c === 3 || c === 5) ? ' pvm-val-perc' : '');
                        row.appendChild(td);
                    }
                }
            }

            var valCells = row.querySelectorAll('.mob-val');

            if (is7d) {
                var dias = [];
                try { dias = JSON.parse(row.dataset.diasHist || '[]'); } catch(e) {}
                for (var d = 0; d < NUM_DIAS; d++) {
                    var td = valCells[d];
                    if (!td) continue;
                    if (d < dias.length && dias[d].t) {
                        var dia = dias[d];
                        var corP = corProjecao(dia.p / 100, row.dataset.modelo);
                        var corD = (dia.d > 0) ? '#dc3545' : '#198754';
                        var htmlMob = '<div style="font-weight:600;font-size:0.86rem">' + fmtVal(dia.v, simb, fmt) + '</div>'
                            + '<div style="color:' + corP + ';font-size:0.78rem">' + dia.p.toFixed(1).replace('.', ',') + '%</div>'
                            + '<div style="color:' + corD + ';font-size:0.72rem">' + (dia.d > 0 ? '-' + dia.d.toFixed(1).replace('.', ',') + '%' : '&#10003;') + '</div>';
                        // Breakdown contas fechadas/abertas no dia atual (mobile)
                        if (d === HOJE_IDX_7D && dia.f !== undefined) {
                            td.style.cursor = 'pointer';
                            htmlMob += '<div class="pv-origem-detalhe" style="display:none;margin-top:3px;padding:3px 4px;background:#f8f9fa;border:1px solid #dee2e6;border-radius:4px;font-size:0.72rem;">'
                                + '<div style="display:flex;justify-content:space-between;gap:4px"><span style="color:#6c757d">Fechadas</span><span style="font-weight:600">' + fmtVal(dia.f, simb, fmt) + '</span></div>'
                                + '<div style="display:flex;justify-content:space-between;gap:4px"><span style="color:#6c757d">' + (dia.on || 'Abertas') + '</span><span style="font-weight:600;color:#0d6efd">' + fmtVal(dia.a, simb, fmt) + '</span></div>'
                                + '<hr style="margin:2px 0">'
                                + '<div style="display:flex;justify-content:space-between;gap:4px"><span style="font-weight:700">Total</span><span style="font-weight:700">' + fmtVal(dia.v, simb, fmt) + '</span></div>'
                                + '</div>';
                        }
                        td.innerHTML = htmlMob;
                        if (d === HOJE_IDX_7D && dia.f !== undefined) {
                            td.onclick = function() {
                                var det = this.querySelector('.pv-origem-detalhe');
                                if (det) det.style.display = det.style.display === 'none' ? 'block' : 'none';
                            };
                        }
                    } else {
                        td.innerHTML = '<span style="color:#ccc">-</span>';
                    }
                }
            } else {
                var suf = capitalizar(periodoAtual);
                var vOrc = parseFloat(row.dataset['orc' + suf]) || 0;
                var vReal = parseFloat(row.dataset['real' + suf]) || 0;
                var vProj = parseFloat(row.dataset['proj' + suf]) || 0;
                var cor = row.dataset['cor' + suf];
                var pVal = row.dataset['perc' + suf];
                if (valCells.length >= 7) {
                    var fmtMob = mobValorIntegral ? fmtVal : fmtValCompact;
                    // Realizado
                    valCells[0].textContent = fmtMob(vReal, simb, fmt);
                    valCells[0].style.color = '#212529';
                    // % Realizado
                    var percRealMob = (vOrc > 0) ? ((vReal / vOrc) * 100) : 0;
                    valCells[1].textContent = percRealMob.toFixed(1).replace('.', ',') + '%';
                    valCells[1].style.color = cor;
                    // GAP (orçado - realizado)
                    var gap = vOrc - vReal;
                    valCells[2].textContent = fmtMob(gap, simb, fmt);
                    valCells[2].style.color = '#212529';
                    // % GAP (% realizado - 100)
                    var percGap = percRealMob - 100;
                    valCells[3].textContent = percGap.toFixed(1).replace('.', ',') + '%';
                    valCells[3].style.color = cor;
                    // Projeção
                    valCells[4].textContent = fmtMob(vProj, simb, fmt);
                    valCells[4].style.color = '#212529';
                    // % Projeção
                    valCells[5].textContent = pVal;
                    valCells[5].style.color = cor;
                    // Orçado
                    valCells[6].textContent = fmtMob(vOrc, simb, fmt);
                    valCells[6].style.color = '#212529';
                }
            }
        });

        // Rowspans de empresa (mobile)
        mobRows.forEach(function(row) {
            var td = row.querySelector('.pvm-empresa');
            if (td) { td.removeAttribute('rowspan'); td.style.display = ''; }
        });
        var mobVisible = [];
        mobRows.forEach(function(row) { if (row.style.display !== 'none') mobVisible.push(row); });

        // Ordenar por grupo de empresa (pior % Realizado do grupo) - mobile
        if (!is7d && mobVisible.length > 1) {
            var suf = capitalizar(periodoAtual);
            var gruposMob = {};
            var ordemMob = [];
            mobVisible.forEach(function(row) {
                var emp = row.dataset.empresa;
                if (!gruposMob[emp]) { gruposMob[emp] = []; ordemMob.push(emp); }
                gruposMob[emp].push(row);
            });
            var percGrupoMob = {};
            ordemMob.forEach(function(emp) {
                var pior = Infinity;
                gruposMob[emp].forEach(function(row) {
                    var orc = parseFloat(row.dataset['orc' + suf]) || 0;
                    var real = parseFloat(row.dataset['real' + suf]) || 0;
                    var perc = (orc > 0) ? (real / orc) : 0;
                    if (perc < pior) pior = perc;
                });
                percGrupoMob[emp] = pior;
            });
            ordemMob.sort(function(a, b) { return percGrupoMob[a] - percGrupoMob[b]; });
            mobVisible = [];
            ordemMob.forEach(function(emp) {
                gruposMob[emp].forEach(function(row) { mobTbody.appendChild(row); mobVisible.push(row); });
            });
        }

        var mi = 0;
        while (mi < mobVisible.length) {
            var mEmp = mobVisible[mi].dataset.empresa;
            var mStartTd = mobVisible[mi].querySelector('.pvm-empresa');
            var mSpan = 1, mj = mi + 1;
            while (mj < mobVisible.length && mobVisible[mj].dataset.empresa === mEmp) {
                var mHideTd = mobVisible[mj].querySelector('.pvm-empresa');
                if (mHideTd) mHideTd.style.display = 'none';
                mSpan++; mj++;
            }
            if (mStartTd && mSpan > 1) mStartTd.setAttribute('rowspan', mSpan);
            mobVisible[mi].style.borderTop = '2px solid #adb5bd';
            mi = mj;
        }

        // Zebra striping por grupo de empresa (mobile) — alterna dentro do grupo
        (function() {
            var mEmpIdx = 0, mci = 0;
            while (mci < mobVisible.length) {
                var mce = mobVisible[mci].dataset.empresa;
                var baseOdd = (mEmpIdx % 2 === 0);
                var rowInGroup = 0;
                while (mci < mobVisible.length && mobVisible[mci].dataset.empresa === mce) {
                    mobVisible[mci].classList.remove('pv-zebra-odd', 'pv-zebra-even');
                    var isOdd = (rowInGroup % 2 === 0) ? baseOdd : !baseOdd;
                    mobVisible[mci].classList.add(isOdd ? 'pv-zebra-odd' : 'pv-zebra-even');
                    mci++; rowInGroup++;
                }
                mEmpIdx++;
            }
        })();

        // Atualizar label da variável no mobile (só quando não é orçamento/submeta)
        var varLabel = document.getElementById('planilhaVarLabel');
        var varLabelWrap = document.getElementById('planilhaVarLabelWrap');
        if (showVarCol) {
            if (varLabelWrap) varLabelWrap.style.display = 'none';
        } else if (varLabel && mobVisible.length > 0) {
            var vn = mobVisible[0].dataset.varname || '';
            varLabel.textContent = vn ? ('\u25B8 ' + vn) : '';
            if (varLabelWrap) varLabelWrap.style.display = vn ? '' : 'none';
        } else if (varLabelWrap) {
            varLabelWrap.style.display = 'none';
        }

        // Legenda K/M/MM (mobile, somente modo abreviado e não 7d)
        var legenda = document.getElementById('planilhaMobLegenda');
        if (legenda) {
            legenda.style.display = (!mobValorIntegral && !is7d) ? '' : 'none';
        }
        // Legenda K/M/MM (desktop, somente modo abreviado e não 7d)
        var legendaDesk = document.getElementById('planilhaDeskLegenda');
        if (legendaDesk) {
            legendaDesk.style.display = (!deskValorIntegral && !is7d) ? '' : 'none';
        }
    }

    document.querySelectorAll('.planilha-periodo-btn').forEach(function(btn) {
        btn.addEventListener('click', function() {
            periodoAtual = this.dataset.periodo;
            document.querySelectorAll('.planilha-periodo-btn').forEach(function(b) {
                b.classList.remove('active');
            });
            this.classList.add('active');
            atualizarPlanilha();
        });
    });

    document.querySelectorAll('.planilha-modelo-btn').forEach(function(btn) {
        btn.addEventListener('click', function() {
            modeloAtual = this.dataset.modelo;
            document.querySelectorAll('.planilha-modelo-btn').forEach(function(b) {
                b.classList.remove('active');
            });
            this.classList.add('active');
            // Auto-switch valores
            deskValorIntegral = (modeloAtual === 'submeta' || modeloAtual === 'orcamento');
            mobValorIntegral = deskValorIntegral;
            document.querySelectorAll('.planilha-valores-btn').forEach(function(b) {
                var esperado = deskValorIntegral ? 'integral' : 'abreviado';
                if (b.dataset.valores === esperado) {
                    b.classList.add('active');
                } else {
                    b.classList.remove('active');
                }
            });
            lastModo = null;
            atualizarPlanilha();
        });
    });

    // Filtro de Valores
    document.querySelectorAll('.planilha-valores-btn').forEach(function(btn) {
        btn.addEventListener('click', function() {
            deskValorIntegral = (this.dataset.valores === 'integral');
            mobValorIntegral = deskValorIntegral;
            document.querySelectorAll('.planilha-valores-btn').forEach(function(b) {
                b.classList.remove('active');
            });
            this.classList.add('active');
            atualizarPlanilha();
        });
    });

    atualizarPlanilha();
})();
</script>

<?php elseif ($visaoDashboard !== 'modelo'): ?>

<?php
// ========== RESUMO GERAL (4 CARDS COMPACTOS) ==========
// Detectar qual modelo ativo (usa a primeira Meta disponível como referência)
// ---- Computar dados de resumo por modelo (meta, submeta, orcamento) ----
$_modelosDisponiveis = ['meta', 'submeta', 'orcamento'];
$_resumoPorModelo = [];
foreach ($_modelosDisponiveis as $_mdl) {
    $_resMes = $visaoConsolidadaPorModelo[$_mdl]['mes'] ?? null;
    if (!$_resMes || ($_resMes['total_orc'] <= 0 && $_resMes['total_real'] <= 0)) continue;
    $r = [];
    $r['orc'] = $_resMes['total_orc'];
    $r['real'] = $_resMes['total_real'];
    $r['perc'] = $_resMes['perc_total'];
    $r['restante'] = max(0, $r['orc'] - $r['real']);
    $r['restPerc'] = ($r['orc'] > 0) ? ($r['restante'] / $r['orc']) : 0;
    $r['isOrc'] = ($_mdl === 'orcamento');
    // Projeção
    $r['projValor'] = 0;
    foreach ($kpisVariaveis as $_kv) {
        $_kvMod = strtolower(trim((string)($modeloPorVariavel[$_kv['id']] ?? 'orcamento')));
        if ($_kvMod === $_mdl) {
            $r['projValor'] += abs((float)($_kv['projMesValor'] ?? 0));
        }
    }
    $r['projPerc'] = ($r['orc'] > 0) ? ($r['projValor'] / $r['orc']) : 0;
    // Variação vs mês anterior
    $r['varPerc'] = null;
    foreach ($kpisVariaveis as $_kv) {
        $_kvMod = strtolower(trim((string)($modeloPorVariavel[$_kv['id']] ?? 'orcamento')));
        if ($_kvMod === $_mdl && $_kv['varMes'] !== null) {
            $r['varPerc'] = $_kv['varMes'];
            break;
        }
    }
    // Alertas por modelo (thresholds alinhados com obterClasseCorProjecao)
    $r['alertEstourada'] = 0;
    $r['alertAtencao'] = 0;
    $r['alertOk'] = 0;
    foreach ($kpisVariaveis as $_kv) {
        $_kvMod = strtolower(trim((string)($modeloPorVariavel[$_kv['id']] ?? 'orcamento')));
        if ($_kvMod !== $_mdl) continue;
        $_kvProjPerc = abs((float)($_kv['projMesPerc'] ?? 0));
        if ($_mdl === 'orcamento') {
            if ($_kvProjPerc > 0.90) { $r['alertEstourada']++; }
            elseif ($_kvProjPerc > 0.80) { $r['alertAtencao']++; }
            else { $r['alertOk']++; }
        } else {
            if ($_kvProjPerc < 0.95) { $r['alertEstourada']++; }
            elseif ($_kvProjPerc < 1.0) { $r['alertAtencao']++; }
            else { $r['alertOk']++; }
        }
    }
    $r['diffProjOrc'] = $r['projValor'] - $r['orc'];
    $r['diffProjOrcPerc'] = ($r['orc'] > 0) ? ($r['diffProjOrc'] / $r['orc']) : 0;
    $r['projAcima'] = $r['isOrc'] ? ($r['diffProjOrc'] > 0) : ($r['diffProjOrc'] >= 0);
    $r['porDia'] = ($diasRestantesMesCorrente > 0) ? ($r['restante'] / $diasRestantesMesCorrente) : 0;
    // Nomes das variáveis do modelo
    $r['nomes'] = [];
    foreach ($kpisVariaveis as $_kv) {
        $_kvMod = strtolower(trim((string)($modeloPorVariavel[$_kv['id']] ?? 'orcamento')));
        if ($_kvMod === $_mdl) {
            $r['nomes'][] = $_kv['nome'];
        }
    }
    $_resumoPorModelo[$_mdl] = $r;
}
// Modelo padrão (para tendência, empresa, etc.)
$_resumoModelo = 'meta';
if (!empty($metasCharts)) {
    $_resumoModelo = strtolower(trim((string)($modeloPorVariavel[$metasCharts[0]['id']] ?? 'meta')));
}
$_isOrcResumo = ($_resumoModelo === 'orcamento');

// Preparar variáveis ordenadas para strip de 7 dias
$_stripPorTipo = ['meta' => [], 'orcamento' => [], 'submeta' => [], 'resultado' => []];
foreach ($metasCharts as $_sm) {
    $_smNorm = strtolower(trim((string)($modeloPorVariavel[$_sm['id']] ?? 'meta')));
    if (isset($_stripPorTipo[$_smNorm])) {
        $_stripPorTipo[$_smNorm][] = $_sm;
    }
}
$_stripOrdenadas = array_merge(
    $_stripPorTipo['meta'],
    $_stripPorTipo['orcamento'],
    $_stripPorTipo['submeta'],
    $_stripPorTipo['resultado']
);

// Determinar qual modelo exibir por padrão (todos = meta)
$_modeloDefault = isset($_resumoPorModelo['meta']) ? 'meta' : array_key_first($_resumoPorModelo);
$_modeloLabelsResumo = ['meta' => 'Meta', 'submeta' => 'Submeta', 'orcamento' => 'Orçamento'];

if (!empty($_resumoPorModelo)):
?>
<div class="<?= $modoPercentual ? 'visao-percentual' : '' ?>">
<?php foreach ($_resumoPorModelo as $_mdlKey => $_r):
    $_mdlLabel = $_modeloLabelsResumo[$_mdlKey] ?? ucfirst($_mdlKey);
    $_mdlVisible = ($_mdlKey === $_modeloDefault) ? '' : 'display:none;';
?>
<!-- ==================== RESUMO RÁPIDO - <?= strtoupper($_mdlKey) ?> ==================== -->
<div class="resumo-modelo-bloco" data-modelo-resumo="<?= $_mdlKey ?>" style="<?= $_mdlVisible ?>">
<div class="resumo-cards-grid mb-3">
    <div class="resumo-modelo-indicador" data-modelo-todos-label>
        <i class="bi bi-info-circle"></i> Valores de: <strong><?= htmlspecialchars(implode(', ', $_r['nomes'] ?: [$_mdlLabel])) ?></strong>
    </div>
    <?php
    // Cores dinâmicas baseadas na PROJEÇÃO (thresholds de obterClasseCorProjecao)
    if ($_r['isOrc']) {
        $_corProj = ($_r['projPerc'] > 0.90) ? '#ef4444' : (($_r['projPerc'] > 0.80) ? '#f59e0b' : '#22c55e');
    } else {
        $_corProj = ($_r['projPerc'] >= 1.0) ? '#22c55e' : (($_r['projPerc'] >= 0.95) ? '#f59e0b' : '#ef4444');
    }
    $_corReal = $_corProj;
    $_iconRealCls = ($_corReal === '#22c55e') ? 'resumo-icon-green' : (($_corReal === '#f59e0b') ? 'resumo-icon-yellow' : 'resumo-icon-red');
    $_iconProjCls = $_iconRealCls;
    ?>
    <!-- Realizado -->
    <div class="resumo-card" style="border-left-color: <?= $_corReal ?>;">
        <div class="resumo-card-header">
            <span class="resumo-card-title"><?= $_r['isOrc'] ? 'Gasto Realizado' : 'Realizado' ?></span>
            <span class="resumo-card-icon-circle <?= $_iconRealCls ?>"><i class="bi bi-cash-stack"></i></span>
        </div>
        <div class="resumo-card-valor dado-valor" data-raw-value="<?= $_r['real'] ?>" data-mascara="<?= htmlspecialchars($mascaraPrincipal) ?>"><?= formatarValorDashboard($_r['real'], $mascaraPrincipal, $moeda) ?></div>
        <div class="resumo-card-sub"><?= formatarPercentDashboard($_r['perc']) ?> <?= $_r['isOrc'] ? 'consumido' : 'da meta' ?></div>
        <?php if ($_r['varPerc'] !== null): ?>
        <div class="resumo-card-var <?= $_r['varPerc'] >= 0 ? 'var-positivo' : 'var-negativo' ?>">
            <?= $_r['varPerc'] >= 0 ? '&uarr;' : '&darr;' ?> <?= ($_r['varPerc'] >= 0 ? '+' : '') . formatarPercentDashboard($_r['varPerc']) ?> vs ano ant.
        </div>
        <?php endif; ?>
    </div>
    <!-- A Realizar / Disponível -->
    <div class="resumo-card resumo-card-arealizar">
        <div class="resumo-card-header">
            <span class="resumo-card-title"><?= $_r['isOrc'] ? 'Disponível' : 'A Realizar' ?></span>
            <span class="resumo-card-icon-circle resumo-icon-blue"><i class="bi bi-clipboard-check"></i></span>
        </div>
        <div class="resumo-card-valor dado-valor" data-raw-value="<?= $_r['restante'] ?>" data-mascara="<?= htmlspecialchars($mascaraPrincipal) ?>"><?= formatarValorDashboard($_r['restante'], $mascaraPrincipal, $moeda) ?></div>
        <div class="resumo-card-sub"><?= formatarPercentDashboard($_r['restPerc']) ?> restante</div>
        <div class="resumo-card-var var-info dado-valor-line"><i class="bi bi-bar-chart-line"></i> <span class="dado-valor" data-raw-value="<?= $_r['porDia'] ?>" data-mascara="<?= htmlspecialchars($mascaraPrincipal) ?>"><?= formatarValorDashboard($_r['porDia'], $mascaraPrincipal, $moeda) ?></span>/dia</div>
        <div class="resumo-card-var var-info"><i class="bi bi-calendar3"></i> <?= $diasRestantesMesCorrente ?> dias restantes</div>
    </div>
    <!-- Projeção -->
    <div class="resumo-card" style="border-left-color: <?= $_corProj ?>;">
        <div class="resumo-card-header">
            <span class="resumo-card-title">Projeção</span>
            <span class="resumo-card-icon-circle <?= $_iconProjCls ?>"><i class="bi bi-graph-up-arrow"></i></span>
        </div>
        <div class="resumo-card-valor dado-valor" data-raw-value="<?= $_r['projValor'] ?>" data-mascara="<?= htmlspecialchars($mascaraPrincipal) ?>"><?= formatarValorDashboard($_r['projValor'], $mascaraPrincipal, $moeda) ?></div>
        <div class="resumo-card-sub"><?= formatarPercentDashboard($_r['projPerc']) ?> <?= $_r['isOrc'] ? 'do orçamento' : 'da meta' ?></div>
        <div class="resumo-card-var <?= $_r['projAcima'] ? ($_r['isOrc'] ? 'var-negativo' : 'var-positivo') : ($_r['isOrc'] ? 'var-positivo' : 'var-negativo') ?>">
            <?= $_r['projAcima'] ? '&uarr;' : '&darr;' ?> <?= formatarPercentDashboard(abs($_r['diffProjOrcPerc'])) ?> <?= $_r['diffProjOrc'] >= 0 ? 'acima' : 'abaixo' ?> do orçado
        </div>
    </div>
    <!-- Orçado -->
    <div class="resumo-card resumo-card-orcado">
        <div class="resumo-card-header">
            <span class="resumo-card-title"><?= $_r['isOrc'] ? 'Orçamento' : 'Orçado' ?></span>
            <span class="resumo-card-icon-circle resumo-icon-orange"><i class="bi bi-briefcase"></i></span>
        </div>
        <div class="resumo-card-valor dado-valor" data-raw-value="<?= $_r['orc'] ?>" data-mascara="<?= htmlspecialchars($mascaraPrincipal) ?>"><?= formatarValorDashboard($_r['orc'], $mascaraPrincipal, $moeda) ?></div>
        <div class="resumo-card-sub">100,0 % referência</div>
    </div>
</div>

<!-- ALERTAS - <?= strtoupper($_mdlKey) ?> -->
<?php if ($_r['alertEstourada'] > 0 || $_r['alertAtencao'] > 0 || $_r['alertOk'] > 0): ?>
<div class="alertas-destaques mb-3" style="display:none;">
    <div class="alertas-header">
        <span><i class="bi bi-bell"></i> Alertas e Destaques</span>
    </div>
    <div class="alertas-badges">
        <?php if ($_r['alertEstourada'] > 0): ?>
        <div class="alerta-badge alerta-vermelho" role="button" data-scroll-kpi>
            <i class="bi bi-exclamation-triangle-fill"></i>
            <div>
                <strong><?= $_r['alertEstourada'] ?> conta<?= $_r['alertEstourada'] > 1 ? 's' : '' ?> <?= $_r['isOrc'] ? 'estourada' . ($_r['alertEstourada'] > 1 ? 's' : '') : 'crítica' . ($_r['alertEstourada'] > 1 ? 's' : '') ?></strong>
                <small><?= $_r['isOrc'] ? 'Acima de 90%' : 'Projeção abaixo de 95%' ?></small>
            </div>
        </div>
        <?php endif; ?>
        <?php if ($_r['alertAtencao'] > 0): ?>
        <div class="alerta-badge alerta-amarelo" role="button" data-scroll-kpi>
            <i class="bi bi-exclamation-circle-fill"></i>
            <div>
                <strong><?= $_r['alertAtencao'] ?> conta<?= $_r['alertAtencao'] > 1 ? 's' : '' ?> em atenção</strong>
                <small><?= $_r['isOrc'] ? 'Entre 80% e 90%' : 'Entre 95% e 100%' ?></small>
            </div>
        </div>
        <?php endif; ?>
        <?php if ($_r['alertOk'] > 0): ?>
        <div class="alerta-badge alerta-verde" role="button" data-scroll-kpi>
            <i class="bi bi-check-circle-fill"></i>
            <div>
                <strong><?= $_r['alertOk'] ?> conta<?= $_r['alertOk'] > 1 ? 's' : '' ?> no esperado</strong>
                <small>Dentro da <?= $_r['isOrc'] ? 'previsão' : 'meta' ?></small>
            </div>
        </div>
        <?php endif; ?>
    </div>
</div>
<?php endif; ?>
</div><!-- /resumo-modelo-bloco <?= $_mdlKey ?> -->
<?php endforeach; ?>

<!-- ALERTAS CONSOLIDADOS (visível apenas em Todos) -->
<?php
$_alertTodosEstourada = 0;
$_alertTodosAtencao = 0;
$_alertTodosOk = 0;
foreach ($_resumoPorModelo as $_atk => $_atv) {
    $_alertTodosEstourada += $_atv['alertEstourada'];
    $_alertTodosAtencao += $_atv['alertAtencao'];
    $_alertTodosOk += $_atv['alertOk'];
}
?>
<?php if ($_alertTodosEstourada > 0 || $_alertTodosAtencao > 0 || $_alertTodosOk > 0): ?>
<div class="alertas-destaques alertas-todos mb-3">
    <div class="alertas-header">
        <span><i class="bi bi-bell"></i> Alertas e Destaques</span>
    </div>
    <div class="alertas-badges">
        <?php if ($_alertTodosEstourada > 0): ?>
        <div class="alerta-badge alerta-vermelho" role="button" data-scroll-kpi>
            <i class="bi bi-exclamation-triangle-fill"></i>
            <div>
                <strong><?= $_alertTodosEstourada ?> conta<?= $_alertTodosEstourada > 1 ? 's' : '' ?> crítica<?= $_alertTodosEstourada > 1 ? 's' : '' ?></strong>
                <small>Projeção fora do esperado</small>
            </div>
        </div>
        <?php endif; ?>
        <?php if ($_alertTodosAtencao > 0): ?>
        <div class="alerta-badge alerta-amarelo" role="button" data-scroll-kpi>
            <i class="bi bi-exclamation-circle-fill"></i>
            <div>
                <strong><?= $_alertTodosAtencao ?> conta<?= $_alertTodosAtencao > 1 ? 's' : '' ?> em atenção</strong>
                <small>Risco de fechar fora</small>
            </div>
        </div>
        <?php endif; ?>
        <?php if ($_alertTodosOk > 0): ?>
        <div class="alerta-badge alerta-verde" role="button" data-scroll-kpi>
            <i class="bi bi-check-circle-fill"></i>
            <div>
                <strong><?= $_alertTodosOk ?> conta<?= $_alertTodosOk > 1 ? 's' : '' ?> no esperado</strong>
                <small>Parabéns! Está dentro do planejado.</small>
            </div>
        </div>
        <?php endif; ?>
    </div>
</div>
<?php endif; ?>
<?php endif; ?>

<!-- ==================== ÚLTIMOS 7 DIAS (scroll horizontal) ==================== -->
<?php if (!empty($_stripOrdenadas)): ?>
<div class="ultimos7-scroll-wrap mb-3">
    <div class="ultimos7-scroll-inner">
        <?php foreach ($_stripOrdenadas as $_sv):
            $_svModelo = strtolower(trim((string)($modeloPorVariavel[$_sv['id']] ?? 'meta')));
            $_svMascara = $mascaraPorVariavel[$_sv['id']] ?? 'moeda';
            $_svDias = $_sv['diasHistorico'] ?? [];
            if (empty($_svDias)) continue;

            // Badge class
            $_svBadgeCls = match ($_svModelo) {
                'submeta' => 'bg-success',
                'resultado' => 'bg-secondary',
                'orcamento' => 'bg-info',
                default => 'bg-primary',
            };
        ?>
        <div class="ultimos7-card" data-modelo-card="<?= htmlspecialchars($_svModelo) ?>">
            <div class="ultimos7-card-header">
                <span class="ultimos7-card-nome"><?= htmlspecialchars($_sv['nome']) ?></span>
                <span class="badge <?= $_svBadgeCls ?> ultimos7-card-badge"><?= ucfirst($_svModelo) ?></span>
            </div>
            <div class="ultimos7-dias-row">
                <?php
                $diasSemanaAbrev = ['seg','ter','qua','qui','sex','sab','dom'];
                $_svObk = $_sv['origemBreakdownStrip'] ?? null;
                foreach ($_svDias as $_svDia => $_svVal):
                    $_svDtObj = DateTime::createFromFormat('Y-m-d', $_svDia);
                    if ($_svDtObj) {
                        $_svDiaSem = $diasSemanaAbrev[((int)$_svDtObj->format('N')) - 1];
                        $_svDiaNum = (int)$_svDtObj->format('j');
                        $_svDiaMes = str_pad((int)$_svDtObj->format('n'), 2, '0', STR_PAD_LEFT);
                    } else {
                        $_svDiaSem = '-';
                        $_svDiaNum = 0;
                        $_svDiaMes = '00';
                    }
                    // Meta diária por dia
                    $_svDParts = explode('-', $_svDia);
                    $_svMetaDia = calcularMetaDiaria((float)$_sv['orcMes'], (int)($_svDParts[2] ?? 1), (int)($_svDParts[1] ?? $mesCorrente), (int)($_svDParts[0] ?? $anoCorrente), $usarPesoDia);
                    $_svPercDia = ($_svMetaDia > 0) ? ($_svVal / $_svMetaDia) : 0;
                    $_svClsDia = ($_svPercDia >= 1.0) ? 'u7-ok' : (($_svPercDia >= 0.5) ? 'u7-warn' : 'u7-danger');
                    $_svIsHoje = ($_svDia === $hojeStr6h);
                    $_svTemBreakdown = ($_svIsHoje && $_svObk);
                ?>
                <div class="ultimos7-dia-cell<?= $_svTemBreakdown ? ' u7-has-breakdown' : '' ?>"<?= $_svTemBreakdown ? ' onclick="this.querySelector(\'.u7-breakdown\').style.display=this.querySelector(\'.u7-breakdown\').style.display===\'none\'?\'block\':\'none\'"' : '' ?>>
                    <div class="u7-dia-label"><?= $_svDiaSem ?> <?= $_svDiaNum ?>/<?= $_svDiaMes ?></div>
                    <?php $_svValDisplay = ($_svModelo === 'orcamento') ? abs($_svVal) : $_svVal; ?>
                    <?php if ($_svModelo !== 'orcamento'): ?>
                    <div class="u7-dia-valor dado-valor" data-raw-value="<?= $_svValDisplay ?>" data-mascara="<?= htmlspecialchars($_svMascara) ?>"><?= formatarValorDashboard($_svValDisplay, $_svMascara, $moeda) ?></div>
                    <?php else: ?>
                    <div class="u7-dia-valor dado-valor" data-raw-value="<?= $_svValDisplay ?>" data-mascara="<?= htmlspecialchars($_svMascara) ?>"><?= formatarValorDashboard($_svValDisplay, $_svMascara, $moeda) ?></div>
                    <?php endif; ?>
                    <div class="u7-dia-perc <?= $_svClsDia ?>"><?= formatarPercentDashboard($_svPercDia) ?></div>
                    <?php
                        $_svDeltaDia = max(0, 1 - $_svPercDia);
                        if ($_svDeltaDia > 0):
                            $_svDeltaFmt = number_format($_svDeltaDia * 100, 1, ',', '.');
                    ?>
                    <div class="u7-dia-delta">-<?= $_svDeltaFmt ?>%</div>
                    <?php else: ?>
                    <div class="u7-dia-delta" style="color:#16a34a">&#10003;</div>
                    <?php endif; ?>
                    <?php if ($_svTemBreakdown): ?>
                    <div class="u7-breakdown" style="display:none">
                        <div class="u7-bk-row"><span class="u7-bk-label">Fechadas</span><span class="u7-bk-val dado-valor" data-raw-value="<?= $_svObk['f'] ?>" data-mascara="<?= htmlspecialchars($_svMascara) ?>"><?= formatarValorDashboard($_svObk['f'], $_svMascara, $moeda) ?></span></div>
                        <div class="u7-bk-row"><span class="u7-bk-label" style="color:#0d6efd"><?= htmlspecialchars($_svObk['on']) ?></span><span class="u7-bk-val dado-valor" data-raw-value="<?= $_svObk['a'] ?>" data-mascara="<?= htmlspecialchars($_svMascara) ?>" style="color:#0d6efd;font-weight:600"><?= formatarValorDashboard($_svObk['a'], $_svMascara, $moeda) ?></span></div>
                        <hr style="margin:2px 0">
                        <div class="u7-bk-row"><span class="u7-bk-label" style="font-weight:700">Total</span><span class="u7-bk-val dado-valor" data-raw-value="<?= $_svValDisplay ?>" data-mascara="<?= htmlspecialchars($_svMascara) ?>" style="font-weight:700"><?= formatarValorDashboard($_svValDisplay, $_svMascara, $moeda) ?></span></div>
                    </div>
                    <?php endif; ?>
                </div>
                <?php endforeach; ?>
            </div>
        </div>
        <?php endforeach; ?>
    </div>
</div>
<?php endif; ?>

<!-- ==================== TENDÊNCIA ==================== -->
<?php
// Computar tendência para cada modelo disponível
$_tendPorModelo = [];
$_tendTrimBase = (int)ceil($mesCorrente / 3);
$_tendTrimMesInicio = (($_tendTrimBase - 1) * 3) + 1;
$_tendTrimMesFim    = $_tendTrimBase * 3;
$_tendSubMes  = htmlspecialchars($nomeMesAtual) . ' ' . $anoCorrente . ' &middot; Dia ' . $diaHoje . ' de ' . $ultimoDia;
$_tendSubTrim = htmlspecialchars($nomesMes[$_tendTrimMesInicio - 1] ?? '') . ' a ' . htmlspecialchars($nomesMes[$_tendTrimMesFim - 1] ?? '') . ' ' . $anoCorrente;
$_tendSubAno  = 'Jan a Dez ' . $anoCorrente;

foreach ($_resumoPorModelo as $_tmdl => $_tData) {
    // Contas deste modelo
    $_tContas = [];
    foreach ($kpisVariaveis as $_kv) {
        $_kvMod = strtolower(trim((string)($modeloPorVariavel[$_kv['id']] ?? 'orcamento')));
        if ($_kvMod === $_tmdl && isset($contasPorVariavel[(int)$_kv['id']])) {
            foreach ($contasPorVariavel[(int)$_kv['id']] as $_cid) {
                $_tContas[$_cid] = true;
            }
        }
    }
    $_tOrc = $_tData['orc'];

    // ---- Mês: diário ----
    $_mL = []; $_mR = []; $_mO = []; $_mP = [];
    $_acR = 0.0; $_acO = 0.0;
    for ($d = 1; $d <= $ultimoDia; $d++) {
        $_mL[] = $d;
        $valDia = 0.0;
        foreach ($_tContas as $_cid => $_) {
            $valDia += (float)($mapContaDiaMesAtual[$_cid][$d] ?? 0);
        }
        $_acR += $valDia;
        $_mR[] = ($d <= $diaHoje) ? round($_acR, 2) : null;
        $_acO += calcularMetaDiaria((float)$_tOrc, $d, $mesCorrente, $anoCorrente, $usarPesoDia);
        $_mO[] = round($_acO, 2);
    }
    $_pBase = ($diaHoje >= 1 && $diaHoje <= $ultimoDia) ? ($_mR[$diaHoje - 1] ?? 0) : 0;
    $_mAvg  = ($diaHoje > 0) ? ($_pBase / $diaHoje) : 0;
    for ($d = 1; $d <= $ultimoDia; $d++) {
        if ($d < $diaHoje) $_mP[] = null;
        elseif ($d == $diaHoje) $_mP[] = round((float)$_pBase, 2);
        else $_mP[] = round($_pBase + $_mAvg * ($d - $diaHoje), 2);
    }

    // ---- Trimestre: mensal ----
    $_trL = []; $_trR = []; $_trO = []; $_trP = [];
    $_acRT = 0.0; $_acOT = 0.0;
    for ($m = $_tendTrimMesInicio; $m <= $_tendTrimMesFim; $m++) {
        $_trL[] = $nomesMes[$m - 1] ?? ('M' . $m);
        $rM = 0.0; $oM = 0.0;
        foreach ($_tContas as $_cid => $_) {
            $rM += (float)($valoresRealizadosMensais[$m][$_cid] ?? 0);
            $oM += (float)($valoresOrcadosMensais[$m][$_cid] ?? 0);
        }
        $_acRT += $rM; $_acOT += $oM;
        $_trR[] = ($m <= $mesCorrente) ? round($_acRT, 2) : null;
        $_trO[] = round($_acOT, 2);
    }
    $_trIdx = $mesCorrente - $_tendTrimMesInicio;
    $_trPB  = ($_trIdx >= 0 && $_trIdx < count($_trR)) ? ($_trR[$_trIdx] ?? 0) : 0;
    $_trMA  = ($mesCorrente >= $_tendTrimMesInicio) ? ($_trPB / ($mesCorrente - $_tendTrimMesInicio + 1)) : 0;
    for ($m = $_tendTrimMesInicio; $m <= $_tendTrimMesFim; $m++) {
        if ($m < $mesCorrente) $_trP[] = null;
        elseif ($m == $mesCorrente) $_trP[] = round((float)$_trPB, 2);
        else $_trP[] = round($_trPB + $_trMA * ($m - $mesCorrente), 2);
    }

    // ---- Ano: mensal ----
    $_aL = []; $_aR = []; $_aO = []; $_aP = [];
    $_acRA = 0.0; $_acOA = 0.0;
    for ($m = 1; $m <= 12; $m++) {
        $_aL[] = $nomesMes[$m - 1] ?? ('M' . $m);
        $rM = 0.0; $oM = 0.0;
        foreach ($_tContas as $_cid => $_) {
            $rM += (float)($valoresRealizadosMensais[$m][$_cid] ?? 0);
            $oM += (float)($valoresOrcadosMensais[$m][$_cid] ?? 0);
        }
        $_acRA += $rM; $_acOA += $oM;
        $_aR[] = ($m <= $mesCorrente) ? round($_acRA, 2) : null;
        $_aO[] = round($_acOA, 2);
    }
    $_aPB = ($mesCorrente >= 1) ? ($_aR[$mesCorrente - 1] ?? 0) : 0;
    $_aMA = ($mesCorrente > 0) ? ($_aPB / $mesCorrente) : 0;
    for ($m = 1; $m <= 12; $m++) {
        if ($m < $mesCorrente) $_aP[] = null;
        elseif ($m == $mesCorrente) $_aP[] = round((float)$_aPB, 2);
        else $_aP[] = round($_aPB + $_aMA * ($m - $mesCorrente), 2);
    }

    // Para orçamento, converter todos os valores para positivo (débitos são negativos no BD)
    if ($_tmdl === 'orcamento') {
        $_absMap = function($v) { return ($v === null) ? null : round(abs($v), 2); };
        $_mR = array_map($_absMap, $_mR);
        $_mO = array_map($_absMap, $_mO);
        $_mP = array_map($_absMap, $_mP);
        $_trR = array_map($_absMap, $_trR);
        $_trO = array_map($_absMap, $_trO);
        $_trP = array_map($_absMap, $_trP);
        $_aR = array_map($_absMap, $_aR);
        $_aO = array_map($_absMap, $_aO);
        $_aP = array_map($_absMap, $_aP);
    }

    $_tendPorModelo[$_tmdl] = [
        'mes' => ['labels' => $_mL, 'realizado' => $_mR, 'orcado' => $_mO, 'projecao' => $_mP],
        'trimestre' => ['labels' => $_trL, 'realizado' => $_trR, 'orcado' => $_trO, 'projecao' => $_trP],
        'ano' => ['labels' => $_aL, 'realizado' => $_aR, 'orcado' => $_aO, 'projecao' => $_aP],
    ];

    // ---- Per-company trend lines (only when multi-empresa) ----
    if (count($empresasParaDadosDias) > 1) {
        $_tendEmpresasMdl = [];
        foreach ($empresasParaDadosDias as $_empId) {
            $_empId = (int)$_empId;
            $_empMap = $mapContaDiaMesAtualPorEmpresa[$_empId] ?? [];
            $_empNome = $mapNomeEmpresa[$_empId] ?? ('Empresa ' . $_empId);

            // Orçado mensal desta empresa para este modelo
            $_empOrcMes = 0.0;
            foreach (($visaoConsolidadaEmpresas ?? []) as $_empBk) {
                if ((int)($_empBk['cdempresa'] ?? 0) === $_empId) {
                    $_empOrcMes = (float)($_empBk['modelos'][$_tmdl]['mes']['total_orc'] ?? 0);
                    break;
                }
            }

            // Mês: diário cumulativo por empresa
            $_emR = []; $_emO = []; $_emP = [];
            $_eAcR = 0.0; $_eAcO = 0.0;
            for ($d = 1; $d <= $ultimoDia; $d++) {
                $vd = 0.0;
                foreach ($_tContas as $_cid => $_) {
                    $vd += (float)($_empMap[$_cid][$d] ?? 0);
                }
                $_eAcR += $vd;
                $_emR[] = ($d <= $diaHoje) ? round($_eAcR, 2) : null;
                $_eAcO += calcularMetaDiaria((float)$_empOrcMes, $d, $mesCorrente, $anoCorrente, $usarPesoDia);
                $_emO[] = round($_eAcO, 2);
            }
            $_ePB = ($diaHoje >= 1 && $diaHoje <= $ultimoDia) ? ($_emR[$diaHoje - 1] ?? 0) : 0;
            $_eAvg = ($diaHoje > 0) ? ($_ePB / $diaHoje) : 0;
            for ($d = 1; $d <= $ultimoDia; $d++) {
                if ($d < $diaHoje) $_emP[] = null;
                elseif ($d == $diaHoje) $_emP[] = round((float)$_ePB, 2);
                else $_emP[] = round($_ePB + $_eAvg * ($d - $diaHoje), 2);
            }

            // Trimestre: mensal cumulativo por empresa
            $_etrR = []; $_etrO = []; $_etrP = [];
            $_eAcRT = 0.0; $_eAcOT = 0.0;
            $_empRealM = $valRealizadosMensaisEmp[$_empId] ?? [];
            $_empOrcM  = $valOrcadosMensaisEmp[$_empId] ?? [];
            for ($m = $_tendTrimMesInicio; $m <= $_tendTrimMesFim; $m++) {
                $rM = 0.0; $oM = 0.0;
                foreach ($_tContas as $_cid => $_) {
                    $rM += (float)($_empRealM[$m][$_cid] ?? 0);
                    $oM += (float)($_empOrcM[$m][$_cid] ?? 0);
                }
                $_eAcRT += $rM; $_eAcOT += $oM;
                $_etrR[] = ($m <= $mesCorrente) ? round($_eAcRT, 2) : null;
                $_etrO[] = round($_eAcOT, 2);
            }
            $_etrIdx = $mesCorrente - $_tendTrimMesInicio;
            $_etrPB = ($_etrIdx >= 0 && $_etrIdx < count($_etrR)) ? ($_etrR[$_etrIdx] ?? 0) : 0;
            $_etrMA = ($mesCorrente >= $_tendTrimMesInicio) ? ($_etrPB / ($mesCorrente - $_tendTrimMesInicio + 1)) : 0;
            for ($m = $_tendTrimMesInicio; $m <= $_tendTrimMesFim; $m++) {
                if ($m < $mesCorrente) $_etrP[] = null;
                elseif ($m == $mesCorrente) $_etrP[] = round((float)$_etrPB, 2);
                else $_etrP[] = round($_etrPB + $_etrMA * ($m - $mesCorrente), 2);
            }

            // Ano: mensal cumulativo por empresa
            $_eaR = []; $_eaO = []; $_eaP = [];
            $_eAcRA = 0.0; $_eAcOA = 0.0;
            for ($m = 1; $m <= 12; $m++) {
                $rM = 0.0; $oM = 0.0;
                foreach ($_tContas as $_cid => $_) {
                    $rM += (float)($_empRealM[$m][$_cid] ?? 0);
                    $oM += (float)($_empOrcM[$m][$_cid] ?? 0);
                }
                $_eAcRA += $rM; $_eAcOA += $oM;
                $_eaR[] = ($m <= $mesCorrente) ? round($_eAcRA, 2) : null;
                $_eaO[] = round($_eAcOA, 2);
            }
            $_eaPB = ($mesCorrente >= 1) ? ($_eaR[$mesCorrente - 1] ?? 0) : 0;
            $_eaMA = ($mesCorrente > 0) ? ($_eaPB / $mesCorrente) : 0;
            for ($m = 1; $m <= 12; $m++) {
                if ($m < $mesCorrente) $_eaP[] = null;
                elseif ($m == $mesCorrente) $_eaP[] = round((float)$_eaPB, 2);
                else $_eaP[] = round($_eaPB + $_eaMA * ($m - $mesCorrente), 2);
            }

            // Para orçamento, abs()
            if ($_tmdl === 'orcamento') {
                $_absMap2 = function($v) { return ($v === null) ? null : round(abs($v), 2); };
                $_emR = array_map($_absMap2, $_emR); $_emO = array_map($_absMap2, $_emO); $_emP = array_map($_absMap2, $_emP);
                $_etrR = array_map($_absMap2, $_etrR); $_etrO = array_map($_absMap2, $_etrO); $_etrP = array_map($_absMap2, $_etrP);
                $_eaR = array_map($_absMap2, $_eaR); $_eaO = array_map($_absMap2, $_eaO); $_eaP = array_map($_absMap2, $_eaP);
            }

            $_tendEmpresasMdl[] = [
                'cdempresa' => $_empId,
                'dsempresa' => $_empNome,
                'mes' => ['realizado' => $_emR, 'orcado' => $_emO, 'projecao' => $_emP],
                'trimestre' => ['realizado' => $_etrR, 'orcado' => $_etrO, 'projecao' => $_etrP],
                'ano' => ['realizado' => $_eaR, 'orcado' => $_eaO, 'projecao' => $_eaP],
            ];
        }
        $_tendPorModelo[$_tmdl]['empresas'] = $_tendEmpresasMdl;
    }
}
// Manter variáveis para compatibilidade (modelo padrão)
$_tendDefault = $_tendPorModelo[$_modeloDefault] ?? reset($_tendPorModelo) ?: [];
$_tendMesLabels = $_tendDefault['mes']['labels'] ?? [];
$_tendMesRealizado = $_tendDefault['mes']['realizado'] ?? [];
$_tendMesOrcado = $_tendDefault['mes']['orcado'] ?? [];
$_tendMesProjecao = $_tendDefault['mes']['projecao'] ?? [];
$_rOrc = $_resumoPorModelo[$_modeloDefault]['orc'] ?? 0;
$_tendTemEmpresas = !empty($_tendPorModelo[$_modeloDefault]['empresas'] ?? []);
?>
<div class="tendencia-card mb-3">
    <div class="tendencia-header">
        <span class="tendencia-titulo"><i class="bi bi-graph-up"></i> Tendência</span>
        <div class="tendencia-controls">
            <?php if ($_tendTemEmpresas): ?>
            <div class="tendencia-toggle tendencia-modo-toggle" role="group" aria-label="Modo da tendência">
                <button type="button" class="tendencia-periodo-btn active" data-tend-modo="consolidado">Consolidado</button>
                <button type="button" class="tendencia-periodo-btn" data-tend-modo="empresas">Por Empresa</button>
            </div>
            <?php endif; ?>
            <div class="tendencia-toggle" role="group" aria-label="Período da tendência">
                <button type="button" class="tendencia-periodo-btn active" data-tend-periodo="mes">Mês</button>
                <button type="button" class="tendencia-periodo-btn" data-tend-periodo="trimestre">Trimestre</button>
                <button type="button" class="tendencia-periodo-btn" data-tend-periodo="ano">Ano</button>
            </div>
        </div>
    </div>
    <div class="tendencia-subtitulo-wrap">
        <span class="tendencia-subtitulo" id="tendenciaSubtitulo"><?= $_tendSubMes ?></span>
    </div>
    <div class="tendencia-chart-wrap">
        <canvas id="chartTendencia"></canvas>
    </div>
</div>

<!-- ==================== DESEMPENHO POR EMPRESA ==================== -->
<?php
$_empCoresTend = ['#3b82f6','#ef4444','#f59e0b','#10b981','#8b5cf6','#ec4899','#06b6d4','#f97316','#6366f1','#14b8a6'];
// Coleta todos os modelos que possuem empresas (>1) para o carousel
$_empModelosDisponiveis = [];
foreach (['meta','submeta','resultado','orcamento'] as $_emk) {
    $_emkArr = $dashboardConsolidadoComparativo[$_emk]['mes']['empresas'] ?? [];
    if (!empty($_emkArr) && count($_emkArr) > 1) {
        usort($_emkArr, fn($a, $b) => $b['perc_total'] <=> $a['perc_total']);
        $_empModelosDisponiveis[$_emk] = $_emkArr;
    }
}
if (!empty($_empModelosDisponiveis)):
?>
<div class="empresa-desempenho mb-3">
    <div class="empresa-desempenho-header">
        <div>
            <span class="empresa-desempenho-titulo"><i class="bi bi-bar-chart-line"></i> Desempenho por Empresa</span>
            <small class="empresa-desempenho-sub">Ordenado por % Realizado</small>
        </div>
        <a href="<?= htmlspecialchars(urlComVisaoDashboard('planilha')) ?>" class="empresa-desempenho-link">Ver planilha <i class="bi bi-arrow-right"></i></a>
    </div>
    <!-- Legenda de cores do gráfico de tendência -->
    <div class="empresa-desempenho-legenda">
        <span class="ed-leg-item"><span class="ed-leg-dot" style="background:#f97316;"></span> Orçado</span>
        <span class="ed-leg-item"><span class="ed-leg-dot" style="background:#22c55e;"></span> Realizado</span>
        <span class="ed-leg-item"><span class="ed-leg-dot" style="background:#8b5cf6;"></span> Projetado</span>
    </div>
    <?php foreach ($_empModelosDisponiveis as $_emkModelo => $_emkEmpresas):
        $_emkIsOrc = ($_emkModelo === 'orcamento');
        $_emkLabel = ucfirst($_emkModelo);
        $_emkVisible = ($_emkModelo === $_resumoModelo) ? '' : 'display:none;';
        // Map de vars por empresa para detalhe expandível
        $_empVarsPorEmpresa = [];
        foreach (($visaoConsolidadaEmpresas ?? []) as $_empBk) {
            $_eid = (int)($_empBk['cdempresa'] ?? 0);
            $_empVarsPorEmpresa[$_eid] = $_empBk['modelos'][$_emkModelo]['mes']['vars'] ?? [];
        }
        // Map empresa → cor
        $_empCorMap = [];
        $_tendEmpOrder = $_tendPorModelo[$_emkModelo]['empresas'] ?? ($_tendPorModelo[$_resumoModelo]['empresas'] ?? []);
        foreach ($_tendEmpOrder as $_tei => $_teData) {
            $_empCorMap[(int)$_teData['cdempresa']] = $_empCoresTend[$_tei % count($_empCoresTend)];
        }
    ?>
    <div class="emp-modelo-bloco" data-emp-modelo="<?= $_emkModelo ?>" style="<?= $_emkVisible ?>">
    <div class="empresa-desempenho-lista">
        <?php foreach ($_emkEmpresas as $_ei => $_emp):
            $_empPerc = ($_emp['perc_total'] ?? 0) * 100;
            $_empPercClamped = min(100, max(0, $_empPerc));
            $_empBarColor = $_empPerc >= 100 ? '#22c55e' : ($_empPerc >= 80 ? '#22c55e' : ($_empPerc >= 60 ? '#f59e0b' : '#ef4444'));
            if ($_emkIsOrc) {
                $_empBarColor = $_empPerc >= 100 ? '#ef4444' : ($_empPerc >= 90 ? '#f59e0b' : '#22c55e');
            }
            $_empIdDesemp = (int)($_emp['cdempresa'] ?? 0);
            $_empCor = $_empCorMap[$_empIdDesemp] ?? '#64748b';
            $_empVars = $_empVarsPorEmpresa[$_empIdDesemp] ?? [];
            $_empProjTotal = $_emp['proj_total'] ?? null;
        ?>
        <div class="empresa-desempenho-item" data-modelo-card="<?= htmlspecialchars($_emkModelo) ?>">
            <div class="empresa-item-top" onclick="this.closest('.empresa-desempenho-item').classList.toggle('ed-expanded')" style="cursor:pointer;">
                <div class="empresa-item-info">
                    <span class="empresa-item-pos" style="background:<?= $_empCor ?>;color:#fff;"><?= $_ei + 1 ?></span>
                    <span class="empresa-item-nome"><?= htmlspecialchars($_emp['dsempresa'] ?? '') ?></span>
                    <span class="kpi-lista-badge kpi-badge-<?= htmlspecialchars($_emkModelo) ?>"><?= htmlspecialchars($_emkLabel) ?></span>
                </div>
                <div class="d-flex align-items-center gap-2">
                    <div class="empresa-item-perc" style="color: <?= $_empBarColor ?>;"><?= number_format($_empPerc, 1, ',', '.') ?>%</div>
                    <i class="bi bi-chevron-down ed-chevron"></i>
                </div>
            </div>
            <div class="empresa-item-bar-wrapper">
                <div class="empresa-item-bar" style="width: <?= number_format($_empPercClamped, 1) ?>%; background: <?= $_empBarColor ?>;"></div>
            </div>
            <!-- Legenda rápida (Orçado / Realizado / Projetado) -->
            <div class="empresa-item-resumo dado-valor">
                <span><span class="ed-leg-dot ed-leg-dot-sm" style="background:#f97316;"></span> <span class="dado-valor" data-raw-value="<?= abs($_emp['total_orc']) ?>" data-mascara="<?= htmlspecialchars($mascaraPrincipal) ?>"><?= formatarValorDashboard(abs($_emp['total_orc']), $mascaraPrincipal, $moeda) ?></span></span>
                <span><span class="ed-leg-dot ed-leg-dot-sm" style="background:#22c55e;"></span> <span class="dado-valor" data-raw-value="<?= abs($_emp['total_real']) ?>" data-mascara="<?= htmlspecialchars($mascaraPrincipal) ?>"><?= formatarValorDashboard(abs($_emp['total_real']), $mascaraPrincipal, $moeda) ?></span></span>
                <?php if (($_emp['proj_total'] ?? null) !== null): ?>
                <span><span class="ed-leg-dot ed-leg-dot-sm" style="background:#8b5cf6;"></span> <span class="dado-valor" data-raw-value="<?= abs($_emp['proj_total']) ?>" data-mascara="<?= htmlspecialchars($mascaraPrincipal) ?>"><?= formatarValorDashboard(abs($_emp['proj_total']), $mascaraPrincipal, $moeda) ?></span></span>
                <?php endif; ?>
            </div>
            <!-- Cards KPI da empresa (expandível) -->
            <?php
                $_empOrc  = abs($_emp['total_orc']);
                $_empReal = abs($_emp['total_real']);
                $_empRestante = max(0, $_empOrc - $_empReal);
                $_empPercVal = $_empPerc;
                $_empRestantePerc = max(0, 100 - $_empPercVal);
                $_empMediaDiaria = ($diasRestantesMesCorrente > 0) ? ($_empRestante / $diasRestantesMesCorrente) : 0;
                $_empProjVal = ($_empProjTotal !== null) ? abs($_empProjTotal) : null;
                $_empProjPerc = ($_emp['proj_perc'] !== null) ? abs($_emp['proj_perc']) * 100 : null;
                $_empClasseCor = obterClasseCorProjecao($_empPercVal / 100, $_emkModelo);
                $_empProjClasseCor = ($_empProjPerc !== null) ? obterClasseCorProjecao($_empProjPerc / 100, $_emkModelo) : $_empClasseCor;
            ?>
            <div class="empresa-item-detalhe">
                <div class="ed-cards-grid">
                    <!-- META -->
                    <div class="ed-card">
                        <div class="ed-card-label"><?= $_emkIsOrc ? 'ORÇAMENTO' : 'META' ?></div>
                        <div class="ed-card-value dado-valor" data-raw-value="<?= $_empOrc ?>" data-mascara="<?= htmlspecialchars($mascaraPrincipal) ?>"><?= formatarValorDashboard($_empOrc, $mascaraPrincipal, $moeda) ?></div>
                        <div class="ed-card-sub"><?= $_emkIsOrc ? 'Orçamento do mês' : 'Meta do mês' ?></div>
                    </div>
                    <!-- REALIZADO -->
                    <div class="ed-card">
                        <div class="ed-card-label">REALIZADO</div>
                        <div class="ed-card-value-line">
                            <span class="ed-card-value dado-valor" data-raw-value="<?= $_empReal ?>" data-mascara="<?= htmlspecialchars($mascaraPrincipal) ?>"><?= formatarValorDashboard($_empReal, $mascaraPrincipal, $moeda) ?></span>
                            <span class="ed-card-perc <?= $_empClasseCor ?>"><?= formatarPercentDashboard($_empPercVal) ?></span>
                        </div>
                        <div class="ed-card-sub">Valor já realizado</div>
                    </div>
                    <!-- A REALIZAR -->
                    <div class="ed-card">
                        <div class="ed-card-label"><?= $_emkIsOrc ? 'SALDO' : 'A REALIZAR' ?></div>
                        <div class="ed-card-value dado-valor <?= $_emkIsOrc ? ($_empRestantePerc > 10 ? 'text-success' : 'text-danger') : '' ?>" data-raw-value="<?= $_empRestante ?>" data-mascara="<?= htmlspecialchars($mascaraPrincipal) ?>"><?= formatarValorDashboard($_empRestante, $mascaraPrincipal, $moeda) ?></div>
                        <div class="ed-card-sub"><?= $_emkIsOrc ? 'Saldo disponível' : 'Saldo a realizar' ?></div>
                    </div>
                    <!-- MÉDIA DIÁRIA PARA META -->
                    <div class="ed-card">
                        <div class="ed-card-label"><?= $_emkIsOrc ? 'GASTO DIÁRIO' : 'MÉDIA DIÁRIA P/ META' ?></div>
                        <div class="ed-card-value dado-valor" data-raw-value="<?= $_empMediaDiaria ?>" data-mascara="<?= htmlspecialchars($mascaraPrincipal) ?>"><?= formatarValorDashboard($_empMediaDiaria, $mascaraPrincipal, $moeda) ?></div>
                        <div class="ed-card-sub"><?= $_emkIsOrc ? 'Máximo por dia' : 'Por dia' ?> (<?= $diasRestantesMesCorrente ?> dias)</div>
                    </div>
                    <?php if ($_empProjVal !== null): ?>
                    <!-- PROJEÇÃO -->
                    <div class="ed-card">
                        <div class="ed-card-label">PROJEÇÃO</div>
                        <div class="ed-card-value dado-valor <?= $_empProjClasseCor ?>" data-raw-value="<?= $_empProjVal ?>" data-mascara="<?= htmlspecialchars($mascaraPrincipal) ?>"><?= formatarValorDashboard($_empProjVal, $mascaraPrincipal, $moeda) ?></div>
                        <div class="ed-card-sub">Expectativa (<span class="<?= $_empProjClasseCor ?>"><?= $_empProjPerc !== null ? formatarPercentDashboard($_empProjPerc) : '-' ?></span>)</div>
                    </div>
                    <?php endif; ?>
                    <!-- % A REALIZAR / % REALIZADO -->
                    <div class="ed-card">
                        <div class="ed-card-label">A REALIZAR</div>
                        <div class="ed-card-value <?= $_empClasseCor ?>"><?= formatarPercentDashboard($_empRestantePerc) ?></div>
                        <div class="ed-card-sub">% que Resta</div>
                    </div>
                    <div class="ed-card">
                        <div class="ed-card-label">REALIZADO</div>
                        <div class="ed-card-value <?= $_empClasseCor ?>"><?= formatarPercentDashboard($_empPercVal) ?></div>
                        <div class="ed-card-sub">% Realizado</div>
                    </div>
                </div>
                <?php if (!empty($_empVars)): ?>
                <div class="ed-detalhe-titulo" style="margin-top:10px;">Detalhamento por conta</div>
                <?php foreach ($_empVars as $_ev):
                    $_evPerc = ($_ev['orc'] > 0) ? (($_ev['real'] / $_ev['orc']) * 100) : 0;
                ?>
                <div class="ed-detalhe-row">
                    <div class="ed-detalhe-nome"><?= htmlspecialchars($_ev['nome'] ?? '') ?></div>
                    <div class="ed-detalhe-vals">
                        <span class="ed-dv"><span class="ed-leg-dot ed-leg-dot-xs" style="background:#f97316;"></span><?= formatarValorDashboard(abs($_ev['orc']), $mascaraPrincipal, $moeda) ?></span>
                        <span class="ed-dv"><span class="ed-leg-dot ed-leg-dot-xs" style="background:#22c55e;"></span><?= formatarValorDashboard(abs($_ev['real']), $mascaraPrincipal, $moeda) ?></span>
                        <?php if ($_ev['proj_valor'] !== null): ?>
                        <span class="ed-dv"><span class="ed-leg-dot ed-leg-dot-xs" style="background:#8b5cf6;"></span><?= formatarValorDashboard(abs($_ev['proj_valor']), $mascaraPrincipal, $moeda) ?></span>
                        <?php endif; ?>
                    </div>
                    <div class="ed-detalhe-perc" style="color:<?= $_evPerc >= 100 ? '#22c55e' : ($_evPerc >= 80 ? '#f59e0b' : '#ef4444') ?>;"><?= number_format($_evPerc, 1, ',', '.') ?>%</div>
                </div>
                <?php endforeach; ?>
                <?php endif; ?>
            </div>
        </div>
        <?php endforeach; ?>
    </div>
    </div><!-- /emp-modelo-bloco -->
    <?php endforeach; ?>
</div>
<?php endif; ?>
</div><!-- /visao-percentual wrapper -->

<?php else: ?>
<div class="mb-4" id="dashboardConsolidadoComparativo">
    <?php
        $ordemModelos = ['meta', 'submeta', 'resultado', 'orcamento'];
        foreach ($ordemModelos as $modeloBloco):
            $langModelo = obterLinguagem($modeloBloco);
            $titulo = match ($modeloBloco) {
                'meta' => 'Meta',
                'submeta' => 'Submeta',
                'resultado' => 'Resultado',
                'orcamento' => 'Inicio',
                default => strtoupper($modeloBloco),
            };
            $percentLabel = ($modeloBloco === 'orcamento') ? 'Percentual Consumido (Consolidado)' : 'Percentual Atingido (Consolidado)';
            $planejadoLabel = $langModelo['planejado'] ?? (($modeloBloco === 'orcamento') ? 'Orçamento' : 'Meta');
            $realizadoLabel = $langModelo['realizado'] ?? (($modeloBloco === 'orcamento') ? 'Gasto Realizado' : 'Realizado');
            $criticoLabel = ($modeloBloco === 'orcamento') ? 'Acima de 90%' : 'Abaixo de 90% (Projeção)';

            // Se não houver nenhuma empresa com dados no mês, não exibe o card
            $bucketMes = $dashboardConsolidadoComparativo[$modeloBloco]['mes']['empresas'] ?? [];
            if (empty($bucketMes)) continue;
    ?>
        <div class="card border-0 shadow-sm mb-3" data-modelo="<?= htmlspecialchars($modeloBloco) ?>">
            <div class="card-body">
                <div class="d-flex justify-content-between align-items-start gap-2 flex-wrap">
                    <div>
                        <div class="text-uppercase small text-secondary fw-semibold">Consolidado (por empresa)</div>
                        <h5 class="mb-0"><?= htmlspecialchars($titulo) ?></h5>
                    </div>
                    <div class="btn-group btn-group-sm" role="group" aria-label="Período">
                        <button type="button" class="btn btn-outline-secondary active" data-modelo-periodo="mes">Mês</button>
                        <button type="button" class="btn btn-outline-secondary" data-modelo-periodo="trimestre">Trimestre</button>
                        <button type="button" class="btn btn-outline-secondary" data-modelo-periodo="ano">Ano</button>
                    </div>
                </div>

                <?php if ($modeloBloco === 'orcamento'): ?>
                    <div class="row g-2 mt-2">
                        <div class="col-6 col-md-3">
                            <div class="small text-muted">Gasto realizado</div>
                            <div class="fw-semibold fs-5" data-role="orc-total-real"></div>
                        </div>
                        <div class="col-6 col-md-3">
                            <div class="small text-muted">Orçamento</div>
                            <div class="fw-semibold fs-5" data-role="orc-total-orc"></div>
                        </div>
                        <div class="col-6 col-md-3">
                            <div class="small text-muted">Saldo disponível</div>
                            <div class="fw-semibold fs-5" data-role="orc-total-saldo"></div>
                        </div>
                        <div class="col-6 col-md-3" data-role-wrap="orc-total-proj" style="display:none;">
                            <div class="small text-muted">Projeção de gasto</div>
                            <div class="fw-semibold fs-5" data-role="orc-total-proj"></div>
                        </div>
                    </div>

                    <div class="row g-3 mt-2 align-items-stretch">
                        <div class="col-12 col-lg-8">
                            <div class="text-uppercase small text-secondary fw-semibold">Termômetro financeiro (agrupado)</div>
                            <div class="mt-2" style="height: 320px;">
                                <canvas id="chart-orcamento-termometro"></canvas>
                            </div>
                        </div>
                        <div class="col-12 col-lg-4">
                            <div class="text-uppercase small text-secondary fw-semibold">Consumo do orçamento</div>
                            <div class="d-flex gap-3 align-items-center mt-2">
                                <div style="width: 160px; height: 160px;" class="flex-shrink-0">
                                    <canvas id="chart-orcamento-consumo"></canvas>
                                </div>
                                <div class="flex-grow-1">
                                    <div class="small text-muted">% consumido</div>
                                    <div class="fw-bold" style="font-size: 1.35rem;" data-role="orc-consumo-perc"></div>
                                    <div class="small text-muted">Gasto / Orçamento</div>
                                </div>
                            </div>
                            <hr class="my-2">
                            <div class="text-uppercase small text-secondary fw-semibold mb-2">Mini ranking de atenção</div>
                            <div class="small">
                                <div class="d-flex justify-content-between gap-2">
                                    <div class="text-muted">Maior consumo:</div>
                                    <div class="fw-semibold text-end" data-role="orc-ranking-maior">-</div>
                                </div>
                                <div class="d-flex justify-content-between gap-2 mt-1">
                                    <div class="text-muted">Menor consumo:</div>
                                    <div class="fw-semibold text-end" data-role="orc-ranking-menor">-</div>
                                </div>
                            </div>

                            <hr class="my-2">
                            <div class="text-uppercase small text-secondary fw-semibold mb-2">Empresas (consumo)</div>
                            <div class="small">
                                <div class="d-flex justify-content-between gap-2">
                                    <div class="text-muted">Menor consumo:</div>
                                    <div class="fw-semibold text-end" data-role="orc-emp-melhor">-</div>
                                </div>
                                <div class="d-flex justify-content-between gap-2 mt-1">
                                    <div class="text-muted">Maior consumo:</div>
                                    <div class="fw-semibold text-end" data-role="orc-emp-pior">-</div>
                                </div>
                                <div class="d-flex justify-content-between gap-2 mt-1">
                                    <div class="text-muted">Acima de 90%:</div>
                                    <div class="fw-semibold text-end" data-role="orc-emp-criticos" tabindex="0" role="button" style="cursor: help;">-</div>
                                </div>
                            </div>
                        </div>
                    </div>
                <?php else: ?>

                <div class="row g-2 mt-2">
                    <div class="col-12 col-md-3">
                        <div class="small text-muted"><?= htmlspecialchars($realizadoLabel) ?></div>
                        <div class="fw-semibold fs-5" data-role="total-real"></div>
                    </div>
                    <div class="col-12 col-md-3">
                        <div class="small text-muted"><?= htmlspecialchars($planejadoLabel) ?></div>
                        <div class="fw-semibold fs-5" data-role="total-orc"></div>
                    </div>
                    <div class="col-12 col-md-3" data-role-wrap="total-proj" style="display:none;">
                        <div class="small text-muted">Projeção (Total)</div>
                        <div class="fw-semibold fs-5" data-role="total-proj"></div>
                    </div>
                    <div class="col-12 col-md-3">
                        <div class="small text-muted"><?= htmlspecialchars($percentLabel) ?></div>
                        <div class="fw-bold fs-5" data-role="perc-total"></div>
                    </div>
                </div>

                <div class="row g-2 mt-2 small">
                    <div class="col-12 col-md-4">
                        <div class="text-muted">Melhor desempenho</div>
                        <div class="fw-semibold" data-role="melhor"></div>
                    </div>
                    <div class="col-12 col-md-4">
                        <div class="text-muted">Menor desempenho</div>
                        <div class="fw-semibold" data-role="pior"></div>
                    </div>
                    <div class="col-12 col-md-4">
                        <div class="text-muted"><?= htmlspecialchars($criticoLabel) ?></div>
                        <div class="fw-semibold" data-role="criticos" tabindex="0" role="button" style="cursor: help;"></div>
                    </div>
                </div>

                <div class="mt-3" style="height: 340px;">
                    <canvas id="chart-modelo-<?= htmlspecialchars($modeloBloco) ?>"></canvas>
                </div>
                <?php endif; ?>
            </div>
        </div>
    <?php endforeach; ?>
</div>
<?php endif; ?>



<?php if (!empty($kpisVariaveis) && $visaoDashboard !== 'modelo' && $visaoDashboard !== 'planilha'): ?>
<!-- ==================== LISTA COMPACTA DE CONTAS + ACCORDION ==================== -->
<div class="mb-4 <?= $modoPercentual ? 'visao-percentual' : '' ?>">
    <div class="kpi-lista-container" id="kpi-lista-section">
    <?php 
    // Mapa por variável por empresa: [cdvariavel][cdempresa] => {orc, real, proj_valor, proj_perc, dsempresa}
    $_varPorEmpresa = [];
    $_multiEmpresa = (is_array($visaoConsolidadaEmpresas) && count($visaoConsolidadaEmpresas) > 1);
    $_empCoresKpi = ['#3b82f6','#ef4444','#f59e0b','#10b981','#8b5cf6','#ec4899','#06b6d4','#f97316','#6366f1','#14b8a6'];
    if ($_multiEmpresa) {
        foreach ($visaoConsolidadaEmpresas as $_empIdx => $_empData) {
            $_eId = (int)($_empData['cdempresa'] ?? 0);
            $_eNome = $_empData['dsempresa'] ?? '';
            $_eCor = $_empCoresKpi[$_empIdx % count($_empCoresKpi)];
            foreach (['meta','submeta','resultado','orcamento'] as $_mdlKey) {
                foreach (['mes','trimestre','ano'] as $_perKey) {
                    $_vars = $_empData['modelos'][$_mdlKey][$_perKey]['vars'] ?? [];
                    foreach ($_vars as $_vd) {
                        $_vid = (int)($_vd['id'] ?? 0);
                        if ($_vid <= 0) continue;
                        $_varPorEmpresa[$_vid][$_eId] = [
                            'dsempresa' => $_eNome,
                            'cor' => $_eCor,
                            'mes' => [],
                            'trimestre' => [],
                            'ano' => [],
                        ];
                    }
                }
            }
            // Preencher por período
            foreach (['meta','submeta','resultado','orcamento'] as $_mdlKey) {
                foreach (['mes','trimestre','ano'] as $_perKey) {
                    $_vars = $_empData['modelos'][$_mdlKey][$_perKey]['vars'] ?? [];
                    foreach ($_vars as $_vd) {
                        $_vid = (int)($_vd['id'] ?? 0);
                        if ($_vid <= 0 || !isset($_varPorEmpresa[$_vid][$_eId])) continue;
                        $_varPorEmpresa[$_vid][$_eId][$_perKey] = [
                            'orc' => (float)($_vd['orc'] ?? 0),
                            'real' => (float)($_vd['real'] ?? 0),
                            'proj_valor' => $_vd['proj_valor'] ?? null,
                            'proj_perc' => $_vd['proj_perc'] ?? null,
                        ];
                    }
                }
            }
        }
    }

    ?>
    <!-- Legenda da barra de progresso -->
    <div class="kpi-lista-legenda">
        <span class="kpi-lista-leg-item"><span class="ed-leg-dot" style="background:#f97316;"></span> Orçado</span>
        <span class="kpi-lista-leg-item"><span class="ed-leg-dot" style="background:#22c55e;"></span> Realizado</span>
        <span class="kpi-lista-leg-item"><span class="ed-leg-dot" style="background:#8b5cf6;"></span> Projetado</span>
    </div>
    <?php
    $kpiIdx = 0;
    foreach ($kpisVariaveis as $kpiVar): 
        $mascaraVar   = $mascaraPorVariavel[$kpiVar['id']] ?? 'moeda';
        $modelo       = $modeloPorVariavel[$kpiVar['id']] ?? 'orcamento';
        $lang         = obterLinguagem($modelo);
        $isOrcamentoVar = (strtolower(trim((string)$modelo)) === 'orcamento');
        
        // Cores baseadas na PROJEÇÃO do MÊS, TRIMESTRE e ANO
        $classeCorMes = obterClasseCorProjecao($kpiVar['projMesPerc'], $modelo);
        $classeCorTrim = obterClasseCorProjecao($kpiVar['projTrimPerc'], $modelo);
        $classeCorAno = obterClasseCorProjecao($kpiVar['projAnoPerc'], $modelo);
        
        $classeVarMesVar = 'text-muted';
        if ($kpiVar['varMes'] !== null) {
            $classeVarMesVar = ($kpiVar['varMes'] >= 0) ? 'text-success' : 'text-danger';
        }
        
        $classeVarTrimVar = 'text-muted';
        if ($kpiVar['varTrim'] !== null) {
            $classeVarTrimVar = $isOrcamentoVar
                ? (($kpiVar['varTrim'] >= 0) ? 'text-danger' : 'text-success')
                : (($kpiVar['varTrim'] >= 0) ? 'text-success' : 'text-danger');
        }
        
        $classeVarAnoVar = 'text-muted';
        if ($kpiVar['varAno'] !== null) {
            $classeVarAnoVar = ($kpiVar['varAno'] >= 0) ? 'text-success' : 'text-danger';
        }
        
        // Calcula percentuais do mês
        $percMes = ($kpiVar['orcMes'] != 0.0) ? ($kpiVar['realMes'] / $kpiVar['orcMes']) : 0.0;
        $restanteMes = max(0.0, 1.0 - $percMes);
        
        // Calcula percentuais do trimestre
        $percTrim = ($kpiVar['orcTrim'] != 0.0) ? ($kpiVar['realTrim'] / $kpiVar['orcTrim']) : 0.0;
        $restanteTrim = max(0.0, 1.0 - $percTrim);
        
        // Calcula percentuais do ano
        $percAno = ($kpiVar['orcAno'] != 0.0) ? ($kpiVar['realAno'] / $kpiVar['orcAno']) : 0.0;
        $restanteAno = max(0.0, 1.0 - $percAno);
        
        // Calcula média diária necessária para bater a meta no mês
        $isMesCorrenteSelecionado = ((int)$anoFiltro === (int)$anoCorrente
            && is_array($mesesSelecionados)
            && count($mesesSelecionados) === 1
            && (int)$mesesSelecionados[0] === (int)$mesCorrente);

        $mediaDiariaMetaMes = 0.0;
        if ($isMesCorrenteSelecionado && $diasRestantesMesCorrente > 0) {
            $mediaDiariaMetaMes = max(0.0, ($kpiVar['orcMes'] - $kpiVar['realMes']) / $diasRestantesMesCorrente);
        }
        
        // Calcula média diária necessária para bater a meta no trimestre
        $trimestreSistemaVar = (int)ceil($mesCorrente / 3);
        $trimestreRefVar = ($trimestreFiltro > 0 && $trimestreFiltro <= 4) ? (int)$trimestreFiltro : $trimestreSistemaVar;
        $isTrimestreCorrenteSelecionado = ((int)$anoFiltro === (int)$anoCorrente && $trimestreRefVar === $trimestreSistemaVar);

        $mesesFinalTrimVar = (int)($trimestreRefVar * 3);
        $mesesInicioTrimVar = (int)(($trimestreRefVar - 1) * 3 + 1);
        
        $diasTrimTotalVar = 0;
        for ($m = $mesesInicioTrimVar; $m <= $mesesFinalTrimVar; $m++) {
            if ($m <= 12) {
                $diasTrimTotalVar += (int)date('t', strtotime($anoref . '-' . str_pad($m, 2, '0', STR_PAD_LEFT) . '-01'));
            }
        }
        
        $diasTrimDecorridosVar = 0;
        if ($mesCorrente < $mesesInicioTrimVar) {
            $diasTrimDecorridosVar = 0;
        } elseif ($mesCorrente > $mesesFinalTrimVar) {
            $diasTrimDecorridosVar = $diasTrimTotalVar;
        } else {
            for ($m = $mesesInicioTrimVar; $m < $mesCorrente; $m++) {
                $diasTrimDecorridosVar += (int)date('t', strtotime($anoref . '-' . str_pad((string)$m, 2, '0', STR_PAD_LEFT) . '-01'));
            }
            $diasTrimDecorridosVar += $diaCorrente;
        }
        
        $diasRestantesTrimestre = max(0, $diasTrimTotalVar - $diasTrimDecorridosVar);
        
        $mediaDiariaMetaTrim = 0.0;
        if ($isTrimestreCorrenteSelecionado && $diasRestantesTrimestre > 0) {
            $mediaDiariaMetaTrim = max(0.0, ($kpiVar['orcTrim'] - $kpiVar['realTrim']) / $diasRestantesTrimestre);
        }
        
        $mediaDiariaMetaAno = 0.0;
        if ((int)$anoFiltro === (int)$anoCorrente && $diasRestantesAno > 0) {
            $mediaDiariaMetaAno = max(0.0, ($kpiVar['orcAno'] - $kpiVar['realAno']) / $diasRestantesAno);
        }
        
        // Variação do mês (vs mês anterior)
        $varMesAnterior = $kpiVar['varMes'] ?? null;
        $classeVarMesVar = 'text-muted';
        if ($varMesAnterior !== null) {
            $classeVarMesVar = $isOrcamentoVar
                ? (($varMesAnterior >= 0) ? 'text-danger' : 'text-success')
                : (($varMesAnterior >= 0) ? 'text-success' : 'text-danger');
        }
        
        $classeVarAnoVar = 'text-muted';
        if ($kpiVar['varAno'] !== null) {
            $classeVarAnoVar = $isOrcamentoVar
                ? (($kpiVar['varAno'] >= 0) ? 'text-danger' : 'text-success')
                : (($kpiVar['varAno'] >= 0) ? 'text-success' : 'text-danger');
        }
        
        // Cor da barra de progresso (baseada na projeção do mês)
        $projMesPercAbs = abs((float)($kpiVar['projMesPerc'] ?? 0));
        if ($isOrcamentoVar) {
            $corBarraLista = ($projMesPercAbs > 0.9) ? '#ef4444' : (($projMesPercAbs > 0.8) ? '#f59e0b' : '#22c55e');
        } else {
            $corBarraLista = ($projMesPercAbs >= 1.0) ? '#22c55e' : (($projMesPercAbs >= 0.8) ? '#f59e0b' : '#ef4444');
        }
        $largBarra = min(100, $percMes * 100);
        $saldoMes = $kpiVar['orcMes'] - $kpiVar['realMes'];
        
        // Badge do modelo
        $modeloBadgeClass = match ($modelo) {
            'meta' => 'kpi-badge-meta',
            'submeta' => 'kpi-badge-submeta',
            'resultado' => 'kpi-badge-resultado',
            default => 'kpi-badge-orcamento',
        };

        // Origem
        $_origemKpi = $origemPorVariavel[(int)$kpiVar['id']] ?? null;
        $_temOrigemKpi = !empty($kpiVar['fl_origem']) && $_origemKpi && empty($kpiVar['fl_agregar_calc']);
        $_origemDisplay = '';
        $_origemNomeKpi = '';
        if ($_temOrigemKpi) {
            $_origemNomeKpi = htmlspecialchars($_origemKpi['dsintegracao']);
            $_origemRawKpi = $_origemKpi['valor_raw'];
            $_origemNumerico = ($_origemRawKpi !== null && preg_match('/^-?[0-9]+(\.[0-9]+)?$/', str_replace(',', '.', trim($_origemRawKpi))));
            if ($_origemRawKpi !== null && preg_match('/^\d{4}-\d{2}-\d{2}/', trim($_origemRawKpi))) {
                $_dt = date_create(trim($_origemRawKpi));
                $_origemDisplay = $_dt ? $_dt->format('d/m/Y') : htmlspecialchars($_origemRawKpi);
            } elseif ($_origemNumerico) {
                $_origemDisplay = formatarValorDashboard((float)str_replace(',', '.', $_origemRawKpi), $mascaraVar, $moeda);
            } else {
                $_origemDisplay = htmlspecialchars($_origemRawKpi ?? '');
            }
        }
        
        $kpiIdx++;
    ?>
    <!-- LINHA COMPACTA DA CONTA -->
    <div class="kpi-lista-item <?= ($kpiIdx % 2 === 0) ? 'kpi-lista-even' : 'kpi-lista-odd' ?>" data-kpi-id="<?= (int)$kpiVar['id'] ?>" data-modelo-card="<?= htmlspecialchars(strtolower(trim((string)$modelo))) ?>">
        <!-- Cabeçalho clicável (linha resumo) -->
        <div class="kpi-lista-header" role="button" tabindex="0" aria-expanded="false" data-toggle-kpi="<?= (int)$kpiVar['id'] ?>">
            <div class="kpi-lista-info">
                <div class="kpi-lista-nome-row">
                    <span class="kpi-lista-badge <?= $modeloBadgeClass ?>"><?= ucfirst($modelo) ?></span>
                    <span class="kpi-lista-nome"><?= htmlspecialchars($kpiVar['nome']) ?></span>
                </div>
                <?php if ($_temOrigemKpi): ?>
                <div class="kpi-lista-origem">
                    <i class="bi bi-database"></i> <?= $_origemDisplay ?>
                </div>
                <?php endif; ?>
                <div class="kpi-lista-barra-wrapper">
                    <div class="kpi-lista-barra" style="width: <?= number_format($largBarra, 1) ?>%; background: <?= $corBarraLista ?>;"></div>
                </div>
                <div class="kpi-lista-vals">
                    <span class="kpi-lista-val-item"><span class="ed-leg-dot" style="background:#f97316;"></span> <span class="dado-valor" data-raw-value="<?= abs($kpiVar['orcMes']) ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard(abs($kpiVar['orcMes']), $mascaraVar, $moeda) ?></span></span>
                    <span class="kpi-lista-val-item"><span class="ed-leg-dot" style="background:#22c55e;"></span> <span class="dado-valor" data-raw-value="<?= abs($kpiVar['realMes']) ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard(abs($kpiVar['realMes']), $mascaraVar, $moeda) ?></span></span>
                    <?php if ($kpiVar['projMesValor'] !== null): ?>
                    <span class="kpi-lista-val-item"><span class="ed-leg-dot" style="background:#8b5cf6;"></span> <span class="dado-valor <?= $classeCorMes ?>" data-raw-value="<?= abs($kpiVar['projMesValor']) ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard(abs($kpiVar['projMesValor']), $mascaraVar, $moeda) ?></span></span>
                    <?php endif; ?>
                </div>
            </div>
            <div class="kpi-lista-resumo">
                <div class="kpi-lista-perc <?= $classeCorMes ?>"><?= formatarPercentDashboard($percMes) ?></div>
                <div class="kpi-lista-saldo dado-valor <?= $saldoMes >= 0 ? ($isOrcamentoVar ? 'text-success' : 'text-muted') : ($isOrcamentoVar ? 'text-danger' : 'text-danger') ?>" data-raw-value="<?= $saldoMes ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard($saldoMes, $mascaraVar, $moeda) ?></div>
                <i class="bi bi-chevron-down kpi-lista-chevron"></i>
            </div>
        </div>

        <!-- PAINEL EXPANSÍVEL (Accordion) -->
        <div class="kpi-lista-detail" id="kpi-detail-<?= (int)$kpiVar['id'] ?>" style="display:none;">
            <div class="kpi-lista-detail-inner kpi-variable-card">
                <div class="card-body">
                    <!-- Toggle de período -->
                    <div class="d-flex justify-content-end mb-2">
                        <div class="btn-group btn-group-sm kpi-period-toggle" role="group">
                            <button type="button" class="btn btn-outline-secondary active" data-period="mes">Mês</button>
                            <button type="button" class="btn btn-outline-secondary" data-period="trimestre">Trimestre</button>
                            <button type="button" class="btn btn-outline-secondary" data-period="ano">Ano</button>
                        </div>
                    </div>

                    <!-- ===== MÊS ===== -->
                    <div class="kpi-period-content" data-period="mes">
                        <div class="kpi-compact">
                            <?php if ($_multiEmpresa):
                                $_kvId = (int)$kpiVar['id'];
                                $_kvEmps = $_varPorEmpresa[$_kvId] ?? [];
                            ?>
                            <!-- Legenda consolidada -->
                            <div class="kpi-emp-legenda">
                                <span class="kpi-emp-leg-item"><span class="ed-leg-dot" style="background:#f97316;"></span> <?= $lang['planejado'] ?>: <strong class="dado-valor" data-raw-value="<?= abs($kpiVar['orcMes']) ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard(abs($kpiVar['orcMes']), $mascaraVar, $moeda) ?></strong></span>
                                <span class="kpi-emp-leg-item"><span class="ed-leg-dot" style="background:#22c55e;"></span> <?= $lang['realizado'] ?>: <strong class="dado-valor" data-raw-value="<?= abs($kpiVar['realMes']) ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard(abs($kpiVar['realMes']), $mascaraVar, $moeda) ?></strong></span>
                                <?php if ($kpiVar['projMesValor'] !== null): ?>
                                <span class="kpi-emp-leg-item"><span class="ed-leg-dot" style="background:#8b5cf6;"></span> <?= $lang['projecao'] ?>: <strong class="dado-valor <?= $classeCorMes ?>" data-raw-value="<?= abs($kpiVar['projMesValor']) ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard(abs($kpiVar['projMesValor']), $mascaraVar, $moeda) ?></strong></span>
                                <?php endif; ?>
                            </div>
                            <!-- Por empresa -->
                            <?php if (!empty($_kvEmps)):
                                // Ordenar por % desc
                                uasort($_kvEmps, function($a, $b) {
                                    $pA = (($a['mes']['orc'] ?? 0) != 0) ? (($a['mes']['real'] ?? 0) / $a['mes']['orc']) : 0;
                                    $pB = (($b['mes']['orc'] ?? 0) != 0) ? (($b['mes']['real'] ?? 0) / $b['mes']['orc']) : 0;
                                    return $pB <=> $pA;
                                });
                            ?>
                            <div class="kpi-emp-lista">
                                <?php foreach ($_kvEmps as $_keId => $_keData):
                                    $_keOrc  = abs((float)($_keData['mes']['orc'] ?? 0));
                                    $_keReal = abs((float)($_keData['mes']['real'] ?? 0));
                                    $_keProj = ($_keData['mes']['proj_valor'] !== null) ? abs((float)$_keData['mes']['proj_valor']) : null;
                                    $_kePerc = ($_keOrc > 0) ? ($_keReal / $_keOrc * 100) : 0;
                                    $_kePercClamped = min(100, max(0, $_kePerc));
                                    if ($isOrcamentoVar) {
                                        $_keBarColor = ($_kePerc >= 100) ? '#ef4444' : (($_kePerc >= 90) ? '#f59e0b' : '#22c55e');
                                    } else {
                                        $_keBarColor = ($_kePerc >= 100) ? '#22c55e' : (($_kePerc >= 80) ? '#f59e0b' : '#ef4444');
                                    }
                                ?>
                                <div class="kpi-emp-row">
                                    <div class="kpi-emp-row-header">
                                        <span class="kpi-emp-dot" style="background:<?= $_keData['cor'] ?>;"></span>
                                        <span class="kpi-emp-nome"><?= htmlspecialchars($_keData['dsempresa'] ?? '') ?></span>
                                        <span class="kpi-emp-perc" style="color:<?= $_keBarColor ?>;"><?= number_format($_kePerc, 1, ',', '.') ?>%</span>
                                    </div>
                                    <div class="kpi-emp-bar-wrap">
                                        <div class="kpi-emp-bar" style="width:<?= number_format($_kePercClamped, 1) ?>%;background:<?= $_keBarColor ?>;"></div>
                                    </div>
                                    <div class="kpi-emp-vals">
                                        <span><span class="ed-leg-dot ed-leg-dot-xs" style="background:#f97316;"></span> <span class="dado-valor" data-raw-value="<?= $_keOrc ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard($_keOrc, $mascaraVar, $moeda) ?></span></span>
                                        <span><span class="ed-leg-dot ed-leg-dot-xs" style="background:#22c55e;"></span> <span class="dado-valor" data-raw-value="<?= $_keReal ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard($_keReal, $mascaraVar, $moeda) ?></span></span>
                                        <?php if ($_keProj !== null): ?>
                                        <span><span class="ed-leg-dot ed-leg-dot-xs" style="background:#8b5cf6;"></span> <span class="dado-valor" data-raw-value="<?= $_keProj ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard($_keProj, $mascaraVar, $moeda) ?></span></span>
                                        <?php endif; ?>
                                    </div>
                                </div>
                                <?php endforeach; ?>
                            </div>
                            <?php endif; ?>
                            <!-- % restante e realizado -->
                            <div class="kpi-row" style="margin-top:8px;">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['restante']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorMes ?> text-nowrap"><?= formatarPercentDashboard($restanteMes) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= htmlspecialchars($lang['restante_desc']) ?></div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['percentual_label']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorMes ?> text-nowrap"><?= formatarPercentDashboard($percMes) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= htmlspecialchars($lang['percentual_desc']) ?></div>
                                </div>
                            </div>
                            <?php else: ?>
                            <?php if (!$modoPercentual): ?>
                            <div class="kpi-row">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['planejado']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value dado-valor text-nowrap" data-raw-value="<?= $kpiVar['orcMes'] ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard($kpiVar['orcMes'], $mascaraVar, $moeda) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= htmlspecialchars($lang['planejado']) ?> do mês</div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['realizado']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value dado-valor text-nowrap" data-raw-value="<?= $kpiVar['realMes'] ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard($kpiVar['realMes'], $mascaraVar, $moeda) ?></span>
                                        <span class="kpi-perc-inline <?= $classeCorMes ?>"><?= formatarPercentDashboard($percMes) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap">Valor já <?= strtolower($lang['realizado']) ?></div>
                                </div>
                            </div>
                            <div class="kpi-row">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['restante']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value dado-valor text-nowrap" data-raw-value="<?= max(0, $kpiVar['orcMes'] - $kpiVar['realMes']) ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard(max(0, $kpiVar['orcMes'] - $kpiVar['realMes']), $mascaraVar, $moeda) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= $isOrcamentoVar ? 'Saldo disponível' : 'Saldo a realizar' ?></div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= $isOrcamentoVar ? 'Gasto Diário' : 'Média Diária para Meta' ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value dado-valor text-nowrap" data-raw-value="<?= $mediaDiariaMetaMes ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard($mediaDiariaMetaMes, $mascaraVar, $moeda) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= $isOrcamentoVar ? 'Máximo por dia' : 'Por dia' ?> (<?= $diasRestantesMesCorrente ?> dias)</div>
                                </div>
                            </div>
                            <div class="kpi-row">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['projecao']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value dado-valor <?= $classeCorMes ?> text-nowrap" data-raw-value="<?= abs($kpiVar['projMesValor']) ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard(abs($kpiVar['projMesValor']), $mascaraVar, $moeda) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap">Expectativa (<span class="<?= $classeCorMes ?>"><?= formatarPercentDashboard(abs($kpiVar['projMesPerc'])) ?></span>)</div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['vs_anterior']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value dado-valor <?= $classeVarMesVar ?> text-nowrap" data-raw-value="<?= $kpiVar['realMesAnt'] ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard($kpiVar['realMesAnt'], $mascaraVar, $moeda) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap">
                                        Vs <?= formatarValorDashboard($kpiVar['realMes'], $mascaraVar, $moeda) ?>
                                        <?php if ($varMesAnterior !== null): ?>
                                            <span class="<?= $classeVarMesVar ?>">(<?= ($varMesAnterior >= 0 ? '+' : '') . formatarPercentDashboard($varMesAnterior) ?>)</span>
                                        <?php endif; ?>
                                    </div>
                                </div>
                            </div>
                            <?php else: ?>
                            <div class="kpi-row">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['projecao']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorMes ?> text-nowrap"><?= formatarPercentDashboard(abs($kpiVar['projMesPerc'])) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap">Expectativa de <?= $isOrcamentoVar ? 'consumo' : 'atingimento' ?></div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['vs_anterior']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeVarMesVar ?> text-nowrap"><?php if ($varMesAnterior !== null): ?><?= ($varMesAnterior >= 0 ? '+' : '') . formatarPercentDashboard($varMesAnterior) ?><?php else: ?>-<?php endif; ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap">Variação vs mês anterior</div>
                                </div>
                            </div>
                            <?php if (!$isOrcamentoVar):
                                $contasVarKpi = $contasPorVariavel[(int)$kpiVar['id']] ?? [];
                                $realizadoHojeKpi = 0.0;
                                if (!empty($contasVarKpi) && !empty($mapContaDiaMesAtual)) {
                                    foreach ($contasVarKpi as $ctaKpi) {
                                        if (isset($mapContaDiaMesAtual[$ctaKpi][$diaHoje])) {
                                            $realizadoHojeKpi += (float)$mapContaDiaMesAtual[$ctaKpi][$diaHoje];
                                        }
                                    }
                                }
                                $metaDiariaKpi = calcularMetaDiaria($kpiVar['orcMes'], $diaHoje, $mesHoje, $anoHoje, $usarPesoDia);
                                $percHojeKpi = ($metaDiariaKpi > 0) ? ($realizadoHojeKpi / $metaDiariaKpi) : 0;
                                $percHojeKpiFalta = max(0.0, 1.0 - $percHojeKpi);
                                $classeHojeKpi = ($percHojeKpi >= 1.0) ? 'text-success' : (($percHojeKpi >= 0.5) ? 'text-warning' : 'text-danger');
                                $corBarraKpi = ($percHojeKpi >= 1.0) ? '#22c55e' : (($percHojeKpi >= 0.5) ? '#f59e0b' : '#ef4444');
                                $largBarraKpi = min(100, $percHojeKpi * 100);
                            ?>
                            <div class="kpi-row" style="display: block !important;">
                                <div class="dia-corrente-kpi px-1 py-1">
                                    <div class="d-flex justify-content-between align-items-center mb-1">
                                        <span class="kpi-label" style="font-size: 0.7rem;">Hoje (<?= str_pad($diaHoje, 2, '0', STR_PAD_LEFT) ?>/<?= str_pad($mesHoje, 2, '0', STR_PAD_LEFT) ?>)</span>
                                        <span class="fw-bold <?= $classeHojeKpi ?>" style="font-size: 0.95rem;"><?= formatarPercentDashboard($percHojeKpi) ?></span>
                                    </div>
                                    <div style="height: 5px; background: #e5e7eb; border-radius: 3px; overflow: hidden;">
                                        <div style="height: 100%; width: <?= number_format($largBarraKpi, 1) ?>%; background: <?= $corBarraKpi ?>; border-radius: 3px; transition: width 0.4s;"></div>
                                    </div>
                                    <div class="d-flex justify-content-between mt-1" style="font-size: 0.68rem;">
                                        <span class="<?= $classeHojeKpi ?>">Realizado: <?= formatarPercentDashboard($percHojeKpi) ?></span>
                                        <span class="<?= ($percHojeKpiFalta > 0) ? 'text-danger' : 'text-success' ?>">
                                            <?= ($percHojeKpiFalta > 0) ? 'Falta ' . formatarPercentDashboard($percHojeKpiFalta) : '&#10003; Meta atingida' ?>
                                        </span>
                                    </div>
                                </div>
                            </div>
                            <?php endif; ?>
                            <?php endif; ?>
                            <div class="kpi-row">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['restante']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorMes ?> text-nowrap"><?= formatarPercentDashboard($restanteMes) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= htmlspecialchars($lang['restante_desc']) ?></div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['percentual_label']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorMes ?> text-nowrap"><?= formatarPercentDashboard($percMes) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= htmlspecialchars($lang['percentual_desc']) ?></div>
                                </div>
                            </div>
                            <?php endif; /* endif $_multiEmpresa */ ?>
                        </div>
                    </div>

                    <!-- ===== TRIMESTRE ===== -->
                    <div class="kpi-period-content d-none" data-period="trimestre">
                        <div class="kpi-compact">
                            <?php if ($_multiEmpresa):
                                $_kvEmpsT = $_varPorEmpresa[(int)$kpiVar['id']] ?? [];
                            ?>
                            <div class="kpi-emp-legenda">
                                <span class="kpi-emp-leg-item"><span class="ed-leg-dot" style="background:#f97316;"></span> <?= $lang['planejado'] ?>: <strong class="dado-valor" data-raw-value="<?= abs($kpiVar['orcTrim']) ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard(abs($kpiVar['orcTrim']), $mascaraVar, $moeda) ?></strong></span>
                                <span class="kpi-emp-leg-item"><span class="ed-leg-dot" style="background:#22c55e;"></span> <?= $lang['realizado'] ?>: <strong class="dado-valor" data-raw-value="<?= abs($kpiVar['realTrim']) ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard(abs($kpiVar['realTrim']), $mascaraVar, $moeda) ?></strong></span>
                                <?php if ($kpiVar['projTrimValor'] !== null): ?>
                                <span class="kpi-emp-leg-item"><span class="ed-leg-dot" style="background:#8b5cf6;"></span> <?= $lang['projecao'] ?>: <strong class="dado-valor <?= $classeCorTrim ?>" data-raw-value="<?= abs($kpiVar['projTrimValor']) ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard(abs($kpiVar['projTrimValor']), $mascaraVar, $moeda) ?></strong></span>
                                <?php endif; ?>
                            </div>
                            <?php if (!empty($_kvEmpsT)):
                                uasort($_kvEmpsT, function($a, $b) {
                                    $pA = (($a['trimestre']['orc'] ?? 0) != 0) ? (($a['trimestre']['real'] ?? 0) / $a['trimestre']['orc']) : 0;
                                    $pB = (($b['trimestre']['orc'] ?? 0) != 0) ? (($b['trimestre']['real'] ?? 0) / $b['trimestre']['orc']) : 0;
                                    return $pB <=> $pA;
                                });
                            ?>
                            <div class="kpi-emp-lista">
                                <?php foreach ($_kvEmpsT as $_keId => $_keData):
                                    $_keOrc  = abs((float)($_keData['trimestre']['orc'] ?? 0));
                                    $_keReal = abs((float)($_keData['trimestre']['real'] ?? 0));
                                    $_keProj = ($_keData['trimestre']['proj_valor'] !== null) ? abs((float)$_keData['trimestre']['proj_valor']) : null;
                                    $_kePerc = ($_keOrc > 0) ? ($_keReal / $_keOrc * 100) : 0;
                                    $_kePercClamped = min(100, max(0, $_kePerc));
                                    $_keBarColor = $isOrcamentoVar
                                        ? (($_kePerc >= 100) ? '#ef4444' : (($_kePerc >= 90) ? '#f59e0b' : '#22c55e'))
                                        : (($_kePerc >= 100) ? '#22c55e' : (($_kePerc >= 80) ? '#f59e0b' : '#ef4444'));
                                ?>
                                <div class="kpi-emp-row">
                                    <div class="kpi-emp-row-header">
                                        <span class="kpi-emp-dot" style="background:<?= $_keData['cor'] ?>;"></span>
                                        <span class="kpi-emp-nome"><?= htmlspecialchars($_keData['dsempresa'] ?? '') ?></span>
                                        <span class="kpi-emp-perc" style="color:<?= $_keBarColor ?>;"><?= number_format($_kePerc, 1, ',', '.') ?>%</span>
                                    </div>
                                    <div class="kpi-emp-bar-wrap">
                                        <div class="kpi-emp-bar" style="width:<?= number_format($_kePercClamped, 1) ?>%;background:<?= $_keBarColor ?>;"></div>
                                    </div>
                                    <div class="kpi-emp-vals">
                                        <span><span class="ed-leg-dot ed-leg-dot-xs" style="background:#f97316;"></span> <span class="dado-valor" data-raw-value="<?= $_keOrc ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard($_keOrc, $mascaraVar, $moeda) ?></span></span>
                                        <span><span class="ed-leg-dot ed-leg-dot-xs" style="background:#22c55e;"></span> <span class="dado-valor" data-raw-value="<?= $_keReal ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard($_keReal, $mascaraVar, $moeda) ?></span></span>
                                        <?php if ($_keProj !== null): ?>
                                        <span><span class="ed-leg-dot ed-leg-dot-xs" style="background:#8b5cf6;"></span> <span class="dado-valor" data-raw-value="<?= $_keProj ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard($_keProj, $mascaraVar, $moeda) ?></span></span>
                                        <?php endif; ?>
                                    </div>
                                </div>
                                <?php endforeach; ?>
                            </div>
                            <?php endif; ?>
                            <div class="kpi-row" style="margin-top:8px;">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['restante']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorTrim ?> text-nowrap"><?= formatarPercentDashboard($restanteTrim) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= htmlspecialchars($lang['restante_desc']) ?></div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['percentual_label']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorTrim ?> text-nowrap"><?= formatarPercentDashboard($percTrim) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= htmlspecialchars($lang['percentual_desc']) ?></div>
                                </div>
                            </div>
                            <?php else: ?>
                            <?php if (!$modoPercentual): ?>
                            <div class="kpi-row">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['planejado']) ?> (Trimestre)</div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value text-nowrap"><?= formatarValorDashboard($kpiVar['orcTrim'], $mascaraVar, $moeda) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= htmlspecialchars($lang['planejado']) ?> do trimestre</div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['realizado']) ?> (Trimestre)</div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value text-nowrap"><?= formatarValorDashboard($kpiVar['realTrim'], $mascaraVar, $moeda) ?></span>
                                        <span class="kpi-perc-inline <?= $classeCorTrim ?>"><?= formatarPercentDashboard($percTrim) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap">Valor já <?= strtolower($lang['realizado']) ?></div>
                                </div>
                            </div>
                            <div class="kpi-row">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['restante']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value text-nowrap"><?= formatarValorDashboard(max(0, $kpiVar['orcTrim'] - $kpiVar['realTrim']), $mascaraVar, $moeda) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= $isOrcamentoVar ? 'Saldo disponível' : 'Saldo a realizar' ?></div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= $isOrcamentoVar ? 'Gasto Diário' : 'Média Diária para Meta' ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value text-nowrap"><?= formatarValorDashboard($mediaDiariaMetaTrim, $mascaraVar, $moeda) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= $isOrcamentoVar ? 'Máximo por dia' : 'Necessário por dia' ?> (<?= $diasRestantesTrimestre ?> dias)</div>
                                </div>
                            </div>
                            <div class="kpi-row">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['projecao']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorTrim ?> text-nowrap"><?= formatarValorDashboard(abs($kpiVar['projTrimValor']), $mascaraVar, $moeda) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap">Expectativa (<span class="<?= $classeCorTrim ?>"><?= formatarPercentDashboard(abs($kpiVar['projTrimPerc'])) ?></span>)</div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['vs_anterior']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeVarTrimVar ?> text-nowrap"><?= formatarValorDashboard($kpiVar['realTrimAnt'], $mascaraVar, $moeda) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap">
                                        Vs <?= formatarValorDashboard($kpiVar['realTrim'], $mascaraVar, $moeda) ?>
                                        <?php if ($kpiVar['varTrim'] !== null): ?>
                                            <span class="<?= $classeVarTrimVar ?>"> (<?= ($kpiVar['varTrim'] >= 0 ? '+' : '') . formatarPercentDashboard($kpiVar['varTrim']) ?>)</span>
                                        <?php endif; ?>
                                    </div>
                                </div>
                            </div>
                            <?php else: ?>
                            <div class="kpi-row">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['projecao']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorTrim ?> text-nowrap"><?= formatarPercentDashboard(abs($kpiVar['projTrimPerc'])) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap">Expectativa de <?= $isOrcamentoVar ? 'consumo' : 'atingimento' ?></div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['vs_anterior']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeVarTrimVar ?> text-nowrap"><?php if ($kpiVar['varTrim'] !== null): ?><?= ($kpiVar['varTrim'] >= 0 ? '+' : '') . formatarPercentDashboard($kpiVar['varTrim']) ?><?php else: ?>-<?php endif; ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap">Variação vs trimestre anterior</div>
                                </div>
                            </div>
                            <?php endif; ?>
                            <div class="kpi-row">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['restante']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorTrim ?> text-nowrap"><?= formatarPercentDashboard($restanteTrim) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= htmlspecialchars($lang['restante_desc']) ?></div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['percentual_label']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorTrim ?> text-nowrap"><?= formatarPercentDashboard($percTrim) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= htmlspecialchars($lang['percentual_desc']) ?></div>
                                </div>
                            </div>
                            <?php endif; /* endif $_multiEmpresa trimestre */ ?>
                        </div>
                    </div>

                    <!-- ===== ANO ===== -->
                    <div class="kpi-period-content d-none" data-period="ano">
                        <div class="kpi-compact">
                            <?php if ($_multiEmpresa):
                                $_kvEmpsA = $_varPorEmpresa[(int)$kpiVar['id']] ?? [];
                            ?>
                            <div class="kpi-emp-legenda">
                                <span class="kpi-emp-leg-item"><span class="ed-leg-dot" style="background:#f97316;"></span> <?= $lang['planejado'] ?>: <strong class="dado-valor" data-raw-value="<?= abs($kpiVar['orcAno']) ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard(abs($kpiVar['orcAno']), $mascaraVar, $moeda) ?></strong></span>
                                <span class="kpi-emp-leg-item"><span class="ed-leg-dot" style="background:#22c55e;"></span> <?= $lang['realizado'] ?>: <strong class="dado-valor" data-raw-value="<?= abs($kpiVar['realAno']) ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard(abs($kpiVar['realAno']), $mascaraVar, $moeda) ?></strong></span>
                                <?php if ($kpiVar['projAnoValor'] !== null): ?>
                                <span class="kpi-emp-leg-item"><span class="ed-leg-dot" style="background:#8b5cf6;"></span> <?= $lang['projecao'] ?>: <strong class="dado-valor <?= $classeCorAno ?>" data-raw-value="<?= abs($kpiVar['projAnoValor']) ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard(abs($kpiVar['projAnoValor']), $mascaraVar, $moeda) ?></strong></span>
                                <?php endif; ?>
                            </div>
                            <?php if (!empty($_kvEmpsA)):
                                uasort($_kvEmpsA, function($a, $b) {
                                    $pA = (($a['ano']['orc'] ?? 0) != 0) ? (($a['ano']['real'] ?? 0) / $a['ano']['orc']) : 0;
                                    $pB = (($b['ano']['orc'] ?? 0) != 0) ? (($b['ano']['real'] ?? 0) / $b['ano']['orc']) : 0;
                                    return $pB <=> $pA;
                                });
                            ?>
                            <div class="kpi-emp-lista">
                                <?php foreach ($_kvEmpsA as $_keId => $_keData):
                                    $_keOrc  = abs((float)($_keData['ano']['orc'] ?? 0));
                                    $_keReal = abs((float)($_keData['ano']['real'] ?? 0));
                                    $_keProj = ($_keData['ano']['proj_valor'] !== null) ? abs((float)$_keData['ano']['proj_valor']) : null;
                                    $_kePerc = ($_keOrc > 0) ? ($_keReal / $_keOrc * 100) : 0;
                                    $_kePercClamped = min(100, max(0, $_kePerc));
                                    $_keBarColor = $isOrcamentoVar
                                        ? (($_kePerc >= 100) ? '#ef4444' : (($_kePerc >= 90) ? '#f59e0b' : '#22c55e'))
                                        : (($_kePerc >= 100) ? '#22c55e' : (($_kePerc >= 80) ? '#f59e0b' : '#ef4444'));
                                ?>
                                <div class="kpi-emp-row">
                                    <div class="kpi-emp-row-header">
                                        <span class="kpi-emp-dot" style="background:<?= $_keData['cor'] ?>;"></span>
                                        <span class="kpi-emp-nome"><?= htmlspecialchars($_keData['dsempresa'] ?? '') ?></span>
                                        <span class="kpi-emp-perc" style="color:<?= $_keBarColor ?>;"><?= number_format($_kePerc, 1, ',', '.') ?>%</span>
                                    </div>
                                    <div class="kpi-emp-bar-wrap">
                                        <div class="kpi-emp-bar" style="width:<?= number_format($_kePercClamped, 1) ?>%;background:<?= $_keBarColor ?>;"></div>
                                    </div>
                                    <div class="kpi-emp-vals">
                                        <span><span class="ed-leg-dot ed-leg-dot-xs" style="background:#f97316;"></span> <span class="dado-valor" data-raw-value="<?= $_keOrc ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard($_keOrc, $mascaraVar, $moeda) ?></span></span>
                                        <span><span class="ed-leg-dot ed-leg-dot-xs" style="background:#22c55e;"></span> <span class="dado-valor" data-raw-value="<?= $_keReal ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard($_keReal, $mascaraVar, $moeda) ?></span></span>
                                        <?php if ($_keProj !== null): ?>
                                        <span><span class="ed-leg-dot ed-leg-dot-xs" style="background:#8b5cf6;"></span> <span class="dado-valor" data-raw-value="<?= $_keProj ?>" data-mascara="<?= htmlspecialchars($mascaraVar) ?>"><?= formatarValorDashboard($_keProj, $mascaraVar, $moeda) ?></span></span>
                                        <?php endif; ?>
                                    </div>
                                </div>
                                <?php endforeach; ?>
                            </div>
                            <?php endif; ?>
                            <div class="kpi-row" style="margin-top:8px;">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['restante']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorAno ?> text-nowrap"><?= formatarPercentDashboard($kpiVar['restantePerc']) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= htmlspecialchars($lang['restante_desc']) ?></div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['percentual_label']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorAno ?> text-nowrap"><?= formatarPercentDashboard($kpiVar['atingPerc']) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= htmlspecialchars($lang['percentual_desc']) ?></div>
                                </div>
                            </div>
                            <?php else: ?>
                            <?php if (!$modoPercentual): ?>
                            <div class="kpi-row">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['planejado']) ?> (Ano)</div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value text-nowrap"><?= formatarValorDashboard($kpiVar['orcAno'], $mascaraVar, $moeda) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= htmlspecialchars($lang['planejado']) ?> do ano</div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['realizado']) ?> (Ano)</div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value text-nowrap"><?= formatarValorDashboard($kpiVar['realAno'], $mascaraVar, $moeda) ?></span>
                                        <span class="kpi-perc-inline <?= $classeCorAno ?>"><?= formatarPercentDashboard($kpiVar['atingPerc']) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap">Valor já <?= strtolower($lang['realizado']) ?></div>
                                </div>
                            </div>
                            <div class="kpi-row">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['restante']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value text-nowrap"><?= formatarValorDashboard(max(0, $kpiVar['orcAno'] - $kpiVar['realAno']), $mascaraVar, $moeda) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= $isOrcamentoVar ? 'Saldo disponível' : 'Saldo a realizar' ?></div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= $isOrcamentoVar ? 'Gasto Diário' : 'Média Diária para Meta' ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value text-nowrap"><?= formatarValorDashboard($mediaDiariaMetaAno, $mascaraVar, $moeda) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= $isOrcamentoVar ? 'Máximo por dia' : 'Necessário por dia' ?> (<?= $diasRestantesAno ?> dias)</div>
                                </div>
                            </div>
                            <div class="kpi-row">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['projecao']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorAno ?> text-nowrap"><?= formatarValorDashboard(abs($kpiVar['projAnoValor']), $mascaraVar, $moeda) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap">Expectativa (<span class="<?= $classeCorAno ?>"><?= formatarPercentDashboard(abs($kpiVar['projAnoPerc'])) ?></span>)</div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['vs_anterior']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeVarAnoVar ?> text-nowrap"><?= formatarValorDashboard($kpiVar['realAnoAnt'], $mascaraVar, $moeda) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap">
                                        Vs <?= formatarValorDashboard($kpiVar['realAno'], $mascaraVar, $moeda) ?>
                                        <?php if ($kpiVar['varAno'] !== null): ?>
                                            <span class="<?= $classeVarAnoVar ?>"> (<?= ($kpiVar['varAno'] >= 0 ? '+' : '') . formatarPercentDashboard($kpiVar['varAno']) ?>)</span>
                                        <?php endif; ?>
                                    </div>
                                </div>
                            </div>
                            <?php else: ?>
                            <div class="kpi-row">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['projecao']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorAno ?> text-nowrap"><?= formatarPercentDashboard(abs($kpiVar['projAnoPerc'])) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap">Expectativa de <?= $isOrcamentoVar ? 'consumo' : 'atingimento' ?></div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['vs_anterior']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeVarAnoVar ?> text-nowrap"><?php if ($kpiVar['varAno'] !== null): ?><?= ($kpiVar['varAno'] >= 0 ? '+' : '') . formatarPercentDashboard($kpiVar['varAno']) ?><?php else: ?>-<?php endif; ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap">Variação vs ano anterior</div>
                                </div>
                            </div>
                            <?php endif; ?>
                            <div class="kpi-row">
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['restante']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorAno ?> text-nowrap"><?= formatarPercentDashboard($kpiVar['restantePerc']) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= htmlspecialchars($lang['restante_desc']) ?></div>
                                </div>
                                <div class="kpi-cell">
                                    <div class="kpi-label"><?= htmlspecialchars($lang['percentual_label']) ?></div>
                                    <div class="kpi-value-line">
                                        <span class="kpi-value <?= $classeCorAno ?> text-nowrap"><?= formatarPercentDashboard($kpiVar['atingPerc']) ?></span>
                                    </div>
                                    <div class="kpi-sub text-muted text-nowrap"><?= htmlspecialchars($lang['percentual_desc']) ?></div>
                                </div>
                            </div>
                            <?php endif; /* endif $_multiEmpresa ano */ ?>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <?php endforeach; ?>
    </div>
</div>
<?php endif; ?>

</div>



<style>
/* ==================== TOGGLE BUTTONS (VISÃO + MODELO) ==================== */
.dash-toggle-bar {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}
@media (min-width: 768px) {
    .dash-toggle-bar {
        flex-wrap: nowrap;
    }
}
.dash-toggle-group,
.dash-modelo-group {
    display: inline-flex;
    gap: 6px;
    background: #f1f5f9;
    border-radius: 50px;
    padding: 4px;
    flex-shrink: 0;
}
.dash-toggle-btn,
.dash-modelo-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 18px;
    border-radius: 50px;
    font-size: 0.85rem;
    font-weight: 600;
    text-decoration: none;
    border: none;
    cursor: pointer;
    transition: all 0.2s ease;
    color: #334155;
    background: transparent;
    white-space: nowrap;
}
.dash-toggle-btn:hover,
.dash-modelo-btn:hover {
    color: #0f172a;
    background: #e2e8f0;
    text-decoration: none;
}
.dash-toggle-btn.active {
    background: #2563eb;
    color: #ffffff !important;
    box-shadow: 0 2px 8px rgba(37, 99, 235, 0.3);
}
.dash-toggle-btn.active:hover {
    background: #1d4ed8;
    color: #ffffff !important;
}
.dash-modelo-btn.active {
    background: #2563eb;
    color: #ffffff !important;
    box-shadow: 0 2px 8px rgba(37, 99, 235, 0.3);
}
.dash-modelo-btn.active:hover {
    background: #1d4ed8;
    color: #ffffff !important;
}
.dash-toggle-btn i,
.dash-modelo-btn i {
    font-size: 0.9rem;
}
@media (max-width: 576px) {
    .dash-toggle-bar {
        gap: 6px;
        flex-wrap: wrap;
    }
    .dash-toggle-group {
        display: none !important;
    }
    .dash-modelo-group {
        width: 100%;
        display: flex;
        justify-content: center;
        gap: 2px;
        padding: 3px;
        border-radius: 30px;
    }
    .dash-toggle-btn,
    .dash-modelo-btn {
        flex: 1;
        justify-content: center;
        padding: 6px 4px;
        font-size: 0.7rem;
        gap: 3px;
        white-space: nowrap;
    }
    .dash-toggle-btn i,
    .dash-modelo-btn i {
        font-size: 0.72rem;
    }
    .dash-toggle-btn span,
    .dash-modelo-btn span {
        /* show text, just smaller */
    }
    .dash-numerico-group {
        width: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 6px;
    }
}

/* Toggle Exibição Numérica */
.dash-numerico-group {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    margin-left: auto;
}
.dash-numerico-label {
    font-size: 0.78rem;
    color: #64748b;
    font-weight: 500;
    white-space: nowrap;
}
.dash-numerico-btn {
    padding: 4px 10px;
    border-radius: 20px;
    font-size: 0.8rem;
    font-weight: 700;
    border: 1px solid #cbd5e1;
    cursor: pointer;
    transition: all 0.2s ease;
    color: #475569;
    background: #fff;
    white-space: nowrap;
    min-width: 32px;
    text-align: center;
    font-family: monospace;
}
.dash-numerico-btn:hover {
    background: #f1f5f9;
    border-color: #94a3b8;
}
.dash-numerico-btn.active {
    background: #2563eb;
    color: #ffffff;
    border-color: #2563eb;
}

/* ==================== ÚLTIMOS 7 DIAS (scroll horizontal) ==================== */
.ultimos7-scroll-wrap {
    overflow: visible;
}
.ultimos7-scroll-inner {
    display: flex;
    gap: 14px;
    overflow-x: auto;
    padding-bottom: 6px;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
}
.ultimos7-scroll-inner::-webkit-scrollbar {
    height: 5px;
}
.ultimos7-scroll-inner::-webkit-scrollbar-track {
    background: #f1f5f9;
    border-radius: 3px;
}
.ultimos7-scroll-inner::-webkit-scrollbar-thumb {
    background: #cbd5e1;
    border-radius: 3px;
}
.ultimos7-card {
    flex: 0 0 auto;
    min-width: 370px;
    max-width: 480px;
    background: #ffffff;
    border-radius: 12px;
    padding: 12px 14px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.05);
    border: 1px solid #e2e8f0;
    scroll-snap-align: start;
}
.ultimos7-card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
}
.ultimos7-card-nome {
    font-size: 0.82rem;
    font-weight: 700;
    text-transform: uppercase;
    color: #334155;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 70%;
}
.ultimos7-card-badge {
    font-size: 0.65rem;
    padding: 2px 7px;
    border-radius: 10px;
}
.ultimos7-dias-row {
    display: flex;
    gap: 4px;
}
.ultimos7-dia-cell {
    flex: 0 0 auto;
    text-align: center;
    min-width: 48px;
    padding: 4px 3px;
    border-radius: 6px;
    background: #f8fafc;
}
.u7-dia-label {
    font-size: 0.68rem;
    color: #94a3b8;
    font-weight: 600;
    text-transform: uppercase;
    white-space: nowrap;
    margin-bottom: 2px;
}
.u7-dia-valor {
    font-size: 0.78rem;
    font-weight: 700;
    color: #1e293b;
    white-space: nowrap;
    overflow: visible;
}
.u7-dia-perc {
    font-size: 0.68rem;
    font-weight: 600;
    margin-top: 1px;
}
.u7-ok { color: #16a34a; }
.u7-warn { color: #d97706; }
.u7-danger { color: #dc2626; }
.u7-dia-delta {
    font-size: 0.62rem;
    font-weight: 600;
    color: #dc3545;
    margin-top: 0;
}
@media (min-width: 768px) {
    .u7-dia-delta { font-size: 0.72rem; }
}

/* Breakdown contas fechadas/abertas */
.u7-has-breakdown { cursor: pointer; position: relative; }
.u7-has-breakdown:hover { background: #eef2ff; }
.u7-breakdown {
    margin-top: 4px;
    padding: 4px 6px;
    background: #f8f9fa;
    border: 1px solid #dee2e6;
    border-radius: 4px;
    font-size: 0.72rem;
    text-align: left;
}
.u7-bk-row { display: flex; justify-content: space-between; gap: 6px; }
.u7-bk-label { color: #6c757d; white-space: nowrap; }
.u7-bk-val { font-weight: 600; white-space: nowrap; }
@media (min-width: 768px) {
    .u7-breakdown { font-size: 0.82rem; padding: 5px 8px; }
}

/* Desktop: fontes maiores e cards mais amplos */
@media (min-width: 768px) {
    .ultimos7-card {
        min-width: 420px;
        max-width: 560px;
        padding: 16px 20px;
    }
    .ultimos7-card-nome {
        font-size: 1rem;
    }
    .ultimos7-card-badge {
        font-size: 0.75rem;
        padding: 3px 10px;
    }
    .ultimos7-dia-cell {
        padding: 6px 4px;
    }
    .u7-dia-label {
        font-size: 0.78rem;
    }
    .u7-dia-valor {
        font-size: 0.92rem;
    }
    .u7-dia-perc {
        font-size: 0.78rem;
    }
    .ultimos7-scroll-inner {
        gap: 18px;
    }
}

@media (max-width: 575px) {
    .ultimos7-card {
        min-width: 370px;
        padding: 12px 12px;
    }
    .ultimos7-card-nome {
        font-size: 0.85rem;
    }
    .ultimos7-dias-row {
        gap: 4px;
    }
    .ultimos7-dia-cell {
        padding: 5px 4px;
        min-width: 52px;
        flex: 0 0 auto;
    }
    .u7-dia-valor {
        font-size: 0.78rem;
        white-space: nowrap;
        overflow: visible;
    }
    .u7-dia-label {
        font-size: 0.64rem;
    }
    .u7-dia-perc {
        font-size: 0.66rem;
    }
}

/* ==================== RESUMO RÁPIDO (4 cards) ==================== */
.resumo-modelo-indicador {
    grid-column: 1 / -1;
    font-size: 0.78rem;
    color: #6b7280;
    padding: 4px 10px;
    background: #f0f4ff;
    border-radius: 8px;
    display: flex;
    align-items: center;
    gap: 5px;
}
.resumo-modelo-indicador i { color: #3b82f6; }
.resumo-modelo-contas {
    font-size: 0.72rem;
    color: #9ca3af;
    font-weight: 400;
}
.resumo-cards-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
}
@media (min-width: 768px) {
    .resumo-cards-grid {
        grid-template-columns: repeat(4, 1fr);
        gap: 16px;
    }
}
@media (min-width: 768px) {
    .resumo-cards-grid {
        grid-template-columns: repeat(4, 1fr);
        gap: 16px;
    }
}

.resumo-card {
    background: #ffffff;
    border-radius: 14px;
    padding: 16px 18px;
    position: relative;
    overflow: hidden;
    border-left: 5px solid transparent;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.resumo-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}
.resumo-card-arealizar {
    border-left-color: #3b82f6;
}
.resumo-card-orcado {
    border-left-color: #f97316;
}

.resumo-card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 6px;
}
.resumo-card-title {
    font-size: 0.78rem;
    font-weight: 600;
    color: #6b7280;
    text-transform: uppercase;
    letter-spacing: 0.3px;
}
/* Icon circles */
.resumo-card-icon-circle {
    width: 36px;
    height: 36px;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
}
.resumo-icon-green {
    background: #dcfce7;
    color: #16a34a;
}
.resumo-icon-blue {
    background: #dbeafe;
    color: #2563eb;
}
.resumo-icon-purple {
    background: #ede9fe;
    color: #7c3aed;
}
.resumo-icon-orange {
    background: #ffedd5;
    color: #ea580c;
}
.resumo-icon-red {
    background: #fee2e2;
    color: #dc2626;
}
.resumo-icon-yellow {
    background: #fef9c3;
    color: #ca8a04;
}
.resumo-card-valor {
    font-size: 1.25rem;
    font-weight: 700;
    color: #111827;
    line-height: 1.2;
    margin-bottom: 2px;
    white-space: nowrap;
}
.resumo-card-sub {
    font-size: 0.78rem;
    color: #6b7280;
}
.resumo-card-var {
    font-size: 0.72rem;
    font-weight: 500;
    margin-top: 6px;
    padding: 3px 8px;
    border-radius: 6px;
    display: inline-block;
}
.var-positivo {
    background: #dcfce7;
    color: #15803d;
}
.var-negativo {
    background: #fef2f2;
    color: #dc2626;
}
.var-info {
    background: #eff6ff;
    color: #2563eb;
}

@media (max-width: 576px) {
    .resumo-card {
        padding: 12px 14px;
    }
    .resumo-card-valor {
        font-size: 1.05rem;
    }
    .resumo-card-icon-circle {
        width: 30px;
        height: 30px;
        border-radius: 8px;
        font-size: 0.85rem;
    }
}

/* ==================== ALERTAS E DESTAQUES ==================== */
.alertas-destaques {
    background: #fff;
    border-radius: 14px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.04);
    padding: 16px 20px;
}
.alertas-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 12px;
    font-size: 0.9rem;
    font-weight: 700;
    color: #1e293b;
}
.alertas-header i {
    color: #f59e0b;
}
.alertas-badges {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
}
.alerta-badge {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    border-radius: 10px;
    font-size: 0.8rem;
    flex: 1;
    min-width: 150px;
}
.alerta-badge strong {
    display: block;
    line-height: 1.2;
    font-size: 0.82rem;
}
.alerta-badge small {
    display: block;
    opacity: 0.75;
    font-size: 0.7rem;
}
.alerta-badge i {
    font-size: 1.15rem;
    flex-shrink: 0;
}
.alerta-badge[data-scroll-kpi] {
    cursor: pointer;
    transition: transform 0.15s, box-shadow 0.15s;
}
.alerta-badge[data-scroll-kpi]:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.alerta-vermelho {
    background: #fef2f2;
    color: #991b1b;
    border: 1px solid #fecaca;
}
.alerta-vermelho i { color: #dc2626; }
.alerta-amarelo {
    background: #fffbeb;
    color: #92400e;
    border: 1px solid #fde68a;
}
.alerta-amarelo i { color: #f59e0b; }
.alerta-verde {
    background: #f0fdf4;
    color: #166534;
    border: 1px solid #bbf7d0;
}
.alerta-verde i { color: #22c55e; }

@media (max-width: 576px) {
    .alertas-badges {
        flex-direction: column;
    }
    .alerta-badge {
        min-width: auto;
    }
}

/* ==================== TENDÊNCIA ==================== */
.tendencia-card {
    background: #ffffff;
    border-radius: 14px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.04);
    padding: 18px 20px;
}
.tendencia-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}
.tendencia-titulo {
    font-size: 0.92rem;
    font-weight: 700;
    color: #1e293b;
}
.tendencia-titulo i {
    color: #8b5cf6;
    margin-right: 4px;
}
.tendencia-toggle {
    display: inline-flex;
    gap: 4px;
    background: #f1f5f9;
    border-radius: 50px;
    padding: 3px;
}
.tendencia-periodo-btn {
    padding: 5px 14px;
    border-radius: 50px;
    font-size: 0.75rem;
    font-weight: 600;
    border: none;
    cursor: pointer;
    transition: all 0.2s ease;
    color: #475569;
    background: transparent;
    white-space: nowrap;
}
.tendencia-periodo-btn:hover {
    color: #0f172a;
    background: #e2e8f0;
}
.tendencia-periodo-btn.active {
    background: #2563eb;
    color: #ffffff;
    box-shadow: 0 1px 4px rgba(37,99,235,0.25);
}
.tendencia-subtitulo-wrap {
    margin-bottom: 10px;
}
.tendencia-subtitulo {
    font-size: 0.78rem;
    color: #94a3b8;
    font-weight: 500;
}
.tendencia-chart-wrap {
    position: relative;
    height: 260px;
}
@media (max-width: 576px) {
    .tendencia-chart-wrap {
        height: 200px;
    }
    .tendencia-card {
        padding: 14px 12px;
    }
    .tendencia-periodo-btn {
        padding: 4px 10px;
        font-size: 0.7rem;
    }
}

/* Separador no toggle de modelo/exibição */
.dash-modelo-sep {
    display: inline-block;
    width: 1px;
    height: 22px;
    background: #cbd5e1;
    margin: 0 4px;
    vertical-align: middle;
    flex-shrink: 0;
}
@media (max-width: 576px) {
    .dash-modelo-sep {
        display: none;
    }
}

/* ==================== DESEMPENHO POR EMPRESA ==================== */
.empresa-desempenho {
    background: #fff;
    border-radius: 14px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.04);
    padding: 16px 20px;
    overflow: hidden;
}
.empresa-desempenho-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: 14px;
}
.empresa-desempenho-titulo {
    font-size: 0.9rem;
    font-weight: 700;
    color: #1e293b;
    display: block;
}
.empresa-desempenho-titulo i {
    color: #2563eb;
    margin-right: 4px;
}
.empresa-desempenho-sub {
    font-size: 0.72rem;
    color: #94a3b8;
    display: block;
    margin-top: 2px;
}
.empresa-desempenho-link {
    font-size: 0.78rem;
    font-weight: 600;
    color: #2563eb;
    text-decoration: none;
    white-space: nowrap;
}
.empresa-desempenho-link:hover {
    text-decoration: underline;
    color: #1d4ed8;
}
.empresa-desempenho-lista {
    display: flex;
    flex-direction: column;
    gap: 0;
}
.empresa-desempenho-item {
    padding: 12px 0;
    border-bottom: 1px solid #f1f5f9;
}
.empresa-desempenho-item:last-child {
    border-bottom: none;
}
.empresa-item-top {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 6px;
}
.empresa-item-info {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    flex: 1;
}
.empresa-item-pos {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: #f1f5f9;
    color: #64748b;
    font-size: 0.68rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.empresa-item-nome {
    font-size: 0.85rem;
    font-weight: 700;
    color: #1e293b;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
.empresa-item-perc {
    font-size: 1rem;
    font-weight: 700;
    flex-shrink: 0;
}
.empresa-item-bar-wrapper {
    height: 6px;
    background: #e5e7eb;
    border-radius: 3px;
    overflow: hidden;
    margin-bottom: 4px;
}
.empresa-item-bar {
    height: 100%;
    border-radius: 3px;
    transition: width 0.4s ease;
    min-width: 2px;
}
.empresa-item-valores {
    font-size: 0.72rem;
    color: #94a3b8;
    text-align: right;
}

/* Tendência: controles side-by-side */
.tendencia-controls {
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
}
@media (max-width: 576px) {
    .tendencia-controls {
        gap: 4px;
    }
    .tendencia-modo-toggle .tendencia-periodo-btn {
        padding: 4px 8px;
        font-size: 0.68rem;
    }
}

/* Legenda do desempenho por empresa */
.empresa-desempenho-legenda {
    display: flex;
    gap: 14px;
    align-items: center;
    margin-bottom: 12px;
    padding: 6px 10px;
    background: #f8fafc;
    border-radius: 8px;
}
.ed-leg-item {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 0.72rem;
    font-weight: 600;
    color: #475569;
}
.ed-leg-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}
.ed-leg-dot-sm {
    width: 6px;
    height: 6px;
    display: inline-block;
    border-radius: 50%;
    margin-right: 2px;
    vertical-align: middle;
}
.ed-leg-dot-xs {
    width: 5px;
    height: 5px;
    display: inline-block;
    border-radius: 50%;
    margin-right: 2px;
    vertical-align: middle;
}

/* Valores resumidos rápidos (Orçado / Realizado / Projetado) */
.empresa-item-resumo {
    display: flex;
    gap: 12px;
    font-size: 0.72rem;
    color: #64748b;
    text-align: right;
    justify-content: flex-end;
    padding: 4px 0 0;
}
.empresa-item-resumo span {
    display: flex;
    align-items: center;
    gap: 2px;
}

/* Cards KPI dentro do detalhe expandível de cada empresa */
.ed-cards-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
}
.ed-card {
    padding: 8px 10px;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    background: #fff;
}
.ed-card-label {
    font-size: 0.65rem;
    color: #6b7280;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    margin-bottom: 2px;
}
.ed-card-value {
    font-size: clamp(0.85rem, 2vw, 1.05rem);
    font-weight: 700;
    line-height: 1.3;
    white-space: nowrap;
}
.ed-card-value-line {
    display: flex;
    align-items: baseline;
    gap: 6px;
}
.ed-card-perc {
    font-size: 0.72rem;
    font-weight: 600;
    white-space: nowrap;
}
.ed-card-sub {
    font-size: 0.65rem;
    color: #9ca3af;
    margin-top: 1px;
}

/* Chevron de expansão */
.ed-chevron {
    font-size: 0.7rem;
    color: #94a3b8;
    transition: transform 0.2s ease;
}
.ed-expanded .ed-chevron {
    transform: rotate(180deg);
}

/* Detalhe expandível */
.empresa-item-detalhe {
    display: none;
    margin-top: 8px;
    padding: 8px 10px;
    background: #f8fafc;
    border-radius: 8px;
}
.ed-expanded .empresa-item-detalhe {
    display: block;
}
.ed-detalhe-titulo {
    font-size: 0.7rem;
    font-weight: 700;
    color: #94a3b8;
    text-transform: uppercase;
    margin-bottom: 6px;
    letter-spacing: 0.3px;
}
.ed-detalhe-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
    border-bottom: 1px solid #e2e8f0;
}
.ed-detalhe-row:last-child {
    border-bottom: none;
}
.ed-detalhe-nome {
    font-size: 0.74rem;
    font-weight: 600;
    color: #334155;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex: 1;
}
.ed-detalhe-vals {
    display: flex;
    gap: 8px;
    flex-shrink: 0;
}
.ed-dv {
    font-size: 0.68rem;
    color: #64748b;
    display: flex;
    align-items: center;
    gap: 1px;
    white-space: nowrap;
}
.ed-detalhe-perc {
    font-size: 0.72rem;
    font-weight: 700;
    flex-shrink: 0;
    min-width: 42px;
    text-align: right;
}

@media (min-width: 768px) {
    /* Desktop: alertas e empresa side by side */
    .alertas-destaques {
        flex: 1;
    }
    .empresa-desempenho {
        flex: 1;
    }
}

/* ==================== BOTTOM NAVIGATION (MOBILE) ==================== */
.dash-bottom-nav {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background: linear-gradient(135deg, #f8fafc 0%, #eef2ff 100%);
    border-top: 1px solid #e2e8f0;
    box-shadow: 0 -2px 10px rgba(0,0,0,0.06);
    display: flex;
    justify-content: space-around;
    align-items: flex-end;
    padding: 5px 4px max(5px, env(safe-area-inset-bottom));
    z-index: 1040;
}
.dash-bottom-nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
    text-decoration: none;
    color: #94a3b8;
    font-size: 0.6rem;
    font-weight: 500;
    padding: 4px 6px 3px;
    border-radius: 10px;
    transition: all 0.2s ease;
    min-width: 48px;
}
.dash-bottom-nav-item i {
    font-size: 1.1rem;
}
.dash-bottom-nav-item:hover {
    color: #475569;
    text-decoration: none;
}
.dash-bottom-nav-item:active {
    transform: scale(0.93);
}
.dash-bottom-nav-item.active {
    color: #2563eb;
    font-weight: 700;
    background: rgba(37, 99, 235, 0.1);
}
.dash-bottom-nav-item.active i {
    color: #2563eb;
}
/* Botão central elevado (visão padrão do usuário) */
.dash-bottom-nav-item.nav-center {
    position: relative;
    margin-top: -18px;
    padding: 0;
    background: none;
    min-width: 56px;
}
.dash-bottom-nav-item.nav-center .nav-center-circle {
    width: 50px;
    height: 50px;
    border-radius: 50%;
    background: linear-gradient(135deg, #f8fafc 0%, #eef2ff 100%);
    border: 1px solid #e2e8f0;
    box-shadow: 0 -3px 10px rgba(37,99,235,0.1), 0 2px 8px rgba(0,0,0,0.06);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s ease;
}
.dash-bottom-nav-item.nav-center i {
    font-size: 1.3rem;
    color: #94a3b8;
}
.dash-bottom-nav-item.nav-center span {
    margin-top: 2px;
}
.dash-bottom-nav-item.nav-center:active .nav-center-circle {
    transform: scale(0.93);
}
.dash-bottom-nav-item.nav-center.active .nav-center-circle {
    background: linear-gradient(135deg, #2563eb 0%, #1e40af 100%);
    border-color: #2563eb;
    box-shadow: 0 -3px 14px rgba(37,99,235,0.3), 0 2px 8px rgba(0,0,0,0.08);
}
.dash-bottom-nav-item.nav-center.active i {
    color: #fff;
}
.dash-bottom-nav-item.nav-center.active {
    color: #2563eb;
    background: none;
}
/* Add bottom padding to page content to prevent bottom nav overlap */
@media (max-width: 767.98px) {
    body {
        padding-bottom: 78px;
    }
}

/* ==================== TRANSIÇÃO MODELO CAROUSEL ==================== */
.emp-modelo-bloco {
    animation: empModeloFadeIn 0.35s ease;
}
@keyframes empModeloFadeIn {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ==================== LISTA COMPACTA + ACCORDION ==================== */
.kpi-lista-container {
    background: #fff;
    border-radius: 14px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.04);
    border: 1px solid rgba(0,0,0,0.04);
    overflow: hidden;
}
.kpi-lista-legenda {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 10px 16px;
    border-bottom: 1px solid #f0f0f0;
    background: #fafbfc;
}
.kpi-lista-leg-item {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 0.72rem;
    font-weight: 600;
    color: #6b7280;
    text-transform: uppercase;
    letter-spacing: 0.3px;
}
.kpi-lista-vals {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 4px;
    flex-wrap: wrap;
}
.kpi-lista-val-item {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.7rem;
    font-weight: 600;
    color: #374151;
    white-space: nowrap;
}
@media (max-width: 576px) {
    .kpi-lista-vals {
        gap: 6px;
    }
    .kpi-lista-val-item {
        font-size: 0.65rem;
    }
}

.kpi-lista-item {
    border-bottom: 1px solid #f0f0f0;
}
.kpi-lista-item:last-child {
    border-bottom: none;
}
.kpi-lista-odd {
    background: #fafbfc;
}
.kpi-lista-even {
    background: #ffffff;
}

.kpi-lista-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 16px;
    cursor: pointer;
    transition: background 0.15s ease;
    user-select: none;
}
.kpi-lista-header:hover {
    background: rgba(59, 130, 246, 0.04);
}

.kpi-lista-info {
    flex: 1;
    min-width: 0;
}

.kpi-lista-nome-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 4px;
}

.kpi-lista-badge {
    display: inline-block;
    font-size: 0.65rem;
    font-weight: 600;
    padding: 2px 6px;
    border-radius: 4px;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    white-space: nowrap;
    flex-shrink: 0;
}
.kpi-badge-meta {
    background: #dbeafe;
    color: #1d4ed8;
}
.kpi-badge-submeta {
    background: #dcfce7;
    color: #15803d;
}
.kpi-badge-resultado {
    background: #e5e7eb;
    color: #374151;
}
.kpi-badge-orcamento {
    background: #fef3c7;
    color: #92400e;
}

.kpi-lista-nome {
    font-size: 0.88rem;
    font-weight: 600;
    color: #1f2937;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.kpi-lista-origem {
    font-size: 0.72rem;
    color: #6b7280;
    margin-bottom: 4px;
}
.kpi-lista-origem i {
    font-size: 0.68rem;
}

.kpi-lista-barra-wrapper {
    height: 6px;
    background: #e5e7eb;
    border-radius: 3px;
    overflow: hidden;
    width: 100%;
}

.kpi-lista-barra {
    height: 100%;
    border-radius: 3px;
    transition: width 0.3s ease;
    min-width: 2px;
}

.kpi-lista-resumo {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-shrink: 0;
}

.kpi-lista-perc {
    font-size: 1.05rem;
    font-weight: 700;
    white-space: nowrap;
    min-width: 60px;
    text-align: right;
}

.kpi-lista-saldo {
    font-size: 0.78rem;
    font-weight: 500;
    white-space: nowrap;
    min-width: 80px;
    text-align: right;
}

.kpi-lista-chevron {
    font-size: 0.75rem;
    color: #9ca3af;
    transition: transform 0.2s ease;
    flex-shrink: 0;
}
.kpi-lista-item.kpi-lista-open .kpi-lista-chevron {
    transform: rotate(180deg);
}

/* Painel de detalhe (accordion) */
.kpi-lista-detail {
    border-top: 1px solid #e5e7eb;
    background: #f8fafc;
}

.kpi-lista-detail-inner {
    border-radius: 0 !important;
    box-shadow: none !important;
    border: none !important;
    background: transparent !important;
}

.kpi-lista-detail-inner .card-body {
    padding: 12px 16px !important;
}

/* Animação suave de expansão */
.kpi-lista-detail[style*="display: block"],
.kpi-lista-detail[style*="display:block"] {
    animation: kpiSlideDown 0.2s ease-out;
}

@keyframes kpiSlideDown {
    from { opacity: 0; max-height: 0; }
    to { opacity: 1; max-height: 600px; }
}

/* Mobile: ajustes */
@media (max-width: 576px) {
    .kpi-lista-header {
        padding: 10px 12px;
        gap: 8px;
    }
    .kpi-lista-nome {
        font-size: 0.82rem;
    }
    .kpi-lista-perc {
        font-size: 0.95rem;
        min-width: 52px;
    }
    .kpi-lista-saldo {
        font-size: 0.72rem;
        min-width: 65px;
    }
    .kpi-lista-detail-inner .card-body {
        padding: 10px 12px !important;
    }
}

/* Grid responsivo para cards de metas */
.dashboard-metas-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 12px;
}
@media (min-width: 768px) {
    .dashboard-metas-grid {
        grid-template-columns: repeat(2, minmax(300px, 1fr));
    }
}
@media (min-width: 992px) {
    .dashboard-metas-grid {
        grid-template-columns: repeat(3, minmax(320px, 1fr));
    }
}
@media (min-width: 1400px) {
    .dashboard-metas-grid {
        grid-template-columns: repeat(4, minmax(340px, 1fr));
    }
}

/* Histórico dos últimos 7 dias - Tabela estilo planilha compacta */
.historico-tabela {
    width: 100%;
    min-width: auto;
    border-collapse: collapse;
    font-size: 0.8rem;
    margin: 0;
    padding: 0;
}

.historico-tabela tbody tr {
    margin: 0;
    padding: 0;
}

.historico-tabela td {
    padding: 2px 1px;
    text-align: center;
    vertical-align: middle;
    border: none;
    margin: 0;
    white-space: nowrap;
}

/* Zebra striping - cards consolidado */
#dashboardConsolidadoComparativo > .card:nth-child(odd) {
    background: #f7f8fb;
}
#dashboardConsolidadoComparativo > .card:nth-child(even) {
    background: #ffffff;
}

/* Zebra striping nas linhas (alternância de fundo) */
.historico-tabela tbody tr:nth-child(odd) {
    background-color: #f8f9fa;
}
.historico-tabela tbody tr:nth-child(even) {
    background-color: #ffffff;
}

.historico-dia-data {
    font-size: 0.7rem;
    color: #64748b;
    font-weight: 500;
    white-space: nowrap;
    line-height: 1;
    margin: 0;
    padding: 0;
    text-transform: lowercase;
}

.historico-dia-valor {
    font-size: 1.1rem;
    font-weight: 600;
    color: #000;
    white-space: nowrap;
    line-height: 1.1;
    margin: 0;
    padding: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.historico-dia-perc {
    font-size: 1.0rem;
    font-weight: 700;
    white-space: nowrap;
    line-height: 1.1;
    margin: 0;
    padding: 0;
}

.historico-dia-falta {
    font-size: 0.78rem;
    font-weight: 600;
    white-space: nowrap;
    line-height: 1.1;
    margin: 0;
    padding: 0;
    opacity: 0.85;
}

/* Dia Corrente - Meta Diária */
.dia-corrente-box {
    padding-bottom: 4px;
}
.dia-corrente-kpi {
    border-top: 1px solid #e5e7eb;
    padding-top: 6px;
    margin-top: 2px;
}

/* Mobile: reduz ainda mais */
@media (max-width: 576px) {
    .historico-tabela {
        font-size: 0.75rem;
    }
    .historico-tabela td {
        padding: 1px 0.5px;
    }
    .historico-dia-data {
        font-size: 0.65rem;
    }
    .historico-dia-valor {
        font-size: 0.95rem;
    }
}


/* Card horizontal estilo imagem */
.dashboard-card-horizontal {
    border-radius: 8px;
    box-shadow: 0 1px 4px rgba(0,0,0,0.03);
    min-height: 160px;
}

/* Zebra striping - alterna cor nos donut cards do grid */
.dashboard-metas-grid > .dashboard-card-horizontal:nth-child(odd),
.dashboard-metas-grid > .card:nth-child(odd) {
    background: linear-gradient(145deg, #f2f4f8, #f7f8fb) !important;
}
.dashboard-metas-grid > .dashboard-card-horizontal:nth-child(even),
.dashboard-metas-grid > .card:nth-child(even) {
    background: linear-gradient(145deg, #f8f9fa, #ffffff) !important;
}
.dashboard-card-horizontal:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(0,0,0,0.08);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.dashboard-card-horizontal .card-body {
    padding: 16px;
}
.dashboard-chart-wrapper-donut-horizontal {
    position: relative;
    width: 140px;
    height: 140px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}
.dashboard-chart-wrapper-donut-horizontal canvas {
    max-width: 100%;
    max-height: 100%;
}
.donut-metric-horizontal {
    font-size: 2rem;
    font-weight: 700;
    line-height: 1;
}
.donut-legend-horizontal {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}
.donut-legend-horizontal .legend-item-horizontal {
    display: flex;
    align-items: center;
    gap: 8px;
    color: #6b7280;
    font-size: 0.9rem;
    min-width: 0;
}
.donut-legend-horizontal .legend-item-horizontal span:first-child {
    flex-shrink: 0;
}
.donut-legend-horizontal .legend-item-horizontal span:nth-child(2) {
    min-width: 0;
    flex: 0 1 auto;
}
.donut-legend-horizontal .legend-item-horizontal span:last-child {
    white-space: nowrap;
    font-weight: 600;
}
.donut-legend-horizontal .legend-box-horizontal {
    width: 16px;
    height: 6px;
    border-radius: 2px;
    display: inline-block;
    flex-shrink: 0;
}

/* Responsividade para mobile */
@media (max-width: 768px) {
    .dashboard-card-horizontal {
        min-height: auto;
    }
    .dashboard-card-horizontal .card-body {
        flex-direction: column;
        gap: 1rem;
        padding: 12px;
    }
    .dashboard-chart-wrapper-donut-horizontal {
        width: 120px;
        height: 120px;
    }
    .donut-metric-horizontal {
        font-size: 1.75rem;
    }
    .donut-legend-horizontal .legend-item-horizontal {
        font-size: 0.85rem;
    }
}
.kpi-card {
    background: linear-gradient(135deg, #f8fafc, #ffffff);
    border-radius: 8px;
}
.dashboard-chart-wrapper-line {
    position: relative;
    height: 280px;
}
.kpi-label {
    letter-spacing: 0.03em;
}
.kpi-icon {
    font-size: 1.2rem;
}
.dashboard-chart-wrapper {
    position: relative;
    height: 260px;
}
/* Grid super compacto para cards em desktop */
#dashboardChartsContainer .row.g-3 {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 10px;
    align-items: stretch;
}
#dashboardChartsContainer .col-12.col-sm-6.col-lg-4.col-xl-3 {
    padding: 0;
    margin: 0;
}
.dashboard-card .card-body {
    padding: 8px 8px 6px 8px;
}
.dashboard-card .mb-2, .dashboard-card .mb-1, .dashboard-card .mb-0 {
    margin-bottom: 0.18rem !important;
}
.dashboard-card .small {
    font-size: 0.92em;
}
.dashboard-card .fw-semibold {
    font-weight: 500 !important;
}
/* Pequenas interações para desktop */
.dashboard-card {
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.dashboard-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(0,0,0,0.08);
}
/* Melhorias de layout para desktop (estilo semelhante ao mobile) */
@media (min-width: 992px) {
    #dashboardCardsContainer .row.g-3 {
        grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
        gap: 12px;
    }
    .dashboard-card {
        border-radius: 12px;
        box-shadow: 0 2px 10px rgba(0,0,0,0.06);
        padding: 16px 14px 10px 14px;
        background: linear-gradient(145deg, #f8fafc, #ffffff);
    }
    .dashboard-card .card-body {
        padding: 0; /* já aplicamos padding no card para ficar como mobile */
    }
    .dashboard-card .small {
        font-size: 0.95em;
    }
}
@media (min-width: 1200px) {
    #dashboardCardsContainer .row.g-3 {
        grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
        gap: 16px;
    }
}
@media (min-width: 1400px) {
    .dashboard-chart-wrapper {
        height: 320px;
    }
    #dashboardCardsContainer .row.g-3 {
        grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    }
}
@media (max-width: 768px) {
    .dashboard-card {
        border-radius: 10px;
        padding: 16px 10px 0 10px;
    }
    .kpi-card {
        border-radius: 10px;
    }
    .dashboard-chart-wrapper-line {
        height: 220px;
    }
    .dashboard-chart-wrapper {
        height: 220px;
    }
    .dashboard-chart-wrapper-donut {
        max-width: 200px;
    }
    .kpi-icon {
        font-size: 1.2rem;
    }
    #dashboardCardsContainer .row.g-3 {
        display: flex;
        flex-wrap: wrap;
        gap: 1rem;
    }
    #dashboardCardsContainer .col-12.col-sm-6.col-lg-4.col-xl-3 {
        width: 100%;
        max-width: 100%;
    }
}
.dashboard-chart-wrapper-donut {
    position: relative;
    width: 100%;
    max-width: 240px;
    aspect-ratio: 1 / 1;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
}
.dashboard-chart-wrapper-donut canvas {
    max-width: 100%;
    max-height: 100%;
}
.chart-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 10px;
    align-items: stretch;
}
/* Grid responsivo para os cards de variáveis */
.kpi-variable-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 12px;
}

@media (min-width: 768px) {
    .kpi-variable-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: 14px;
    }
}

@media (min-width: 992px) {
    .kpi-variable-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: 16px;
    }
}

@media (min-width: 1400px) {
    .kpi-variable-grid {
        grid-template-columns: repeat(3, 1fr);
        gap: 18px;
    }
}

@media (min-width: 1800px) {
    .kpi-variable-grid {
        grid-template-columns: repeat(4, 1fr);
        gap: 20px;
    }
}

/* Estilo dos KPI Cards */
.kpi-variable-card {
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.05);
    border: 1px solid rgba(0,0,0,0.04);
    overflow: hidden;
    transition: box-shadow 0.2s ease;
}

/* Zebra striping - alterna cor nos cards do grid */
.kpi-variable-grid > .kpi-variable-card:nth-child(odd) {
    background: #f7f8fb;
}
.kpi-variable-grid > .kpi-variable-card:nth-child(even) {
    background: #ffffff;
}

.kpi-variable-card:hover {
    box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}

.kpi-variable-card .card-body {
    padding: 12px;
}

.kpi-variable-card h5 {
    font-size: 13px;
    font-weight: 700;
    margin-bottom: 6px;
    line-height: 1.15;
}

.kpi-variable-card .small {
    font-size: 0.75rem;
}

/* ==== ORÇAMENTO CONSOLIDADO - CARD SEÇÃO GRÁFICOS ==== */
.dashboard-card-orcamento-consolidado {
    border: 1px solid rgba(0, 0, 0, 0.06);
}

.dashboard-card-orcamento-consolidado:hover {
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08) !important;
}

/* Layout em duas colunas para detalhamento */
.orc-detalhado-container {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
    align-items: start;
}

/* Coluna Esquerda: Barras Horizontais */
.orc-detalhado-barras {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.orc-linha-item {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.orc-nome-conta {
    font-size: 0.8rem;
    color: #4b5563;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    max-width: 100%;
}

.orc-barra-horizontal-wrapper {
    position: relative;
    height: 24px;
}

.orc-barra-horizontal-fundo {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: #f3f4f6;
    border-radius: 4px;
    border: 1px solid #e5e7eb;
    z-index: 0;
}

.orc-barra-horizontal-container {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    z-index: 1;
}

.orc-barra-horizontal {
    height: 100%;
    border-radius: 3px;
    transition: width 0.3s ease;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
    min-width: 2px;
}

/* Cores das barras baseadas no percentual */
.orc-barra-verde {
    color: #059669;
}

.orc-barra-amarelo {
    color: #d97706;
}

.orc-barra-vermelho {
    color: #dc2626;
}

.orc-percentual-barra {
    font-size: 0.75rem;
    text-align: right;
    padding-right: 2px;
}

.orc-percentual-barra.orc-barra-verde {
    color: #059669;
}

.orc-percentual-barra.orc-barra-amarelo {
    color: #d97706;
}

.orc-percentual-barra.orc-barra-vermelho {
    color: #dc2626;
}

/* Coluna Direita: Valores */
.orc-detalhado-valores {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding-left: 12px;
    border-left: 1px solid #f3f4f6;
}

.orc-linha-valores {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    font-size: 0.8rem;
}

.orc-valor-item {
    text-align: center;
    padding: 6px;
    background: #f9fafb;
    border-radius: 4px;
    border: 1px solid #e5e7eb;
}

.orc-valor-item .text-muted {
    font-size: 0.65rem;
    margin-bottom: 2px;
}

.orc-valor-item .fw-semibold {
    font-size: 0.8rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Responsividade para tablet/mobile */
@media (max-width: 1024px) {
    .orc-detalhado-container {
        grid-template-columns: 1fr;
        gap: 16px;
    }
    
    .orc-detalhado-valores {
        border-left: none;
        border-top: 1px solid #f3f4f6;
        padding-left: 0;
        padding-top: 12px;
    }
}

@media (max-width: 768px) {
    .orc-detalhado-container {
        gap: 12px;
    }
    
    .orc-linha-valores {
        grid-template-columns: repeat(3, 1fr);
        gap: 6px;
    }
    
    .orc-valor-item {
        padding: 4px;
        font-size: 0.75rem;
    }
    
    .orc-barra-horizontal-wrapper {
        height: 20px;
    }
    
    .dashboard-card-horizontal .card-body {
        padding: 12px;
    }
}

/* Grid super compacto em mobile */
@media (max-width: 576px) {
    .orc-linha-item {
        gap: 3px;
    }
    
    .orc-nome-conta {
        font-size: 0.7rem;
    }
    
    .orc-barra-horizontal-wrapper {
        height: 18px;
    }
    
    .orc-percentage {
        font-size: 0.65rem;
    }
    
    .orc-linha-valores {
        grid-template-columns: repeat(3, 1fr);
        gap: 4px;
    }
}

/* Grid compacto em blocos de 2 colunas */

.kpi-compact {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.kpi-row {
    display: grid;
    grid-template-columns: repeat(2, minmax(120px, 1fr));
    gap: 8px 12px;
    align-items: start;
    padding: 6px 4px;
    border-radius: 6px;
}

/* % inline ao lado do valor Realizado */
.kpi-perc-inline {
    font-size: 0.78rem;
    font-weight: 600;
    white-space: nowrap;
    opacity: 0.9;
}

.kpi-cell {
    padding: 8px 10px;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    background: transparent;
    min-width: 0;
}

.kpi-value-line {
    display: flex;
    align-items: baseline;
    gap: 8px;
    min-width: 0;
}

.kpi-sub {
    font-size: 0.72rem;
    color: #6b7280;
    margin-top: 2px;
}

.kpi-progress-inline {
    margin-top: 4px;
}

@media (max-width: 540px) {
    .kpi-row {
        grid-template-columns: repeat(2, minmax(140px, 1fr));
        gap: 10px 12px;
    }
    .kpi-cell {
        padding: 8px 10px;
    }
    .kpi-compact {
        gap: 10px;
    }
}

/* Desktop: mais espaço e melhor distribuição */
@media (min-width: 992px) {
    .kpi-variable-card .card-body {
        padding: 16px 18px;
    }
    
    .kpi-variable-card h5 {
        font-size: 15px;
        margin-bottom: 8px;
    }
    
    .kpi-row { 
        gap: 10px 16px;
    }
}

/* Telas grandes: layout mais respirado */
@media (min-width: 1400px) {
    .kpi-variable-card .card-body {
        padding: 18px 20px;
    }
    
    .kpi-variable-card h5 {
        font-size: 16px;
    }
    
    .kpi-row { 
        gap: 12px 18px;
    }
}

/* ── Per-company breakdown inside KPI accordion ── */
.kpi-emp-legenda {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    padding: 7px 10px;
    background: #f8f9fa;
    border-radius: 8px;
    margin-bottom: 8px;
}
.kpi-emp-leg-item {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 0.78rem;
    color: #374151;
    white-space: nowrap;
}
.kpi-emp-leg-item .ed-leg-dot-xs {
    width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
}
.kpi-emp-leg-item strong { font-weight: 700; }
.kpi-emp-lista {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.kpi-emp-row {
    background: #fff;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    padding: 7px 10px;
}
.kpi-emp-row-header {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 4px;
}
.kpi-emp-dot {
    width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
}
.kpi-emp-nome {
    flex: 1;
    font-size: 0.78rem;
    font-weight: 600;
    color: #1f2937;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.kpi-emp-perc {
    font-size: 0.82rem;
    font-weight: 700;
    white-space: nowrap;
}
.kpi-emp-bar-wrap {
    height: 5px;
    background: #e5e7eb;
    border-radius: 3px;
    overflow: hidden;
    margin-bottom: 5px;
}
.kpi-emp-bar {
    height: 100%;
    border-radius: 3px;
    transition: width .3s;
}
.kpi-emp-vals {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 12px;
    font-size: 0.73rem;
    color: #4b5563;
}
.kpi-emp-vals .ed-leg-dot-xs {
    width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
}
.kpi-emp-vals span {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    white-space: nowrap;
}

/* Toggle de período (Mês/Ano) */
.kpi-period-toggle {
    border-radius: 5px;
    overflow: hidden;
}

.kpi-period-toggle .btn {
    padding: 3px 8px;
    font-size: 0.8rem;
    border: none;
}

.kpi-period-toggle .btn.active {
    background-color: #495057;
    color: white;
    border-color: #495057;
}

/* Items de KPI */
.kpi-item {
    text-align: left;
    display: flex;
    flex-direction: column;
    gap: 0px;
}

.kpi-label {
    font-size: 0.7rem;
    color: #6b7280;
    font-weight: 600;
    line-height: 1.1;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    margin-bottom: 2px;
}

.kpi-value {
    font-size: clamp(0.8rem, 1.5vw, 1.1rem);
    font-weight: 700;
    line-height: 1.25;
    white-space: nowrap;
    max-width: 100%;
}

/* Mobile: valores mais compactos */
@media (max-width: 480px) {
    .kpi-value {
        font-size: clamp(1.05rem, 3vw, 1.25rem);
    }
    
    .kpi-label {
        font-size: 0.65rem;
    }
}

/* Tablet: tamanho intermediário */
@media (min-width: 481px) and (max-width: 991px) {
    .kpi-value {
        font-size: clamp(0.75rem, 1.5vw, 1.0rem);
    }
}

/* Desktop: valores maiores e mais legíveis */
@media (min-width: 992px) {
    .kpi-value {
        font-size: clamp(0.9rem, 1.3vw, 1.2rem);
    }
    
    .kpi-label {
        font-size: 0.75rem;
        margin-bottom: 3px;
    }
}

/* Telas grandes: máxima legibilidade */
@media (min-width: 1400px) {
    .kpi-value {
        font-size: clamp(1.0rem, 1.2vw, 1.3rem);
    }
    
    .kpi-label {
        font-size: 0.78rem;
    }
}

.kpi-value.text-success,
.kpi-value.text-warning,
.kpi-value.text-danger {
    font-weight: 700;
}

.kpi-item small {
    font-size: 0.68rem;
    line-height: 1.2;
    color: #6b7280;
    margin-top: 2px;
    word-wrap: break-word;
    overflow-wrap: break-word;
}

@media (min-width: 992px) {
    .kpi-item small {
        font-size: 0.72rem;
        margin-top: 3px;
    }
}

@media (min-width: 1400px) {
    .kpi-item small {
        font-size: 0.75rem;
    }
}

/* Barra de Progresso Subtle */
.kpi-progress-bar {
    height: 4px;
    background-color: #e5e7eb;
    border-radius: 2px;
    overflow: hidden;
    cursor: pointer;
    position: relative;
    margin-top: 8px;
}

.kpi-progress-bar .progress-indicator {
    height: 100%;
    border-radius: 2px;
    transition: width 0.3s ease;
}

.kpi-progress-bar:hover .progress-indicator {
    box-shadow: 0 0 4px rgba(0,0,0,0.15);
}

@media (min-width: 992px) {
    .kpi-progress-bar {
        margin-top: 10px;
    }
}

/* ==================== VISÃO PERCENTUAL ==================== */
/* Ocultar valores monetários quando em modo percentual */
.visao-percentual .dado-valor {
    display: none !important;
}
.visao-percentual .dado-valor-line {
    display: none !important;
}

/* Ocultar valores monetários nos históricos (últimos 7 dias) */
.visao-percentual .historico-dia-valor {
    display: none !important;
}

/* KPI Cards: em modo percentual, as linhas monetárias são controladas via PHP */

/* Barras de progresso (Orçamento/Submeta): expandir coluna de barras para ocupar espaço todo */
.visao-percentual .orc-detalhado-container {
    grid-template-columns: 1fr !important;
}

/* Ajustar cards de donuts para manter apenas percentuais visíveis */
.visao-percentual .feriados-toggle + div .text-end.dado-valor {
    display: none !important;
}

/* ==================== VISÃO PLANILHA ==================== */
.table-planilha {
    font-size: 0.9rem;
    border-collapse: collapse;
}

.table-planilha thead th {
    background: #f8f9fa;
    font-weight: 600;
    color: #495057;
    padding: 0.75rem 0.5rem;
    border: 1px solid #dee2e6;
    vertical-align: middle;
}

.table-planilha tbody td {
    padding: 0.6rem 0.5rem;
    border: 1px solid #dee2e6;
    vertical-align: middle;
}

/* Zebra striping linhas planilha desktop - controlado via JS por grupo empresa */
.table-planilha tbody tr.pv-zebra-odd,
.table-planilha tbody tr.pv-zebra-odd > td {
    background-color: #f0f2f6 !important;
    --bs-table-bg: #f0f2f6;
    --bs-table-accent-bg: #f0f2f6;
}
.table-planilha tbody tr.pv-zebra-even,
.table-planilha tbody tr.pv-zebra-even > td {
    background-color: #ffffff !important;
    --bs-table-bg: #ffffff;
    --bs-table-accent-bg: #ffffff;
}
.table-planilha tbody tr.pv-zebra-odd td.pv-empresa {
    background-color: #e8eaf0 !important;
}
.table-planilha tbody tr.pv-zebra-even td.pv-empresa {
    background-color: #f8f9fa !important;
}

.table-planilha tbody tr:hover > td {
    background: #e2e6ed !important;
    --bs-table-hover-bg: #e2e6ed;
}

/* Bordas mais grossas para separar empresas e períodos */
.table-planilha th[rowspan],
.table-planilha td[rowspan] {
    font-weight: 600;
}

/* Cabeçalhos de período com cores diferenciadas */
.table-planilha .bg-info.bg-opacity-10 {
    background-color: rgba(13, 202, 240, 0.1) !important;
}

.table-planilha .bg-warning.bg-opacity-10 {
    background-color: rgba(255, 193, 7, 0.1) !important;
}

.table-planilha .bg-success.bg-opacity-10 {
    background-color: rgba(25, 135, 84, 0.1) !important;
}

/* Responsividade da tabela planilha */
@media (max-width: 1400px) {
    .table-planilha {
        font-size: 0.85rem;
    }
    
    .table-planilha thead th,
    .table-planilha tbody td {
        padding: 0.5rem 0.4rem;
    }
}

@media (max-width: 992px) {
    .table-planilha {
        font-size: 0.8rem;
    }
    
    .table-planilha thead th,
    .table-planilha tbody td {
        padding: 0.4rem 0.3rem;
        min-width: 90px !important;
    }
}
</style>

<!-- Modal Sincronização Automática -->
<div class="modal fade" id="modalSyncAuto" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false">
  <div class="modal-dialog modal-md modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header bg-warning py-2">
        <h6 class="modal-title"><i class="bi bi-arrow-repeat"></i> Sincronizando ERP (período automático)</h6>
        <button type="button" class="btn-close" data-bs-dismiss="modal" id="btnFecharSync"></button>
      </div>
      <div class="modal-body">
        <div id="syncResultado" class="small"></div>
        <div class="mt-3" id="syncProgresso" style="display:none;">
          <div class="progress mb-2" style="height: 6px;">
            <div class="progress-bar progress-bar-striped progress-bar-animated bg-warning" role="progressbar" style="width: 0%;"></div>
          </div>
          <ul class="small mb-0" id="syncEtapas">
            <li data-step="preparar">1) Preparando sincronização...</li>
            <li data-step="sincronizar">2) Sincronizando com ERP...</li>
            <li data-step="consolidar">3) Consolidando dados...</li>
            <li data-step="atualizar">4) Atualizando dashboard...</li>
          </ul>
        </div>
      </div>
      <div class="modal-footer py-2">
        <button class="btn btn-secondary btn-sm" data-bs-dismiss="modal" id="btnFecharSyncFooter">Fechar</button>
      </div>
    </div>
  </div>
</div>

<!-- ==================== BARRA DE NAVEGAÇÃO INFERIOR (MOBILE) ==================== -->
<nav class="dash-bottom-nav d-md-none" id="dashBottomNav">
    <?php
    $_bottomItems = [
        ['visao' => '', 'icon' => 'bi-house-fill', 'label' => 'Home', 'href' => '?m=home'],
        ['visao' => 'variavel', 'icon' => 'bi-card-list', 'label' => 'Detalhado'],
        ['visao' => 'modelo', 'icon' => 'bi-columns-gap', 'label' => 'Consolidado'],
        ['visao' => 'percentual', 'icon' => 'bi-percent', 'label' => 'Percentual'],
        ['visao' => 'planilha', 'icon' => 'bi-table', 'label' => 'Planilha'],
    ];
    // Determinar a visão padrão do usuário para o botão central
    $_visaoPadraoNav = $_SESSION['visao_padrao'] ?? 'variavel';
    // Filtrar itens visíveis
    $_navVisible = [];
    foreach ($_bottomItems as $_bItem) {
        $_bVisao = $_bItem['visao'] ?: 'variavel';
        if ($_bItem['visao'] !== '' && !in_array($_bVisao, $visoesUsuario, true)) continue;
        $_navVisible[] = $_bItem;
    }
    // Encontrar índice do item padrão (ignorar Home que tem visao vazia)
    $_centerIdx = -1;
    foreach ($_navVisible as $_i => $_bItem) {
        if ($_bItem['visao'] !== '' && $_bItem['visao'] === $_visaoPadraoNav) { $_centerIdx = $_i; break; }
    }
    // Se não encontrou, colocar no meio
    if ($_centerIdx < 0) $_centerIdx = (int)(count($_navVisible) / 2);
    // Balancear: mover o item padrão para o centro geométrico
    $_navCenter = $_navVisible[$_centerIdx];
    $_others = array_values(array_filter($_navVisible, fn($v, $k) => $k !== $_centerIdx, ARRAY_FILTER_USE_BOTH));
    $_half = (int)ceil(count($_others) / 2);
    $_navLeft = array_slice($_others, 0, $_half);
    $_navRight = array_slice($_others, $_half);
    // Render esquerda
    foreach ($_navLeft as $_bItem):
        $_bActive = false;
        if ($_bItem['visao'] === '' && $visaoDashboard === 'variavel') $_bActive = true;
        elseif ($_bItem['visao'] !== '' && $visaoDashboard === $_bItem['visao']) $_bActive = true;
        $_bHref = isset($_bItem['href']) ? $_bItem['href'] : htmlspecialchars(urlComVisaoDashboard($_bItem['visao'] ?: 'variavel'));
    ?>
    <a href="<?= $_bHref ?>" class="dash-bottom-nav-item <?= $_bActive ? 'active' : '' ?>">
        <i class="bi <?= $_bItem['icon'] ?>"></i>
        <span><?= $_bItem['label'] ?></span>
    </a>
    <?php endforeach; ?>
    <?php // Render centro (elevado)
    if ($_navCenter):
        $_bActive = false;
        if ($_navCenter['visao'] === '' && $visaoDashboard === 'variavel') $_bActive = true;
        elseif ($_navCenter['visao'] !== '' && $visaoDashboard === $_navCenter['visao']) $_bActive = true;
        $_bHref = isset($_navCenter['href']) ? $_navCenter['href'] : htmlspecialchars(urlComVisaoDashboard($_navCenter['visao'] ?: 'variavel'));
    ?>
    <a href="<?= $_bHref ?>" class="dash-bottom-nav-item nav-center <?= $_bActive ? 'active' : '' ?>">
        <div class="nav-center-circle"><i class="bi <?= $_navCenter['icon'] ?>"></i></div>
        <span><?= $_navCenter['label'] ?></span>
    </a>
    <?php endif; ?>
    <?php // Render direita
    foreach ($_navRight as $_bItem):
        $_bActive = false;
        if ($_bItem['visao'] === '' && $visaoDashboard === 'variavel') $_bActive = true;
        elseif ($_bItem['visao'] !== '' && $visaoDashboard === $_bItem['visao']) $_bActive = true;
        $_bHref = isset($_bItem['href']) ? $_bItem['href'] : htmlspecialchars(urlComVisaoDashboard($_bItem['visao'] ?: 'variavel'));
    ?>
    <a href="<?= $_bHref ?>" class="dash-bottom-nav-item <?= $_bActive ? 'active' : '' ?>">
        <i class="bi <?= $_bItem['icon'] ?>"></i>
        <span><?= $_bItem['label'] ?></span>
    </a>
    <?php endforeach; ?>
</nav>

<!-- Chart.js e inicialização dos gráficos do dashboard -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
<script>
    const dashboardChartData = <?= json_encode($chartData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>; // atualmente não usado, mantido para futuras evoluções
    const dashboardMoeda     = <?= json_encode($moeda, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
    const dashboardAnoRef    = <?= (int)$anoref ?>;
    const dashboardMesNome   = <?= json_encode($nomeMesAtual, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
    const dashboardMetas = <?= json_encode($metasCharts, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
    const dashboardSerieYtd  = <?= json_encode($serieYtd, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
    const dashboardModelo    = 'meta';
    const dashboardVisao      = <?= json_encode($visaoDashboard, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
    const dashboardConsolidadoComparativo = <?= json_encode(($dashboardConsolidadoComparativo ?? []), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PARTIAL_OUTPUT_ON_ERROR | JSON_INVALID_UTF8_SUBSTITUTE) ?>;
    const dashboardOrcamentoTermometro = <?= json_encode(($orcamentoTermometro ?? []), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PARTIAL_OUTPUT_ON_ERROR | JSON_INVALID_UTF8_SUBSTITUTE) ?>;
    
    // Função de linguagem dinâmica
    function getLinguagem(modelo) {
        if (modelo === 'meta') {
            return {
                realizado: 'Realizado',
                restante: 'A Realizar'
            };
        }
        return {
            realizado: 'Gasto Realizado',
            restante: 'Saldo Disponível'
        };
    }
    
    const dashboardLinguagem = getLinguagem(dashboardModelo);

    document.addEventListener('DOMContentLoaded', function () {
        // Toggle Mês/Ano nos KPI Cards
        function initKpiToggle() {
            document.querySelectorAll('.kpi-period-toggle').forEach((toggle) => {
                toggle.querySelectorAll('.btn').forEach((btn) => {
                    btn.addEventListener('click', (e) => {
                        e.preventDefault();
                        const period = btn.getAttribute('data-period');
                        const card = btn.closest('.kpi-variable-card');
                        if (!card) return;
                        
                        // Remove active de todos os botões do toggle
                        toggle.querySelectorAll('.btn').forEach((b) => {
                            b.classList.remove('active');
                        });
                        // Marca o clicado como ativo
                        btn.classList.add('active');
                        
                        // Oculta todos os períodos
                        card.querySelectorAll('.kpi-period-content').forEach((content) => {
                            content.classList.add('d-none');
                        });
                        // Mostra o período selecionado
                        const contentToShow = card.querySelector(`.kpi-period-content[data-period="${period}"]`);
                        if (contentToShow) {
                            contentToShow.classList.remove('d-none');
                        }
                    });
                });
            });
        }
        
        // Accordion toggle para lista compacta de contas
        function initKpiListaAccordion() {
            document.querySelectorAll('[data-toggle-kpi]').forEach(function(header) {
                header.addEventListener('click', function(e) {
                    // Não disparar se clicou num botão interno
                    if (e.target.closest('.kpi-period-toggle')) return;
                    
                    var kpiId = header.getAttribute('data-toggle-kpi');
                    var item = header.closest('.kpi-lista-item');
                    var detail = document.getElementById('kpi-detail-' + kpiId);
                    if (!detail || !item) return;
                    
                    var isOpen = item.classList.contains('kpi-lista-open');
                    
                    if (isOpen) {
                        detail.style.display = 'none';
                        item.classList.remove('kpi-lista-open');
                        header.setAttribute('aria-expanded', 'false');
                    } else {
                        detail.style.display = 'block';
                        item.classList.add('kpi-lista-open');
                        header.setAttribute('aria-expanded', 'true');
                    }
                });
                
                // Suporte a teclado (Enter/Space)
                header.addEventListener('keydown', function(e) {
                    if (e.key === 'Enter' || e.key === ' ') {
                        e.preventDefault();
                        header.click();
                    }
                });
            });
        }
        
        // ==================== SWIPE MOBILE POR MODELO (cards + empresa) ====================
        var _modeloCarousel = null;
        function initModeloCarousel() {
            var btns = document.querySelectorAll('[data-modelo-filter]');
            if (!btns || btns.length <= 2) return; // "Todos" + apenas 1 modelo = não precisa

            // Coletar modelos específicos (excluir "todos")
            var modeloBtns = [];
            btns.forEach(function(b) {
                var m = b.getAttribute('data-modelo-filter');
                if (m && m !== 'todos') modeloBtns.push(b);
            });
            if (modeloBtns.length <= 1) return;

            var currentIdx = 0;

            function switchModelo(idx) {
                idx = ((idx % modeloBtns.length) + modeloBtns.length) % modeloBtns.length;
                currentIdx = idx;
                modeloBtns[idx].click();
                var modelo = modeloBtns[idx].getAttribute('data-modelo-filter');
                document.querySelectorAll('[data-emp-modelo]').forEach(function(blk) {
                    blk.style.display = (blk.getAttribute('data-emp-modelo') === modelo) ? '' : 'none';
                });
            }

            // Sincronizar índice ao clicar manualmente nos botões
            btns.forEach(function(btn) {
                btn.addEventListener('click', function() {
                    var modelo = btn.getAttribute('data-modelo-filter');
                    if (modelo === 'todos') {
                        document.querySelectorAll('[data-emp-modelo]').forEach(function(blk) {
                            blk.style.display = (blk.getAttribute('data-emp-modelo') === _modeloAtivo) ? '' : 'none';
                        });
                        return;
                    }
                    for (var i = 0; i < modeloBtns.length; i++) {
                        if (modeloBtns[i].getAttribute('data-modelo-filter') === modelo) {
                            currentIdx = i;
                            break;
                        }
                    }
                    document.querySelectorAll('[data-emp-modelo]').forEach(function(blk) {
                        blk.style.display = (blk.getAttribute('data-emp-modelo') === modelo) ? '' : 'none';
                    });
                });
            });

            // ===== SWIPE/DRAG horizontal em qualquer lugar da tela =====
            var startX = 0;
            var startY = 0;
            var startTime = 0;
            var dragging = false;
            var MIN_SWIPE_DIST = 50;   // px mínimos para considerar swipe
            var MAX_SWIPE_TIME = 400;  // ms máximo
            var MAX_Y_DRIFT = 80;      // px máximo vertical (evita scroll virar swipe)

            function isScrollableHorizontal(el) {
                while (el && el !== document.body) {
                    if (el.scrollWidth > el.clientWidth + 5 && el.classList && !el.classList.contains('resumo-cards-grid')) {
                        var style = window.getComputedStyle(el);
                        if (style.overflowX === 'auto' || style.overflowX === 'scroll') return true;
                    }
                    el = el.parentElement;
                }
                return false;
            }

            function handleSwipeEnd(dx, dy, dt, target) {
                if (dt > MAX_SWIPE_TIME || dy > MAX_Y_DRIFT || Math.abs(dx) < MIN_SWIPE_DIST) return;
                if (isScrollableHorizontal(target)) return;
                if (dx < 0) {
                    switchModelo(currentIdx + 1);
                } else {
                    switchModelo(currentIdx - 1);
                }
            }

            // Touch (mobile)
            document.addEventListener('touchstart', function(e) {
                if (e.touches.length !== 1) return;
                startX = e.touches[0].clientX;
                startY = e.touches[0].clientY;
                startTime = Date.now();
            }, {passive: true});

            document.addEventListener('touchend', function(e) {
                if (e.changedTouches.length !== 1) return;
                var dx = e.changedTouches[0].clientX - startX;
                var dy = Math.abs(e.changedTouches[0].clientY - startY);
                handleSwipeEnd(dx, dy, Date.now() - startTime, e.target);
            }, {passive: true});

            // Mouse drag (desktop)
            document.addEventListener('mousedown', function(e) {
                if (e.button !== 0) return; // apenas botão esquerdo
                dragging = true;
                startX = e.clientX;
                startY = e.clientY;
                startTime = Date.now();
            });

            document.addEventListener('mouseup', function(e) {
                if (!dragging) return;
                dragging = false;
                var dx = e.clientX - startX;
                var dy = Math.abs(e.clientY - startY);
                handleSwipeEnd(dx, dy, Date.now() - startTime, e.target);
            });

            // Cancelar drag se sair da janela
            document.addEventListener('mouseleave', function() {
                dragging = false;
            });

            _modeloCarousel = {
                goto: function(idx) { switchModelo(idx); }
            };
        }

        // Toggle de exibição numérica (Compacta/Completa)
        var exibicaoModo = 'compacta'; // default
        var moedaSimbolo = <?= json_encode($moeda['simbolo'] ?? 'R$') ?>;
        
        function fmtValorCompacto(val, simbolo) {
            val = parseFloat(val) || 0;
            var neg = val < 0;
            var abs = Math.abs(val);
            var formatted;
            var isInteiro = (dashboardMoeda && dashboardMoeda.formato === 'inteiro');
            var sep = ',';
            var decSuf = 3;
            var decK = 2;
            if (abs >= 1e9) {
                formatted = (abs / 1e9).toFixed(decSuf).replace('.', sep) + (isInteiro ? 'MM' : 'B');
            } else if (abs >= 1e6) {
                formatted = (abs / 1e6).toFixed(decSuf).replace('.', sep) + 'M';
            } else if (abs >= 1e3) {
                formatted = (abs / 1e3).toFixed(decK).replace('.', sep) + 'K';
            } else if (abs >= 100) {
                formatted = isInteiro ? Math.round(abs).toString() : abs.toFixed(2).replace('.', ',');
            } else {
                formatted = isInteiro ? Math.round(abs).toString() : abs.toFixed(2).replace('.', ',');
            }
            return (neg ? '-' : '') + simbolo + ' ' + formatted;
        }
        
        function fmtValorCompleto(val, simbolo, mascara) {
            val = parseFloat(val) || 0;
            if (mascara === 'percentual') {
                return (val * 100).toFixed(2).replace('.', ',').replace(/\B(?=(\d{3})+(?!\d))/g, '.') + ' %';
            }
            var neg = val < 0;
            var abs = Math.abs(val);
            var isInteiro = (dashboardMoeda && dashboardMoeda.formato === 'inteiro');
            if (isInteiro) {
                var intPart = Math.round(abs).toString().replace(/\B(?=(\d{3})+(?!\d))/g, '.');
                return (neg ? '-' : '') + simbolo + ' ' + intPart;
            }
            var parts = abs.toFixed(2).split('.');
            parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, '.');
            var formatted = parts.join(',');
            return (neg ? '-' : '') + simbolo + ' ' + formatted;
        }
        
        function aplicarExibicaoNumerica(modo) {
            exibicaoModo = modo;
            var els = document.querySelectorAll('.dado-valor[data-raw-value]');
            els.forEach(function(el) {
                var raw = el.getAttribute('data-raw-value');
                var mascara = el.getAttribute('data-mascara') || 'moeda';
                if (modo === 'compacta') {
                    el.textContent = fmtValorCompacto(raw, moedaSimbolo);
                } else {
                    el.textContent = fmtValorCompleto(raw, moedaSimbolo, mascara);
                }
            });
            // Atualizar gráfico de tendência com novo formato
            if (typeof _tendChart !== 'undefined' && _tendChart) {
                buildTendenciaChart(_tendPeriodoAtual, _tendModo);
            }
        }
        
        function initExibicaoToggle() {
            var btns = document.querySelectorAll('[data-exibicao]');
            if (!btns.length) return;
            btns.forEach(function(btn) {
                btn.addEventListener('click', function() {
                    var modo = btn.getAttribute('data-exibicao');
                    btns.forEach(function(b) { b.classList.remove('active'); });
                    btn.classList.add('active');
                    aplicarExibicaoNumerica(modo === 'completa' ? 'completa' : 'compacta');
                });
            });
            // Aplicar estado inicial
            aplicarExibicaoNumerica('compacta');
        }
        
        // Toggle de modelo (Meta/Submeta/Orçamento) - filtra cards e lista
        var _modeloAtivo = <?= json_encode($_modeloDefault ?? 'meta') ?>;

        function initModeloToggle() {
            var btns = document.querySelectorAll('[data-modelo-filter]');
            if (!btns.length) return;
            
            btns.forEach(function(btn) {
                btn.addEventListener('click', function() {
                    var modelo = btn.getAttribute('data-modelo-filter');
                    
                    // Toggle active state
                    btns.forEach(function(b) { b.classList.remove('active'); });
                    btn.classList.add('active');
                    
                    // Filter KPI list cards
                    var cards = document.querySelectorAll('[data-modelo-card]');
                    cards.forEach(function(card) {
                        if (modelo === 'todos') {
                            card.style.display = '';
                        } else {
                            var cardModelo = card.getAttribute('data-modelo-card');
                            if (cardModelo === modelo) {
                                card.style.display = '';
                            } else {
                                card.style.display = 'none';
                                if (card.classList.contains('kpi-lista-open')) {
                                    card.classList.remove('kpi-lista-open');
                                    var detail = card.querySelector('.kpi-lista-detail');
                                    if (detail) detail.style.display = 'none';
                                }
                            }
                        }
                    });

                    // Switch resumo cards + alerts blocks
                    var blocos = document.querySelectorAll('[data-modelo-resumo]');
                    var alertasTodos = document.querySelector('.alertas-todos');
                    if (modelo === 'todos') {
                        // Show only default model cards, hide per-model alerts, show consolidated
                        blocos.forEach(function(bloco) {
                            var isDefault = (bloco.getAttribute('data-modelo-resumo') === _modeloAtivo);
                            if (isDefault) {
                                bloco.style.display = '';
                                var cardsGrid = bloco.querySelector('.resumo-cards-grid');
                                if (cardsGrid) cardsGrid.style.display = '';
                                // Hide per-model alerts inside default block
                                var perAlerts = bloco.querySelector('.alertas-destaques');
                                if (perAlerts) perAlerts.style.display = 'none';
                            } else {
                                bloco.style.display = 'none';
                            }
                        });
                        if (alertasTodos) alertasTodos.style.display = '';
                    } else {
                        // Show only selected model (cards + alerts)
                        blocos.forEach(function(bloco) {
                            var match = (bloco.getAttribute('data-modelo-resumo') === modelo);
                            bloco.style.display = match ? '' : 'none';
                            if (match) {
                                var cardsGrid = bloco.querySelector('.resumo-cards-grid');
                                if (cardsGrid) cardsGrid.style.display = '';
                                var perAlerts = bloco.querySelector('.alertas-destaques');
                                if (perAlerts) perAlerts.style.display = '';
                            }
                        });
                        if (alertasTodos) alertasTodos.style.display = 'none';
                    }
                    // Show "Valores de: X" indicator always (visible in each model block)
                    var indicators = document.querySelectorAll('[data-modelo-todos-label]');
                    indicators.forEach(function(ind) {
                        ind.style.display = '';
                    });

                    // Switch empresa desempenho blocks
                    var empBlocos = document.querySelectorAll('[data-emp-modelo]');
                    if (empBlocos.length) {
                        var empTarget = (modelo === 'todos') ? _modeloAtivo : modelo;
                        empBlocos.forEach(function(blk) {
                            blk.style.display = (blk.getAttribute('data-emp-modelo') === empTarget) ? '' : 'none';
                        });
                    }

                    // Switch tendência chart data
                    var tendTarget = (modelo === 'todos') ? _modeloAtivo : modelo;
                    if (_tendDataPorModelo[tendTarget]) {
                        _tendData = _tendDataPorModelo[tendTarget];
                        var activePeriodo = document.querySelector('[data-tend-periodo].active');
                        var periodo = activePeriodo ? activePeriodo.getAttribute('data-tend-periodo') : 'mes';
                        buildTendenciaChart(periodo, _tendModo);
                    }
                });
            });
        }
        
        // Click em alerta rola até a lista de contas
        function initAlertaScroll() {
            document.querySelectorAll('[data-scroll-kpi]').forEach(function(badge) {
                badge.addEventListener('click', function() {
                    var target = document.getElementById('kpi-lista-section');
                    if (target) {
                        target.scrollIntoView({ behavior: 'smooth', block: 'start' });
                    }
                });
            });
        }
        
        // Gráfico de Tendência (Mês / Trimestre / Ano) — por modelo
        var _tendChart = null;
        var _tendModo = 'consolidado'; // 'consolidado' | 'empresas'
        var _tendPeriodoAtual = 'mes';
        var _tendSubtitulos = {
            mes: <?= json_encode($_tendSubMes ?? '', JSON_UNESCAPED_UNICODE) ?>,
            trimestre: <?= json_encode($_tendSubTrim ?? '', JSON_UNESCAPED_UNICODE) ?>,
            ano: <?= json_encode($_tendSubAno ?? '', JSON_UNESCAPED_UNICODE) ?>
        };
        var _tendCoresEmpresas = ['#3b82f6','#ef4444','#f59e0b','#10b981','#8b5cf6','#ec4899','#06b6d4','#f97316','#6366f1','#14b8a6'];
        var _tendDataPorModelo = {};
        <?php foreach ($_tendPorModelo as $_tmKey => $_tmVal): ?>
        _tendDataPorModelo[<?= json_encode($_tmKey) ?>] = {
            mes: {
                labels: <?= json_encode($_tmVal['mes']['labels'], JSON_UNESCAPED_UNICODE) ?>,
                realizado: <?= json_encode($_tmVal['mes']['realizado'], JSON_UNESCAPED_UNICODE) ?>,
                orcado: <?= json_encode($_tmVal['mes']['orcado'], JSON_UNESCAPED_UNICODE) ?>,
                projecao: <?= json_encode($_tmVal['mes']['projecao'], JSON_UNESCAPED_UNICODE) ?>,
                subtitulo: _tendSubtitulos.mes,
                tooltipPrefix: 'Dia '
            },
            trimestre: {
                labels: <?= json_encode($_tmVal['trimestre']['labels'], JSON_UNESCAPED_UNICODE) ?>,
                realizado: <?= json_encode($_tmVal['trimestre']['realizado'], JSON_UNESCAPED_UNICODE) ?>,
                orcado: <?= json_encode($_tmVal['trimestre']['orcado'], JSON_UNESCAPED_UNICODE) ?>,
                projecao: <?= json_encode($_tmVal['trimestre']['projecao'], JSON_UNESCAPED_UNICODE) ?>,
                subtitulo: _tendSubtitulos.trimestre,
                tooltipPrefix: ''
            },
            ano: {
                labels: <?= json_encode($_tmVal['ano']['labels'], JSON_UNESCAPED_UNICODE) ?>,
                realizado: <?= json_encode($_tmVal['ano']['realizado'], JSON_UNESCAPED_UNICODE) ?>,
                orcado: <?= json_encode($_tmVal['ano']['orcado'], JSON_UNESCAPED_UNICODE) ?>,
                projecao: <?= json_encode($_tmVal['ano']['projecao'], JSON_UNESCAPED_UNICODE) ?>,
                subtitulo: _tendSubtitulos.ano,
                tooltipPrefix: ''
            },
            empresas: <?= json_encode($_tmVal['empresas'] ?? [], JSON_UNESCAPED_UNICODE) ?>
        };
        <?php endforeach; ?>
        var _tendData = _tendDataPorModelo[<?= json_encode($_modeloDefault ?? 'meta') ?>] || {};

        function _tendFmtVal(v, simbolo) {
            if (typeof exibicaoModo !== 'undefined' && exibicaoModo === 'compacta') {
                return fmtValorCompacto(v, simbolo);
            }
            var parts = Math.abs(v).toFixed(2).split('.');
            parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, '.');
            return (v < 0 ? '-' : '') + simbolo + ' ' + parts.join(',');
        }

        function buildTendenciaChart(periodo, modo) {
            var canvas = document.getElementById('chartTendencia');
            if (!canvas) return;
            modo = modo || _tendModo;
            _tendPeriodoAtual = periodo;
            _tendModo = modo;

            var d = _tendData[periodo] || _tendData.mes;
            var simbolo = (dashboardMoeda && dashboardMoeda.simbolo) ? dashboardMoeda.simbolo : 'R$';
            var prefix = d.tooltipPrefix;

            var subEl = document.getElementById('tendenciaSubtitulo');
            if (subEl) subEl.innerHTML = d.subtitulo;

            if (_tendChart) { _tendChart.destroy(); _tendChart = null; }

            var datasets = [];

            if (modo === 'empresas' && _tendData.empresas && _tendData.empresas.length > 0) {
                // Modo por empresa: uma linha de realizado por empresa + orçado consolidado
                datasets.push({
                    label: 'Orçado (Total)',
                    data: d.orcado,
                    borderColor: '#f97316',
                    backgroundColor: 'transparent',
                    borderWidth: 2,
                    borderDash: [6, 4],
                    pointRadius: 0,
                    pointHoverRadius: 4,
                    tension: 0.1,
                    fill: false
                });
                _tendData.empresas.forEach(function(emp, i) {
                    var cor = _tendCoresEmpresas[i % _tendCoresEmpresas.length];
                    var empPeriodo = emp[periodo] || {};
                    datasets.push({
                        label: emp.dsempresa,
                        data: empPeriodo.realizado || [],
                        borderColor: cor,
                        backgroundColor: 'transparent',
                        borderWidth: 2,
                        pointRadius: 0,
                        pointHoverRadius: 5,
                        tension: 0.3,
                        fill: false,
                        spanGaps: false
                    });
                });
            } else {
                // Modo consolidado (padrão)
                datasets = [
                    {
                        label: 'Realizado',
                        data: d.realizado,
                        borderColor: '#22c55e',
                        backgroundColor: 'rgba(34,197,94,0.08)',
                        borderWidth: 2.5,
                        pointRadius: 0,
                        pointHoverRadius: 5,
                        tension: 0.3,
                        fill: true,
                        spanGaps: false
                    },
                    {
                        label: 'Orçado',
                        data: d.orcado,
                        borderColor: '#f97316',
                        backgroundColor: 'transparent',
                        borderWidth: 2,
                        borderDash: [6, 4],
                        pointRadius: 0,
                        pointHoverRadius: 4,
                        tension: 0.1,
                        fill: false
                    },
                    {
                        label: 'Projeção',
                        data: d.projecao,
                        borderColor: '#8b5cf6',
                        backgroundColor: 'transparent',
                        borderWidth: 2,
                        borderDash: [4, 4],
                        pointRadius: 0,
                        pointHoverRadius: 4,
                        tension: 0.3,
                        fill: false,
                        spanGaps: false
                    }
                ];
            }

            _tendChart = new Chart(canvas.getContext('2d'), {
                type: 'line',
                data: { labels: d.labels, datasets: datasets },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    interaction: { mode: 'index', intersect: false },
                    plugins: {
                        legend: {
                            position: 'bottom',
                            labels: {
                                usePointStyle: true,
                                pointStyle: 'line',
                                padding: 16,
                                font: { size: 11, weight: '500' }
                            },
                            onClick: function(e, legendItem, legend) {
                                var index = legendItem.datasetIndex;
                                var ci = legend.chart;
                                var meta = ci.getDatasetMeta(index);
                                meta.hidden = meta.hidden === null ? !ci.data.datasets[index].hidden : null;
                                ci.update();
                            }
                        },
                        tooltip: {
                            backgroundColor: 'rgba(15,23,42,0.9)',
                            titleFont: { size: 13, weight: '600' },
                            bodyFont: { size: 12 },
                            padding: 10,
                            cornerRadius: 8,
                            callbacks: {
                                title: function(items) { return prefix + items[0].label; },
                                label: function(ctx) {
                                    if (ctx.raw === null) return null;
                                    return ctx.dataset.label + ': ' + _tendFmtVal(parseFloat(ctx.raw) || 0, simbolo);
                                }
                            }
                        }
                    },
                    scales: {
                        x: {
                            grid: { display: false },
                            ticks: { font: { size: 11 }, color: '#94a3b8', maxTicksLimit: 15 }
                        },
                        y: {
                            beginAtZero: true,
                            grid: { color: 'rgba(0,0,0,0.04)' },
                            ticks: {
                                font: { size: 11 },
                                color: '#94a3b8',
                                callback: function(value) {
                                    if (typeof exibicaoModo !== 'undefined' && exibicaoModo === 'completa') {
                                        return _tendFmtVal(value, simbolo);
                                    }
                                    if (Math.abs(value) >= 1e6) return simbolo + ' ' + (value / 1e6).toFixed(1) + 'M';
                                    if (Math.abs(value) >= 1e3) return simbolo + ' ' + (value / 1e3).toFixed(0) + 'K';
                                    return simbolo + ' ' + value;
                                }
                            }
                        }
                    }
                }
            });
        }

        function initTendenciaMes() {
            buildTendenciaChart('mes', 'consolidado');
            // Período buttons
            var btns = document.querySelectorAll('[data-tend-periodo]');
            btns.forEach(function(btn) {
                btn.addEventListener('click', function() {
                    btns.forEach(function(b) { b.classList.remove('active'); });
                    btn.classList.add('active');
                    buildTendenciaChart(btn.getAttribute('data-tend-periodo'), _tendModo);
                });
            });
            // Modo toggle (Consolidado / Por Empresa)
            var modoBtns = document.querySelectorAll('[data-tend-modo]');
            modoBtns.forEach(function(btn) {
                btn.addEventListener('click', function() {
                    modoBtns.forEach(function(b) { b.classList.remove('active'); });
                    btn.classList.add('active');
                    buildTendenciaChart(_tendPeriodoAtual, btn.getAttribute('data-tend-modo'));
                });
            });
        }
        
        function formatValor(v) {
            if (!dashboardMoeda) return v.toFixed(2);
            const simbolo = dashboardMoeda.simbolo || 'R$';
            const formato = dashboardMoeda.formato || 'decimal';
            const casas   = (formato === 'inteiro') ? 0 : 2;
            return simbolo + ' ' + v.toLocaleString('pt-BR', { minimumFractionDigits: casas, maximumFractionDigits: casas });
        }

        function formatPercent(p) {
            const v = (p * 100);
            return v.toFixed(1).replace('.', ',') + ' %';
        }

        function toneColor(p) {
            // p é agora a projeção, não o percentual atingido
            if (p >= 1.0) return '#16a34a'; // verde
            if (p >= 0.95) return '#f59e0b'; // amarelo
            return '#dc2626'; // vermelho
        }

        function toneColorByModelo(modelo, p) {
            const v = Number(p || 0);
            if (modelo === 'orcamento') {
                // Orçamento: quanto MENOR o consumo, melhor
                if (v <= 0.80) return '#16a34a'; // verde
                if (v <= 0.90) return '#f59e0b'; // amarelo
                return '#dc2626'; // vermelho
            }
            return toneColor(v);
        }

        // ✅ Tooltip externo (HTML) para não cortar valores
        function externalTooltipHandler(context) {
            const { chart, tooltip } = context;

            let tooltipEl = document.getElementById('chartjs-tooltip');
            if (!tooltipEl) {
                tooltipEl = document.createElement('div');
                tooltipEl.id = 'chartjs-tooltip';
                tooltipEl.style.position = 'fixed';
                tooltipEl.style.pointerEvents = 'none';
                tooltipEl.style.background = 'rgba(17, 24, 39, 0.92)';
                tooltipEl.style.color = '#fff';
                tooltipEl.style.borderRadius = '8px';
                tooltipEl.style.padding = '10px 12px';
                tooltipEl.style.fontSize = '12px';
                tooltipEl.style.lineHeight = '1.2';
                tooltipEl.style.zIndex = '9999';
                tooltipEl.style.whiteSpace = 'nowrap';
                tooltipEl.style.boxShadow = '0 6px 18px rgba(0,0,0,0.18)';
                document.body.appendChild(tooltipEl);
            }

            if (tooltip.opacity === 0) {
                tooltipEl.style.opacity = 0;
                return;
            }

            const lines = tooltip.body?.map(b => b.lines).flat() || [];
            const title = tooltip.title?.[0]
                ? `<div style="font-weight:700;margin-bottom:6px">${tooltip.title[0]}</div>`
                : '';
            tooltipEl.innerHTML = title + lines.map(l => `<div>${l}</div>`).join('');

            const rect = chart.canvas.getBoundingClientRect();
            const x = rect.left + tooltip.caretX;
            const y = rect.top + tooltip.caretY;

            tooltipEl.style.opacity = 1;

            const vw = window.innerWidth;
            const vh = window.innerHeight;
            const pad = 12;

            // posição inicial (próximo do cursor)
            tooltipEl.style.left = `${x + 12}px`;
            tooltipEl.style.top  = `${y + 12}px`;

            // clamp na viewport (evita cortar na borda da tela)
            const bb = tooltipEl.getBoundingClientRect();
            let left = x + 12;
            let top  = y + 12;

            if (left + bb.width + pad > vw) left = vw - bb.width - pad;
            if (top + bb.height + pad > vh) top = vh - bb.height - pad;
            if (left < pad) left = pad;
            if (top < pad) top = pad;

            tooltipEl.style.left = `${left}px`;
            tooltipEl.style.top  = `${top}px`;
        }

        function buildKpiDonuts() {
            if (!window.Chart || !Array.isArray(dashboardMetas)) return;
            
            // Lazy loading com IntersectionObserver
            if ('IntersectionObserver' in window) {
                const observer = new IntersectionObserver((entries) => {
                    entries.forEach(entry => {
                        if (entry.isIntersecting && !entry.target.dataset.chartInit) {
                            const canvas = entry.target;
                            const metaId = canvas.id.replace('chart-kpi-donut-', '');
                            const m = dashboardMetas.find(meta => String(meta.id) === metaId);
                            if (m) {
                                createDonutChart(canvas, m);
                                canvas.dataset.chartInit = 'true';
                                observer.unobserve(canvas);
                            }
                        }
                    });
                }, { rootMargin: '50px' }); // Pré-carrega 50px antes de aparecer
                
                dashboardMetas.forEach((m) => {
                    const cid = 'chart-kpi-donut-' + String(m.id);
                    const ctx = document.getElementById(cid);
                    if (ctx) observer.observe(ctx);
                });
            } else {
                // Fallback: cria todos de uma vez (navegadores antigos)
                dashboardMetas.forEach((m) => {
                    const cid = 'chart-kpi-donut-' + String(m.id);
                    const ctx = document.getElementById(cid);
                    if (ctx) createDonutChart(ctx, m);
                });
            }
        }

        // =============================
        // Visão Consolidada por Modelo (comparativo por empresa)
        // =============================
        const chartsModelos = {}; // key: modelo
        const chartsOrcamento = { bar: null, donut: null };

        const centerTextPlugin = {
            id: 'centerText',
            afterDraw(chart, args, pluginOptions) {
                const opts = pluginOptions || {};
                const text = String(opts.text || '').trim();
                if (!text) return;
                const ctx = chart.ctx;
                const meta = chart.getDatasetMeta(0);
                if (!meta || !meta.data || !meta.data[0]) return;
                const x = meta.data[0].x;
                const y = meta.data[0].y;
                ctx.save();
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';
                ctx.fillStyle = opts.color || 'rgba(17,24,39,0.92)';
                ctx.font = opts.font || '800 20px system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif';
                ctx.fillText(text, x, y);
                ctx.restore();
            }
        };

        function getModeloLabels(modelo) {
            if (modelo === 'orcamento') {
                return {
                    realizado: 'Gasto Realizado',
                    restante: 'Saldo Disponível',
                    projecao: 'Projeção (total)'
                };
            }
            return {
                realizado: 'Realizado',
                restante: 'A Realizar',
                projecao: 'Projeção (total)'
            };
        }

        function escapeHtml(str) {
            return String(str)
                .replace(/&/g, '&amp;')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;')
                .replace(/"/g, '&quot;')
                .replace(/'/g, '&#039;');
        }

        function hexToRgba(hex, alpha) {
            const h = String(hex || '').replace('#', '').trim();
            if (h.length !== 6) return `rgba(0,0,0,${alpha})`;
            const r = parseInt(h.slice(0, 2), 16);
            const g = parseInt(h.slice(2, 4), 16);
            const b = parseInt(h.slice(4, 6), 16);
            return `rgba(${r},${g},${b},${alpha})`;
        }

        const percentInBarsPlugin = {
            id: 'percentInBars',
            afterDatasetsDraw(chart, args, pluginOptions) {
                const opts = pluginOptions || {};
                const ctx = chart.ctx;
                const totalOrc = Array.isArray(opts.totalOrc) ? opts.totalOrc : [];
                const showProj = !!opts.showProj;
                const showReal = (opts.showReal !== undefined) ? !!opts.showReal : true;
                const showRest = (opts.showRest !== undefined) ? !!opts.showRest : true;
                const showRestBelow = (opts.showRestBelow !== undefined) ? !!opts.showRestBelow : true;
                const showRealBelow = (opts.showRealBelow !== undefined) ? !!opts.showRealBelow : false;

                const idxRealGlobal = chart.data.datasets.findIndex(d => d && d._role === 'real');
                const metaRealGlobal = (idxRealGlobal >= 0) ? chart.getDatasetMeta(idxRealGlobal) : null;

                ctx.save();
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';
                // Fonte maior para ficar mais visual no consolidado
                ctx.font = '800 14px system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif';

                chart.data.datasets.forEach((dataset, datasetIndex) => {
                    const meta = chart.getDatasetMeta(datasetIndex);
                    if (!meta || meta.hidden) return;

                    const role = dataset._role;
                    if (role !== 'real' && role !== 'rest' && role !== 'proj') return;
                    if (role === 'proj' && !showProj) return;
                    if (role === 'real' && !showReal) return;
                    if (role === 'rest' && !showRest) return;
                    // Se o realizado será desenhado abaixo (fora do stack), não desenhar dentro.
                    if (role === 'real' && showRealBelow) return;
                    // restante pode ser desenhado abaixo (fora do stack) OU dentro (no segmento cinza)
                    if (role === 'rest' && showRestBelow) return;

                    meta.data.forEach((element, index) => {
                        const v = Number(dataset.data?.[index]);
                        if (!isFinite(v) || v <= 0) return;
                        const base = Number(totalOrc[index] || 0);
                        if (!isFinite(base) || base <= 0) return;

                        const perc = v / base;
                        if (!isFinite(perc) || perc <= 0) return;

                        // Para o restante, quando NÃO estiver no rodapé, desenhar o texto usando o segmento do realizado
                        // (usuário quer o "13%" onde estava o "87%"), sem mexer na projeção.
                        let elementUse = element;
                        let usingRealGeometryForRest = false;
                        if (role === 'rest' && !showRestBelow && metaRealGlobal?.data?.[index]) {
                            elementUse = metaRealGlobal.data[index];
                            usingRealGeometryForRest = true;
                        }

                        if (!elementUse) return;
                        const elY = elementUse.y;
                        const elBase = elementUse.base;
                        if (!isFinite(elY) || !isFinite(elBase)) return;

                        const chartArea = chart.chartArea || { top: 0, bottom: chart.height };

                        // Se o realizado for muito pequeno no ANO (ou em qualquer período), não pode "sumir".
                        // Em vez de abortar, aplicamos fallback de posição.
                        let height = Math.abs(elBase - elY);
                        let isTiny = height < 18;

                        // Caso especial: % A Realizar usa geometria do realizado; se o realizado for minúsculo,
                        // volta a usar o próprio segmento cinza para garantir que o texto apareça.
                        if (role === 'rest' && usingRealGeometryForRest && isTiny) {
                            elementUse = element;
                            usingRealGeometryForRest = false;
                            const y2 = elementUse?.y;
                            const b2 = elementUse?.base;
                            if (!isFinite(y2) || !isFinite(b2)) return;
                            height = Math.abs(b2 - y2);
                            isTiny = height < 18;
                        }

                        const x = elementUse.x;
                        let y = (elY + elBase) / 2;
                        const text = (perc * 100).toFixed(0) + '%';

                        // Para projeção (barra contorno), não desenha percentual
                        if (role === 'proj') {
                            return;
                        }

                        if (role === 'real') {
                            // % Realizado será desenhado abaixo (fora do stack)
                            return;
                        }

                        if (role === 'rest' && !showRestBelow) {
                            const topY = Math.min(elY, elBase);
                            // % A Realizar acima da barra (onde estava a projeção)
                            y = topY - 12;
                        }

                        if (role === 'rest' && showRestBelow) {
                            // Quando o restante for ao rodapé, não desenhar dentro do stack.
                            return;
                        }

                        if (role === 'rest') {
                            ctx.fillStyle = 'rgba(17,24,39,0.75)';
                        } else if (role === 'proj') {
                            ctx.fillStyle = 'rgba(245,158,11,0.95)';
                        } else {
                            // % Realizado: usar sempre cor escura (pedido do usuário).
                            ctx.fillStyle = 'rgba(17,24,39,0.85)';
                        }

                        ctx.fillText(text, x, y);
                    });
                });

                // Percentuais abaixo das barras (fora do stack)
                if (showRealBelow || (showRestBelow && showRest)) {
                    const chartArea = chart.chartArea;
                    const yBottom = Math.min(chart.height - 8, (chartArea?.bottom ?? (chart.height - 20)) - 6);
                    const yRealBelow = yBottom - 14;
                    // Mesmo tamanho do percentual da projeção
                    ctx.font = '800 14px system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif';
                    ctx.fillStyle = 'rgba(17,24,39,0.85)';

                    // % Realizado abaixo das barras
                    if (showRealBelow) {
                        const idxReal = chart.data.datasets.findIndex(d => d && d._role === 'real');
                        if (idxReal >= 0) {
                            const metaReal = chart.getDatasetMeta(idxReal);
                            metaReal?.data?.forEach((element, index) => {
                                const base = Number(totalOrc[index] || 0);
                                if (!isFinite(base) || base <= 0) return;
                                const realVal = Number(chart.data.datasets[idxReal].data?.[index]);
                                if (!isFinite(realVal) || realVal < 0) return;
                                const realPerc = realVal / base;
                                if (!isFinite(realPerc)) return;
                                const text = (realPerc * 100).toFixed(0) + '%';
                                const x = element?.x;
                                if (!isFinite(x)) return;
                                ctx.fillText(text, x, yRealBelow);
                            });
                        }
                    }

                    // % A Realizar no rodapé (quando explicitamente habilitado)
                    if (showRestBelow && showRest) {
                        const idxRest = chart.data.datasets.findIndex(d => d && d._role === 'rest');
                        if (idxRest >= 0) {
                            const metaRest = chart.getDatasetMeta(idxRest);
                            metaRest?.data?.forEach((element, index) => {
                                const base = Number(totalOrc[index] || 0);
                                if (!isFinite(base) || base <= 0) return;
                                const restVal = Number(chart.data.datasets[idxRest].data?.[index]);
                                if (!isFinite(restVal) || restVal < 0) return;
                                const restPerc = restVal / base;
                                if (!isFinite(restPerc)) return;
                                const text = (restPerc * 100).toFixed(0) + '%';
                                const x = element?.x;
                                if (!isFinite(x)) return;
                                ctx.fillText(text, x, yBottom);
                            });
                        }
                    }
                }

                ctx.restore();
            }
        };

        function destroyModeloChart(modelo) {
            if (chartsModelos[modelo]) {
                chartsModelos[modelo].destroy();
                delete chartsModelos[modelo];
            }
        }

        function destroyOrcamentoCharts() {
            if (chartsOrcamento.bar) {
                chartsOrcamento.bar.destroy();
                chartsOrcamento.bar = null;
            }
            if (chartsOrcamento.donut) {
                chartsOrcamento.donut.destroy();
                chartsOrcamento.donut = null;
            }
        }

        function renderOrcamentoTermometro(periodo) {
            const card = document.querySelector('#dashboardConsolidadoComparativo [data-modelo="orcamento"]');
            if (!card) return;
            const d = (dashboardOrcamentoTermometro && dashboardOrcamentoTermometro[periodo]) ? dashboardOrcamentoTermometro[periodo] : null;
            if (!d) return;

            const orc = Number(d.orc || 0);
            const real = Number(d.real || 0);
            const saldo = Math.max(0, Number(d.saldo || (orc - real)));
            const proj = (d.proj === null || d.proj === undefined) ? null : Number(d.proj);
            const consumoPerc = Number(d.consumoPerc || 0);
            const projPerc = (d.projPerc === null || d.projPerc === undefined) ? null : Number(d.projPerc);

            const statusPerc = (projPerc !== null) ? projPerc : consumoPerc;
            const colReal = toneColorByModelo('orcamento', statusPerc);

            const elReal = card.querySelector('[data-role="orc-total-real"]');
            const elOrc = card.querySelector('[data-role="orc-total-orc"]');
            const elSaldo = card.querySelector('[data-role="orc-total-saldo"]');
            const elProj = card.querySelector('[data-role="orc-total-proj"]');
            const wrapProj = card.querySelector('[data-role-wrap="orc-total-proj"]');
            const elConsPerc = card.querySelector('[data-role="orc-consumo-perc"]');
            const elMaior = card.querySelector('[data-role="orc-ranking-maior"]');
            const elMenor = card.querySelector('[data-role="orc-ranking-menor"]');

            const elEmpMelhor = card.querySelector('[data-role="orc-emp-melhor"]');
            const elEmpPior = card.querySelector('[data-role="orc-emp-pior"]');
            const elEmpCriticos = card.querySelector('[data-role="orc-emp-criticos"]');

            if (elReal) elReal.textContent = formatValor(real);
            if (elOrc) elOrc.textContent = formatValor(orc);
            if (elSaldo) elSaldo.textContent = formatValor(saldo);
            if (wrapProj) {
                const hasProj = (proj !== null && isFinite(proj));
                wrapProj.style.display = hasProj ? '' : 'none';
                if (hasProj && elProj) elProj.textContent = formatValor(proj);
            }
            if (elConsPerc) elConsPerc.textContent = formatPercent(consumoPerc);

            const maior = d.ranking && d.ranking.maior ? d.ranking.maior : null;
            const menor = d.ranking && d.ranking.menor ? d.ranking.menor : null;
            if (elMaior) elMaior.textContent = maior ? `${maior.nome} (${formatPercent(Number(maior.perc || 0))})` : '-';
            if (elMenor) elMenor.textContent = menor ? `${menor.nome} (${formatPercent(Number(menor.perc || 0))})` : '-';

            // Ranking por EMPRESA (multi-empresa): usa o bucket comparativo já existente
            const bucketEmpresas = (dashboardConsolidadoComparativo && dashboardConsolidadoComparativo.orcamento && dashboardConsolidadoComparativo.orcamento[periodo])
                ? (dashboardConsolidadoComparativo.orcamento[periodo].empresas || [])
                : [];

            if (Array.isArray(bucketEmpresas) && bucketEmpresas.length) {
                const empresasOrdenadas = [...bucketEmpresas].sort((a, b) => {
                    const pa = (a.proj_perc !== null && a.proj_perc !== undefined) ? Number(a.proj_perc || 0) : Number(a.perc_total || 0);
                    const pb = (b.proj_perc !== null && b.proj_perc !== undefined) ? Number(b.proj_perc || 0) : Number(b.perc_total || 0);
                    // Orçamento: menor consumo é melhor
                    return pa - pb;
                });
                const melhorEmp = empresasOrdenadas[0] || null;
                const piorEmp = empresasOrdenadas[empresasOrdenadas.length - 1] || null;

                const pm = melhorEmp ? ((melhorEmp.proj_perc !== null && melhorEmp.proj_perc !== undefined) ? Number(melhorEmp.proj_perc || 0) : Number(melhorEmp.perc_total || 0)) : 0;
                const pp = piorEmp ? ((piorEmp.proj_perc !== null && piorEmp.proj_perc !== undefined) ? Number(piorEmp.proj_perc || 0) : Number(piorEmp.perc_total || 0)) : 0;

                if (elEmpMelhor) elEmpMelhor.textContent = melhorEmp ? `${melhorEmp.dsempresa} (${formatPercent(pm)})` : '-';
                if (elEmpPior) elEmpPior.textContent = piorEmp ? `${piorEmp.dsempresa} (${formatPercent(pp)})` : '-';

                const criticosLista = bucketEmpresas
                    .map((e) => {
                        const p = (e.proj_perc !== null && e.proj_perc !== undefined) ? Number(e.proj_perc || 0) : Number(e.perc_total || 0);
                        return {
                            nome: String(e.dsempresa || ''),
                            perc: p,
                            isCritico: (p > 0.90)
                        };
                    })
                    .filter(x => x.isCritico)
                    .sort((a, b) => (b.perc - a.perc));

                const criticosQtd = criticosLista.length;
                if (elEmpCriticos) {
                    elEmpCriticos.textContent = String(criticosQtd);

                    const instancia = (window.bootstrap && bootstrap.Popover) ? bootstrap.Popover.getInstance(elEmpCriticos) : null;
                    if (instancia) instancia.dispose();

                    if (criticosQtd > 0 && window.bootstrap && bootstrap.Popover) {
                        const conteudo = criticosLista
                            .map(x => `<div style="margin-bottom: 4px;">${escapeHtml(x.nome)}: <strong>${escapeHtml(formatPercent(Number(x.perc || 0)))}</strong></div>`)
                            .join('');

                        elEmpCriticos.setAttribute('data-bs-toggle', 'popover');
                        elEmpCriticos.setAttribute('data-bs-trigger', 'hover focus');
                        elEmpCriticos.setAttribute('data-bs-placement', 'top');
                        elEmpCriticos.setAttribute('data-bs-html', 'true');
                        elEmpCriticos.setAttribute('data-bs-title', 'Empresas acima de 90%');
                        elEmpCriticos.setAttribute('data-bs-content', conteudo);

                        new bootstrap.Popover(elEmpCriticos, {
                            html: true,
                            sanitize: false,
                            customClass: 'popover-criticos'
                        });
                    } else {
                        elEmpCriticos.removeAttribute('data-bs-toggle');
                        elEmpCriticos.removeAttribute('data-bs-trigger');
                        elEmpCriticos.removeAttribute('data-bs-placement');
                        elEmpCriticos.removeAttribute('data-bs-html');
                        elEmpCriticos.removeAttribute('data-bs-title');
                        elEmpCriticos.removeAttribute('data-bs-content');
                    }
                }
            } else {
                if (elEmpMelhor) elEmpMelhor.textContent = '-';
                if (elEmpPior) elEmpPior.textContent = '-';
                if (elEmpCriticos) {
                    elEmpCriticos.textContent = '-';
                    const instancia = (window.bootstrap && bootstrap.Popover) ? bootstrap.Popover.getInstance(elEmpCriticos) : null;
                    if (instancia) instancia.dispose();
                    elEmpCriticos.removeAttribute('data-bs-toggle');
                    elEmpCriticos.removeAttribute('data-bs-trigger');
                    elEmpCriticos.removeAttribute('data-bs-placement');
                    elEmpCriticos.removeAttribute('data-bs-html');
                    elEmpCriticos.removeAttribute('data-bs-title');
                    elEmpCriticos.removeAttribute('data-bs-content');
                }
            }

            // Bar chart: Orçamento × Gasto (empilhado)
            const canvasBar = card.querySelector('#chart-orcamento-termometro');
            if (canvasBar && window.Chart) {
                const datasets = [
                    {
                        label: 'Gasto realizado',
                        data: [real],
                        backgroundColor: hexToRgba(colReal, 0.78),
                        borderWidth: 0,
                        stack: 'stack-1'
                    },
                    {
                        label: 'Saldo disponível',
                        data: [saldo],
                        backgroundColor: 'rgba(226,232,240,0.95)',
                        borderWidth: 0,
                        stack: 'stack-1'
                    }
                ];

                const hasProj = (proj !== null && isFinite(proj));
                if (hasProj) {
                    datasets.push({
                        label: 'Projeção de gasto',
                        data: [proj],
                        type: 'bar',
                        grouped: false,
                        backgroundColor: 'rgba(0,0,0,0)',
                        borderColor: [colReal],
                        borderWidth: 3,
                        borderSkipped: false,
                        order: 99,
                        stack: 'stack-proj'
                    });
                }

                if (!chartsOrcamento.bar) {
                    const ctx = canvasBar.getContext('2d');
                    chartsOrcamento.bar = new Chart(ctx, {
                        type: 'bar',
                        data: {
                            labels: ['Consolidado'],
                            datasets
                        },
                        options: {
                            maintainAspectRatio: false,
                            responsive: true,
                            scales: {
                                x: { stacked: true },
                                y: {
                                    stacked: true,
                                    ticks: {
                                        callback: function(value) {
                                            return formatValor(Number(value || 0));
                                        }
                                    }
                                }
                            },
                            plugins: {
                                legend: { position: 'bottom' },
                                tooltip: {
                                    enabled: false,
                                    external: externalTooltipHandler,
                                    callbacks: {
                                        label: function(ctx) {
                                            const label = ctx.dataset.label || '';
                                            const v = Number(ctx.raw || 0);
                                            return label + ': ' + formatValor(v);
                                        }
                                    }
                                }
                            }
                        }
                    });
                } else {
                    chartsOrcamento.bar.data.datasets = datasets;
                    chartsOrcamento.bar.update();
                }
            }

            // Donut: % consumido
            const canvasDonut = card.querySelector('#chart-orcamento-consumo');
            if (canvasDonut && window.Chart) {
                const donutData = {
                    labels: ['Consumido', 'Saldo'],
                    datasets: [
                        {
                            data: [real, saldo],
                            backgroundColor: [colReal, 'rgba(226,232,240,0.95)'],
                            borderWidth: 0,
                            hoverOffset: 3,
                            cutout: '72%'
                        }
                    ]
                };

                if (!chartsOrcamento.donut) {
                    const ctx2 = canvasDonut.getContext('2d');
                    chartsOrcamento.donut = new Chart(ctx2, {
                        type: 'doughnut',
                        data: donutData,
                        options: {
                            plugins: {
                                legend: { display: false },
                                tooltip: {
                                    enabled: false,
                                    external: externalTooltipHandler,
                                    callbacks: {
                                        label: function(ctx) {
                                            const label = ctx.label || '';
                                            const v = Number(ctx.raw || 0);
                                            const perc = (orc !== 0) ? (v / orc) : 0;
                                            const percTxt = (perc * 100).toFixed(1).replace('.', ',') + '%';
                                            return label + ': ' + formatValor(v) + ' (' + percTxt + ')';
                                        }
                                    }
                                }
                            }
                        }
                    });
                } else {
                    chartsOrcamento.donut.data = donutData;
                    chartsOrcamento.donut.update();
                }
            }
        }

        function renderModeloComparativo(modelo, periodo) {
            const container = document.querySelector(`#dashboardConsolidadoComparativo [data-modelo="${modelo}"]`);
            if (!container) return;

            const data = (dashboardConsolidadoComparativo?.[modelo]?.[periodo]) || null;
            const empresas = Array.isArray(data?.empresas) ? data.empresas : [];
            if (!empresas.length) return;

            const labels = getModeloLabels(modelo);

            const totalReal = empresas.reduce((s, e) => s + Number(e.total_real || 0), 0);
            const totalOrcSum = empresas.reduce((s, e) => s + Number(e.total_orc || 0), 0);
            const percTotal = totalOrcSum !== 0 ? (totalReal / totalOrcSum) : 0;

            const totalProjSum = empresas.reduce((s, e) => {
                const pv = e.proj_total;
                if (pv === null || pv === undefined) return s;
                const n = Number(pv);
                return isFinite(n) ? (s + n) : s;
            }, 0);

            const totalRealEl = container.querySelector('[data-role="total-real"]');
            const totalOrcEl = container.querySelector('[data-role="total-orc"]');
            const percTotalEl = container.querySelector('[data-role="perc-total"]');
            const totalProjEl = container.querySelector('[data-role="total-proj"]');
            const totalProjWrap = container.querySelector('[data-role-wrap="total-proj"]');
            const melhorEl = container.querySelector('[data-role="melhor"]');
            const piorEl = container.querySelector('[data-role="pior"]');
            const criticosEl = container.querySelector('[data-role="criticos"]');

            if (totalRealEl) totalRealEl.textContent = formatValor(totalReal);
            if (totalOrcEl) totalOrcEl.textContent = formatValor(totalOrcSum);
            if (percTotalEl) percTotalEl.textContent = formatPercent(percTotal);

            if (totalProjWrap) {
                const hasProjInBucket = empresas.some(e => e.proj_total !== null && e.proj_total !== undefined);
                totalProjWrap.style.display = hasProjInBucket ? '' : 'none';
                if (hasProjInBucket && totalProjEl) {
                    totalProjEl.textContent = formatValor(totalProjSum);
                }
            }

            const empresasOrdenadas = [...empresas].sort((a, b) => {
                const pa = (a.proj_perc !== null && a.proj_perc !== undefined) ? Number(a.proj_perc || 0) : Number(a.perc_total || 0);
                const pb = (b.proj_perc !== null && b.proj_perc !== undefined) ? Number(b.proj_perc || 0) : Number(b.perc_total || 0);
                // Meta: maior é melhor | Orçamento: menor é melhor
                return (modelo === 'orcamento') ? (pa - pb) : (pb - pa);
            });
            const melhor = empresasOrdenadas[0] || null;
            const pior = empresasOrdenadas[empresasOrdenadas.length - 1] || null;
            if (melhorEl) {
                const pm = melhor ? ((melhor.proj_perc !== null && melhor.proj_perc !== undefined) ? Number(melhor.proj_perc || 0) : Number(melhor.perc_total || 0)) : 0;
                melhorEl.textContent = melhor ? `${melhor.dsempresa} (${formatPercent(pm)})` : '-';
            }
            if (piorEl) {
                const pp = pior ? ((pior.proj_perc !== null && pior.proj_perc !== undefined) ? Number(pior.proj_perc || 0) : Number(pior.perc_total || 0)) : 0;
                piorEl.textContent = pior ? `${pior.dsempresa} (${formatPercent(pp)})` : '-';
            }

            const criticosLista = empresas
                .map((e) => {
                    const p = (e.proj_perc !== null && e.proj_perc !== undefined) ? Number(e.proj_perc || 0) : Number(e.perc_total || 0);
                    const isCritico = (modelo === 'orcamento') ? (p > 0.90) : (p < 0.90);
                    return {
                        nome: String(e.dsempresa || ''),
                        perc: p,
                        isCritico
                    };
                })
                .filter(x => x.isCritico)
                .sort((a, b) => (modelo === 'orcamento') ? (b.perc - a.perc) : (a.perc - b.perc));

            const criticosQtd = criticosLista.length;
            if (criticosEl) {
                criticosEl.textContent = String(criticosQtd);

                const instancia = (window.bootstrap && bootstrap.Popover) ? bootstrap.Popover.getInstance(criticosEl) : null;
                if (instancia) instancia.dispose();

                if (criticosQtd > 0 && window.bootstrap && bootstrap.Popover) {
                    const conteudo = criticosLista
                        .map(x => `<div style="margin-bottom: 4px;">${escapeHtml(x.nome)}: <strong>${escapeHtml(formatPercent(Number(x.perc || 0)))}</strong></div>`)
                        .join('');

                    criticosEl.setAttribute('data-bs-toggle', 'popover');
                    criticosEl.setAttribute('data-bs-trigger', 'hover focus');
                    criticosEl.setAttribute('data-bs-placement', 'top');
                    criticosEl.setAttribute('data-bs-html', 'true');
                    criticosEl.setAttribute('data-bs-title', (modelo === 'orcamento') ? 'Empresas acima de 90%' : 'Empresas abaixo de 90% na (Projeção)');
                    criticosEl.setAttribute('data-bs-content', conteudo);

                    new bootstrap.Popover(criticosEl, {
                        html: true,
                        sanitize: false,
                        customClass: 'popover-criticos'
                    });
                } else {
                    // limpa atributos quando não há críticos
                    criticosEl.removeAttribute('data-bs-toggle');
                    criticosEl.removeAttribute('data-bs-trigger');
                    criticosEl.removeAttribute('data-bs-placement');
                    criticosEl.removeAttribute('data-bs-html');
                    criticosEl.removeAttribute('data-bs-title');
                    criticosEl.removeAttribute('data-bs-content');
                }
            }

            const canvas = container.querySelector(`#chart-modelo-${modelo}`);
            if (!canvas || !window.Chart) return;

            const nomes = empresas.map(e => String(e.dsempresa || ''));
            const realizado = empresas.map(e => Number(e.total_real || 0));
            const restante = empresas.map(e => Math.max(0, Number(e.total_orc || 0) - Number(e.total_real || 0)));
            const totalOrcArr = empresas.map(e => Number(e.total_orc || 0));

            // Cor por empresa baseada na PROJEÇÃO (preferencial) ou no atingimento atual
            const statusPerc = empresas.map(e => {
                const pProj = e.proj_perc;
                if (pProj !== null && pProj !== undefined) return Number(pProj) || 0;
                return Number(e.perc_total || 0);
            });
            const statusHex = statusPerc.map(p => toneColorByModelo(modelo, Number(p || 0)));
            const corReal = statusHex.map(h => hexToRgba(h, 0.78));

            const hasProj = empresas.some(e => e.proj_total !== null && e.proj_total !== undefined);
            const projTotal = empresas.map(e => {
                const pv = e.proj_total;
                if (pv === null || pv === undefined) return null;
                return Number(pv);
            });

            destroyModeloChart(modelo);

            const baseDatasets = [
                {
                    label: labels.realizado,
                    data: realizado,
                    backgroundColor: corReal,
                    borderWidth: 0,
                    stack: 'stack-1'
                },
                {
                    label: labels.restante,
                    data: restante,
                    backgroundColor: 'rgba(226,232,240,0.95)',
                    borderWidth: 0,
                    stack: 'stack-1'
                }
            ];

            if (hasProj) {
                baseDatasets.push({
                    label: labels.projecao,
                    data: projTotal,
                    // Barra de projeção TOTAL sobreposta (não soma no stack)
                    type: 'bar',
                    grouped: false,
                    // Contorno para leitura (evita "misturar" com o realizado)
                    backgroundColor: 'rgba(0,0,0,0)',
                    borderColor: statusHex,
                    borderWidth: 3,
                    borderSkipped: false,
                    order: 99,
                    stack: 'stack-proj',
                    _role: 'proj'
                });
            }

            // Marca roles para o plugin de percentuais
            baseDatasets[0]._role = 'real';
            baseDatasets[1]._role = 'rest';

            const ctx = canvas.getContext('2d');
            chartsModelos[modelo] = new Chart(ctx, {
                type: 'bar',
                data: {
                    labels: nomes,
                    datasets: baseDatasets
                },
                options: {
                    indexAxis: 'x',
                    maintainAspectRatio: false,
                    responsive: true,
                    interaction: {
                        mode: 'index',
                        intersect: false
                    },
                    layout: {
                        padding: {
                            bottom: 10
                        }
                    },
                    scales: {
                        x: {
                            stacked: true,
                            ticks: {
                                callback: function(value) {
                                    const lblRaw = (this && typeof this.getLabelForValue === 'function')
                                        ? this.getLabelForValue(value)
                                        : value;
                                    const lbl = String(lblRaw ?? '');
                                    return lbl.length > 14 ? (lbl.slice(0, 14) + '…') : lbl;
                                },
                                autoSkip: true,
                                maxRotation: 30,
                                minRotation: 0
                            }
                        },
                        y: {
                            stacked: true,
                            ticks: {
                                callback: function(value) {
                                    return formatValor(Number(value || 0));
                                }
                            }
                        }
                    },
                    plugins: {
                        legend: {
                            position: 'bottom'
                        },
                        tooltip: {
                            enabled: false,
                            external: externalTooltipHandler,
                            mode: 'index',
                            intersect: false,
                            callbacks: {
                                title: function(items) {
                                    const it = items?.[0];
                                    return it ? String(it.label || '') : '';
                                },
                                label: function(ctx) {
                                    const idx = Number(ctx.dataIndex || 0);
                                    const base = Number(totalOrcArr[idx] || 0);
                                    const role = ctx?.dataset?._role;
                                    const raw = ctx.raw;

                                    if (!isFinite(base) || base <= 0) {
                                        const label = String(ctx.dataset.label || '');
                                        const v = Number(raw || 0);
                                        return label + ': ' + formatValor(isFinite(v) ? v : 0);
                                    }

                                    if (role === 'proj') {
                                        if (raw === null || raw === undefined) return null;
                                        const v = Number(raw);
                                        if (!isFinite(v)) return null;
                                        const p = v / base;
                                        return 'Projeção: ' + formatValor(v) + ' (' + formatPercent(p) + ')';
                                    }

                                    if (role === 'real') {
                                        const v = Number(raw || 0);
                                        const p = (isFinite(v) ? (v / base) : 0);
                                        return (modelo === 'orcamento' ? 'Realizado' : 'Realizado') + ': ' + formatValor(isFinite(v) ? v : 0) + ' (' + formatPercent(p) + ')';
                                    }

                                    if (role === 'rest') {
                                        const v = Number(raw || 0);
                                        const p = (isFinite(v) ? (v / base) : 0);
                                        return (modelo === 'orcamento' ? 'Saldo' : 'A realizar') + ': ' + formatValor(isFinite(v) ? v : 0) + ' (' + formatPercent(p) + ')';
                                    }

                                    const label = String(ctx.dataset.label || '');
                                    const v = Number(raw || 0);
                                    return label + ': ' + formatValor(isFinite(v) ? v : 0);
                                }
                            }
                        }
                    }
                },
                plugins: [percentInBarsPlugin],
            });

            // Atualiza opções do plugin (por chart) após criação
            chartsModelos[modelo].options.plugins.percentInBars = {
                totalOrc: totalOrcArr,
                showProj: hasProj,
                // Mostra % A Realizar acima e % Realizado abaixo
                showReal: false,
                showRealBelow: true,
                showRest: false,
                showRestBelow: false
            };
            chartsModelos[modelo].update();
        }

        function initVisaoConsolidadaComparativo() {
            const root = document.getElementById('dashboardConsolidadoComparativo');
            if (!root) return;

            root.querySelectorAll('[data-modelo]').forEach((card) => {
                const modelo = card.getAttribute('data-modelo');
                if (!modelo) return;

                if (modelo === 'orcamento' && dashboardOrcamentoTermometro && dashboardOrcamentoTermometro.mes) {
                    destroyOrcamentoCharts();
                    renderOrcamentoTermometro('mes');
                } else {
                    renderModeloComparativo(modelo, 'mes');
                }

                const toggle = card.querySelectorAll('[data-modelo-periodo]');
                toggle.forEach((btn) => {
                    btn.addEventListener('click', (e) => {
                        e.preventDefault();
                        toggle.forEach(b => b.classList.remove('active'));
                        btn.classList.add('active');
                        const periodo = btn.getAttribute('data-modelo-periodo');

                        if (modelo === 'orcamento' && dashboardOrcamentoTermometro && dashboardOrcamentoTermometro[periodo]) {
                            renderOrcamentoTermometro(periodo);
                        } else {
                            renderModeloComparativo(modelo, periodo);
                        }
                    });
                });
            });
        }
        
        function createDonutChart(ctx, m) {
            const orcAno = Number(m.orcAno || 0);
            const realAno = Number(m.realAno || 0);
            const restAno = Math.max(0, orcAno - realAno);
            const orcMes = Number(m.orcMes || 0);
            const realMes = Number(m.realMes || 0);
            const restMes = Math.max(0, orcMes - realMes);

            // Usar PROJEÇÃO, não percentual atingido
            const projAnoPerc = Number(m.projAnoPerc || 0);
            const projMesPerc = Number(m.projMesPerc || 0);
            const modeloVar = String(m.modelo || 'meta');
            const colAno  = toneColorByModelo(modeloVar, projAnoPerc);
            const colMes  = toneColorByModelo(modeloVar, projMesPerc);

            new Chart(ctx, {
                type: 'doughnut',
                data: {
                    labels: [dashboardLinguagem.realizado, dashboardLinguagem.restante],
                    datasets: [
                        {
                            // Anel externo: Ano
                            data: [realAno, restAno],
                            backgroundColor: [ colAno, 'rgba(226, 232, 240, 0.95)' ],
                            borderWidth: 0,
                            hoverOffset: 4,
                            cutout: '60%',
                            radius: '100%'
                        },
                        {
                            // Anel interno: Mês
                            data: [realMes, restMes],
                            backgroundColor: [ colMes, 'rgba(234, 238, 243, 0.95)' ],
                            borderWidth: 0,
                            hoverOffset: 4,
                            cutout: '0%',
                            radius: '60%'
                        }
                    ]
                },
                options: {
                    plugins: {
                        legend: { display: false },
                        tooltip: {
                            enabled: false, // ✅ desliga o tooltip "no canvas"
                            external: externalTooltipHandler, // ✅ tooltip HTML externo (não corta)
                            callbacks: {
                                label: function(ctx) {
                                    const label = ctx.label || '';
                                    const v = Number(ctx.raw || 0);
                                    const base = (ctx.datasetIndex === 0) ? orcAno : orcMes;
                                    const perc = base !== 0 ? (v / base) : 0;
                                    const percTxt = (perc * 100).toFixed(1).replace('.', ',') + '%';
                                    if (dashboardVisao === 'percentual') {
                                        return label + ': ' + percTxt;
                                    }
                                    return label + ': ' + formatValor(v) + ' (' + percTxt + ')';
                                }
                            }
                        }
                    }
                }
            });
        }

        function wireFeriadosToggle() {
            document.querySelectorAll('.feriados-toggle').forEach((el) => {
                el.addEventListener('click', (e) => {
                    e.preventDefault();
                    const id = el.getAttribute('data-feriados');
                    const list = document.getElementById('feriados-list-' + String(id));
                    if (!list) return;
                    list.classList.toggle('d-none');
                });
            });
        }
        

        const btnCharts = document.getElementById('btnViewCharts');
        const btnCards  = document.getElementById('btnViewCards');
        const contCharts= document.getElementById('dashboardChartsContainer');
        const contCards = document.getElementById('dashboardCardsContainer');

        if (btnCharts && btnCards && contCharts && contCards) {
            function mostrarGraficos() {
                contCharts.classList.remove('d-none');
                contCharts.style.display = 'block';
                contCards.classList.add('d-none');
                contCards.style.display = 'none';
                btnCharts.classList.add('btn-primary');
                btnCharts.classList.remove('btn-outline-secondary');
                btnCards.classList.remove('btn-primary');
                btnCards.classList.add('btn-outline-secondary');
            }

            function mostrarPlanilha() {
                contCharts.classList.add('d-none');
                contCharts.style.display = 'none';
                contCards.classList.remove('d-none');
                contCards.style.display = 'flex';
                btnCards.classList.add('btn-primary');
                btnCards.classList.remove('btn-outline-secondary');
                btnCharts.classList.remove('btn-primary');
                btnCharts.classList.add('btn-outline-secondary');
            }

            mostrarGraficos();

            btnCharts.addEventListener('click', function (e) {
                e.preventDefault();
                mostrarGraficos();
            });

            btnCards.addEventListener('click', function (e) {
                e.preventDefault();
                mostrarPlanilha();
            });
        }

        try {
            if (dashboardVisao !== 'modelo') {
                buildKpiDonuts();
            } else {
                initVisaoConsolidadaComparativo();
            }
        } catch (e) {
            console.error('Erro ao inicializar gráficos do dashboard:', e);
        }

        try { wireFeriadosToggle(); } catch (e) { console.error('Erro wireFeriadosToggle:', e); }
        try { initKpiToggle(); } catch (e) { console.error('Erro initKpiToggle:', e); }
        try { initKpiListaAccordion(); } catch (e) { console.error('Erro initKpiListaAccordion:', e); }
        try { initModeloToggle(); } catch (e) { console.error('Erro initModeloToggle:', e); }
        try { initModeloCarousel(); } catch (e) { console.error('Erro initModeloCarousel:', e); }
        try { initAlertaScroll(); } catch (e) { console.error('Erro initAlertaScroll:', e); }
        try { initExibicaoToggle(); } catch (e) { console.error('Erro initExibicaoToggle:', e); }
        try { initTendenciaMes(); } catch (e) { console.error('Erro initTendenciaMes:', e); }

        // Sincronização automática de período
        const modalSyncAuto = new bootstrap.Modal(document.getElementById('modalSyncAuto'));

        function setSyncStage(stage) {
            const $bar = document.querySelector('#syncProgresso .progress-bar');
            const steps = ['preparar', 'sincronizar', 'consolidar', 'atualizar'];
            let idx = steps.indexOf(stage);
            if (idx === -1) idx = 0;

            document.querySelectorAll('#syncEtapas li').forEach(li => {
                li.classList.remove('fw-bold', 'text-success');
            });
            
            steps.forEach((s, i) => {
                const $li = document.querySelector(`#syncEtapas li[data-step="${s}"]`);
                if (i < idx) {
                    $li.classList.add('text-success', 'fw-bold');
                } else if (i === idx) {
                    $li.classList.add('fw-bold');
                }
            });

            let width = 0;
            if (stage === 'preparar') width = 15;
            else if (stage === 'sincronizar') width = 50;
            else if (stage === 'consolidar') width = 80;
            else if (stage === 'atualizar') width = 100;
            $bar.style.width = width + '%';
        }

        window.abrirSyncModal = function(e) {
            e.preventDefault();
            document.getElementById('syncResultado').innerHTML = '';
            document.getElementById('syncProgresso').style.display = 'none';
            document.querySelectorAll('#syncEtapas li').forEach(li => {
                li.classList.remove('fw-bold', 'text-success');
            });
            document.querySelector('#syncProgresso .progress-bar').style.width = '0%';
            document.getElementById('btnFecharSync').disabled = false;
            document.getElementById('btnFecharSyncFooter').disabled = false;
            
            modalSyncAuto.show();
            executarSyncAutomatico();
        };

        async function executarSyncAutomatico() {
            document.getElementById('syncProgresso').style.display = 'block';
            setSyncStage('preparar');
            document.body.style.cursor = 'wait';

            document.getElementById('syncResultado').innerHTML = `
                <div class="text-center py-3">
                    <div class="spinner-border text-warning" role="status">
                        <span class="visually-hidden">Sincronizando...</span>
                    </div>
                    <p class="mt-2 mb-0">Sincronizando dados do período automático, aguarde...</p>
                </div>
            `;

            try {
                setSyncStage('sincronizar');
                const resp = await fetch('?m=home_actions&ajax=sincronizar_periodo_automatico', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json;charset=UTF-8' },
                    body: JSON.stringify({})
                });

                let json, texto;
                try {
                    texto = await resp.text();
                    if (!texto) {
                        throw new Error('Resposta vazia do servidor');
                    }
                    json = JSON.parse(texto);
                } catch (parseErr) {
                    console.error('Erro ao parsear JSON:', parseErr, 'Resposta:', texto);
                    document.getElementById('syncResultado').innerHTML = `<div class="alert alert-danger mt-2">Erro ao processar resposta do servidor (${resp.status})</div>`;
                    document.getElementById('btnFecharSync').disabled = false;
                    document.getElementById('btnFecharSyncFooter').disabled = false;
                    document.body.style.cursor = '';
                    return;
                }

                if (!json.ok) {
                    document.getElementById('syncResultado').innerHTML = `<div class="alert alert-warning mt-2">${json.msg || 'Erro na sincronização'}</div>`;
                    document.getElementById('btnFecharSync').disabled = false;
                    document.getElementById('btnFecharSyncFooter').disabled = false;
                    document.body.style.cursor = '';
                    return;
                }

                // Validar se houve sincronização efetiva
                if (!json || json === null || (json.total === null || json.total === undefined)) {
                    document.getElementById('syncResultado').innerHTML = `
                        <div class="alert alert-danger mt-2">
                            <i class="bi bi-exclamation-circle"></i>
                            <strong>Sincronização nunca foi efetuada!</strong><br>
                            <small>Nenhuma integração está configurada ou ativa para esta empresa. Por favor, contate o administrador do sistema.</small>
                        </div>
                    `;
                    document.getElementById('btnFecharSync').disabled = false;
                    document.getElementById('btnFecharSyncFooter').disabled = false;
                    document.body.style.cursor = '';
                    return;
                }

                setSyncStage('consolidar');

                let htmlResumo = `
                    <div class="mt-2">
                        <h6 class="mb-2"><i class="bi bi-check-circle"></i> Sincronização concluída</h6>
                        <div class="alert alert-success py-2 px-2 small">${json.msg}</div>
                        <div class="alert alert-info py-2 px-2 small mb-0">
                            <strong>Totais:</strong> ${json.total || 0} inseridos | ${json.ignorados || 0} ignorados | ${json.erros || 0} erros
                        </div>
                `;

                if (json.ignorados_motivos) {
                    const m = json.ignorados_motivos;
                    const itens = [];
                    if (m.empresa_origem_sem_mapeamento) itens.push(`<li>${m.empresa_origem_sem_mapeamento} com empresa de origem sem mapeamento em back.empresa.cdintegracao</li>`);
                    if (m.empresa_nao_vinculada_integracao) itens.push(`<li>${m.empresa_nao_vinculada_integracao} de empresas não vinculadas à integração (back.integracao_empresa)</li>`);
                    if (m.dtmovimento_vazio) itens.push(`<li>${m.dtmovimento_vazio} sem dtmovimento na query de origem</li>`);
                    if (m.dtmovimento_invalido) itens.push(`<li>${m.dtmovimento_invalido} com dtmovimento em formato inválido</li>`);
                    if (m.exercicio_nao_criado) itens.push(`<li>${m.exercicio_nao_criado} sem exercício válido para empresa/ano</li>`);

                    if (itens.length) {
                        htmlResumo += `
                            <div class="alert alert-warning py-2 px-2 small mt-2 mb-0">
                                <strong>Motivos dos ignorados:</strong>
                                <ul class="mb-0">${itens.join('')}</ul>
                            </div>
                        `;
                    }
                }

                htmlResumo += '</div>';
                document.getElementById('syncResultado').innerHTML = htmlResumo;
                setSyncStage('atualizar');

                // Deixa o usuário ver o resultado antes de recarregar
                // Para recarregar manualmente, o usuário clica no fechar

            } catch (e) {
                console.error(e);
                document.getElementById('syncResultado').innerHTML = `<div class="alert alert-danger mt-2">${e.message || 'Erro inesperado na sincronização.'}</div>`;
            } finally {
                document.getElementById('btnFecharSync').disabled = false;
                document.getElementById('btnFecharSyncFooter').disabled = false;
                document.body.style.cursor = '';
            }
        }

        // Recarregar página quando usuário fecha o modal
        document.getElementById('btnFecharSync').addEventListener('click', function() {
            location.reload();
        });
        document.getElementById('btnFecharSyncFooter').addEventListener('click', function() {
            location.reload();
        });
    });

    // ========== Scripts dos Filtros ==========
    
    function atualizarLabelEmpresas() {
        const checkboxesDesktop = document.querySelectorAll('#filtrosFormDesktop input.empresa-checkbox:checked');
        const labelDesktop = document.getElementById('empresasLabelDesktop');
        
        if (checkboxesDesktop.length === 0) {
            labelDesktop.textContent = 'Nenhuma selecionada';
        } else if (checkboxesDesktop.length === 1) {
            const empresa = checkboxesDesktop[0].parentElement.parentElement.querySelector('label small').textContent;
            labelDesktop.textContent = empresa;
        } else {
            labelDesktop.textContent = `${checkboxesDesktop.length} selecionadas`;
        }
    }

    function atualizarLabelMeses() {
        const mesesDesktop = document.querySelectorAll('#filtrosFormDesktop input.mes-checkbox:checked');
        const labelDesktop = document.getElementById('mesesLabelDesktop');
        if (!labelDesktop) return;

        if (mesesDesktop.length === 0) {
            labelDesktop.textContent = 'Nenhum selecionado';
        } else if (mesesDesktop.length === 1) {
            const nome = mesesDesktop[0].parentElement.parentElement.querySelector('label small')?.textContent;
            labelDesktop.textContent = nome || '1 selecionado';
        } else {
            labelDesktop.textContent = `${mesesDesktop.length} selecionados`;
        }
    }

    function mesesDoTrimestre(tri) {
        const t = Number(tri || 0);
        if (t < 1 || t > 4) return [];
        const start = (t - 1) * 3 + 1;
        return [start, start + 1, start + 2];
    }

    function sincronizarMesesComTrimestre(tri) {
        const meses = mesesDoTrimestre(tri);
        if (meses.length === 0) return;

        // Flag para não disparar o comportamento inverso (meses -> trimestre)
        window.__syncMesesFromTrimestre = true;

        // Ajusta meses em ambos formulários (desktop + mobile)
        ['#filtrosForm', '#filtrosFormDesktop'].forEach(formSel => {
            const form = document.querySelector(formSel);
            if (!form) return;
            form.querySelectorAll('input.mes-checkbox').forEach(cb => {
                const m = Number(cb.value);
                cb.checked = meses.includes(m);
            });
        });

        // "Selecionar todos" deve ficar desmarcado (apenas 3 meses)
        const allMesesMobile = document.getElementById('selecionarTodosMeses');
        const allMesesDesktop = document.getElementById('selecionarTodosMesesDesktop');
        if (allMesesMobile) allMesesMobile.checked = false;
        if (allMesesDesktop) allMesesDesktop.checked = false;

        atualizarLabelMeses();

        window.__syncMesesFromTrimestre = false;
    }

    function sincronizarSelectTrimestre(valor) {
        const v = String(valor ?? '0');
        const tDesk = document.getElementById('filtroTrimestreDesktop');
        const tMob  = document.getElementById('filtroTrimestre');
        if (tDesk && String(tDesk.value) !== v) tDesk.value = v;
        if (tMob && String(tMob.value) !== v) tMob.value = v;
    }
    
    function aplicarFiltros() {
        const formMobile = document.getElementById('filtrosForm');
        const formDesktop = document.getElementById('filtrosFormDesktop');

        // Definir qual layout está ativo de forma estável (mesmo com collapse/dropdown)
        const isDesktop = window.matchMedia('(min-width: 768px)').matches;
        const formAtivo = isDesktop ? formDesktop : formMobile;

        if (!formAtivo) {
            console.warn('Nenhum formulário de filtros encontrado');
            return;
        }

        // Coletar valores dos filtros
        const params = new URLSearchParams();
        
        // Ano
        const anoInput = formAtivo.querySelector('select[name="ano"]');
        if (anoInput && anoInput.value !== undefined) params.append('ano', anoInput.value);

        // Trimestre (precisa vir antes do mês para forçar meses do trimestre, se aplicável)
        const trimestreInput = formAtivo.querySelector('select[name="trimestre"]');
        const trimestreVal = trimestreInput && trimestreInput.value !== undefined ? Number(trimestreInput.value || 0) : 0;

        // Mês (múltiplos checkboxes)
        let mesesCheckedUnique = [];
        if (trimestreVal > 0) {
            // Regra: ao aplicar trimestre, seleciona automaticamente todos os meses do trimestre
            mesesCheckedUnique = mesesDoTrimestre(trimestreVal).map(String);
        } else {
            const mesesChecked = Array.from(formAtivo.querySelectorAll('input.mes-checkbox:checked'))
                .map(cb => cb.value)
                .filter(v => v !== null && v !== undefined && String(v).trim() !== '');
            mesesCheckedUnique = Array.from(new Set(mesesChecked));
        }

        if (mesesCheckedUnique.length > 0) {
            mesesCheckedUnique.forEach(m => params.append('mes[]', m));
        }
        
        // País
        const paisInput = formAtivo.querySelector('select[name="cdpais"]');
        if (paisInput && paisInput.value !== undefined) params.append('cdpais', paisInput.value);

        // Se o usuário interagiu com o campo de país nesta tela, sinalizar para o backend
        // aplicar o comportamento "selecionar todas as empresas do país" mesmo se o valor não mudou.
        if (window.__paisTouched === true) {
            params.append('pais_explicit', '1');
        }

        // Moeda
        const moedaInput = formAtivo.querySelector('select[name="cdmoeda"]');
        if (moedaInput && moedaInput.value !== undefined) params.append('cdmoeda', moedaInput.value);

        if (window.__moedaTouched === true) {
            params.append('moeda_explicit', '1');
        }
        
        // Empresas (múltiplos checkboxes)
        // IMPORTANTE: existem checkboxes duplicados (mobile + desktop).
        // Coletar SOMENTE do form ativo para não agregar empresa marcada no form escondido.
        const empresasChecked = Array.from(formAtivo.querySelectorAll('input.empresa-checkbox:checked'))
            .map(cb => cb.value)
            .filter(v => v !== null && v !== undefined && String(v).trim() !== '');
        const empresasCheckedUnique = Array.from(new Set(empresasChecked));
        
        // DEBUG detalhado
        const allCheckboxes = formAtivo.querySelectorAll('input.empresa-checkbox');
        console.log('[aplicarFiltros] Form ativo:', formAtivo.id, '| isDesktop=', isDesktop);
        console.log('[aplicarFiltros] Total de checkboxes no form ativo:', allCheckboxes.length);
        console.log('[aplicarFiltros] Checkboxes checked (raw):', empresasChecked);
        console.log('[aplicarFiltros] Checkboxes checked (unique):', empresasCheckedUnique);
        console.log('[aplicarFiltros] Quantidade (unique):', empresasCheckedUnique.length);
        
        // IMPORTANTE: Se não há empresas selecionadas, NÃO enviar parâmetro cdempresa
        // Isto faz PHP usar SESSION (mantém seleção anterior)
        if (empresasCheckedUnique.length > 0) {
            empresasCheckedUnique.forEach(emp => {
                params.append('cdempresa[]', emp);
                console.log('[aplicarFiltros] Adicionando cdempresa[]=' + emp);
            });
        } else {
            console.log('[aplicarFiltros] Nenhuma empresa selecionada, não enviando cdempresa (usará SESSION)');
        }
        
        // Centro de Custo
        const centroCustoInput = formAtivo.querySelector('select[name="cdcentrocusto"]');
        if (centroCustoInput && centroCustoInput.value !== undefined) params.append('cdcentrocusto', centroCustoInput.value);
        
        // Trimestre
        if (trimestreInput && trimestreInput.value !== undefined) params.append('trimestre', String(trimestreVal));
        
        // Log de debug
        const urlCompleta = '?' + params.toString();
        console.log('[aplicarFiltros] URL completa:', urlCompleta);
        console.log('[aplicarFiltros] Parâmetros:', Object.fromEntries(params));
        
        // Debug: mostrar o que está sendo enviado
        let debugMsg = 'Filtros aplicados:\n';
        debugMsg += 'Ano: ' + (anoInput?.value || 'N/A') + '\n';
        debugMsg += 'Meses: ' + (mesesCheckedUnique.length > 0 ? mesesCheckedUnique.join(', ') : 'Nenhum') + '\n';
        debugMsg += 'País: ' + (paisInput?.value || 'Todos') + '\n';
        debugMsg += 'Moeda: ' + (moedaInput?.value || 'N/A') + '\n';
        debugMsg += 'Empresas: ' + (empresasCheckedUnique.length > 0 ? empresasCheckedUnique.join(', ') : 'Nenhuma') + '\n';
        debugMsg += 'Centro: ' + (centroCustoInput?.value || 'Todos') + '\n';
        debugMsg += 'Trimestre: ' + (trimestreInput?.value || 'N/A') + '\n\n';
        debugMsg += 'URL:\n' + urlCompleta;
        console.log(debugMsg);
        
        // Redirecionar com todos os parâmetros
        window.location.href = urlCompleta;
    }
    
    function limparFiltros() {
        // Limpar todos os checkboxes de empresa
        document.querySelectorAll('input.empresa-checkbox').forEach(cb => cb.checked = false);
        document.getElementById('selecionarTodas').checked = false;
        document.getElementById('selecionarTodasDesktop').checked = false;

        // Limpar meses
        document.querySelectorAll('input.mes-checkbox').forEach(cb => cb.checked = false);
        const allMesesMobile = document.getElementById('selecionarTodosMeses');
        const allMesesDesktop = document.getElementById('selecionarTodosMesesDesktop');
        if (allMesesMobile) allMesesMobile.checked = false;
        if (allMesesDesktop) allMesesDesktop.checked = false;
        
        // Atualizar labels
        atualizarLabelEmpresas();
        atualizarLabelMeses();
        
        // Redirecionar para home com parâmetro de limpeza
        window.location.href = '?limpar_filtros=1';
    }

    function toggleTodasEmpresas() {
        const checkboxMobile = document.getElementById('selecionarTodas');
        const checkboxDesktop = document.getElementById('selecionarTodasDesktop');
        
        const empresasCheckboxesMobile = document.querySelectorAll('#filtrosForm input.empresa-checkbox');
        const empresasCheckboxesDesktop = document.querySelectorAll('#filtrosFormDesktop input.empresa-checkbox');
        
        const isChecked = checkboxMobile?.checked || checkboxDesktop?.checked;
        
        empresasCheckboxesMobile.forEach(cb => cb.checked = isChecked);
        empresasCheckboxesDesktop.forEach(cb => cb.checked = isChecked);
        
        // Sincronizar checkbox "Selecionar Todas" entre mobile e desktop
        if (checkboxMobile) checkboxMobile.checked = isChecked;
        if (checkboxDesktop) checkboxDesktop.checked = isChecked;
        
        // Atualizar label
        atualizarLabelEmpresas();
    }

    function toggleTodosMeses() {
        const checkboxMobile = document.getElementById('selecionarTodosMeses');
        const checkboxDesktop = document.getElementById('selecionarTodosMesesDesktop');

        const mesesCheckboxesMobile = document.querySelectorAll('#filtrosForm input.mes-checkbox');
        const mesesCheckboxesDesktop = document.querySelectorAll('#filtrosFormDesktop input.mes-checkbox');

        const isChecked = checkboxMobile?.checked || checkboxDesktop?.checked;

        mesesCheckboxesMobile.forEach(cb => cb.checked = isChecked);
        mesesCheckboxesDesktop.forEach(cb => cb.checked = isChecked);

        if (checkboxMobile) checkboxMobile.checked = isChecked;
        if (checkboxDesktop) checkboxDesktop.checked = isChecked;

        atualizarLabelMeses();
    }
    
    // Inicializar labels ao carregar página
    document.addEventListener('DOMContentLoaded', function() {
        atualizarLabelEmpresas();
        atualizarLabelMeses();
        
        // Inicializar tooltips do Bootstrap
        const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
        tooltipTriggerList.map(function (tooltipTriggerEl) {
            return new bootstrap.Tooltip(tooltipTriggerEl);
        });

        // Se trimestre estiver selecionado, sincroniza meses automaticamente (desktop e mobile)
        const triDesk = document.getElementById('filtroTrimestreDesktop');
        const triMob  = document.getElementById('filtroTrimestre');
        const triInicial = Number(triDesk?.value || triMob?.value || 0);
        if (triInicial > 0) {
            sincronizarSelectTrimestre(triInicial);
            sincronizarMesesComTrimestre(triInicial);
        }

        // Ao mudar trimestre, forçar meses do trimestre e manter selects sincronizados
        [triDesk, triMob].forEach(el => {
            if (!el) return;
            el.addEventListener('change', () => {
                const tri = Number(el.value || 0);
                sincronizarSelectTrimestre(tri);
                if (tri > 0) {
                    sincronizarMesesComTrimestre(tri);
                }
            });
        });

        // Inverso: ao mudar meses manualmente, limpar trimestre (para não ficar incoerente)
        const attachMesChangeHandler = (formSel) => {
            const form = document.querySelector(formSel);
            if (!form) return;
            form.querySelectorAll('input.mes-checkbox').forEach(cb => {
                cb.addEventListener('change', () => {
                    if (window.__syncMesesFromTrimestre === true) return;
                    const triDesk2 = document.getElementById('filtroTrimestreDesktop');
                    const triMob2  = document.getElementById('filtroTrimestre');
                    const triAtual = Number(triDesk2?.value || triMob2?.value || 0);
                    if (triAtual > 0) {
                        sincronizarSelectTrimestre(0);
                    }
                    atualizarLabelMeses();
                });
            });
        };

        attachMesChangeHandler('#filtrosForm');
        attachMesChangeHandler('#filtrosFormDesktop');

        // Marcar interação explícita com o filtro de País (desktop e mobile)
        // (select não dispara 'change' quando re-seleciona o mesmo valor; por isso usamos interação)
        window.__paisTouched = false;
        window.__moedaTouched = false;
        ['#filtroPaisDesktop', '#filtroPais'].forEach(sel => {
            const el = document.querySelector(sel);
            if (!el) return;
            el.addEventListener('mousedown', () => { window.__paisTouched = true; }, { passive: true });
            el.addEventListener('focus', () => { window.__paisTouched = true; }, { passive: true });
        });

        ['#filtroMoedaDesktop', '#filtroMoeda'].forEach(sel => {
            const el = document.querySelector(sel);
            if (!el) return;
            el.addEventListener('mousedown', () => { window.__moedaTouched = true; }, { passive: true });
            el.addEventListener('focus', () => { window.__moedaTouched = true; }, { passive: true });
        });

        // Evitar que o dropdown feche ao clicar dentro (checkbox/label)
        document.querySelectorAll('#filtrosFormDesktop .dropdown-menu').forEach(menu => {
            menu.addEventListener('click', function(e) {
                e.stopPropagation();
            });
        });
        
        // DEBUG: Log do estado dos checkboxes ao carregar
        const checkboxesDesktop = document.querySelectorAll('#filtrosFormDesktop input.empresa-checkbox:checked');
        const checkboxesMobile = document.querySelectorAll('#filtrosForm input.empresa-checkbox:checked');
        console.log('[DOMContentLoaded] Checkboxes marcadas no Desktop:', Array.from(checkboxesDesktop).map(cb => cb.value));
        console.log('[DOMContentLoaded] Checkboxes marcadas no Mobile:', Array.from(checkboxesMobile).map(cb => cb.value));
        
        // Sincronizar estado do "Selecionar Todas"
        const totalCheckboxes = document.querySelectorAll('#filtrosFormDesktop input.empresa-checkbox').length;
        const checkedDesktop = document.querySelectorAll('#filtrosFormDesktop input.empresa-checkbox:checked').length;
        const checkedMobile = document.querySelectorAll('#filtrosForm input.empresa-checkbox:checked').length;
        
        const selecionarTodasDesktop = document.getElementById('selecionarTodasDesktop');
        const selecionarTodasMobile = document.getElementById('selecionarTodas');
        
        // Se todos estão marcados, marcar "Selecionar Todas"
        if (selecionarTodasDesktop && checkedDesktop === totalCheckboxes && totalCheckboxes > 0) {
            selecionarTodasDesktop.checked = true;
            console.log('[DOMContentLoaded] Todos selecionados (Desktop) - marcando checkbox "Selecionar Todas"');
        }
        if (selecionarTodasMobile && checkedMobile === totalCheckboxes && totalCheckboxes > 0) {
            selecionarTodasMobile.checked = true;
            console.log('[DOMContentLoaded] Todos selecionados (Mobile) - marcando checkbox "Selecionar Todas"');
        }

        // Chevron rotation para o toggle de filtros desktop
        const filtrosCollapseDesktop = document.getElementById('filtrosCollapseDesktop');
        const filtrosChevron = document.getElementById('filtrosChevronDesktop');
        if (filtrosCollapseDesktop && filtrosChevron) {
            filtrosCollapseDesktop.addEventListener('show.bs.collapse', function() {
                filtrosChevron.style.transform = 'rotate(180deg)';
            });
            filtrosCollapseDesktop.addEventListener('hide.bs.collapse', function() {
                filtrosChevron.style.transform = 'rotate(0deg)';
            });
        }
    });
</script>
