/* ==========================================================================
   +JUNTOS 2026 - camada de override do projeto (dist/css/app.css)
   ==========================================================================

   COMO TRABALHAR AQUI
   -------------------
   Este projeto NAO tem build de front-end: nao existe Vite nem Mix rodando,
   e este arquivo e editado a mao e servido direto. O cache e furado pelo
   ?v={{ filemtime(...) }} nos dois head.blade.php, entao basta salvar.

   Ordem de carga (importa muito):
     plugins (@stack('styles')) -> adminlte.purged.css -> ESTE ARQUIVO
   Como este e o ultimo, para vencer AdminLTE, Bootstrap ou plugins basta
   igualar a especificidade deles. So use !important quando o concorrente
   tiver especificidade MAIOR, ou for style inline (do Blade ou escrito por
   JS de plugin, como o jquery-knob faz no input). Fora disso, e ruido.
   Regra pratica: antes de escrever !important, confira quem esta ganhando.

   As variantes mobile dos componentes NAO ficam junto do componente: estao
   agrupadas na secao 15, que por historico caiu no meio do arquivo. Mover
   isso mudaria a cascata, o que exige validar tela por tela no browser -
   por isso segue assim, e por isso a numeracao abaixo parece torta.

   INDICE (na ordem do arquivo)
   ----------------------------
   1.  Design tokens
   2.  Base, links e chrome do AdminLTE
       2.1 Preloader: a garrafa enchendo (a peca da secao 9.1, so o nivel muda)
   3.  Login e telas de auth
   4.  Utilitarios de layout
   5.  Dash: KPIs, knob e cards
   6.  Dash: ranking
   7.  Dash: noticias e venda acumulada
   8.  Dash: comparativos
   9.  Dash: gatilho
       9.1 a garrafa que enche (duas fotos + SVG, animado so com transform)
   10. Dash: premiacao e relampago
   11. Dash: logindash
   12. Botoes, textos e formularios
   13. Plugins: Select2 e foco de campo
   14. Conteudo: premios, termo, PDF e links
       14.1 texto escrito no editor rico (novidade e aviso) e o miolo do
            Summernote no painel
   15. Ajustes por breakpoint (@supports e @media)
       15.1 telas de auth no celular: tudo na tela, sem rolagem
   16. Utilitarios diversos
       16.1 o "?" de ajuda (balao explicativo; o .mj-tip vive no 19.2)
   17. Listagens: tabela no desktop, cards no mobile
       + cor da paginacao (vermelho escuro do tema)
   18. Ajuste de metas: grade de KPIs por mes
       18.1 a linha do gatilho e o resumo do alvo/marcos
       18.2 aviso de ajuste sobrescrito (renderiza na tela de importacoes)
   19. Ranking: leaderboard por grupo
       19.1 grade larga. Usa @container, nao @media: a sidebar do AdminLTE muda
            a largura util do painel sem mudar a da janela. Por isso as
            variantes deste componente nao ficam na secao 15.
       19.2 abas geral/mes, scoreboard e grafico de evolucao (SVG, sem Chart.js)
       19.3 posicao dentro do card-rede (dash de admin e executivo)
       19.4 os grupos lado a lado (admin sem recorte de grupo)
       19.5 bloco de topo do dash: posicao + evolucao na mesma linha
       19.6 coluna lateral do dash encostando no rodape da linha
   20. Animacoes de entrada (IntersectionObserver, uma vez por peca)
       20.1 escalonamento  20.2 barras  20.3 tracos SVG
       20.4 entrada de blocos  20.5 knob
   21. Premios: simulacao de premiacao mensal
       Tabela no espaco largo, cards no estreito. Usa @container, como o 19.
   22. Importacoes: as etapas da carga
       22.1 acompanhamento da apuracao do ranking
   23. Sessoes ativas: KPIs do topo e o relogio do auto-refresh
   24. Destino: a viagem do premio final (a unica tela que e peca, e nao
       relatorio). Tambem usa @container, como o 19 e o 21.

   ==========================================================================
   1. DESIGN TOKENS
   --------------------------------------------------------------------------
   Fonte unica de verdade do tema. Para retematizar, altere so este bloco.
   Nota: Bootstrap 4.6 nao consome custom properties; estes tokens sao
   consumidos apenas por este arquivo.
   ========================================================================== */
:root {
    /* Marca */
    --brand: #ed1c24;
    --brand-rgb: 237, 28, 36;
    --brand-dark: #b00006;
    /* fim dos gradientes (preloader, sidebar mobile) */
    --brand-active: #b3211d;
    /* item ativo da sidebar */
    --accent: #ffcb00;
    /* estrelas, destaques */
    --ok: #1a9c53;
    /* meta batida em texto sobre fundo claro. O #1BEE78 do Functions::VERDE
       e feito para fundo escuro e some no branco */
    --brand-deep: #611e1e;
    /* textos pequenos sobre fundo claro */

    /* Textura de fundo da pagina. Vive num token porque e consumida em TRES
       lugares que precisam ser identicos (body::before, .modal-content e
       .preloader - vide secoes 2 e 2.1); trocar a arte e uma linha so.
       Sao DUAS artes: esta, mais discreta, e a do painel; o login troca o
       token pela arte cheia (secao 3).
       A URL em si nao esta aqui: vem de --arte-fundo-painel, definida no
       tema.css que mora na pasta de arte da campanha. Este arquivo e igual nas
       duas campanhas; o que muda e o arquivo de la. */
    --page-bg: var(--arte-fundo-painel);

    /* Texto */
    --text: #333333;
    --text-muted: #6c757d;
    /* rotulos, legendas (cinza do Bootstrap 4) */

    /* Neutros de estrutura */
    --border: #dee2e6;
    /* borda de card e tabela */
    --divider: #f1f3f5;
    /* separador interno, mais leve que a borda */
    --surface: #fff;
    /* fundo de card sobre o bg da pagina */

    /* Forma */
    --radius: 10px;
    --radius-lg: 12px;
    --radius-sm: 0.25rem;
    /* botoes e pills */

    /* Sombras */
    --shadow-brand: 0 0 2px rgba(var(--brand-rgb), 0.3),
        0 1px 3px rgba(var(--brand-rgb), 0.5);
    --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.08);
}


/* ==========================================================================
   2. BASE, LINKS E CHROME DO ADMINLTE
   ========================================================================== */
html,
body {
    font-family: 'Montserrat', sans-serif;
}

/* A cor de base fica no HTML, e o BODY precisa ser transparente. Nao e questao
   de gosto: o body::before abaixo tem z-index negativo, e camada negativa entra
   no contexto de empilhamento da RAIZ, nao do body. Nesse contexto a ordem e
   fundo do html -> camadas negativas -> fundo dos blocos em fluxo, e o body e
   um bloco em fluxo. Ou seja, qualquer cor no body e pintada DEPOIS da imagem e
   a tapa. O !important vence o .login-page do AdminLTE, que pinta #e9ecef aqui. */
html {
    background: #fff !important;
}

body {
    background: transparent !important;
}

/* A textura da pagina e uma CAMADA FIXA, nao um background-attachment: fixed.
   Motivo: no iOS o attachment fixed nao e fixo de verdade - o fundo e medido
   pela viewport, e a barra de URL que some e volta no scroll muda essa altura,
   entao a imagem redimensiona e pula enquanto a pessoa rola. Um ::before com
   position: fixed da o mesmo efeito parado, sem esse recalculo.

   O cover e obrigatorio: as artes sao 16:9, e com background-size: 100% (largura
   cheia, altura automatica) num celular de 390px a imagem vira uma faixa de
   ~220px no topo com branco embaixo.

   z-index: -1 poe a camada abaixo do conteudo. Nenhum ancestral pode criar
   contexto de empilhamento aqui (transform, filter, opacity < 1), senao ela
   some - por isso o fundo mora no body e nao no .wrapper. */
body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    background: var(--page-bg) no-repeat center center #fff;
    background-size: cover;
}

/* O modal e uma caixa menor que a tela: com attachment fixed ele mostrava um
   recorte deslocado da imagem, diferente a cada posicao de scroll. */
.modal-content {
    background: var(--page-bg) no-repeat center center #fff !important;
    background-size: cover !important;
}

.content-wrapper {
    padding: 10px;
}

.navbar-dark,
.sidebar-dark-primary {
    background: var(--brand);
    border: 0;
}

.navbar-dark .navbar-nav .nav-link {
    color: var(--brand);
}

.navbar-dark .nav-link:hover {
    color: #000 !important;
}

/* --------------------------------------------------------------------------
   2.1 Preloader: a garrafa enchendo
   --------------------------------------------------------------------------
   Markup em layouts/preloader.blade.php, que so inclui layouts/garrafa.blade.php
   - a peca e a MESMA do card de gatilho (secao 9.1): as mesmas duas fotos, a
   mesma onda, as mesmas bolhas. Aqui so troca o que era ligado ao dado.

   La:    .liq-nivel  = translateY calculado de --fill, o percentual real.
   Aqui:  .pre-nivel  = enche uma vez ate o gargalo e para.

   O mapa do viewBox e o mesmo dos dois lados - fundo do liquido y=2010, linha
   d'agua da foto cheia y=324 - senao as duas garrafas discordariam da mesma
   fotografia.

   Depois que enche, a peca NAO congela: as bolhas continuam subindo e o
   respiro do .liq-balanco continua. O que para e so a onda, e de proposito -
   garrafa cheia tem superficie parada, e e ai que a foto vazia troca pela
   cheia e a peca vira exatamente a fotografia do produto.
   Por isso tambem nao ha loop de enche-esvazia: esvaziar a garrafa a cada 2s
   passaria a mensagem errada.

   O fundo e o mesmo da pagina (--page-bg, seja a arte do painel ou a do
   login). Assim a cortina nao troca de cor ao subir, so revela o conteudo.
   -------------------------------------------------------------------------- */
/* Copia fiel da camada de fundo da pagina (body::before, secao 2), inclusive o
   position e o size: qualquer diferenca aqui vira um salto de imagem quando a
   cortina sobe, que e exatamente o que este fundo existe para evitar. O
   .preloader ja e position: fixed cobrindo a tela, entao basta repetir o
   enquadramento. */
.preloader {
    background: var(--page-bg) no-repeat center center #fff;
    background-size: cover;
}

.pre-garrafa {
    /* Duracao da agitacao da superficie (secao 9.1). Aqui e a do preEnche, que
       nao tem atraso e dura menos que o gatilhoEnche do card - sem acertar isto
       a superficie continuaria batendo depois de a garrafa ter parado de subir.
       E tambem quando a onda assenta e o gargalo da foto cheia aparece. */
    --churn: 1.7s;

    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.75rem;
}

/* Vence o width/height 100% de .garrafa (secao 9.1) por especificidade: la a
   garrafa preenche a coluna do card, aqui ela e que define o tamanho. */
.pre-garrafa .garrafa {
    width: auto;
    height: min(56vh, 380px);
}

.pre-marca {
    width: min(160px, 40vw);
    height: auto;
    fill: var(--brand);
    animation: preMarca 0.7s ease-out 0.55s both;
}

/* O 88% e uma passada do nivel final: liquido que sobe rapido bate no gargalo
   e volta um pouco. Sem isso a subida termina como uma barra de progresso.

   Para exatamente em 324, que e onde a FOTO cheia realmente para - com o ar
   que toda garrafa tem embaixo da tampa. Nao ha o que escolher aqui: passar
   disso descolaria o liquido da fotografia. */
.pre-nivel {
    animation: preEnche var(--churn) ease-out forwards;
}

@keyframes preEnche {
    0% {
        transform: translateY(2060px);
    }

    88% {
        transform: translateY(300px);
    }

    100% {
        transform: translateY(324px);
    }
}

/* A onda assenta quando o nivel para: sem a mare infinita, a superficie deixa
   de se mexer por baixo da foto cheia, que a essa altura ja tomou a tela. Sao
   duas animacoes infinitas a menos rodando atras de uma imagem opaca. O `from`
   de cada repouso repete o ultimo keyframe da agitacao de proposito - e o que
   torna a troca invisivel. Ver garrafaRepouso* na secao 9.1. */
.pre-garrafa .liq-onda-tras {
    animation: gatilhoEnchendoTras var(--churn) ease-in-out both,
        garrafaRepousoTras 0.7s ease-out var(--churn) both;
}

.pre-garrafa .liq-onda-frente {
    animation: gatilhoEnchendoFrente var(--churn) ease-in-out both,
        garrafaRepousoFrente 0.7s ease-out var(--churn) both;
}

.pre-garrafa .garrafa-cheia {
    animation: garrafaAssenta 0.7s ease-out var(--churn) both;
}

.pre-garrafa .garrafa-vazia {
    animation: garrafaSai 0.7s ease-out var(--churn) both;
}

@keyframes preMarca {
    from {
        opacity: 0;
        transform: translateY(10px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

/* Sem movimento: a garrafa cheia, parada - ou seja, a propria fotografia do
   produto. As bolhas saem de cena porque sem a animacao elas ficariam paradas
   na linha d'agua, como sujeira no vidro. */
@media (prefers-reduced-motion: reduce) {
    .pre-nivel {
        transform: translateY(324px);
    }

    .pre-garrafa .garrafa-cheia {
        opacity: 1;
    }

    .pre-garrafa .garrafa-vazia {
        opacity: 0;
    }

    .pre-nivel,
    .pre-marca,
    .pre-garrafa .liq-balanco,
    .pre-garrafa .liq-onda,
    .pre-garrafa .garrafa-cheia,
    .pre-garrafa .garrafa-vazia {
        animation: none;
    }

    .pre-garrafa .liq-bolha-sobe {
        display: none;
    }
}

.sidebar {
    /* padding-left: 1rem !important; */
}

[class*="sidebar-dark-"] .sidebar a {
    color: #fff;
    font-size: 0.8rem !important;
}

.mouse {
    cursor: pointer;
}

.fa.fa-star {
    color: var(--accent);
}

a {
    color: var(--brand);
}

/* grid / table */
.table-transp-white th {
    background: var(--brand);
    color: #fff;
}


/* grid / table */

/* ==========================================================================
   3. LOGIN E TELAS DE AUTH
   ========================================================================== */
/* A arte cheia (lanternas e telhados) e so das telas de auth e de erro, que
   sao as que usam layouts/app.blade.php - ali o body ja vem com .login-page.
   O painel fica com a versao discreta do token (secao 1), que e fundo de
   trabalho e nao pode competir com os cards. Como o token e herdado, isto
   sozinho troca a arte nos tres consumidores: body::before, .modal-content e
   .preloader. */
body.login-page {
    --page-bg: var(--arte-fundo-login);
}

/* body.login-page e um flex column com align-items:center, entao o #app encolhe
   ate o conteudo (fit-content). Com a caixa em width:auto, a largura passava a
   depender de qual aba estava aberta - a aba do 1o acesso tem um paragrafo
   longo, entao a caixa esticava e a logo, que e uma % dela, crescia junto.
   Largura definida aqui: o layout para de reagir a troca de aba. */
body.login-page #app {
    width: 100%;
}

/* O .login-page do AdminLTE e height:100vh com justify-content:center. Quando o
   conteudo passa da altura da janela, um flex centrado transborda para os DOIS
   lados - e a parte de cima sai ACIMA do inicio do scroll, cortada e
   inalcancavel. Era o que comia a tampa no celular, e nenhuma rolagem
   recuperava.
   A troca: a janela deixa de ser altura fixa (min-height), o alinhamento vai
   para o topo e a centralizacao passa a ser feita pelas margens auto do #app -
   que centram enquanto ha folga e colapsam quando nao ha, deixando o conteudo
   comecar no topo em vez de vazar. */
body.login-page {
    height: auto;
    min-height: 100vh;
    justify-content: flex-start;
}

body.login-page #app {
    margin-top: auto;
    margin-bottom: auto;
}

.login-box {
    width: 600px;
    max-width: calc(100% - 30px);
    margin-left: auto;
    margin-right: auto;
}

/* A tela do termo (auth/termo.blade.php) usa .card-box, nao .login-box: o PDF do
   regulamento pede mais largura que o formulario de login. Sem largura definida
   aqui a caixa ia de ponta a ponta do monitor (o #app e width:100%), e a caixa
   larga demais era metade do problema do regulamento parecer pequeno. */
.card-box {
    width: 1000px;
    max-width: calc(100% - 30px);
    margin-left: auto;
    margin-right: auto;
}

.login-box h1,
.card-box h1 {
    margin-top: 2rem;
    font-size: 1.2rem;
    color: var(--brand);
}

.login-box .brand {
    width: 40%;
    max-width: 240px;
}

.login-box .femsa {
    margin-top: 2.5rem !important;
}

.login-box-msg {
    color: var(--brand);
}

.login-box .nav-tabs {
    border: 0;
}

.login-box .nav-link {
    border: none !important;
}

/* Alerta das telas de auth. Fica fora do card (e fora das abas) porque a
   mensagem renderizada dentro de uma aba inativa nao aparece para quem
   acabou de submeter o formulario. */
.auth-alerta {
    max-width: 600px;
    margin: 0 auto 1rem auto;
}

.auth-alerta .alert {
    margin-bottom: 0.5rem;
    font-size: 0.9rem;
    text-align: left;
}

/* Texto de apoio dentro do card da marca (fundo vermelho, texto branco). */
.auth-ajuda {
    font-size: 0.8rem;
    line-height: 1.35rem;
    color: #fff;
    margin: 0 0 0.75rem 0;
    text-align: left;
}

.auth-requisitos {
    margin-top: -0.25rem;
}

.auth-ajuda-rodape {
    margin-top: 1rem;
}

/* Botao "ver senha": imita o input-group-text para nao brigar com o campo. */
.js-ver-senha {
    border: 1px solid #ced4da;
    border-left: 0;
    background: #e9ecef;
    color: var(--brand);
}

.js-ver-senha:focus {
    box-shadow: none;
}

/* ==========================================================================
   4. UTILITARIOS DE LAYOUT
   ========================================================================== */
table,
.dataTables_wrapper,
.text-black {
    color: var(--text) !important;
}

.content-header h1 {
    font-size: 1.4rem;
    color: var(--brand);
}

.nobackground {
    /* color: #fff !important; */
    background: none !important;
    border: 0 !important;
}

.noboxshadow {
    box-shadow: none !important;
}

.noborder {
    border: 0 !important;
}

.nopad {
    padding: 0 !important;
}

.logomenu {
    margin-top: 10px;
    margin-bottom: 10px;
    margin-left: 8px;
}

#whats {
    display: inline-block;
    position: fixed;
    width: 63px;
    height: 64px;
    right: 70px;
    bottom: 100px;
}

#whats img,
#whats a {
    width: 63px;
    height: 64px;
    display: block;
}

/* ==========================================================================
   5. DASH: KPIs, KNOB E CARDS
   ========================================================================== */
.bg-dash {
    /* color: var(--brand); */
    /* background: #f2f2f2; */
    /* background: linear-gradient(180deg,#730B20 0,#3A0000 67%) !important; */
}

.bg-kpi-bonus {
    background: #f2f2f2;
}

.bg-kpi-relampago {
    background: #fff;
    /* border: 1px solid var(--brand) !important; */
    box-sizing: border-box;
    box-shadow: var(--shadow-brand) !important;

}


.bg-redes {
    background: transparent !important;
}

.brand-link {
    border: none !important;
}

