/* WhatsTracker — landing pública.
   Paleta e formato herdados do sistema antigo (backend/old): neutros puros
   (chroma 0) com um único verde primário em hue 160, cartões com borda fina e
   dark mode de primeira classe. Tipografia Instrument Sans, a mesma do painel.

   Os mapas não usam tiles. A malha viária real de Maringá-PR sai de
   landing/mapa-ruas.svg aplicada como `mask-image`: assim as ruas ganham a cor
   do tema (um <img> externo não enxergaria o botão claro/escuro), o arquivo é
   cacheado à parte do index.html e não há requisição a servidor de terceiro
   em cada visita. Ver tools/gerar-mapa-landing.py. */

:root {
  --bg: #f8f8f8;
  --fg: #030303;
  --card: #ffffff;
  --muted: #eeeeee;
  --muted-fg: #555555;
  --border: #d7d7d7;
  --primary: #008d4d;
  /* dois tons mais escuro que --primary, só para texto branco sobre botão
     passar em contraste (4.3:1 -> 5.8:1); visualmente idêntico */
  --primary-strong: #00753f;
  --primary-fg: #ffffff;

  /* Tinta das ruas no fundo. Separada do resto porque no escuro a malha
     precisa de mais luz para não sumir. */
  --ruas: #4a4a4a;
  --ruas-alfa: 0.5;
  /* Bolha do WhatsApp, do lado de quem envia. */
  --balao-enviado: #d9fdd3;
  --balao-recebido: #ffffff;
  --fone-fundo: #ece5dd;

  --fonte: 'Instrument Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --largura: 1200px;
  --margem: clamp(16px, 4vw, 32px);
  --raio: 10px;
  /* Volta inteira da rota no mapa do painel. Igual ao `dur` do animateMotion
     gerado — se mudar lá, muda aqui. */
  --ciclo-rota: 28s;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --bg: #010101;
    --fg: #eeeeee;
    --card: #030303;
    --muted: #121212;
    --muted-fg: #8f8f8f;
    --border: #1b1b1b;
    --primary: #00ad6a;
    --primary-strong: #00ad6a;
    --primary-fg: #010101;
    --ruas: #9aa0a0;
    --ruas-alfa: 0.42;
    --balao-enviado: #005c4b;
    --balao-recebido: #202c33;
    --fone-fundo: #0b141a;
  }
}

:root[data-theme='dark'] {
  --bg: #010101;
  --fg: #eeeeee;
  --card: #030303;
  --muted: #121212;
  --muted-fg: #8f8f8f;
  --border: #1b1b1b;
  --primary: #00ad6a;
  --primary-strong: #00ad6a;
  --primary-fg: #010101;
  --ruas: #9aa0a0;
  --ruas-alfa: 0.42;
  --balao-enviado: #005c4b;
  --balao-recebido: #202c33;
  --fone-fundo: #0b141a;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: 84px;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--fonte);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  text-wrap: balance;
  letter-spacing: -0.025em;
  line-height: 1.15;
}

p {
  margin: 0;
  text-wrap: pretty;
}

a {
  color: inherit;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

svg {
  flex: none;
}

/* O sprite de ícones (`<svg hidden>` no topo do body) não pode ocupar espaço.
   `hidden` sozinho não basta: o atributo é definido para elementos HTML e o
   `<svg>` está no namespace SVG — onde a regra `[hidden]` do navegador não
   alcança, ele volta a ser uma caixa substituída com o tamanho padrão de
   300x150 px. Como os `<symbol>` de dentro não desenham nada, o resultado é um
   bloco branco de 150 px de altura entre o cabeçalho e o conteúdo. Regra de
   autor vence a do navegador, e sem `!important`: nada mais aqui define
   `display` para este elemento. */
svg[hidden] {
  display: none;
}

strong {
  font-weight: 600;
}

:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
  border-radius: 4px;
}

.container {
  width: 100%;
  max-width: var(--largura);
  margin-inline: auto;
  padding-inline: var(--margem);
}

.icone {
  width: 20px;
  height: 20px;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Glifos que só fazem sentido cheios (barra de status, handset, microfone). */
.icone--cheio {
  fill: currentColor;
  stroke: none;
}

/* Só aparece no teclado; sem ele o primeiro Tab cai no menu inteiro. */
.pular {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 100;
  padding: 10px 16px;
  border-radius: var(--raio);
  background: var(--primary-strong);
  color: var(--primary-fg);
  font-size: 0.875rem;
  text-decoration: none;
  translate: 0 -200%;
}

.pular:focus-visible {
  translate: 0;
}

/* ---------------------------------------------------------------- header */

.topo {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg) 80%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}

@supports not (backdrop-filter: blur(1px)) {
  .topo {
    background: var(--bg);
  }
}

.topo__linha {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 64px;
  gap: 16px;
}

.marca {
  display: flex;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  font-weight: 600;
  font-size: 1.0625rem;
}

.marca__simbolo {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 999px;
  background: var(--primary);
  color: var(--primary-fg);
}

.marca__simbolo .icone {
  width: 16px;
  height: 16px;
}

.topo__nav {
  display: flex;
  gap: 26px;
}

.topo__nav a {
  font-size: 0.875rem;
  color: var(--muted-fg);
  text-decoration: none;
  transition: color 0.15s ease;
}

