/* ═══════════════════════════════════════════════════════════════════════════
   NexusLOS Rotas — Minimalismo / estilo suíço
   Grade, contraste alto, espaço em branco. Azul de rastreio + laranja de
   entrega. Inter para texto; JetBrains Mono para sigla, chave e dinheiro —
   número em fonte monoespaçada alinha coluna com coluna e lê-se muito melhor.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  color-scheme: light;

  --azul-500: #2563eb;
  --azul-600: #1d4ed8;
  --azul-700: #1e40af;
  --laranja-500: #ea580c;

  --fundo: #f7f9fc;
  --fundo-malha: #dce5f2;
  --papel: #ffffff;
  --papel-alto: #ffffff;
  --tinta: #0f1b2d;
  --tinta-media: #43536b;
  --tinta-fraca: #6b7c94;
  --borda: #dfe6f0;
  --borda-forte: #c3d0e2;
  --marca: var(--azul-500);
  --marca-tinta: #ffffff;
  --marca-fraca: #eaf1fe;
  --realce: #eff5ff;
  --valor: var(--laranja-500);

  --alerta: #92400e;
  --alerta-fundo: #fffaeb;
  --alerta-borda: #fcd9a4;
  --erro: #b42318;
  --erro-fundo: #fef3f2;
  --erro-borda: #fda29b;

  --sombra-1: 0 1px 2px rgba(16, 30, 54, .06);
  --sombra-2: 0 4px 14px -4px rgba(16, 30, 54, .12), 0 1px 3px rgba(16, 30, 54, .06);
  --sombra-3: 0 18px 40px -12px rgba(16, 30, 54, .22), 0 2px 8px rgba(16, 30, 54, .08);

  --raio: 12px;
  --raio-g: 18px;

  --rapido: 140ms;
  --medio: 240ms;
  --lento: 420ms;
  --saida: cubic-bezier(.16, 1, .3, 1);
}

[data-tema="escuro"] {
  color-scheme: dark;

  --fundo: #0b1220;
  --fundo-malha: #1a2740;
  --papel: #121c2e;
  --papel-alto: #16233a;
  --tinta: #e9eff8;
  --tinta-media: #a6b6cc;
  --tinta-fraca: #7d8ea8;
  --borda: #24334d;
  --borda-forte: #33455f;
  --marca: #5c9dff;
  --marca-tinta: #06122a;
  --marca-fraca: #17243c;
  --realce: #1a2942;
  --valor: #ff9c5b;

  --alerta: #fbd38d;
  --alerta-fundo: #2a2113;
  --alerta-borda: #4d3c1c;
  --erro: #fda29b;
  --erro-fundo: #2a1615;
  --erro-borda: #5b2724;

  --sombra-1: 0 1px 2px rgba(0, 0, 0, .4);
  --sombra-2: 0 4px 14px -4px rgba(0, 0, 0, .55);
  --sombra-3: 0 18px 40px -12px rgba(0, 0, 0, .7);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--fundo);
  color: var(--tinta);
  font-family: Inter, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* Malha de fundo: pontinhos discretos que somem para baixo. Dá textura sem
   competir com o conteúdo, que é o ponto do estilo suíço. */
