/**
 * CSS do componente geográfico — ETAPA 17.
 *
 * Só o necessário ao componente. Sem Bootstrap, sem framework, sem reset
 * global: este arquivo não deve alterar nada fora do elemento hospedeiro.
 *
 * Os nomes de classe são contrato estável com o consumidor. O que eles
 * SIGNIFICAM não é definido aqui: `status-0` não quer dizer "livre", "vago" ou
 * qualquer outra coisa comercial. O SaaS mapeia seus estados para os índices e
 * fornece a legenda; se o significado mudar, nada neste arquivo muda.
 *
 * Personalização: redefina os tokens `--mapa-*` em QUALQUER ancestral comum ao
 * mapa e à legenda — `:root`, `body` ou um contêiner do seu app.
 */

/* Os tokens públicos nunca são declarados aqui; são apenas LIDOS, com o padrão
 * embutido no `var()`, para variáveis privadas.
 *
 * A diferença importa: se o componente declarasse `--mapa-area` no próprio
 * elemento, essa declaração venceria qualquer valor herdado de um ancestral, e
 * definir os tokens no `body` do aplicativo não teria efeito nenhum. Lendo-os
 * para dentro de `--_*`, a herança volta a funcionar e o consumidor tematiza de
 * onde quiser.
 *
 * O bloco vale também para `.mapa-legenda`, que costuma viver fora do elemento
 * hospedeiro e, sem isso, renderizaria sem cor.
 */