.topo__nav a:hover {
  color: var(--fg);
}

.topo__acoes {
  display: flex;
  align-items: center;
  gap: 12px;
}

.tema {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: var(--raio);
  background: transparent;
  color: var(--muted-fg);
  cursor: pointer;
}

.tema:hover {
  background: var(--muted);
  color: var(--fg);
}

.tema__lua {
  display: none;
}

:root[data-theme='dark'] .tema__sol {
  display: none;
}

:root[data-theme='dark'] .tema__lua {
  display: block;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .tema__sol {
    display: none;
  }
  :root:not([data-theme='light']) .tema__lua {
    display: block;
  }
}

/* ---------------------------------------------------------------- botões */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 18px;
  border: 1px solid transparent;
  border-radius: var(--raio);
  font-family: inherit;
  font-size: 0.9375rem;
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background-color 0.15s ease,
    border-color 0.15s ease,
    color 0.15s ease;
}

.btn--primario {
  background: var(--primary-strong);
  color: var(--primary-fg);
}

.btn--primario:hover {
  background: color-mix(in srgb, var(--primary-strong) 88%, #000);
}

.btn--contorno {
  border-color: var(--border);
  color: var(--fg);
  background: color-mix(in srgb, var(--card) 70%, transparent);
}

.btn--contorno:hover {
  background: var(--muted);
}

.btn--fantasma {
  color: var(--muted-fg);
}

.btn--fantasma:hover {
  background: var(--muted);
  color: var(--fg);
}

.btn--neutro {
  background: var(--muted);
  color: var(--fg);
}

.btn--neutro:hover {
  background: var(--border);
}

.btn--grande {
  padding: 15px 30px;
  font-size: 1.0625rem;
}

.btn--largo {
  width: 100%;
}

/* ------------------------------------------------------------------ hero */

/* 64 px do topo fixo + 64 de respiro. Este número já foi de 132 para 96 no
   meio da caçada ao "espaço vazio" — que no fim era o sprite de ícones medindo
   300x150 px (ver `svg[hidden]` mais acima). Com o fantasma fora, 96 deixava o
   título colado no cabeçalho; 128 é o espaço de verdade. */
.hero {
  position: relative;
  isolation: isolate;
  padding-block: 128px 88px;
  overflow: hidden;
}

/* A malha viária de verdade, esmaecida. São duas máscaras: as ruas e um
   degradê radial que dissolve as bordas — sem ele o mapa termina numa linha
   reta no meio da tela.

   Em dois elementos aninhados, uma máscara cada, e não em duas camadas com
   `mask-composite: intersect`: a camada de baixo é composta contra um fundo
   transparente, e o que os navegadores fazem nesse caso não é o mesmo em todos
   eles. Aninhado não tem canto escuro. */
.hero__mapa {
  position: absolute;
  inset: -10% -5% auto;
  height: 118%;
  z-index: -1;
  /* O degradê é o que decide onde o mapa aparece. Estava com núcleo opaco de
     8% morrendo em 68% e centrado a 62%/32%: o canto superior esquerdo — onde
     fica o título e a faixa atrás do topo fixo — ficava com o mapa apagado, e
     lia como espaço em branco entre o cabeçalho e o conteúdo.

     O núcleo fica alto (chega ao topo da tela, por trás do cabeçalho, que é
     translúcido e desfoca o que passa embaixo) e deslocado para a DIREITA,
     onde está o celular. A coluna da esquerda, que é só texto, pega a parte
     já dissolvida do degradê — é lá que a leitura tem que ganhar. */
  -webkit-mask: radial-gradient(115% 105% at 70% 18%, #000 8%, transparent 72%);
  mask: radial-gradient(115% 105% at 70% 18%, #000 8%, transparent 72%);
  pointer-events: none;
}

/* 40% da tinta que o mapa do painel usa. O painel não tem texto por cima; o
   hero tem, e na opacidade cheia o subtítulo (--muted-fg) sobre um pixel de
   rua dava 2,89:1 no claro e 3,04:1 no escuro — abaixo do mínimo de 4,5:1.
   Nestes 0,20 / 0,17 o mesmo par vai a 5,08:1 e 5,39:1, e o título fica em
   14:1. O mapa continua visível porque é padrão, não conteúdo: a malha se lê
   pela repetição, não pelo contraste de cada traço. */
.hero__mapa::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--ruas);
  opacity: calc(var(--ruas-alfa) * 0.4);
  -webkit-mask: url('/mapa-ruas.svg') center / cover no-repeat;
  mask: url('/mapa-ruas.svg') center / cover no-repeat;
}

.hero__grade {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  align-items: start;
  gap: clamp(32px, 5vw, 72px);
}

/* Sem isso, uma palavra longa do título estica a coluna e come o celular. */
.hero__texto {
  min-width: 0;
}

.chamada {
  display: inline-flex;
  align-items: center;
  margin-bottom: 18px;
  padding: 5px 14px;
  border: 1px solid color-mix(in srgb, var(--primary) 35%, var(--border));
  border-radius: 999px;
  background: color-mix(in srgb, var(--primary) 10%, var(--card));
  color: var(--primary);
  font-size: 0.875rem;
  font-weight: 500;
}

.hero__titulo {
  font-size: clamp(2.25rem, 4.6vw, 3.5rem);
  font-weight: 700;
}

.hero__linha {
  margin-top: 22px;
  max-width: 46ch;
  font-size: clamp(1rem, 1.4vw, 1.125rem);
  color: var(--muted-fg);
}

.hero__acoes {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 32px;
}

.hero__risco {
  margin-top: 16px;
  max-width: 44ch;
  font-size: 0.875rem;
  color: var(--muted-fg);
}

.hero__checks {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  margin-top: 32px;
  font-size: 0.875rem;
  color: var(--muted-fg);
}

.hero__checks li {
  display: flex;
  align-items: center;
  gap: 7px;
}

.hero__checks .icone {
  width: 16px;
  height: 16px;
  color: var(--primary);
}

/* ------------------------------------------------- celular do WhatsApp */

.fone {
  justify-self: center;
  width: min(372px, 100%);
}

.fone__corpo {
  padding: 11px;
  border: 1px solid var(--border);
  border-radius: 42px;
  background: var(--card);
  box-shadow:
    0 2px 0 color-mix(in srgb, var(--fg) 6%, transparent) inset,
    0 34px 80px -38px rgb(0 0 0 / 0.55);
}

.fone__tela {
  display: flex;
  flex-direction: column;
  height: 660px;
  border-radius: 32px;
  background: var(--fone-fundo);
  overflow: hidden;
}

/* ---- barra de status (do sistema, não do WhatsApp) --------------------- */

.fone__status {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 9px 20px 5px;
  background: var(--primary-strong);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* Recorte da câmera. Fica sobre a barra e não no fluxo: é buraco na tela, não
   conteúdo — se entrasse no flex, empurraria a hora e os ícones. */
.fone__ilha {
  position: absolute;
  top: 6px;
  left: 50%;
  translate: -50% 0;
  width: 76px;
  height: 20px;
  border-radius: 999px;
  background: #000;
}

.fone__sinais {
  display: flex;
  align-items: center;
  gap: 5px;
}

.fone__sinais .icone {
  width: 15px;
  height: 15px;
}

/* ---- cabeçalho da conversa -------------------------------------------- */

.fone__topo {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 14px 12px;
  background: var(--primary-strong);
  color: #fff;
}

.fone__voltar .icone {
  width: 18px;
  height: 18px;
  rotate: 180deg;
  opacity: 0.9;
}

.fone__avatar {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 999px;
  background: rgb(255 255 255 / 0.22);
  font-size: 0.75rem;
  font-weight: 600;
}

.fone__quem {
  display: flex;
  flex-direction: column;
  line-height: 1.25;
  min-width: 0;
  flex: 1;
}

.fone__nome {
  font-size: 0.9375rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fone__estado {
  font-size: 0.6875rem;
  opacity: 0.85;
}

.fone__acoes {
  display: flex;
  align-items: center;
  gap: 14px;
  opacity: 0.92;
}

.fone__acoes .icone {
  width: 19px;
  height: 19px;
}

.fone__acoes .icone:last-child {
  width: 15px;
}

/* ---- conversa ---------------------------------------------------------- */

.fone__conversa {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 18px 12px;
  overflow: hidden;
  /* Papel de parede do WhatsApp, sugerido: pontinhos esparsos, não uma
     reprodução do desenho da Meta. */
  background-image: radial-gradient(
    color-mix(in srgb, var(--fg) 7%, transparent) 1px,
    transparent 1px
  );
  background-size: 22px 22px;
}

.balao {
  position: relative;
  max-width: 84%;
  padding: 9px 12px;
  border-radius: 12px;
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--fg);
  box-shadow: 0 1px 1px rgb(0 0 0 / 0.12);
  animation: surgir 0.45s ease-out backwards;
}

.balao--recebido {
  align-self: flex-start;
  border-start-start-radius: 3px;
  background: var(--balao-recebido);
}

.balao--enviado {
  align-self: flex-end;
  border-start-end-radius: 3px;
  background: var(--balao-enviado);
}

.balao--1 {
  animation-delay: 0.35s;
  /* Reserva a altura das três linhas que vão ser digitadas: sem isso a bolha
     cresce letra a letra e empurra o resto da conversa para baixo. */
  min-height: 5.2em;
}

.balao--2 {
  animation-delay: 3.4s;
}

.balao--3 {
  animation-delay: 6.4s;
}

@keyframes surgir {
  from {
    opacity: 0;
    translate: 0 10px;
    scale: 0.96;
  }
}

.cursor {
  display: inline-block;
  width: 2px;
  height: 1em;
  margin-left: 1px;
  background: var(--primary);
  vertical-align: text-bottom;
  animation: piscar 1s steps(2) infinite;
}

@keyframes piscar {
  50% {
    opacity: 0;
  }
}

/* Cartão de "localização em tempo real" dentro da bolha enviada. */
.balao--local {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 86%;
  padding: 6px 6px 8px;
}

.local__mapa {
  position: relative;
  display: block;
  aspect-ratio: 16 / 10;
  border-radius: 9px;
  background: color-mix(in srgb, var(--fg) 8%, var(--card));
  overflow: hidden;
}

/* Mesmo mapa do fundo, de perto: um RECORTE do mesmo desenho. O zoom e a
   posição saem do gerador (--mini-*) e correspondem exatamente ao viewBox
   recortado do SVG que vai por cima — é o que põe o marcador sobre a rua
   certa, e não sobre um enquadramento qualquer. */
.local__mapa::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--ruas);
  opacity: 0.62;
  -webkit-mask: url('/mapa-ruas.svg') var(--mini-x, 46%) var(--mini-y, 42%) /
    var(--mini-zoom, 340%) no-repeat;
  mask: url('/mapa-ruas.svg') var(--mini-x, 46%) var(--mini-y, 42%) /
    var(--mini-zoom, 340%) no-repeat;
}