.malha {
  position: fixed;
  inset: 0 0 auto 0;
  height: 420px;
  z-index: -1;
  background-image: radial-gradient(circle at center, var(--fundo-malha) 1px, transparent 1px);
  background-size: 22px 22px;
  -webkit-mask-image: linear-gradient(to bottom, #000, transparent);
  mask-image: linear-gradient(to bottom, #000, transparent);
  opacity: .7;
  pointer-events: none;
}

.pular {
  position: absolute;
  left: -9999px;
  top: .5rem;
  z-index: 100;
  padding: .6rem 1rem;
  background: var(--marca);
  color: var(--marca-tinta);
  border-radius: 8px;
  font-weight: 600;
  text-decoration: none;
}
.pular:focus { left: .75rem; }

/* ── cabeçalho ─────────────────────────────────────────────────────────── */

.cabecalho { padding: 1.75rem 1rem .5rem; }

.cabecalho-conteudo {
  max-width: 54rem;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.marca { display: flex; align-items: center; gap: .85rem; }

.marca-simbolo { width: 40px; height: 40px; color: var(--marca); flex: none; }

/* O tracinho da marca “percorre” a rota uma vez ao carregar. */
.marca-trilha {
  stroke-dasharray: 4 5;
  animation: correr 1.6s linear infinite;
}
@keyframes correr { to { stroke-dashoffset: -18; } }

.marca-destino { animation: pulsar 2.4s var(--saida) infinite; transform-origin: 32px 10px; }
@keyframes pulsar {
  0%, 70%, 100% { transform: scale(1); opacity: 1; }
  35%           { transform: scale(1.18); opacity: .75; }
}

.marca-texto { display: flex; flex-direction: column; line-height: 1.15; }
.marca-nome { font-size: 1.15rem; font-weight: 700; letter-spacing: -.015em; }
.marca-sub {
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--tinta-fraca);
}

.botao-redondo {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  padding: 0;
  color: var(--tinta-media);
  background: var(--papel);
  border: 1px solid var(--borda);
  border-radius: 50%;
  box-shadow: var(--sombra-1);
  cursor: pointer;
  transition: color var(--rapido), border-color var(--rapido), transform var(--rapido);
}
.botao-redondo:hover { color: var(--marca); border-color: var(--borda-forte); transform: translateY(-1px); }
.botao-redondo svg { width: 20px; height: 20px; grid-area: 1 / 1; transition: opacity var(--medio), transform var(--medio); }
.icone-lua { opacity: 0; transform: rotate(-45deg) scale(.6); }
[data-tema="escuro"] .icone-sol { opacity: 0; transform: rotate(45deg) scale(.6); }
[data-tema="escuro"] .icone-lua { opacity: 1; transform: none; }

/* ── painel ────────────────────────────────────────────────────────────── */

.painel { max-width: 54rem; margin: 0 auto; padding: 1rem 1rem 2rem; }

/* SEM `overflow: hidden`: a lista dos campos precisa sair pela borda do cartão. No SPOT a
   tipologia é o último campo e o corte escondia CARRETA e BITREM (17/10/2026). Quem
   respeita a curva dos cantos são as abas de operação, logo abaixo. O `z-index` põe a
   lista aberta por cima do mapa e dos cartões de resultado, que vêm depois. */
.cartao-consulta {
  position: relative;
  z-index: 1;
  background: var(--papel);
  border: 1px solid var(--borda);
  border-radius: var(--raio-g);
  box-shadow: var(--sombra-2);
  animation: subir var(--lento) var(--saida) both;
}

@keyframes subir {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

/* ── seletor de operação ───────────────────────────────────────────────── */

/* Colunas iguais para quantas operações houver. `auto-fit` em vez de um número fixo
   porque a quantidade visível muda em tempo de execução: quem só tem acesso a uma vê uma
   aba só, e a grade precisa acompanhar sem regra por operação. */
.operacoes {
  position: relative;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  border-bottom: 1px solid var(--borda);
  border-radius: calc(var(--raio-g) - 1px) calc(var(--raio-g) - 1px) 0 0;
  background: linear-gradient(var(--realce), transparent);
}

/* A posição e a largura vêm do JS (--indicador-x e --indicador-w), medidas do botão
   ativo. Uma regra por operação, como era com duas, não sobrevive a abas escondidas:
   quem não vê a Amazon teria o traço parado sobre uma aba invisível. */
.operacoes-indicador {
  position: absolute;
  bottom: -1px;
  left: 0;
  width: var(--indicador-w, 50%);
  height: 2px;
  background: var(--marca);
  transform: translateX(var(--indicador-x, 0));
  transition: transform var(--medio) var(--saida), width var(--medio) var(--saida);
}

.operacao {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .55rem;
  padding: 1rem;
  font: inherit;
  font-weight: 600;
  color: var(--tinta-fraca);
  background: none;
  border: 0;
  cursor: pointer;
  transition: color var(--rapido), background var(--rapido);
}
.operacao svg { width: 20px; height: 20px; transition: transform var(--medio) var(--saida); }
.operacao:hover { color: var(--tinta-media); background: var(--realce); }
/* O fundo do hover encosta nos cantos do cartão. Primeira e última VISÍVEIS, não do DOM:
   quem não vê a Amazon tem a Shopee na ponta. */
.operacao:nth-child(1 of .operacao:not([hidden])) { border-top-left-radius: calc(var(--raio-g) - 1px); }
.operacao:nth-last-child(1 of .operacao:not([hidden])) { border-top-right-radius: calc(var(--raio-g) - 1px); }
.operacao.ativa { color: var(--marca); }
.operacao.ativa svg { transform: scale(1.08); }

/* ── formulário ────────────────────────────────────────────────────────── */

.formulario {
  display: grid;
  gap: 1.15rem;
  padding: 1.5rem;
}
@media (min-width: 40rem) {
  .formulario { grid-template-columns: 1fr 1fr; }
  .campo-largo, .trilha, .acao { grid-column: 1 / -1; }
}

.campo { display: grid; gap: .4rem; min-width: 0; }

label {
  display: flex;
  align-items: center;
  gap: .5rem;
  font-size: .8rem;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--tinta-media);
}

.opcional {
  padding: .1rem .4rem;
  font-size: .65rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--tinta-fraca);
  background: var(--realce);
  border-radius: 999px;
}

/* ── combo ─────────────────────────────────────────────────────────────── */

.combo { position: relative; }

.combo input {
  width: 100%;
  padding: .7rem 2.4rem .7rem .8rem;
  font: inherit;
  font-size: .95rem;
  color: var(--tinta);
  background: var(--papel-alto);
  border: 1px solid var(--borda-forte);
  border-radius: var(--raio);
  box-shadow: var(--sombra-1);
  transition: border-color var(--rapido), box-shadow var(--rapido), background var(--rapido);
}
.combo input::placeholder { color: var(--tinta-fraca); }
.combo input:hover:not(:disabled) { border-color: var(--marca); }
.combo input:focus {
  outline: none;
  border-color: var(--marca);
  box-shadow: 0 0 0 3px var(--marca-fraca);
}
.combo input:disabled {
  background: var(--fundo);
  color: var(--tinta-fraca);
  border-color: var(--borda);
  box-shadow: none;
  cursor: not-allowed;
}

/* Campo com valor escolhido: sigla e tipologia em monoespaçada. */
.combo input.preenchido {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-weight: 500;
  font-size: .9rem;
}

.combo-seta {
  position: absolute;
  top: 0;
  right: 0;
  display: grid;
  place-items: center;
  width: 2.4rem;
  height: 100%;
  padding: 0;
  color: var(--tinta-fraca);
  background: none;
  border: 0;
  border-radius: 0 var(--raio) var(--raio) 0;
  cursor: pointer;
}
.combo-seta svg { width: 18px; height: 18px; transition: transform var(--medio) var(--saida); }
.combo-seta:hover { color: var(--marca); }
.combo[data-aberto="sim"] .combo-seta svg { transform: rotate(180deg); }
.combo input:disabled ~ .combo-seta { cursor: not-allowed; opacity: .35; }

.combo-lista {
  position: absolute;
  z-index: 30;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  max-height: 16rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  margin: 0;
  padding: .3rem;
  list-style: none;
  background: var(--papel-alto);
  border: 1px solid var(--borda-forte);
  border-radius: var(--raio);
  box-shadow: var(--sombra-3);
  animation: abrirLista var(--rapido) var(--saida);
}
@keyframes abrirLista {
  from { opacity: 0; transform: translateY(-6px) scale(.99); }
  to   { opacity: 1; transform: none; }
}

.combo-item {
  display: flex;
  align-items: baseline;
  gap: .55rem;
  padding: .5rem .6rem;
  border-radius: 8px;
  font-size: .9rem;
  cursor: pointer;
  transition: background var(--rapido);
}
.combo-item .sigla {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-weight: 700;
  font-size: .85rem;
  color: var(--tinta);
  flex: none;
}
.combo-item .cidade {
  color: var(--tinta-fraca);
  font-size: .85rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.combo-item.destacado { background: var(--marca-fraca); }
.combo-item.destacado .sigla { color: var(--marca); }

.combo-vazio { padding: .7rem .6rem; color: var(--tinta-fraca); font-size: .875rem; }
/* Orientação no topo da lista de cidades: não é opção, então não parece uma. */
.combo-dica {
  padding: .55rem .6rem .45rem;
  color: var(--tinta-fraca);
  font-size: .78rem;
  line-height: 1.35;
  cursor: default;
}

/* ── trilha do trajeto ─────────────────────────────────────────────────── */

.trilha {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .35rem .5rem;
  min-height: 2rem;
  padding: .7rem .85rem;
  background: var(--realce);
  border: 1px dashed var(--borda-forte);
  border-radius: var(--raio);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: .82rem;
  font-weight: 500;
}
.trilha:empty { display: none; }

.trilha-parada {
  padding: .2rem .5rem;
  color: var(--tinta);
  background: var(--papel);
  border: 1px solid var(--borda-forte);
  border-radius: 6px;
  animation: entrarParada var(--medio) var(--saida) both;
}
@keyframes entrarParada {
  from { opacity: 0; transform: translateX(-6px) scale(.94); }
  to   { opacity: 1; transform: none; }
}

.trilha-seta { color: var(--marca); flex: none; }
.trilha-seta svg { width: 16px; height: 16px; display: block; }

.trilha-tipo {
  margin-left: auto;
  padding: .2rem .55rem;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .05em;
  color: var(--marca);
  background: var(--marca-fraca);
  border-radius: 999px;
}

/* Com tipologia E serviço na trilha, só o primeiro empurra: o `margin-left: auto` no
   segundo abriria um vão entre os dois. */
.trilha-servico { margin-left: 0; }

/* ── modalidade: BID ou SPOT, só no Mercado Livre ──────────────────────── */

.modalidades {
  display: inline-flex;
  gap: .2rem;
  padding: .25rem;
  margin: 1.1rem 1.5rem 0;
  background: var(--realce);
  border: 1px solid var(--borda);
  border-radius: 999px;
}

.modalidade {
  padding: .38rem 1.15rem;
  font: inherit;
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .02em;
  color: var(--tinta-fraca);
  background: none;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  transition: color var(--rapido), background var(--rapido);
}
.modalidade:hover { color: var(--tinta); }
/* Cor MAIS peso: um par de botões em que só a cor muda fica ilegível para quem não
   distingue as duas, e aqui a escolha troca a tabela inteira. */
.modalidade.ativa {
  color: var(--marca-tinta);
  background: var(--marca);
}

.campos-spot {
  display: grid;
  gap: 1.15rem;
  grid-column: 1 / -1;
}
@media (min-width: 40rem) {
  .campos-spot { grid-template-columns: 1fr 1fr; }
}

/* Discreto: a parada extra é exceção, não o caminho comum. */
.parada-mais {
  justify-self: start;
  padding: .3rem 0;
  font: inherit;
  font-size: .8rem;
  font-weight: 600;
  color: var(--marca);
  background: none;
  border: 0;
  cursor: pointer;
}
.parada-mais:hover { text-decoration: underline; }

/* O aviso de uso da tabela SPOT: presente, porque o valor depende de acionamento prévio do
   cliente, mas sem competir com o número. */
.aviso-spot {
  margin: .9rem 0 0;
  font-size: .75rem;
  line-height: 1.5;
  color: var(--tinta-fraca);
  border-top: 1px solid var(--borda);
  padding-top: .75rem;
}

/* ── serviço: o quarto passo, só do Mercado Livre ──────────────────────── */

.rotulo-servico {
  display: flex;
  align-items: center;
  gap: .5rem;
  font-size: .8rem;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--tinta-media);
}

.servicos {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .6rem;
}

.servico {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  padding: .7rem .8rem;
  font: inherit;
  font-size: .86rem;
  font-weight: 600;
  color: var(--tinta-media);
  background: var(--papel);
  border: 1px solid var(--borda-forte);
  border-radius: 10px;
  cursor: pointer;
  transition: color var(--rapido), border-color var(--rapido), background var(--rapido);
}
.servico:hover { color: var(--tinta); border-color: var(--marca); background: var(--realce); }

/* O estado marcado é cor MAIS traço: um par de botões em que só a cor muda fica ilegível
   para quem não distingue as duas, e aqui a escolha errada custa dinheiro. */
.servico.ativo {
  color: var(--marca);
  background: var(--marca-fraca);
  border-color: var(--marca);
  box-shadow: inset 0 0 0 1px var(--marca);
}
.servico-icone { width: 18px; height: 18px; flex: none; }

/* Um serviço só não é escolha: não pode parecer um botão a clicar. */
.servicos:has(.servico:only-child) .servico { cursor: default; }

/* ── botão ─────────────────────────────────────────────────────────────── */

.acao {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .55rem;
  min-height: 48px;
  padding: .8rem 1.25rem;
  font: inherit;
  font-size: 1rem;
  font-weight: 600;
  color: var(--marca-tinta);
  background: var(--marca);
  border: 0;
  border-radius: var(--raio);
  box-shadow: var(--sombra-2);
  cursor: pointer;
  transition: background var(--rapido), transform var(--rapido), box-shadow var(--rapido);
}
.acao svg { width: 19px; height: 19px; }
.acao:hover:not(:disabled) { background: var(--azul-600); transform: translateY(-1px); box-shadow: var(--sombra-3); }
.acao:active:not(:disabled) { transform: translateY(0); }
.acao:disabled {
  color: var(--tinta-fraca);
  background: var(--borda);
  box-shadow: none;
  cursor: not-allowed;
}

:focus-visible { outline: 2px solid var(--marca); outline-offset: 2px; }

/* ── resultados ────────────────────────────────────────────────────────── */

.saida { margin-top: 1.25rem; display: grid; gap: .9rem; }

.cartao {
  padding: 1.35rem;
  background: var(--papel);
  border: 1px solid var(--borda);
  border-left: 3px solid var(--marca);
  border-radius: var(--raio-g);
  box-shadow: var(--sombra-2);
  animation: entrarCartao var(--lento) var(--saida) both;
  animation-delay: calc(var(--i, 0) * 70ms);
}
@keyframes entrarCartao {
  from { opacity: 0; transform: translateY(16px) scale(.98); }
  to   { opacity: 1; transform: none; }
}

.cartao-topo {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.1rem;
}
.cartao h2 {
  margin: 0 0 .3rem;
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: -.01em;
}
.cartao .chave {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: .74rem;
  color: var(--tinta-fraca);
  word-break: break-all;
}

.selo {
  flex: none;
  padding: .28rem .6rem;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--marca);
  background: var(--marca-fraca);
  border-radius: 999px;
}