.sidebar-dark-primary .nav-sidebar>.nav-item>.nav-link.active,
.sidebar-light-primary .nav-sidebar>.nav-item>.nav-link.active,
.sidebar-dark-primary .nav-treeview>.nav-item>.nav-link.active,
.sidebar-light-primary .nav-treeview>.nav-item>.nav-link.active {
    color: #fff !important;
    background: var(--brand-active) !important;
    box-shadow: none;
}

.nav-pills .nav-link {
    border-radius: 2rem;
}

/* Titulos de secao do submenu ADMINISTRATIVO (<li class="nav-header">).
   O AdminLTE ja estiliza .nav-header, mas com 0.9rem: maior que os proprios
   itens da sidebar, que a regra de [class*="sidebar-dark-"] .sidebar a poe em
   0.8rem. Aqui ele volta a ser rotulo, e a separacao do item NAO e feita
   apagando a cor: branco lavado sobre o vermelho da marca le como item
   desabilitado, nao como titulo. Quem separa e o --accent (o amarelo da
   campanha, o mesmo das estrelas): outro matiz, entao nao se confunde com o
   texto branco dos itens, e vivo, entao nao parece desligado. O tamanho e o
   caixa-alta espacada fazem o resto. */
.nav-treeview>.nav-header {
    padding: 0.55rem 1rem 0.1rem 1.5rem;
    font-size: 0.58rem;
    font-weight: 800;
    letter-spacing: 0.1em;
    color: var(--accent);
}

.nav-treeview>.nav-header:first-child {
    padding-top: 0.2rem;
}

/* O recorte de quem alcanca a secao, dito no proprio titulo. E nota, nao
   titulo: sai da caixa-alta e perde o peso, para nao competir com ele. */
.nav-header-nota {
    font-size: 0.9em;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: none;
    opacity: 0.75;
}

/* Os itens do submenu vinham com o respiro vertical do AdminLTE (0.5rem),
   calibrado para o texto de 0.9rem dele, nao para os 0.8rem daqui. Com as
   seis secoes acima o submenu passou a estourar a dobra em tela baixa; este
   aperto devolve mais espaco do que os proprios titulos ocupam. */
.nav-treeview>.nav-item>.nav-link {
    padding-top: 0.32rem;
    padding-bottom: 0.32rem;
}

.main-header {
    margin: 0;
    padding: 0;
}

.knob {
    font-size: 18px !important;
    line-height: 18px !important;
    user-select: none;
    /* supported by Chrome and Opera */
    -webkit-user-select: none;
    /* Safari */
    -khtml-user-select: none;
    /* Konqueror HTML */
    -moz-user-select: none;
    /* Firefox */
    -ms-user-select: none;
    /* Internet Explorer/Edge */
}

.bg-dash .knob {
    z-index: 1 !important;
    margin-left: -5.5rem !important;
}

.bg-dash .knob-label {
    font-size: 1.1rem !important;
    /* display: block !important; */
    position: absolute !important;
    top: 2.51rem;
    right: 2.2rem !important;
}

.bg-kpirelampago .knob {
    z-index: 1 !important;
    /* margin-left: -5.5rem !important; */
}

.bg-kpirelampago .knob-label {
    font-size: 1.1rem !important;
    position: absolute !important;
    top: 3.76em;
    right: 39% !important;
}

.knob:focus,
.knob:focus {
    outline: none;
}


/* cards dash */
.card {
    /* border-radius: 0.35rem; */
    border-radius: 10px;
}

.bg-dash .card-title {
    font-size: 0.8rem !important;
    padding-top: 0.3rem;
    color: var(--brand);
    font-weight: 700;
}

.card-header {
    border: 0 !important;
}

/* --------------------------------------------------------------------------
   Resumo no header do card de rede (dash de admin, gerente e executivo, e a
   tela de metas)
   --------------------------------------------------------------------------
   Markup em painel/dash/rede-resumo-head.blade.php, incluido pelo header de
   painel/dash/card-rede.blade.php e pelo de painel/metas.blade.php.

   Esses cards nascem colapsados, entao o header e tudo que se ve de uma rede
   ate alguem abrir. Com so o nome ali, comparar trinta redes era abrir trinta
   cards; os dois numeros que decidem se vale abrir passam a vir junto.

   O header vira flex porque o AdminLTE posiciona .card-title e .card-tools com
   float, e float nao acomoda uma terceira peca. Em contexto flex os floats sao
   ignorados e os tres viram itens da mesma linha.

   O resumo fica sempre na SEGUNDA linha (flex-basis 100%), e nao encaixado
   entre o nome e o botao. Numa col-lg-4 o nome de uma rede real ("SUPERMERCADO
   SAO JOAO LTDA") ja come a linha inteira: tentar caber tudo junto ou cortaria
   o nome com reticencias - e o nome e o que identifica o card - ou deixaria a
   quebra a mercê do tamanho do nome, com cards vizinhos de alturas diferentes.
   Duas linhas sempre custa ~18px por card e e previsivel.
   -------------------------------------------------------------------------- */
.mj-rede-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.15rem 0.5rem;
}

.mj-rede-head .card-title {
    float: none;
    flex: 1 1 auto;
    min-width: 0;
}

.mj-rede-head .card-tools {
    float: none;
    flex: 0 0 auto;
}

.mj-rede-resumo {
    flex: 1 0 100%;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.1rem 0.7rem;
    margin: 0;
    font-size: 0.68rem;
    color: var(--text-muted);
}

/* Verde so ao bater a meta; abaixo disso, neutro. Nao ha vermelho aqui de
   proposito: a meta e mensal e acumula ao longo do mes, entao no dia 10 QUASE
   TODA rede esta abaixo de 100% - pintar isso de vermelho alarmaria o mes
   inteiro e apagaria o unico limiar que significa alguma coisa em qualquer dia.
   A leitura fina (a escala de 4 cores do Functions::getColor) segue nos knobs e
   nas barras dentro do card. */
.mj-rede-chip b {
    font-size: 0.85rem;
    font-weight: 800;
    color: var(--text);
}

.mj-rede-chip.is-ok b {
    color: var(--ok);
}

.borderradius {
    border-radius: 10px;
}

/* Vive DENTRO de .card-body.p-0, nao e mais o proprio card-body.
   Motivo: o slideUp()/slideDown() do AdminLTE anima a altura do .card-body.
   Com min-height ali, a altura usada ficava travada em 300px durante toda a
   animacao e o collapse virava um salto seco no final. Com o min-height aqui,
   o wrapper anima livre e este bloco e clipado pelo overflow:hidden que o
   jQuery aplica. Bonus: background-size deixa de ser reamostrado por frame,
   porque a altura deste elemento nao muda. */
.card-kpi {
    position: relative;
    padding: 0 1.25rem 1.25rem;
    /* antes herdado de .card-body (1.25rem) */
    background-repeat: no-repeat;
    background-position: 1rem 6rem;
    background-size: auto 65%;
    min-height: 300px;
}

.card-kpi .card-title {
    color: var(--brand);
    padding-top: 0.3rem;
    font-size: 0.8rem;
}

.kpi h1,
.kpi h2,
.kpi h3 {
    margin: 0;
    margin-bottom: 0.35rem;
    padding: 0;
}

.kpi h1 {
    font-size: 0.8rem;
    font-weight: 400;
    text-transform: uppercase;
    color: var(--text);
}

.kpi h2 {
    font-size: 1.2rem;
    font-weight: bold;
    /* text-transform: uppercase; */
    color: var(--text);
}

.kpi h3,
.kpi-label {
    font-size: 0.65rem;
    font-weight: 200;
    text-transform: uppercase;
    color: var(--brand);
}

.kpi-label {
    line-height: 1.1rem;
}

.kpi .peso {
    font-size: 0.7rem;
}

.bold-red {
    color: var(--brand);
    font-weight: bold;
}

.bold-green {
    /* color: #00FF55; */
    font-weight: bold;
}

.bold-white {
    color: var(--brand);
    font-weight: bold;
}

.bold-orange {
    /* color: var(--accent); */
    font-weight: bold;
}

.card-danger:not(.card-outline)>.card-header {
    border-top-left-radius: 12px;
    border-top-right-radius: 12px;
}

.bg-card {
    /* background-color: var(--brand); */
    border: 1px solid var(--brand);
    border-radius: 12px;
}


/* ==========================================================================
   6. DASH: RANKING
   ========================================================================== */
.bg-ranking {
    /* background: linear-gradient(180deg,var(--accent) 0,#DA6F7E 67%); */
    background: #fff !important;
    border-radius: 10px;
}

.ranking,
.bg-horizontal {
    /* padding: 1.5rem; */
    padding: 20px;
    margin: 0;
    background: var(--arte-trofeu) no-repeat right bottom !important;
    min-height: 182px;
    /* background-size: contain; */
}

.bg-horizontal {
    /* background-position: 2rem 3.3rem */
}

.ranking h5,
.ranking h1,
.ranking h2 {
    font-size: 0.7rem;
    font-weight: bold;
    /* text-transform: uppercase; */
    color: var(--brand);

    padding: 0;
    margin: 0;
}

.ranking h1 {
    font-size: 3rem;
    /* line-height: 5rem; */
    font-weight: bold;
    margin-bottom: 2rem;
}

.ranking h2 {
    /* font-size: 1.6rem; */
    font-size: 3rem;
    font-weight: 100;
}

.card-ranking {
    /* height: 100%; */
    border-radius: 10px;
    /* background: #740002; */
    background: none !important;
    padding-bottom: 1rem;
}

.card-ranking .card-body {
    border-radius: 10px;
}



.card-ranking .nav-tabs .nav-item.show .nav-link,
.card-ranking .nav-tabs .nav-link.active {
    /* background: linear-gradient(180deg,#DA6F7E 0,var(--accent) 67%) !important; */
    /* background: var(--accent); */
    border: none;
}

.card-ranking:not(.card-outline)>.card-header a.active {
    font-weight: bold !important;
    color: var(--brand);
}

.backdrop-sidebar {
    background: var(--brand);
    /* background: linear-gradient(0deg,var(--brand) 0,var(--brand-dark) 50%) !important; */
    /* background-color: rgba(8, 8, 8, 0.7); */
    /* backdrop-filter: blur(16px) brightness(-13); */
}

/* ==========================================================================
   7. DASH: NOTICIAS E VENDA ACUMULADA
   ========================================================================== */
.font1 {
    font-size: 0.8rem !important;
    line-height: 1.9rem !important;
}

.news dt,
.news dt a {
    color: var(--brand);
    font-size: 1rem;
}

.news dd,
.news dd a {
    font-size: 0.8rem;
    font-weight: 200;
    color: #000;
}