.local__cena {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* Azul do ponto de localização do WhatsApp, não o verde da marca: neste
   cartão quem está falando é o aplicativo dele, não o seu produto. */
.local__eu-halo {
  fill: #1e88e5;
  opacity: 0.2;
}

.local__eu-ponto {
  fill: #1e88e5;
  stroke: #fff;
  stroke-width: 2.5;
}

/* Onda saindo do marcador: duas, defasadas em meio ciclo, para sempre haver
   uma em curso. `transform-box: fill-box` põe a origem no centro do próprio
   círculo — sem isso a escala sairia do canto do viewBox e a onda andaria
   para o lado em vez de abrir. */
.local__onda {
  fill: none;
  stroke: #1e88e5;
  stroke-width: 2;
  transform-box: fill-box;
  transform-origin: center;
  animation: onda 3s ease-out infinite;
}

.local__onda:nth-of-type(2) {
  animation-delay: 1.5s;
}

@keyframes onda {
  from {
    scale: 0.45;
    opacity: 0.6;
  }
  to {
    scale: 3.6;
    opacity: 0;
  }
}

.local__titulo {
  display: flex;
  align-items: center;
  gap: 6px;
  padding-inline: 4px;
  font-size: 0.8125rem;
  font-weight: 600;
}

.local__titulo .icone {
  width: 14px;
  height: 14px;
  color: var(--primary);
}

.local__estado {
  display: flex;
  align-items: center;
  gap: 6px;
  padding-inline: 4px;
  font-size: 0.6875rem;
  color: color-mix(in srgb, var(--fg) 62%, transparent);
  font-variant-numeric: tabular-nums;
}

.pulso {
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: var(--primary);
  animation: pulsar 1.6s ease-in-out infinite;
}

@keyframes pulsar {
  50% {
    opacity: 0.25;
    scale: 0.72;
  }
}

.balao__hora {
  display: flex;
  align-items: center;
  gap: 3px;
  align-self: flex-end;
  padding-inline: 4px;
  font-size: 0.625rem;
  color: color-mix(in srgb, var(--fg) 45%, transparent);
}

.visto {
  width: 13px;
  height: 13px;
  color: #53bdeb;
}

/* ---- campo de digitação ------------------------------------------------ */

.fone__barra {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px 6px;
  background: var(--fone-fundo);
}

.fone__campo {
  display: flex;
  align-items: center;
  gap: 9px;
  flex: 1;
  min-width: 0;
  padding: 9px 12px;
  border-radius: 999px;
  background: var(--balao-recebido);
  box-shadow: 0 1px 1px rgb(0 0 0 / 0.1);
  color: color-mix(in srgb, var(--fg) 55%, transparent);
}

.fone__campo .icone {
  width: 19px;
  height: 19px;
}

.fone__placeholder {
  flex: 1;
  min-width: 0;
  font-size: 0.875rem;
}

.fone__mic {
  display: grid;
  place-items: center;
  flex: none;
  width: 42px;
  height: 42px;
  border-radius: 999px;
  background: var(--primary-strong);
  color: #fff;
}

.fone__mic .icone {
  width: 19px;
  height: 19px;
}

/* Barra de início do sistema. */
.fone__inicio {
  display: block;
  width: 118px;
  height: 4px;
  margin: 6px auto 8px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--fg) 35%, transparent);
}