/* Tipologia e serviço empilham no celular e ficam lado a lado a partir do momento em que
   cabem, sempre alinhados à direita do título. */
.selos {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: .35rem;
  flex: none;
}

/* O serviço é a moldura do valor (ida, ou ida e volta), não a natureza da carga. Cor
   própria para não se confundir com a tipologia, que fica ao lado. */
.selo-servico {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  color: var(--valor);
  background: color-mix(in srgb, var(--valor) 12%, transparent);
}
.selo-icone { width: 14px; height: 14px; flex: none; }

/* A homologação (LINE HAUL, SPOT...) diz para qual solicitação aquele teto vale. Contorno
   em vez de fundo: é qualificação da linha, não mais uma medida do valor. */
.selo-homologacao {
  background: transparent;
  box-shadow: inset 0 0 0 1px currentColor;
}

.medidas { display: grid; gap: 1rem; margin: 0; }
@media (min-width: 30rem) { .medidas { grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); } }

/* O cartão do SPOT tem até QUATRO medidas, e duas delas são valores em real. Com a largura
   mínima do BID (9rem) as colunas se espremem e o teto encosta na precificação ao lado —
   duas quantias em dinheiro coladas se leem como uma só. */
.cartao-spot .medidas { gap: 1rem 1.4rem; }
@media (min-width: 30rem) {
  .cartao-spot .medidas { grid-template-columns: repeat(auto-fit, minmax(11.5rem, 1fr)); }
}

