/* =============================================================================
   SurfApp — campos compostos do painel

   Estilos dos componentes que o Backpack FREE não traz e que passaram a ser
   escritos no projeto: select pesquisável, calendário em português, campo
   monetário, bloco de endereço e mapa.

   Regras de convivência com o tema:

   - nada de `!important`. Este arquivo é carregado DEPOIS de `surfapp-setup.css`
     (ver `config/backpack/theme-tabler.php`), então vence por ordem de cascata,
     que é o mesmo acordo que a paleta e as etiquetas de situação já seguem;
   - as cores saem das variáveis do Tabler já reapontadas pela paleta do SurfApp
     (`--tblr-border-color`, `--tblr-primary`, ...). Nenhum hexadecimal solto:
     mudar a marca de uma escola não pode exigir mexer aqui;
   - `z-index` local e baixo. Menu de select e calendário disputam espaço apenas
     dentro do próprio formulário; a modal do mapa usa a escala do Bootstrap,
     sem valor inventado — a correção de sobreposição está em
     `surfapp-modal.js`, movendo o elemento, e não em número maior.
   ========================================================================== */

/* -----------------------------------------------------------------------------
   Select pesquisável
   -------------------------------------------------------------------------- */

.surf-select {
    position: relative;
}

/*
   O `<select>` original continua sendo quem o formulário envia, então ele não
   pode sair do DOM nem ser `display: none` — campo escondido assim fica fora da
   validação nativa do navegador e, num campo obrigatório, o Chrome recusa o
   envio reclamando de um elemento que ninguém vê. Tirar da vista sem tirar da
   página é o meio-termo.
*/
.surf-select__native {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
    opacity: 0;
    pointer-events: none;
}

.surf-select__control {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem;
    min-height: 2.375rem;
    height: auto;
    padding: 0.25rem 2rem 0.25rem 0.5rem;
    cursor: text;
}

.surf-select--focused .surf-select__control {
    border-color: var(--tblr-primary);
    box-shadow: 0 0 0 0.25rem rgba(var(--tblr-primary-rgb), 0.2);
}

.surf-select__chips {
    display: contents;
}

.surf-select__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    max-width: 100%;
    padding: 0.125rem 0.25rem 0.125rem 0.5rem;
    font-size: 0.8125rem;
    line-height: 1.4;
    background-color: var(--surf-mint, #c2dfdb);
    border: 1px solid var(--tblr-border-color);
    border-radius: 1rem;
}

.surf-select__chip-text {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.surf-select__chip-remove,
.surf-select__clear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.25rem;
    height: 1.25rem;
    padding: 0;
    font-size: 1rem;
    line-height: 1;
    color: var(--tblr-secondary);
    background: none;
    border: 0;
    border-radius: 50%;
    cursor: pointer;
}

.surf-select__chip-remove:hover,
.surf-select__clear:hover {
    color: var(--tblr-danger);
    background-color: rgba(var(--tblr-danger-rgb), 0.1);
}

.surf-select__clear {
    position: absolute;
    top: 50%;
    right: 0.5rem;
    transform: translateY(-50%);
}

.surf-select__search {
    flex: 1 1 6rem;
    min-width: 6rem;
    padding: 0.125rem 0;
    color: inherit;
    background: none;
    border: 0;
    outline: none;
}

.surf-select__menu {
    position: absolute;
    top: calc(100% + 2px);
    right: 0;
    left: 0;
    z-index: 5;
    max-height: 16rem;
    overflow-y: auto;
    background-color: var(--tblr-bg-surface, #fff);
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius, 4px);
    box-shadow: 0 4px 12px rgba(10, 38, 56, 0.12);
}

.surf-select__option {
    display: flex;
    flex-direction: column;
    padding: 0.375rem 0.625rem;
    cursor: pointer;
}

.surf-select__option:hover,
.surf-select__option.is-active {
    background-color: var(--surf-mint, #c2dfdb);
}

.surf-select__option-subtitle {
    font-size: 0.75rem;
    color: var(--tblr-secondary);
}

.surf-select__message {
    padding: 0.5rem 0.625rem;
    font-size: 0.8125rem;
    color: var(--tblr-secondary);
}

.surf-select__error {
    color: var(--tblr-danger);
}

.surf-select__more {
    display: block;
    width: 100%;
    padding: 0.5rem;
    font-size: 0.8125rem;
    color: var(--tblr-primary);
    background: none;
    border: 0;
    border-top: 1px solid var(--tblr-border-color);
    cursor: pointer;
}

/* -----------------------------------------------------------------------------
   Calendário em português
   -------------------------------------------------------------------------- */

.surf-date {
    position: relative;
}

.surf-date__panel {
    position: absolute;
    top: calc(100% + 2px);
    left: 0;
    z-index: 5;
    width: 17rem;
    padding: 0.5rem;
    background-color: var(--tblr-bg-surface, #fff);
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius, 4px);
    box-shadow: 0 4px 12px rgba(10, 38, 56, 0.12);
}

.surf-date__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 0.375rem;
}

.surf-date__title {
    font-weight: 600;
}

.surf-date__nav,
.surf-date__action {
    padding: 0.125rem 0.5rem;
    color: var(--tblr-primary);
    background: none;
    border: 0;
    border-radius: var(--tblr-border-radius, 4px);
    cursor: pointer;
}

.surf-date__nav:hover,
.surf-date__action:hover {
    background-color: var(--surf-mint, #c2dfdb);
}

.surf-date__grid {
    width: 100%;
    table-layout: fixed;
    border-collapse: collapse;
}

.surf-date__grid th {
    padding: 0.25rem 0;
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--tblr-secondary);
    text-align: center;
}

.surf-date__grid td {
    padding: 1px;
    text-align: center;
}