.fone__nota {
  margin-top: 18px;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--muted-fg);
  text-align: center;
  text-wrap: pretty;
}

/* ------------------------------------------------- preview do painel */

.preview {
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--card);
  overflow: hidden;
  box-shadow: 0 24px 60px -40px rgb(0 0 0 / 0.45);
}

.preview__barra {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--border);
}

.preview__identidade {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 500;
  font-size: 0.9375rem;
}

.preview__acoes {
  display: flex;
  gap: 14px;
  color: var(--primary);
}

.preview__corpo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  gap: 1px;
  background: var(--border);
}

.preview__lista {
  display: flex;
  flex-direction: column;
  background: var(--card);
  padding: 20px;
}

.preview__titulo {
  margin-bottom: 12px;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--muted-fg);
}

.preview__rodape {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: auto;
  padding-top: 18px;
  font-size: 0.8125rem;
  color: var(--muted-fg);
}

.preview__rodape .icone {
  width: 15px;
  height: 15px;
  color: var(--primary);
}

.linha-contato {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-block: 10px;
}

.linha-contato + .linha-contato {
  border-top: 1px solid var(--border);
}

.avatar {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 999px;
  background: var(--muted);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted-fg);
}

.linha-contato__dados {
  min-width: 0;
  flex: 1;
}