/* No dash a novidade e um resumo: 3 linhas por item para o card nao crescer */
.news-resumo dd {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.vendaacumulado {
    color: var(--brand);
    background: #ececec;
    border-radius: 10px;
    /* background: linear-gradient(180deg,#C73333 0,#391E29 67%) !important; */
}

.vendaacumulado b {
    font-weight: 2rem;
}

.vendaacumulado h1,
.vendaacumulado h2 {
    font-size: 0.8rem;
    /* line-height: 1rem; */
    /* text-transform: uppercase; */
    width: 80%;
    margin-bottom: 2rem;
}

.vendaacumulado h2 {
    margin-bottom: 0rem;
    line-height: 1rem;
}

.vendaacumulado h3 {
    font-size: 1rem;
}

.vendaacumulado h1 {
    margin-top: 30px;
    font-size: 1.2rem;
    font-weight: bold;
    line-height: normal;
}

.vendaacumulado p {
    font-size: 1rem;
    color: var(--accent);
}

/* ==========================================================================
   8. DASH: COMPARATIVOS
   ========================================================================== */
.comparativos {
    padding: 0 !important;
}

.comparativos,
.bg-card-comparativos {
    color: #000;
    background-color: #fff;
    /* padding: 0 !important; */
    /* background: linear-gradient(180deg,#191821 0,#353536 67%) !important; */
}

.comparativos .card-danger:not(.card-outline)>.card-header,
.card-danger:not(.card-outline)>.card-header a {
    color: #000;
}

.card-comparativos .nav-tabs .nav-item.show .nav-link,
.card-comparativos .nav-tabs .nav-link.active {
    background: none !important;
    border: none;
}

.bg-header-comparativos {
    background: #fff !important;
}

.card-comparativos:not(.card-outline)>.card-header {
    color: #E08A8B;
    font-size: 0.8rem;
}

.card-comparativos:not(.card-outline)>.card-header a.active {
    font-weight: bold !important;
    color: #FF5455;
}

.card-comparativos {
    box-shadow: none !important;
}

.small1,
.smallbonus {
    font-size: 0.7rem;
    /* font-weight: bold; */
    padding-bottom: 0.50rem;
}

.small2 {
    font-size: 0.7rem;
}

.smallbonus {
    font-weight: normal;
    text-transform: uppercase;
}

/* ==========================================================================
   9. DASH: GATILHO
   ========================================================================== */
.roundbar {
    border-radius: 6px !important;
    margin-bottom: 0.8rem;
    /* background-color: #e6e9ec; */
    /* background-color: #56606D; */
}

.gatilhobar-horizontal {
    height: 2rem !important;
}

.bgbarhorizontal {
    padding-top: 2rem;
}

.card-outline,
.card-outline .card-header {
    color: #000;
}

/* --------------------------------------------------------------------------
   9.1 Gatilho: a garrafa que enche
   --------------------------------------------------------------------------
   O markup inteiro esta em layouts/garrafa.blade.php, compartilhado com o
   preloader (secao 2.1). Leia o docblock de la antes de mexer aqui: e ele que
   explica o essencial - a garrafa nao e mais um vetor com liquido em
   gradiente, sao DUAS FOTOS da mesma Coca-Cola de vidro. A vazia fica embaixo
   e sempre visivel; a cheia entra por cima, recortada pela linha d'agua. O que
   sobe e a fotografia, nao uma cor.

   Disso vem a regra que explica quase tudo o que mudou nesta secao: contorno,
   tampa, friso e reflexos de vidro nao existem mais em CSS. Eles estao na
   foto. O que sobrou de vetor aqui e so o que a foto nao tem porque se move -
   menisco, espuma, bolhas - e o que e dado: os marcos e o halo.

   O card passa o dado numa unica variavel:

       .card-gatilho { --fill: 0..100 }

   Dentro do clipPath do liquido ha tres transforms ANINHADOS, um por grupo,
   justamente para nao se sobrescreverem (transform nao acumula no mesmo
   elemento):

       .liq-nivel   sobe/desce conforme --fill      <- unica ligada ao dado
         .liq-balanco   respiro vertical lento
           .liq-onda        mare: a superficie incha e assenta, na vertical

   Essas tres classes aparecem DUAS vezes no SVG: uma dentro do clipPath, que
   revela a foto cheia, e outra num grupo irmao, que carrega o menisco, a
   espuma e as bolhas. Nao ha nada em JS sincronizando as duas - sao os mesmos
   keyframes no mesmo relogio do documento, entao sobem coladas.

   Mapa do viewBox (0 0 682 2048, o enquadramento das duas fotos): fundo do
   liquido y=2010, linha d'agua da foto cheia y=324. Logo o curso util e 1686
   unidades. Estes tres numeros tambem estao no Blade (nivel e marcos): mexeu
   num lado, mexa no outro.
   -------------------------------------------------------------------------- */
/* A coluna da garrafa. Centraliza porque a caixa do vidro pode ser mais
   estreita e mais baixa que ela: quem manda no tamanho e a proporcao da foto,
   nao a caixa. */
.graficoGatilho {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 422px;
}

.garrafa {
    width: 100%;
    height: 100%;
}

/* --------------------------------------------------------------------------
   A caixa do vidro e os rotulos de marco.

   O rotulo do marco era <text> dentro do SVG e escalava junto com a garrafa.
   Numa coluna de 62px (o card do dash a 1366) ele saia com 5px - o rotulo
   vermelho da garrafa so tornou visivel um problema que ja existia. Agora ele
   e HTML, com tamanho fixo, e le igual em qualquer largura de card.

   O preco de tirar o texto do SVG e a ancoragem: o rotulo precisa cair na mesma
   altura da linha, que continua sendo vetor. Por isso a caixa tem aspect-ratio
   igual a do viewBox - assim o SVG a preenche sem sobra, e `top: Y%` na caixa e
   o mesmo y/2048 la dentro. Com o preserveAspectRatio sozinho a garrafa fica
   centralizada com folga VARIAVEL conforme a largura, e o rotulo descolaria da
   propria linha.

   A largura sai de um min(), e nao de height + max-width, porque com as duas
   dimensoes definidas o aspect-ratio e IGNORADO: a caixa ficava 422 de altura
   com a largura da coluna, a proporcao se perdia e o rotulo descolava da linha
   em tudo que nao fosse a largura exata do 1920. Aqui a largura e a unica coisa
   definida - ou a coluna inteira, ou o tanto que cabe nos 422px de altura - e a
   altura vem do aspect-ratio. Assim a proporcao vale sempre.
   -------------------------------------------------------------------------- */
.graficoGatilho {
    --garrafa-alt: 422px;
}

.gatilho-vidro {
    position: relative;
    width: min(100%, calc(var(--garrafa-alt) * 682 / 2048));
    height: auto;
    aspect-ratio: 682 / 2048;
}

.gatilho-rotulo {
    position: absolute;
    top: var(--y);
    left: 50%;
    transform: translate(-50%, -100%);
    margin-top: -0.2rem;
    font-size: 0.7rem;
    font-weight: bold;
    font-style: italic;
    letter-spacing: 0.04em;
    line-height: 1;
    white-space: nowrap;
    pointer-events: none;
    color: var(--brand-deep);

    /* Halo, pelo mesmo motivo do paint-order que o texto tinha no SVG: sobre
       foto nenhum fundo e chapado, e o rotulo de 100% mora na altura do
       gargalo, onde vidro claro e cola escura dividem os mesmos 11px. */
    text-shadow: 0 0 3px rgba(255, 255, 255, 0.95), 0 0 3px rgba(255, 255, 255, 0.95);
}

/* Atingido: submerso na cola, inverte para continuar legivel. */
.gatilho-rotulo.is-atingido {
    color: #fff;
    text-shadow: 0 0 3px rgba(45, 10, 5, 0.75), 0 0 3px rgba(45, 10, 5, 0.75);
}

/* As fotos nao precisam de estilo - so nao podem virar alvo de arrasto ou de
   selecao dentro do card. */
.garrafa-foto {
    pointer-events: none;
}

/* A foto cheia inteira, a que troca com a vazia quando a garrafa enche (ver
   .is-cheio, mais abaixo). Enquanto sobe, fica fora - quem mostra o liquido
   ate la e a copia mascarada pela linha d'agua. */
.garrafa-cheia {
    opacity: 0;
}

/* O h1 herda width:80% de .vendaacumulado; aqui a coluna ja e estreita. */
.card-gatilho h1 {
    width: 100%;
}

.liq-nivel {
    transform: translateY(calc(2010px - 1686px * var(--fill) / 100));
    animation: gatilhoEnche 1.9s cubic-bezier(0.22, 1, 0.36, 1) 0.25s both;
}

/* So o from: o to e o transform acima, congelado pelo fill-mode both. */
@keyframes gatilhoEnche {
    from {
        transform: translateY(2060px);
    }
}

/* --churn: quanto dura a agitacao da superficie enquanto o nivel sobe, e
   quando a onda assenta na garrafa cheia. Aqui e o 0.25s de atraso + 1.9s do
   gatilhoEnche; no preloader o enche e outro (1.7s), por isso o valor mora no
   card e nao na regra da onda. */
.card-gatilho {
    --churn: 2.15s;
}

/* --------------------------------------------------------------------------
   Quem dispara a subida e o observador da secao 20, nao o render.

   O motivo esta no comentario do anima.blade.php: aquele observador so comeca
   a olhar DEPOIS que a cortina do preloader cai, exatamente para nao gastar
   animacao atras dela. A subida da garrafa ficava de fora desse acordo -
   comecava no render, e como o preloader so sai 900ms depois do load, numa
   tela lenta a garrafa terminava de encher escondida. A cortina subia e o
   usuario via um bloco vermelho parado.

   O :not(.anima-on) e obrigatorio nos dois seletores. Se o estado vazio valesse
   tambem com o card aceso, o translateY(2060px) daqui venceria por
   especificidade o nivel real la de cima - e como o `to` do gatilhoEnche e
   implicito (sai do transform do elemento), a animacao encheria de 2060 ate
   2060, ou seja, nada.

   Sem JS, sem IntersectionObserver ou com movimento reduzido nao existe
   html.anima-pronta: nada aqui casa, e a garrafa nasce cheia no nivel certo.
   -------------------------------------------------------------------------- */
html.anima-pronta [data-anima~="gatilho"]:not(.anima-on) .liq-nivel {
    transform: translateY(2060px);
    animation: none;
}

/* A agitacao da superficie tem de recomecar junto com o nivel, senao ela roda
   atras da cortina e o liquido sobe com a superficie ja assentada. O gargalo
   da foto cheia entra na mesma conta: ele so pode aparecer no fim da subida.

   As bolhas ficam de fora de proposito: elas moram dentro do .liq-nivel, que
   enquanto vazio esta em 2060px, fora do recorte da garrafa. Nao ha nada para
   esconder, e zerar a animacao delas so as deixaria paradas na linha d'agua. */
html.anima-pronta [data-anima~="gatilho"]:not(.anima-on) .liq-onda-tras,
html.anima-pronta [data-anima~="gatilho"]:not(.anima-on) .liq-onda-frente,
html.anima-pronta [data-anima~="gatilho"]:not(.anima-on) .garrafa-vazia,
html.anima-pronta [data-anima~="gatilho"]:not(.anima-on) .garrafa-cheia {
    animation: none;
}

.liq-balanco {
    animation: gatilhoBalanco 2.9s ease-in-out infinite alternate;
}

@keyframes gatilhoBalanco {
    from {
        transform: translateY(-15px);
    }

    to {
        transform: translateY(15px);
    }
}

/* MARE, nao correnteza: as duas camadas se movem so na VERTICAL, porque o resto
   da peca (o nivel enchendo, o respiro, as bolhas) tambem sobe - uma onda
   correndo de lado era o unico movimento remando contra o desenho.

   O que mantem a superficie viva sem o deslize lateral:

   1. Fase fixa em X. Sem translateX as duas senoides ficariam com as cristas
      eternamente alinhadas, e a de tras viraria um vulto parado. O -85.25px e
      um QUARTO do arco (341 / 4) - meio arco poe a crista de uma bem no vale
      da outra e o topo do liquido fica simetrico demais. Vai no mesmo
      translate() do Y: transform nao acumula.
   2. Periodos que nao fecham entre si (5.2s x 3.7s). Como nao ha divisor
      comum curto, o encontro das duas cristas demora a se repetir e o olho
      nao acha o loop.
   3. Keyframes IRREGULARES, quatro por camada, e nao um sobe-desce simetrico.
      A onda passa por um pico principal e um secundario, em tempos que nao se
      dividem - assim ela nunca fica dois ciclos iguais nem para nos extremos.
   4. Amplitudes diferentes entre as camadas, e a da frente bem maior. E o
      cruzamento das duas em ritmos distintos que muda a SILHUETA da superficie;
      sem isso o desenho apenas sobe e desce inteiro, rigido.

   Historico, porque estes numeros ja foram ajustados duas vezes na direcao
   errada: com 9.5s/6.2s e amplitude baixa a superficie parecia TRAVADA, e
   encurtar so o periodo (4.8s/3.4s) trocou o travado por um TREMOR - movimento
   curto e rapido demais para ler como onda. O que faltava era amplitude junto
   com mudanca de forma. Periodo e amplitude andam juntos aqui: encurtar um sem
   abrir o outro sempre cai num dos dois defeitos.

   As distancias sao ~1,85x as da versao vetorial porque o viewBox cresceu de
   1108 para 2048 de altura ao virar foto - o movimento na TELA e o mesmo.

   A de tras nao pinta mais uma crista opaca: sobre a foto ela e um vulto claro
   e translucido por baixo da superficie (.liq-vulto), recortado pelo liquido.
   Opaca, como era no vetor, ela cobriria a fotografia.

   Sao DUAS animacoes por camada, em sequencia: a agitacao de enchimento e
   depois a mare. Elas nao se somam - as duas escrevem transform, e quem esta
   depois na lista vence enquanto estiver ativa. A mare entra com delay de
   var(--churn) e, sem fill-mode, nao pinta nada durante esse atraso; e por isso
   que a primeira aparece antes e some na hora certa. O ultimo keyframe da
   agitacao repete o 0% da mare de proposito: e o que torna a troca invisivel. */
.liq-onda-tras {
    animation: gatilhoEnchendoTras var(--churn, 2.15s) ease-in-out both,
        gatilhoMareTras 5.2s ease-in-out var(--churn, 2.15s) infinite;
}

.liq-onda-frente {
    animation: gatilhoEnchendoFrente var(--churn, 2.15s) ease-in-out both,
        gatilhoMareFrente 3.7s ease-in-out var(--churn, 2.15s) infinite;
}

/* Enquanto enche a superficie e batida, e as duas camadas vao em sentidos
   opostos: e o cruzamento delas que da a leitura de liquido entrando. A
   amplitude decai a cada passada - a agua se acalma sozinha, e chegar na mare
   com a superficie ja quase parada evita o degrau na troca. */
@keyframes gatilhoEnchendoTras {
    0% {
        transform: translate(-85.25px, -48px);
    }

    30% {
        transform: translate(-85.25px, 41px);
    }

    55% {
        transform: translate(-85.25px, -28px);
    }

    78% {
        transform: translate(-85.25px, 26px);
    }

    100% {
        transform: translate(-85.25px, 22px);
    }
}

@keyframes gatilhoEnchendoFrente {
    0% {
        transform: translateY(63px);
    }

    30% {
        transform: translateY(-52px);
    }

    55% {
        transform: translateY(39px);
    }

    78% {
        transform: translateY(-44px);
    }

    100% {
        transform: translateY(-37px);
    }
}

/* 0% e 100% identicos: o loop fecha sem salto. Os tempos do meio (36/64 e
   28/52/76) sao os que quebram a simetria - ver o item 3 do comentario acima. */
@keyframes gatilhoMareTras {
    0% {
        transform: translate(-85.25px, 22px);
    }

    36% {
        transform: translate(-85.25px, -26px);
    }

    64% {
        transform: translate(-85.25px, 7px);
    }

    100% {
        transform: translate(-85.25px, 22px);
    }
}

@keyframes gatilhoMareFrente {
    0% {
        transform: translateY(-37px);
    }

    28% {
        transform: translateY(26px);
    }

    52% {
        transform: translateY(41px);
    }

    76% {
        transform: translateY(-11px);
    }

    100% {
        transform: translateY(-37px);
    }
}

/* --------------------------------------------------------------------------
   Garrafa cheia: a onda para e a foto assume.

   Enquanto o nivel e um dado parcial, a mare roda para sempre - liquido que
   nao chegou ao fim continua se mexendo. No cheio isso inverte: garrafa cheia
   tem superficie parada, e parada ela pode ser coberta pelo gargalo da propria
   foto cheia, que traz o menisco e as bolhas presas no vidro.

   Por isso a lista de animacoes aqui nao tem a mare: a agitacao entrega direto
   ao repouso, que zera o deslocamento vertical e congela ali (fill-mode both).
   O `from` de cada repouso repete o ultimo keyframe da agitacao, senao haveria
   um salto na troca.

   Junto com isso as duas fotos TROCAM: a vazia sai, a cheia entra. Elas estao
   no mesmo enquadramento, entao a troca em si nao se ve - o que se ve e o
   pescoco parar de ser vidro limpo e virar o menisco de verdade. Sobrepor uma
   na outra em vez de trocar nao serve: o vidro e translucido nas duas, e duas
   camadas de vidro leem como uma mancha leitosa no gargalo.

   O respiro do .liq-balanco continua: ele e o que mantem as bolhas vivas, e
   elas ficam por cima da foto cheia justamente para nao sumirem na troca.
   -------------------------------------------------------------------------- */
.card-gatilho.is-cheio .liq-onda-tras {
    animation: gatilhoEnchendoTras var(--churn) ease-in-out both,
        garrafaRepousoTras 0.7s ease-out var(--churn) both;
}

.card-gatilho.is-cheio .liq-onda-frente {
    animation: gatilhoEnchendoFrente var(--churn) ease-in-out both,
        garrafaRepousoFrente 0.7s ease-out var(--churn) both;
}

.card-gatilho.is-cheio .garrafa-cheia {
    animation: garrafaAssenta 0.7s ease-out var(--churn) both;
}

.card-gatilho.is-cheio .garrafa-vazia {
    animation: garrafaSai 0.7s ease-out var(--churn) both;
}

@keyframes garrafaRepousoTras {
    from {
        transform: translate(-85.25px, 22px);
    }

    to {
        transform: translate(-85.25px, 0);
    }
}

@keyframes garrafaRepousoFrente {
    from {
        transform: translateY(-37px);
    }

    to {
        transform: translateY(0);
    }
}

@keyframes garrafaAssenta {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@keyframes garrafaSai {
    from {
        opacity: 1;
    }

    to {
        opacity: 0;
    }
}

/* --------------------------------------------------------------------------
   A superficie: quatro tracos sobre o MESMO path da onda.

   Contra a foto o menisco nao pode ser branco. O que separa a cola do vidro
   numa garrafa de verdade e uma linha quente, cor de creme, com espuma fina
   por cima e sombra por baixo. Sao quatro tracos do mais largo ao mais fino
   porque a soma deles ja da o degrade da espuma - um unico traco com desfoque
   sairia igual e custaria um filtro rasterizado a cada quadro, com varias
   redes abertas no dash.

   Todos vivem dentro do recorte do vidro, entao morrem na parede da garrafa.
   Na garrafa cheia eles ficam atras do gargalo da foto e somem de cena.
   -------------------------------------------------------------------------- */
.liq-sombra {
    fill: none;
    stroke: rgba(70, 17, 8, 0.30);
    stroke-width: 34;
    transform: translateY(14px);
}

.liq-espuma-larga {
    fill: none;
    stroke: rgba(243, 215, 186, 0.10);
    stroke-width: 30;
}

.liq-espuma {
    fill: none;
    stroke: rgba(248, 226, 199, 0.22);
    stroke-width: 13;
}

.liq-superficie {
    fill: none;
    stroke: rgba(255, 244, 224, 0.55);
    stroke-width: 5;
}

/* O segundo ritmo, submerso. Herdeiro da onda de tras do vetor: la ela era uma
   crista opaca que somava ao corpo do liquido, aqui e um vulto claro passando
   por baixo da superficie - sobre a fotografia, qualquer coisa opaca aqui
   apagaria justamente o que se quer mostrar. */
.liq-vulto {
    fill: none;
    stroke: rgba(255, 255, 255, 0.09);
    stroke-width: 22;
}

/* As bolhas sobem do fundo do liquido ate a linha d'agua. O curso (1400) e
   ~83% do curso util, a mesma proporcao da versao vetorial: bolha que nasce
   colada na superficie nao le como gas subindo. */
.liq-bolha-sobe {
    animation: gatilhoSobe var(--dur) linear var(--atraso) infinite;
}

@keyframes gatilhoSobe {
    from {
        transform: translateY(1400px);
    }

    to {
        transform: translateY(45px);
    }
}

/* Creme, nao branco: contra a foto da cola o branco puro vira ponto de luz de
   plastico. O tamanho vem do Blade (raio 4 a 14 num viewBox de 682). */
.liq-bolha {
    fill: rgba(255, 238, 217, 0.55);
    transform-box: fill-box;
    transform-origin: center;
    animation: gatilhoBolha var(--dur) ease-in var(--atraso) infinite;
}

@keyframes gatilhoBolha {
    0% {
        opacity: 0;
        transform: translateX(0) scale(0.45);
    }

    12% {
        opacity: 0.8;
    }

    50% {
        transform: translateX(17px) scale(1);
    }

    88% {
        opacity: 0.65;
    }

    100% {
        opacity: 0;
        transform: translateX(1px) scale(1.15);
    }
}

/* --------------------------------------------------------------------------
   Marcos: metas parciais e alvo final, em unidades do viewBox (682 de largura).
   O rotulo em 58 da ~12px na largura que a coluna lateral entrega - ficar
   maior que isso nao cabe no gargalo, onde mora o marco de 100%.

   O rotulo destas linhas e HTML (.gatilho-rotulo, mais acima). Aqui fica so o
   traco, que precisa ser vetor para morrer na borda do vidro.

   Os dois estados nunca dividem o mesmo fundo: marco pendente esta, por
   definicao, acima do nivel (vidro vazio) e marco atingido esta submerso (a
   foto da cola). Por isso escuro x branco, e nao uma cor unica de compromisso.
   -------------------------------------------------------------------------- */
.gatilho-marco line {
    stroke: var(--brand-deep);
    stroke-width: 8;
    stroke-dasharray: 26 22;
    opacity: 0.55;
}

.gatilho-marco.is-atingido line {
    stroke: rgba(255, 255, 255, 0.85);
    opacity: 1;
}

.gatilho-aura {
    animation: gatilhoPulsa 2.6s ease-in-out 1.5s infinite;
}

@keyframes gatilhoPulsa {

    0%,
    100% {
        opacity: 0.85;
    }

    50% {
        opacity: 0.35;
    }
}

.gatilho-selo {
    display: inline-block;
    margin-top: 0.25rem;
    padding: 0.3rem 0.7rem;
    border-radius: 999px;
    background: var(--accent);
    color: #5a3800;
    font-size: 0.62rem;
    font-weight: bold;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

@media (prefers-reduced-motion: reduce) {

    .liq-nivel,
    .liq-balanco,
    .liq-onda-tras,
    .liq-onda-frente,
    .liq-bolha-sobe,
    .liq-bolha,
    .gatilho-aura {
        animation: none;
    }

    .liq-bolha {
        opacity: 0.5;
    }
}


.boxGatilho {
    border: 1px solid #fff;
    border-radius: 1rem;
    padding: 1rem;
    margin-bottom: 20px;

}

/* ==========================================================================
   10. DASH: PREMIACAO E RELAMPAGO
   ========================================================================== */
.premiacao {
    padding: 0 !important;
}

.premiacao,
.bg-card-premiacao {
    color: #ffffff;
    padding: 0 !important;
    text-align: center;
    background: linear-gradient(0deg, #192437 0, var(--brand) 67%) !important;
}

.bg-card-premiacao {
    padding: 0.25rem !important;
}

.card-premiacao .nav-tabs .nav-item.show .nav-link,
.card-premiacao .nav-tabs .nav-link.active {
    background: none !important;
    border: none;
}

.card-premiacao .nav-tabs .nav-link {
    border-radius: 0.30rem !important;
}

.bg-header-premiacao {
    background: var(--brand) !important;
}

.card-premiacao:not(.card-outline)>.card-header {
    color: #000;
    font-size: 0.8rem;
}

.card-premiacao:not(.card-outline)>.card-header a.active {
    font-weight: bold !important;
    color: #000;
}


.swiper-button-next:after,
.swiper-rtl .swiper-button-prev:after,
.swiper-button-prev:after,
.swiper-rtl .swiper-button-next:after {
    color: #CB6868;
}

.card-nopad {
    margin-bottom: 0 !important;
    padding-bottom: 0 !important;
    padding-top: 1.5rem !important;
}

.card-premiacao {
    box-shadow: none !important;
}

.card-kpirelampago {
    padding-top: 0.50rem;
    background-repeat: no-repeat;
    background-position: center bottom;
}

.bgrelampago2 {
    background-repeat: no-repeat;
    background-position: center bottom;
    background-size: auto 30%;
    min-height: 495px;
}

.mySwiper {
    min-height: 457px;
}

.bg-kpirelampago {
    background: linear-gradient(0deg, #2D2634 0, #581530 67%) !important;
}

.kpirelampago h1,
.kpirelampago h2,
.kpirelampago h3,
.kpirelampago h4 {
    margin: 0;
    margin-bottom: 0.35rem;
    padding: 0;
}

.kpirelampago h1 {
    font-size: 0.8rem;
    font-weight: 400;
    text-transform: uppercase;
    color: #ffffff;
    margin-bottom: 3rem;
}

.kpirelampago h2 {
    font-size: 1.1rem;
    font-weight: bold;
    text-transform: uppercase;
    color: #ffffff;
}

.kpirelampago h3,
.kpirelampago-label {
    font-size: 0.9rem;
    font-weight: 200;
    text-transform: uppercase;
}

.kpirelampago h4 {
    font-size: 1.1rem;
    font-weight: bold;
    text-transform: uppercase;
    color: #F688A9;
}

.padding-labels {
    padding: 0.9rem 0;
    margin-bottom: 5.5rem;
}

/* ==========================================================================
   11. DASH: LOGINDASH
   ========================================================================== */
.logindash {
    padding: 0 !important;
}

.logindash,
.bg-card-logindash {
    color: #fff;
    /* padding: 0 !important; */
    /* background: linear-gradient(180deg,#191821 0,#353536 67%) !important; */
}

.bg-card-logindash {
    background: var(--brand);
    border-radius: 10px;
}

.card-logindash .nav-tabs {
    padding-left: 25%;
    height: 55px;
}

.card-logindash .nav-tabs .nav-item:nth-child(2) {
    margin-left: 10px;
}

.card-logindash .nav-tabs .nav-item.show .nav-link,
.card-logindash .nav-tabs .nav-link.active,
.card-logindash {
    background: none !important;
    border: none;
}

.bg-header-logindash {
    background: none !important;

}

.card-logindash:not(.card-outline)>.card-header {
    color: var(--brand);
    font-size: 0.7rem;
}

.card-logindash:not(.card-outline)>.card-header a {
    color: var(--brand);
    border: 1px solid var(--brand) !important;
    border-radius: 1rem;
    padding: 5px 20px;
}

.card-logindash:not(.card-outline)>.card-header a.active {
    font-weight: bold !important;
    color: #fff;
    background: var(--brand) !important;
    border-radius: 1rem;
    position: relative;
    /* necessário para a seta */
}

/* seta centralizada */
.card-logindash:not(.card-outline)>.card-header a.active::after {
    content: "";
    position: absolute;
    bottom: -10px;
    /* joga a seta pra fora do botão */
    left: 50%;
    transform: translateX(-50%);
    width: 0;
    height: 0;
    border-left: 10px solid transparent;
    border-right: 10px solid transparent;
    border-top: 10px solid var(--brand);
    /* mesma cor do fundo */
}

.card-logindash {
    box-shadow: none !important;
}

.smallLogin {
    font-size: 0.8rem;
    color: #fff;
    text-align: left;
    margin: 0;
    padding: 0;
}


/* ==========================================================================
   12. BOTOES, TEXTOS E FORMULARIOS
   ========================================================================== */
.icheck-danger>input:first-child:checked+input[type="hidden"]+label::before,
.icheck-danger>input:first-child:checked+label::before {
    background-color: var(--brand);
    color: #fff;
}

.btn-danger {
    background-color: var(--brand);
}

.btn-default {
    background-color: #fff;
    color: var(--brand);
}

.txtFooter {
    margin-top: 1rem;
    color: var(--brand);
    font-weight: 100;
    font-size: 0.75rem;
}

.txtFooter a {
    color: var(--brand);
}

/* O copyright era separado do contato por dois <br> vazios (~40px fixos, que
   nao encolhem na tela pequena). Virou bloco com margem, que a secao 15.1
   reduz no celular. */
.txtFooter-copy {
    display: block;
    margin-top: 2rem;
}

.subtitulo {
    color: var(--brand);
    margin-top: 0.35rem;
    font-size: 0.9rem;
}

.descricao {
    color: #000;
    font-size: 0.8rem;
    width: 80%;
}

/* Selects nativos com o mesmo raio do Select2 (secao 13), para nao ficarem
   dois cantos diferentes lado a lado no mesmo filtro. Prefixar com o elemento
   ja vence o .form-control / .custom-select do Bootstrap, sem !important.
   Cobre tambem o "Mostrar _MENU_ registros" do DataTables, que sai como
   select.custom-select.custom-select-sm.form-control.form-control-sm. */
select.form-control,
select.form-control-sm,
select.custom-select,
select.custom-select-sm {
    border-radius: var(--radius);
}

/* select2 */
.select2-container--bootstrap4 .select2-selection,
/* ==========================================================================
   13. PLUGINS: SELECT2 E FOCO DE CAMPO
   ========================================================================== */
.select2-container--bootstrap4 .select2-selection--multiple .select2-search__field {
    background: none;
    color: var(--brand);
    border-radius: 10px;
}

.select2-container--bootstrap4 .select2-results__option--highlighted,
.select2-container--bootstrap4 .select2-results__option--highlighted.select2-results__option[aria-selected="true"] {
    background: var(--brand);
    color: #fff;
}

.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice,
.select2-container--bootstrap4 .select2-selection--single .select2-selection__rendered {
    color: var(--brand);
}

.select2-search__field::placeholder {
    color: rgb(255, 255, 255);
    opacity: 1;
    /* Firefox */
}

.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b {
    border-color: #FFF transparent transparent transparent;

}

.select2-container--bootstrap4.select2-container--focus .select2-selection {
    border-color: var(--brand);
    border-radius: 10px;
}

/* Aberto, o tema arredonda so o lado livre do par campo+dropdown; o padrao
   dele e 0.25rem e aqui o campo e 10px. */
.select2-container--bootstrap4 .select2-dropdown.select2-dropdown--below {
    border-bottom-right-radius: var(--radius);
    border-bottom-left-radius: var(--radius);
}

.select2-container--bootstrap4 .select2-dropdown.select2-dropdown--above {
    border-top-left-radius: var(--radius);
    border-top-right-radius: var(--radius);
}

/* Foco da marca nos campos (o AdminLTE deixa azul do Bootstrap).
   Sem !important: mesma especificidade do AdminLTE e este arquivo carrega
   depois dele nos dois head.blade.php. */
.form-control:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 0.2rem rgba(var(--brand-rgb), 0.25);
}



/* ==========================================================================
   14. CONTEUDO: PREMIOS, TERMO, PDF E LINKS
   ========================================================================== */
.subG {
    font-size: 1.4rem;
}

.subX {
    font-size: 1.2rem;
    font-weight: bold;
}

.white {
    color: #ffffff;
}

.h-premios {
    background: #fff !important;
    min-height: 470px;
}

.h-premios ul li {
    padding: 2px;
}

/* Os quatro meses lado a lado, terminando na mesma linha.
   O .row do Bootstrap ja da a mesma altura as colunas (align-items: stretch);
   o que faltava era o card esticar dentro da coluna e a lista de premios
   crescer para ocupar a sobra. Sem isso o bloco branco de cada mes para onde
   o texto daquele mes acaba, e dezembro (lista mais longa) desalinha os
   outros tres. Nao da para resolver so com o min-height do .h-premios: ele e
   um piso, nao um teto. */
.premios-mes {
    display: flex;
}

.premios-mes>.card {
    width: 100%;
}

.premios-mes .card-body {
    display: flex;
    flex-direction: column;
}

.premios-mes .h-premios {
    flex: 1 1 auto;
}

/* Premios do mes agrupados por categoria (LIFESTYLE, TECNOLOGIA, +JUNTOS,
   EDUCACAO). O rotulo e um <b> dentro do proprio <li>: vira linha propria,
   para o nome do premio nao emendar na categoria. */
.premios-categorias li + li {
    margin-top: 0.5rem;
}

.premios-categorias li b {
    display: block;
    color: var(--brand);
    font-size: 0.75rem;
    letter-spacing: 0.05em;
}

/* Marca dos premios personalizados (+JUNTOS): a foto do catalogo nao tem a
   arte da marca aplicada, entao cada item personalizado leva um asterisco e a
   legenda .nota-ilustra-legenda explica - na pagina de premios uma vez, abaixo
   dos quatro meses; no card do dash dentro do proprio slide do Swiper, que so
   mostra um premio por vez. O asterisco do cabecalho da pagina de premios
   (grupos) fica em outro bloco, longe destes.
   Sem cor propria de proposito: a legenda aparece tanto no card branco da
   pagina quanto sobre o gradiente vermelho do .bg-card-premiacao, onde o
   texto e branco - qualquer cor fixa sumiria em um dos dois. */
.nota-ilustra {
    font-weight: bold;
    margin-left: 2px;
}

.nota-ilustra-legenda {
    display: block;
    font-size: 0.75rem;
    font-style: italic;
    margin-top: 0.5rem;
    opacity: 0.85;
}

.bgcolor {
    /* background-color: #BF0D0D; */
    min-height: 470px
}

.bgcolor ul li {
    padding: 5px;

}

.descricaoT {
    font-size: 1rem;
    font-weight: 200;
}

.m10 {
    margin: 10px 0;
}

.ml20 {
    margin-left: 20px;
}

.linkblank {
    color: var(--brand) !important;
    text-decoration: underline;
}

.linkblank:hover,
.linkblank:active,
.linkblank:active {
    color: var(--brand) !important;
    font-weight: bold;
}

/* .os-content-glue, .sidebar,  { */
.sidebar-dark-primary {
    /* background-color: transparent !important; */
    /* background-color: rgba(0, 0, 0, 0.2) !important; */
}

.sidebar-collapse .sidebar-dark-primary {
    /* background-color: transparent !important; */
    /* background-color: rgba(78, 13, 13, 1) !important; */
}

.sidebar-collapse .sidebar-dark-primary:hover,
.sidebar-collapse .sidebar-dark-primary:active {
    background-color: var(--brand);
    /* background-color: rgba(0, 0, 0, 0.8) !important; */
}

.pdfview {
    width: 100%;
    height: 100%;
}

/* Visualizador do Adobe na tela do termo. Altura em vh porque a caixa fixa de
   500px ficava baixa em monitor grande; o teto evita estourar o viewport em tela
   alta e o piso mantem leitura no celular. */
.pdfview-termo {
    width: 100%;
    height: min(78vh, 900px);
    min-height: 420px;
}

.labelpdf {
    font-size: 0.8rem;
    word-break: break-word;
    font-weight: normal;
    /* O texto do aceite fica FORA do card vermelho, mas herdava o color:#fff do
       .logindash (resto do tema escuro antigo). Na arte clara de 2026 ele sumia
       no fundo. */
    color: var(--brand-deep);
}

.termo {
    width: 80% !important;
    max-width: none !important;
}

.pad5 {
    padding: 0.5rem 2rem;
}

/* --------------------------------------------------------------------------
   14.1 Texto escrito no editor rico do painel
   --------------------------------------------------------------------------
   Duas telas consomem: o detalhe da novidade e o modal de aviso do dash. O que
   o admin escolheu no Summernote (negrito, tamanho, cor) viaja em style inline
   e nao passa por aqui - estas regras so dao ritmo ao bloco e seguram os
   extremos: titulo de dentro do texto nao pode competir com o titulo da peca,
   e imagem ou tabela coladas nao podem estourar a coluna. */
.texto-rico {
    font-size: 0.9rem;
    line-height: 1.6;
    color: #000;
}

.texto-rico p {
    margin-bottom: 0.8rem;
}

.texto-rico p:last-child {
    margin-bottom: 0;
}

.texto-rico h1,
.texto-rico h2,
.texto-rico h3,
.texto-rico h4,
.texto-rico h5 {
    color: var(--brand);
    font-size: 1rem;
    font-weight: 700;
    margin: 1.2rem 0 0.5rem;
}

.texto-rico ul,
.texto-rico ol {
    padding-left: 1.4rem;
    margin-bottom: 0.8rem;
}

.texto-rico blockquote {
    border-left: 3px solid var(--brand);
    padding-left: 0.8rem;
    margin: 1rem 0;
    color: #444;
}

.texto-rico a {
    color: var(--brand);
    text-decoration: underline;
}

.texto-rico img,
.texto-rico table {
    max-width: 100%;
}

/* No modal do aviso o primeiro paragrafo nao pode encostar no cabecalho. */
.modal-body .texto-rico {
    margin-bottom: 0.5rem;
}

/* Miolo do editor no painel: herdava o fundo da tela e ficava sem contraste
   com o texto preto que o Summernote grava. */
.note-editor.note-frame .note-editable {
    background: #fff;
    color: #000;
}

/* ==========================================================================
   15. AJUSTES POR BREAKPOINT (@supports e @media)
   ========================================================================== */
@supports (-webkit-backdrop-filter: none) or (backdrop-filter: none) {


    .logindash,
    .bg-card-logindash {
        -webkit-backdrop-filter: blur(30px) brightness(-7);
        backdrop-filter: blur(16px) brightness(-7);
    }
}

/* slightly transparent fallback for Firefox (not supporting backdrop-filter) */
@supports not ((-webkit-backdrop-filter: none) or (backdrop-filter: none)) {}


@media (max-width: 992px) {

    /* O cover que ficava aqui virou regra unica na secao 2 (body::before):
       o enquadramento agora e o mesmo em toda largura, e o preloader e o modal
       - que este override nao alcancava - deixam de destoar no celular. */

    .brand-link {
        display: none !important
    }

    .backdrop-sidebar,
    .sidebar-dark-primary {
        /* background-color: rgba(0, 0, 0, 0.9) !important; */
        background: linear-gradient(0deg, var(--brand) 0, var(--brand-dark) 50%) !important;
    }
}

@media (max-width: 428px) {
    .bg-horizontal {
        background: none !important;
    }

    .ranking {
        background-size: 30% !important;
    }

    /* Era width:320px fixo, e ai a caixa nao acompanhava a tela: num aparelho de
       390px sobravam 35px de folga de cada lado enquanto o formulario dentro
       ficava com 296px. O max-width:calc(100% - 30px) da secao 3 ja e largura
       estavel (nao depende de qual aba esta aberta, que era o motivo de existir
       uma largura declarada aqui) e deixa a caixa crescer com o aparelho. */
    .login-box {
        width: 100%;
    }

    .card-logindash .nav-tabs {
        padding-left: 6%;
    }

    /* Termo no celular: a moldura vermelha (1.25rem do card-body) mais o respiro
       da coluna e do .pad5 comiam uns 70px dos ~390px de tela, e o Adobe em
       FIT_WIDTH desenhava o regulamento em ~270px. Estreitando o respiro so
       aqui, o documento recupera a largura. O escopo em .card-box existe porque
       .bg-card-logindash e .pad5 tambem servem login, reset e formularios. */
    .card-box .bg-card-logindash {
        padding: 0.5rem;
    }

    .card-box .pad5 {
        padding: 0.5rem 0.75rem;
    }

    .pdfview-termo {
        height: 68vh;
        min-height: 300px;
    }

    #whats {
        display: inline-block;
        position: fixed;
        width: 43px;
        height: 34px;
        right: 10px;
        bottom: 100px;
    }

    #whats img,
    #whats a {
        width: 43px;
        height: 44px;
        display: block;
    }

    .card-kpi {
        padding-top: 0rem;
        background-size: auto 55%;
    }

    .kpi h3,
    .kpi-label {
        font-size: 0.6rem;
    }

    .col-6.col-sm-12.col-md-6.kpi-label.text-left {
        margin: 0 !important;
        padding: 0 !important;
        text-align: right !important;
    }
}

/* Celular deitado: a consulta de largura acima nao pega (a tela tem 800px+ de
   largura), e ali 68vh/78vh dao ~280px - o piso de altura do visualizador e que
   passava a mandar, estourando a tela. Por isso este corte e por ALTURA. */
@media (max-height: 500px) {
    .pdfview-termo {
        height: 78vh;
        min-height: 240px;
    }
}

/* --------------------------------------------------------------------------
   15.1 Telas de auth no celular: tudo na tela, sem rolagem
   --------------------------------------------------------------------------
   O body.login-page e um flex centrado verticalmente: quando o conteudo passa
   da altura da janela, ele nao "comeca do topo e desce" - ele transborda para
   os DOIS lados, e a parte de cima (a tampa) fica acima do scroll, cortada e
   inalcancavel. Por isso o problema aparecia como logo cortada, e nao como
   rolagem comum.

   A conta e de altura, entao o que encolhe aqui e o que so ocupa espaco: a
   tampa (que passa a ser limitada por vh, nao por % da caixa), os respiros
   entre titulo, card e rodape, e o padding do card. O formulario em si -
   campos, botao e textos de ajuda - fica do mesmo tamanho: e o que a pessoa
   precisa tocar e ler.

   O corte e em 767.98px (abaixo do md do Bootstrap) e nao nos 428px do bloco
   acima porque celular grande (430x932) tambem estourava. O escopo em
   .login-box preserva o termo (.card-box), que tem regra propria. */
@media (max-width: 767.98px) {
    body.login-page main {
        padding-top: 0.5rem !important;
        padding-bottom: 0.5rem !important;
    }

    /* Limitada pela ALTURA da janela: a largura em % fazia a tampa crescer em
       celular grande justamente onde ja faltava altura. */
    .login-box .brand {
        width: auto;
        max-width: 62%;
        max-height: 130px;
    }

    /* <br> solto depois do titulo (esta no Blade de login, reset e email).
       No celular o respiro dele vira a margem do proprio h1, abaixo. */
    .login-box .text-center>br {
        display: none;
    }

    .login-box h1 {
        margin-top: 0.75rem;
        margin-bottom: 0.75rem;
        font-size: 1.05rem;
    }

    .login-box .card-logindash .nav-tabs {
        height: 46px;
    }

    .login-box .bg-card-logindash {
        padding: 1rem;
    }

    /* O card interno de cada aba (auth.access, auth.firstaccess) so existe para
       agrupar o form: o respiro dele duplica o do card vermelho de fora. */
    .login-box .bg-card-logindash .card-body {
        padding: 0;
    }

    .auth-ajuda {
        font-size: 0.75rem;
        line-height: 1.15rem;
        margin-bottom: 0.5rem;
    }

    .auth-alerta {
        margin-bottom: 0.5rem;
    }

    .auth-alerta .alert {
        padding: 0.45rem 0.65rem;
        margin-bottom: 0.35rem;
        font-size: 0.78rem;
    }

    .login-box .femsa {
        margin-top: 1rem !important;
        width: auto;
        max-height: 56px;
    }

    .login-box .txtFooter {
        margin-top: 0.5rem;
        font-size: 0.7rem;
    }

    .login-box .txtFooter-copy {
        margin-top: 0.6rem;
    }
}

/* Celular de tela curta (o iPhone SE/8 com a barra de endereco aberta tem
   ~553px uteis, o Android ~600px). O bloco acima ja cabia nos ~660px de um
   celular atual; aqui a conta e apertada de novo, e por isso a tampa perde
   mais um tanto e o respiro entre os campos encolhe. O corte de 700px e a
   altura em que o conteudo do bloco anterior ainda cabe com folga. */
@media (max-width: 767.98px) and (max-height: 700px) {
    .login-box .brand {
        max-height: 76px;
    }

    .login-box h1 {
        margin-top: 0.4rem;
        margin-bottom: 0.4rem;
        font-size: 1rem;
    }

    .login-box .card-logindash .nav-tabs {
        height: 42px;
    }

    .login-box .bg-card-logindash {
        padding: 0.85rem;
    }

    /* O mb-3 do Blade (16px) e o mesmo em toda a aplicacao; so aqui ele e espaco
       que falta. Os campos em si nao mudam de tamanho. */
    .login-box .input-group.mb-3 {
        margin-bottom: 0.75rem !important;
    }

    .login-box .femsa {
        margin-top: 0.5rem !important;
        max-height: 44px;
    }

    .login-box .txtFooter {
        margin-top: 0.35rem;
        font-size: 0.65rem;
    }

    .login-box .txtFooter-copy {
        margin-top: 0.35rem;
    }
}

/* Erro de login no celular: o alerta entra ACIMA do card e e altura que nao
   existia na conta dos dois blocos anteriores. Em vez de deixar a tela rolar
   justamente na hora em que a pessoa precisa ler a mensagem e corrigir o campo,
   a tampa cede o espaco - ela e o unico elemento ali que so decora.
   O :has() e progressivo de proposito: onde ele nao existir, a tela apenas
   volta a rolar um pouco no estado de erro, que era o comportamento anterior. */
@supports selector(:has(*)) {
    @media (max-width: 767.98px) {
        body.login-page:has(.auth-alerta) .login-box .brand {
            max-height: 84px;
        }
    }

    /* Mesma troca no notebook de tela baixa, onde a tampa e maior e portanto tem
       mais a ceder. Aqui o alerta tambem fica compacto: com a caixa em 600px a
       mensagem cabe em menos linhas e nao precisa do corpo cheio. */
    @media (min-width: 768px) and (max-height: 920px) {
        body.login-page:has(.auth-alerta) .login-box .brand {
            max-height: 100px;
        }

        body.login-page:has(.auth-alerta) .auth-alerta {
            margin-bottom: 0.6rem;
        }

        body.login-page:has(.auth-alerta) .auth-alerta .alert {
            padding: 0.5rem 0.75rem;
            margin-bottom: 0.4rem;
        }
    }

    @media (min-width: 768px) and (max-height: 800px) {
        body.login-page:has(.auth-alerta) .login-box .brand {
            max-height: 58px;
        }
    }

    @media (max-width: 767.98px) and (max-height: 700px) {
        body.login-page:has(.auth-alerta) .login-box .brand {
            max-height: 46px;
        }

        /* Na tela curta a tampa sozinha nao paga o alerta: aqui o respiro
           interno tambem volta ao minimo, e so enquanto a mensagem existe. */
        body.login-page:has(.auth-alerta) .login-box .bg-card-logindash {
            padding: 0.6rem;
        }

        body.login-page:has(.auth-alerta) .login-box .input-group.mb-3 {
            margin-bottom: 0.5rem !important;
        }

        /* Duas mensagens ao mesmo tempo na tela mais curta: o unico bloco que
           ainda da para sair e o texto generico de ajuda, e ele nem faz falta
           aqui - a propria mensagem de erro de senha manda a pessoa para a aba
           do 1o acesso. O seletor pede .alert + .alert de proposito: com uma
           mensagem so, o texto de ajuda fica. */
        body.login-page:has(.auth-alerta .alert + .alert) .auth-ajuda {
            display: none;
        }
    }
}

/* Notebook de tela baixa (1440x900, 1366x768): a mesma conta dos blocos de
   celular, com outro culpado - aqui a caixa tem os 600px de largura, entao a
   tampa vai aos 240px e o login sozinho passa dos 900px de altura. Nao e o
   layout que muda, so a tampa e o respiro do <main>. */
@media (min-width: 768px) and (max-height: 920px) {
    body.login-page main {
        padding-top: 0.75rem !important;
        padding-bottom: 0.75rem !important;
    }

    .login-box .brand {
        width: auto;
        max-width: 40%;
        max-height: 175px;
    }

    .login-box h1 {
        margin-top: 1rem;
    }

    .login-box .femsa {
        margin-top: 1.25rem !important;
    }
}

/* Notebook de 768px ou 720px de altura (1366x768, 1280x720). Segundo degrau
   da regra acima: aqui nem a tampa de 175px cabe, e o respiro entre titulo,
   card e rodape tambem tem de ceder. Os campos e o botao continuam do tamanho
   que estao - e o mesmo criterio dos blocos de celular. */
@media (min-width: 768px) and (max-height: 800px) {
    .login-box .brand {
        max-height: 110px;
    }

    /* <br> solto depois do titulo, mesmo caso da secao 15.1. */
    .login-box .text-center>br {
        display: none;
    }

    .login-box h1 {
        margin-top: 0.5rem;
        margin-bottom: 0.5rem;
    }

    .login-box .femsa {
        margin-top: 0.75rem !important;
    }

    .login-box .txtFooter {
        margin-top: 0.5rem;
    }

    .login-box .txtFooter-copy {
        margin-top: 0.75rem;
    }
}

/* Grade de KPIs em duas colunas entre 1200px e 1720px.
   Os cards de KPI tem knob, imagem e tres linhas de numero: em tres colunas
   eles so respiram numa tela bem larga, por isso abaixo de 1720px caem para
   duas. A regra vale SO para a grade de KPIs (o [data-anima="lista"] do dash e
   do metas), e nao para todo .col-xl-4 da aplicacao: quando era global, ela
   engordava tambem a coluna da posicao no bloco de topo, que e col-xl-4 ao
   lado de um col-xl-8. Somando 50% + 66,6% a linha estourava e o grafico de
   evolucao caia para baixo do scoreboard em qualquer tela menor que 1720px.

   O piso de 1200px (o proprio col-xl) e obrigatorio: sem ele a regra tambem
   pegava celular, e como o seletor de atributo vence o .col-12 do Blade, os
   cards ficavam em duas colunas esmagadas na tela pequena. Abaixo de xl quem
   manda sao as classes da coluna (col-12 no celular, col-sm-6 acima de 576). */
@media screen and (min-width: 1200px) and (max-width: 1720px) {
    [data-anima="lista"]>.col-xl-4 {
        flex: 0 0 50%;
        max-width: 50%;
    }
}

/* A garrafa do gatilho e limitada pela LARGURA da coluna dela, nunca pelos
   422px de altura: com o card em col-xl-3 ela fica com um terco de 255 a 394px.
   Dai o 8/4 do Blade virar 7/5 quando ha largura para isso - a garrafa cresce
   ~30% (139px no lugar de 108, a 1920) e o texto continua respirando.

   O corte e em 1500px, e nao no col-xl (1200), porque o limite nao e a tela e
   sim a largura do CARD: abaixo de ~290px de card o texto comeca a quebrar
   palavra no meio ("Volume alcançad/o") na coluna de 7. A 1500px o card tem
   ~290px, e e por isso que o numero e este.

   Nao dava para resolver so aqui: o rotulo do marco e HTML de tamanho fixo
   (.gatilho-rotulo, secao 9.1) justamente porque a 1366 nem 7/5 salva a
   legibilidade - la a garrafa fica com 62px e qualquer texto que escale com ela
   sai ilegivel. Esta regra melhora a garrafa; quem garante o rotulo e a de la. */
@media screen and (min-width: 1500px) {
    .card-gatilho>.row>.col-8 {
        flex: 0 0 58.333333%;
        max-width: 58.333333%;
    }

    .card-gatilho>.row>.col-4 {
        flex: 0 0 41.666667%;
        max-width: 41.666667%;
    }
}

/* ==========================================================================
   16. UTILITARIOS DIVERSOS
   ========================================================================== */
.img-fluid {
    /* margin-top: 50px; */
}

.gridUser {
    text-align: center;
    margin-right: 5px;
    margin-top: 5px;
}

.gridUser div>p {
    margin: 0;
    padding: 0;
    font-size: 0.8rem;
}

.btn-ir {
    font-size: 0.9rem;
}


.bg-success {
    background-color: var(--brand) !important;
}


.embed-container {
    position: relative;
    padding-bottom: 56.25%;
    height: 0;
    overflow: hidden;
    max-width: 100%;
}

.embed-container iframe,
.embed-container object,
.embed-container embed {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}


.minimenuheader {
    position: absolute;
    right: 0;
}

.smalltitle {
    font-size: 11px !important;
}

.invalid-feedback {
    color: #620901 !important;
}

.mB10 {
    margin-bottom: 15px;
}

/* ==========================================================================
   16.1 O "?" DE AJUDA
   --------------------------------------------------------------------------
   Explica um numero da tela sem ocupar linha de texto: o balao e o .mj-tip da
   secao 19.2, disparado pelo painel.dash.tip. Nasceu no ranking, onde "% da
   meta" nao dizia de que periodo era.

   E <button> de verdade (foco e teclado), entao aqui reseta a aparencia de
   botao do Bootstrap: sem fundo, sem padding e sem o letter-spacing herdado do
   cabecalho em caixa alta, que empurrava o "?" para fora do circulo.
   ========================================================================== */
.mj-ajuda {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.05rem;
    height: 1.05rem;
    padding: 0;
    margin-left: 0.2rem;
    border: 1px solid var(--border);
    border-radius: 50%;
    background: transparent;
    color: var(--text-muted);
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0;
    line-height: 1;
    vertical-align: middle;
    cursor: help;
    transition: color 0.15s, border-color 0.15s;
}

.mj-ajuda:hover,
.mj-ajuda:focus-visible {
    border-color: var(--brand);
    color: var(--brand);
    outline: none;
}

.mj-ajuda:focus-visible {
    box-shadow: 0 0 0 2px rgba(var(--brand-rgb), 0.25);
}

/* sobre o cabecalho escuro da tabela (apuracao da premiacao), onde o cinza do
   texto secundario e a borda clara desaparecem */
.thead-dark .mj-ajuda {
    border-color: rgba(255, 255, 255, 0.55);
    color: #fff;
}

.thead-dark .mj-ajuda:hover,
.thead-dark .mj-ajuda:focus-visible {
    border-color: var(--accent);
    color: var(--accent);
}

/* ==========================================================================
   17. LISTAGENS: TABELA NO DESKTOP, CARDS NO MOBILE
   --------------------------------------------------------------------------
   Uso na view:
     <table class="table ... mj-cards">        -> ativa os cards em < 768px
       <td class="mj-card-actions">            -> vai para o canto sup. direito
       <td class="mj-card-title">              -> titulo do card (sem rotulo)
       <td class="mj-card-sub">                -> subtitulo (sem rotulo)
       <td data-label="Fone">                  -> linha "rotulo -> valor"

   As celulas rotuladas seguem a ordem das colunas (itens flex de mesmo
   `order` mantem a ordem do DOM), entao nao precisa classe por coluna.

   Requisitos: o DataTable precisa de "responsive": false, senao o plugin
   Responsive move as celulas para child rows e desmonta o card. Para nao
   perder a leitura no desktop, envolva a tabela em .mj-table-scroll depois
   do init (ver painel/usuarios/index).

   Cores vem dos tokens da secao 1 (--surface, --border, --divider,
   --text-muted, --radius, --shadow-card).
   ========================================================================== */
@media (min-width: 768px) {
    .mj-table-scroll {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
}

@media (max-width: 767.98px) {

    .mj-cards thead,
    .mj-cards tfoot {
        display: none;
    }

    .mj-cards,
    .mj-cards tbody,
    .mj-cards tbody tr,
    .mj-cards tbody td {
        display: block;
        width: 100%;
    }

    .mj-cards {
        border: 0;
    }

    /* Cada registro e um card. O :nth-of-type vence o .table-striped */
    .mj-cards tbody tr,
    .mj-cards.table-striped tbody tr:nth-of-type(odd) {
        position: relative;
        display: flex;
        flex-direction: column;
        background-color: var(--surface);
        border: 1px solid var(--border);
        border-radius: var(--radius);
        box-shadow: var(--shadow-card);
        padding: 0.75rem;
        margin-bottom: 0.75rem;
    }

    /* .sorting_1 e a coluna ordenada, que o DataTables pinta de cinza */
    .mj-cards tbody td,
    .mj-cards tbody td.sorting_1 {
        background-color: transparent;
        border: 0;
        padding: 0.35rem 0;
        white-space: normal;
        word-break: break-word;
    }

    .mj-cards tbody td[data-label] {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: 0.75rem;
        border-top: 1px solid var(--divider);
        font-size: 0.875rem;
    }

    .mj-cards tbody td[data-label]::before {
        content: attr(data-label);
        flex: 0 0 auto;
        font-weight: 600;
        color: var(--text-muted);
    }

    /* Cabecalho do card: o padding a direita reserva espaco para as acoes */
    .mj-cards tbody td.mj-card-title {
        order: -2;
        padding: 0 2.5rem 0.15rem 0;
        font-size: 1rem;
        font-weight: 700;
        line-height: 1.3;
        color: var(--text);
    }

    .mj-cards tbody td.mj-card-sub {
        order: -1;
        padding: 0 2.5rem 0.35rem 0;
        font-size: 0.8125rem;
        color: var(--text-muted);
    }

    .mj-cards tbody td.mj-card-actions {
        position: absolute;
        top: 0.5rem;
        right: 0.5rem;
        width: auto;
        padding: 0;
    }

    /* ----------------------------------------------------------------------
       Paginacao do DataTables no mobile (vale para qualquer listagem, nao so
       as .mj-cards). O dataTables.bootstrap4.css usa white-space: nowrap no
       .dataTables_paginate e na ul.pagination, entao com muitas paginas
       ("Anterior 1 2 3 4 5 ... 36 Proximo") a barra estoura a largura da tela
       sem poder quebrar linha. Aqui a barra quebra em pills centralizadas.
       Os seletores repetem o `div.` do plugin de proposito: o dele e
       (0,3,3) e venceria por especificidade, mesmo este arquivo vindo depois.
       ---------------------------------------------------------------------- */
    div.dataTables_wrapper div.dataTables_paginate,
    div.dataTables_wrapper div.dataTables_paginate ul.pagination {
        white-space: normal;
    }

    div.dataTables_wrapper div.dataTables_paginate ul.pagination {
        flex-wrap: wrap;
        justify-content: center;
        margin: 0;
    }

    div.dataTables_wrapper div.dataTables_paginate .page-item {
        margin: 2px;
    }

    div.dataTables_wrapper div.dataTables_paginate .page-link {
        margin-left: 0;
        /* anula o -1px que junta as bordas na barra */
        padding: 0.35rem 0.6rem;
        font-size: 0.8125rem;
        border-radius: var(--radius-sm);
    }
}

/* --------------------------------------------------------------------------
   Cor da paginacao (Anterior 1 2 3 Proximo). O Bootstrap 4 pinta os links de
   azul (#007bff); aqui trocamos pelo vermelho escuro do tema. Vale para o
   DataTables e para o paginate padrao do Laravel. Sem !important: estes
   seletores igualam a especificidade do Bootstrap e este arquivo vem depois.
   -------------------------------------------------------------------------- */
.page-link {
    color: var(--brand-dark);
}

.page-link:hover {
    color: #fff;
    background-color: var(--brand-dark);
    border-color: var(--brand-dark);
}

.page-link:focus {
    box-shadow: 0 0 0 0.2rem rgba(176, 0, 6, 0.25);
}

.page-item.active .page-link {
    color: #fff;
    background-color: var(--brand-dark);
    border-color: var(--brand-dark);
}

/* ==========================================================================
   18. AJUSTE DE METAS: GRADE DE KPIS POR MES
   --------------------------------------------------------------------------
   Tela painel/ajuste-metas: tabela com um input por mes. No desktop e uma
   tabela normal; no mobile cada KPI vira card (mesma ideia da secao 17, mas
   com inputs no lugar de texto). Os campos alterados ganham destaque amarelo
   ate salvar. Cores vem dos tokens da secao 1.
   ========================================================================== */

/* Remove as setinhas do input numerico (o campo e type=text, mas fica a
   prova de mudanca futura para type=number) */
.input-meta::-webkit-outer-spin-button,
.input-meta::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.input-meta {
    -moz-appearance: textfield;
}

/* Campo com valor diferente do original: destaque ate salvar */
.input-meta.meta-alterada {
    background-color: #fff3cd;
    border-color: var(--accent);
}

@media (max-width: 767.98px) {
    .metas-table thead {
        display: none;
    }

    .metas-table,
    .metas-table tbody,
    .metas-table tbody tr,
    .metas-table tbody td {
        display: block;
        width: 100%;
    }

    .metas-table {
        border: 0;
    }

    /* Cada KPI e um card. O :nth-of-type vence o .table-striped */
    .metas-table tbody tr,
    .metas-table.table-striped tbody tr:nth-of-type(odd) {
        position: relative;
        display: flex;
        flex-direction: column;
        background-color: var(--surface);
        border: 1px solid var(--border);
        border-radius: var(--radius);
        box-shadow: var(--shadow-card);
        padding: 0.75rem;
        margin-bottom: 0.75rem;
    }

    .metas-table tbody td {
        background-color: transparent;
        border: 0;
        padding: 0.35rem 0;
    }

    /* Nome do KPI: titulo do card */
    .metas-table tbody td.td-kpi-nome {
        order: -2;
        font-size: 1rem;
        font-weight: 700;
        padding-bottom: 0.15rem;
    }

    /* Badge do tipo: logo abaixo do titulo */
    .metas-table tbody td.td-kpi-tipo {
        order: -1;
        padding-bottom: 0.5rem;
    }

    /* Linhas de mes: rotulo -> input */
    .metas-table tbody td[data-label] {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 0.75rem;
        border-top: 1px solid var(--divider);
        padding: 0.5rem 0;
    }

    .metas-table tbody td[data-label]::before {
        content: attr(data-label);
        flex: 0 0 auto;
        font-weight: 600;
        color: var(--text-muted);
        font-size: 0.875rem;
    }

    .metas-table tbody td[data-label] .input-meta {
        max-width: 180px;
    }
}

/* --------------------------------------------------------------------------
   18.1 A linha do gatilho
   --------------------------------------------------------------------------
   O gatilho fica na mesma grade dos KPIs, mas nao e um deles: e outra tabela no
   banco (`gatilho`) e alimenta os marcos da garrafa do dash. O filete da marca e
   o fundo mais quente existem para separar as duas coisas sem tirar a linha da
   tabela - fora dela, ela perderia o colar do Excel e o "salvar so o que mudou".

   O :nth-of-type vence o .table-striped do Bootstrap, que pinta as linhas
   impares e passaria por cima do destaque.
   -------------------------------------------------------------------------- */
.metas-table tbody tr.linha-gatilho,
.metas-table.table-striped tbody tr.linha-gatilho:nth-of-type(odd) {
    background-color: #fffaf0;
}

/* O filete so no desktop: la a linha e uma faixa horizontal e o traco separa as
   duas partes da grade. No mobile cada td vira bloco, e o mesmo traco em todos
   eles seria uma cerca dentro do card - ali a marca vai na borda esquerda, e o
   separador entre os meses continua sendo o do td[data-label] da secao 18. */
@media (min-width: 768px) {
    .metas-table tbody tr.linha-gatilho > td {
        border-top: 3px solid var(--brand);
    }
}

@media (max-width: 767.98px) {
    .metas-table tbody tr.linha-gatilho,
    .metas-table.table-striped tbody tr.linha-gatilho:nth-of-type(odd) {
        border-left: 4px solid var(--brand);
    }
}

/* Resumo do gatilho: o alvo derivado e os marcos que a garrafa vai desenhar.
   Nao ha input para o alvo de proposito - meses e total editaveis podiam
   discordar, e os marcos (acumulado / total) nunca fechariam em 100%. */
.gatilho-resumo {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 1.25rem;
    margin-top: 0.75rem;
    padding: 0.6rem 0.9rem;
    border: 1px solid var(--border);
    border-left: 4px solid var(--brand);
    border-radius: var(--radius-sm);
    background-color: #fffaf0;
    color: var(--text);
    font-size: 0.875rem;
}

.gatilho-resumo-titulo {
    font-weight: 700;
    color: var(--brand-deep);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    font-size: 0.75rem;
}

/* Os marcos sao o dado que se olha antes de salvar: monoespacado para os
   percentuais nao dancarem de largura a cada digito digitado. */
#gatilhoMarcos {
    font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   18.2 Aviso de ajuste sobrescrito
   --------------------------------------------------------------------------
   Renderiza na tela de IMPORTACOES, nao aqui - mora nesta secao porque o
   assunto e o mesmo: o ajuste manual de meta. A planilha de metas apaga e
   reescreve os meses que traz, e este aviso lista o que ela derrubou, com o
   valor antigo a vista para dar de repor.

   O amarelo forte vem do .alert-warning do AdminLTE (#ffc107 com texto
   #1f2d3d, ~9:1 de contraste), que e o padrao do painel - nao se mexe nele
   aqui. O que falta e a tabela DENTRO do alerta: as bordas do Bootstrap
   assumem fundo claro e desaparecem sobre esse amarelo.
   -------------------------------------------------------------------------- */
.tabela-ajustes-sobrescritos {
    color: inherit;
}

.tabela-ajustes-sobrescritos th,
.tabela-ajustes-sobrescritos td {
    border-top-color: rgba(0, 0, 0, 0.12);
}

.tabela-ajustes-sobrescritos thead th {
    border-bottom-color: rgba(0, 0, 0, 0.25);
}

/* Os volumes existem para serem comparados coluna a coluna. */
.tabela-ajustes-sobrescritos td.text-right,
.tabela-ajustes-sobrescritos th.text-right {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}


/* ==========================================================================
   19. RANKING: LEADERBOARD POR GRUPO
   --------------------------------------------------------------------------
   Uso na view:
     @include('painel.dash.ranking.leaderboard', ['lista' => $lista])

   Lista, nao tabela: o mesmo markup serve celular e desktop, sem rolagem
   horizontal e sem virar card. O que muda e a grade.

   Os breakpoints aqui sao @container, nao @media, e por um motivo pratico: a
   sidebar do AdminLTE abre e fecha e muda a largura util do painel sem mudar a
   largura da janela. Medindo o container, a lista responde ao espaco que
   realmente tem. Por isso as variantes deste componente NAO estao na secao 15
   com as outras - elas nao sao por breakpoint de tela.

   O contorno do container e o .mj-rank; quem mede e ele.
   ========================================================================== */
.mj-rank {
    container-type: inline-size;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
    overflow: hidden;
}

/* Cabecalho de colunas: so existe quando existem colunas */
.mj-rank-cols {
    display: none;
    /* rotulo que quebra em duas linhas desce para o pe da faixa, alinhado com
       os de uma linha, em vez de flutuar no alto */
    align-items: end;
    line-height: 1.25;
    gap: 0.1rem 0.7rem;
    padding: 0.45rem 0.9rem 0.45rem 0;
    border-bottom: 1px solid var(--border);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.mj-rank-cols .r {
    text-align: right;
}

.mj-rank-list {
    display: flex;
    flex-direction: column;
}

/* ---------- faixas de contexto ---------- */
.mj-rank-band {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 1rem;
    background: linear-gradient(90deg, rgba(255, 203, 0, 0.22), rgba(255, 203, 0, 0));
    border-bottom: 1px solid var(--divider);
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--brand-deep);
}

.mj-rank-band::before {
    content: "";
    width: 3px;
    height: 12px;
    background: var(--accent);
    border-radius: 2px;
}

.mj-rank-band.is-cut {
    background: none;
    color: var(--text-muted);
    border-top: 1px solid var(--border);
}

.mj-rank-band.is-cut::before {
    background: var(--border);
}

/* Separador da janela de vizinhos: conta quantas ficaram fora, sem nomear nem
   posicionar nenhuma delas. */
.mj-rank-band.is-gap {
    background: none;
    color: var(--text-muted);
    border-top: 1px solid var(--border);
    text-transform: none;
    letter-spacing: 0.02em;
    font-weight: 600;
}

.mj-rank-band.is-gap::before {
    content: "\22EF";
    width: auto;
    height: auto;
    background: none;
    color: var(--text-muted);
    font-size: 0.85rem;
    line-height: 1;
}

/* ---------- a linha ---------- */
.mj-rank-row {
    display: grid;
    grid-template-columns: 3.1rem 1fr auto;
    align-items: center;
    gap: 0.1rem 0.7rem;
    width: 100%;
    text-align: left;
    appearance: none;
    border: 0;
    border-bottom: 1px solid var(--divider);
    background: var(--surface);
    font: inherit;
    color: var(--text);
    padding: 0.6rem 0.9rem 0.6rem 0;
}

/* Zona de premiacao: um bloco continuo, nao uma medalha. O corte pode ser top 5
   ou top 10; medalha e coisa das tres primeiras. Fica so um veu quente, porque o
   trilho da esquerda ja esta ocupado codificando o movimento. Vem antes do hover
   e do destaque de proposito: os dois tem que vencer este fundo. */
.mj-rank-row[data-premiacao="1"] {
    background: linear-gradient(90deg, rgba(255, 203, 0, 0.09), rgba(255, 203, 0, 0));
}

button.mj-rank-row {
    cursor: pointer;
}

button.mj-rank-row:hover {
    background: var(--divider);
}

button.mj-rank-row:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: -2px;
}

.mj-rank-row[data-destaque="1"] {
    background: var(--divider);
}

/* Trilho da posicao: a faixa de 3px codifica o movimento desde a ultima
   analise, e o numero fica em coluna fixa para as posicoes alinharem na
   varredura vertical. */
.mj-rank-rail {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    align-self: stretch;
}

.mj-rank-rail::before {
    content: "";
    width: 3px;
    align-self: stretch;
    background: var(--border);
    border-radius: 0 2px 2px 0;
}

.mj-rank-row[data-mv="up"] .mj-rank-rail::before {
    background: var(--verde, #28a745);
}

.mj-rank-row[data-mv="down"] .mj-rank-rail::before {
    background: #9b2c3f;
}

.mj-rank-pos {
    font-size: 1.1rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
    color: var(--text-muted);
    min-width: 2ch;
}

/* O disco vale para a zona de premiacao inteira: com corte em top 5, deixar o
   4o e o 5o sem disco fazia eles parecerem fora do bloco em que estao. O que
   distingue o podio nao e a forma, e o metal. */
.mj-rank-row[data-medalha] .mj-rank-pos,
.mj-rank-row[data-premiacao="1"] .mj-rank-pos {
    display: grid;
    place-items: center;
    width: 1.85rem;
    height: 1.85rem;
    min-width: 0;
    border-radius: 50%;
    color: var(--brand-deep);
    font-size: 0.95rem;
}

/* metal: so as tres primeiras */
.mj-rank-row[data-medalha="1"] .mj-rank-pos {
    background: var(--accent);
}

.mj-rank-row[data-medalha="2"] .mj-rank-pos {
    background: #b0aeb4;
}

.mj-rank-row[data-medalha="3"] .mj-rank-pos {
    background: #c2865c;
}

/* premiacao fora do podio: mesmo disco, ouro lavado com aro. Le como "do mesmo
   grupo que os tres de cima, mas nao e medalha". */
.mj-rank-row[data-premiacao="1"]:not([data-medalha]) .mj-rank-pos {
    background: rgba(255, 203, 0, 0.2);
    box-shadow: inset 0 0 0 1.5px rgba(255, 203, 0, 0.8);
}

.mj-rank-main {
    min-width: 0;
}

.mj-rank-name {
    display: block;
    font-size: 0.9rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Linha anonima: o rotulo e a propria posicao, nao um apelido. Apelido estavel
   ao longo da campanha permitiria montar o historico do concorrente. */
.mj-rank-name.is-anon {
    color: var(--text-muted);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}

/* Sem colocacao: a rede existe no mes, mas ainda nao pontuou. O travessao no
   lugar do numero e a cor apagada dizem "ainda nao comecou", nao "ultimo lugar".
   Ver AnaliseService::gravarPosicao, que e quem grava a posicao zero. */
.mj-rank-row[data-sem-posicao="1"] .mj-rank-pos {
    color: var(--text-muted);
    font-weight: 500;
}

/* trilho codifica subida e queda: sem posicao nao ha movimento */
.mj-rank-row[data-sem-posicao="1"] .mj-rank-rail::before {
    display: none;
}

/* Linha velada: a campanha decidiu nao expor concorrente, entao sobra a posicao.
   O peso menor e o que evita a leitura de "faltou carregar": a linha nao esta
   incompleta, ela e assim de proposito. As colunas da direita continuam no
   markup, vazias, segurando a grade das outras linhas no lugar. */
.mj-rank-row[data-velada="1"] {
    color: var(--text-muted);
}

.mj-rank-row[data-velada="1"] .mj-rank-name {
    opacity: 0.75;
}

/* sem numero nenhum, o trilho de movimento nao tem o que codificar */
.mj-rank-row[data-velada="1"] .mj-rank-rail::before {
    opacity: 0.35;
}

.mj-rank-you {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.05rem 0.35rem;
    border-radius: 3px;
    background: var(--brand);
    color: #fff;
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    vertical-align: 1px;
}

.mj-rank-sub {
    display: block;
    font-size: 0.72rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.mj-rank-sub b {
    color: var(--text);
    font-weight: 600;
}

.mj-rank-aside {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.15rem;
}

.mj-rank-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    font-size: 0.72rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
    white-space: nowrap;
}

.mj-rank-chip[data-mv="up"] {
    color: #157f3d;
}

.mj-rank-chip[data-mv="down"] {
    color: #9b2c3f;
}

.mj-spark {
    display: block;
}

/* Coluna que so existe no desktop: no celular a mesma informacao esta na
   linha .mj-rank-sub embaixo do nome. */
.mj-rank-pts {
    display: none;
}

.mj-rank-foot {
    padding: 0.6rem 1rem 0.7rem;
    border-top: 1px solid var(--border);
    font-size: 0.72rem;
    color: var(--text-muted);
}

.mj-rank-foot b {
    color: var(--text);
    font-weight: 600;
}

.mj-rank-empty {
    padding: 1.5rem 1rem;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.85rem;
}

/* ==========================================================================
   19.1 Leaderboard: grade larga (medida no painel, nao na janela)
   ========================================================================== */
@container (min-width: 600px) {
    /* A coluna de "% das metas dos KPIs" (6.3rem, entre pontos e evolucao)
       saiu em 04/09/2026: e medida de metas, nao de ranking. As duas grades
       abaixo tem de continuar identicas, senao cabecalho e linha desalinham. */
    .mj-rank-cols {
        display: grid;
        grid-template-columns: 3.1rem minmax(0, 1fr) 6.4rem 5.4rem;
    }

    .mj-rank-row {
        grid-template-columns: 3.1rem minmax(0, 1fr) 6.4rem 5.4rem;
        padding-top: 0.5rem;
        padding-bottom: 0.5rem;
    }

    .mj-rank-sub {
        display: none;
    }

    .mj-rank-pts {
        display: flex;
        flex-direction: column;
        align-items: flex-end;
        font-variant-numeric: tabular-nums;
    }

    .mj-rank-pts .v {
        font-size: 0.875rem;
        font-weight: 700;
    }

    .mj-rank-pts .u {
        font-size: 0.65rem;
        color: var(--text-muted);
    }

    .mj-rank-aside {
        justify-content: center;
    }

    .mj-rank-aside .mj-spark {
        order: -1;
    }
}

/* ==========================================================================
   19.2 Ranking: abas geral/mes, scoreboard e evolucao
   --------------------------------------------------------------------------
   O scoreboard e a evolucao tambem sao containers proprios: no dash da rede
   eles vivem lado a lado num card estreito, e na tela de ranking ocupam a
   largura toda. Medir o container e nao a janela deixa os dois casos certos com
   o mesmo markup.
   ========================================================================== */
/* Barra de navegacao do ranking: o mes da campanha e o tipo de ranking, lado a
   lado. Os dois grupos sao submits do mesmo form de filtros. */
.mj-rank-nav {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem 1.25rem;
    margin-bottom: 0.75rem;
    padding: 0.5rem 0.75rem;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
}

.mj-rank-nav-grupo {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.mj-rank-nav-lbl {
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
    white-space: nowrap;
}

.mj-rank-seg {
    display: flex;
    gap: 2px;
    padding: 3px;
    background: var(--divider);
    border-radius: var(--radius-sm);
}

.mj-rank-nav-note {
    margin-left: auto;
    font-size: 0.68rem;
    color: var(--text-muted);
}

.mj-rank-mes {
    appearance: none;
    border: 0;
    background: transparent;
    font: inherit;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--text-muted);
    padding: 0.3rem 0.62rem;
    border-radius: 4px;
    cursor: pointer;
}

.mj-rank-mes:hover {
    color: var(--text);
}

.mj-rank-mes.is-active {
    background: var(--brand);
    color: #fff;
}

.mj-rank-mes:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

.mj-rank-tab {
    appearance: none;
    border: 0;
    background: transparent;
    font: inherit;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    padding: 0.3rem 0.7rem;
    border-radius: 4px;
    cursor: pointer;
    white-space: nowrap;
}

.mj-rank-tab:hover {
    color: var(--text);
}

.mj-rank-tab.is-active {
    background: var(--brand);
    color: #fff;
}

.mj-rank-tab:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}

/* ---------- scoreboard ---------- */
.mj-score {
    container-type: inline-size;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
    overflow: hidden;
}

.mj-score-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.2rem 0.6rem;
    padding: 0.7rem 1rem 0.5rem;
    border-bottom: 1px solid var(--divider);
}

.mj-score-head .who {
    font-size: 0.95rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--text);
}

.mj-score-head .tag {
    font-size: 0.68rem;
    color: var(--text-muted);
}

.mj-score-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1px;
    background: var(--divider);
}

.mj-score-tile {
    background: var(--surface);
    padding: 0.9rem 1rem 1rem;
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: end;
    column-gap: 0.75rem;
    row-gap: 0.1rem;
}

.mj-score-tile .lbl {
    grid-column: 1 / -1;
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.mj-score-tile .big {
    font-size: 2.4rem;
    font-weight: 700;
    letter-spacing: -0.04em;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--brand);
}

.mj-score-tile .big i {
    font-size: 1rem;
    font-style: normal;
    font-weight: 600;
    letter-spacing: 0;
    color: var(--text-muted);
}

.mj-score-tile .mj-spark {
    grid-column: 2;
    grid-row: 2 / 4;
    align-self: center;
}

.mj-score-tile .foot {
    grid-column: 1;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.45rem;
    font-size: 0.8rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.mj-score-tile .foot b {
    color: var(--text);
    font-weight: 700;
}

@container (min-width: 460px) {
    .mj-score-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ---------- evolucao ---------- */
.mj-evo {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
    padding: 1rem 1rem 1.1rem;
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    color: var(--text);
}

.mj-evo-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.35rem 0.75rem;
}

.mj-evo-head .t {
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.mj-evo-head .w {
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--text);
}

.mj-evo-legend {
    display: flex;
    gap: 0.9rem;
    font-size: 0.72rem;
    color: var(--text-muted);
}

.mj-evo-legend i {
    display: inline-block;
    width: 14px;
    height: 0;
    margin-right: 0.3rem;
    vertical-align: 3px;
    border-top: 2px solid var(--brand);
}

.mj-evo-legend i.is-dash {
    border-top-style: dashed;
    border-color: var(--text-muted);
}

/* O grafico tem ALTURA fixa e largura vinda do viewBox (que cresce com a
   quantidade de analises). Antes era width:100%/height:auto, e num container
   largo o SVG inteiro escalava junto - inclusive os textos de 9px, que viravam
   20px. Fixando a altura, o desenho nunca fica desproporcional; quando o mes
   tem muitas analises, o excesso vira rolagem horizontal aqui. */
.mj-evo-plot {
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    margin: 0 -0.25rem;
    padding: 0 0.25rem;
}

/* A altura cresce por breakpoint, dentro de limites. A largura acompanha pela
   proporcao do viewBox, entao o desenho fica maior na tela grande sem voltar ao
   problema antigo (escalar sem teto e inflar os textos de 9px). O excesso vira
   rolagem no wrapper. */
.mj-evo-plot svg {
    display: block;
    height: 148px;
    width: auto;
    max-width: none;
}

@media (min-width: 992px) {
    .mj-evo-plot svg {
        height: 186px;
    }
}

/* Nao ha terceiro degrau de proposito: a altura multiplica a largura pela
   proporcao do viewBox, e crescer mais faria o desenho voltar a estourar a
   coluna numa tela grande - trocando um problema pelo outro. */

/* ---------- pontos interativos ---------- */
.mj-evo-pt {
    cursor: pointer;
}

.mj-evo-pt:focus {
    outline: none;
}

.mj-evo-pt:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 1px;
}

/* a marca visivel cresce quando o alvo invisivel ao lado recebe o ponteiro */
.mj-evo-pt:hover+.mj-evo-marca,
.mj-evo-pt:focus-visible+.mj-evo-marca {
    r: 5.5;
}

/* O balao de explicacao. Nasceu para os pontos do grafico e hoje serve tambem
   o "?" de ajuda da secao 16.1: os dois disparam o mesmo painel.dash.tip.
   Segue morando aqui para nao mudar a cascata de quem ja o consumia. */
.mj-tip {
    position: fixed;
    z-index: 1080;
    /* 19rem e nao 15: o "?" da %meta explica periodo, conta e criterio, e em
       15rem a explicacao virava uma coluna de 14 linhas */
    max-width: 19rem;
    padding: 0.4rem 0.6rem;
    border-radius: var(--radius-sm);
    background: var(--brand-deep);
    color: #fff;
    font-size: 0.72rem;
    line-height: 1.35;
    box-shadow: 0 4px 14px -4px rgba(0, 0, 0, 0.4);
    pointer-events: none;
}

.mj-tip[hidden] {
    display: none;
}

.mj-evo-cap {
    font-size: 0.68rem;
    color: var(--text-muted);
    line-height: 1.5;
}

/* ==========================================================================
   19.3 Ranking: posicao dentro do card-rede (dash de admin e executivo)
   ========================================================================== */
.mj-rede-pos {
    align-items: center;
    margin-bottom: 0.15rem;
}

.mj-rede-pos .mj-spark {
    display: inline-block;
    vertical-align: middle;
    margin-left: 0.3rem;
}

.mj-rede-de {
    font-size: 0.68rem;
    color: var(--text-muted);
    margin-right: 0.2rem;
}

/* ==========================================================================
   19.4 Ranking: os grupos lado a lado (admin sem recorte de grupo)
   --------------------------------------------------------------------------
   Substitui os 121 cards por rede que a tela antiga empilhava. Uma coluna por
   grupo; o grupo inteiro fica a um clique.
   ========================================================================== */
.mj-grupos {
    container-type: inline-size;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 1px;
    background: var(--border);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
    overflow: hidden;
}

@container (min-width: 560px) {
    .mj-grupos {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@container (min-width: 900px) {
    .mj-grupos {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@container (min-width: 1180px) {
    .mj-grupos {
        grid-template-columns: repeat(5, minmax(0, 1fr));
    }
}

.mj-grupo {
    background: var(--surface);
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.mj-grupo-head {
    display: flex;
    justify-content: space-between;
    gap: 0.4rem;
    margin: 0;
    padding: 0.6rem 0.75rem 0.5rem;
    border-bottom: 1px solid var(--divider);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--brand);
}

.mj-grupo-head em {
    font-style: normal;
    font-size: 0.62rem;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    color: var(--text-muted);
}

.mj-grupo-row {
    display: grid;
    grid-template-columns: 1.7rem minmax(0, 1fr) auto;
    align-items: center;
    gap: 0.45rem;
    padding: 0.4rem 0.75rem;
    border-bottom: 1px solid var(--divider);
    color: var(--text);
    text-decoration: none;
}

.mj-grupo-row:hover {
    background: var(--divider);
    color: var(--text);
    text-decoration: none;
}

.mj-grupo-row .p {
    font-size: 0.78rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
}

/* na coluna compacta nao cabe disco, mas a zona de premiacao inteira ganha a
   cor da marca na posicao - mesmo critério do leaderboard */
.mj-grupo-row[data-medalha] .p,
.mj-grupo-row[data-premiacao="1"] .p {
    color: var(--brand);
}

.mj-grupo-row[data-medalha] .p {
    font-weight: 700;
}

.mj-grupo-row[data-premiacao="1"] {
    background: linear-gradient(90deg, rgba(255, 203, 0, 0.09), rgba(255, 203, 0, 0));
}

.mj-grupo-row[data-premiacao="1"]:hover {
    background: var(--divider);
}

.mj-grupo-row .nm {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.mj-grupo-row .nm b {
    font-size: 0.78rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mj-grupo-row .nm .pt {
    font-size: 0.65rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.mj-grupo-more {
    margin-top: auto;
    padding: 0.5rem 0.75rem 0.65rem;
    font-size: 0.65rem;
    color: var(--text-muted);
}

.mj-grupo-more:hover {
    color: var(--brand);
}

/* ==========================================================================
   19.5 Ranking: bloco de topo do dash (posicao + evolucao lado a lado)
   --------------------------------------------------------------------------
   No dash da rede e em metas, o scoreboard e o grafico ficam na mesma linha.
   Como as duas alturas naturais nao batem (dois numeros grandes de um lado, um
   grafico do outro), o card estica para acompanhar a linha. So vale quando as
   colunas estao lado a lado: empilhadas no celular, cada um volta a ter a
   altura do proprio conteudo.
   ========================================================================== */
/* respiro entre o topo e a secao dos KPIs */
.mj-topo {
    margin-bottom: 1rem;
}

@media (min-width: 1200px) {

    .mj-topo>[class*="col-"]>.mj-score,
    .mj-topo>[class*="col-"]>.mj-evo {
        height: 100%;
    }

    /* o grafico fica ancorado embaixo, para a legenda nao flutuar no meio */
    .mj-topo>[class*="col-"]>.mj-evo .mj-evo-plot {
        margin-top: auto;
    }

    /* Aqui os dois tiles EMPILHAM em vez de ficar lado a lado, e cada um estica
       para dividir a altura. Antes ficavam curtos no topo e sobrava um vazio
       grande embaixo do card - o esticar criava o vao em vez de usar o espaco.
       Vence o @container de 460px do proprio .mj-score-grid por especificidade. */
    .mj-topo .mj-score {
        display: flex;
        flex-direction: column;
    }

    .mj-topo .mj-score-grid {
        flex: 1;
        grid-template-columns: minmax(0, 1fr);
        grid-auto-rows: 1fr;
    }

    /* rotulo no alto, numero e pontuacao embaixo: o tile mais alto distribui em
       vez de acumular folga no meio */
    .mj-topo .mj-score-tile {
        align-content: space-between;
        row-gap: 0.5rem;
    }

    /* com mais altura, o numero da posicao pode crescer */
    .mj-topo .mj-score-tile .big {
        font-size: 3rem;
    }

    .mj-topo .mj-score-tile .big i {
        font-size: 1.1rem;
    }
}

/* ==========================================================================
   19.6 Dash: coluna lateral encostando no rodape da linha
   --------------------------------------------------------------------------
   A coluna do gatilho + comparativo terminava bem antes da grade de KPIs, que
   e mais alta, e sobrava um vazio grande embaixo dela. Aqui o comparativo
   absorve a altura que sobra e encosta no rodape, entao o unico buraco que
   resta e o slot vago da grade de KPIs - que le como "falta um KPI", nao como
   layout quebrado. Quantos KPIs a rede tem varia, entao esse slot e inerente.

   Sao varios niveis de flex porque o card-comparativo e aninhado: card >
   card-body > row > col > card interno > card-body colorido. O fundo colorido
   so desce ate embaixo se a cadeia toda esticar.

   So no PC: empilhado no celular cada card volta a ter a altura do conteudo.
   ========================================================================== */
@media (min-width: 1200px) {
    .mj-lateral {
        display: flex;
        flex-direction: column;
    }

    /* Sem zerar a margem: os cards de KPI da coluna vizinha terminam com o
       margin-bottom de 1rem do .card do AdminLTE, e a coluna toda mede isso. Se
       este card zerar a dele, ele desce 1rem alem da ultima linha de KPIs - era
       a linha passando um pouco. Mantendo a margem, o flex desconta ela da
       altura e as duas colunas fecham no mesmo ponto, seja qual for o valor que
       o tema use. */
    .mj-lateral>.card:last-child {
        flex: 1;
    }

    .mj-lateral>.card:last-child,
    .mj-lateral>.card:last-child>.card-body,
    .mj-lateral>.card:last-child>.card-body>.row,
    .mj-lateral>.card:last-child>.card-body>.row>.col-12,
    .mj-lateral .card-comparativos,
    .mj-lateral .card-comparativos>.card-body {
        display: flex;
        flex-direction: column;
        min-height: 0;
    }

    .mj-lateral>.card:last-child>.card-body,
    .mj-lateral>.card:last-child>.card-body>.row,
    .mj-lateral>.card:last-child>.card-body>.row>.col-12,
    .mj-lateral .card-comparativos,
    .mj-lateral .card-comparativos>.card-body,
    .mj-lateral .card-comparativos .tab-content {
        flex: 1;
    }

    .mj-lateral .card-comparativos .tab-content {
        display: flex;
        flex-direction: column;
        min-height: 0;
    }

    /* Esticar a caixa por fora nao resolvia nada: a lista continuava amontoada no
       topo com branco embaixo. Aqui as linhas se distribuem na altura ganha.
       Precisa ser .tab-pane.active e nao .tab-pane: o Bootstrap esconde as abas
       inativas com display:none, e um display:flex aqui as traria de volta.
       Este seletor tem especificidade (0,4,0) contra a (0,2,0) do plugin. */
    .mj-lateral .card-comparativos .tab-content>.tab-pane.active {
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        flex: 1;
        min-height: 0;
    }
}

/* Placar da aba: quantos KPIs ja estao na meta. O percentual de cada um a tela
   ja mostrava; o total, nao. */
.mj-comp-placar {
    padding-bottom: 0.5rem;
    margin-bottom: 0.35rem;
    border-bottom: 1px solid var(--border);
    font-size: 0.72rem;
    color: var(--text-muted);
}

.mj-comp-placar b {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--brand);
}

/* ==========================================================================
   20. ANIMACOES DE ENTRADA
   --------------------------------------------------------------------------
   Ligadas por resources/views/painel/dash/anima.blade.php.

   ESTRUTURA: o IntersectionObserver marca CONTAINERES, nao pecas. Um
   .mj-rank-list recebe data-anima e acende as 30 linhas, as 30 barras e os 30
   sparklines de dentro dele de uma vez. Observar peca a peca daria centenas de
   observers numa tela de admin (121 redes). Por isso os seletores abaixo sao
   sempre "container aceso -> filho anima".

   TODO estado inicial daqui esta preso a html.anima-pronta, classe que o head
   so poe quando ha JS, ha IntersectionObserver e o usuario nao pediu movimento
   reduzido. Sem ela nada abaixo se aplica e a tela renderiza no estado final.
   Isso nao e detalhe de acessibilidade: barra escondida que nunca anima e dado
   perdido, entao o padrao tem que ser "visivel".

   Animar sempre transform / opacity / clip-path. width e stroke-width em
   elemento grande custam layout a cada frame, e esta tela chega a ~1450 barras.

   ESCALONAMENTO: a peca publica --i (seu indice na lista) e cada transicao
   calcula o proprio atraso. O teto de 12 existe para a 30a linha de um ranking
   nao esperar 1,4s so para comecar.

   INDICE
     20.1 barras       20.2 tracos SVG
     20.3 listas       20.4 knob
   ========================================================================== */

/* --------------------------------------------------------------------------
   20.1 Barras
   clip-path e nao width nem scaleX: width faz layout a cada frame, e scaleX
   numa barra de 3px com border-radius esmaga o raio durante a animacao.
   -------------------------------------------------------------------------- */
html.anima-pronta [data-anima~="barras"] .mj-anima-barra {
    clip-path: inset(0 100% 0 0);
}

html.anima-pronta [data-anima~="barras"].anima-on .mj-anima-barra {
    clip-path: inset(0 0 0 0);
    transition: clip-path 1.1s cubic-bezier(0.22, 1, 0.36, 1) calc(min(var(--i, 0), 12) * 45ms);
}

/* --------------------------------------------------------------------------
   20.2 Tracos SVG
   Depende de pathLength="1" na polyline: normaliza o comprimento do traco, e
   com isso o dasharray funciona sem ninguem medir o path em JS.
   -------------------------------------------------------------------------- */
html.anima-pronta [data-anima~="tracos"] .mj-traco {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
}

html.anima-pronta [data-anima~="tracos"].anima-on .mj-traco {
    stroke-dashoffset: 0;
    transition: stroke-dashoffset 1.1s ease-out calc(min(var(--i, 0), 12) * 45ms);
}

/* Area e marcas entram DEPOIS do traco. Na ordem inversa a marca final ficaria
   flutuando sozinha antes de a linha chegar nela. */
html.anima-pronta [data-anima~="tracos"] .mj-traco-area,
html.anima-pronta [data-anima~="tracos"] .mj-traco-marca {
    opacity: 0;
}

/* A area do sparkline nasce com opacity .1 no proprio SVG: e para esse valor
   que ela volta, nao para 1. */
html.anima-pronta [data-anima~="tracos"].anima-on .mj-traco-area {
    opacity: 0.1;
    transition: opacity 0.5s ease-out calc(min(var(--i, 0), 12) * 45ms + 0.7s);
}

html.anima-pronta [data-anima~="tracos"].anima-on .mj-traco-marca {
    opacity: 1;
    transition: opacity 0.4s ease-out calc(min(var(--i, 0), 12) * 45ms + 0.85s);
}

/* --------------------------------------------------------------------------
   20.3 Listas: os filhos diretos sobem em cascata
   -------------------------------------------------------------------------- */
html.anima-pronta [data-anima~="lista"]>* {
    opacity: 0;
    transform: translateY(10px);
}

html.anima-pronta [data-anima~="lista"].anima-on>* {
    opacity: 1;
    transform: none;
    transition: opacity 0.45s ease-out calc(min(var(--i, 0), 12) * 45ms),
        transform 0.45s cubic-bezier(0.22, 1, 0.36, 1) calc(min(var(--i, 0), 12) * 45ms);
}

/* --------------------------------------------------------------------------
   20.4 Knob
   O valor quem anima e o partial do plugin: e canvas, so da para redesenhar em
   JS. Aqui fica so o fade, para o gauge nao aparecer cravado em zero antes de
   o observador mandar contar.
   -------------------------------------------------------------------------- */
html.anima-pronta .knob-anima {
    opacity: 0;
}

html.anima-pronta .knob-anima.anima-on {
    opacity: 1;
    transition: opacity 0.4s ease-out;
}

/* ==========================================================================
   21. PREMIOS: SIMULACAO DE PREMIACAO MENSAL
   --------------------------------------------------------------------------
   Uso na view:
     @include('painel.premios.tabela-simulacao', ['simulacao' => $simulacao])

   Substitui a imagem tabela@2x.png, que era ilegivel no celular e por isso
   ficava escondida abaixo de 428px - o que tirava a explicacao da conta
   justamente de quem mais acessa por telefone.

   O markup traz o mesmo conteudo duas vezes, e aqui decidimos qual aparece:
   ate 819px de container sao os cards, dali para cima e a tabela. Sao 27
   colunas com cabecalho de tres niveis; nenhum reflow em CSS mantem isso
   legivel num celular, entao a versao estreita e outro desenho, nao a mesma
   tabela espremida.

   O breakpoint e @container e nao @media pelo mesmo motivo da secao 19: a
   sidebar do AdminLTE abre e fecha e muda a largura util do painel sem mudar
   a da janela. Navegador sem @container fica nos cards, que funcionam em
   qualquer largura.

   Cores vem dos tokens da secao 1 (--brand, --ok, --surface, --border,
   --divider, --text-muted, --radius, --shadow-card).
   ========================================================================== */
.mj-simul {
    container-type: inline-size;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
    padding: 0.9rem;
    color: var(--text);
}

.mj-simul-legenda p {
    margin: 0 0 0.8rem;
    font-size: 0.82rem;
    line-height: 1.5;
    color: var(--text-muted);
}

.mj-simul-legenda b {
    color: var(--text);
}

/* Cada dica descreve um dos dois layouts: a da tabela so aparece com ela, no
   @container la embaixo. */
.mj-simul-dica,
.mj-simul-dica-cards {
    margin: 0 0 0.5rem;
    font-size: 0.72rem;
    color: var(--text-muted);
}

.mj-simul-dica {
    display: none;
}

/* --------------------------------------------------------------------------
   21.1 Estreito: um card por cliente, um indicador por linha
   -------------------------------------------------------------------------- */
.mj-simul-scroll {
    display: none;
}

.mj-simul-cards {
    display: grid;
    gap: 0.75rem;
}

.mj-simul-card {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 0.7rem 0.8rem 0.8rem;
}

.mj-simul-card.is-fora {
    border-color: rgba(var(--brand-rgb), 0.35);
}

.mj-simul-card-topo {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    padding-bottom: 0.45rem;
    border-bottom: 2px solid var(--divider);
}

.mj-simul-card-pos {
    flex: 0 0 auto;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    background: var(--brand);
    color: #fff;
    font-size: 0.8rem;
    font-weight: 800;
}

.mj-simul-card-nome {
    flex: 1 1 auto;
    font-size: 1rem;
    font-weight: 700;
}

.mj-simul-card-total {
    flex: 0 0 auto;
    text-align: right;
}

.mj-simul-card-total b {
    font-size: 1.2rem;
    color: var(--ok);
}

.mj-simul-card.is-fora .mj-simul-card-total b {
    color: var(--brand);
}

.mj-simul-card-total small {
    display: block;
    font-size: 0.62rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.mj-simul-card-status {
    margin: 0.5rem 0 0;
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--ok);
}

.mj-simul-card.is-fora .mj-simul-card-status {
    color: var(--brand);
}

.mj-simul-card-grupo {
    margin: 0.85rem 0 0.1rem;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.mj-simul-card-grupo.is-bonus {
    color: var(--brand);
}

.mj-simul-card-lista {
    margin: 0;
    padding: 0;
    list-style: none;
}

.mj-simul-card-item {
    position: relative;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.6rem;
    padding: 0.45rem 0 0.55rem;
    border-top: 1px solid var(--divider);
}

.mj-simul-card-kpi {
    font-size: 0.76rem;
    line-height: 1.25;
}

.mj-simul-card-kpi small {
    display: block;
    font-size: 0.64rem;
    color: var(--text-muted);
}

.mj-simul-card-valor {
    flex: 0 0 auto;
    text-align: right;
}

.mj-simul-card-valor b {
    font-size: 0.95rem;
}

.mj-simul-card-item.is-ok .mj-simul-card-valor b {
    color: var(--ok);
}

.mj-simul-card-item.is-baixo .mj-simul-card-valor b {
    color: var(--brand);
}

.mj-simul-card-valor small {
    display: block;
    font-size: 0.66rem;
    color: var(--text-muted);
}

/* A barra e a leitura rapida do card: escala 0 a 130%, com um risco no 100%
   (= 76.92% da escala) para separar quem bateu a meta de quem passou dela.
   O preenchimento vem do --pct calculado na view. */
.mj-simul-card-barra {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    height: 3px;
    border-radius: 2px;
    background: var(--divider);
}

.mj-simul-card-barra::before {
    content: "";
    display: block;
    width: var(--pct, 0%);
    height: 100%;
    border-radius: 2px;
    background: var(--ok);
}

.mj-simul-card-item.is-baixo .mj-simul-card-barra::before {
    background: var(--brand);
}

.mj-simul-card-barra::after {
    content: "";
    position: absolute;
    top: -2px;
    bottom: -2px;
    left: 76.92%;
    width: 1px;
    background: var(--text-muted);
    opacity: 0.55;
}

/* --------------------------------------------------------------------------
   21.2 Largo: a tabela, com a coluna do cliente fixa na rolagem
   -------------------------------------------------------------------------- */
@container (min-width: 820px) {

    .mj-simul-cards {
        display: none;
    }

    .mj-simul-dica {
        display: block;
    }

    .mj-simul-dica-cards {
        display: none;
    }

    .mj-simul-scroll {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    /* separate, e nao collapse: com collapse as bordas da celula sticky ficam
       para tras e somem por baixo das colunas que rolam */
    /* max-content + min-width: 100% e o que faz o `width` das colunas fixas
       valer. Com `width: 100%` o Chrome usa a largura do container como base e
       espreme as celulas abaixo da medida pedida - e ai os offsets `right` das
       colunas fixas, que sao a soma dessas larguras, saem do lugar. */
    .mj-simul-tabela {
        width: max-content;
        min-width: 100%;
        border-collapse: separate;
        border-spacing: 0;
        font-size: 0.78rem;
    }

    .mj-simul-tabela thead th {
        padding: 0.4rem 0.45rem;
        background: var(--brand);
        border-right: 1px solid rgba(255, 255, 255, 0.25);
        border-bottom: 1px solid rgba(255, 255, 255, 0.25);
        color: #fff;
        font-weight: 700;
        text-align: center;
        vertical-align: middle;
    }

    .mj-simul-tabela thead th.is-bonus {
        background: var(--brand-dark);
    }

    /* O rotulo do grupo e centrado na faixa inteira, entao numa tabela rolada
       ele acaba embaixo das colunas fixas. Sticky dentro do proprio th, com as
       bordas nas larguras dessas colunas (90 e 76+72+58), mantem o texto na
       parte visivel da faixa sem sair dela. */
    .mj-simul-grupo {
        display: inline-block;
        position: sticky;
        left: 90px;
        right: 206px;
    }

    .mj-simul-kpi-nome {
        display: block;
        max-width: 11rem;
        font-size: 0.66rem;
        line-height: 1.2;
        text-transform: uppercase;
    }

    .mj-simul-kpi-peso {
        display: block;
        margin-top: 0.2rem;
        font-size: 0.72rem;
        font-weight: 800;
        color: var(--accent);
    }

    .mj-simul-sub {
        font-size: 0.64rem;
        font-weight: 600;
    }

    .mj-simul-tabela tbody th,
    .mj-simul-tabela tbody td {
        padding: 0.45rem 0.5rem;
        background: var(--surface);
        border-bottom: 1px solid var(--divider);
        text-align: center;
        white-space: nowrap;
    }

    .mj-simul-tabela tbody td.is-bonus {
        background: #fdf3f3;
    }

    .mj-simul-pct {
        font-weight: 700;
    }

    .mj-simul-pct.is-ok {
        color: var(--ok);
    }

    .mj-simul-pct.is-baixo {
        color: var(--brand);
    }

    /* Colunas fixas na rolagem: o cliente na esquerda e o resultado na direita.
       Sem isso, 27 colunas fazem o leitor perder de vista de quem e a linha e
       em quantos pontos ela deu - justamente as duas pontas que interessam.

       Os `right` sao a soma das larguras das colunas a direita de cada uma, e
       por isso as tres tem `width` fixo. Os valores cabem folgados (o mais
       largo e "Ranking", no cabecalho), entao o layout auto respeita a medida.
       Mexeu numa largura, refaca as somas.

       O box-shadow faz a borda de separacao: em celula sticky a `border` fica
       para tras e some por baixo das colunas que rolam. */
    .mj-simul-col-cliente,
    .mj-simul-col-total,
    .mj-simul-col-rank,
    .mj-simul-col-status {
        position: sticky;
        z-index: 2;
    }

    .mj-simul-tabela thead .mj-simul-col-cliente,
    .mj-simul-tabela thead .mj-simul-col-total,
    .mj-simul-tabela thead .mj-simul-col-rank,
    .mj-simul-tabela thead .mj-simul-col-status {
        z-index: 3;
    }

    .mj-simul-col-cliente {
        left: 0;
        width: 90px;
        text-align: left;
    }

    .mj-simul-col-status {
        right: 0;
        width: 58px;
    }

    .mj-simul-col-rank {
        right: 58px;
        width: 72px;
    }

    .mj-simul-col-total {
        right: 130px;
        width: 76px;
    }

    .mj-simul-tabela tbody th.mj-simul-col-cliente {
        box-shadow: 1px 0 0 var(--border);
        font-weight: 700;
        text-align: left;
    }

    .mj-simul-tabela tbody .mj-simul-col-total {
        box-shadow: -1px 0 0 var(--border);
    }

    .mj-simul-tabela tbody .mj-simul-col-total {
        font-size: 0.9rem;
        font-weight: 800;
        color: var(--ok);
    }

    .mj-simul-tabela tbody .mj-simul-col-rank {
        font-weight: 700;
        color: var(--ok);
    }

    .mj-simul-tabela tbody tr.is-fora .mj-simul-col-total,
    .mj-simul-tabela tbody tr.is-fora .mj-simul-col-rank {
        color: var(--brand);
    }

    .mj-simul-col-status .fa-thumbs-up {
        color: var(--ok);
    }

    .mj-simul-col-status .fa-thumbs-down {
        color: var(--brand);
    }
}

/* ==========================================================================
   22. IMPORTACOES: AS ETAPAS DA CARGA
   --------------------------------------------------------------------------
   Uso: resources/views/painel/importacoes/inserir.blade.php

   A tela era um select de tipo, um campo de arquivo e um botao "Executar".
   Nada dizia a ORDEM (metas e volumes encontram a rede pelo codigo, entao a
   base de redes vem primeiro ou o resto e descartado em silencio), nem quantos
   arquivos cada base tem (volume sao 13, o resto e 1), e o campo de arquivo
   aparecia inclusive para a Analise, que nao usa arquivo.

   Agora e um card por etapa, numerado. O numero nao e enfeite: e a unica coisa
   na tela que comunica a sequencia.
   ========================================================================== */

.etapas-importacao {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.etapa-importacao {
    margin-bottom: 0;
}

.etapa-importacao .card-body {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 1rem;
}

.etapa-cabecalho {
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
    /* Cresce e encolhe, para o bloco do formulario ficar com o que precisa e
       nao mais que isso. */
    flex: 1 1 20rem;
    min-width: 0;
}

.etapa-numero {
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    background: var(--brand);
    color: #fff;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    /* line-height 1 porque o flex centraliza: a altura de linha herdada
       empurrava o numero para baixo do circulo. */
    line-height: 1;
}

.etapa-texto {
    min-width: 0;
}

.etapa-titulo {
    margin: 0 0 0.15rem;
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--text);
}

.etapa-descricao {
    margin: 0 0 0.25rem;
    font-size: 0.85rem;
    color: var(--text-muted);
}

/* O que ja existe no banco. Derivado dos dados, porque nao ha log de
   importacao: a tabela `importacoes` esta vazia e so tem timestamps. */
.etapa-estado {
    margin: 0;
    font-size: 0.8rem;
    color: var(--text);
}

.etapa-estado i {
    color: var(--brand);
}

.etapa-separador {
    color: var(--border);
    margin: 0 0.15rem;
}

.etapa-form {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    /* Nao cresce: o texto da etapa fica com a sobra. */
    flex: 0 1 auto;
    margin: 0;
}

.etapa-arquivo {
    font-size: 0.85rem;
    max-width: 15rem;
}

.etapa-botao {
    white-space: nowrap;
}

/* Ate tablet os dois blocos empilham, e o formulario passa a ocupar a linha
   inteira: com o campo de arquivo ao lado do texto em tela estreita, o nome do
   arquivo selecionado nao caberia em nenhum dos dois. */
@media (max-width: 767.98px) {
    .etapa-importacao .card-body {
        flex-direction: column;
        align-items: stretch;
    }

    .etapa-form {
        flex: 1 1 auto;
        justify-content: space-between;
    }

    .etapa-arquivo {
        max-width: none;
    }
}

/* --------------------------------------------------------------------------
   22.1 Importacoes: acompanhamento da apuracao do ranking
   --------------------------------------------------------------------------
   A apuracao roda em fila, entao a tela pergunta o andamento de tres em tres
   segundos (o JS esta na propria view). Aqui e so a barra.

   Duas variantes, porque as fases sao de dois tipos: as que tem total conhecido
   (uma escrita por rede) rendem percentual, e as outras nao. Barra que inventa
   numero mente sobre o que falta, entao nessas a barra fica listrada e animada,
   sem afirmar posicao.
   -------------------------------------------------------------------------- */

.analise-progresso {
    /* Ocupa a linha inteira abaixo do botao, dentro do card da etapa. */
    flex: 1 1 100%;
    margin-top: 0.5rem;
}

.analise-progresso-topo {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.5rem;
    margin-bottom: 0.25rem;
    font-size: 0.8rem;
}

.analise-etapa {
    color: var(--text);
    font-weight: 600;
}

.analise-contagem {
    color: var(--text-muted);
    /* Nao encolhe: o percentual e o dado que o olho procura primeiro. */
    flex: 0 0 auto;
}

.analise-barra {
    height: 0.5rem;
    border-radius: 999px;
    background: var(--divider);
    overflow: hidden;
}

.analise-barra-preenchida {
    height: 100%;
    width: 0;
    border-radius: 999px;
    background: var(--brand);
    transition: width 0.4s ease;
}

/* Fase sem total: a listra andando diz "trabalhando" sem afirmar quanto falta. */
.analise-barra-preenchida.indeterminada {
    background-image: linear-gradient(
        90deg,
        rgba(255, 255, 255, 0.45) 25%,
        transparent 25%,
        transparent 50%,
        rgba(255, 255, 255, 0.45) 50%,
        rgba(255, 255, 255, 0.45) 75%,
        transparent 75%
    );
    background-size: 1rem 1rem;
    animation: analise-listra 0.9s linear infinite;
}

@keyframes analise-listra {
    from { background-position: 0 0; }
    to { background-position: 1rem 0; }
}

/* Terminou: verde, porque o vermelho da marca aqui parece erro. */
.analise-progresso[data-estado="concluido"] .analise-barra-preenchida {
    background: var(--ok);
    animation: none;
}

.analise-progresso[data-estado="erro"] .analise-barra-preenchida {
    background: var(--brand-dark);
    animation: none;
}

.analise-aviso {
    margin: 0.4rem 0 0;
    font-size: 0.8rem;
    color: var(--brand-dark);
}

.analise-aviso code {
    /* O comando fica selecionavel e legivel: e para ser copiado. */
    background: var(--divider);
    color: var(--text);
    padding: 0 0.25rem;
    border-radius: var(--radius-sm);
    user-select: all;
}

@media (prefers-reduced-motion: reduce) {
    .analise-barra-preenchida {
        transition: none;
    }

    .analise-barra-preenchida.indeterminada {
        animation: none;
    }
}


/* ==========================================================================
   23. SESSOES ATIVAS: KPIS DO TOPO E O RELOGIO DO AUTO-REFRESH
   --------------------------------------------------------------------------
   Cinco numeros acima da tabela de /painel/online. Nao usam o .small-box do
   AdminLTE de proposito: aquele componente e um bloco colorido de dashboard,
   com icone grande e link de rodape, e aqui o que se quer e o oposto - um
   numero grande e sobrio, porque o assunto da tela e a tabela abaixo.

   Os cinco dividem a linha por igual no XL (col-xl sem numero), caem para
   dois por linha no tablet e o ultimo ocupa a largura toda: "contas em mais
   de um lugar" e o unico que tem rotulo comprido e o unico que muda de cor.
   ========================================================================== */

.mj-sessoes-kpis {
    margin-bottom: 1rem;
}

.mj-sessao-kpi {
    background: var(--surface);
    border: 1px solid var(--border);
    border-left: 3px solid var(--divider);
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
    padding: 0.75rem 1rem;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.mj-sessao-kpi-num {
    font-size: 1.75rem;
    font-weight: 700;
    line-height: 1.1;
    color: var(--text);
}

.mj-sessao-kpi-rot {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

/* Verde so no "ativos agora": e o unico numero que significa boa noticia.
   O token --ok e o verde feito para fundo claro. */
.mj-sessao-kpi-ok {
    border-left-color: var(--ok);
}

/* Vermelho so quando ha o que olhar - a classe nao sai do Blade com zero. Um
   zero pintado de alerta treina o olho a ignorar a cor, que e justamente o
   contrario do que este numero precisa. */
.mj-sessao-kpi-alerta {
    border-left-color: var(--brand);
}

.mj-sessao-kpi-alerta .mj-sessao-kpi-num {
    color: var(--brand);
}

/* O relogio da proxima atualizacao. Some da vista quando o switch esta
   desligado, mas continua ocupando o lugar para o cabecalho nao pular. */
.mj-sessoes-relogio {
    font-size: 0.8rem;
    color: var(--text-muted);
    white-space: nowrap;
}

.mj-sessoes-relogio.mj-off {
    visibility: hidden;
}

/* O traco na coluna de acao de quem NAO pode derrubar sessao (o grupo Admin le
   a tela, so o SuperAdmin derruba). Existe para a celula nao ficar vazia e
   parecer que faltou carregar alguma coisa. */
.mj-sessoes-sem-acao {
    color: var(--text-muted);
}

@media (max-width: 767.98px) {
    .mj-sessao-kpi {
        margin-bottom: 0.5rem;
    }

    .mj-sessao-kpi-num {
        font-size: 1.35rem;
    }
}


/* ==========================================================================
   24. DESTINO: A VIAGEM DO PREMIO FINAL
   --------------------------------------------------------------------------
   Uso na view: resources/views/painel/destino.blade.php, com os dois partials
   de painel/destino/ (gema.blade.php e brilho.blade.php).

   Esta e a unica tela do painel que e PECA, e nao relatorio, e por isso e a
   unica que troca o fundo claro por vermelho cheio. O bloco inteiro e um
   CARTAZ apoiado sobre a mesa do painel: raio, sombra e o respiro do
   content-wrapper em volta sao o que o separam da sidebar, que tambem e
   vermelha. Sem essa moldura as duas areas viram uma mancha so.

   POR QUE O VERMELHO NAO E --brand. Texto branco sobre #ed1c24 da 4,4:1, e
   texto corrido precisa de 4,5:1. Os paragrafos desta pagina sao longos e sao
   o conteudo dela - nao dava para resolver aumentando a fonte, porque "texto
   grande" comeca em 24px. O --destino-fundo e o mesmo vermelho escurecido ate
   5,6:1; lido sozinho continua sendo o vermelho da campanha, e encostado na
   sidebar ainda ajuda a separar o cartaz do chrome.

   A LAPIDACAO e recorte de verdade, medido do
   campanhas/diamantes2026/pagina-destino/pagina_site_diamantes_2026.svg:
   --gema-faceta e o poligono de fora (a pedra preta) e --gema-foto o de
   dentro (a foto). As porcentagens sao tortas porque sao as do desenho, e a
   faceta e mais grossa embaixo que em cima - por isso sao dois poligonos e
   nao um padding.

   BREAKPOINT em @container, e nao @media, pelo mesmo motivo das secoes 19 e
   21: a sidebar do AdminLTE abre e fecha e muda a largura util do painel sem
   mudar a da janela. Navegador sem @container fica na coluna unica, que
   funciona em qualquer largura.

   INDICE
     24.1 o cartaz e a chamada   24.2 texto corrido
     24.3 a gema                 24.4 o brilho
     24.5 as tres gemas encavaladas
     24.6 rodape de navegacao    24.7 duas colunas (@container)
   ========================================================================== */
.mj-destino {
    /* Os dois recortes da pedra. Caixa de 466x382 no desenho original. */
    --gema-faceta: polygon(75.6% 0%, 93.2% 18.9%, 100% 27.2%, 53.4% 100%, 0% 33.6%, 17.6% 9.2%);
    --gema-foto: polygon(81.1% 0%, 91.9% 11.8%, 100% 20.6%, 50% 100%, 0% 36.6%, 18.9% 10%);
    --gema-proporcao: 466 / 382;

    /* O retangulo que a janela ocupa dentro da pedra, em % da caixa. A foto e
       posicionada NELE, e nao na caixa inteira: e o que a peca faz, e sem isso
       a foto entra ampliada e o losango mostra so um pedaco do meio dela. E por
       ele que --gema-foto acima esta normalizado, e nao pela caixa. */
    --gema-janela-x: 7.7%;
    --gema-janela-y: 6.9%;
    --gema-janela-larg: 74.7%;
    --gema-janela-alt: 73.5%;
    --gema-preto: #1d1d1b;

    /* O vermelho da marca, escurecido ate o branco passar em 4,5:1. */
    --destino-fundo: #cf141b;

    container-type: inline-size;
    background: var(--destino-fundo);
    color: #fff;
    border-radius: var(--radius-lg);
    box-shadow: 0 2px 16px rgba(0, 0, 0, 0.18);
    padding: clamp(1.75rem, 5cqi, 4rem) clamp(1.25rem, 4.5cqi, 3.5rem) clamp(2rem, 5cqi, 4rem);

    /* Segura os brilhos que passam da borda. Os deslocamentos negativos deles
       sao pequenos de proposito, mas o clip garante o canto arredondado. */
    overflow: hidden;
}

/* --------------------------------------------------------------------------
   24.1 A chamada
   O itálico e o contraste de peso sao da peca, e a fonte itálica de verdade
   (300 e 700) e pedida so nesta tela, no @section('prescript') da view.
   -------------------------------------------------------------------------- */
.mj-destino-capa {
    margin-bottom: clamp(2rem, 6cqi, 4rem);
}

.mj-destino-chamada {
    margin: 0;
    max-width: 22ch;

    /* Contra a viuva. A peca quebra a chamada em duas linhas cheias, e a
       largura fluida daqui deixava "varejo" sozinho na terceira. O balance
       reparte as linhas; onde nao existe, a quebra normal continua valendo. */
    text-wrap: balance;
    font-size: clamp(1.7rem, 4.4cqi + 0.5rem, 3.5rem);
    font-style: italic;
    font-weight: 300;
    line-height: 1.05;
    letter-spacing: -0.015em;
    color: #fff;
}

.mj-destino-chamada b {
    font-weight: 700;
}

/* --------------------------------------------------------------------------
   24.2 Texto corrido
   -------------------------------------------------------------------------- */
.mj-destino-bloco {
    display: grid;
    gap: clamp(1.75rem, 5cqi, 3.5rem);
    align-items: center;
    margin-top: clamp(2.5rem, 7cqi, 5.5rem);
}

.mj-destino-texto p {
    margin: 0 0 1.05em;
    max-width: 46ch;
    font-size: clamp(0.95rem, 0.85cqi + 0.78rem, 1.08rem);
    line-height: 1.62;
}

.mj-destino-texto p:last-child {
    margin-bottom: 0;
}

.mj-destino-texto b {
    font-weight: 700;
}

.mj-destino-abertura {
    font-weight: 700;
}

/* O <b> vira linha propria: e a quebra da peca ("Chile:" em cima, "o palco da
   conquista" embaixo). Titulo sem <b> - o do terceiro bloco - nao tem o que
   quebrar e segue inteiro. */
.mj-destino-titulo {
    margin: 0 0 1.1rem;
    max-width: 17ch;
    font-size: clamp(1.35rem, 2.6cqi + 0.55rem, 2.3rem);
    font-style: italic;
    font-weight: 300;
    line-height: 1.1;
    letter-spacing: -0.01em;
    color: #fff;
}

.mj-destino-titulo b {
    display: block;
    font-weight: 700;
}

/* --------------------------------------------------------------------------
   24.3 A gema
   O padding da caixa da arte e a folga por onde os brilhos passam da pedra:
   eles sao posicionados contra ESTA caixa, e nao contra a gema, entao ficam
   sempre dentro do cartaz por mais estreita que seja a tela.
   -------------------------------------------------------------------------- */
.mj-destino-arte {
    position: relative;
    padding: 9% 7%;

    /* Teto para a coluna unica: num monitor largo, sem @container, a gema
       sozinha encheria a tela inteira. O conjunto de tres tem o teto dele,
       menor, na 24.5.

       O width: 100% NAO e redundante com o stretch do grid. Item de grid com
       margem auto no eixo inline NAO estica: as margens comem a folga e a
       caixa cai para fit-content. Sem ele a gema nascia com zero de largura e
       a coluna ficava vazia, com os brilhos do tamanho de um til. */
    width: 100%;
    max-width: 34rem;
    margin-inline: auto;
}

.mj-gema {
    position: relative;
    margin: 0;
    aspect-ratio: var(--gema-proporcao);
    background: var(--gema-preto);
    clip-path: var(--gema-faceta);
}

.mj-gema-foto {
    position: absolute;
    left: var(--gema-janela-x);
    top: var(--gema-janela-y);
    width: var(--gema-janela-larg);
    height: var(--gema-janela-alt);
    object-fit: cover;
    clip-path: var(--gema-foto);
}

/* --------------------------------------------------------------------------
   24.4 O brilho
   -------------------------------------------------------------------------- */
.mj-brilho {
    position: absolute;
    z-index: 4;
    width: 30%;
    pointer-events: none;
}

.mj-brilho-borda {
    fill: #fff;
}

/* O miolo e o vermelho CHEIO da marca. Contra o fundo escurecido ele acende,
   que e o efeito da peca impressa - ali o miolo tambem e mais claro que o
   papel em volta. */
.mj-brilho-miolo {
    fill: var(--brand);
}

.mj-brilho--g {
    width: 44%;
}

.mj-brilho--m {
    width: 30%;
}

.mj-brilho--p {
    width: 20%;
}

.mj-brilho--acima-esq {
    left: 0;
    top: 0;
}

.mj-brilho--acima-dir {
    right: 0;
    top: 0;
}

.mj-brilho--abaixo-esq {
    left: 8%;
    bottom: 0;
}

.mj-brilho--meio-esq {
    left: 0;
    top: 36%;
}

/* --------------------------------------------------------------------------
   24.5 As tres gemas encavaladas
   Posicao e tamanho sao os do desenho, em porcentagem da caixa do conjunto
   (401x545 no artboard original) - e por isso o conjunto escala inteiro, sem
   breakpoint, ate a largura de um celular.

   A ordem de empilhamento tambem e a da peca: a cordilheira atras, a bandeira
   na frente.
   -------------------------------------------------------------------------- */
.mj-destino-cluster {
    position: relative;
    aspect-ratio: 401 / 545;
    width: 100%;
    max-width: 26rem;
    margin-inline: auto;
    padding: 0;
}

.mj-destino-cluster .mj-gema {
    position: absolute;
}

.mj-gema--cordilheira {
    left: 17.2%;
    top: 0;
    width: 82.8%;
    z-index: 1;
}

.mj-gema--centro {
    left: 3.1%;
    top: 48.9%;
    width: 84.2%;
    z-index: 2;
}

.mj-gema--bandeira {
    left: 0;
    top: 24.2%;
    width: 67.2%;
    z-index: 3;
}

/* Dentro do conjunto os brilhos se penduram nos cantos da composicao, e nao
   nos de uma gema. */
.mj-destino-cluster .mj-brilho--acima-dir {
    right: -2%;
    top: -4%;
}

.mj-destino-cluster .mj-brilho--meio-esq {
    left: -5%;
    top: 26%;
}

/* --------------------------------------------------------------------------
   24.6 Rodape: por onde se anda ate o premio
   -------------------------------------------------------------------------- */
.mj-destino-rodape {
    margin-top: clamp(2.5rem, 7cqi, 5.5rem);
    padding-top: clamp(1.25rem, 3cqi, 2rem);
    border-top: 1px solid rgba(255, 255, 255, 0.28);
}

.mj-destino-rodape-titulo {
    margin: 0 0 0.5rem;
    font-size: 1.05rem;
    font-weight: 700;
    color: #fff;
}

.mj-destino-rodape p {
    margin: 0 0 1rem;
    max-width: 52ch;
    font-size: 0.95rem;
    line-height: 1.6;
}

.mj-destino-links {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 1.75rem;
}

/* Prefixar com o pai ja vence o `a { color: var(--brand) }` da secao 2, sem
   !important. */
.mj-destino-links a {
    color: #fff;
    font-weight: 700;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.3em;
}

.mj-destino-links a:hover,
.mj-destino-links a:focus {
    color: #fff;
    text-decoration-thickness: 2px;
}

.mj-destino-links a:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 3px;
    border-radius: 2px;
}

/* --------------------------------------------------------------------------
   24.7 Duas colunas
   O ponto e 720px de CONTAINER: abaixo disso a coluna de texto passaria dos
   30ch e o diamante viraria um selo.
   -------------------------------------------------------------------------- */
@container (min-width: 720px) {

    .mj-destino-bloco {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    }

    /* O conjunto de tres e mais alto que largo: sozinho numa coluna de metade
       da tela ele empurraria o texto para uma tira. */
    .mj-destino-bloco--arte-primeiro {
        grid-template-columns: minmax(0, 0.82fr) minmax(0, 1fr);
    }

}