.surf-date__day {
    width: 100%;
    padding: 0.3125rem 0;
    font-size: 0.8125rem;
    background: none;
    border: 1px solid transparent;
    border-radius: var(--tblr-border-radius, 4px);
    cursor: pointer;
}

.surf-date__day:hover:not(:disabled) {
    background-color: var(--surf-mint, #c2dfdb);
}

/* Hoje é marcado com contorno, e o dia escolhido com fundo cheio: são
   informações diferentes e precisam continuar distinguíveis quando coincidem. */
.surf-date__day.is-today {
    border-color: var(--tblr-primary);
}

.surf-date__day.is-selected {
    color: #fff;
    background-color: var(--tblr-primary);
    border-color: var(--tblr-primary);
}

.surf-date__day:disabled {
    color: var(--tblr-secondary);
    cursor: not-allowed;
    opacity: 0.4;
}

.surf-date__foot {
    display: flex;
    justify-content: space-between;
    margin-top: 0.375rem;
    border-top: 1px solid var(--tblr-border-color);
    padding-top: 0.375rem;
}

/* -----------------------------------------------------------------------------
   Campo monetário
   -------------------------------------------------------------------------- */

/* Alinhado à direita porque valor se confere pela vírgula, não pela primeira
   letra: uma coluna de preços com o decimal na mesma posição é lida de relance. */
.surf-money input {
    text-align: right;
}

/* -----------------------------------------------------------------------------
   Bloco de endereço
   -------------------------------------------------------------------------- */

.surf-address__feedback {
    display: block;
    margin-top: 0.25rem;
    font-size: 0.8125rem;
    min-height: 1.25rem;
}

.surf-address__feedback--success { color: var(--tblr-success); }
.surf-address__feedback--error   { color: var(--tblr-danger); }
.surf-address__feedback--warning { color: var(--tblr-warning); }
.surf-address__feedback--info    { color: var(--tblr-secondary); }

/* O botão de buscar CEP muda de rótulo enquanto consulta; a marca visual
   evita que um clique repetido pareça a única saída numa rede lenta. */
.surf-address__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
}

.surf-address__actions .is-loading {
    opacity: 0.6;
    cursor: progress;
}

.surf-address__coords {
    font-family: var(--tblr-font-monospace, monospace);
    font-size: 0.8125rem;
    color: var(--tblr-secondary);
}

/* -----------------------------------------------------------------------------
   Mapa
   -------------------------------------------------------------------------- */

.surf-map {
    width: 100%;
    height: 24rem;
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius, 4px);
}

/* Em telas baixas o mapa não pode ocupar a altura toda da modal e empurrar os
   botões de confirmar para fora do alcance. */
@media (max-height: 700px) {
    .surf-map {
        height: 16rem;
    }
}

@media (max-width: 575.98px) {
    .surf-map {
        height: 14rem;
    }
}

/*
   O Leaflet declara `z-index` alto nos próprios painéis (400 a 700). Dentro de
   uma modal do Bootstrap isso é irrelevante — o contexto é o da modal —, mas
   uma folha de estilo do tema poderia elevá-los acima do cabeçalho da modal.
   Prender os painéis ao contexto do mapa fecha o assunto.
*/
.surf-map .leaflet-pane,
.surf-map .leaflet-top,
.surf-map .leaflet-bottom {
    z-index: 1;
}

/* -----------------------------------------------------------------------------
   Interruptores (switch) — correção de contraste
   --------------------------------------------------------------------------

   DEFEITO OBSERVADO: todo switch LIGADO do painel aparecia igual a um
   desligado. Não dava para saber, olhando, se "Permite agendar aulas" estava
   ativo — num formulário de plano comercial, isso decide o que o aluno pode
   fazer depois de pagar.

   CAUSA: o field `switch` do Backpack recebe `'color' => 'primary'` e escreve
   no elemento pai, literalmente, `--bg-switch-checked-color: primary`. A regra
   dele é `background-color: var(--bg-switch-checked-color, black)`. Como
   `primary` não é uma cor CSS válida, a declaração inteira é descartada pelo
   navegador — e o fallback `black` nem chega a ser consultado, porque a
   variável ESTÁ definida, só que com valor inválido. Resultado: fundo
   transparente, exatamente igual ao estado desligado.

   CORREÇÃO: pintar o fundo a partir do nome, ignorando a variável quebrada.

   Por que não simplesmente redefinir `--bg-switch-checked-color`: o Backpack
   escreve a variável no atributo `style` do elemento, e estilo inline vence
   qualquer folha de estilo — a redefinição seria ignorada. Por isso o alvo é a
   declaração final (`background-color`), e a especificidade é elevada
   prendendo o seletor ao próprio elemento que carrega o inline
   (`.form-switch[style*=…]`, 0-4-0) para vencer a regra do pacote
   (`.form-switch .form-check-input:checked`, 0-3-0) sem recorrer a
   `!important`.

   A cor também vai em `border-color`: com fundo colorido e borda cinza o
   controle fica com um halo que parece defeito de renderização. */

/* Rede de segurança primeiro: qualquer switch com a variável declarada fica
   legível, mesmo que o `color` seja um nome que não está mapeado abaixo. No
   pior caso a cor é a errada — problema de estética, não de leitura de estado. */
.form-switch[style*='--bg-switch-checked-color'] .form-check-input:checked {
    background-color: var(--tblr-primary);
    border-color: var(--tblr-primary);
}

/* Depois os nomes conhecidos. Mesma especificidade da regra acima, então
   vencem por ordem — e é por isso que precisam vir depois dela. */
.form-switch[style*='--bg-switch-checked-color: secondary'] .form-check-input:checked {
    background-color: var(--tblr-secondary);
    border-color: var(--tblr-secondary);
}