.linha-contato__nome {
  display: block;
  font-size: 0.9375rem;
  font-weight: 500;
}

.linha-contato__local {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 0.8125rem;
  color: var(--muted-fg);
}

.linha-contato__local .icone {
  width: 13px;
  height: 13px;
}

.selo {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--muted);
  color: var(--muted-fg);
  font-size: 0.75rem;
  white-space: nowrap;
}

.selo--ativo {
  background: color-mix(in srgb, var(--primary) 12%, transparent);
  color: var(--primary);
}

.selo__ponto {
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: currentColor;
}

/* ------------------------------------------------------- mapa de verdade */

.mapa {
  position: relative;
  isolation: isolate;
  background: var(--card);
}

/* O aspecto tem que ser exatamente o do viewBox: os alertas são HTML
   posicionado por porcentagem sobre o mesmo enquadramento que o SVG recorta.
   Nada de `min-height` aqui — em tela estreita ele esticaria a caixa, o SVG
   cortaria as laterais e os balões sairiam do lugar. */
.mapa--painel {
  aspect-ratio: 1200 / 750;
}

/* As ruas e a rota compartilham o mesmo enquadramento: a máscara em `cover` e
   o SVG em `slice` recortam a mesma área da mesma moldura 1200x750. */
.mapa__ruas {
  position: absolute;
  inset: 0;
  background: var(--ruas);
  opacity: calc(var(--ruas-alfa) * 1.3);
  -webkit-mask: url('/mapa-ruas.svg') center / cover no-repeat;
  mask: url('/mapa-ruas.svg') center / cover no-repeat;
}

.mapa__rota {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  color: var(--primary);
}

.rota {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.rota--prevista {
  stroke: var(--muted-fg);
  stroke-width: 3;
  stroke-dasharray: 1 9;
  opacity: 0.7;
}

.rota--feita {
  stroke: currentColor;
  stroke-width: 4;
  stroke-dasharray: var(--comprimento, 3000);
  stroke-dashoffset: 0;
  animation: tracar var(--ciclo-rota) linear infinite;
}

@keyframes tracar {
  from {
    stroke-dashoffset: var(--comprimento, 3000);
  }
  88%,
  96% {
    stroke-dashoffset: 0;
    opacity: 1;
  }
  to {
    stroke-dashoffset: 0;
    opacity: 0;
  }
}

.ponto {
  fill: currentColor;
}

.ponto--saida {
  opacity: 0.55;
}

.ponto__halo {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  opacity: 0.5;
}

.veiculo__halo {
  fill: currentColor;
  opacity: 0.18;
  animation: respirar 2.4s ease-in-out infinite;
}

@keyframes respirar {
  50% {
    opacity: 0.05;
    scale: 1.45;
  }
}

.veiculo__ponto {
  fill: currentColor;
  stroke: var(--card);
  stroke-width: 2.5;
}

.mapa__credito {
  position: absolute;
  right: 8px;
  bottom: 6px;
  padding: 2px 8px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--card) 78%, transparent);
  font-size: 0.6875rem;
  color: var(--muted-fg);
}

.mapa__credito a {
  color: inherit;
}


/* ---------------------------------------------------- alertas na rota */

/* Estas cinco cores são as do painel — COR_VARIANTE em
   frontend/src/lib/tracking.ts. São hex fixo lá porque as layers do MapLibre
   não aceitam `var()`, e são hex fixo aqui pelo mesmo motivo que lá: o ponto
   de evento tem anel branco e é legível nos dois temas por construção.
   Mudou o token do painel, mude aqui. */
.mapa {
  --cor-success: #008d4d;
  --cor-warning: #e17100;
  --cor-destructive: #e7000b;
  --cor-info: #155dfc;
  --cor-secondary: #555555;
  /* CORES_MAPA.contorno — o anel branco por cima do mapa. */
  --cor-contorno: #ffffff;
}

/* Cerca virtual: CORES_MAPA.cerca é `success`, o mesmo verde da marca, com
   18% de preenchimento e traço de 2,5 — igual ao cerca-map-editor. */
.cerca {
  fill: var(--cor-success);
  fill-opacity: 0.18;
  stroke: var(--cor-success);
  stroke-width: 2.5;
}

