/*
    Identidade CombatOS na web — as MESMAS cores e a mesma fonte do app.

    Os valores nao foram escolhidos aqui: sao copia literal de
    android/.../ui/theme/Theme.kt. Se um dia mudarem la, mudam aqui. Duas
    paletas parecidas mas diferentes e pior do que duas obviamente distintas —
    o usuario percebe que "algo esta errado" sem saber dizer o que.
*/

:root {
    /* Marca */
    --combat-red: #E3242B;
    --combat-red-dark: #B0121B;
    --combat-black: #000000;

    /*
        ESCADA DE SUPERFICIE — quatro degraus, nao dois.

        A pagina era #000000 puro com UM nivel de superficie por cima. Preto puro
        contra texto claro produz halacao (o texto parece vibrar na borda), e com
        um degrau so nao ha como dizer "isto esta acima daquilo" a nao ser com
        borda — o que deixa tudo parecendo recortado com tesoura.

        Produto que nasce escuro nao usa preto: usa cinza muito escuro e degraus
        de elevacao. O fundo desce para #0B0B0C, a superficie sobe conforme o
        elemento se afasta do papel.
    */
    --combat-fundo: #0B0B0C;          /* a pagina */
    --combat-surface: #16161A;        /* cartao, barra, lateral */
    --combat-surface-variant: #1F1F25; /* hover, campo, disco de icone */
    --combat-elevado: #26262D;        /* menu suspenso, modal */

    --combat-outline: #2A2A32;
    --combat-outline-forte: #3A3A45;

    --combat-white: #F7F7F7;
    --combat-gray: #A5A5A5;

    /*
        Cores SEMANTICAS, separadas do vermelho da marca de proposito.
        A regra do app vale aqui: vermelho so em identidade e acao primaria;
        estado usa estas. Quando tudo grita, nada e urgente.
    */
    --combat-success: #30D158;
    --combat-warning: #FF9F0A;
    --combat-danger: #FF453A;
    --combat-info: #0A84FF;

    /*
        RAIO DE CANTO — quatro valores, cada um com um trabalho.

        Havia SETE (3, 6, 7, 8, 0.5rem, 10, 12px) espalhados pelo arquivo, cada
        componente escolhendo o seu. Ninguem nota um raio isolado; todo mundo
        nota vinte deles discordando, e o que se le e "montado as pressas".
    */
    --raio-xs: 3px;     /* marca de faixa, barra de progresso */
    --raio-sm: 6px;     /* controle: botao, campo, chip, menu */
    --raio-md: 10px;    /* bloco: cartao, foto, modal, vitrine */
    --raio-redondo: 50%;
    --raio-pilula: 999px;

    /*
        ELEVACAO. Sombra no escuro nao e "escurecer embaixo" — o fundo ja e
        escuro. E um halo preto MAIS denso que o fundo, com um fio de luz no topo
        que simula a quina do objeto pegando a luz do ambiente.
    */
    --sombra-1: 0 1px 2px rgba(0, 0, 0, 0.5);
    --sombra-2: 0 2px 8px rgba(0, 0, 0, 0.55), 0 1px 2px rgba(0, 0, 0, 0.4);
    --sombra-3: 0 12px 32px rgba(0, 0, 0, 0.65), 0 2px 8px rgba(0, 0, 0, 0.45);

    /*
        MOVIMENTO. Tres duracoes e duas curvas, e nada mais.

        120ms para o que responde ao dedo (hover, foco) — acima disso a interface
        parece molhada. 200ms para o que entra em cena. 320ms so para o que
        atravessa a tela.

        A curva de SAIDA e quase-elastica de proposito: o elemento chega rapido e
        assenta. Linear parece maquina; isto parece objeto com peso.
    */
    --mov-rapido: 120ms;
    --mov-medio: 200ms;
    --mov-lento: 320ms;
    --mov-padrao: cubic-bezier(0.4, 0, 0.2, 1);
    --mov-saida: cubic-bezier(0.16, 1, 0.3, 1);

    /*
        ESPACAMENTO — a mesma escala do Spacing.kt do app.

        A web vinha escolhendo utilitario do Bootstrap caso a caso: 68 mb-1,
        40 mb-3, 23 mb-2, 22 mb-4, 20 mt-3. Cada tela com o seu ritmo, o que da
        exatamente a sensacao de telas feitas por pessoas diferentes.
    */
    --esp-xs: 0.25rem;
    --esp-sm: 0.5rem;
    --esp-md: 0.75rem;
    --esp-lg: 1rem;
    --esp-xl: 1.5rem;
    --esp-2xl: 2rem;
}

/*
    Bebas Neue: a fonte de display da marca. Vai em NUMERO e titulo curto.
    Nunca em frase — condensada em caixa alta e otima em "R$ 300" e pessima
    em duas linhas de texto.
*/
@font-face {
    font-family: 'Bebas Neue';
    src: url('../fonts/bebas-neue.ttf') format('truetype');
    font-display: swap;
}