.form-switch[style*='--bg-switch-checked-color: success'] .form-check-input:checked {
    background-color: var(--tblr-success);
    border-color: var(--tblr-success);
}

.form-switch[style*='--bg-switch-checked-color: info'] .form-check-input:checked {
    background-color: var(--tblr-info);
    border-color: var(--tblr-info);
}

.form-switch[style*='--bg-switch-checked-color: warning'] .form-check-input:checked {
    background-color: var(--tblr-warning);
    border-color: var(--tblr-warning);
}

.form-switch[style*='--bg-switch-checked-color: danger'] .form-check-input:checked {
    background-color: var(--tblr-danger);
    border-color: var(--tblr-danger);
}

.form-switch[style*='--bg-switch-checked-color: dark'] .form-check-input:checked {
    background-color: var(--tblr-dark);
    border-color: var(--tblr-dark);
}

/* -----------------------------------------------------------------------------
   Seções do formulário
   --------------------------------------------------------------------------

   O Backpack empilha todos os campos num card único. Num cadastro de sete
   campos isso é o certo; num de dezoito — plano comercial, matrícula — vira
   uma parede sem hierarquia, em que preço, regra de uso e situação têm
   exatamente o mesmo peso visual.

   A seção é um cabeçalho que quebra a lista em blocos nomeados, com um fundo
   branco levemente destacado do card e uma descrição curta dizendo para que
   serve aquele grupo. */

.surf-form-section {
    margin-top: 0.5rem;
    padding: 0.75rem 1rem;
    background-color: var(--tblr-bg-surface-secondary, #faf8f5);
    border-left: 3px solid var(--tblr-primary);
    border-radius: var(--tblr-border-radius, 4px);
}

/* A primeira seção não precisa do respiro de cima: ela encosta no topo do card. */
.surf-form-section:first-child {
    margin-top: 0;
}

.surf-form-section__title {
    margin: 0;
    font-size: 0.875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--surf-navy, #0a2638);
}

.surf-form-section__desc {
    margin: 0.125rem 0 0;
    font-size: 0.8125rem;
    color: var(--tblr-secondary);
}

/* -----------------------------------------------------------------------------
   Matrícula: resumo da oferta e valor final
   -------------------------------------------------------------------------- */

.surf-offer {
    padding: 0.75rem 1rem;
    background-color: var(--tblr-bg-surface-secondary, #faf8f5);
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius, 4px);
}

.surf-offer__label {
    display: block;
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--tblr-secondary);
}

.surf-offer__value {
    display: block;
    font-weight: 600;
}

.surf-offer__rules {
    padding-left: 1.1rem;
    margin: 0;
    font-size: 0.8125rem;
    color: var(--tblr-secondary);
}

.surf-offer__flow {
    padding-top: 0.5rem;
    font-size: 0.8125rem;
    border-top: 1px dashed var(--tblr-border-color);
}

.surf-final-price {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 2.375rem;
}

/* Maior que o resto do formulário: é o número que a pessoa confere em voz alta
   com o aluno antes de confirmar. */