.mapa__alertas {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* O alerta acende quando o marcador passa por ele: o atraso vem de --t, a
   fração do ciclo em que aquele ponto do trajeto é alcançado. */
.alerta {
  position: absolute;
  left: var(--x);
  top: var(--y);
  --atraso: calc(var(--ciclo-rota) * var(--t));
}

.alerta--success {
  --cor: var(--cor-success);
}
.alerta--warning {
  --cor: var(--cor-warning);
}
.alerta--destructive {
  --cor: var(--cor-destructive);
}
.alerta--info {
  --cor: var(--cor-info);
}

.alerta__halo,
.alerta__ponto,
.alerta__popup {
  position: absolute;
  opacity: 0;
  animation-duration: var(--ciclo-rota);
  animation-delay: var(--atraso);
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

/* Ponto do evento: raio 7 e anel branco de 2, como a layer `eventos-pontos`
   do replay-map. */
.alerta__ponto {
  top: -7px;
  left: -7px;
  width: 14px;
  height: 14px;
  border: 2px solid var(--cor-contorno);
  border-radius: 999px;
  background: var(--cor);
  animation-name: alerta-ponto;
}

/* Halo do evento em foco: raio 14, 25% de preenchimento e contorno de 2 na
   própria cor — a mesma layer que o painel acende ao focar um evento. */
.alerta__halo {
  top: -14px;
  left: -14px;
  width: 28px;
  height: 28px;
  border: 2px solid var(--cor);
  border-radius: 999px;
  background: color-mix(in srgb, var(--cor) 25%, transparent);
  animation-name: alerta-halo;
}

/* O ponto nasce quando o marcador chega e fica de pé até o fim da volta —
   é assim que o painel mostra o trajeto: os eventos ficam marcados nele. */
@keyframes alerta-ponto {
  0% {
    opacity: 0;
    scale: 0;
  }
  2%,
  86% {
    opacity: 1;
    scale: 1;
  }
  94%,
  100% {
    opacity: 0;
    scale: 1;
  }
}

/* O halo é só o instante do foco, como o clique no pin. */
@keyframes alerta-halo {
  0% {
    opacity: 0;
    scale: 0.5;
  }
  1.5%,
  9% {
    opacity: 1;
    scale: 1;
  }
  11%,
  100% {
    opacity: 0;
    scale: 1.1;
  }
}

/* Popup no formato do `conteudoPopupEvento` + map-popup.css do painel. */
.alerta__popup {
  display: flex;
  flex-direction: column;
  gap: 6px;
  bottom: 18px;
  left: 0;
  width: 250px;
  translate: -50% 0;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--card);
  box-shadow:
    0 4px 6px -4px rgb(0 0 0 / 0.1),
    0 10px 24px -6px rgb(0 0 0 / 0.18);
  animation-name: alerta-popup;
}

/* Perto da borda de cima não cabe popup acima do ponto; perto das laterais o
   popup centralizado sairia do mapa. O gerador marca esses casos. */
.alerta--abaixo .alerta__popup {
  bottom: auto;
  top: 18px;
}

.alerta--esq .alerta__popup {
  left: -14px;
  translate: 0 0;
}

.alerta--dir .alerta__popup {
  left: auto;
  right: -14px;
  translate: 0 0;
}

@keyframes alerta-popup {
  0% {
    opacity: 0;
    scale: 0.94;
  }
  1.5%,
  9% {
    opacity: 1;
    scale: 1;
  }
  11%,
  100% {
    opacity: 0;
    scale: 0.98;
  }
}

/* Cabeçalho: bolinha na cor da severidade + nome do evento em versalete. */
.popup__cabecalho {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted-fg);
}

.popup__cabecalho::before {
  content: '';
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--cor);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--cor) 22%, transparent);
}

.popup__texto {
  font-size: 13px;
  font-weight: 500;
  line-height: 1.45;
  color: var(--fg);
  white-space: normal;
}

.popup__hora {
  padding-top: 6px;
  border-top: 1px solid var(--border);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  color: var(--muted-fg);
}

/* --------------------------------------------------------------- seções */

.secao {
  padding-block: 80px;
}

.secao--alt {
  background: color-mix(in srgb, var(--muted) 50%, var(--bg));
  border-block: 1px solid var(--border);
}

.secao__cabeca {
  max-width: 44rem;
  margin: 0 auto 48px;
  text-align: center;
}

.secao__titulo {
  font-size: clamp(1.75rem, 3.4vw, 2.25rem);
  font-weight: 700;
}

.secao__texto {
  margin-top: 16px;
  color: var(--muted-fg);
}

/* ------------------------------------------------------------- recursos */

.grade-3 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px;
}

.cartao {
  padding: 26px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--card);
}

.cartao__icone {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-bottom: 18px;
  border-radius: var(--raio);
  background: color-mix(in srgb, var(--primary) 12%, transparent);
  color: var(--primary);
}

.cartao__titulo {
  margin-bottom: 8px;
  font-size: 1.0625rem;
  font-weight: 600;
}

.cartao__texto {
  color: var(--muted-fg);
  font-size: 0.9375rem;
}

/* --------------------------------------------------------- como funciona */

.passos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 32px;
}

.passo__numero {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  margin-bottom: 20px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--primary) 12%, transparent);
  color: var(--primary);
  font-size: 1.0625rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.passo__titulo {
  margin-bottom: 8px;
  font-size: 1.1875rem;
  font-weight: 600;
}

.passo__texto {
  color: var(--muted-fg);
  font-size: 0.9375rem;
}

.destaque {
  display: flex;
  gap: 20px;
  max-width: 56rem;
  margin: 56px auto 0;
  padding: 26px 28px;
  border: 1px solid color-mix(in srgb, var(--primary) 35%, var(--border));
  border-radius: 14px;
  background: color-mix(in srgb, var(--primary) 7%, var(--card));
}

.destaque__icone {
  display: grid;
  place-items: center;
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: var(--raio);
  background: color-mix(in srgb, var(--primary) 16%, transparent);
  color: var(--primary);
}

.destaque__titulo {
  margin-bottom: 8px;
  font-size: 1.125rem;
  font-weight: 600;
}

.destaque__texto {
  font-size: 0.9375rem;
  color: var(--muted-fg);
}