.medida { display: flex; align-items: center; gap: .7rem; }
.medida-icone {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  flex: none;
  color: var(--tinta-fraca);
  background: var(--realce);
  border-radius: 10px;
}
.medida-icone svg { width: 19px; height: 19px; }
.medida.destaque .medida-icone { color: var(--valor); background: color-mix(in srgb, var(--valor) 12%, transparent); }

dt {
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--tinta-fraca);
}
dd {
  margin: 0;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 1.3rem;
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.2;
}
dd.valor { color: var(--valor); font-size: 1.55rem; }

.marca-linha {
  margin: 1.1rem 0 0;
  padding-top: .8rem;
  border-top: 1px dashed var(--borda);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: .76rem;
  color: var(--tinta-fraca);
}

/* ── avisos e estados ──────────────────────────────────────────────────── */

.aviso, .erro-caixa {
  display: flex;
  gap: .75rem;
  margin: 0;
  padding: .95rem 1.1rem;
  border-radius: var(--raio);
  font-size: .9rem;
  line-height: 1.5;
  animation: subir var(--medio) var(--saida) both;
}
.aviso svg, .erro-caixa svg { width: 20px; height: 20px; flex: none; margin-top: .1rem; }

.aviso {
  color: var(--alerta);
  background: var(--alerta-fundo);
  border: 1px solid var(--alerta-borda);
}
.erro-caixa {
  color: var(--erro);
  background: var(--erro-fundo);
  border: 1px solid var(--erro-borda);
  font-weight: 500;
}