.surf-final-price__value {
    font-size: 1.25rem;
    line-height: 1.2;
    color: var(--surf-navy, #0a2638);
}

.surf-final-price__hint {
    font-size: 0.75rem;
    color: var(--tblr-secondary);
}

/* -----------------------------------------------------------------------------
   Alertas com texto corrido
   --------------------------------------------------------------------------

   DEFEITO OBSERVADO: um aviso escrito como parágrafo saía despedaçado — cada
   `<strong>` numa coluna própria, o texto entre eles noutra, e o resultado
   ilegível em qualquer largura.

   CAUSA: o Tabler declara `.alert { display: flex; gap: 1rem }`. Cada filho do
   alerta vira um item de flex, e um parágrafo com ênfase no meio tem vários
   filhos. O Bootstrap, que o projeto usa como referência, mantém `.alert` em
   `display: block` — é o Tabler que muda.

   CORREÇÃO: devolver o `block` quando o alerta NÃO pede flex explicitamente.
   O `:not(.d-flex)` preserva os alertas que usam o eixo de propósito (o de
   galeria e o do painel da plataforma alinham texto e botão com
   `d-flex justify-content-between`), então nenhum deles muda. */

.alert:not(.d-flex) {
    display: block;
}

/* -----------------------------------------------------------------------------
   Ações rápidas do dashboard
   --------------------------------------------------------------------------

   Sobre o tamanho do título: o `style.css` do Backpack traz
   `.page-body .container-fluid h2 { font-size: 27px }`, que vence a classe
   utilitária `.h6` (0-2-1 contra 0-1-0). O `h2 class="h6"` fica então com o
   corpo grande do pacote e a entrelinha pequena do utilitário — e o título
   passa por cima do parágrafo seguinte.

   A tentação é consertar isso globalmente. NÃO FAÇA: os títulos de card do
   dashboard e do wizard já são escritos assim e vêm grandes por causa dessa
   mesma regra. Normalizar o painel inteiro reduziria todos eles de uma vez, o
   que é um redesenho, não uma correção. O ajuste fica no escopo deste
   componente. */

.surf-quick {
    /* Faixa turquesa à esquerda: dá ao bloco o mesmo peso das seções de
       formulário sem competir com os cartões de indicador logo abaixo. */
    border-left: 3px solid var(--tblr-primary);
}

.page-body .container-fluid .surf-quick__title {
    margin: 0;
    font-size: 1rem;
    line-height: 1.4;
    font-weight: 600;
}

.surf-quick__subform {
    padding: 0.75rem;
    background-color: var(--tblr-bg-surface-secondary, #faf8f5);
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius, 4px);
}

.surf-quick__summary {
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
    background-color: var(--surf-mint, #c2dfdb);
    border-radius: var(--tblr-border-radius, 4px);
}

/* -----------------------------------------------------------------------------
   Seção recolhível (cabeçalho clicável em card branco)
   -------------------------------------------------------------------------- */

.surf-collapse-card {
    margin-bottom: 1rem;
}

.surf-collapse-card__toggle {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    padding: 1rem;
    text-align: left;
    background: none;
    border: 0;
    cursor: pointer;
}

.surf-collapse-card__toggle:hover {
    background-color: var(--tblr-bg-surface-secondary, #faf8f5);
}

.surf-collapse-card__toggle:focus-visible {
    outline: 2px solid var(--tblr-primary);
    outline-offset: -2px;
}

.surf-collapse-card__title {
    margin: 0;
    font-size: 0.9375rem;
    font-weight: 600;
}

.surf-collapse-card__desc {
    margin: 0.125rem 0 0;
    font-size: 0.8125rem;
    color: var(--tblr-secondary);
}

/* A seta é o sinal de que o cabeçalho inteiro é clicável — o problema original
   era justamente parecer texto. Ela gira ao abrir, ligando causa e efeito. */
.surf-collapse-card__chevron {
    margin-left: auto;
    font-size: 0.75rem;
    color: var(--tblr-secondary);
    transition: transform 0.15s ease-in-out;
}

.surf-collapse-card__toggle[aria-expanded='true'] .surf-collapse-card__chevron {
    transform: rotate(180deg);
}

.surf-collapse-card__body {
    padding: 0 1rem 1rem;
    border-top: 1px solid var(--tblr-border-color);
}

@media (prefers-reduced-motion: reduce) {
    .surf-collapse-card__chevron {
        transition: none;
    }
}

/* -----------------------------------------------------------------------------
   Mensagem de erro escrita pelo cliente (surfapp-validation.js)

   A cor, o tamanho e o espaçamento continuam sendo os do `.invalid-feedback` do
   tema — de propósito: o erro do cliente e o do servidor têm de ser a MESMA
   mensagem vermelha, no mesmo lugar. O que falta no tema é só o gatilho de
   exibição.

   O vendor mostra a mensagem por adjacência (`.is-invalid ~ .invalid-feedback`),
   e essa regra não alcança dois casos que o painel tem: campo dentro de
   `.input-group` (a mensagem sai depois do grupo, e aí não é mais irmã do
   input) e mensagem criada por JavaScript acima do texto de ajuda. Marcar o
   estado numa classe própria resolve os dois sem depender da posição no DOM.

   Duas classes contra uma: vence o `display: none` do tema por especificidade,
   sem `!important` e sem depender da ordem de carregamento.
   -------------------------------------------------------------------------- */

.invalid-feedback.surf-field-error--shown {
    display: block;
}

/* -----------------------------------------------------------------------------
   Recebimento junto com a matrícula (ação rápida)

   O bloco fica dentro do mesmo passo da oferta, e precisa ser lido como uma
   SEGUNDA pergunta — "e o dinheiro, entrou agora?" — e não como mais dois
   campos do preço. Sem separação visual, o valor recebido vira vizinho do
   desconto e é preenchido no automático, que é justamente o erro de caixa que
   este atalho não pode introduzir.

   Traço, e não caixa cheia: a moldura de fundo já é usada pelo cadastro rápido
   de aluno (`.surf-quick__subform`), e repeti-la aqui daria dois blocos de
   mesmo peso disputando a atenção no meio do formulário.
   -------------------------------------------------------------------------- */

.surf-quick__pay {
    padding-top: 0.75rem;
    border-top: 1px dashed var(--tblr-border-color);
}

/* -----------------------------------------------------------------------------
   Resumo do aluno e do cliente (admin/students/summary, admin/customers/summary)

   Uma única regra, e ela existe por um efeito colateral concreto:
   `admin.partials.styles` define `.surf-table-wrap table { min-width: 640px }`,
   pensado para as tabelas largas do painel (extrato, relatórios). No resumo há
   duas tabelas de TRÊS colunas lado a lado, cada uma dentro de meia tela — os
   640px forçariam uma barra de rolagem horizontal em tabelas que cabem
   folgadas, e barra de rolagem que não precisa existir é lida como defeito.

   O piso continua existindo (`22rem`): sem nenhum, "Presente"/"Cancelada pela
   escola" quebrariam em três linhas num celular. Abaixo disso a rolagem do
   `.surf-table-wrap` volta a agir, como nas demais telas.

   Sem `!important`, como o resto do arquivo — mas aqui a ordem de cascata NÃO
   ajuda: `admin.partials.styles` imprime um `<style>` em `after_styles`, que
   sai depois de todas as folhas ligadas no `<head>`, inclusive desta. Quem
   decide é a especificidade: duas classes (0,2,0) contra uma classe e um
   elemento (0,1,1).
   -------------------------------------------------------------------------- */

.surf-table-wrap .surf-summary-table {
    min-width: 22rem;
}

/* -----------------------------------------------------------------------------
   Barra de seleção da galeria da aula (admin/gallery/show)

   O botão "Identificar selecionadas" nasce desabilitado e só liga quando há
   mídia marcada — foi assim que o `alert('Selecione ao menos uma mídia')`
   deixou de ser necessário. Ao lado dele fica o texto que explica o estado e
   conta o que já foi marcado (`#lote-ajuda`, ligado por `aria-describedby`).

   Duas regras, e as duas existem por um efeito concreto no celular:

   1. o texto de apoio muda de tamanho conforme a contagem ("Selecione as
      mídias..." → "3 mídias selecionadas."). Num `flex` sem piso, cada mudança
      reposiciona o botão alguns pixels para os lados — e um alvo de toque que
      se move sozinho é como se erra o clique. O `min-width` reserva o espaço da
      frase mais longa e o botão para de andar;

   2. `text-align: end` mantém o texto colado ao botão quando os dois cabem na
      mesma linha; quando não cabem, o `flex-wrap` do próprio Tabler quebra e o
      alinhamento deixa de ter efeito, que é o desejado.

   Sem `!important`, como o resto do arquivo: `.surf-media-toolbar` não disputa
   com nenhuma regra do tema.
   -------------------------------------------------------------------------- */

.surf-media-toolbar #lote-ajuda {
    min-width: 12rem;
    text-align: end;
}

@media (max-width: 575.98px) {
    /* No celular a barra já quebrou em duas linhas: reservar largura ali só
       abriria um vão à esquerda do texto. */
    .surf-media-toolbar #lote-ajuda {
        min-width: 0;
        text-align: start;
    }
}

/* -----------------------------------------------------------------------------
   Modal do mapa — área útil
   --------------------------------------------------------------------------

   DEFEITO OBSERVADO: a modal de "Selecionar no mapa" era uma `modal-lg` com um
   mapa de altura fixa (24rem). Num monitor comum sobrava metade da tela vazia
   ao redor de um mapa pequeno demais para escolher a ponta de um pico — dava
   para ver o quarteirão, não a pedra.

   CORREÇÃO: a modal passa a ocupar ~90% da largura e da altura úteis, e o mapa
   passa a CRESCER até o que sobrar dentro dela.

   Por que o mapa cresce por `flex`, e não por outra altura fixa: altura fixa
   dentro de uma modal medida em `vh` é a receita para os dois defeitos opostos
   ao mesmo tempo — vão vazio embaixo do mapa nas telas altas e rodapé fora da
   tela nas baixas. Cabeçalho, barra de ações e rodapé não crescem (`flex: 0 0
   auto`), então confirmar, cancelar, buscar e reposicionar continuam visíveis
   em qualquer viewport; só o mapa disputa o que sobra.

   `min-height: 0` no corpo não é decoração: sem ele, um filho flexível se
   recusa a encolher abaixo do próprio conteúdo e a coluna transborda o
   `modal-content`, empurrando o rodapé para fora justamente nas telas baixas
   que a regra tenta proteger.

   O contêiner do mapa muda de tamanho com a viewport, e o Leaflet mede o
   contêiner uma vez só. Quem refaz a conta é o JS (`invalidateSize` no
   `shown.bs.modal`, de novo no quadro seguinte e a cada `resize`) — ver
   `public/js/admin/surfapp-address.js`. As duas metades são obrigatórias:
   sozinha, esta folha entrega um contêiner grande com meio mapa cinza.
   -------------------------------------------------------------------------- */

.surf-map-modal .modal-dialog {
    width: 90vw;
    max-width: 90vw;
    height: 90vh;
    /* `modal-dialog-centered` declara `min-height: calc(100% - margem*2)`, e
       `min-height` VENCE `height`: sem zerar isto a modal media 94% da altura
       em vez dos 90% pedidos, e a margem escrita logo abaixo não valia nada.
       Medido no navegador: 849px de altura numa janela de 905px. */
    min-height: 0;
    margin: 5vh auto;
    /* `modal-dialog-centered` alinha ao centro; com altura própria o filho
       precisa esticar, senão o `modal-content` colapsa no conteúdo. */
    align-items: stretch;
}

/* `dvh` desconta a barra de endereço do navegador móvel, que `vh` ignora — é a
   diferença entre o rodapé visível e o rodapé escondido atrás da barra. Fica
   em `@supports` porque é a única parte daqui que não é universal. */
@supports (height: 100dvh) {
    .surf-map-modal .modal-dialog {
        height: 90dvh;
        margin: 5dvh auto;
    }
}

.surf-map-modal .modal-content {
    height: 100%;
    max-height: 100%;
    overflow: hidden;
}

.surf-map-modal .modal-body {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-height: 0;
    /* Se nem com o mapa no mínimo couber tudo, o CORPO rola — a página por
       baixo continua travada pelo Bootstrap e o rodapé continua no lugar. */
    overflow-y: auto;
}

/* Vence `.surf-map` (0-1-0) por especificidade, e não por ordem: as regras de
   altura fixa lá em cima continuam valendo para o mapa fora da modal. */
.surf-map-modal .surf-map {
    flex: 1 1 auto;
    height: auto;
    min-height: 14rem;
}

.surf-map-modal__heading {
    min-width: 0;
}

.surf-map-modal__address {
    font-size: 0.8125rem;
    color: var(--tblr-secondary);
}

.surf-map-modal__toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    flex: 0 0 auto;
}