.aviso {
  display: flex;
  gap: 14px;
  max-width: 56rem;
  margin: 40px auto 0;
  padding: 20px 22px;
  border: 1px solid color-mix(in srgb, var(--primary) 35%, var(--border));
  border-radius: 14px;
  background: color-mix(in srgb, var(--primary) 7%, transparent);
}

.aviso .icone {
  color: var(--primary);
  margin-top: 3px;
}

.aviso__titulo {
  margin-bottom: 4px;
  font-weight: 600;
  color: var(--primary);
}

.aviso__texto {
  font-size: 0.9375rem;
  color: var(--muted-fg);
}

/* ---------------------------------------------------------------- limites */

.limites {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 16px 28px;
  max-width: 60rem;
  margin-inline: auto;
}

.limites li {
  display: flex;
  gap: 12px;
  padding: 16px 18px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--card);
  font-size: 0.9375rem;
  color: var(--muted-fg);
}

.limites .icone {
  flex: none;
  width: 18px;
  height: 18px;
  margin-top: 3px;
  color: #c0392b;
}

:root[data-theme='dark'] .limites .icone {
  color: #ef6a5c;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .limites .icone {
    color: #ef6a5c;
  }
}

.limites strong {
  color: var(--fg);
}

/* ---------------------------------------------------------------- planos */

.planos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 24px;
  align-items: start;
}

.plano {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 30px 26px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--card);
}

.plano--destaque {
  border-color: color-mix(in srgb, var(--primary) 45%, var(--border));
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--primary) 8%, var(--card)),
    var(--card) 60%
  );
}

.plano__selo {
  position: absolute;
  top: -12px;
  left: 50%;
  translate: -50% 0;
  padding: 4px 12px;
  border-radius: 999px;
  background: var(--primary-strong);
  color: var(--primary-fg);
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
}

.plano__nome {
  font-size: 1.1875rem;
  font-weight: 600;
}

.plano__descricao {
  margin-top: 4px;
  font-size: 0.875rem;
  color: var(--muted-fg);
}

.plano__preco {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px;
  margin: 20px 0 24px;
}

.plano__valor {
  font-size: 2.5rem;
  font-weight: 700;
  letter-spacing: -0.03em;
}

.plano__periodo {
  color: var(--muted-fg);
  font-size: 0.9375rem;
}

.plano__itens {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 28px;
  font-size: 0.9375rem;
}

.plano__itens li {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.plano__itens .icone {
  width: 16px;
  height: 16px;
  margin-top: 4px;
  color: var(--primary);
}

.plano__acao {
  margin-top: auto;
}

/* ------------------------------------------------------------------- faq */

.faq {
  display: grid;
  gap: 12px;
  max-width: 52rem;
  margin-inline: auto;
}

.faq__item {
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--card);
}

.faq__pergunta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 22px;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}

.faq__pergunta::-webkit-details-marker {
  display: none;
}

/* Sinal de aberto/fechado próprio: o triângulo nativo some junto com o
   list-style, e sem indicação a linha vira um parágrafo qualquer. */
.faq__pergunta::after {
  content: '';
  flex: none;
  width: 9px;
  height: 9px;
  border: 2px solid var(--muted-fg);
  border-block-start: 0;
  border-inline-start: 0;
  rotate: 45deg;
  translate: 0 -2px;
  transition: rotate 0.2s ease;
}

.faq__item[open] .faq__pergunta::after {
  rotate: 225deg;
  translate: 0 2px;
}

.faq__resposta {
  padding: 0 22px 20px;
  font-size: 0.9375rem;
  color: var(--muted-fg);
}

/* ------------------------------------------------------------ cta final */

.final {
  text-align: center;
  padding-block: 88px;
}

.final__titulo {
  font-size: clamp(1.75rem, 3.4vw, 2.25rem);
  font-weight: 700;
}

.final__texto {
  max-width: 44rem;
  margin: 16px auto 32px;
  color: var(--muted-fg);
}

/* ---------------------------------------------------------------- rodapé */

.rodape {
  border-top: 1px solid var(--border);
  padding-block: 32px 40px;
}

.rodape__linha {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 28px;
}

.rodape__links {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin-inline-start: auto;
  font-size: 0.875rem;
}

.rodape__links a {
  color: var(--muted-fg);
  text-decoration: none;
}

.rodape__links a:hover {
  color: var(--fg);
}

.rodape__nota {
  margin-top: 20px;
  max-width: 68ch;
  font-size: 0.8125rem;
  color: var(--muted-fg);
}

/* ------------------------------------------------- documentos legais */

.doc {
  max-width: 52rem;
  padding-block: 124px 80px;
}

.doc__volta a {
  font-size: 0.875rem;
  color: var(--muted-fg);
  text-decoration: none;
}

.doc__volta a:hover {
  color: var(--fg);
}

.doc__titulo {
  margin-top: 12px;
  font-size: clamp(2rem, 4vw, 2.75rem);
  font-weight: 700;
}

.doc__resumo {
  margin-top: 18px;
  font-size: 1.0625rem;
  color: var(--muted-fg);
}

.doc__data {
  margin-top: 10px;
  font-size: 0.8125rem;
  color: var(--muted-fg);
}

.doc__indice {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 32px;
  padding: 18px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--card);
}

.doc__indice a {
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--muted);
  font-size: 0.875rem;
  text-decoration: none;
  color: var(--muted-fg);
}