.vazio {
  display: grid;
  justify-items: center;
  gap: .5rem;
  padding: 2.5rem 1rem;
  text-align: center;
  color: var(--tinta-fraca);
}
.vazio svg { width: 150px; height: auto; color: var(--borda-forte); }
.vazio p { margin: 0; font-size: .9rem; max-width: 26rem; }

/* Carrinho percorrendo a rota da ilustração vazia. */
.vazio-rota { stroke-dasharray: 5 6; animation: correr 2.4s linear infinite; }
.vazio-veiculo { animation: percorrer 3.6s var(--saida) infinite; }
@keyframes percorrer {
  0%, 100% { transform: translateX(0); }
  50%      { transform: translateX(96px); }
}

/* ── esqueleto de carregamento ─────────────────────────────────────────── */

.esqueleto {
  padding: 1.35rem;
  background: var(--papel);
  border: 1px solid var(--borda);
  border-left: 3px solid var(--borda-forte);
  border-radius: var(--raio-g);
}
.osso {
  height: 12px;
  border-radius: 6px;
  background: linear-gradient(90deg, var(--realce) 25%, var(--borda) 50%, var(--realce) 75%);
  background-size: 200% 100%;
  animation: brilhar 1.4s linear infinite;
}
.osso + .osso { margin-top: .8rem; }
.osso.titulo { width: 55%; height: 16px; }
.osso.curto  { width: 30%; }
.osso.grande { width: 42%; height: 30px; margin-top: 1.4rem; }
@keyframes brilhar { to { background-position: -200% 0; } }

/* ── rodapé ────────────────────────────────────────────────────────────── */

.rodape {
  max-width: 54rem;
  margin: 0 auto;
  padding: 1rem 1rem 3rem;
  text-align: center;
}
.rodape p { margin: 0; font-size: .8rem; color: var(--tinta-fraca); }

/* ═══════════════════════════════════════════════════════════════════════════
   Movimento reduzido.
   Quem liga isso no sistema costuma fazê-lo por enjoo, vertigem ou
   enxaqueca — a página inteira para, e nada aqui depende de animação para
   ser entendido ou operado. O brilho do esqueleto vira estático, e não
   pulsante, porque o pulso é justamente o que incomoda.
   ═══════════════════════════════════════════════════════════════════════════ */

html[data-movimento="reduzido"] { scroll-behavior: auto; }

html[data-movimento="reduzido"] *,
html[data-movimento="reduzido"] *::before,
html[data-movimento="reduzido"] *::after {
  animation-duration: .001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: .001ms !important;
}

html[data-movimento="reduzido"] .osso { background: var(--realce); }
html[data-movimento="reduzido"] .acao:hover:not(:disabled),
html[data-movimento="reduzido"] .botao-redondo:hover { transform: none; }

/* ═══════════════════════════════════════════════════════════════════════════
   CELULAR
   O layout já nasce em uma coluna e só vira duas a partir de 40rem — mas
   telefone não é só largura menor: é dedo em vez de ponteiro. Daí os alvos de
   toque de 44px e, principalmente, os 16px nos campos: abaixo disso o iOS dá
   zoom sozinho ao focar um input, a página salta e o usuário tem de fechar o
   zoom na mão a cada campo.
   ═══════════════════════════════════════════════════════════════════════════ */

@media (max-width: 40rem) {
  body { font-size: 15px; }

  .cabecalho { padding: 1rem .9rem .25rem; }
  .marca-simbolo { width: 34px; height: 34px; }
  .marca-nome { font-size: 1.02rem; }
  .painel { padding: .75rem .9rem 1.5rem; }
  .formulario { padding: 1.1rem; gap: 1rem; }

  /* 16px exatos: é o piso abaixo do qual o Safari do iPhone dá zoom no foco. */
  .combo input {
    font-size: 16px;
    min-height: 46px;
    padding: .75rem 2.9rem .75rem .85rem;
  }
  .combo input.preenchido { font-size: 15px; }

  .combo-seta { width: 2.9rem; }
  .combo-seta svg { width: 20px; height: 20px; }

  /* Alvo de toque confortável na lista, e altura menor para o teclado virtual
     não empurrar a lista para fora da tela. */
  .combo-item { padding: .7rem .65rem; min-height: 44px; align-items: center; }
  .combo-lista { max-height: 13rem; }

  .botao-redondo { width: 44px; height: 44px; }

  .operacao { padding: .9rem .5rem; font-size: .92rem; }
  .operacao svg { width: 18px; height: 18px; }

  .trilha { font-size: .78rem; padding: .6rem .7rem; }
  .trilha-tipo { margin-left: 0; }

  .acao { min-height: 50px; }

  .cartao, .esqueleto { padding: 1.1rem; border-radius: 14px; }
  .cartao-topo { flex-direction: column; gap: .6rem; }
  .selo { align-self: flex-start; }
  .medidas { gap: .85rem; }
  dd { font-size: 1.2rem; }
  dd.valor { font-size: 1.4rem; }

  .vazio { padding: 1.75rem .5rem; }
  .vazio svg { width: 130px; }
}