.surf-map-modal__hint {
    font-size: 0.8125rem;
    color: var(--tblr-secondary);
    flex: 1 1 14rem;
    min-width: 0;
}

.surf-map-modal__footer {
    flex: 0 0 auto;
    justify-content: space-between;
}

.surf-map-modal__readout {
    font-size: 0.8125rem;
    font-family: var(--tblr-font-monospace, monospace);
}

.surf-map-modal__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-inline-start: auto;
}

/* Tablet: a margem de 5% vira desperdício numa tela já estreita. */
@media (max-width: 991.98px) {
    .surf-map-modal .modal-dialog {
        width: 94vw;
        max-width: 94vw;
        height: 94vh;
        margin: 3vh auto;
    }

    @supports (height: 100dvh) {
        .surf-map-modal .modal-dialog {
            height: 94dvh;
            margin: 3dvh auto;
        }
    }
}

/* Celular: tela cheia. Qualquer margem aqui rouba área do mapa e não devolve
   nada — o fundo escurecido não é conteúdo. */
@media (max-width: 575.98px) {
    .surf-map-modal .modal-dialog {
        width: 100%;
        max-width: 100%;
        height: 100vh;
        margin: 0;
    }

    @supports (height: 100dvh) {
        .surf-map-modal .modal-dialog {
            height: 100dvh;
        }
    }

    .surf-map-modal .modal-content {
        border-radius: 0;
        border-inline: 0;
    }

    .surf-map-modal .surf-map {
        min-height: 10rem;
    }

    /* Empilhado: com dois botões e o par de coordenadas na mesma linha, o
       "Usar esta localização" saía pela direita em 360px. */
    .surf-map-modal__footer {
        justify-content: stretch;
    }

    .surf-map-modal__actions {
        margin-inline-start: 0;
        width: 100%;
    }

    .surf-map-modal__actions .btn {
        flex: 1 1 auto;
    }
}