.doc__indice a:hover {
  background: color-mix(in srgb, var(--primary) 14%, transparent);
  color: var(--primary);
}

.doc__secao {
  margin-top: 56px;
  scroll-margin-top: 84px;
}

.doc__secao h2 {
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
  font-size: 1.5rem;
  font-weight: 700;
}

.doc__secao h3 {
  margin-top: 32px;
  font-size: 1.0625rem;
  font-weight: 600;
}

.doc__secao p {
  margin-top: 14px;
  color: var(--muted-fg);
}

.doc__secao h2 + p {
  margin-top: 20px;
}

.doc__lista {
  display: grid;
  gap: 12px;
  margin-top: 16px;
  padding-inline-start: 0;
  color: var(--muted-fg);
}

.doc__lista li {
  position: relative;
  padding-inline-start: 20px;
}

.doc__lista li::before {
  content: '';
  position: absolute;
  inset-inline-start: 2px;
  top: 0.66em;
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--primary);
}

.doc__lista strong,
.doc__secao strong {
  color: var(--fg);
}

.doc__tabela {
  width: 100%;
  margin-top: 20px;
  border: 1px solid var(--border);
  border-radius: 14px;
  border-collapse: separate;
  border-spacing: 0;
  overflow: hidden;
  font-size: 0.9375rem;
  text-align: start;
}

.doc__tabela th,
.doc__tabela td {
  padding: 12px 16px;
  text-align: start;
  vertical-align: top;
  border-bottom: 1px solid var(--border);
}

.doc__tabela thead th {
  background: var(--muted);
  font-size: 0.8125rem;
  font-weight: 600;
}

.doc__tabela td {
  color: var(--muted-fg);
}

.doc__tabela tr:last-child td {
  border-bottom: 0;
}

.doc__secao code {
  padding: 1px 6px;
  border-radius: 5px;
  background: var(--muted);
  font-size: 0.875em;
}

.doc__controlador {
  margin-top: 28px;
  padding: 20px 22px;
  border: 1px solid color-mix(in srgb, var(--primary) 30%, var(--border));
  border-radius: 14px;
  background: color-mix(in srgb, var(--primary) 6%, var(--card));
}

.doc__controlador-titulo {
  margin-bottom: 14px;
  font-size: 0.8125rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--primary);
}

.doc__controlador dl {
  display: grid;
  gap: 10px 32px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  margin: 0;
}

.doc__controlador dt {
  font-size: 0.75rem;
  color: var(--muted-fg);
}

.doc__controlador dd {
  margin: 2px 0 0;
  font-size: 0.9375rem;
  font-weight: 500;
}

.doc__controlador a {
  color: inherit;
}

.doc__contato {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 20px;
}

@media (max-width: 560px) {
  .doc {
    padding-block: 100px 60px;
  }

  /* Tabela larga não pode empurrar a página inteira para o lado. */
  .doc__tabela {
    display: block;
    overflow-x: auto;
  }
}

/* ----------------------------------------------------------- responsivo */

@media (max-width: 1080px) {
  .topo__nav {
    gap: 18px;
  }
}

@media (max-width: 940px) {
  .topo__nav {
    display: none;
  }

  .hero {
    padding-block: 104px 64px;
  }

  .hero__grade {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    text-align: center;
  }

  .hero__linha,
  .hero__risco {
    margin-inline: auto;
  }

  .hero__acoes,
  .hero__checks {
    justify-content: center;
  }

  /* Sem `order: -1` aqui: com o aparelho maior, pôr o visual antes do texto
     empurraria a proposta inteira para fora da primeira tela no celular.
     Quem chega pelo telefone lê o título primeiro. */
  .fone {
    margin-top: 12px;
  }

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

@media (max-width: 560px) {
  .secao {
    padding-block: 60px;
  }

  .fone__tela {
    height: 620px;
  }

  .topo__acoes .btn--fantasma {
    display: none;
  }

  .destaque {
    flex-direction: column;
    gap: 14px;
  }

  /* Num mapa de ~330 px, 250 de popup encostam nas duas bordas. */
  .alerta__popup {
    width: 200px;
    padding: 10px 12px;
  }

  .popup__texto {
    font-size: 12px;
  }

}

/* ------------------------------------------------------- menos movimento */

/* Sem `animation-duration: 0` global: zerar tudo de uma vez deixa animações
   presas no primeiro quadro (a rota some, as bolhas não aparecem). Cada peça
   tem o seu estado de repouso. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .balao,
  .veiculo__halo,
  .pulso,
  .cursor {
    animation: none;
  }

  /* A onda some; o marcador continua lá, que é o que o cartão precisa dizer. */
  .local__onda {
    animation: none;
    opacity: 0.35;
  }

  .rota--feita {
    animation: none;
    stroke-dasharray: none;
  }

  /* Sem piscar: os pontos ficam todos de pé, que é o mapa de um trajeto já
     terminado. Os popups somem — no painel eles também só abrem no clique,
     e seis abertos de uma vez cobririam o mapa. */
  .alerta__ponto {
    animation: none;
    opacity: 1;
  }

  .alerta__halo,
  .alerta__popup {
    animation: none;
    display: none;
  }

  .faq__pergunta::after {
    transition: none;
  }
}