:where(.mapa, .mapa-legenda) {
  /* superfície */
  --_fundo: var(--mapa-fundo, #f5f6f8);
  --_area: var(--mapa-area, #cfd6de);
  --_traco: var(--mapa-traco, #ffffff);
  --_largura: var(--mapa-traco-largura, 0.6);

  /* interação */
  --_realce: var(--mapa-realce, #9db3c8);
  /* tom escuro e neutro de propósito: o contorno de seleção não deve ser
     confundido com nenhuma das cores que o consumidor der aos seus estados */
  --_selecionado: var(--mapa-selecionado, #16283a);
  /* Opacidade do véu de seleção. Em 30% a cor do estado continua legível por
     baixo; em 100% todos os selecionados ficam de uma cor só e o estado deixa
     de aparecer neles — as duas leituras são defensáveis, ver README. */
  --_veu: var(--mapa-selecao-veu, 30%);
  --_foco: var(--mapa-foco, #1b4f8a);
  --_erro: var(--mapa-erro, #9b2c2c);

  /* Estados do consumidor. Os padrões são placeholders neutros: existem só para
     que algo apareça antes de o SaaS escolher a sua paleta e a sua legenda. */
  --_s0: var(--mapa-status-0, #b8c4d0);
  --_s1: var(--mapa-status-1, #9fb6cc);
  --_s2: var(--mapa-status-2, #d8b365);
  --_s3: var(--mapa-status-3, #c47f5a);
  --_s4: var(--mapa-status-4, #8a7fb5);
  --_s5: var(--mapa-status-5, #5f9ea0);
}

.mapa {
  position: relative;
  display: block;
  background: var(--_fundo);
  color: inherit;
}

.mapa-palco {
  display: block;
  width: 100%;
}

/* O SVG publicado traz `viewBox` e nenhuma dimensão, então tem proporção
   intrínseca: com `width: 100%` e `height: auto` ele preenche a largura, e
   `max-height` o reduz preservando a proporção. O consumidor define o teto de
   altura pela variável; sem ela, o mapa ocupa o que a largura mandar. */
.mapa-palco svg {
  display: block;
  width: 100%;
  height: auto;
  max-height: var(--mapa-altura-max, none);
  margin-inline: auto;
}

/* ---------- áreas ---------- */

.mapa-estado,
.mapa-municipio {
  fill: var(--_area);
  stroke: var(--_traco);
  /* espessura em unidades do viewBox, não `vector-effect: non-scaling-stroke`:
     o efeito visual é o mesmo em escala fixa e o navegador consegue compor a
     camada sem recalcular o traço de cada área */
  stroke-width: var(--_largura);
  cursor: pointer;
  /* sem `transition` no preenchimento: numa UF com centenas de municípios, cada
     área que o ponteiro cruza dispararia uma animação de repintura própria, e o
     realce passa a arrastar atrás do mouse */
}

/* O anel de foco padrão do navegador desenha um RETÂNGULO em volta da caixa da
   área — inútil num mapa, onde a forma é irregular. Ele é desligado aqui, no
   `:focus` (e não só no `:focus-visible`, senão aparece ao clicar com o mouse),
   e substituído pelo cursor de foco desenhado logo abaixo. */
.mapa-estado:focus,
.mapa-municipio:focus,
.mapa-palco:focus {
  outline: none;
}

/* O cursor de foco é um `<use>` que repete a forma da área focada e fica sempre
   como último elemento do SVG. Estilizar a própria área não funcionaria: no SVG
   a ordem de pintura é a ordem do documento, então o contorno de um município
   ficaria escondido embaixo dos vizinhos desenhados depois dele. */
.mapa-cursor {
  fill: none;
  stroke: var(--_foco);
  stroke-width: calc(var(--_largura) * 4);
  stroke-linejoin: round;
  pointer-events: none;
}

.mapa-cursor.is-oculto { display: none; }

/* dobra por dentro em claro, para o cursor continuar legível sobre área escura */
.mapa-cursor-interno {
  fill: none;
  stroke: #ffffff;
  stroke-width: calc(var(--_largura) * 1.5);
  pointer-events: none;
}

/* ---------- estados do consumidor ---------- */

/* Cada status combina cor com um padrão de traço distinto. A diferença entre
   dois status permanece perceptível sem enxergar cor nenhuma.
 *
 * As classes vão dentro de `:where()` de propósito: assim elas não somam
 * especificidade, e as regras de interação abaixo (`:hover`, `.is-selecionado`)
 * vencem sempre — independentemente da ordem em que este arquivo for lido ou de
 * o consumidor acrescentar folhas próprias.
 *
 * Sem isso, `.mapa-municipio.status-3` e `.mapa-municipio:hover` empatam em
 * especificidade e decide quem vem por último no arquivo. Foi exatamente esse
 * empate que fez o realce de hover e o de seleção sumirem em todo município que
 * tinha dado: a cor do status ganhava dos dois.
 */
.mapa-municipio:where(.status-0) { fill: var(--_s0); }
.mapa-municipio:where(.status-1) { fill: var(--_s1); }
.mapa-municipio:where(.status-2) { fill: var(--_s2); stroke-dasharray: 2 1.5; }
.mapa-municipio:where(.status-3) { fill: var(--_s3); stroke-dasharray: 4 2; }
.mapa-municipio:where(.status-4) { fill: var(--_s4); stroke-dasharray: 1 1; }
.mapa-municipio:where(.status-5) { fill: var(--_s5); stroke-dasharray: 6 2 1 2; }

/* Ausência de dado é um estado próprio e explícito: não é "livre", não é
   "zero". Vem hachurado justamente para não ser confundido com um valor. */
.mapa-municipio:where(.is-sem-dados) {
  fill: transparent;
  stroke: var(--_area);
  stroke-dasharray: 1 2;
}

/* ---------- interação ----------
 *
 * Vem depois dos estados do consumidor, e com especificidade maior que eles:
 * o que o usuário está fazendo agora tem precedência sobre o que o dado diz.
 */

.mapa-estado:hover,
.mapa-municipio:hover {
  fill: var(--_realce);
}

/* A seleção NÃO troca o preenchimento.
 *
 * Trocar significaria apagar o estado do dado justamente no município que o
 * usuário acabou de escolher — e ainda faria a cor de seleção competir com as
 * cores que o consumidor escolheu para os seus estados, que ele não controla
 * juntas. Seleção é estado da interface; status é estado do dado. São eixos
 * diferentes e precisam de canais visuais diferentes.
 *
 * O contorno vive numa camada própria, desenhada depois de todas as áreas: no
 * SVG a ordem de pintura é a do documento, então um contorno aplicado à própria
 * área ficaria escondido sob os vizinhos desenhados em seguida.
 */
.mapa-selecao-traco {
  /* véu translúcido: escurece a área o bastante para o olho achar o que está
     selecionado, e transparente o bastante para a cor do dado continuar legível
     por baixo. `--mapa-selecao-veu` controla essa proporção. */
  fill: color-mix(in srgb, var(--_selecionado) var(--_veu), transparent);
  stroke: var(--_selecionado);
  stroke-width: calc(var(--_largura) * 3.5);
  stroke-linejoin: round;
  pointer-events: none;
}

/* fio claro por dentro, para o contorno se destacar também sobre área escura */
.mapa-selecao-traco.mapa-selecao-interna {
  fill: none;
  stroke: #ffffff;
  stroke-width: calc(var(--_largura) * 1.2);
}

/* ---------- bloqueio ----------
 *
 * Marca o que a regra do consumidor não deixa selecionar. É dica de interface,
 * nunca a regra em si: quem decide é o servidor do SaaS.
 */
.mapa-municipio.is-bloqueado {
  cursor: not-allowed;
  opacity: 0.55;
}

/* ---------- carregamento, status e erro ---------- */

.mapa-status {
  margin: 0 0 8px;
  font-size: 0.875rem;
  line-height: 1.4;
  min-height: 1.4em;
}

.mapa-status.is-erro {
  color: var(--_erro);
  font-weight: 600;
}

.mapa.is-carregando .mapa-palco {
  opacity: 0.5;
  pointer-events: none;
}

/* barra de progresso indeterminada; o texto em `.mapa-status` é o que o leitor
   de tela anuncia, a barra é o equivalente visual */
.mapa.is-carregando::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--_foco), transparent);
  animation: mapa-progresso 1.1s linear infinite;
}

@keyframes mapa-progresso {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}

/* ---------- legenda ---------- */

/* Estrutura mínima para o consumidor montar a legenda textual exigida pela
   seção 17. As palavras são dele; o componente só oferece a forma. */
.mapa-legenda {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin-top: 12px;
  padding: 0;
  list-style: none;
  font-size: 0.8125rem;
}

.mapa-legenda li {
  display: flex;
  align-items: center;
  gap: 6px;
}

.mapa-legenda svg {
  width: 18px;
  height: 12px;
  flex-shrink: 0;
}

/* ---------- preferências do usuário ---------- */

@media (prefers-reduced-motion: reduce) {
  .mapa-estado,
  .mapa-municipio { transition: none; }
  .mapa.is-carregando::after { animation: none; opacity: 0.6; }
}

@media (prefers-contrast: more) {
  /* sobrescreve as privadas: preferência do usuário tem precedência sobre o
     tema do consumidor, e não deve ser anulada pelos tokens públicos dele */
  :where(.mapa, .mapa-legenda) {
    --_traco: #000000;
    --_largura: 0.9;
    --_area: #e8eaee;
  }
  .mapa-municipio.is-selecionado { stroke: #000000; }
}

/* Toque: alvo pequeno com dedo grande. Sem hover disponível, o realce de
   seleção passa a ser a única confirmação — por isso ele é reforçado. */
@media (hover: none) {
  .mapa-estado:hover,
  .mapa-municipio:hover { fill: var(--_area); }
  .mapa-selecao-traco { stroke-width: calc(var(--_largura) * 5); }
}