/* Telas bem estreitas (iPhone SE e similares): a chave longa da Shopee não
   pode alargar o cartão e criar rolagem horizontal na página inteira. */
@media (max-width: 24rem) {
  .cartao .chave { font-size: .68rem; }
  .medida-icone { width: 34px; height: 34px; }
  .operacao { gap: .35rem; }
}

/* Entalhe e barra inferior do iPhone. */
@supports (padding: max(0px)) {
  .cabecalho { padding-left: max(.9rem, env(safe-area-inset-left)); padding-right: max(.9rem, env(safe-area-inset-right)); }
  .painel    { padding-left: max(.9rem, env(safe-area-inset-left)); padding-right: max(.9rem, env(safe-area-inset-right)); }
  .rodape    { padding-bottom: max(3rem, calc(env(safe-area-inset-bottom) + 2rem)); }
}

/* Ponteiro grosso (dedo) em qualquer largura — inclui tablet em paisagem, que
   passaria batido por um teste só de largura. */
@media (pointer: coarse) {
  .combo-item { min-height: 44px; }
  .combo-seta { min-width: 44px; }
}

/* ── número que sobe até o valor ───────────────────────────────────────── */

.numero {
  display: inline-block;
  /* A largura em `ch` que o contador reserva só é exata com dígitos de largura
     igual — que é o caso da JetBrains Mono, mas declarar deixa explícito. */
  font-variant-numeric: tabular-nums;
}

/* Enquanto sobe, o valor fica levemente translúcido e assenta ao chegar. Sem
   isto a contagem parece um erro de renderização em vez de um efeito. */
.numero.contando { opacity: .82; }
dd.valor .numero { transition: opacity var(--medio) var(--saida); }

html[data-movimento="reduzido"] .numero.contando { opacity: 1; }

/* ── controles do cabeçalho ────────────────────────────────────────────── */

.controles { display: flex; align-items: center; gap: .5rem; }

/* O interruptor de animação nasce "desligado" quando o sistema pede menos
   movimento; ligado, ganha a cor da marca para dizer que está ativo. */
.icone-movimento-off { opacity: 0; transform: scale(.6); }
html[data-movimento="reduzido"] .icone-movimento-on { opacity: 0; transform: scale(.6); }
html[data-movimento="reduzido"] .icone-movimento-off { opacity: 1; transform: none; }
html[data-movimento="completo"] #movimento { color: var(--marca); border-color: var(--marca); }

/* ── convite para instalar ─────────────────────────────────────────────── */

.instalar {
  position: fixed;
  z-index: 60;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 1rem;
  padding-bottom: max(1rem, calc(env(safe-area-inset-bottom) + .5rem));
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--medio) var(--saida), transform var(--medio) var(--saida);
  pointer-events: none;
}
.instalar.visivel { opacity: 1; transform: none; pointer-events: auto; }

.instalar-caixa {
  max-width: 32rem;
  margin: 0 auto;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: .9rem;
  padding: 1rem;
  background: var(--papel-alto);
  border: 1px solid var(--borda-forte);
  border-radius: var(--raio-g);
  box-shadow: var(--sombra-3);
}

.instalar-icone { border-radius: 12px; align-self: start; }

.instalar-titulo { margin: 0; font-size: .98rem; font-weight: 700; }
.instalar-desc { margin: .15rem 0 0; font-size: .85rem; color: var(--tinta-media); line-height: 1.45; }

/* Passos do iPhone: aqui não há botão que instale, então o convite vira receita. */
.instalar-passos {
  margin: .7rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: .5rem;
}
.instalar-passos li {
  display: flex;
  align-items: center;
  gap: .55rem;
  font-size: .84rem;
  color: var(--tinta-media);
}
.instalar-passos svg { width: 22px; height: 22px; flex: none; color: var(--marca); }
.instalar-passos strong { color: var(--tinta); font-weight: 600; }

.instalar-acoes {
  grid-column: 1 / -1;
  display: flex;
  gap: .6rem;
  margin-top: .2rem;
}
.instalar-sim, .instalar-nao {
  flex: 1;
  min-height: 44px;
  padding: .6rem 1rem;
  font: inherit;
  font-size: .92rem;
  font-weight: 600;
  border-radius: 10px;
  cursor: pointer;
  transition: background var(--rapido), color var(--rapido);
}
.instalar-sim {
  color: var(--marca-tinta);
  background: var(--marca);
  border: 0;
}
.instalar-sim:hover { background: var(--azul-600); }
.instalar-nao {
  color: var(--tinta-media);
  background: transparent;
  border: 1px solid var(--borda-forte);
}
.instalar-nao:hover { color: var(--tinta); background: var(--realce); }

@media (min-width: 32rem) {
  .instalar-acoes { grid-column: 2; justify-content: flex-end; }
  .instalar-sim, .instalar-nao { flex: none; min-width: 8rem; }
}

/* ── tela de entrada ──────────────────────────────────────────────────────
   Aparece antes de tudo: sem sessão não há consulta. Usa os mesmos tokens do
   resto da página, então acompanha os dois temas sem regra própria.
   ───────────────────────────────────────────────────────────────────────── */

/* `[hidden]` do navegador e uma regra de ATRIBUTO; qualquer `display` num seletor de
   classe empata em especificidade e, vindo depois, vence — o elemento reaparece. Sem
   esta linha, `.entrada { display: grid }` fazia a tela de login ignorar o `hidden` e
   aparecer empilhada com o formulario de consulta. Vale para a pagina inteira, para o
   proximo `hidden` nao cair na mesma armadilha. */