html, body {
    background-color: var(--combat-fundo);
    color: var(--combat-white);
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

h1, h2, h3 {
    font-family: 'Bebas Neue', sans-serif;
    letter-spacing: 0.04em;
}

/* Numero de destaque: valor do mes, total do caixa, contagem. */
.combat-numero {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 2rem;
    letter-spacing: 0.02em;
    line-height: 1.1;
}

/* Rotulo de secao: cinza, maiusculo, espacado. NUNCA vermelho. */
.combat-rotulo {
    color: var(--combat-gray);
    text-transform: uppercase;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.1em;
}

/* ---- Bootstrap reescrito para a paleta ---- */

.btn-danger,
.btn-primary {
    background-color: var(--combat-red);
    border-color: var(--combat-red);
    color: #fff;
}

.btn-danger:hover,
.btn-primary:hover {
    background-color: var(--combat-red-dark);
    border-color: var(--combat-red-dark);
}

.card,
.list-group-item {
    background-color: var(--combat-surface);
    border: 1px solid var(--combat-outline);
    color: var(--combat-white);
}

.form-control,
.form-select {
    background-color: var(--combat-surface-variant);
    border-color: var(--combat-outline);
    color: var(--combat-white);
}

.form-control:focus,
.form-select:focus {
    background-color: var(--combat-surface-variant);
    border-color: var(--combat-red);
    color: var(--combat-white);
    box-shadow: 0 0 0 0.2rem rgba(227, 36, 43, 0.25);
}

.form-control::placeholder {
    color: var(--combat-gray);
}

/*
    Tabela: a estrutura principal da web, no lugar da lista do app.

    As variaveis --bs-table-* sao OBRIGATORIAS. O Bootstrap 5 nao pinta a celula
    com "background-color" direto: ele usa essas variaveis internas, e por isso
    uma regra .table { background: ... } e simplesmente ignorada. Foi assim que a
    tabela ficou BRANCA no meio de um painel preto.
*/
.table {
    --bs-table-bg: transparent;
    --bs-table-color: var(--combat-white);
    --bs-table-border-color: var(--combat-outline);
    --bs-table-striped-bg: var(--combat-surface-variant);
    --bs-table-striped-color: var(--combat-white);
    --bs-table-hover-bg: var(--combat-surface-variant);
    --bs-table-hover-color: var(--combat-white);

    color: var(--combat-white);
    border-color: var(--combat-outline);
    margin-bottom: 0;
}

.table > thead th {
    background-color: transparent;
    color: var(--combat-gray);
    text-transform: uppercase;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    border-bottom: 1px solid var(--combat-outline);
    padding: 0.85rem 1rem;
}

.table > tbody > tr > td {
    background-color: transparent;
    border-color: rgba(58, 58, 60, 0.6);
    padding: 0.85rem 1rem;
    vertical-align: middle;
}

/* Ultima linha sem divisoria: a borda do card ja fecha o bloco. */
.table > tbody > tr:last-child > td {
    border-bottom: none;
}

/* Numero em tabela: tabular para as casas alinharem coluna a coluna. */
.combat-valor {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}

/* ---- Estado (as mesmas semanticas do app) ---- */

.combat-sucesso { color: var(--combat-success); }
.combat-atencao { color: var(--combat-warning); }
.combat-perigo  { color: var(--combat-danger); }

.combat-chip {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: var(--raio-sm);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.combat-chip-sucesso { background: rgba(48, 209, 88, 0.16);  color: var(--combat-success); }
.combat-chip-atencao { background: rgba(255, 159, 10, 0.16); color: var(--combat-warning); }
.combat-chip-perigo  { background: rgba(255, 69, 58, 0.16);  color: var(--combat-danger); }
.combat-chip-marca   { background: rgba(227, 36, 43, 0.16);  color: var(--combat-red); }
.combat-chip-neutro  { background: rgba(165, 165, 165, 0.16); color: var(--combat-gray); }

/* ---- Layout ---- */

.page { position: relative; display: flex; flex-direction: column; }

main { flex: 1; }

.sidebar {
    background-color: var(--combat-surface);
    border-right: 1px solid var(--combat-outline);
}

.top-row {
    background-color: var(--combat-surface);
    border-bottom: 1px solid var(--combat-outline);
    justify-content: flex-end;
    height: 3.5rem;
    display: flex;
    align-items: center;
}

.nav-scrollable a,
.navbar-brand {
    color: var(--combat-white);
}

/*
   O logo da barra lateral.

   A classe existia no NavMenu e NAO tinha regra nenhuma no CSS: a imagem
   renderizava no tamanho natural do arquivo. Com o arquivo antigo de 780px de
   largura isso empurrava a barra de 250px, e o que segurava o estrago era o
   proprio Bootstrap.

   A LARGURA e a medida que manda, e nao a altura: o recorte tem proporcao ~5:1
   e quem limita e a barra lateral. Pedir altura deixaria a largura livre para
   estourar de novo no dia em que alguem trocar o arquivo.
*/
.combat-logo {
    width: 100%;
    max-width: 160px;
    height: auto;
    display: block;
}

.nav-item ::deep .nav-link.active {
    background-color: rgba(227, 36, 43, 0.15);
    color: var(--combat-white);
    border-left: 3px solid var(--combat-red);
}

.nav-item ::deep .nav-link:hover {
    background-color: var(--combat-surface-variant);
    color: var(--combat-white);
}

@media (min-width: 641px) {
    .page { flex-direction: row; }

    .sidebar {
        width: 250px;
        height: 100vh;
        position: sticky;
        top: 0;
    }

    .top-row { position: sticky; top: 0; z-index: 1; }
}

/* ---- Carregamento e erro ---- */

.loading-progress circle {
    fill: none;
    stroke: var(--combat-outline);
    stroke-width: 0.6rem;
    transform-origin: 50% 50%;
    transform: rotate(-90deg);
}

.loading-progress circle:last-child {
    stroke: var(--combat-red);
    stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
    transition: stroke-dasharray 0.05s ease-in-out;
}

.loading-progress-text {
    position: absolute;
    text-align: center;
    font-family: 'Bebas Neue', sans-serif;
    inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
    color: var(--combat-white);
}

.loading-progress-text:after {
    content: var(--blazor-load-percentage-text, "Carregando");
}

#blazor-error-ui {
    background: var(--combat-danger);
    color: #fff;
    bottom: 0;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}


/* ==========================================================================
   Identidade — o que faz a tela parecer CombatOS e nao um painel escuro
   qualquer. Sao tres recursos, usados com parcimonia:
   ========================================================================== */

/*
    1. FAIXA DA MARCA na lateral do bloco principal.

    E o mesmo gesto do app, onde a linha vermelha marca o que importa. Aqui ela
    da ao bloco de dinheiro um peso que borda cinza nenhuma daria — e sem pintar
    o cartao inteiro de vermelho, que gritaria.
*/
.combat-destaque {
    border-left: 3px solid var(--combat-red);
}

/*
    2. RESPIRO MENOR nos cartoes de numero.

    O padrao do Bootstrap deixa muito ar embaixo de um numero curto, e o cartao
    fica com cara de inacabado. Altura igual entre eles tambem importa: quatro
    blocos de alturas diferentes lado a lado leem como desalinhamento, nao como
    variedade.
*/
.combat-bloco {
    background-color: var(--combat-surface);
    border: 1px solid var(--combat-outline);
    border-radius: var(--raio-md);
    padding: 1.1rem 1.25rem;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 108px;
}

.combat-bloco:hover {
    border-color: rgba(227, 36, 43, 0.4);
}

/*
    3. TITULO DE TELA na fonte de display.

    Bebas em caixa alta e a assinatura visual do CombatOS. Usada no titulo da
    pagina, ela diz de que produto e a tela antes de qualquer texto ser lido.
*/
.combat-titulo {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 2rem;
    letter-spacing: 0.06em;
    line-height: 1;
    margin: 0;
}

/* Numero grande de destaque — o "saldo". */
.combat-numero-hero {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 3.5rem;
    line-height: 1;
    letter-spacing: 0.01em;
}

/* Barra de progresso do mes, mais fina e sem cantos redondos exagerados. */
.combat-barra {
    height: 6px;
    background-color: var(--combat-outline);
    border-radius: var(--raio-xs);
    overflow: hidden;
}

.combat-barra > div {
    height: 100%;
    background-color: var(--combat-success);
    border-radius: var(--raio-xs);
}

/* Dentro de linha de tabela a barra encolhe: ali ela e coluna, nao destaque. */
.combat-barra-fina {
    height: 4px;
}


/* ==========================================================================
   Foto de aluno e de produto
   ========================================================================== */

.combat-foto {
    width: 96px;
    height: 96px;
    border-radius: var(--raio-md);
    background-color: var(--combat-surface-variant);
    border: 1px solid var(--combat-outline);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.combat-foto img {
    width: 100%;
    height: 100%;

    /* cover, e nao contain: foto de rosto em proporcao qualquer preenche o
       quadrado sem tarja preta nas laterais. */
    object-fit: cover;
}

/*
    Sem foto, as INICIAIS.

    Melhor do que um icone de silhueta repetido em toda linha: as letras mudam
    por pessoa, entao a lista continua tendo pontos de referencia visual mesmo
    sem nenhuma foto cadastrada.
*/
.combat-foto-vazia {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 1.6rem;
    color: var(--combat-gray);
    letter-spacing: 0.05em;
}

.combat-foto-mini {
    width: 38px;
    height: 38px;
    border-radius: var(--raio-sm);
}

.combat-foto-mini .combat-foto-vazia {
    font-size: 0.85rem;
}

/*
    O <input type="file"> nativo nao aceita estilo e fica destoando de tudo.
    Escondido, quem abre o dialogo e o <label for=""> — que e um botao de
    verdade e obedece ao CSS.

    display:none quebraria o foco por teclado; a tecnica abaixo mantem o campo
    acessivel e invisivel.
*/
.combat-arquivo {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Acao destrutiva discreta: texto vermelho, sem peso de botao. */
.combat-botao-texto-perigo {
    background: none;
    border: none;
    color: var(--combat-danger);
    padding: 0;
    text-align: left;
}

.combat-botao-texto-perigo:hover {
    color: var(--combat-danger);
    text-decoration: underline;
}


/*
    Largura maxima da area de conteudo.

    Sem isto, num monitor de 1920px a tabela estica para ~1600px: o nome do aluno
    fica num extremo, o botao no outro, e a linha fica dificil de seguir com o
    olho. Limite de leitura confortavel vale para tabela tambem — esticar nao e
    "aproveitar a tela", e degradar.
*/
.combat-conteudo {
    max-width: 1400px;

    /* Centralizado. Sem isto o limite existia mas o conteudo ficava colado na
       esquerda, com um vazio do tamanho de meia tela sobrando na direita — que
       e pior do que nao ter limite nenhum. */
    margin-inline: auto;
}

/*
    Bloco de numero em altura FIXA.

    Quatro cartoes lado a lado com alturas diferentes leem como desalinhamento.
    A altura fixa vem do caso com subtitulo; quem nao tem subtitulo sobra espaco
    embaixo, e isso e melhor do que a fila de cima ficar mais curta que a de baixo.
*/
.combat-bloco {
    min-height: 118px;
}

/* Rodape da tabela: contagem e link para o mes inteiro. */
.combat-rodape-tabela {
    border-top: 1px solid var(--combat-outline);
    padding: 0.75rem 1rem;
    font-size: 0.85rem;
}


/* ==========================================================================
   Financeiro
   ========================================================================== */

/*
    Faixa AMBAR, irma da vermelha do .combat-destaque.

    Fiado em aberto e dinheiro que saiu e nao voltou: merece marca. Nao usa
    vermelho porque vermelho aqui e marca e acao primaria — estado tem as cores
    semanticas, senao tudo grita e nada e urgente.
*/
.combat-destaque-atencao {
    border-left: 3px solid var(--combat-warning);
}

/* Navegacao de competencia: seta, nome, seta. */
.combat-competencia {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

/*
    A largura minima existe para a barra nao PULAR ao trocar de mes: "MAIO" e
    "SETEMBRO" tem tamanhos bem diferentes, e sem a reserva as setas dancariam a
    cada clique.

    Mas 190px era reserva demais — sobrava um vao no meio e as setas paravam de
    parecer parte do mesmo controle. 150px cobre o mes mais longo com folga
    pequena.
*/
.combat-competencia-nome {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 1.15rem;
    letter-spacing: 0.08em;
    color: var(--combat-white);
    min-width: 150px;
    text-align: center;
}

.combat-competencia-seta {
    background: none;
    border: 1px solid var(--combat-outline);
    border-radius: var(--raio-sm);
    color: var(--combat-white);
    width: 2rem;
    height: 2rem;
    line-height: 1;
    font-size: 1.25rem;
    cursor: pointer;
}

.combat-competencia-seta:hover:not(:disabled) {
    border-color: var(--combat-red);
    background-color: var(--combat-surface-variant);
}

/*
    Desabilitado com opacidade, e nao com fundo cinza.

    A lajota cinza foi um defeito real no app: o botao desligado ficava MAIS
    visivel que o ligado. Aqui ele simplesmente recua.
*/
.combat-competencia-seta:disabled {
    opacity: 0.3;
    cursor: default;
}

/* ---- Filtros ---- */

.combat-filtros {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.combat-filtro {
    background: none;
    border: 1px solid var(--combat-outline);
    border-radius: var(--raio-pilula);
    color: var(--combat-gray);
    padding: 0.35rem 0.9rem;
    font-size: 0.85rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
}

.combat-filtro:hover {
    color: var(--combat-white);
    border-color: var(--combat-gray);
}

.combat-filtro-ativo,
.combat-filtro-ativo:hover {
    background-color: var(--combat-red);
    border-color: var(--combat-red);
    color: #fff;
}

/*
    A contagem dentro do chip responde "vale a pena clicar?" antes do clique.
    Filtro que abre numa tela vazia e trabalho jogado fora.
*/
.combat-filtro-conta {
    font-variant-numeric: tabular-nums;
    font-size: 0.75rem;
    opacity: 0.75;
}

/* Nao pode esticar sozinha ate o outro lado da barra da secao. */
.combat-busca {
    width: 240px;
    max-width: 100%;
}

/* Coluna de acao: botao e menu na mesma linha, colados a direita. */
.combat-acoes {
    white-space: nowrap;
}

.combat-acoes > * {
    vertical-align: middle;
}

/*
    Respiro entre a acao primaria e o menu.

    Colados, "Receber" e os tres pontos leem como um controle so, e o clique
    erra o alvo. Meio rem separa sem afastar.
*/
.combat-acoes > * + * {
    margin-left: 0.5rem;
}

/* Divisoria fina dentro de um cartao, para separar dois blocos de numero. */
.combat-divisoria {
    height: 1px;
    background-color: var(--combat-outline);
}

/*
    Faixa do aluno: um quadradinho da cor + o nome.

    A cor sozinha nao serve — branca e cinza somem no fundo escuro, e daltonismo
    torna azul e roxa indistinguiveis. O nome escrito e o dado; a cor so ajuda a
    varrer a lista com o olho.
*/
.combat-faixa {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
}

.combat-faixa-marca {
    width: 12px;
    height: 12px;
    border-radius: var(--raio-xs);

    /* Contorno claro para faixa preta nao sumir no cartao escuro. */
    border: 1px solid rgba(247, 247, 247, 0.35);
    flex-shrink: 0;
}

/*
    Linha de quem ja tem presenca hoje.

    Verde MUITO diluido, com a faixa a esquerda. Na chamada o professor corre o
    olho de cima a baixo procurando quem falta — o estado precisa ser legivel a
    meio metro do monitor, sem que a lista vire um semaforo.
*/
.combat-linha-presente > td:first-child {
    box-shadow: inset 3px 0 0 var(--combat-success);
}

.combat-linha-presente > td {
    background-color: rgba(48, 209, 88, 0.07) !important;
}

/* Campo de numero: casas alinhadas e digitacao a direita, como em planilha. */
.combat-campo-numero {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* ---- Fiado ---- */

.combat-fiado {
    border-top: 1px solid var(--combat-outline);
}

.combat-fiado-linha {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem 0;
    border-bottom: 1px solid rgba(58, 58, 60, 0.6);
}

.combat-fiado-linha:last-child {
    border-bottom: none;
}


/* ==========================================================================
   Aviso de resultado

   Fica no topo do conteudo, nao flutuando sobre a tabela: o dono acabou de
   clicar num botao e o olho ja esta na tela. Aviso que some sozinho depois de
   tres segundos e aviso que a pessoa perde quando desviou o olhar.
   ========================================================================== */

.combat-aviso {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    border-radius: var(--raio-md);
    padding: 0.7rem 1rem;
    font-size: 0.9rem;
}

.combat-aviso-sucesso {
    background: rgba(48, 209, 88, 0.12);
    border: 1px solid rgba(48, 209, 88, 0.35);
    color: var(--combat-success);
}

.combat-aviso-perigo {
    background: rgba(255, 69, 58, 0.12);
    border: 1px solid rgba(255, 69, 58, 0.35);
    color: var(--combat-danger);
}

/*
   Nem sucesso nem erro: "esta funcionando de um jeito que voce talvez nao
   espere". Hoje serve ao modo simulacao do envio automatico, onde tudo esta
   configurado e nada sai — dizer isso em verde seria mentira e em vermelho
   seria alarme falso.
*/
.combat-aviso-alerta {
    background: rgba(255, 159, 10, 0.12);
    border: 1px solid rgba(255, 159, 10, 0.35);
    color: var(--combat-warning);
}

.combat-aviso-fechar {
    background: none;
    border: none;
    color: inherit;
    font-size: 1.25rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.7;
}

.combat-aviso-fechar:hover {
    opacity: 1;
}


/* ==========================================================================
   Menu de tres pontos

   Sem Bootstrap JS. O "veu" e uma camada invisivel sobre a tela inteira: e o
   que faz o clique em qualquer outro lugar fechar o menu. Sem ele, sobram dois
   menus abertos e o dono clica em "Cancelar cobranca" na linha errada.
   ========================================================================== */

.combat-veu {
    position: fixed;
    inset: 0;
    z-index: 1040;
}

.combat-menu-ancora {
    position: relative;
    display: inline-block;
}

.combat-menu-botao {
    background: none;
    border: none;
    color: var(--combat-gray);
    font-size: 1.3rem;
    line-height: 1;
    padding: 0.15rem 0.5rem;
    border-radius: var(--raio-sm);
    cursor: pointer;
}

.combat-menu-botao:hover {
    color: var(--combat-white);
    background-color: var(--combat-surface-variant);
}

.combat-menu-painel {
    position: absolute;
    right: 0;
    top: calc(100% + 4px);
    z-index: 1050;
    min-width: 190px;
    background-color: var(--combat-surface-variant);
    border: 1px solid var(--combat-outline);
    border-radius: var(--raio-md);
    padding: 0.3rem 0;
    box-shadow: 0 12px 28px rgba(0, 0, 0, 0.6);
    text-align: left;
}

.combat-menu-item {
    display: block;
    width: 100%;
    background: none;
    border: none;
    color: var(--combat-white);
    text-align: left;
    padding: 0.5rem 0.9rem;
    font-size: 0.9rem;
    cursor: pointer;
    white-space: nowrap;
}

.combat-menu-item:hover:not(:disabled) {
    background-color: rgba(227, 36, 43, 0.15);
}

.combat-menu-item-perigo {
    color: var(--combat-danger);
}

.combat-menu-item:disabled {
    opacity: 0.4;
    cursor: default;
}


/* ==========================================================================
   Janela sobreposta
   ========================================================================== */

.combat-modal-fundo {
    position: fixed;
    inset: 0;
    z-index: 1060;
    background: rgba(0, 0, 0, 0.72);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
}

.combat-modal {
    background-color: var(--combat-surface);
    border: 1px solid var(--combat-outline);
    border-radius: var(--raio-md);
    width: 100%;

    /*
        Altura limitada com rolagem SO no corpo: em monitor de notebook a lista
        de mensalidades passa da tela, e sem isto o botao Fechar ficaria abaixo
        da dobra, dentro de uma janela que nao rola.
    */
    max-height: calc(100vh - 3rem);
    display: flex;
    flex-direction: column;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.7);
}

.combat-modal-estreito { max-width: 420px; }
.combat-modal-medio    { max-width: 680px; }
.combat-modal-largo    { max-width: 900px; }

.combat-modal-topo {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding: 1.25rem 1.5rem;
    border-bottom: 1px solid var(--combat-outline);
}

.combat-modal-topo .combat-titulo {
    font-size: 1.5rem;
}

.combat-modal-corpo {
    padding: 1.5rem;
    overflow-y: auto;
}

.combat-modal-rodape {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    padding: 1rem 1.5rem;
    border-top: 1px solid var(--combat-outline);
}

.combat-modal-fechar {
    background: none;
    border: none;
    color: var(--combat-gray);
    font-size: 1.6rem;
    line-height: 1;
    cursor: pointer;
}

.combat-modal-fechar:hover {
    color: var(--combat-white);
}

/* Lista dentro de janela: rola ela, nao a janela inteira. */
.combat-lista-rolavel {
    max-height: 46vh;
    overflow-y: auto;
}


/* ==========================================================================
   PIX
   ========================================================================== */

/*
    Fundo BRANCO com folga em volta, mesmo num painel preto.

    Nao e escolha estetica: leitor de QR espera modulo escuro sobre fundo claro,
    e a margem clara ("zona de silencio") faz parte da especificacao. QR
    invertido ou encostado na borda falha em boa parte dos aplicativos de banco,
    e falhar aqui significa o aluno na frente do dono sem conseguir pagar.
*/
.combat-qr {
    background: #FFFFFF;
    border-radius: var(--raio-md);
    padding: 10px;
    display: inline-block;
    line-height: 0;
}

.combat-qr svg {
    width: 100%;
    height: auto;
    display: block;
}

/* O copia e cola: fonte de largura fixa e quebra por caractere. */
.combat-pix-codigo {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.75rem;
    line-height: 1.4;
    word-break: break-all;
    resize: none;
}


/* ==========================================================================
   Cartao de arte marcial

   A MESMA ilustracao do app, como fundo. A decisao de por a arte atras do nome
   ja foi tomada la e o motivo vale aqui: com a imagem em cima e o nome num
   rodape, o nome — que e o que se clica — vira legenda da figura.
   ========================================================================== */

.combat-arte-link {
    display: block;
    text-decoration: none;
    color: inherit;
}

.combat-arte {
    position: relative;
    height: 120px;
    border-radius: var(--raio-md);
    overflow: hidden;
    background-color: var(--combat-surface);
    border: 1px solid var(--combat-outline);
    transition: border-color 0.15s ease, transform 0.15s ease;
}

.combat-arte-link:hover .combat-arte {
    border-color: var(--combat-red);

    /* Dois pixels. O suficiente para o cartao responder ao mouse sem a pagina
       inteira parecer que balanca. */
    transform: translateY(-2px);
}

/* Brilho vermelho no canto, para o cartao nao ser so preto. */
.combat-arte-brilho {
    position: absolute;
    inset: 0;
    background: radial-gradient(circle at 15% 30%,
        rgba(227, 36, 43, 0.16), transparent 62%);
}

/*
    A ilustracao ja vem em cor unica e fundo transparente — o que sobrou foi a
    silhueta. Deslocada e sangrando pela borda, ela vira TEXTURA de fundo em vez
    de figurinha centralizada.
*/
.combat-arte-imagem {
    position: absolute;
    right: -6px;
    bottom: 0;
    height: 86%;
    width: auto;
    opacity: 0.30;
    pointer-events: none;
}

.combat-arte-conteudo {
    position: relative;
    height: 100%;
    padding: 1rem 1.1rem;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
}

.combat-arte-nome {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 1.5rem;
    letter-spacing: 0.04em;
    line-height: 1;
    color: var(--combat-white);
}

.combat-arte-detalhe {
    color: var(--combat-gray);
    font-size: 0.8rem;
    margin-top: 0.15rem;
}

/* Bloco de numero com a faixa da marca — para o primeiro do Inicio. */
.combat-bloco-destaque {
    border-left: 3px solid var(--combat-red);
}

/* Linha de alerta (graduacao, aniversario) dentro de um cartao. */
.combat-linha-alerta {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.85rem 1rem;
    border-bottom: 1px solid rgba(58, 58, 60, 0.6);
}

.combat-linha-alerta:last-child {
    border-bottom: none;
}


/* ==========================================================================
   Vitrine da loja
   ========================================================================== */

/*
    Grade que se adapta sozinha.

    auto-fill com minmax faz o navegador decidir quantas colunas cabem — 6 num
    monitor largo, 2 num notebook — sem uma linha de media query. Cada cartao
    nunca fica menor que 168px, que e onde a foto para de ajudar a reconhecer o
    produto.
*/
.combat-vitrine {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
    gap: 0.85rem;
}

/*
    Destaques rolam na horizontal.

    scroll-snap prende o cartao na borda ao soltar o dedo ou a roda: rolagem
    livre para a metade de um produto e a sensacao de que a lista escapou.
*/
.combat-carrossel {
    display: flex;
    gap: 0.85rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    padding-bottom: 0.5rem;
}

.combat-carrossel > * {
    scroll-snap-align: start;
    flex: 0 0 200px;
}

.combat-carrossel::-webkit-scrollbar {
    height: 6px;
}

.combat-carrossel::-webkit-scrollbar-thumb {
    background: var(--combat-outline);
    border-radius: var(--raio-xs);
}

.combat-vitrine-item {
    background-color: var(--combat-surface);
    border: 1px solid var(--combat-outline);
    border-radius: var(--raio-md);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    transition: border-color 0.15s ease;
}

.combat-vitrine-item:hover {
    border-color: rgba(227, 36, 43, 0.45);
}

.combat-vitrine-destaque {
    border-left: 3px solid var(--combat-red);
}

/* Fora de linha continua legivel, mas recua — nao e erro, e catalogo antigo. */
.combat-vitrine-inativo {
    opacity: 0.55;
}

.combat-vitrine-foto {
    position: relative;
    aspect-ratio: 1 / 1;
    background-color: var(--combat-surface-variant);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.combat-vitrine-foto img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.combat-vitrine-foto .combat-foto-vazia {
    font-size: 2.4rem;
}

/*
    O estado vai SOBRE a foto.

    Numa grade, procurar um chip embaixo de cada cartao e mais lento do que ver
    a etiqueta sempre no mesmo canto.
*/
.combat-vitrine-selo {
    position: absolute;
    top: 0.5rem;
    left: 0.5rem;
    padding: 0.1rem 0.5rem;
    border-radius: var(--raio-sm);
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.combat-vitrine-corpo {
    padding: 0.75rem;
    display: flex;
    flex-direction: column;
    flex: 1;
}

/*
    Nome em ate duas linhas, com reticencias.

    Sem o limite, "Camiseta oficial da equipe manga longa" empurraria o preco
    para baixo e a grade viraria um serrote de cartoes de alturas diferentes.
*/
.combat-vitrine-nome {
    font-size: 0.9rem;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: 2.25rem;
}

.combat-vitrine-preco {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 1.35rem;
    color: var(--combat-success);
    line-height: 1.2;
}

.combat-vitrine-corpo .combat-menu-ancora {
    flex-shrink: 0;
}


/* ==========================================================================
   Acabamento geral
   ========================================================================== */

/*
    Cartao com relevo discreto.

    Sombra em vez de so borda: no fundo preto, a borda de 1px sozinha faz o
    cartao parecer recortado com tesoura. A sombra da a ele a espessura que
    separa "bloco de conteudo" de "retangulo desenhado".
*/
.card {
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
    border-radius: var(--raio-md);
}

/* Bloco e cartao sao a MESMA familia: mesma borda, mesmo raio, mesma sombra.
   Conviviam com aparencias diferentes (raio 8 contra 10, um com sombra e outro
   sem) para cumprir a mesma funcao. */
.combat-bloco {
    transition: border-color 0.15s ease;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

/* Foco visivel na cor da marca — acessibilidade sem quebrar a identidade. */
.form-control:focus,
.form-select:focus,
.btn:focus-visible {
    box-shadow: 0 0 0 0.2rem rgba(227, 36, 43, 0.25);
    border-color: var(--combat-red);
}

.btn {
    border-radius: var(--raio-sm);
}

/* Linha de tabela responde ao mouse sem piscar. */
.table > tbody > tr {
    transition: background-color 0.12s ease;
}

/* ---- Turmas, cartilha e aula ---- */

/* Um horario da grade: dia em negrito, hora ao lado. */
.combat-horario {
    display: inline-flex;
    align-items: baseline;
    gap: 0.35rem;
    background-color: var(--combat-surface-variant);
    border: 1px solid var(--combat-outline);
    border-radius: var(--raio-sm);
    padding: 0.2rem 0.55rem;
    font-size: 0.8rem;
}

.combat-sequencia {
    border-top: 1px solid var(--combat-outline);
}

.combat-sequencia-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0;
    border-bottom: 1px solid rgba(58, 58, 60, 0.6);
}

/*
    O numero da sequencia em Bebas.

    A ORDEM e o conteudo da aula, nao decoracao: aquecimento antes de
    finalizacao. O numero grande deixa isso obvio de relance.
*/
.combat-sequencia-numero {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 1.1rem;
    color: var(--combat-red);
    min-width: 1.2rem;
    text-align: center;
}

/* Descricao da tecnica: duas linhas, o resto some. */
.combat-descricao {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.combat-link {
    color: var(--combat-red);
    text-decoration: none;
}

.combat-link:hover {
    text-decoration: underline;
}

/* ============================================================
   Menu de uma modalidade (/arte/{id})
   ============================================================

   Espelha o ModalityHomeScreen do app: UM destaque no topo — a chamada de
   hoje, que e a acao do dia — e o resto em linha com disco cinza.

   O disco e cinza, nao vermelho. Se os cinco icones fossem vermelhos, o
   cartao vermelho de verdade logo acima deixaria de saltar; a mesma decisao
   ja foi tomada no app e o motivo esta la. */


/* ---- O destaque ---- */

.combat-chamada-hoje {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 1.1rem 1.25rem;
    background-color: var(--combat-surface);
    border: 1px solid var(--combat-outline);

    /* Borda vermelha marca o cartao sem pintar o fundo inteiro: destaque que
       continua legivel no preto e nao vira bloco colorido no meio da pagina. */
    border-left: 3px solid var(--combat-red);
    border-radius: var(--raio-md);
    color: inherit;
    text-decoration: none;
    transition: border-color 0.15s ease, transform 0.15s ease;
}

.combat-chamada-hoje:hover {
    border-color: var(--combat-red);
    border-left-color: var(--combat-red);
    transform: translateY(-2px);
}

.combat-chamada-icone {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 44px;
    height: 44px;
    border-radius: var(--raio-redondo);
    background-color: rgba(227, 36, 43, 0.15);
    color: var(--combat-red);
}

.combat-chamada-corpo {
    flex: 1 1 auto;
    min-width: 0;
}

.combat-chamada-numeros {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
}

.combat-chamada-seta {
    color: var(--combat-gray);
    font-size: 1.5rem;
    line-height: 1;
}

/* ---- As linhas ---- */

.combat-navegacao {
    border-top: 1px solid var(--combat-outline);
}

.combat-navegacao-item {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.9rem 0.25rem;
    border-bottom: 1px solid var(--combat-outline);
    color: inherit;
    text-decoration: none;
    transition: background-color 0.12s ease;
}

.combat-navegacao-item:hover {
    background-color: var(--combat-surface);
}

.combat-navegacao-icone {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 40px;
    height: 40px;
    border-radius: var(--raio-redondo);
    background-color: var(--combat-surface-variant);
    color: var(--combat-gray);
}

.combat-navegacao-texto {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
}

.combat-navegacao-titulo {
    font-weight: 600;
}

.combat-navegacao-sub {
    color: var(--combat-gray);
    font-size: 0.85rem;

    /* Uma linha. "Grade da semana: dias, horarios e professor" quebrando em
       duas desalinha a altura das linhas e a lista perde o ritmo. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.combat-navegacao-seta {
    color: var(--combat-gray);
    font-size: 1.35rem;
    line-height: 1;
}

/* Bloco em foco: quem clicou em "Aula do dia" cai numa pagina que tem
   cartilha tambem, e precisa achar na hora o que veio fazer. */
.combat-em-foco {
    border-left: 3px solid var(--combat-red);
    padding-left: 0.85rem;
}

/* ============================================================
   Alertas (/alertas) e o sino do cabecalho
   ============================================================ */

.combat-linha-clicavel {
    color: inherit;
    text-decoration: none;
    transition: background-color 0.12s ease;
}

.combat-linha-clicavel:hover {
    background-color: var(--combat-surface-variant);
}

/* Disco do icone. Vermelho na graduacao — que e a acao — e cinza no
   aniversario, que e lembrete. Se os dois fossem vermelhos, nenhum seria. */
.combat-alerta-icone {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 34px;
    height: 34px;
    border-radius: var(--raio-redondo);
    background-color: rgba(227, 36, 43, 0.15);
    color: var(--combat-red);
}

.combat-alerta-icone-neutro {
    background-color: var(--combat-surface-variant);
    color: var(--combat-gray);
}

/* Sem isto o nome longo empurra a faixa e o chip para fora da linha em vez
   de encolher: min-width de item flex e auto, nao zero. */
.min-w-0 {
    min-width: 0;
}

.combat-sino {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: var(--raio-redondo);
    color: var(--combat-gray);
    text-decoration: none;
    transition: background-color 0.12s ease, color 0.12s ease;
}

.combat-sino:hover {
    background-color: var(--combat-surface);
    color: var(--combat-white);
}

/* ============================================================
   Cabecalho de pagina, dentro da barra superior
   ============================================================ */

.combat-cabecalho-texto {
    min-width: 0;
}

/*
    Titulo em fonte de TEXTO, nao em Bebas.

    A Bebas e a fonte do numero neste produto — presenca, faturamento, contagem.
    Gastando ela tambem no titulo de toda tela, o numero para de saltar; e em
    caixa alta a leitura vai para cartaz de academia em vez de painel de gestao.
*/
.combat-cabecalho-titulo {
    font-size: 1.05rem;
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: -0.01em;
    margin: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.combat-cabecalho-contexto {
    font-size: 0.78rem;
    color: var(--combat-gray);
    line-height: 1.2;
    margin: 2px 0 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Acoes de TELA moram aqui. Acao de LINHA continua na linha — misturar as duas
   escalas no mesmo lugar foi o que encheu o Financeiro de botao vermelho. */
.combat-cabecalho-acoes {
    display: flex;
    align-items: center;
    gap: var(--esp-sm);
    flex-shrink: 0;
}

/* No celular a barra ja divide 100% da largura com o sino e o Sair; as acoes de
   tela descem para a pagina em vez de espremer o titulo ate ele sumir. */
@media (max-width: 991.98px) {
    .combat-cabecalho-acoes {
        display: none;
    }
}

/* ============================================================
   MOVIMENTO
   ============================================================

   Regra que vale para tudo daqui para baixo: animacao existe para explicar
   uma mudanca de estado, nunca para enfeitar. Se a pessoa PERCEBE a animacao
   como animacao, ela esta longa demais.

   Nada anima opacidade e transform ao mesmo tempo que layout: so essas duas
   propriedades rodam na placa de video, e animar altura ou margem derruba os
   60 quadros no primeiro cartao. */

@keyframes combat-surgir {
    from {
        opacity: 0;
        transform: translateY(8px);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes combat-brilho {
    from { background-position: -180% 0; }
    to   { background-position: 180% 0; }
}

@keyframes combat-pulsar {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.45; }
}

/*
    Entrada escalonada do conteudo.

    Os blocos sobem 8px em sequencia, 40ms entre um e outro. O escalonamento faz
    o olho percorrer a tela na ordem em que ela deve ser lida, em vez de tudo
    materializar de uma vez.

    Para no sexto filho de proposito: passando disso o ultimo bloco entraria meio
    segundo depois do primeiro, e ai a espera vira custo real.
*/
.combat-conteudo > * {
    animation: combat-surgir var(--mov-lento) var(--mov-saida) both;
}

.combat-conteudo > *:nth-child(1) { animation-delay: 0ms; }
.combat-conteudo > *:nth-child(2) { animation-delay: 40ms; }
.combat-conteudo > *:nth-child(3) { animation-delay: 80ms; }
.combat-conteudo > *:nth-child(4) { animation-delay: 120ms; }
.combat-conteudo > *:nth-child(5) { animation-delay: 160ms; }
.combat-conteudo > *:nth-child(n + 6) { animation-delay: 200ms; }

/* O cabecalho da barra entra junto, so que sem subir: ele e ancora da tela e
   nao pode dar a impressao de que a barra inteira balancou. */
.combat-cabecalho-texto {
    animation: combat-surgir var(--mov-medio) var(--mov-saida) both;
}

/*
    ACESSIBILIDADE — e nao "carinho".

    Quem marcou reducao de movimento no sistema costuma ter um motivo clinico:
    enxaqueca vestibular, epilepsia fotossensivel, tontura. Ignorar essa marca
    nao deixa a interface mais bonita para essa pessoa, deixa inutilizavel.

    Nada e removido: tudo vira instantaneo. A mudanca de estado continua legivel.
*/
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ============================================================
   ELEVACAO E RESPOSTA AO TOQUE
   ============================================================ */

.card {
    background-color: var(--combat-surface);
    border: 1px solid var(--combat-outline);
    box-shadow: var(--sombra-1);
    transition:
        border-color var(--mov-rapido) var(--mov-padrao),
        box-shadow var(--mov-rapido) var(--mov-padrao);
}

.combat-bloco {
    box-shadow: var(--sombra-1);
    transition:
        border-color var(--mov-rapido) var(--mov-padrao),
        box-shadow var(--mov-rapido) var(--mov-padrao),
        transform var(--mov-rapido) var(--mov-padrao);
}

/* Metrica sobe 1px e ganha sombra: e clicavel-parecido sem prometer clique. */
.combat-bloco:hover {
    border-color: var(--combat-outline-forte);
    box-shadow: var(--sombra-2);
    transform: translateY(-1px);
}

.combat-arte,
.combat-vitrine-item,
.combat-chamada-hoje {
    box-shadow: var(--sombra-1);
}

.combat-arte-link:hover .combat-arte,
.combat-chamada-hoje:hover {
    box-shadow: var(--sombra-2);
}

.combat-modal,
.combat-menu-painel {
    background-color: var(--combat-elevado);
    box-shadow: var(--sombra-3);
}

/* ============================================================
   DENSIDADE — os tokens de espacamento em uso de verdade
   ============================================================

   Ate aqui eles estavam declarados e nao aplicados: variavel sem uso e o
   mesmo que nao ter variavel. */

.table > thead th {
    padding: var(--esp-md) var(--esp-lg);
    font-size: 0.68rem;
    letter-spacing: 0.12em;

    /* Cabecalho gruda no topo ao rolar uma lista longa: sem isso, na linha 40
       a pessoa nao sabe mais qual coluna e qual. */
    position: sticky;
    top: 0;
    z-index: 2;
    background-color: var(--combat-surface);
}

.table > tbody > tr > td {
    padding: var(--esp-md) var(--esp-lg);
}

.table > tbody > tr:hover > td {
    background-color: rgba(255, 255, 255, 0.022);
}

.btn {
    font-size: 0.875rem;
    font-weight: 500;
    padding: 0.45rem var(--esp-lg);
    transition:
        background-color var(--mov-rapido) var(--mov-padrao),
        border-color var(--mov-rapido) var(--mov-padrao),
        transform var(--mov-rapido) var(--mov-padrao);
}

/* Afunda 1px no clique. E o unico retorno tatil que uma tela plana consegue
   dar, e a falta dele e parte do que faz um painel parecer maquete. */
.btn:active {
    transform: translateY(1px);
}

.btn-sm {
    padding: 0.3rem var(--esp-md);
    font-size: 0.8rem;
}

.form-control,
.form-select {
    padding: 0.45rem var(--esp-md);
    transition:
        border-color var(--mov-rapido) var(--mov-padrao),
        box-shadow var(--mov-rapido) var(--mov-padrao);
}

/* ---------- Icone ---------- */

/*
    Traco de espessura CONSTANTE.

    Sem isto o mesmo desenho a 16px sai anemico e a 32px sai gordo, porque o
    navegador escala o traco junto com a caixa. `non-scaling-stroke` mede a
    espessura em pixels de tela, e o icone mantem a mesma voz em toda medida.
*/
.combat-icone {
    flex-shrink: 0;
    vector-effect: non-scaling-stroke;
}

.combat-icone * {
    vector-effect: non-scaling-stroke;
}

/* ---------- Carregando ---------- */

/*
    Brilho que atravessa o bloco cinza.

    Bloco parado nao diz se o sistema esta trabalhando ou travado — e no Render
    free, que hiberna, a espera passa de trinta segundos. O brilho e a diferenca
    entre "carregando" e "quebrou".
*/
.combat-esqueleto {
    background: linear-gradient(
        90deg,
        var(--combat-surface) 25%,
        var(--combat-surface-variant) 50%,
        var(--combat-surface) 75%
    );
    background-size: 220% 100%;
    animation: combat-brilho 1.4s ease-in-out infinite;
    border-radius: var(--raio-sm);
}

.combat-carregando {
    animation: combat-pulsar 1.6s ease-in-out infinite;
}

/* ============================================================
   Cabecalho na barra: acoes e competencia
   ============================================================ */

/* Botao dentro da barra nao cresce com a barra: 4rem de altura com um botao de
   2,4rem no meio precisa que o botao pare de esticar sozinho. */
.combat-cabecalho-acoes .btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    white-space: nowrap;
}

/* A competencia vira um controle unico — segmento, nao tres pecas soltas. */
.combat-cabecalho-acoes .combat-competencia {
    display: inline-flex;
    align-items: center;
    gap: 0;
    background-color: var(--combat-surface-variant);
    border: 1px solid var(--combat-outline);
    border-radius: var(--raio-sm);
    overflow: hidden;
}

.combat-cabecalho-acoes .combat-competencia-seta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border: none;
    background: none;
    color: var(--combat-gray);
    transition:
        background-color var(--mov-rapido) var(--mov-padrao),
        color var(--mov-rapido) var(--mov-padrao);
}

.combat-cabecalho-acoes .combat-competencia-seta:hover:not(:disabled) {
    background-color: var(--combat-elevado);
    color: var(--combat-white);
}

.combat-cabecalho-acoes .combat-competencia-seta:disabled {
    opacity: 0.35;
}

.combat-cabecalho-acoes .combat-competencia-nome {
    padding: 0 var(--esp-md);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    color: var(--combat-white);
    white-space: nowrap;

    /* Largura minima trava a barra no lugar: sem isto, "MAIO DE 2026" e
       "SETEMBRO DE 2026" mudam a largura do controle e as setas dancam sob o
       cursor entre um mes e outro. */
    min-width: 10.5rem;
    text-align: center;
}

/* A barra ganha uma linha de luz no topo do conteudo abaixo dela. E o truque
   que separa "barra flutuando" de "barra desenhada": um fio claro de 1px marca
   a quina onde a superficie termina. */
.top-row {
    box-shadow: var(--sombra-1);
}

/* ============================================================
   Densidade dentro dos dialogos
   ============================================================

   O pacote visual anterior mexeu em tabela, botao e campo, mas parou na porta
   do modal — e formulario e onde a pessoa passa mais tempo. */

.combat-modal-corpo .form-control,
.combat-modal-corpo .form-select {
    padding: 0.45rem var(--esp-md);
}

.combat-modal-corpo .form-text {
    font-size: 0.76rem;
    margin-top: var(--esp-xs);
}

/* Rotulo colado no campo, nao boiando: 4px separa o par "rotulo + campo" do
   par seguinte e o formulario passa a ser lido aos pares. */
.combat-modal-corpo .combat-rotulo {
    margin-bottom: var(--esp-xs);
}

/* Lista rolavel dentro do modal com o cabecalho da tabela grudado. */
.combat-lista-rolavel {
    max-height: 320px;
    overflow-y: auto;
    border: 1px solid var(--combat-outline);
    border-radius: var(--raio-sm);
}

/* O rodape sustenta o botao secundario a esquerda (a "Ficha") sem quebrar o
   alinhamento a direita dos outros dois. */
.combat-modal-rodape {
    display: flex;
    align-items: center;
    gap: var(--esp-sm);
}

/* ============================================================
   Busca global (Ctrl+K)
   ============================================================ */

.combat-paleta {
    position: fixed;
    top: 12vh;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1080;
    width: min(560px, calc(100vw - 2rem));
    background-color: var(--combat-elevado);
    border: 1px solid var(--combat-outline-forte);
    border-radius: var(--raio-md);
    box-shadow: var(--sombra-3);
    overflow: hidden;

    /* Entra descendo 8px, nao aparecendo do nada: a paleta vem "de cima da
       tela", e o movimento diz de onde ela veio. */
    animation: combat-surgir var(--mov-medio) var(--mov-saida);
}

/* 12vh e nao centralizada: a paleta cresce para BAIXO conforme os resultados
   entram, e centralizada ela subiria a cada tecla digitada. */

.combat-paleta-campo {
    display: flex;
    align-items: center;
    gap: var(--esp-md);
    padding: var(--esp-lg);
    border-bottom: 1px solid var(--combat-outline);
    color: var(--combat-gray);
}

.combat-paleta-entrada {
    flex: 1 1 auto;
    min-width: 0;
    background: none;
    border: none;
    outline: none;
    color: var(--combat-white);
    font-size: 1rem;
}

.combat-paleta-entrada::placeholder {
    color: var(--combat-gray);
}

.combat-tecla {
    padding: 2px var(--esp-sm);
    border: 1px solid var(--combat-outline);
    border-radius: var(--raio-xs);
    background: none;
    color: var(--combat-gray);
    font-size: 0.7rem;
}

.combat-paleta-lista {
    max-height: 52vh;
    overflow-y: auto;
}

.combat-paleta-item {
    display: flex;
    align-items: center;
    gap: var(--esp-md);
    width: 100%;
    padding: var(--esp-md) var(--esp-lg);
    border: none;
    background: none;
    color: inherit;
    text-align: left;
    transition: background-color var(--mov-rapido) var(--mov-padrao);
}

.combat-paleta-item:hover,
.combat-paleta-item-ativo {
    background-color: var(--combat-surface-variant);
}

.combat-paleta-icone {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 32px;
    height: 32px;
    border-radius: var(--raio-sm);
    background-color: var(--combat-surface);
    color: var(--combat-gray);
}

/* ============================================================
   Lateral retratil
   ============================================================

   Monitor de balcao costuma ser pequeno e a tabela do Financeiro tem seis
   colunas. Recolher a lateral devolve 250px para o dado, que e o que a pessoa
   veio ver. O estado NAO e lembrado de proposito: recolher e um gesto para a
   tarefa da hora, nao uma preferencia. */

.combat-recolher {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border: 1px solid var(--combat-outline);
    border-radius: var(--raio-sm);
    background: none;
    color: var(--combat-gray);
    transition:
        background-color var(--mov-rapido) var(--mov-padrao),
        color var(--mov-rapido) var(--mov-padrao);
}

.combat-recolher:hover {
    background-color: var(--combat-surface-variant);
    color: var(--combat-white);
}

@media (min-width: 641px) {
    .page.combat-lateral-recolhida .sidebar {
        width: 0;
        overflow: hidden;

        /* Borda some junto: 1px de borda numa lateral de largura zero vira um
           risco vertical no meio do nada. */
        border-right: none;
    }
}

.sidebar {
    transition: width var(--mov-lento) var(--mov-padrao);
}

/* Botao da busca na barra. Mostra a TECLA em vez de so o icone: atalho que
   ninguem descobre e atalho que ninguem usa. */
.combat-busca-atalho {
    display: inline-flex;
    align-items: center;
    gap: var(--esp-sm);
    height: 32px;
    padding: 0 var(--esp-md);
    border: 1px solid var(--combat-outline);
    border-radius: var(--raio-sm);
    background: none;
    color: var(--combat-gray);
    font-size: 0.82rem;
    transition:
        border-color var(--mov-rapido) var(--mov-padrao),
        color var(--mov-rapido) var(--mov-padrao);
}

.combat-busca-atalho:hover {
    border-color: var(--combat-outline-forte);
    color: var(--combat-white);
}

/* ============================================================
   Linha de cobranca — mesma leitura do app
   ============================================================ */

/*
    Bolinha de estado no inicio da linha.

    A coluna "Situacao" com etiqueta saiu: uma coluna de bolinhas deixa a pessoa
    achar as vencidas descendo o olho, sem ler palavra nenhuma. A palavra
    continua embaixo do nome para quem precisa do detalhe.
*/
.combat-ponto {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: var(--raio-redondo);
    flex-shrink: 0;
}

/*
    Acao de linha e ICONE, nao botao preenchido.

    O "Receber" era um btn-danger em toda linha em aberto. Com a lista cheia
    viravam vinte botoes vermelhos empilhados: o vermelho parava de significar
    acao primaria e o botao ficava maior que o dado sobre o qual ele age. Esta
    e a mesma correcao ja feita no app; a web tinha ficado de fora.
*/
.combat-acao-icone {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border: none;
    border-radius: var(--raio-sm);
    background: none;
    color: var(--combat-gray);
    transition:
        background-color var(--mov-rapido) var(--mov-padrao),
        color var(--mov-rapido) var(--mov-padrao);
}

.combat-acao-icone:hover {
    background-color: var(--combat-surface-variant);
    color: var(--combat-white);
}

/* Verde no receber, como no app: e a acao boa da linha. */
.combat-acao-receber {
    color: var(--combat-success);
}

.combat-acao-receber:hover {
    background-color: rgba(48, 209, 88, 0.14);
    color: var(--combat-success);
}

/* Desabilitado nao pode continuar verde e reagindo ao mouse: enquanto uma baixa
   esta em curso, um icone com a cor de acao convida a clicar de novo — e clicar
   de novo e o caminho para dar baixa duas vezes na mesma cobranca. */
.combat-acao-icone:disabled {
    opacity: 0.35;
    cursor: default;
}

.combat-acao-icone:disabled:hover {
    background: none;
    color: var(--combat-gray);
}

/* ============================================================
   Tabela: usar a largura que existe
   ============================================================

   A tabela terminava antes da borda do cartao e deixava um retangulo preto do
   lado direito. A causa raiz era um <col> a mais no colgroup, ja corrigida —
   isto garante que ela nunca mais encolha por conta propria. */

.card .table {
    width: 100%;
    table-layout: fixed;
}

/* Nome longo corta com reticencia em vez de empurrar a coluna do valor. */
.card .table td,
.card .table th {
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ...MENOS a celula de acao.
 *
 * O painel do menu de tres pontos e `position: absolute` dentro da celula.
 * Ancestral com `overflow: hidden` RECORTA descendente absoluto, e `z-index`
 * nao salva — z-index ordena o que sobrou, nao devolve o que foi cortado. Com
 * a regra acima valendo para todo `td`, o menu de "Cobrar por PIX / Mudar o
 * valor / Cancelar" aparecia fatiado dentro de uma celula de 34px de altura,
 * em TODAS as tabelas do painel de uma vez.
 *
 * Duas miras, em regras SEPARADAS de proposito. Seletor invalido derruba a
 * regra inteira, e `:has()` nao existe em navegador velho — juntas numa lista
 * so, a mira boa cairia junto com a outra e o menu voltaria a ser cortado. Hoje
 * toda celula de acao ja tem a classe; o `:has()` e a rede para a proxima. */
.card .table td.combat-acoes {
    overflow: visible;
}

.card .table td:has(.combat-menu-ancora) {
    overflow: visible;
}

/* Mesmo motivo, um nivel acima.
 *
 * `.table-responsive` e `overflow-x: auto`, e pela especificacao recortar um
 * eixo obriga o outro a recortar tambem: o menu morria na altura da linha
 * mesmo com a celula liberada. Acima de 992px a tabela do painel cabe inteira
 * e a rolagem horizontal nao tem funcao nenhuma; abaixo disso ela volta, e a
 * janela estreita e justamente onde ela serve para alguma coisa. */
@media (min-width: 992px) {
    .table-responsive {
        overflow: visible;
    }
}

/* ============================================================
   CODIGO DE RECUPERACAO
   ============================================================

   Fundo de alerta e nao cartao comum: isto nao e informacao da conta, e uma
   TAREFA ("anote agora"). Num cartao neutro o bloco le como detalhe e a pessoa
   fecha a tela sem copiar — e o codigo nao aparece de novo. */

.combat-codigo {
    border: 1px solid var(--combat-warning);
    border-radius: var(--raio-md);
    background-color: rgba(255, 179, 0, 0.08);
    padding: var(--esp-lg);
}

.combat-codigo-valor {
    display: flex;
    align-items: center;
    gap: var(--esp-md);
    justify-content: space-between;
}

/* Monoespacada, grande e com espaco entre as letras.
 *
 * Este codigo vai ser copiado a mao para um papel e digitado meses depois,
 * possivelmente por outra pessoa. O alfabeto ja evita os pares ambiguos; a
 * fonte de largura fixa termina o servico separando o que sobrou. */
.combat-codigo-valor > span {
    font-family: ui-monospace, "Cascadia Mono", "Consolas", monospace;
    font-size: 1.5rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    color: var(--combat-white);

    /* O codigo tem hifen; quebrar a linha no meio dele faria a pessoa copiar
       so metade sem perceber. */
    white-space: nowrap;
    overflow-x: auto;
}

/* O campo onde ele e DIGITADO usa a mesma fonte: assim o que a pessoa ve
   enquanto digita tem a mesma forma do que ela esta lendo no papel. */
.combat-codigo-campo {
    font-family: ui-monospace, "Cascadia Mono", "Consolas", monospace;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

/* Linha que NAO vai entrar na importacao.
 *
 * A classe existia no markup ha tempo e nao tinha regra nenhuma: as linhas
 * barradas ficavam identicas as que iam entrar, e a conferencia antes de
 * importar — que e a unica razao dessa tela existir — pedia ler o motivo de
 * cada linha uma a uma para descobrir quais eram.
 *
 * Apagada e com a barra vermelha na lateral: o motivo em vermelho continua
 * legivel dentro dela, so o resto da linha e que recua. */
.combat-linha-bloqueada > td {
    opacity: 0.55;
}

.combat-linha-bloqueada > td:first-child {
    box-shadow: inset 2px 0 0 var(--combat-danger);
}