/* Janela baixa (notebook com o navegador em meia tela, telefone deitado): o
   que se corta é a margem, nunca o rodapé. */
@media (max-height: 560px) {
    .surf-map-modal .modal-dialog {
        height: 98vh;
        margin: 1vh auto;
    }

    .surf-map-modal .surf-map {
        min-height: 8rem;
    }
}

/* -----------------------------------------------------------------------------
   Endereço da escola copiado para o local de aula (wizard, etapa 2)
   --------------------------------------------------------------------------

   A cópia precisa ficar VISÍVEL depois de feita: sem marca, o formulário fica
   idêntico a um preenchido à mão e ninguém lembra, três campos depois, de onde
   veio aquele CEP — nem que ele pode ser editado sem afetar a escola.
   -------------------------------------------------------------------------- */

.surf-school-address {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
}

.surf-school-address__note {
    font-size: 0.8125rem;
    color: var(--tblr-secondary);
    flex: 1 1 16rem;
    min-width: 0;
}

/* Verde do "veio da escola": o mesmo tom de sucesso do feedback do bloco de
   endereço, para a tela não inventar um terceiro vocabulário de cor. */
.surf-school-address__note--copied {
    color: var(--tblr-success, #2fb344);
}

.surf-school-address__note--warning {
    color: var(--tblr-warning-fg, #c07600);
}

/* -----------------------------------------------------------------------------
   Seleção de nota (surfapp_score)

   Botões de 0 a N no lugar do `input[type=number]` que a tela de avaliação
   usava. O campo numérico obriga a mirar num alvo pequeno no meio de uma tabela
   com vinte linhas, abre teclado no celular e ainda mostra setinhas de
   incremento que ninguém usa para dar nota.

   O que está desenhado aqui são `input[type=radio]` de verdade escondidos atrás
   de `<label>`. O rádio some da vista mas continua no fluxo de foco — é dele
   que vêm a navegação por setas, o anúncio do leitor de tela e o envio junto do
   formulário. Nenhuma linha de JavaScript participa disso, o que importa num
   painel com CSP `script-src 'self'`.

   ACESSIBILIDADE — a cor não é o único sinal de "escolhido", como manda a
   WCAG 1.4.1. A opção marcada acumula quatro diferenças:

     1. o número, que está sempre escrito, marcado ou não;
     2. peso de fonte maior;
     3. um anel interno de 2px (`box-shadow: inset`, e não `border-width`, que
        mudaria o tamanho da caixa e faria a fileira inteira dançar);
     4. a barra sólida embaixo (`__mark`), que é forma, não cor.

   Alvos de toque: 2,25rem no desktop e 2,75rem no celular — acima do mínimo de
   44px recomendado quando somado ao espaçamento da grade.
   -------------------------------------------------------------------------- */

.surf-score {
    /* `min-width: 0` porque `fieldset` nasce com `min-width: min-content` e se
       recusa a encolher dentro de uma célula de tabela estreita. */
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
}

.surf-score__legend {
    /* `float: none` e largura automática desfazem o padrão do Bootstrap para
       legend, que ocupa a linha inteira. */
    float: none;
    width: auto;
    margin-bottom: 0.25rem;
    padding: 0;
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.2;
    color: var(--surf-navy, #0a2638);
}

.surf-score__grid {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
}

.surf-score__cell {
    flex: 0 0 auto;
}

/* O rádio sai da vista sem sair do foco: `display: none` e `visibility: hidden`
   o tirariam da ordem de tabulação e matariam a navegação por setas. */
.surf-score__input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.surf-score__option {
    position: relative;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.0625rem;
    min-width: 2.25rem;
    min-height: 2.25rem;
    padding: 0.25rem 0.5rem;
    background-color: var(--tblr-bg-surface, #fff);
    border: 1px solid var(--tblr-border-color);
    border-radius: var(--tblr-border-radius, 4px);
    font-size: 0.875rem;
    line-height: 1.1;
    color: var(--tblr-body-color);
    cursor: pointer;
    user-select: none;
}

.surf-score__option:hover {
    background-color: var(--tblr-bg-surface-secondary, #faf8f5);
    border-color: var(--tblr-primary);
}

/* Números alinhados em coluna: sem `tabular-nums`, o 1 é mais estreito que o 8
   e a fileira de botões fica com larguras irregulares. */
.surf-score__number {
    font-variant-numeric: tabular-nums;
}

.surf-score__text {
    font-size: 0.75rem;
    white-space: nowrap;
}

/* A opção de limpar é a única com borda tracejada: ela não é uma nota, e a
   diferença de traço diz isso sem depender de leitura. */
.surf-score__option--empty {
    border-style: dashed;
    color: var(--tblr-secondary);
}

/* Barra sólida embaixo da opção escolhida. Ocupa o espaço mesmo apagada, para
   que ligar e desligar não mude a altura do botão. */
.surf-score__mark {
    width: 1rem;
    height: 3px;
    border-radius: 2px;
    background-color: currentColor;
    opacity: 0;
}

.surf-score__input:checked + .surf-score__option {
    background-color: var(--tblr-primary);
    border-color: var(--tblr-primary);
    box-shadow: inset 0 0 0 2px var(--tblr-bg-surface, #fff);
    color: #fff;
    font-weight: 700;
}

.surf-score__input:checked + .surf-score__option--empty {
    background-color: var(--tblr-secondary);
    border-color: var(--tblr-secondary);
    border-style: solid;
}

.surf-score__input:checked + .surf-score__option .surf-score__mark {
    opacity: 1;
}

/* `:focus-visible` e não `:focus`: o clique do mouse não deve deixar anel, mas
   o Tab e as setas precisam deixar. */
.surf-score__input:focus-visible + .surf-score__option {
    outline: 2px solid var(--tblr-primary);
    outline-offset: 2px;
}

.surf-score--invalid .surf-score__option {
    border-color: var(--tblr-danger);
}

.surf-score__error {
    margin: 0.25rem 0 0;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--tblr-danger);
}

@media (max-width: 575.98px) {
    /* No celular o dedo cobre o botão inteiro: alvo maior e grade com mais
       respiro entre as opções. */
    .surf-score__grid {
        gap: 0.375rem;
    }

    .surf-score__option {
        min-width: 2.75rem;
        min-height: 2.75rem;
    }
}

/* -----------------------------------------------------------------------------
   Copiar o telefone para o WhatsApp (surfapp_phone_copy)

   O botão fica ABAIXO do campo, e não num `input-group` ao lado dele. O motivo é
   a largura: no cadastro de cliente o WhatsApp mora numa coluna de `col-md-2`, e
   um botão colado à direita ali sobraria três caracteres para o número. Embaixo
   ele cabe em qualquer largura, mantém o texto legível ("Copiar telefone", e não
   um ícone solto que ninguém decifra) e não muda o alvo de toque no celular.

   O estado desabilitado é o padrão do HTML, e é o que se vê enquanto o telefone
   está vazio ou incompleto. O `title` diz o motivo — sem ele, um botão apagado é
   só um botão quebrado.
   -------------------------------------------------------------------------- */

.surf-phone-copy__btn {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-top: 0.125rem;
    padding: 0.125rem 0;
    font-size: 0.8125rem;
    line-height: 1.2;
    text-decoration: none;
}

.surf-phone-copy__btn:hover:not(:disabled) {
    text-decoration: underline;
}

/* `opacity` e cursor no lugar do cinza-claro do Bootstrap: o botão precisa
   continuar LEGÍVEL desabilitado, porque é o `title` dele que explica o que
   falta preencher. */
.surf-phone-copy__btn:disabled {
    opacity: 0.55;
    cursor: not-allowed;
    text-decoration: none;
}

/* A confirmação da troca já é anunciada pela região viva; aqui ela também
   aparece escrita, para quem enxerga a tela. */
.surf-phone-copy__status {
    display: block;
    font-size: 0.75rem;
    line-height: 1.2;
    color: var(--tblr-success-fg, #1f7a4d);
}

.surf-phone-copy__status:empty {
    display: none;
}

/* ---------------------------------------------------------------------------
   Escolha do fundo do logo (configurações da escola).

   Três cartões com a marca REAL desenhada sobre cada fundo possível, no mesmo
   tamanho e com o mesmo respiro do portal. A pergunta que a escola tem é "qual
   destes deixa minha marca legível?", e ela se responde olhando — não salvando,
   abrindo o portal, voltando e trocando.

   O rádio nativo continua ali (só visualmente escondido): o teclado navega com
   as setas, o leitor de tela anuncia o grupo, e o formulário envia sem JS.
--------------------------------------------------------------------------- */
.surf-logo-plate-option {
    display: block;
    cursor: pointer;
    border: 2px solid var(--tblr-border-color, #dfe3e7);
    border-radius: .5rem;
    padding: .6rem;
    height: 100%;
    transition: border-color .12s ease-in-out;
}

.surf-logo-plate-option:hover {
    border-color: var(--tblr-primary, #0a2638);
}

/* Estado escolhido: borda grossa E um anel. Só a cor da borda não bastaria
   para quem não distingue as duas cores. */
.surf-logo-plate-option.is-selected,
.surf-logo-plate-option:has(input:checked) {
    border-color: var(--tblr-primary, #0a2638);
    box-shadow: 0 0 0 3px rgba(10, 38, 56, .12);
}

/* O foco do teclado precisa aparecer no CARTÃO, já que o rádio está oculto. */
.surf-logo-plate-option:has(input:focus-visible) {
    outline: 2px solid var(--tblr-primary, #0a2638);
    outline-offset: 2px;
}

.surf-logo-plate-option input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.surf-logo-plate-option__preview {
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid transparent;
    border-radius: .375rem;
    padding: .5rem .75rem;
    min-height: 62px;
    margin-bottom: .45rem;
}

.surf-logo-plate-option__preview img {
    max-height: 40px;
    max-width: 100%;
    width: auto;
    object-fit: contain;
    display: block;
}

.surf-logo-plate-option__label {
    display: block;
    font-weight: 600;
    font-size: .875rem;
}

.surf-logo-plate-option__hint {
    display: block;
    font-size: .75rem;
    color: var(--tblr-secondary, #667);
    line-height: 1.3;
}

/* ---------------------------------------------------------------------------
   Campo de upload de imagem com pré-visualização
   (resources/views/admin/partials/image-upload.blade.php).

   O input de arquivo cru respondia "nenhum arquivo selecionado" e mais nada:
   a escola só descobria se tinha escolhido a imagem certa DEPOIS de salvar e
   abrir o portal. Aqui a resposta é imediata — a miniatura ao lado do nome e
   do tamanho do arquivo.

   O `<input type="file">` continua no DOM, escondido por opacidade e NUNCA por
   `display: none`: assim ele permanece focável pelo teclado, e o `<label for>`
   que envolve a zona abre o seletor sem JavaScript nenhum. O JS só acrescenta
   o arrastar-e-soltar e a prévia.
--------------------------------------------------------------------------- */
.surf-upload__zone {
    display: flex;
    align-items: center;
    gap: .85rem;
    width: 100%;
    margin: 0;
    padding: .75rem;
    cursor: pointer;
    /* `relative` porque o input está `absolute` DENTRO desta zona: sem âncora
       aqui ele se posicionaria contra o primeiro ancestral posicionado da
       página — no painel, um cartão ou um modal qualquer. */
    position: relative;
    border: 2px dashed var(--tblr-border-color, #dfe3e7);
    border-radius: .5rem;
    background: var(--tblr-bg-surface, #fff);
    transition: border-color .12s ease-in-out, background-color .12s ease-in-out;
}

.surf-upload__zone:hover {
    border-color: var(--tblr-primary, #0a2638);
}

/* Escolha feita e ainda NÃO salva: a borda vira contínua. O tracejado é o
   convite a soltar um arquivo, e ele não faz mais sentido quando já há um. */
.surf-upload.is-filled .surf-upload__zone {
    border-style: solid;
    border-color: var(--tblr-primary, #0a2638);
}

/* Arquivo pairando sobre a zona: o alvo precisa ficar óbvio ANTES de soltar,
   senão a pessoa não sabe se acertou a área. */
.surf-upload__zone.is-dragging {
    border-color: var(--tblr-primary, #0a2638);
    border-style: solid;
    background: var(--tblr-gray-50, #faf8f5);
}

.surf-upload__zone.is-invalid {
    border-color: var(--tblr-danger, #d63939);
}

/* O foco do teclado aparece na ZONA, porque o input está visualmente oculto —
   sem esta regra, quem navega por tabulação não veria onde está. */
.surf-upload__zone:has(.surf-upload__input:focus-visible) {
    outline: 2px solid var(--tblr-primary, #0a2638);
    outline-offset: 2px;
}

/* `opacity` + `pointer-events: none`, e não `display: none` nem `hidden`: o
   campo tem de continuar na ordem de tabulação e aceitar Enter/Espaço. */
.surf-upload__input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.surf-upload__figure {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 84px;
    height: 64px;
    border-radius: .375rem;
    /* Xadrez claro: a maioria das marcas chega em PNG transparente, e sobre
       branco liso não dá para distinguir "fundo transparente" de "fundo
       branco chapado" — que é exatamente a escolha da placa logo abaixo. */
    background-color: #fff;
    background-image:
        linear-gradient(45deg, #eceff1 25%, transparent 25%, transparent 75%, #eceff1 75%),
        linear-gradient(45deg, #eceff1 25%, transparent 25%, transparent 75%, #eceff1 75%);
    background-size: 12px 12px;
    background-position: 0 0, 6px 6px;
    border: 1px solid var(--tblr-border-color, #dfe3e7);
    overflow: hidden;
}

/* `contain`: a marca enviada tem proporção imprevisível e não pode ser
   cortada nem esticada dentro da miniatura. */
.surf-upload__preview {
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    object-fit: contain;
    display: block;
}

.surf-upload__placeholder {
    font-size: 1.75rem;
    line-height: 1;
    color: rgba(10, 38, 56, .22);
}

.surf-upload__body {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    min-width: 0;
}

.surf-upload__cta {
    font-weight: 600;
    font-size: .875rem;
    color: var(--tblr-primary, #0a2638);
}

/* Nome de arquivo é longo e não pode empurrar o cartão: quebra em vez de
   estourar a largura. */
.surf-upload__info {
    font-size: .8rem;
    color: var(--tblr-secondary, #667);
    overflow-wrap: anywhere;
}

.surf-upload__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: .75rem;
    margin-top: .35rem;
}

/* Remover o arquivo JÁ SALVO é outra ação, e não outra cor: as duas são
   destrutivas e vermelhas. O que as separa é o texto e o ícone — a lixeira
   para o que sai do disco, o "x" para a escolha que ainda nem subiu. */
.surf-upload__remove {
    border: 0;
    background: none;
    padding: 0;
    font-size: .8rem;
    color: var(--tblr-danger, #d63939);
    cursor: pointer;
}

.surf-upload__remove:hover {
    text-decoration: underline;
}

.surf-upload__remove:focus-visible {
    outline: 2px solid var(--tblr-danger, #d63939);
    outline-offset: 2px;
    border-radius: .25rem;
}

.surf-upload__clear {
    border: 0;
    background: none;
    padding: 0;
    font-size: .8rem;
    color: var(--tblr-danger, #d63939);
    cursor: pointer;
}

.surf-upload__clear:hover {
    text-decoration: underline;
}

.surf-upload__clear:focus-visible {
    outline: 2px solid var(--tblr-danger, #d63939);
    outline-offset: 2px;
    border-radius: .25rem;
}

.surf-upload__status {
    margin: .25rem 0 0;
    font-size: .78rem;
    line-height: 1.3;
    color: var(--tblr-secondary, #667);
}

/* Região viva vazia não pode ocupar espaço nem deixar um respiro solto. */
.surf-upload__status:empty {
    display: none;
}

@media (max-width: 575.98px) {
    .surf-upload__figure {
        width: 64px;
        height: 52px;
    }
}