[hidden] { display: none !important; }

.entrada {
  display: grid;
  place-items: center;
  padding: clamp(1.5rem, 5vw, 4rem) 1rem;
}

.entrada-caixa {
  width: min(24rem, 100%);
  display: grid;
  gap: 1rem;
  padding: clamp(1.5rem, 4vw, 2rem);
  background: var(--papel);
  border: 1px solid var(--borda);
  border-radius: var(--raio-g);
  box-shadow: var(--sombra-2);
}

.entrada-titulo {
  margin: 0;
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--tinta);
}

.entrada-desc {
  margin: -0.5rem 0 0;
  color: var(--tinta-fraca);
  font-size: 0.875rem;
}

.entrada-caixa input {
  width: 100%;
  padding: 0.7rem 0.85rem;
  font: inherit;
  color: var(--tinta);
  background: var(--fundo);
  border: 1px solid var(--borda-forte);
  border-radius: var(--raio);
}

.entrada-caixa input:focus-visible {
  outline: 2px solid var(--marca);
  outline-offset: 1px;
}

.entrada-erro {
  margin: 0;
  padding: 0.6rem 0.75rem;
  color: var(--erro);
  background: var(--erro-fundo);
  border: 1px solid var(--erro-borda);
  border-radius: var(--raio);
  font-size: 0.875rem;
}

/* Uma operação só: escolher entre uma coisa não é escolha. */
.operacoes[data-unica] { display: none; }

/* Olho de mostrar a senha. O botão fica DENTRO do campo, e o input ganha espaço à
   direita para o texto nunca correr por baixo do ícone. */
.senha-campo { position: relative; }

.senha-campo input { padding-right: 2.9rem; }

.ver-senha {
  position: absolute;
  right: .4rem;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 2.1rem;
  height: 2.1rem;
  padding: 0;
  color: var(--tinta-fraca);
  background: none;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
}

.ver-senha:hover { color: var(--tinta); background: var(--realce); }
.ver-senha:focus-visible { outline: 2px solid var(--marca); outline-offset: 1px; }
.ver-senha svg { width: 1.25rem; height: 1.25rem; }

/* Um ícone por vez: olho quando está escondida, olho cortado quando está à mostra. */
.icone-olho-corte { display: none; }
.ver-senha[aria-pressed="true"] .icone-olho { display: none; }
.ver-senha[aria-pressed="true"] .icone-olho-corte { display: block; }

/* ── quem está logado ─────────────────────────────────────────────────────
   Avatar com as iniciais + nome, à esquerda dos botões do cabeçalho. A cor do
   avatar sai do próprio nome (ver app.js): duas pessoas diferentes ficam com
   avatares distintos sem precisar de foto nem de cadastro de cor.
   ───────────────────────────────────────────────────────────────────────── */
.quem {
  display: flex;
  align-items: center;
  gap: .5rem;
  min-width: 0;              /* deixa o nome encolher em vez de empurrar os botões */
  margin-right: .15rem;
}

.quem-avatar {
  width: 2rem;
  height: 2rem;
  flex: none;
  border-radius: 999px;
}

.quem-iniciais {
  font-family: inherit;
  font-size: 15px;
  font-weight: 700;
  fill: #fff;
  letter-spacing: .02em;
}

.quem-nome {
  min-width: 0;
  max-width: 11rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: .875rem;
  font-weight: 600;
  color: var(--tinta-media);
}

/* Em tela estreita o nome sai e fica só o avatar: o cabeçalho tem quatro botões
   e o nome é a única peça aqui que pode ceder espaço sem perder função. */
@media (max-width: 32rem) {
  .quem-nome { display: none; }
}

/* Precificação sem valor na planilha (398 rotas da Shopee). O tom apagado diz que é
   ausência de dado, não um número — quem pode ver a margem precisa distinguir "não
   cadastrado" de "não autorizado". */
.sem-valor {
  color: var(--tinta-fraca);
  font-style: italic;
  font-size: .9375rem;
}

/* ── abertura ─────────────────────────────────────────────────────────────
   Depois do login: a rota pontilhada se desenha da origem ao destino e o nome
   aparece. É o gesto do símbolo do cabeçalho, em tamanho grande.

   O traçado mede 35,13 unidades no viewBox (medido com getTotalLength); 36 dá
   folga para a ponta arredondada não ficar cortada no fim do desenho.
   ───────────────────────────────────────────────────────────────────────── */
/* Enquanto a abertura está na tela, a página não rola: o painel já está montado por
   baixo dela, então a barra de rolagem aparecia ao lado do splash — movimento e ruído
   numa tela que deveria estar parada. A classe sai junto com o splash. */
html.abertura-ativa,
html.abertura-ativa body { overflow: hidden; }

.abertura {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: grid;
  place-items: center;
  background: var(--fundo);
  animation: abertura-sair .55s var(--saida) 3.7s forwards;
}

@keyframes abertura-sair {
  to { opacity: 0; visibility: hidden; }
}

.abertura-conteudo {
  display: grid;
  justify-items: center;
  gap: .35rem;
  padding: 1.5rem;
  text-align: center;
}

.abertura-simbolo {
  width: clamp(88px, 22vw, 132px);
  height: clamp(88px, 22vw, 132px);
  color: var(--marca);
  overflow: visible;
}

/* A linha se desenha da origem ao destino.

   `clip-path` NÃO serve aqui: em elemento SVG ele usa o sistema de coordenadas do
   userSpace, e `100%` não se refere à caixa do traçado — o resultado era a linha
   inteira cortada, com os dois pontos visíveis e nada entre eles.

   O jeito certo é o próprio dash: um traço sólido do tamanho do caminho (35,13 →
   36 com folga para a ponta arredondada), deslocado para fora e trazido para dentro.
   Ao terminar, o pontilhado assume e passa a correr, como no símbolo do cabeçalho. */
.abertura-trilha {
  stroke-dasharray: 36;
  stroke-dashoffset: 36;
  animation:
    abertura-desenhar 1.9s var(--saida) .25s forwards,
    abertura-pontilhar 0s linear 2.15s forwards,
    correr 1.6s linear 2.15s infinite;
}

@keyframes abertura-desenhar {
  from { stroke-dashoffset: 36; }
  to   { stroke-dashoffset: 0; }
}

/* Troca o traço sólido pelo pontilhado no instante em que a linha termina de chegar. */
@keyframes abertura-pontilhar {
  to { stroke-dasharray: 4 5; }
}

/* Origem primeiro, destino quando a linha chega: a ordem conta a viagem. */
.abertura-origem {
  transform-origin: 8px 30px;
  animation: abertura-ponto .5s var(--saida) .1s backwards;
}

.abertura-destino {
  transform-origin: 32px 10px;
  animation:
    abertura-ponto .5s var(--saida) 1.85s backwards,
    pulsar 2.4s var(--saida) 2.35s infinite;
}

@keyframes abertura-ponto {
  from { transform: scale(0); opacity: 0; }
  to   { transform: scale(1); opacity: 1; }
}

.abertura-texto {
  display: grid;
  justify-items: center;
  gap: .1rem;
  animation: abertura-subir .7s var(--saida) 2.05s backwards;
}

.abertura-nome {
  font-size: clamp(1.5rem, 6vw, 2.25rem);
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--tinta);
}

.abertura-rotas { color: var(--marca); }

.abertura-sub {
  font-size: clamp(.6875rem, 2.5vw, .8125rem);
  font-weight: 600;
  letter-spacing: .28em;
  color: var(--tinta-fraca);
}

.abertura-saudacao {
  margin: .5rem 0 0;
  font-size: clamp(.875rem, 3vw, 1rem);
  color: var(--tinta-media);
  animation: abertura-subir .7s var(--saida) 2.55s backwards;
}

.abertura-saudacao strong { color: var(--tinta); font-weight: 700; }

@keyframes abertura-subir {
  from { opacity: 0; transform: translateY(.65rem); }
  to   { opacity: 1; transform: none; }
}

/* Movimento reduzido: a abertura nem é criada (ver abertura.js). A regra global que
   zera durações não pode valer aqui — ela faria o splash sumir num piscar em vez de
   não existir, e a promessa do JS resolveria antes da tela aparecer. */

/* Mapa da consulta: mesma experiência para Amazon e Shopee. */
.mapa-rota { overflow: hidden; border: 1px solid var(--borda); border-radius: 18px; background: var(--papel); box-shadow: var(--sombra-2); margin-block: 24px; }
.mapa-cabecalho { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 22px; }
.mapa-cabecalho h2 { margin: 6px 0 0; font-size: 22px; }
.mapa-sobretitulo { color: var(--marca); font-size: 11px; font-weight: 700; letter-spacing: .14em; }
.mapa-rota button { padding: 9px 13px; border: 1px solid var(--borda-forte); border-radius: 9px; background: var(--papel); color: var(--tinta); cursor: pointer; font: inherit; }
.mapa-rota button:hover { background: var(--realce); }
.mapa-rota button:focus-visible { outline: 3px solid var(--marca); outline-offset: 3px; }
.mapa-canvas { height: clamp(300px, 52vh, 490px); width: 100%; z-index: 0; background: #e7edf2; }
.mapa-rota > p { margin: 14px 22px; color: var(--tinta-media); font-size: 13px; line-height: 1.6; }
.mapa-rota > p:empty { display: none; }
.mapa-paradas { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; padding: 0 22px 22px 46px; }
.mapa-paradas li { padding-left: 4px; font-size: 13px; line-height: 1.6; overflow-wrap: anywhere; }
.mapa-paradas li::marker { color: var(--marca); font-weight: 700; }
.mapa-paradas strong, .mapa-paradas span, .mapa-paradas small { display: block; }
.mapa-paradas span { color: var(--tinta-media); }
.mapa-paradas small { color: var(--alerta); }
.mapa-paradas button { margin-top: 8px; font-size: 12px; }
.mapa-pino span { display: grid; place-items: center; width: 32px; height: 32px; border: 3px solid white; border-radius: 50%; background: #ea580c; color: white; font: 700 13px sans-serif; box-shadow: 0 3px 10px #0005; }
.mapa-pino-origem span { background: #2563eb; }
[data-movimento="completo"] .mapa-rota { animation: mapa-entrada .45s ease-out; }
[data-movimento="completo"] .mapa-linha { animation: mapa-fluxo 1.2s linear 3; }
@keyframes mapa-entrada { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }
@keyframes mapa-fluxo { to { stroke-dashoffset: -34; } }
@media (max-width: 560px) { .mapa-cabecalho { padding: 16px; flex-wrap: wrap; } .mapa-paradas { grid-template-columns: 1fr; } }
