:root {
  /* Rail: azul-marinho do mockup de referência da Visão geral (sessão 33,
     pedido do usuário — "utilize esse azul... no tema inteiro, no caso
     sidebar"), trocando o azul-Zeo original. Item ativo em laranja, mesmo
     tratamento que o mockup usa pro nav-item.active — "azul-marinho para
     estrutura, laranja para ação". Único lugar do app (fora da Visão geral
     e do site institucional) onde --azul-rail-ativo aparece é o rail — não
     tem conflito com --azul-primario (ação em botão/link no resto do
     painel), que continua o mesmo. */
  --azul-rail: #112d4a;
  --azul-rail-hover: #183e5d;
  /* Laranja mais fechado que o #f26b3a da marca SÓ aqui: o item ativo do
     rail e o contador carregam TEXTO pequeno (13px, e 10px na tab bar do
     celular) em branco por cima. Com #f26b3a isso dá 3,05:1 — abaixo do
     mínimo de 4,5:1 pra texto pequeno; com este tom dá 4,51:1. O laranja
     da marca segue intacto onde é fundo grande ou elemento decorativo
     (traço do mapa, destaque de título, botão grande). Decisão do usuário
     na sessão 33 (BUG-023/BUG-024). */
  --azul-rail-ativo: #cf4a17;
  --rail-icone: #a9bedd;
  --azul-primario: #2f6fdb;
  --azul-primario-hover: #2557b8;
  --azul-claro: #eaf1fd;
  --fundo-painel: #f5f6f8;
  --fundo-app: #ffffff;
  --texto: #1f2937;
  --texto-secundario: #646b78;
  --borda: #e5e7eb;
  --verde: #16a34a;
  --amarelo: #d97706;
  /* Par texto/fundo de "atenção" reaproveitado em rodízio restrito, rota
     atrasada e observação de parada (DSG-011) — promovido a token porque
     aparecia idêntico, cravado à mão, em 3+ lugares. */
  --amarelo-texto: #92400e;
  --amarelo-fundo: #fef3c7;
  --amarelo-borda: #fde68a;
  --vermelho: #dc2626;
  --raio: 10px;
  --sombra: 0 2px 10px rgba(22, 48, 92, 0.12);
  --sombra-alta: 0 18px 44px rgba(15, 32, 62, 0.28);
  /* Piso de alvo de toque do painel do gestor (TASK-121/DSG-040) — o app do
     motorista já documenta 48px (motorista.css:1-3); o painel nunca teve
     nada declarado e o quadro no celular é operado pelos controles que usam
     este token abaixo de 900px. 44px é o mínimo comum de prática de touch
     UI (WCAG 2.5.8 pede só 24×24 como piso absoluto). */
  --alvo-toque: 44px;

  /* Identidade "console operacional editorial" (sessão 33, mockup de
     referência em neo2) — antes só existia escopada dentro de #vista-geral/
     #vista-entregas (ver bloco --vg-* abaixo, que virou alias destes).
     Promovida pro :root nesta sessão pra virar a paleta do app inteiro:
     botão primário, foco de campo, avatar do topo e as telas de Cadastro/
     Controle de Rotas/Configurações/Relatórios passam a usar --laranja no
     lugar de --azul-primario. --azul-primario continua existindo (ainda
     usado em alguns detalhes que não fazem parte desta rodada) — não foi
     redefinido, só deixou de ser o padrão de botão/foco. */
  --navy: #112d4a;
  --navy-2: #183e5d;
  --laranja: #f26b3a;
  --laranja-hover: #e85c2b;
  --laranja-fundo: #fff0e9;
  --marfim: #f4f3ee;
  --linha-editorial: #dde1dd;
  --sage: #d5e0da;
  --verde-editorial: #4f8f6b;
  --azul-info: #4e7d9f;
  --vermelho-editorial: #c75c4e;
}

* { box-sizing: border-box; }

/* `<button>`, `<input>`, `<select>` e `<textarea>` NÃO herdam `font-family`
   do body — caem na fonte padrão do navegador (Arial aqui). O painel vivia
   com 119 botões em Arial contra 65 em Inter e 18 em DM Sans, e a diferença
   só ficou óbvia no rail, a única lista que alterna botão e link item a
   item: o usuário leu o Arial como "negrito" ao lado do Inter e reportou
   que Cadastro/Equipe/Configurações "não estão em negrito como as demais"
   (sessão 139). A correção item a item não escala — são 119.

   `inherit` e não uma família fixa de propósito: as telas Visão geral e
   Entregas rodam em DM Sans e os números de destaque em Space Grotesk
   (design-system.md §2), então cada controle tem de pegar a fonte do
   CONTEXTO em que está, não uma única resposta global. Especificidade 0,0,1
   — qualquer regra de classe que já declare `font-family` continua vencendo
   esta, então nada do que já estava explícito muda.

   `motorista.css:36` já tinha a mesma regra desde sempre; era só o painel
   que estava sem. */
button, input, select, textarea { font-family: inherit; }

/* Qualquer regra de display de um elemento (ex.: .modal-abas-criar{display:flex})
   vence o atributo [hidden] em especificidade igual, porque origem de autor
   supera UA independente de especificidade — já mordeu duas vezes nesta sessão
   (motorista.html e aqui). Fixa isso globalmente em vez de caçar caso a caso. */
[hidden] { display: none !important; }

body {
  margin: 0;
  font-family: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  color: var(--texto);
  background: var(--fundo-app);
  -webkit-font-smoothing: antialiased;
}

/* ---------- Ícones (sprite <symbol>/<use>) ---------- */

.ico {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
  vertical-align: -3px; /* baseline do SVG fica alto sem isso — corrige o
    caso comum de ícone solto dentro de texto corrido, que não está num
    container flex (esses ignoram vertical-align, então não regride nada). */
}

.ico-sm { width: 16px; height: 16px; }

/* ---------- Layout do app (rail + painel + área principal) ---------- */

.app {
  display: grid;
  grid-template-columns: 68px 1fr;
  height: 100vh;
  /* 100vh no Safari/Chrome mobile mede a viewport com a barra de endereço
     recolhida — maior que a área visível de verdade enquanto ela está à
     mostra. A tab bar (grid-row 2, ver media query mobile abaixo) ficava
     empurrada pra fora da tela, só reaparecendo quando o scroll colapsava a
     barra do navegador. dvh acompanha a viewport visível de verdade;
     mantido o 100vh acima como fallback pra navegador sem suporte. */
  height: 100dvh;
}

/* Painel lateral fechado por padrão (vista Mapa = só mapa) — só abre 3ª
   coluna quando o JS marca .sidebar-aberta (busca, kanban, tabs). */
.app.sidebar-aberta {
  grid-template-columns: 68px 310px 1fr;
}

/* Rail expandido (toggle em #btn-expandir-rail, estado em localStorage) —
   mostra o nome de cada módulo ao lado do ícone. Precisa das 4 combinações
   porque sidebar-aberta e rail-expandida são independentes. */
.app.rail-expandida { grid-template-columns: 190px 1fr; }
.app.rail-expandida.sidebar-aberta { grid-template-columns: 190px 310px 1fr; }

.rail {
  background: var(--azul-rail);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 14px 0;
  gap: 4px;
  overflow: hidden;
}

/* O rail mistura botão (vista que troca sem navegar) e link (página
   própria) item a item — é a lista onde a fonte dos controles mais salta.
   Quem garante a mesma tipografia nos dois é a regra global de
   `button, input, select, textarea` lá em cima; não repetir aqui. */
.rail-icon {
  width: 42px;
  height: 42px;
  border-radius: 11px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  color: var(--rail-icone);
  cursor: pointer;
  border: none;
  background: transparent;
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease;
  flex-shrink: 0;
}

.rail-icon:hover { background: var(--azul-rail-hover); color: #fff; }
/* Item ativo em laranja (sessão 33) — "azul-marinho para estrutura, laranja
   para ação/onde-você-está", igual ao mockup de referência. */
.rail-icon.ativo { background: var(--azul-rail-ativo); color: #fff; box-shadow: 0 8px 18px rgba(242, 107, 58, 0.22); }

/* Rótulo de grupo ("Operação"/"Apoio") — só aparece com o rail expandido;
   retraído viraria um traço solto entre ícones sem significado nenhum. */
.rail-secao {
  display: none;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(169, 190, 221, 0.75);
  padding: 14px 12px 6px;
  white-space: nowrap;
}
.rail.expandida .rail-secao { display: block; }
.rail.expandida .rail-secao:first-of-type { padding-top: 6px; }

/* Contador de entregas do dia no rail (o "24" do mockup) — com o rail
   retraído vira um selo sobreposto no canto do ícone, senão não caberia. */
.rail-contador {
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-left: auto;
}
.rail:not(.expandida) .rail-contador {
  position: absolute;
  transform: translate(14px, -13px);
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  background: var(--azul-rail-ativo);
  font-size: 9.5px;
}
.rail:not(.expandida) .rail-icon { position: relative; }

.rail-spacer { flex: 1; }

/* Logo no rodapé do rail (não no topo — réplica do print) */
.rail-logo {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  color: #fff;
  border: none;
  cursor: pointer;
  margin-top: 6px;
  flex-shrink: 0;
}

.rail-logo:hover { background: rgba(255, 255, 255, 0.26); }
.rail-logo .ico { width: 18px; height: 18px; }

.rail-label {
  display: none;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}

.rail.expandida {
  align-items: stretch;
  padding: 14px 12px;
}

.rail.expandida .rail-icon,
.rail.expandida .rail-logo {
  width: 100%;
  border-radius: 9px;
  justify-content: flex-start;
  padding: 0 10px;
}

.rail.expandida .rail-label { display: inline; }

.painel {
  background: var(--fundo-painel);
  border-right: 1px solid var(--borda);
  display: none;
  flex-direction: column;
  overflow: hidden;
}

.painel.painel-aberta { display: flex; }

.painel-fechar {
  display: flex;
  align-self: flex-end;
  margin: 8px 8px 0 0;
  width: 32px;
  height: 32px;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
  color: var(--texto-secundario);
  cursor: pointer;
}

.painel-abas {
  display: flex;
  border-bottom: 1px solid var(--borda);
  background: #fff;
}

.painel-aba {
  flex: 1;
  padding: 15px 10px;
  font-weight: 600;
  font-size: 14px;
  color: var(--texto-secundario);
  background: none;
  border: none;
  border-bottom: 3px solid transparent;
  cursor: pointer;
  font-family: inherit;
}

.painel-aba.ativa { color: var(--laranja); border-bottom-color: var(--laranja); }

.painel-busca { padding: 12px; position: relative; display: flex; gap: 8px; }

.painel-busca-ico {
  position: absolute;
  left: 23px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--texto-secundario);
  width: 18px;
  height: 18px;
}

.painel-busca input {
  flex: 1;
  min-width: 0;
  padding: 10px 12px 10px 38px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-size: 14px;
  font-family: inherit;
  background: #fff;
}

.painel-busca select {
  flex: 0 0 auto;
  max-width: 118px;
  padding: 10px 8px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-size: 12px;
  font-family: inherit;
  background: #fff;
  color: var(--texto);
}

.painel-busca input:focus,
.campo input:focus,
.campo select:focus,
.campo textarea:focus {
  outline: 2px solid var(--laranja);
  outline-offset: -1px;
  border-color: transparent;
}

.painel-lista { overflow-y: auto; flex: 1; }

.painel-dica {
  margin: 0;
  padding: 10px 14px;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--texto-secundario);
  border-top: 1px solid var(--borda);
  background: #fff;
}

.card-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 11px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--borda);
  background: var(--fundo-painel);
  /* reset pro caso de ser um <button> (motoristas/veículos/em-rota são clicáveis) */
  border-left: none; border-right: none; border-top: none;
  width: 100%;
  text-align: left;
  font-family: inherit;
  font-size: inherit;
  color: inherit;
  cursor: default;
}

.card-item[draggable="true"] { cursor: grab; }
.card-item[draggable="true"]:hover { background: #fff; }
.card-item.arrastando { opacity: 0.45; }

.card-editavel { cursor: pointer; }
.card-editavel:hover { background: #fff; }

.card-inativo { opacity: 0.55; }

.card-item-desativar {
  border: none;
  background: none;
  color: var(--texto-secundario);
  cursor: pointer;
  padding: 6px;
  border-radius: 8px;
  display: flex;
  flex-shrink: 0;
  margin-left: auto;
}
.card-item-desativar:hover { color: var(--vermelho); background: #fef2f2; }
.card-inativo .card-item-desativar:hover { color: var(--verde); background: #f0fdf4; }

.cadastro-toggle-inativos { margin: 4px 0 10px; }

.campo-busca-lista {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-size: 14px;
  font-family: inherit;
  background: #fff;
  margin-bottom: 10px;
}
.campo-busca-lista:focus { outline: 2px solid var(--laranja); outline-offset: -1px; border-color: transparent; }

.lista-cadastro-rodape { margin-top: 10px; text-align: center; }

/* ---------- Abas do modal unificado Novo/Editar ---------- */

.modal-abas-criar {
  display: flex;
  gap: 6px;
  padding: 0 20px 14px;
  border-bottom: 1px solid var(--borda);
}

.modal-aba-criar {
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid var(--borda);
  background: #fff;
  font-size: 13px;
  font-weight: 600;
  color: var(--texto-secundario);
  cursor: pointer;
  font-family: inherit;
}

.modal-aba-criar.ativa { background: var(--laranja); color: #fff; border-color: var(--laranja); }

/* Abas de tipo do modal "Nova entrega/coleta" (#mnp-abas-tipo, sessão 120)
   — mesmo visual de `.modal-aba-criar` acima, mas classe própria: aquela é
   alvo de um listener global (ModalCadastro.ligarAbasNovo), reusar quebrava
   as 3 abas daqui (ver comentário em painel.html). */
.mnp-aba-tipo {
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid var(--borda);
  background: #fff;
  font-size: 13px;
  font-weight: 600;
  color: var(--texto-secundario);
  cursor: pointer;
  font-family: inherit;
}

.mnp-aba-tipo.ativa { background: var(--laranja); color: #fff; border-color: var(--laranja); }

.avatar {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 700;
  font-size: 13px;
  flex-shrink: 0;
}

.card-item-texto { min-width: 0; }
/* Flex (não `block`) por causa do chip de categoria que entra aqui dentro no
   card de destino: como `<strong>` tem font-size 14 e o chip é uma caixa com
   padding própria, no fluxo inline ele estourava a linha e encavalava o
   endereço logo abaixo. Alinhado ao centro e com quebra, o rótulo desce pra
   uma segunda linha em vez de invadir a de baixo quando não cabe. */
.card-item strong { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 14px; }

.card-item span {
  display: block;
  font-size: 12px;
  color: var(--texto-secundario);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.card-item-atribuir {
  flex: 1 1 100%;
  margin-top: 2px;
  font-size: 11.5px;
  padding: 5px 6px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: #fff;
  color: var(--texto);
  font-family: inherit;
}

.lista-vazia {
  padding: 28px 18px;
  text-align: center;
  color: var(--texto-secundario);
  font-size: 13px;
  line-height: 1.6;
}
.lista-vazia.erro { color: var(--vermelho); background: #fef2f2; border-radius: var(--raio); }

.area-principal { display: flex; flex-direction: column; overflow: hidden; }

/* Barra fixa acima das 3 vistas (Visão geral/Mapa/Quadro) — não esconde
   nem troca com a navegação, é onde o sino de notificações mora agora
   (antes só existia dentro do Mapa). */
.topbar {
  flex-shrink: 0;
  height: 58px;
  padding: 0 22px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: #fff;
  border-bottom: 1px solid var(--borda);
}

.topbar-breadcrumb { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--texto-secundario); }
.topbar-breadcrumb strong { color: var(--texto); font-weight: 600; }
.topbar-divisor { color: var(--borda); }

.topbar-acoes { display: flex; align-items: center; gap: 14px; }

.topbar-data {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  color: var(--texto-secundario);
  padding-right: 14px;
  border-right: 1px solid var(--borda);
}
.topbar-data .ico { color: var(--texto-secundario); }

/* Selo de versão clicável (abre o changelog). Discreto de propósito: é
   referência, não ação do dia a dia. */
.topbar-versao {
  padding: 3px 9px;
  border: 1px solid var(--borda);
  border-radius: 999px;
  background: transparent;
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--texto-secundario);
  cursor: pointer;
  white-space: nowrap;
}
.topbar-versao:hover {
  color: var(--laranja);
  border-color: var(--laranja);
}

.topbar-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  /* Sage do mockup de referência (neo2), não mais azul-primário — pedido do
     usuário pra combinar com o tema navy+laranja da Visão geral. */
  background: var(--sage);
  color: var(--navy);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  flex-shrink: 0;
}

@media (max-width: 600px) {
  /* No celular o header fica apertado: data e versão são referência, não
     ação — saem primeiro pra o sino e o avatar continuarem alcançáveis. */
  .topbar-data,
  .topbar-versao { display: none; }
}

.area-conteudo { position: relative; flex: 1; min-height: 0; overflow: hidden; }

#vista-geral, #vista-entregas, #vista-mapa, #vista-kanban-wrap, #vista-destinos { position: absolute; inset: 0; }
#vista-mapa[hidden], #vista-destinos[hidden] { display: none; }

.mapa { width: 100%; height: 100%; }

/* "© OpenStreetMap" é exigência da licença ODbL dos tiles
   (tile.openstreetmap.org) — a política do OSM proíbe explicitamente
   esconder isso em termos de uso/rodapé/página de créditos, tem que ser
   elemento visível do próprio mapa. Discreto (fonte pequena, fundo quase
   transparente) é o que dá pra fazer sem descumprir a regra — nunca
   `display: none` nem opacidade zero, e a fonte não pode encolher a ponto
   de virar ilegível (isso equivaleria a esconder, só que por outro
   caminho). 8px/0.32 é o piso que ainda dá pra ler; pediram menor/mais
   transparente ainda e é aqui que a régua para. `App.iniciarMapa`/
   `abrirMapaDestinos` já tiram o prefixo "Leaflet |" (esse sim é só
   cortesia da lib, sem exigência nenhuma por trás). */
.leaflet-control-attribution {
  background: rgba(255, 255, 255, 0.32) !important;
  font-size: 8px !important;
  padding: 0 3px !important;
  line-height: 1.5 !important;
}

/* ---------- Visão geral + Entregas (telas novas da sessão 33) ----------
   Os --vg-* eram uma paleta escopada só nestas duas vistas; nesta sessão a
   mesma identidade (marfim + azul-marinho + "ação laranja com intenção")
   virou a paleta do app inteiro (tokens --navy/--laranja/--marfim... no
   :root, ver topo do arquivo) — Controle de Rotas, Cadastro, Configurações
   e Relatórios entraram no mesmo visual. Os --vg-* continuam existindo só
   como alias, pra não reescrever as ~99 regras .vg-* e .ent-* já existentes. */

#vista-geral, #vista-entregas {
  --vg-navy: var(--navy);
  --vg-navy-2: var(--navy-2);
  --vg-orange: var(--laranja);
  --vg-orange-hover: var(--laranja-hover);
  --vg-orange-fundo: var(--laranja-fundo);
  --vg-cream: var(--marfim);
  --vg-verde: var(--verde-editorial);
  --vg-verde-fundo: #dbece0;
  --vg-azul: var(--azul-info);
  --vg-azul-fundo: #dce7f1;
  --vg-vermelho: var(--vermelho-editorial);
  --vg-vermelho-fundo: #fbecea;
  --vg-linha: var(--linha-editorial);
  overflow-y: auto;
  background: var(--vg-cream);
  font-family: "DM Sans", "Inter", system-ui, sans-serif;
}

#vista-geral h1, #vista-geral h2, #vista-geral h3,
#vista-geral .vg-card-valor, #vista-geral .vg-indice-numero span,
#vista-geral .vg-paradas-topo strong, #vista-geral .vg-anel span,
#vista-geral .vg-mapa-chip, #vista-geral .vg-motorista-linha strong,
#vista-entregas h1, #vista-entregas h2, #vista-entregas h3,
#vista-entregas .ent-item strong {
  font-family: "Space Grotesk", "Inter", system-ui, sans-serif;
  letter-spacing: -0.02em;
}

#vista-entregas .btn-primario,
#vista-entregas .btn-secundario {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: auto;
}
#vista-entregas .btn-primario { background: var(--vg-orange); box-shadow: 0 7px 16px rgba(242, 107, 58, 0.18); }
#vista-entregas .btn-primario:hover { background: var(--vg-orange-hover); }
#vista-entregas .vg-intro h1 { color: var(--vg-navy); }
#vista-entregas .vg-intro h1 em { font-style: normal; color: var(--vg-orange); }

.visao-geral { max-width: 1080px; margin: 0 auto; padding: 28px 24px 40px; }

.vg-intro { margin-bottom: 22px; }
.vg-intro-acoes { display: flex; gap: 10px; margin-top: 14px; flex-wrap: wrap; }

.vg-overline {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--texto-secundario);
  margin-bottom: 10px;
}

.vg-ponto-vivo { width: 7px; height: 7px; border-radius: 50%; background: #7aca8b; flex-shrink: 0; }

.vg-intro h1 { margin: 0 0 8px; font-size: 30px; line-height: 1.15; color: var(--vg-navy); }
.vg-intro h1 em { font-style: normal; color: var(--vg-orange); }
.vg-intro p { margin: 0; font-size: 14.5px; color: var(--texto-secundario); }

#vista-geral .btn-primario,
#vista-geral .btn-secundario {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: auto;
}

#vista-geral .btn-primario {
  background: var(--vg-orange);
  box-shadow: 0 7px 16px rgba(242, 107, 58, 0.18);
}
#vista-geral .btn-primario:hover { background: var(--vg-orange-hover); }

/* TASK-117: mesma base visual de .vg-card, com destaque laranja (estado
   de atenção, ver design-system.md §4) — some assim que o mínimo pra
   despachar existe (App.atualizarPrimeirosPassos). */
.vg-primeiros-passos {
  background: var(--laranja-fundo);
  border: 1px solid var(--laranja);
  border-radius: var(--raio);
  padding: 16px 18px;
  margin-bottom: 22px;
}
.vg-primeiros-passos h2 { margin: 0 0 4px; font-size: 15px; color: var(--vg-navy); }
.vg-primeiros-passos p { margin: 0; font-size: 13px; color: var(--texto-secundario); }
.vg-primeiros-passos ul { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 10px; }
.vg-primeiros-passos li a {
  display: inline-flex;
  align-items: center;
  padding: 7px 14px;
  border-radius: 999px;
  background: #fff;
  border: 1px solid var(--laranja);
  color: var(--laranja);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
}
.vg-primeiros-passos li a:hover { background: var(--laranja); color: #fff; }

.vg-cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }

.vg-card { background: #fff; border-radius: var(--raio); box-shadow: var(--sombra); padding: 16px 18px; }

.vg-card-topo { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 14px; }
.vg-card-titulo { font-size: 12.5px; font-weight: 600; color: var(--texto-secundario); }

.vg-card-icone {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  background: var(--vg-verde-fundo);
  color: var(--vg-verde);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
/* Um tom por card, igual ao mockup de referência — não é decoração
   aleatória, ajuda a diferenciar os 4 indicadores num relance. */
.vg-cards .vg-card:nth-child(2) .vg-card-icone { background: var(--vg-orange-fundo); color: var(--vg-orange); }
.vg-cards .vg-card:nth-child(3) .vg-card-icone { background: var(--vg-azul-fundo); color: var(--vg-azul); }
.vg-cards .vg-card:nth-child(4) .vg-card-icone { background: #faf2df; color: #b08b4a; }

.vg-card-valor { font-size: 26px; font-weight: 800; color: var(--vg-navy); margin-bottom: 4px; }

.vg-card-detalhe { font-size: 12.5px; font-weight: 600; color: var(--texto-secundario); }
.vg-card-detalhe.positivo { color: var(--vg-verde); }
.vg-card-detalhe.atencao { color: var(--vg-orange); }
/* Card "Em rota agora" ganhou uma 2ª linha de detalhe (sessão 38, ver
   regra técnica 78) — rotas prontas pra sair e pedidos na fila sem
   veículo são contagens diferentes (a Fila de transporte é UMA rota que
   empilha N pedidos), não cabiam mais numa frase só sem confundir. */
.vg-card-detalhe + .vg-card-detalhe { margin-top: 3px; }

@media (max-width: 900px) {
  .vg-cards { grid-template-columns: repeat(2, 1fr); }
  .vg-intro h1 { font-size: 24px; }
}

@media (max-width: 540px) {
  .vg-cards { grid-template-columns: 1fr; }
}

/* ---------- Em campo agora (UI-001, docs/ROUTE-UX-UI.md) ---------- */
/* Faixa compacta de TODAS as rotas abertas — complementa "Rota em destaque"
   (que só dá espaço grande a UMA), sem competir em peso visual com ela. */
.vg-em-campo { margin: 22px 0 0; }
.vg-em-campo-lista {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding-bottom: 2px;
}
.vg-em-campo-item {
  flex: 0 0 220px;
  background: #fff;
  border-radius: var(--raio);
  box-shadow: var(--sombra);
  padding: 12px 14px;
}
.vg-em-campo-topo { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.vg-em-campo-topo strong { font-size: 13.5px; color: var(--vg-navy); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vg-em-campo-status {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--vg-orange);
  background: var(--vg-orange-fundo);
  border-radius: 999px;
  padding: 2px 8px;
  flex-shrink: 0;
}
.vg-em-campo-motorista { display: block; font-size: 12px; color: var(--texto-secundario); margin: 2px 0 8px; }
.vg-em-campo-barra { height: 5px; border-radius: 999px; background: var(--linha-editorial); overflow: hidden; }
.vg-em-campo-barra span { display: block; height: 100%; background: var(--vg-orange); border-radius: 999px; }
.vg-em-campo-meta { display: flex; justify-content: space-between; font-size: 11.5px; color: var(--texto-secundario); margin-top: 6px; }

/* ---------- Rota em destaque ---------- */

.vg-secao-cabecalho {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 30px 0 14px;
}

.vg-secao-cabecalho h2 { margin: 2px 0 0; font-size: 18px; color: var(--vg-navy); }

#vista-geral #vg-ver-todas { background: transparent; border-color: transparent; color: var(--vg-orange); font-weight: 700; }
#vista-geral #vg-ver-todas:hover { background: var(--vg-orange-fundo); }

.vg-destaque-vazio {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 20px;
  background: #fff;
  border: 1px dashed var(--vg-linha);
  border-radius: var(--raio);
  color: var(--texto-secundario);
  font-size: 13.5px;
}
.vg-destaque-vazio .ico { color: var(--texto-secundario); flex-shrink: 0; }

.vg-destaque-grade { display: grid; grid-template-columns: 1.6fr 1fr; gap: 16px; align-items: stretch; }

.vg-mapa-card { background: #fff; border-radius: var(--raio); box-shadow: var(--sombra); overflow: hidden; display: flex; flex-direction: column; }

.vg-mapa-topo { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--vg-linha); }

.vg-mapa-chip { display: inline-flex; align-items: center; gap: 7px; font-weight: 700; font-size: 13px; color: var(--vg-navy); }
.vg-mapa-chip .vg-ponto-vivo { background: var(--vg-orange); box-shadow: 0 0 0 3px var(--vg-orange-fundo); }
/* "Prévia do dia" (sem rota em campo) — mesmo formato do chip "ao vivo",
   sem o ponto pulsante (não tem nada "ao vivo" pra sinalizar). */
.vg-mapa-chip-previa { color: var(--texto-secundario); }
.vg-mapa-chip-previa .ico { color: var(--vg-orange); }
.vg-mapa-muted { font-size: 12.5px; color: var(--texto-secundario); }
.vg-mapa-topo-direita { display: flex; align-items: center; gap: 12px; }
#vg-mapa-abrir-rotas {
  border: none;
  background: transparent;
  padding: 2px;
  color: var(--vg-orange);
  font-weight: 700;
  font-size: 11.5px;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
}
#vg-mapa-abrir-rotas:hover { text-decoration: underline; }

.vg-mini-mapa { height: 260px; width: 100%; background: var(--vg-cream); }

.vg-mapa-rodape { display: flex; gap: 22px; padding: 12px 14px; border-top: 1px solid var(--vg-linha); }
.vg-mapa-rodape strong { display: block; font-size: 13.5px; margin-top: 2px; color: var(--vg-navy); }

.vg-paradas-card { background: #fff; border-radius: var(--raio); box-shadow: var(--sombra); padding: 16px; display: flex; flex-direction: column; gap: 12px; }

.vg-paradas-topo { display: flex; align-items: center; justify-content: space-between; }
.vg-paradas-topo strong { display: block; font-size: 20px; margin-top: 2px; color: var(--vg-navy); }

.vg-anel { position: relative; width: 46px; height: 46px; flex-shrink: 0; }
.vg-anel svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.vg-anel-trilha { fill: none; stroke: var(--vg-cream); stroke-width: 4; }
.vg-anel-valor { fill: none; stroke: var(--vg-orange); stroke-width: 4; stroke-linecap: round; stroke-dasharray: 113; stroke-dashoffset: 113; transition: stroke-dashoffset 0.4s ease; }
.vg-anel span { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 10.5px; font-weight: 700; color: var(--vg-navy); }

.vg-paradas-meta { display: flex; gap: 14px; font-size: 12.5px; color: var(--texto-secundario); }

.vg-paradas-lista { display: flex; flex-direction: column; gap: 8px; max-height: 220px; overflow-y: auto; }

.vg-parada-item { display: flex; align-items: center; gap: 10px; font-size: 13px; }

.vg-parada-numero {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  background: var(--vg-navy); /* pendente ainda longe na fila — mesmo tom "next" do mockup */
}
.vg-parada-numero.entregue { background: var(--vg-verde); }
.vg-parada-numero.nao_entregue { background: var(--vg-vermelho); }
.vg-parada-numero.proxima { background: var(--vg-orange); } /* próxima parada = "ativa agora", cor de ação */

.vg-parada-item > span:not(.vg-parada-numero) { color: var(--texto); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vg-parada-item.concluida span { color: var(--texto-secundario); text-decoration: line-through; }

/* ---------- Grade inferior (despacho, índice, motorista) ---------- */

.vg-grade-inferior { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 16px; }

.vg-card-despacho { background: linear-gradient(155deg, var(--vg-navy), var(--vg-navy-2)); color: #fff; display: flex; flex-direction: column; gap: 6px; }
.vg-card-despacho .vg-card-titulo { color: rgba(255, 255, 255, 0.75); letter-spacing: 0.06em; }
.vg-card-despacho h3 { margin: 2px 0 0; font-size: 19px; }
.vg-card-despacho h3 em { font-style: normal; color: var(--vg-orange); }
.vg-card-despacho p { margin: 0 0 6px; font-size: 12.5px; opacity: 0.9; }
.vg-card-despacho .btn-secundario { align-self: flex-start; background: rgba(255, 255, 255, 0.15); border-color: rgba(255, 255, 255, 0.3); color: #fff; }
.vg-card-despacho .btn-secundario:hover { background: rgba(255, 255, 255, 0.28); }

.vg-indice-numero { display: flex; align-items: baseline; gap: 3px; margin: 8px 0 2px; }
.vg-indice-numero span { font-size: 30px; font-weight: 800; color: var(--vg-navy); }
.vg-indice-numero small { font-size: 15px; color: var(--vg-orange); font-weight: 700; }

.vg-grafico { display: flex; align-items: flex-end; gap: 4px; height: 56px; margin-top: 12px; }
.vg-grafico-vazio { font-size: 12px; color: var(--texto-secundario); align-self: center; }
.vg-barra-coluna { display: flex; flex-direction: column; align-items: center; gap: 4px; flex: 1; height: 100%; justify-content: flex-end; }
.vg-barra { width: 100%; max-width: 18px; background: var(--vg-orange-fundo); border-radius: 3px 3px 0 0; }
.vg-barra-rotulo { font-size: 9.5px; color: var(--texto-secundario); }

.vg-motorista-linha { display: flex; align-items: center; gap: 12px; margin: 8px 0 6px; }
.vg-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 700;
  font-size: 14px;
  flex-shrink: 0;
  background: var(--vg-navy);
}
.vg-motorista-linha strong { display: block; font-size: 14.5px; color: var(--vg-navy); }
.vg-motorista-linha span { font-size: 12.5px; color: var(--texto-secundario); }

/* ---------- Atividade recente ---------- */

.vg-atividade { background: #fff; border-radius: var(--raio); box-shadow: var(--sombra); padding: 16px; margin-top: 16px; }

.vg-atividade-item { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-top: 1px solid var(--vg-linha); font-size: 13px; }
.vg-atividade-item:first-child { border-top: none; }

.vg-atividade-icone {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: #fff;
}
.vg-atividade-icone.verde { background: var(--vg-verde); }
.vg-atividade-icone.vermelho { background: var(--vg-vermelho); }
.vg-atividade-icone.laranja { background: var(--vg-orange); }
.vg-atividade-icone.azul { background: var(--vg-azul); }

.vg-atividade-item > span:not(.vg-atividade-icone) { flex: 1; color: var(--texto); }
.vg-atividade-item small { color: var(--texto-secundario); font-size: 12px; flex-shrink: 0; }

@media (max-width: 900px) {
  .vg-destaque-grade { grid-template-columns: 1fr; }
  .vg-grade-inferior { grid-template-columns: 1fr; }
}

/* ---------- Tela Entregas (lista do dia) ---------- */

.ent-filtros { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }

.ent-filtro {
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--vg-linha);
  background: #fff;
  color: var(--texto-secundario);
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.ent-filtro:hover { border-color: var(--vg-orange); color: var(--vg-orange); }
.ent-filtro.ativo { background: var(--vg-orange); border-color: var(--vg-orange); color: #fff; }

.ent-lista { display: flex; flex-direction: column; gap: 10px; }

.ent-item {
  display: flex;
  align-items: center;
  gap: 14px;
  background: #fff;
  border-radius: var(--raio);
  box-shadow: var(--sombra);
  padding: 14px 18px;
}

/* Sessão 97 (pedido do usuário): clicar na entrega abre o detalhamento da
   viagem (App.abrirDetalheViagem) — só quando a parada tem rota_id (ver
   App.renderEntregas). Sombra mais alta no hover/foco é o mesmo sinal de
   "isto reage" que .card-item já usa noutras listas do painel. */
.ent-item-clicavel {
  cursor: pointer;
  transition: box-shadow 0.15s ease;
}
.ent-item-clicavel:hover,
.ent-item-clicavel:focus-visible {
  box-shadow: var(--sombra-alta);
  outline: none;
}

.ent-item-numero {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 700;
  font-size: 13px;
  background: var(--vg-navy);
}
.ent-item-numero.entregue { background: var(--vg-verde); }
.ent-item-numero.nao_entregue { background: var(--vg-vermelho); }
.ent-item-numero.proxima { background: var(--vg-orange); }

.ent-item-corpo { flex: 1; min-width: 0; }
.ent-item-corpo strong { display: block; font-size: 14.5px; color: var(--vg-navy); }
/* TASK-132 (VIS-029): `.ent-item-detalhe` reconstitui a MESMA linha única
   de sempre — dois `<span>` inline + o separador literal (" · ") viram uma
   única caixa que trunca como um todo, visualmente idêntico ao `<span>`
   solto de antes. Só o `@media` abaixo (celular) separa `.ent-item-linha1`/
   `.ent-item-linha2` em duas linhas de verdade. */
.ent-item-detalhe {
  margin: 2px 0 0;
  font-size: 12.5px;
  color: var(--texto-secundario);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
@media (max-width: 640px) {
  /* Direção (a) do achado: no celular a linha corta exatamente "quem está
     levando" (motorista/veículo/volumes/NF ficam por último e são os
     primeiros a sumir no "..."). `.ent-item-linha1` (data · endereço) é
     contexto — pode truncar. `.ent-item-linha2` (quem · carga) é a
     resposta que o gestor veio buscar — não trunca, quebra linha se
     precisar (`white-space:normal`) e ganha um pouco mais de destaque
     (`--texto` em vez de `--texto-secundario`) porque a hierarquia da
     informação também estava invertida (o dado mais importante no fim da
     linha, não no começo). */
  .ent-item-detalhe { white-space: normal; overflow: visible; text-overflow: clip; }
  .ent-item-linha1 { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .ent-item-separador { display: none; }
  .ent-item-linha2 { display: block; margin-top: 2px; color: var(--texto); font-weight: 600; }
  /* Corpo virou 2-3 linhas (apelido + linha1 + linha2, +garagem às vezes)
     — centralizar o número/check circular contra esse bloco mais alto
     ficava descentrado; alinhar pelo topo, junto do apelido. */
  .ent-item { align-items: flex-start; }
}
/* TASK-115: rota finalizada some do quadro (TASK-039) — aqui é onde
   "voltou à garagem" tem como aparecer pro gestor. */
.ent-item-garagem { display: block; font-size: 11.5px; color: var(--texto-secundario); margin-top: 2px; }

.ent-item-lado { text-align: right; flex-shrink: 0; display: flex; flex-direction: column; gap: 5px; align-items: flex-end; }

.ent-etiqueta {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
}
.ent-etiqueta.entregue { color: var(--vg-verde); background: var(--vg-verde-fundo); }
.ent-etiqueta.nao_entregue { color: var(--vg-vermelho); background: var(--vg-vermelho-fundo); }
.ent-etiqueta.pendente { color: var(--vg-orange); background: var(--vg-orange-fundo); }
.ent-etiqueta.aguardando { color: var(--vg-azul); background: var(--vg-azul-fundo); }

.ent-item-lado small { font-size: 11.5px; color: var(--texto-secundario); }

/* TASK-120 (DSG-034): o Leaflet 1.9.4 põe seus controles (`.leaflet-top`/
   `.leaflet-bottom`) em z-index ~1000, com `pointer-events:auto` nos
   filhos — um z-index de 500 aqui não só ficava visualmente atrás do
   controle "filtro por carro" (topright), ficava também INALCANÇÁVEL ao
   toque (68px de sobreposição com o painel de solicitação rápida do mapa,
   28% da largura do formulário, num celular de 390px — painel removido na
   sessão 120, virou o modal #modal-nova-parada, mas a regra de z-index
   continua valendo pro que ficou). Regra do projeto (design-system.md §7):
   overlay sobre a view do mapa precisa de z-index ≥ 2000. `.mapa-topo`
   continua stacking context próprio — o z-index interno de `.combo-lista`
   regula a ordem ENTRE IRMÃOS aqui dentro, não compete mais com o Leaflet. */
.mapa-topo {
  position: absolute;
  top: 0; left: 0; right: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 18px;
  z-index: 2000;
  pointer-events: none;
}

.mapa-topo > * { pointer-events: auto; }

.mapa-data {
  background: #fff;
  padding: 9px 15px;
  border-radius: var(--raio);
  box-shadow: var(--sombra);
  font-weight: 600;
  font-size: 14px;
  display: flex;
  align-items: center;
  gap: 9px;
}

.mapa-data .ico { width: 18px; height: 18px; color: var(--texto-secundario); }

/* Canto inferior esquerdo do mapa é o único livre: legenda (leaflet-control)
   ocupa o superior direito, zoom + atribuição do Leaflet ocupam o inferior
   direito (ver rules/design-system.md §7 pra z-index acima do Leaflet). */
.mapa-info {
  position: absolute;
  left: 18px;
  bottom: 14px;
  z-index: 2000; /* TASK-120 (DSG-034) — mesma razão do .mapa-topo acima */
  background: #fff;
  padding: 9px 15px;
  border-radius: var(--raio);
  box-shadow: var(--sombra);
  font-weight: 600;
  font-size: 13px;
  color: var(--texto-secundario);
}
.mapa-info:empty { display: none; }
.mapa-info.erro { color: var(--vermelho); }

/* Estimativa da rota sobre o traço — tooltip de HOVER (`sticky`), não mais
   permanente: ver App.desenharRotas em main.js. Some junto com a linha
   quando a configuração "mapa_mostrar_linha_reta" está desligada. */
.mapa-distancia-tooltip {
  background: #fff;
  border: 1px solid var(--borda);
  border-radius: 999px;
  box-shadow: var(--sombra);
  padding: 2px 9px;
  font-size: 11px;
  font-weight: 700;
  color: var(--texto);
}
.mapa-distancia-tooltip::before { display: none; }

/* Filtro por carro do mapa de rotas (sessão 60) — ocupa o lugar da antiga
   legenda "cor por veículo", que foi removida: ela dizia só "cada linha é um
   veículo, abra o popup pra ver qual", enquanto este painel já mostra a cor
   ao lado do nome do carro (é legenda) e ainda deixa focar numa rota.
   Controle Leaflet nativo (topright, sem colidir com o zoom que fica no
   bottomright), então o stacking sobre os panes internos do Leaflet já vem
   resolvido de graça (ver rules/design-system.md §7 — nenhum z-index manual
   aqui de propósito). */
.mapa-filtro {
  background: #fff;
  border-radius: var(--raio);
  box-shadow: var(--sombra);
  padding: 8px 10px;
  font-size: 12px;
  width: 190px;
  /* Este painel é NOSSO, mas mora dentro do `.leaflet-control-container` —
     e o Leaflet declara `font: 12px/1.5 "Helvetica Neue", Arial...` no
     container dele. Com a regra global de `font-family: inherit` nos
     controles (sessão 139), os botões daqui passariam a herdar a fonte do
     LEAFLET em vez da do painel. Declarar a família aqui corta a herança no
     ponto certo: um lugar, em vez de um `font-family` em cada botão/chip
     que este painel vier a ter. */
  font-family: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
}
.mapa-filtro[hidden] { display: none; }

.mapa-filtro-topo {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  color: var(--navy);
  margin-bottom: 6px;
}
.mapa-filtro-minimizado .mapa-filtro-topo { margin-bottom: 0; }

.mapa-filtro-topo-acoes { display: flex; align-items: center; gap: 8px; }

.mapa-filtro-limpar {
  border: none;
  background: none;
  padding: 0;
  font-family: inherit;
  font-size: 11px;
  color: var(--laranja);
  cursor: pointer;
  text-decoration: underline;
}

.mapa-filtro-minimizar {
  border: none;
  background: none;
  padding: 2px;
  display: flex;
  color: var(--navy);
  cursor: pointer;
}

/* Sessão 101: liga/desliga entre "só em rota agora" e "todas as rotas do
   dia" — largura cheia e alinhado à esquerda (diferente de
   .mapa-filtro-limpar, que é um link curto no cabeçalho) porque é a ação
   que troca o CONTEÚDO inteiro da lista acima, não só o foco de um item. */
.mapa-filtro-todas-rotas {
  display: block;
  width: 100%;
  margin-top: 8px;
  padding-top: 8px;
  border: none;
  border-top: 1px solid var(--borda);
  background: none;
  font-family: inherit;
  font-size: 11px;
  text-align: left;
  color: var(--laranja);
  cursor: pointer;
}
.mapa-filtro-minimizar:hover { color: var(--laranja); }

/* Rolagem própria: um dia com muitos carros não pode esticar o painel até
   tampar o mapa inteiro. */
.mapa-filtro-lista { display: flex; flex-direction: column; gap: 3px; max-height: 40vh; overflow-y: auto; }

/* Sessão 101: ninguém em campo agora com o filtro ligado — o painel some
   inteiro seria pior (esconderia o botão "ver todas as rotas do dia"). */
.mapa-filtro-vazio { margin: 4px 0; font-size: 12px; color: var(--texto-secundario); }

/* Chip apagado = rota escondida no mapa. Sem nenhum em foco todos ficam
   acesos (estado "ver todas"), então a lista lê como legenda pura. */
.mapa-filtro-chip {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  border: 1px solid transparent;
  background: none;
  border-radius: 7px;
  padding: 4px 6px;
  font-family: inherit;
  font-size: 12px;
  color: var(--texto);
  cursor: pointer;
  text-align: left;
}
.mapa-filtro-chip:hover { background: var(--fundo-app); }
.mapa-filtro-chip.ativo { border-color: var(--navy); background: var(--fundo-app); font-weight: 700; }
.mapa-filtro-chip i { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.mapa-filtro-chip span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mapa-filtro-chip b { font-size: 11px; color: var(--texto-secundario); }

/* Legenda de status: só aparece quando existe UMA rota no mapa (por filtro
   ou porque só há uma no dia) — é exatamente quando a cor dos pontos deixa
   de ser "o carro" e passa a ser "o status da parada". */
.mapa-filtro-rodape {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-top: 8px;
  padding-top: 7px;
  border-top: 1px solid var(--borda);
  font-size: 11px;
  color: var(--texto-secundario);
}
.mapa-filtro-rodape span { display: flex; align-items: center; gap: 6px; }
.mapa-filtro-rodape i { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }

/* `.mapa-topo-esquerda` (Entrega/Coleta/Coleta + Entrega) e o filtro acima
   moram em árvores de DOM diferentes (o filtro é um controle Leaflet
   "topright", fora de `.mapa-topo` — ver main.js::ligarFiltroVeiculosMapa) —
   nenhum dos dois sabe da largura real do outro. Em telas estreitas o grupo
   de botões (esquerda, sem limite de largura) cresce até embaixo do canto
   onde o painel já está, escondendo "Coleta" atrás dele (achado de QA,
   sessão de testes mobile 320-375px). Reserva um corredor fixo à direita
   pro controle do Leaflet em vez de adivinhar a largura exata de cada um. */
@media (max-width: 400px) {
  .mapa-topo-esquerda { max-width: calc(100% - 130px); }
  .mapa-filtro { width: 120px; }
  .mapa-filtro-lista { max-height: 30vh; }
}

/* Marcador de parada com o número da ordem (mesmo número do card no
   kanban) — ver App.desenharRotas em main.js. Cor de fundo vem de
   Cores.para(placa do veículo), pra diferenciar carros na rua ao mesmo
   tempo num mapa com várias rotas. */
.mapa-marcador-numero span {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 3px solid #fff;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.45);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
}

/* Ponto de partida fixo (empresa cadastrada em Configurações) — sempre no
   mapa, mesmo sem nenhuma rota hoje. Ver App.desenharRotas em main.js. */
/* Ponto de partida (empresa/armazém) no mapa — formato de PINO (gota),
   nunca círculo, de propósito (pedido do usuário, sessão 38: "bater o
   olho e saber que é a empresa" antes mesmo de reparar no ícone). Os
   marcadores de parada são sempre círculos com número — a silhueta
   diferente resolve mesmo quando a cor calha de coincidir (não sobrou
   cor livre: verde/vermelho/laranja/navy já são todos usados pelos
   status de parada). Maior que os 30px do círculo de parada por igual
   motivo. Camiseta no lugar da fábrica genérica: a Gordon & Smith é
   private label de confecção, não uma indústria pesada. */
.mapa-marcador-empresa span {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
  background: var(--azul-rail);
  border: 3px solid #fff;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.5);
}
.mapa-marcador-empresa .ico {
  transform: rotate(45deg); /* desfaz a rotação do pino — ícone sempre reto */
  width: 18px;
  height: 18px;
  color: #fff;
  stroke-width: 1.6;
  fill: #fff; /* camiseta branca sólida — só o contorno finava demais no
    tamanho do marcador e não lia como camiseta de longe. */
}

.botao-flutuante {
  background: #fff;
  border: none;
  width: 40px;
  height: 40px;
  border-radius: var(--raio);
  box-shadow: var(--sombra);
  cursor: pointer;
  color: var(--texto);
  display: flex;
  align-items: center;
  justify-content: center;
}

.botao-flutuante:hover { background: var(--laranja-fundo); color: var(--azul-primario); }

/* Sino de notificações — mesmos eventos que disparam aviso por WhatsApp
   (parada concluída, ver backend/notificacoes.py). "Visto" é rastreado só
   no navegador (localStorage), sem tabela de estado no servidor. */
.notificacoes-wrap { position: relative; }

.notificacoes-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--vermelho);
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.notificacoes-painel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  width: 300px;
  max-width: calc(100vw - 24px);
  max-height: 380px;
  overflow-y: auto;
  background: #fff;
  border-radius: var(--raio);
  box-shadow: var(--sombra-alta);
  z-index: 2000; /* TASK-120 (DSG-034) — era 600, perfurado pelo filtro do Leaflet (~1000) na vista Rotas */
}

/* TASK-120 (DSG-035): `right:0` ancora no `.notificacoes-wrap` (só 40px,
   o botão do sino), não na borda da tela — e o sino não é o último item
   do topbar (o avatar vem depois). Medido ao vivo (`agent-browser`,
   320px): o wrap termina em x=252, sobra só 252px pra um painel de
   ≤296px → nascia **44px** fora da tela pela esquerda (o achado original
   estimou "2px" por aritmética, sem medir em navegador — a causa real é
   essa, não só a largura). `position:fixed` com `left`/`right` fixos
   ignora onde o botão está e ancora na VIEWPORT — impossível vazar pra
   fora, em qualquer largura. Só ≤400px (mesmo piso do bloco de
   `.mapa-filtro` acima) porque em telas maiores a folga já é suficiente
   (confirmado a 390px: cabe sem ajuste). */
@media (max-width: 400px) {
  .notificacoes-painel {
    position: fixed;
    top: 64px;
    left: 12px;
    right: 12px;
    width: auto;
    max-width: none;
  }
}

.notificacoes-topo {
  padding: 12px 14px;
  font-weight: 700;
  font-size: 13px;
  border-bottom: 1px solid var(--borda);
  position: sticky;
  top: 0;
  background: #fff;
}

.notificacoes-secao {
  padding: 8px 14px 4px;
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--texto-secundario);
  background: var(--fundo-painel);
}

.notificacao-item {
  padding: 10px 14px;
  border-bottom: 1px solid var(--borda);
  font-size: 12.5px;
}
.notificacao-item:last-child { border-bottom: none; }
.notificacao-item strong { display: flex; align-items: center; gap: 5px; color: var(--texto); }
.notificacao-item strong .ico { flex-shrink: 0; }
.notificacao-item span { display: block; color: var(--texto-secundario); margin-top: 2px; }
.notificacao-item.nao-entregue strong { color: var(--vermelho); }

.notificacoes-vazio { padding: 18px 14px; text-align: center; color: var(--texto-secundario); font-size: 13px; }

.mapa-topo-esquerda { display: flex; align-items: flex-start; gap: 10px; flex-wrap: wrap; }

.mapa-acao-botao {
  border: none;
  cursor: pointer;
  font-family: inherit;
  color: var(--texto);
}

.mapa-acao-botao .ico { width: 16px; height: 16px; color: var(--laranja); }
.mapa-acao-botao:hover { background: var(--laranja-fundo); }

/* Trilha percorrida (sessão 114) — único botão desta barra que é um TOGGLE
   (os outros navegam/abrem painel); preenchido quando ligado, mesma receita
   de .modal-aba-criar.ativa. */
.mapa-acao-botao.ativo { background: var(--laranja); color: #fff; }
.mapa-acao-botao.ativo .ico { color: #fff; }

/* ---------- Mapa de destinos (sessão 60) ----------
   Mesma receita do `.mapa-topo` da vista Rotas: o mapa ocupa 100% da área e
   o painel de filtro flutua por cima (pointer-events: none no container,
   auto no painel), em vez de comer altura útil do mapa. */
.destinos-topo {
  position: absolute;
  top: 0; left: 0; right: 0;
  padding: 14px 18px;
  z-index: 2000; /* TASK-120 (DSG-034) — mesma razão do .mapa-topo (vista Rotas) */
  pointer-events: none;
}
.destinos-topo > * { pointer-events: auto; }

.destinos-painel {
  background: #fff;
  border-radius: var(--raio);
  box-shadow: var(--sombra-alta);
  width: 260px;
  max-width: calc(100% - 8px);
  overflow: hidden;
}

.destinos-painel-topo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  border-bottom: 1px solid var(--borda);
  font-size: 13px;
  color: var(--navy);
}

.destinos-painel-alternar {
  border: none;
  background: none;
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
  padding: 0 4px;
  color: var(--texto-secundario);
}
.destinos-painel-alternar:hover { color: var(--laranja); }

.destinos-painel-corpo { padding: 10px 12px 12px; display: flex; flex-direction: column; gap: 10px; }
.destinos-painel-corpo[hidden] { display: none; }

.destinos-busca {
  display: flex;
  align-items: center;
  gap: 7px;
  border: 1px solid var(--borda);
  border-radius: 8px;
  padding: 6px 9px;
}
.destinos-busca .ico { color: var(--texto-secundario); flex-shrink: 0; }
.destinos-busca input { border: none; outline: none; width: 100%; font-family: inherit; font-size: 13px; background: none; }

.destinos-acoes { display: flex; gap: 6px; }
.destinos-acoes button {
  flex: 1;
  border: 1px solid var(--borda);
  background: none;
  border-radius: 8px;
  padding: 5px 0;
  font-family: inherit;
  font-size: 12px;
  color: var(--texto-secundario);
  cursor: pointer;
}
.destinos-acoes button:hover { border-color: var(--laranja); color: var(--laranja); }

/* Lista de categorias com rolagem própria: uma conta com muitas categorias
   não pode empurrar o painel até tampar o mapa inteiro. */
.destinos-chips { display: flex; flex-direction: column; gap: 4px; max-height: 22vh; overflow-y: auto; }

/* Chip = filtro E legenda. Desligado fica esmaecido (não some), pra
   continuar servindo de legenda mesmo quando aquela categoria não está no
   mapa naquele momento. */
.destinos-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--borda);
  background: none;
  border-radius: 8px;
  padding: 6px 9px;
  font-family: inherit;
  font-size: 13px;
  color: var(--texto);
  cursor: pointer;
  text-align: left;
  opacity: 0.45;
}
.destinos-chip.ativo { opacity: 1; border-color: var(--navy); background: var(--fundo-app); }
.destinos-chip:hover { opacity: 1; }
.destinos-chip i { width: 11px; height: 11px; border-radius: 50%; flex-shrink: 0; }
.destinos-chip span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.destinos-chip b { font-size: 11.5px; color: var(--texto-secundario); font-weight: 700; }

.destinos-vazio { margin: 0; font-size: 13px; color: var(--texto-secundario); text-align: center; padding: 8px 0; }

/* Ponto de partida da simulação — navy, quadrado-arredondado e maior que os
   marcadores numerados, pra não ser confundido com uma parada. É `L.marker`
   (não circleMarker) de propósito: ver desenharSimulacao em main.js. */
.mapa-marcador-origem span {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 9px;
  background: var(--navy);
  border: 3px solid #fff;
  box-shadow: 0 3px 9px rgba(0, 0, 0, 0.45);
}

/* Lista tickável dos destinos filtrados — o caminho rápido pra montar rota
   com vários pontos (clicar marcador a marcador no mapa não escala). */
.destinos-lista-bloco {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 10px;
  border-top: 1px dashed var(--borda);
}
.destinos-lista-titulo { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 13px; color: var(--navy); }

.destinos-lista { display: flex; flex-direction: column; gap: 2px; max-height: 26vh; overflow-y: auto; }

.destinos-lista-item {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 7px;
  border-radius: 7px;
  cursor: pointer;
  font-size: 12.5px;
  line-height: 1.25;
}
.destinos-lista-item:hover { background: var(--fundo-painel); }
/* Marcado fica com fundo laranja claro — mesma pista do ponto destacado no
   mapa, pra lista e mapa contarem a mesma história. */
.destinos-lista-item.marcado { background: var(--laranja-fundo); }
.destinos-lista-item input { flex-shrink: 0; margin: 0; cursor: pointer; }
.destinos-lista-item i {
  width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0;
}
.destinos-lista-item .destinos-lista-texto { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.destinos-lista-item strong { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.destinos-lista-item small { color: var(--texto-secundario); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.destinos-lista-nota { margin: 0; font-size: 11.5px; color: var(--texto-secundario); text-align: center; padding: 6px 0; }

/* Locais avulsos — marcadores temporários (não persistem), separados do
   cadastro de destinos. Borda pontilhada em cima separa visualmente do
   filtro de categorias, mesmo painel. */
.destinos-avulsos {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding-top: 10px;
  border-top: 1px dashed var(--borda);
}
.destinos-avulsos-titulo { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 13px; color: var(--navy); }
.destinos-avulsos input {
  width: 100%;
  padding: 6px 9px;
  border: 1px solid var(--borda);
  border-radius: 8px;
  font-family: inherit;
  font-size: 12.5px;
}
.destinos-avulsos-linha { display: flex; gap: 6px; }
.destinos-avulsos-linha input { flex: 1; min-width: 0; }
.destinos-avulsos-linha button {
  flex-shrink: 0;
  border: none;
  background: var(--laranja);
  color: #fff;
  border-radius: 8px;
  padding: 0 12px;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}
.destinos-avulsos-linha button:hover { background: var(--laranja-hover); }
.destinos-avulsos-linha button:disabled { background: #f3c3ac; cursor: not-allowed; }

.destinos-avulsos-clicar {
  border: 1px dashed var(--borda);
  background: none;
  border-radius: 8px;
  padding: 6px 0;
  font-family: inherit;
  font-size: 12px;
  color: var(--texto-secundario);
  cursor: pointer;
}
.destinos-avulsos-clicar:hover { border-color: var(--laranja); color: var(--laranja); }
/* Modo "clicando" ativo: mesma cor de ação do resto do app, sem inventar
   token novo — o próprio laranja já significa "ação em andamento" aqui. */
.destinos-avulsos-clicar.ativo { border-style: solid; border-color: var(--laranja); color: var(--laranja); background: var(--laranja-fundo); }

.destinos-avulsos-lista { display: flex; flex-direction: column; gap: 4px; max-height: 20vh; overflow-y: auto; }
.destinos-avulsos-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 8px;
  border-radius: 8px;
  background: var(--fundo-painel);
  font-size: 12.5px;
}
.destinos-avulsos-item span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.destinos-avulsos-item button {
  flex-shrink: 0;
  border: none;
  background: none;
  color: var(--texto-secundario);
  cursor: pointer;
  font-size: 15px;
  line-height: 1;
  padding: 0 2px;
}
.destinos-avulsos-item button:hover { color: var(--vermelho); }

/* Cursor de "marcando local" no mapa inteiro enquanto o modo está ativo. */
.mapa.aguardando-clique { cursor: crosshair; }

/* Pino do local avulso — teardrop, deliberadamente diferente do ponto
   redondo de categoria (cor fixa, não entra na paleta de categorias) e do
   círculo numerado da simulação (não é parada de rota). */
.marcador-avulso { filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.35)); }
.marcador-avulso-remover {
  display: block;
  margin-top: 6px;
  border: none;
  background: none;
  padding: 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--vermelho);
  cursor: pointer;
}

/* Simulador de rota — canto SUPERIOR DIREITO do mapa de destinos, oposto ao
   painel de categorias (esquerda) pra os dois não brigarem. Só aparece com
   algum destino marcado: sem seleção ele não teria o que dizer. */
.destinos-simulador {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 2000; /* TASK-120 (DSG-034) — mesma razão do .mapa-topo (vista Rotas) */
  width: 240px;
  max-width: calc(100% - 24px);
  background: #fff;
  border-radius: var(--raio);
  box-shadow: var(--sombra-alta);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-size: 13px;
}
.destinos-simulador[hidden] { display: none; }

.destinos-simulador-topo {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  color: var(--navy);
}

.destinos-simulador-ver-todos {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--texto-secundario);
  cursor: pointer;
}
.destinos-simulador-ver-todos input { margin: 0; cursor: pointer; }

.destinos-simulador-campo { display: flex; flex-direction: column; gap: 4px; }
.destinos-simulador-campo > span { font-size: 11.5px; color: var(--texto-secundario); }
.destinos-simulador-campo select {
  width: 100%;
  padding: 7px 8px;
  border: 1px solid var(--borda);
  border-radius: 8px;
  font-family: inherit;
  font-size: 12.5px;
}

.destinos-simulador-resultado {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 9px 10px;
  border-radius: 8px;
  background: var(--fundo-app);
  font-size: 12.5px;
}
.destinos-simulador-resultado[hidden] { display: none; }
.destinos-simulador-resultado span { color: var(--texto-secundario); }
.destinos-simulador-resultado .sim-erro { color: var(--vermelho); }
.destinos-simulador-resultado .sim-aviso { color: var(--laranja); font-size: 11.5px; }
/* Economia da roteirizacao — verde (ganho), nao laranja (atencao): e a
   unica linha do resumo que diz que a sugestao VALEU a pena. */
.destinos-simulador-resultado .sim-economia {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 2px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--verde-editorial);
}
.destinos-simulador-resultado .sim-economia .ico { width: 13px; height: 13px; flex-shrink: 0; }

/* Sequência da simulação em texto — o número aqui é o MESMO do pino no mapa
   (a origem entra como "S", que não é parada e por isso não recebe número). */
.sim-sequencia {
  list-style: none;
  margin: 6px 0 0;
  padding: 6px 0 0;
  border-top: 1px solid var(--borda);
  display: flex;
  flex-direction: column;
  gap: 3px;
  max-height: 24vh;
  overflow-y: auto;
}
.sim-sequencia li {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--texto);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sim-sequencia b {
  flex-shrink: 0;
  width: 17px; height: 17px;
  border-radius: 50%;
  background: var(--laranja);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}
.sim-sequencia-origem b { background: var(--navy); }

.destinos-simulador-acoes { display: flex; flex-direction: column; gap: 6px; }
.destinos-simulador-acoes button { width: 100%; justify-content: center; }

/* Caixinha "Incluir na rota" dentro do popup do Leaflet. Borda em cima
   separa do endereço — sem ela a caixinha lê como parte do texto. */
.popup-selecionar {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--borda);
  cursor: pointer;
  font-weight: 600;
  color: var(--navy);
}

/* Lista de revisão do modal "Criar rota simulada" */
.mcr-lista { display: flex; flex-direction: column; gap: 8px; max-height: 46vh; overflow-y: auto; }

.mcr-item {
  display: flex;
  gap: 10px;
  padding: 10px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--fundo-painel);
}

.mcr-ordem {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--laranja);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

.mcr-item-corpo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.mcr-item-corpo > span { font-size: 12px; color: var(--texto-secundario); }
.mcr-item-campos { display: flex; gap: 8px; margin-top: 5px; flex-wrap: wrap; }
.mcr-item-campos select { flex: 0 0 150px; }
.mcr-item-campos input { flex: 1; min-width: 140px; }
.mcr-item-campos select, .mcr-item-campos input {
  padding: 7px 9px;
  border: 1px solid var(--borda);
  border-radius: 8px;
  font-family: inherit;
  font-size: 12.5px;
}

/* O rodapé com a contagem (`#destinos-info`, reaproveita `.mapa-info`) fica
   no canto inferior esquerdo — no celular o painel já ocupa boa parte da
   tela, então ele encolhe pra não brigar com o mapa. */
@media (max-width: 640px) {
  .destinos-painel { width: 210px; }
  .destinos-chips { max-height: 18vh; }
  .destinos-lista { max-height: 22vh; }
}

.combo { position: relative; }

.combo-lista {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 220px;
  overflow-y: auto;
  background: #fff;
  border: 1px solid var(--borda);
  border-radius: 8px;
  box-shadow: var(--sombra-alta);
  z-index: 650;
}

.combo-item {
  padding: 8px 10px;
  font-size: 13px;
  cursor: pointer;
}

.combo-item:hover { background: var(--laranja-fundo); }

.combo-vazio {
  padding: 8px 10px;
  font-size: 12px;
  color: var(--texto-secundario);
}

/* SIM-006 (docs/REAL-WORLD-SIMULATION.md): opção "+ Cadastrar novo
   destino" ao final da lista do combobox — cor de ação (laranja) pra se
   diferenciar visualmente dos resultados de busca normais. */
.combo-item-criar {
  color: var(--laranja);
  font-weight: 600;
  border-top: 1px solid var(--borda);
}
.combo-item-criar:hover { background: var(--laranja-fundo); }

/* Seletor de tags (categoria de carga/marca — sessão 83, `SeletorTags` em
   util.js): chips do que já foi escolhido em cima, campo de digitar +
   sugestão embaixo. `.seletor-tags-campo` é o `.combo` deste widget (mesma
   régua de `position: relative` pra ancorar a lista de sugestões). */
.seletor-tags-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 6px;
}
.seletor-tags-chips:empty { display: none; }

.seletor-tags-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 6px 4px 10px;
  border-radius: 999px;
  background: var(--laranja-fundo);
  color: var(--laranja);
  font-size: 12.5px;
  font-weight: 600;
}

.seletor-tags-chip button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border: none;
  border-radius: 50%;
  background: none;
  color: inherit;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
}
.seletor-tags-chip button:hover { background: rgba(242, 107, 58, 0.18); }

.seletor-tags-campo { position: relative; }

.viagem-paradas { display: flex; flex-direction: column; gap: 6px; }

.viagem-parada-linha { display: flex; align-items: center; gap: 6px; }
.viagem-parada-linha .combo { flex: 1; min-width: 0; }

.viagem-parada-remover {
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--texto-secundario);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 6px;
}

.viagem-parada-remover:hover { color: var(--vermelho); }

.viagem-add-parada {
  align-self: flex-start;
  background: none;
  border: none;
  color: var(--azul-primario);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  padding: 2px 0;
  font-family: inherit;
}

.viagem-add-parada:hover { text-decoration: underline; }

/* ---------- Barra do quadro (data + alerta de rodízio) ---------- */

#vista-kanban-wrap { display: flex; flex-direction: column; }
#vista-kanban-wrap[hidden] { display: none; }

.quadro-topo {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--linha-editorial);
  background: #fff;
  box-shadow: 0 2px 8px rgba(17, 45, 74, 0.04);
  position: relative;
  z-index: 1;
  flex-shrink: 0;
}

.quadro-data {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 14px;
  border: 1px solid var(--linha-editorial);
  border-radius: 999px;
  font-weight: 600;
  font-size: 14px;
  background: var(--marfim);
  transition: border-color 0.15s ease, background 0.15s ease;
}

.quadro-data:focus-within { border-color: var(--laranja); background: #fff; }
.quadro-data .ico { width: 18px; height: 18px; color: var(--laranja); }
.quadro-data input { border: none; background: none; font-family: inherit; font-size: 14px; font-weight: 600; color: var(--navy); }
.quadro-data input:focus { outline: none; }

/* ALTO-003 (docs/ROUTE-SYSTEM-AUDIT.md): filtro client-side por placa,
   motorista ou status — mesmo formato de pílula de .quadro-data, pra não
   introduzir um terceiro estilo de campo no mesmo cabeçalho. */
.quadro-filtro {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 14px;
  border: 1px solid var(--linha-editorial);
  border-radius: 999px;
  background: var(--marfim);
  transition: border-color 0.15s ease, background 0.15s ease;
  min-width: 0;
  flex: 1;
  max-width: 320px;
}
.quadro-filtro:focus-within { border-color: var(--laranja); background: #fff; }
.quadro-filtro .ico { width: 16px; height: 16px; color: var(--texto-secundario); flex-shrink: 0; }
.quadro-filtro input { border: none; background: none; font-family: inherit; font-size: 13.5px; color: var(--navy); width: 100%; min-width: 0; }
.quadro-filtro input:focus { outline: none; }

.quadro-rodizio { font-size: 13px; flex: 1; min-width: 0; }

/* TASK-124 (UX-070): em telas estreitas, `.quadro-data` + `.quadro-filtro` +
   `.quadro-rodizio` + "Viagem rápida" + "Tabela" empilhados (a correção
   original abaixo, que continua valendo — QUANDO o bloco está aberto, ver
   nota) ocupavam ~216px fixos ANTES do quadro nem começar, deixando só 90px
   (14%) de tela pra `.kanban-cards` num card de 250px. `.quadro-data` fica
   sempre visível (é o controle mais usado — trocar de dia); o resto
   (`#quadro-topo-extra`) recolhe atrás do botão "Filtros"
   (`#quadro-filtros-toggle`), que ganha uma bolinha âmbar quando há rodízio
   restrito hoje (`.quadro-topo.rodizio-restrito`, ligada em
   `main.js::carregarRodizio`) — o aviso continua "sempre visível" (guardrail
   do achado original), só que como indicador compacto, não o texto inteiro.
   `display:contents` no wrapper faz ele "desaparecer" da caixa em >600px: os
   filhos continuam participando do flex de `.quadro-topo` exatamente como
   antes de existir o wrapper — só o `@media` abaixo dá comportamento próprio
   a ele. Recolher ≠ desempilhar: quando `#quadro-topo-extra.aberto`, o
   miolo empilhado original (`flex-basis:100%` pra cada pílula, pelo mesmo
   motivo de sempre — `flex:1` sozinho não "pede" quebra de linha) continua
   de pé, só que dentro do bloco expansível. */
.quadro-topo-extra { display: contents; }

.quadro-filtros-toggle { display: none; }

@media (max-width: 600px) {
  /* `flex-wrap: wrap` (não `nowrap`) é o que deixa `#quadro-topo-extra.aberto`
     (flex-basis:100%, ver abaixo) cair pra uma "segunda linha" quando o
     "Filtros" abre — com `nowrap` o painel expandido tentava caber na MESMA
     linha da data e ficava com layout quebrado (achado ao vivo, confirmado
     antes de commitar). Data+toggle continuam numa linha só quando fechado
     porque cabem sozinhos (336px de sobra pra ~200px de conteúdo) — `wrap`
     só quebra quando não cabe. */
  .quadro-topo { flex-wrap: wrap; align-items: center; padding: 8px 14px; }
  .quadro-data { flex: 1; min-width: 0; }
  .quadro-filtros-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    padding: 8px 14px;
    min-height: var(--alvo-toque);
    border: 1px solid var(--linha-editorial);
    border-radius: 999px;
    background: var(--marfim);
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    color: var(--navy);
    cursor: pointer;
    position: relative;
  }
  .quadro-filtros-toggle .ico { width: 16px; height: 16px; }
  .quadro-topo.rodizio-restrito .quadro-filtros-toggle::after {
    content: "";
    position: absolute;
    top: 6px;
    right: 8px;
    width: 8px;
    height: 8px;
    border-radius: 999px;
    background: var(--amarelo);
    border: 1.5px solid #fff;
  }
  .quadro-topo-extra {
    display: none;
    flex-basis: 100%;
    flex-direction: column;
    gap: 8px;
    margin-top: 10px;
  }
  .quadro-topo-extra.aberto { display: flex; }
  .quadro-filtro, .quadro-rodizio { flex: 1 1 100%; max-width: none; }
  .quadro-data, .quadro-filtro { min-height: var(--alvo-toque); }
  .quadro-topo-extra .quadro-alternar-tabela { justify-content: center; min-height: var(--alvo-toque); }
}

/* TASK-130 (VIS-025), direção (b): o scroll-snap acima resolve o gesto
   (uma coluna = uma "página"), mas sozinho não diz QUANTAS colunas
   existem — o gestor teria que decorar a carga de um veículo antes de
   deslizar pro próximo. `Kanban._atualizarPosicaoQuadro()` calcula o texto
   a partir de `.kanban-coluna.offsetLeft`/`scrollLeft`, sem estado próprio
   pra não dessincronizar do DOM real. Só existe no mobile — acima de
   600px várias colunas já ficam visíveis ao mesmo tempo, "3 de 8" não
   informaria nada que a própria tela não mostrasse. */
.quadro-posicao { display: none; }
@media (max-width: 600px) {
  /* Virou <select> na sessão 128 (pedido do usuário) — mesma pílula visual
     de .kanban-select (borda + fundo branco) pra sinalizar que dá pra tocar
     e pular direto pra coluna, não só ler a posição. min-height segue
     --alvo-toque, igual aos outros controles do quadro no mobile (A11Y-002). */
  .quadro-posicao {
    display: block;
    width: calc(100% - 24px);
    margin: 6px 12px 0;
    padding: 0 12px;
    min-height: var(--alvo-toque);
    font-size: 12.5px;
    font-weight: 600;
    font-family: inherit;
    color: var(--texto-secundario);
    text-align: center;
    text-align-last: center;
    border: 1px solid var(--linha-editorial);
    border-radius: 7px;
    background: #fff;
  }
  .quadro-posicao:focus { outline: 2px solid var(--laranja); outline-offset: -1px; border-color: transparent; }
}

/* Alterna entre o quadro (kanban) e a mesma informação em tabela — pedido
   do usuário (25/08/2026) pra facilitar mandar um print resumo de onde os
   carros estão, sem precisar rolar várias colunas. */
.quadro-alternar-tabela {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 8px 14px;
  border: 1px solid var(--linha-editorial);
  border-radius: 999px;
  background: var(--marfim);
  color: var(--navy);
  font-family: inherit;
  font-weight: 600;
  font-size: 13.5px;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
  flex-shrink: 0;
}
.quadro-alternar-tabela .ico { width: 16px; height: 16px; }
.quadro-alternar-tabela:hover { border-color: var(--laranja); }
.quadro-alternar-tabela.ativo { background: var(--laranja); border-color: var(--laranja); color: #fff; }

.quadro-tabela-wrap { flex: 1; overflow: auto; padding: 20px; background: var(--fundo-painel); }

.quadro-tabela {
  width: 100%;
  border-collapse: collapse;
  background: #fff;
  border-radius: var(--raio);
  overflow: hidden;
  box-shadow: var(--sombra);
  font-size: 13.5px;
}
.quadro-tabela th {
  text-align: left;
  padding: 10px 14px;
  background: var(--navy);
  color: #fff;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.quadro-tabela td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--borda);
  vertical-align: top;
}
.quadro-tabela tbody tr:last-child td { border-bottom: none; }
.quadro-tabela tbody tr:nth-child(even) { background: var(--marfim); }
.quadro-tabela strong { display: block; color: var(--texto); }
.quadro-tabela-sub { display: block; font-size: 12px; color: var(--texto-secundario); margin-top: 2px; }

.quadro-tabela-paradas { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.quadro-tabela-paradas li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; }
.quadro-tabela-paradas li strong { display: inline; color: var(--texto); }
.quadro-tabela-paradas li span { color: var(--texto-secundario); font-size: 12.5px; }
.quadro-tabela-paradas li.ok strong { color: var(--verde-editorial); text-decoration: line-through; }
.quadro-tabela-paradas li.atrasada strong { color: var(--vermelho-editorial); }
.quadro-tabela-hora { font-variant-numeric: tabular-nums; }
.quadro-tabela-vazio { color: var(--texto-secundario); font-size: 12.5px; }
.quadro-tabela-alerta { color: var(--vermelho-editorial); }

/* Telefone clicável na visão em tabela do Cadastro (sessão 70) — mesma ação
   do botão "Abrir no WhatsApp" do modal, só que direto na linha da planilha. */
.tabela-link-whatsapp { color: var(--azul-primario); text-decoration: none; }
.tabela-link-whatsapp:hover { text-decoration: underline; }

@media print {
  .quadro-topo, .rail, .app > header { display: none !important; }
  .quadro-tabela-wrap { padding: 0; }
  .quadro-tabela { box-shadow: none; }
}

.rodizio-alerta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  border-radius: 999px;
  background: var(--amarelo-fundo);
  color: var(--amarelo-texto);
  border: 1px solid var(--amarelo-borda);
}
.rodizio-alerta .ico { flex-shrink: 0; }

.rodizio-ok {
  display: inline-block;
  padding: 7px 12px;
  border-radius: 999px;
  background: #f0fdf4;
  color: #166534;
  border: 1px solid #bbf7d0;
}

.rodizio-neutro { color: var(--texto-secundario); }

/* Faixa de erro quando uma (ou mais) das chamadas de carga do painel falha
   (TASK-029) — nunca deixar a tela em branco e muda sem explicação.
   `#vista-mapa`/`#vista-kanban-wrap` são `position:absolute; inset:0`
   (cobrem `.area-principal` inteiro), então isto também precisa ser
   absoluto — senão fica escondido atrás do mapa. z-index acima do
   Leaflet (~1000) e do `.mapa-topo`, mesma régua documentada em
   rules/design-system.md §7 — **100 acima** de `.mapa-topo`/`.mapa-info`/
   `.destinos-*`/`.notificacoes-painel` (TASK-120 subiu os 4 pra 2000; sem
   essa folga, o erro de carga empataria com eles e a ordem de exibição
   dependeria de posição no DOM, não de prioridade visual — erro de carga
   tem que aparecer por cima de tudo do mapa, sempre). */
.faixa-erro-carga {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 2100;
  margin: 0;
  padding: 10px 16px;
  background: #fef2f2;
  color: #991b1b;
  border-bottom: 1px solid #fecaca;
  font-size: 13px;
  font-weight: 600;
}

.kanban-controles {
  display: flex;
  gap: 6px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--linha-editorial);
  background: var(--marfim);
}

.kanban-select {
  flex: 1;
  min-width: 0;
  font-size: 11.5px;
  font-weight: 600;
  font-family: inherit;
  padding: 6px 7px;
  border: 1px solid var(--linha-editorial);
  border-radius: 7px;
  background: #fff;
  color: var(--texto);
  transition: border-color 0.15s ease;
}
.kanban-select:hover { border-color: #d7cabf; }
.kanban-select:focus { outline: 2px solid var(--laranja); outline-offset: -1px; border-color: transparent; }

.aviso-rodizio {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 8px 14px;
  background: var(--amarelo-fundo);
  color: var(--amarelo-texto);
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.45;
  border-bottom: 1px solid var(--amarelo-borda);
}
.aviso-rodizio .ico { flex-shrink: 0; }

/* Rota que não fechou no dia em que nasceu (motorista não finalizou) e
   reaparece carregada pro quadro de hoje — ver kanban.py::obter_kanban.
   Mesma semântica de "atenção" do rodízio restrito, design-system.md §4. */
.kanban-coluna-atrasada {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 6px 14px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--amarelo-texto);
  background: var(--amarelo-fundo);
  border-bottom: 1px solid var(--amarelo-borda);
}
.kanban-coluna-atrasada .ico { flex-shrink: 0; }

.aviso-previa {
  margin: 4px 0 0;
  font-size: 12.5px;
  color: var(--azul-primario);
  line-height: 1.5;
  min-height: 18px;
}

/* ---------- Blocos de configuração ---------- */

.bloco-config {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 16px 0;
  border-bottom: 1px solid var(--borda);
}

.bloco-config:last-child { border-bottom: none; }
.bloco-config select {
  padding: 11px 13px;
  border: 1px solid var(--borda);
  border-radius: 9px;
  font-size: 14.5px;
  font-family: inherit;
  background: #fff;
  color: var(--texto);
  min-width: 220px;
}
.bloco-config-texto { flex: 1; }

/* Tamanho igualado ao de .config-focada (DSG-017) — Cadastro e
   Configurações usam as mesmas classes base, só Configurações tinha
   recebido "campos maiores" na v1.37.1. Trazer Cadastro pro mesmo número
   evita duas telas do mesmo rail parecerem produtos diferentes. */
.bloco-config h4 {
  margin: 0 0 6px;
  font-size: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.bloco-config h4 .ico { width: 18px; height: 18px; color: var(--laranja); }
.bloco-config p { margin: 0; font-size: 12.5px; color: var(--texto-secundario); line-height: 1.6; }

.bloco-config-coluna { flex-direction: column; align-items: stretch; gap: 12px; }
/* Lista/busca continuam esticando (bom, usam a largura toda) — mas um botão
   solto direto no card (ex.: "Novo motorista"/"Novo veículo" em Cadastro,
   sem campo de busca ao lado) não devia virar uma barra do tamanho do card
   inteiro. `.cadastro-toolbar` já resolve isso pra Destinos (busca+botão
   lado a lado); esta regra cobre os botões soltos das outras abas. */
.bloco-config-coluna > .btn-primario.btn-auto,
.bloco-config-coluna > .btn-secundario.btn-auto { align-self: flex-start; }
.bloco-config-coluna h4 { margin: 0; }
.bloco-config-nota { margin: 0; font-size: 13.5px; color: var(--texto-secundario); line-height: 1.6; }
/* Aviso de configuração que reescreve dado JÁ APRESENTADO (`CONT-018`) — o
   caso do turno da operação, que recalcula ociosidade/hora extra de dias
   passados. Fundo âmbar porque é consequência, não erro. */
.bloco-config-aviso {
  margin-top: 8px;
  padding: 8px 10px;
  border-left: 3px solid var(--amarelo, #d97706);
  background: #fffbeb;
  border-radius: 6px;
}

/* Campo raramente usado (ex.: sessão do WhatsApp por conta) — fica fechado
   por padrão pra não competir com grupo/número, que é o que toda conta usa. */
.bloco-config-avancado { display: flex; flex-direction: column; gap: 10px; }
.bloco-config-avancado summary {
  cursor: pointer;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--texto-secundario);
}
.bloco-config-avancado summary:hover { color: var(--texto); }
.bloco-config-avancado[open] summary { margin-bottom: 2px; }

/* Ação destrutiva (limpar o quadro) — o vermelho aqui é a única pista visual
   antes do clique de que este bloco não é como os outros da tela. */
.bloco-config-perigo h4 .ico { color: var(--vermelho); }
.bloco-config-perigo {
  background: #fef4f4;
  border: 1px solid #f3d0d0;
  border-radius: var(--raio);
  padding: 16px;
}

.lista-limpeza {
  margin: 8px 0 18px;
  padding-left: 20px;
  font-size: 12.5px;
  color: var(--texto-secundario);
  line-height: 1.7;
}

/* Versão em Configurações — parece nota de texto, mas é botão (abre o
   changelog em #modal-changelog). Sublinhado tracejado sinaliza "clicável"
   sem parecer link azul de página, que destoaria do resto da tela. */
.link-versao {
  margin: 0;
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  font-size: 12.5px;
  color: var(--texto-secundario);
  cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}
.link-versao:hover { color: var(--laranja); }

.changelog-versao {
  padding: 14px 0;
  border-bottom: 1px solid var(--borda);
}
.changelog-versao:first-child { padding-top: 0; }
.changelog-versao:last-child { border-bottom: none; }
.changelog-versao h4 { margin: 0 0 8px; font-size: 14px; display: flex; align-items: baseline; gap: 8px; }
.changelog-versao .changelog-data { font-size: 12px; font-weight: 400; color: var(--texto-secundario); }
.changelog-versao ul { margin: 0; padding-left: 18px; font-size: 13px; color: var(--texto); line-height: 1.6; }
.changelog-versao li { margin-bottom: 4px; }

.lista-empresas, .lista-cadastro { display: flex; flex-direction: column; border: 1px solid var(--linha-editorial); border-radius: 9px; overflow: hidden; }
.lista-empresas .card-item:last-child, .lista-cadastro .card-item:last-child { border-bottom: none; }
.lista-empresas .card-item, .lista-cadastro .card-item { background: #fff; }

/* Toolbar (busca + "Novo …") lado a lado em vez de empilhado — só a tela de
   Cadastro tem busca; Motoristas/Veículos só têm o botão. */
.cadastro-toolbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.cadastro-toolbar .campo-busca-lista { flex: 1; margin-bottom: 0; }
.cadastro-toolbar .btn-primario, .cadastro-toolbar .btn-secundario { flex-shrink: 0; }

/* ---------- Seleção em massa de destinos (sessão 60) ----------
   Barra só visível no modo Selecionar. Fundo âmbar, não vermelho: o modo em
   si não é destrutivo (marcar não apaga nada) — o vermelho fica reservado
   pro botão que de fato exclui, senão a tela inteira grita antes da hora. */
.selecao-barra {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 10px 14px;
  border: 1px solid #f5d9a8;
  background: #fffaf0;
  border-radius: 9px;
}
.selecao-barra .selecao-todos { margin: 0; font-weight: 600; color: var(--navy); }
.selecao-barra .btn-perigo { margin-left: auto; flex-shrink: 0; }

.card-selecionavel { cursor: pointer; }
.card-selecionavel:hover { background: #fff; }

.card-item-selecao {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  accent-color: var(--laranja);
  cursor: pointer;
}

/* Categoria do destino (texto livre) — a cor vem de CategoriasDestino.cores()
   (util.js) e é a MESMA do ponto daquela categoria no Mapa de destinos: o
   chip aqui e o ponto lá precisam bater, é o que liga as duas telas sem
   repetir legenda. */
/* Seletor com `.card-item` na frente por necessidade, não por estilo: o chip
   é um <span> dentro do card, e `.card-item span` (logo acima) é mais
   específico que uma classe sozinha — sem isso o chip herda dali o cinza
   secundário sobre o fundo colorido (texto ilegível) e o `display: block`,
   que o esticava por toda a linha. */
.card-item .chip-categoria {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #fff;
  white-space: nowrap;
}

/* Lista de Cadastro (Destinos/Motoristas/Veículos) vira uma grade de cards
   em telas largas — a página ganhou o dobro da largura nesta sessão (ver
   .pagina-config-corpo) e uma coluna única de itens ficava com muito espaço
   vazio nas laterais (pedido do usuário). Empresas/Usuários operadores (em
   Configurações) continuam lista simples de propósito — moram dentro de um
   card de meia-largura (.config-grade-2col), não têm espaço de sobra. */
@media (min-width: 640px) {
  .lista-cadastro {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 10px;
    border: none;
    border-radius: 0;
  }
  .lista-cadastro .card-item {
    border: 1px solid var(--linha-editorial);
    border-bottom: 1px solid var(--linha-editorial);
    border-radius: 9px;
    background: var(--fundo-app);
  }
  .lista-cadastro .card-item:last-child { border-bottom: 1px solid var(--linha-editorial); }
}

.form-empresa {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.form-empresa input {
  flex: 1;
  min-width: 110px;
  padding: 8px 10px;
  border: 1px solid var(--borda);
  border-radius: 8px;
  font-size: 13px;
  font-family: inherit;
}

.whatsapp-template { display: flex; flex-direction: column; gap: 6px; }
.whatsapp-template label { font-size: 12.5px; font-weight: 600; color: var(--texto); }
.whatsapp-template textarea {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--borda);
  border-radius: 8px;
  font-size: 13px;
  font-family: inherit;
  resize: vertical;
}
.whatsapp-template-acoes { display: flex; gap: 8px; }

/* ---------- Mensagens rápidas de WhatsApp (disparo manual) ---------- */

.lista-mensagens-rapidas { display: flex; flex-direction: column; gap: 8px; }
.mensagem-rapida-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--linha-editorial);
  border-radius: 8px;
  background: var(--marfim);
}
.mensagem-rapida-item.em-edicao { border-color: var(--laranja); background: var(--laranja-fundo); }
.mensagem-rapida-texto { min-width: 0; flex: 1; cursor: pointer; }
.mensagem-rapida-texto strong { display: block; font-size: 13px; }
.mensagem-rapida-texto span {
  display: block;
  font-size: 12px;
  color: var(--texto-secundario);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 2px;
}
.mensagem-rapida-acoes { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.mensagem-rapida-vazia { padding: 14px; text-align: center; color: var(--texto-secundario); font-size: 12.5px; }

/* ---------- Página de configurações (standalone, não é mais modal) ----------
   Restilizada nesta sessão pra entrar na mesma identidade navy+laranja da
   Visão geral (fundo marfim, cartão com sombra suave, título em Space
   Grotesk) — ver design-system.md. */

.pagina-config { min-height: 100vh; background: var(--marfim); }
/* Dentro do rail compartilhado (Cadastro/Configurações/Relatórios, ver
   js/rail.js) a página vira a 2ª coluna do grid .app — precisa da própria
   rolagem, senão o rail rolaria junto com o conteúdo. */
.app > .pagina-config { height: 100vh; overflow-y: auto; }

.pagina-config-topo {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 24px;
  background: var(--fundo-app);
  border-bottom: 1px solid var(--linha-editorial);
  position: sticky;
  top: 0;
  z-index: 10;
}

.pagina-config-topo h1 {
  margin: 0;
  font-size: 19px;
  font-family: "Space Grotesk", "Inter", system-ui, sans-serif;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--navy);
}

.pagina-config-voltar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: none;
  background: var(--marfim);
  color: var(--texto);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  text-decoration: none;
  flex-shrink: 0;
  transition: background 0.15s ease, color 0.15s ease;
}

.pagina-config-voltar:hover { background: var(--laranja-fundo); color: var(--laranja); }

/* Layout com sidebar de seções (pedido do usuário) — cada item da sidebar
   corresponde a uma das grades de cards; JS (configuracoes.js) mostra só a
   grade com o data-secao-conteudo correspondente. Vira tira de abas
   horizontais em telas estreitas (ver media query mais abaixo). */
.pagina-config-layout { display: flex; align-items: flex-start; }

.config-sidebar {
  flex: 0 0 216px;
  position: sticky;
  top: 69px; /* altura de .pagina-config-topo — fica colada logo abaixo dele */
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 24px 14px;
  border-right: 1px solid var(--linha-editorial);
  height: calc(100vh - 69px);
  overflow-y: auto;
}

.config-sidebar-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  border: none;
  background: transparent;
  color: var(--texto-secundario);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  transition: background 0.15s ease, color 0.15s ease;
}
.config-sidebar-item .ico { flex-shrink: 0; color: inherit; margin-top: 1px; }
.config-sidebar-item:hover { background: var(--laranja-fundo); color: var(--laranja); }
.config-sidebar-item.ativo { background: var(--laranja); color: #fffaf4; }

.pagina-config-corpo {
  flex: 1;
  min-width: 0;
  max-width: 940px;
  margin: 0;
  padding: 28px 24px 40px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

@media (max-width: 860px) {
  .pagina-config-layout { flex-direction: column; }
  .config-sidebar {
    position: static;
    height: auto;
    flex-direction: row;
    flex-wrap: wrap;
    width: 100%;
    border-right: none;
    border-bottom: 1px solid var(--linha-editorial);
    padding: 12px 16px;
  }
  .pagina-config-corpo { max-width: none; }
}

.pagina-config-card {
  background: var(--fundo-app);
  border: 1px solid var(--linha-editorial);
  border-radius: 9px;
  box-shadow: 0 4px 13px rgba(17, 45, 74, 0.025);
  padding: 4px 20px;
}

/* ---------- Layout desktop de Configurações/Cadastro ----------
   Antes tudo era uma coluna única de 760px centralizada — parecia "feito só
   pro celular" numa tela grande, muito espaço vazio nas laterais (pedido do
   usuário). Cards relacionados agora sentam lado a lado (2 colunas) e a
   fileira de ajustes pequenos (Importar/Geocodificação/Relatórios/Exportar/
   toggles/Rodízio) virou uma grade de cards compactos — mesma linguagem de
   "grade de cards" do dashboard de referência (neo2), sem inventar um
   componente novo. Empilha em 1 coluna abaixo de 860px (tablet/celular). */
.config-grade-2col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}

.config-grade-utilitarios {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
  gap: 14px;
}

.pagina-config-card-compacta { padding: 18px; }
.pagina-config-card-compacta .bloco-config {
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  padding: 0;
  border-bottom: none;
  height: 100%;
}
.pagina-config-card-compacta .bloco-config-texto { width: 100%; }
.pagina-config-card-compacta h4 { font-size: 13.5px; }
.pagina-config-card-compacta .btn-primario,
.pagina-config-card-compacta .btn-secundario,
.pagina-config-card-compacta select,
.pagina-config-card-compacta .opcoes-nav-mobile,
.pagina-config-card-compacta .campo-checkbox { width: 100%; }
.pagina-config-card-compacta .opcoes-nav-mobile { flex-direction: column; gap: 8px; }

@media (max-width: 860px) {
  .config-grade-2col,
  .config-grade-utilitarios { grid-template-columns: 1fr; }
}

.btn-perigo {
  padding: 11px 18px;
  background: var(--vermelho);
  color: #fff;
  border: none;
  border-radius: 8px;
  font-weight: 700;
  font-size: 13px;
  cursor: pointer;
  font-family: inherit;
  width: auto;
}

.btn-perigo:hover { background: #b91c1c; }
.btn-perigo:disabled { background: #eba3a3; cursor: not-allowed; }

/* ---------- Página de relatórios/histórico de viagens ---------- */
/* Mesmo cartão (borda/raio/sombra) e micro-rótulo uppercase da Visão geral —
   restilizada nesta sessão junto com Configurações/Cadastro. */

.pagina-relatorio-corpo {
  max-width: 1180px;
  margin: 0 auto;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.relatorio-filtros {
  background: var(--fundo-app);
  border: 1px solid var(--linha-editorial);
  border-radius: 9px;
  box-shadow: 0 4px 13px rgba(17, 45, 74, 0.025);
  padding: 14px 18px;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px;
}

.relatorio-filtros .campo { margin-bottom: 0; flex: 0 0 auto; }
.relatorio-filtros .campo label { font-size: 12px; }

/* Sessão 98: busca de texto livre é o filtro mais usado da tela — largura
   maior que os demais campos (que são select/date, mais curtos por
   natureza) pra caber "nome do motorista, destino, placa" sem cortar. */
.relatorio-filtros .campo-busca { flex: 1 1 220px; min-width: 180px; }
.relatorio-filtros .campo-busca input { width: 100%; }

.relatorio-resumo {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
}

/* Lista de destinos dentro da célula "Destinos": um por linha, com o
   marcador de status na frente. Cada nome é um apelido curto, então a
   coluna não precisa ser larga, mas precisa poder quebrar. */
.ent-destinos {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.ent-destinos li {
  display: flex;
  align-items: baseline;
  gap: 6px;
  white-space: nowrap;
  font-size: 13px;
}

.ent-destinos .ent-destino-marca {
  flex: none;
  width: 1em;
  font-weight: 700;
}

.ent-destinos li.ok { color: var(--verde); }
.ent-destinos li.erro { color: var(--vermelho); }
.ent-destinos li.pendente { color: var(--texto-secundario); }

/* Botão de câmera inline, na mesma linha do destino — versão compacta de
   .kanban-card-pod (que tem o texto "Comprovante" ao lado; aqui só o ícone,
   porque a lista de destinos já é justaposta e apertada). */
.ent-destino-pod {
  flex: none;
  display: inline-flex;
  padding: 0;
  border: none;
  background: none;
  color: var(--azul-primario);
  cursor: pointer;
}

.ent-destino-pod .ico { width: 14px; height: 14px; }
.ent-destino-pod:hover { color: var(--azul-primario-hover); }
.ent-destino-pod:disabled { color: var(--texto-secundario); cursor: wait; }

/* Detalhamento por viagem — sessão 97: virou modal (#modal-detalhe-viagem)
   aberto sob demanda pelo clique numa entrega da lista, ver
   `App.abrirDetalheViagem`. Um card só por vez, nunca uma lista empilhada:
   antes disto (`.ent-viagens-lista`, removida) mostrava TODAS as viagens do
   período sempre visíveis embaixo da tela, redundante com a lista de cima. */
.ent-viagem-card {
  background: var(--fundo-app);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 14px 16px;
}

.ent-viagem-card-topo {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}

.ent-viagem-card-topo strong {
  display: block;
  font-size: 14.5px;
  color: var(--texto);
}

.ent-viagem-card-topo span {
  display: block;
  font-size: 12.5px;
  color: var(--texto-secundario);
  margin-top: 2px;
}

.ent-viagem-card-grade {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 10px 16px;
  margin: 12px 0;
  padding: 12px 0;
  border-top: 1px solid var(--borda);
  border-bottom: 1px solid var(--borda);
}

.ent-viagem-card-grade > div span {
  display: block;
  font-size: 11.5px;
  color: var(--texto-secundario);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.ent-viagem-card-grade > div strong {
  display: block;
  font-size: 13.5px;
  color: var(--texto);
  margin-top: 2px;
}

.ent-viagem-card-destinos > span {
  display: block;
  font-size: 11.5px;
  color: var(--texto-secundario);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin-bottom: 6px;
}

.ent-viagem-card-descricao {
  margin-top: 12px;
}

.ent-viagem-card-descricao > span {
  display: block;
  font-size: 11.5px;
  color: var(--texto-secundario);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  margin-bottom: 4px;
}

.ent-viagem-card-descricao > p {
  margin: 0;
  font-size: 13.5px;
  color: var(--texto);
  white-space: pre-wrap;
}

.relatorio-resumo-card {
  background: var(--fundo-app);
  border: 1px solid var(--linha-editorial);
  border-radius: 9px;
  box-shadow: 0 4px 13px rgba(17, 45, 74, 0.025);
  padding: 14px 16px;
}

.relatorio-resumo-card span {
  display: block;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--texto-secundario);
  margin-bottom: 6px;
}

.relatorio-resumo-card strong {
  font-family: "Space Grotesk", "Inter", system-ui, sans-serif;
  font-size: 23px;
  letter-spacing: -0.03em;
  color: var(--navy);
}

.relatorio-paradas { display: flex; gap: 6px; font-size: 12px; }
.relatorio-paradas .ok { color: var(--verde); }
.relatorio-paradas .erro { color: var(--vermelho); }
.relatorio-paradas .pendente { color: var(--texto-secundario); }

/* ---------- Kanban (Controle de Rotas) ----------
   Restilizado nesta sessão pra entrar na identidade navy+laranja: cabeçalho
   da coluna em navy, acentos (coluna-alvo do drag, card em andamento, botão
   de sugerir ordem) em laranja. Mecânica (drag-and-drop nativo + o seletor
   "atribuir a…" alternativo pra touch) não foi tocada — só marcação visual. */

.kanban {
  display: flex;
  gap: 18px;
  /* Sem padding à DIREITA: `overflow` recorta no padding box, então tudo o
     que é padding vira área por onde a coluna passa rolando e FICA visível.
     Isso nunca incomodou até a aba do carrinho existir — ela é `sticky` e
     não alcança esse trecho, então sobrava um naco de coluna solto na borda,
     separado do resto. O respiro do fim volta como `margin-right` do último
     item (abaixo): margem é conteúdo, rola junto e não deixa faixa morta. */
  padding: 20px 0 20px 20px;
  overflow-x: auto;
  align-items: flex-start;
  flex: 1;
  min-height: 0;
  background: var(--marfim);
}

.kanban::-webkit-scrollbar { height: 10px; }
.kanban::-webkit-scrollbar-track { background: transparent; }
.kanban::-webkit-scrollbar-thumb { background: #d9cfc1; border-radius: 999px; border: 2px solid var(--marfim); }
.kanban::-webkit-scrollbar-thumb:hover { background: var(--laranja); }
.kanban { scrollbar-color: #d9cfc1 transparent; }

/* O respiro do fim do quadro, que era o `padding-right` do `.kanban` (ver
   acima). Só acima de 600px: no celular o bloco `@media` redefine o padding
   inteiro e cada coluna já ocupa a tela toda. */
@media (min-width: 601px) {
  .kanban > .kanban-coluna:last-child { margin-right: 20px; }
}

.kanban-coluna {
  background: var(--fundo-app);
  border: 1px solid var(--linha-editorial);
  border-radius: var(--raio);
  width: 288px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  max-height: 100%;
  box-shadow: 0 6px 18px rgba(17, 45, 74, 0.06);
  overflow: hidden;
  transition: box-shadow 0.2s ease;
}

.kanban-coluna:hover { box-shadow: 0 10px 26px rgba(17, 45, 74, 0.1); }

/* Coluna do CARRINHO (sessão 139) — pedido do usuário: "esse carrinho não é
   tanta prioridade... deixar ele bem mais fino, diferenciando dos carros de
   verdade". O carrinho é o de mão que atravessa a rua até a oficina
   (`veiculos.py`), não um veículo da frota: ele ocupava a mesma largura e o
   mesmo peso visual de uma Master.

   208px em vez de 288px — estreita o bastante pra ler de relance como "outra
   coisa", larga o bastante pro card de parada não apertar o texto (a régua
   foi o card, não a estética). O backend já o manda por último
   (`kanban.py`, ORDER BY); isto é a outra metade. */
.kanban-coluna-carrinho {
  width: 208px;
  border-style: dashed;
  /* Colada na borda direita do quadro (sessão 139): o quadro rola na
     horizontal e o carrinho é o ÚLTIMO, ou seja o primeiro a sair da tela —
     era preciso rolar até o fim pra lembrar que ele existe. `sticky` na
     direita faz as colunas de carro rolarem POR BAIXO dela. z-index acima
     das outras colunas porque é exatamente isso que ela faz: flutuar sobre
     elas. */
  position: sticky;
  right: 0;
  z-index: 3;
  /* Sem sombra à direita: o `.kanban` não tem mais `padding-right` (ver a
     regra dele), então `right: 0` prende a aba exatamente na borda em que o
     `overflow` já recorta as colunas — não sobra faixa nenhuma pra tapar.
     A v1.132.2 precisou de uma sombra de 24px aqui justamente porque o
     padding existia. */
  box-shadow: none;
}

/* O respiro à ESQUERDA e a sombra que diz "isto flutua" só existem enquanto
   a coluna está DE FATO presa em cima de outra (`Kanban._atualizarCarrinho
   Preso` liga a classe quando ainda há scroll à direita).

   Pintar sempre foi o bug da v1.132.2: no fim do scroll a coluna volta pra
   posição natural, onde o `gap: 18px` do `.kanban` já dá o mesmo respiro —
   e aí a faixa passava a cobrir os últimos 18px da coluna vizinha, mais o
   degradê da sombra por cima ("ainda ficou um pedacinho em cima do peugeot").
   Os 18px são o próprio `gap` do quadro: presa ou solta, o intervalo entre o
   carrinho e o vizinho tem de ser o mesmo que separa duas colunas quaisquer.

   A ordem das duas importa: a primeira é pintada POR CIMA da segunda, então
   o marfim sólido recorta o degradê e a sombra só aparece DEPOIS do respiro,
   nunca dentro dele. */
.kanban-coluna-carrinho.presa {
  box-shadow:
    -18px 0 0 0 var(--marfim),
    -26px 0 18px -6px rgba(17, 45, 74, 0.12);
}
.kanban-coluna-carrinho.presa:hover {
  box-shadow:
    -18px 0 0 0 var(--marfim),
    -26px 0 18px -6px rgba(17, 45, 74, 0.18);
}

/* Estado padrão: recolhida numa aba de 48px. O conteúdo continua montado no
   DOM (só escondido) — é o que permite abrir no meio de um arrasto sem
   re-renderizar a coluna sob o cursor, ver `Kanban.ligarAbaCarrinho`. */
.kanban-coluna-carrinho.recolhida {
  width: 48px;
  background: var(--marfim);
  border-style: solid;
  border-color: var(--linha-editorial);
  /* Altura do CONTEÚDO (~125px), não `align-self: stretch`. Stretch fazia a
     aba descer até o fim do quadro — 683px contra colunas de 391 a 683 — e
     sobrava um corredor cinza vazio ao lado de toda coluna curta (relato do
     usuário: "essa parte cinza entre o risco e o último card").

     Igualar à coluna MAIS ALTA não resolveria: a Fila costuma ser a mais
     alta do quadro, e a aba voltaria a sobrar ao lado das curtas — que é
     justamente o caso reclamado. Altura de conteúdo é a única que não deixa
     rabo em nenhuma combinação de colunas.

     Não há `min-height` de propósito: engordar a aba pra virar um alvo de
     arrasto maior seria reintroduzir o mesmo vazio, só que menos. 48×125px
     já é alvo maior que a maioria dos botões da tela. */
  align-self: flex-start;
}
@media (min-width: 601px) {
  .kanban-coluna-carrinho.recolhida > *:not(.kanban-carrinho-aba) { display: none; }
}
.kanban-coluna-carrinho:not(.recolhida) > .kanban-carrinho-aba { display: none; }

.kanban-carrinho-aba {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 14px 0;
  border: 0;
  background: none;
  cursor: pointer;
  color: var(--texto-secundario);
  font: inherit;
  transition: color 0.2s ease, background 0.2s ease;
}
.kanban-carrinho-aba:hover { color: var(--navy); background: #efeee8; }
.kanban-carrinho-aba .ico { width: 18px; height: 18px; flex-shrink: 0; }
/* Nome na vertical, lido de baixo pra cima — a convenção de lombada de
   livro, e a única forma de caber "CARRINHO" em 48px sem abreviar. */
.kanban-carrinho-aba-nome {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-height: 0;
}
/* Pendentes é a única informação que justifica interromper alguém: a aba
   fechada precisa conseguir dizer "tem coisa aqui dentro". */
.kanban-carrinho-aba-contador {
  flex-shrink: 0;
  min-width: 20px;
  padding: 2px 5px;
  border-radius: 999px;
  background: var(--laranja);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.5;
}
/* Cabeçalho apagado: o contraste alto é o que faz a coluna "puxar o olho", e
   é justamente isso que não queremos aqui. */
.kanban-coluna-carrinho .kanban-coluna-topo { opacity: 0.82; }
/* Os dois selects (motorista e origem) ficam lado a lado nos 288px normais;
   a 208px eles truncavam pra "sem mo…" / "sem orig…". Empilhar é o que faz a
   coluna estreita continuar LEGÍVEL — estreitar não pode custar entender o
   que o controle diz. Só aqui: nas colunas de carro os dois cabem. */
.kanban-coluna-carrinho .kanban-controles { flex-direction: column; align-items: stretch; }
/* No celular não precisa de regra própria: o `@media (max-width: 600px)` mais
   abaixo já põe TODA coluna em `calc(100vw - 24px)` e, por vir depois com a
   mesma especificidade, vence o 208px daqui — que é o comportamento certo
   (lá as colunas rolam uma a uma e encolher só atrapalharia). A distinção do
   carrinho continua pela borda tracejada e pelo cabeçalho apagado. */
.kanban-coluna.pool { background: #f7f8f5; }
.kanban-coluna.reserva { background: #fff8ec; border-color: #f3d9a4; }
.kanban-coluna.alvo { border-color: var(--laranja); background: var(--laranja-fundo); box-shadow: 0 10px 26px rgba(242, 107, 58, 0.18); }

/* TASK-124/TASK-130 (UX-070/VIS-025): abaixo de 600px nenhuma das media
   queries deste arquivo redefinia `.kanban-coluna { width: 288px }` — o
   quadro virava um carrossel de 2164px (7 colunas) navegado numa tela de
   360px, sem indicar quantas colunas existem nem onde a coluna atual
   termina. Coluna = largura da viewport + scroll-snap: 1 coluna = 1 "página",
   arrasto vira gesto discreto (para exatamente numa coluna, não no meio de
   duas) e ainda sobra a pista de que há mais conteúdo (o começo da próxima
   coluna aparece na borda). O contador "Nome · 3 de 8" (`.quadro-posicao`,
   `Kanban._atualizarPosicaoQuadro()`) resolve a metade que o snap sozinho
   não resolve: quantas colunas existem. Nada disto toca acima de 600px —
   desktop (4-5 colunas de 288px) e tablet 768px continuam como hoje. */
@media (max-width: 600px) {
  .kanban { padding: 8px 12px; gap: 12px; scroll-snap-type: x mandatory; }
  .kanban-coluna { width: calc(100vw - 24px); scroll-snap-align: start; }
  .kanban-controles { padding: 4px 10px; }
  /* No celular a aba não tem função: cada coluna é uma "página" do carrossel
     com scroll-snap e o `.quadro-posicao` já diz quantas existem — uma
     coluna grudada na direita comeria um terço da tela em TODAS as páginas.
     Aqui o carrinho volta a ser uma coluna normal, sempre aberta; a
     distinção dele continua pela borda tracejada e pelo cabeçalho apagado. */
  .kanban-coluna-carrinho,
  .kanban-coluna-carrinho.presa {
    position: static;
    box-shadow: none;
    border-style: dashed;
  }
  .kanban-coluna-carrinho.recolhida { width: calc(100vw - 24px); align-self: auto; background: var(--fundo-app); }
  /* No celular a coluna nunca recolhe (ver acima) — a altura volta a ser a
     do conteúdo da coluna inteira, não a da aba. */
  .kanban-coluna-carrinho > .kanban-carrinho-aba,
  .kanban-coluna-carrinho [data-carrinho-fechar] { display: none; }
}


/* Duas linhas: nome+avatar (linha1) com o espaço quase inteiro da coluna
   pra não truncar cedo demais, etiqueta de status + contador de pendentes
   (linha2) embaixo, alinhados com o nome — antes tudo dividia uma linha só
   com o avatar, e nome de motorista comprido (ex.: "EDMILSON DA SILVA
   OLIVERA") sobrava só ~40px de largura, truncando pra "ED…". */
.kanban-coluna-topo {
  padding: 14px 14px 12px;
  /* Mesmo gradiente navy do card de despacho da Visão geral
     (.vg-card-despacho) — amplifica o cabeçalho da coluna com o motivo que
     o resto do app já usa pra "painel de controle", em vez de inventar um
     novo tratamento só aqui. */
  background: linear-gradient(155deg, var(--navy), var(--navy-2));
  color: #fffaf4;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.kanban-coluna-topo-linha1 { display: flex; align-items: center; gap: 10px; }
.kanban-coluna-topo-linha2 { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; row-gap: 6px; padding-left: 42px; }

.kanban-coluna-topo .avatar { width: 32px; height: 32px; font-size: 12px; box-shadow: 0 0 0 2px rgba(255, 250, 244, 0.2); }

/* TASK-124 item 3: cabeçalho da coluna compactado no celular (~30px a
   menos de altura) — avatar menor e menos padding/gap, mesma estrutura de
   duas linhas (não mexe na lógica de truncamento do nome, só no espaço ao
   redor). Precisa vir DEPOIS da regra base acima — mesmo motivo do
   comentário em `.kanban-card-alca-texto`: media query e regra base com a
   mesma especificidade, quem vem depois no arquivo vence. */
@media (max-width: 600px) {
  .kanban-coluna-topo { padding: 6px 12px 5px; gap: 2px; }
  .kanban-coluna-topo .avatar { width: 24px; height: 24px; font-size: 10px; }
  .kanban-coluna-topo-linha2 { padding-left: 32px; }
}

.kanban-coluna-nome {
  font-weight: 700;
  font-size: 14px;
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: #fffaf4;
}

.kanban-coluna-nome span {
  display: block;
  font-weight: 500;
  font-size: 11.5px;
  color: rgba(255, 250, 244, 0.62);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.etiqueta-status {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 4px 8px;
  border-radius: 999px;
  background: #e5e7eb;
  color: #4b5563;
  white-space: nowrap;
}

/* UI-003 (docs/ROUTE-UX-UI.md): "sem_rota" (veículo disponível, ninguém
   saiu ainda) e "concluida" (rota fechada com sucesso) usavam exatamente o
   mesmo verde — informações com implicações opostas ("posso despachar
   aqui" vs. "esse trabalho já acabou") ficavam indistinguíveis num
   escaneamento rápido do cabeçalho da coluna. Verde fica só pra "fechou
   com sucesso"; "disponível" usa o tom neutro/informativo que o design
   system já reserva pra isso (--azul-info, ver design-system.md §2). */
.etiqueta-status.sem_rota { background: #e3edf3; color: #2c556e; }
.etiqueta-status.planejada { background: #fef3c7; color: #92400e; }
.etiqueta-status.em_rota { background: #dbeafe; color: #1e40af; }
.etiqueta-status.retornando { background: #ede9fe; color: #5b21b6; }
.etiqueta-status.concluida { background: #dcfce7; color: #166534; }

/* Contador de paradas pendentes no cabeçalho da coluna (TASK-024) — só
   informação, não controle: sem fundo/borda, peso próximo ao da
   .etiqueta-status ao lado. Cor clara porque o cabeçalho da coluna agora é
   navy (ver .kanban-coluna-topo). */
.kanban-contador-pendentes {
  font-size: 11px;
  font-weight: 600;
  color: rgba(255, 250, 244, 0.62);
  white-space: nowrap;
}

/* ROT-003 (docs/ROUTING-MAP-ANALYSIS.md): soma de volumes pendentes da
   coluna — vira aviso (não bloqueio) quando passa da capacidade cadastrada
   do veículo. Mesmo peso visual do contador de pendentes ao lado; só muda
   de cor quando há algo a avisar. */
.kanban-contador-volumes {
  font-size: 11px;
  font-weight: 600;
  color: rgba(255, 250, 244, 0.62);
  white-space: nowrap;
}
.kanban-contador-volumes.acima-capacidade { color: #fde68a; font-weight: 700; }

.kanban-coluna-excluir {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: rgba(255, 250, 244, 0.7);
  cursor: pointer;
  flex-shrink: 0;
}
.kanban-coluna-excluir:hover { color: #fff; background: rgba(255, 255, 255, 0.14); }
.kanban-coluna-excluir:disabled { opacity: 0.5; cursor: default; }

/* Ações de OPERAR a rota no lugar do motorista (iniciar, retornar,
   finalizar) — mesmo formato dos ícones vizinhos, mas destacadas: são o
   fluxo normal de quem registra a viagem pelo quadro, não ações
   secundárias como remarcar/excluir. Eram botões de largura inteira até a
   sessão 42; viraram ícone a pedido do usuário, pra caber junto do
   calendário e da lixeira em vez de empurrar os cards pra baixo. */
.kanban-coluna-acao {
  color: #fff;
  background: rgba(255, 255, 255, 0.16);
}
.kanban-coluna-acao:hover { background: var(--laranja); }

/* Menu "⋯" do cabeçalho da coluna (sessão 141) — as ações que NÃO são a
   principal do estado, cada uma com rótulo escrito. O motivo de existir é
   legibilidade, não espaço: no máximo três ações coexistem, mas "casinha" e
   "calendário" não dizem o que fazem, e o gestor tinha que passar o mouse
   por cima pra descobrir.

   A lista é `absolute` ancorada no próprio <details> (`relative`), e fica no
   CABEÇALHO da coluna — que não tem overflow. O corpo da coluna tem, então
   um menu que morasse lá dentro seria recortado pela borda. */
.kanban-coluna-menu { position: relative; display: flex; }
.kanban-coluna-menu > summary {
  list-style: none;
  /* Safari ainda desenha o triângulo sem isto, e ele apareceria DENTRO do
     botão de 26px, ao lado do ícone. */
  -webkit-appearance: none;
}
.kanban-coluna-menu > summary::-webkit-details-marker { display: none; }
.kanban-coluna-menu > summary::marker { content: ""; }

.kanban-coluna-menu-lista {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 20;
  min-width: 190px;
  display: flex;
  flex-direction: column;
  padding: 4px;
  border-radius: var(--raio);
  background: var(--fundo-app);
  box-shadow: var(--sombra-alta);
}

.kanban-coluna-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: var(--texto);
  font-size: 13px;
  font-weight: 600;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}
.kanban-coluna-menu-item:hover { background: var(--azul-claro); }
.kanban-coluna-menu-item.perigo { color: var(--vermelho); }
.kanban-coluna-menu-item.perigo:hover { background: #fdecec; }

/* Alvo de toque no celular, mesma régua do A11Y-002 (--alvo-toque). */
@media (max-width: 900px) {
  .kanban-coluna-menu-item { min-height: var(--alvo-toque); }
}

.kanban-sugestao {
  padding: 8px 10px 0;
}

.botao-sugerir-ordem {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 7px 10px;
  border: 1px dashed #e4cec4;
  border-radius: 8px;
  background: #fff8f4;
  color: var(--laranja);
  font-size: 11.5px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
}
.botao-sugerir-ordem .ico { width: 14px; height: 14px; }
.botao-sugerir-ordem:hover { background: var(--laranja); color: #fff; border-color: var(--laranja); }
.botao-sugerir-ordem:disabled { opacity: 0.6; cursor: default; }

/* Sessão 75: o botão sempre esteve aqui, mas era o gestor que tinha que
   lembrar de apertar — não havia nada dizendo QUANDO valia a pena. Com
   economia estimada (kanban.py::_economia_de_ordem_km) o botão sai do
   tracejado discreto e vira uma ação afirmativa, com o número logo abaixo.
   `--amarelo-*` de propósito, não `--vermelho`: é "dá pra melhorar", não
   erro (semântica da §4 do design-system). */
.botao-sugerir-ordem.tem-economia {
  border-style: solid;
  border-color: var(--amarelo-borda);
  background: var(--amarelo-fundo);
  color: var(--amarelo-texto);
}
.botao-sugerir-ordem.tem-economia:hover {
  background: var(--amarelo);
  border-color: var(--amarelo);
  color: #fff;
}

.kanban-economia {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-top: 5px;
  font-size: 11px;
  line-height: 1.35;
  color: var(--amarelo-texto);
}
.kanban-economia .ico { width: 13px; height: 13px; flex-shrink: 0; }

/* DESP-002 (docs/DISPATCH-UX.md): barra de distribuição em lote — só
   aparece na Fila de transporte com o modo de seleção ligado. */
.kanban-lote-barra {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  background: var(--laranja-fundo);
  border-bottom: 1px solid var(--borda);
  flex-wrap: wrap;
}
.kanban-lote-contagem { font-size: 12px; font-weight: 700; color: var(--laranja-hover); white-space: nowrap; }
.kanban-lote-select { flex: 1; min-width: 140px; font-size: 12.5px; padding: 5px 6px; border-radius: 6px; border: 1px solid var(--borda); }

/* Sessão 125.2: painel do botão "Outro dia" (reserva o veículo pra um dia
   futuro sem trocar a data do quadro — ver kanban.js::ligarBotaoReservarFuturo).
   Desde a sessão 126 vive no RODAPÉ da coluna, junto das gavetas que ele cria
   (por isso `border-top`, não `border-bottom`).
   Mesmo espírito visual de `.kanban-lote-barra` (faixa inline dentro da
   coluna, não um popover flutuante — mais simples de posicionar e some
   sozinho no próximo render depois de criar a reserva). */
.kanban-reserva-futura {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
  background: var(--azul-claro);
  border-top: 1px solid var(--borda);
  flex-wrap: wrap;
}
.kanban-reserva-chip {
  font-size: 12px;
  font-weight: 600;
  padding: 5px 9px;
  border-radius: 99px;
  border: 1px solid var(--azul-primario);
  background: var(--fundo-app);
  color: var(--azul-primario);
  cursor: pointer;
  white-space: nowrap;
}
.kanban-reserva-chip:hover { background: var(--azul-primario); color: #fff; }
.kanban-reserva-outra { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 160px; }
.kanban-reserva-input {
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  padding: 5px 6px;
  border-radius: 6px;
  border: 1px solid var(--borda);
}

/* ══ Gavetas de dia futuro (sessão 126) ══════════════════════════════════
   Pedido do usuário: "abaixo de todos os carros ter um lugar para clicar
   para abrir essa data que eu selecionar, ai sim eu arrastaria pra la e o
   motorista so veria no dia". Cada faixa é um disclosure + uma zona de
   soltura própria (ver kanban.js::montarDiaFuturo).

   Visual deliberadamente mais quieto que o dos cards de hoje (fundo do
   painel, texto secundário): é agenda, não trabalho do dia — o mesmo
   raciocínio da coluna translúcida que isto substituiu. */
.kanban-dias-futuros { display: flex; flex-direction: column; }
.kanban-coluna.tem-dias-futuros .kanban-corpo > .kanban-cards { flex: 0 0 auto; }

.kanban-dia-futuro {
  border-top: 1px solid var(--linha-editorial);
  background: var(--fundo-painel);
}
.kanban-dia-futuro.alvo {
  background: var(--laranja-fundo);
  box-shadow: inset 3px 0 0 var(--laranja);
}

.kanban-dia-futuro-topo { display: flex; align-items: center; gap: 2px; padding-right: 6px; }
/* `.kanban-coluna-excluir` nasceu pro cabecalho ESCURO da coluna (icone quase
   branco) — na faixa clara da gaveta ele ficava invisivel (achado na
   validacao, sessao 126). Mesma caixa, cor repintada. */
.kanban-dia-futuro .kanban-coluna-excluir { color: var(--texto-secundario); }
.kanban-dia-futuro .kanban-coluna-excluir:hover {
  color: var(--vermelho-editorial);
  background: rgba(17, 45, 74, 0.07);
}

.kanban-dia-futuro-alternar {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 8px 10px;
  background: none;
  border: 0;
  cursor: pointer;
  font-size: 12px;
  font-weight: 700;
  color: var(--texto-secundario);
  text-align: left;
}
.kanban-dia-futuro-alternar:hover { color: var(--azul-primario); }
.kanban-dia-futuro-seta { transition: transform 0.18s ease; transform: rotate(-90deg); flex-shrink: 0; }
.kanban-dia-futuro-alternar[aria-expanded="true"] .kanban-dia-futuro-seta { transform: rotate(0deg); }
.kanban-dia-futuro-data { text-transform: capitalize; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kanban-dia-futuro-contagem {
  margin-left: auto;
  font-size: 11px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 99px;
  background: var(--fundo-app);
  border: 1px solid var(--linha-editorial);
  white-space: nowrap;
}

.kanban-dia-futuro-aviso {
  display: flex;
  align-items: center;
  gap: 5px;
  margin: 0;
  padding: 0 10px 2px;
  font-size: 11px;
  color: var(--texto-secundario);
}
/* A lista da gaveta NÃO rola sozinha (ver `.kanban-corpo`) — cresce e empurra,
   quem rola é a coluna inteira. */
.kanban-dia-futuro-cards { overflow: visible; flex: 0 0 auto; min-height: 54px; padding-top: 6px; }

.kanban-dia-futuro-rodape {
  padding: 7px 10px;
  border-top: 1px solid var(--linha-editorial);
  background: var(--fundo-painel);
}
.kanban-dia-futuro-add {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 7px;
  font-size: 12px;
  font-weight: 600;
  color: var(--texto-secundario);
  background: none;
  border: 1px dashed var(--linha-editorial);
  border-radius: 8px;
  cursor: pointer;
}
.kanban-dia-futuro-add:hover { color: var(--azul-primario); border-color: var(--azul-primario); border-style: solid; }

.kanban-card-selecionar {
  align-self: flex-start;
  margin-top: 3px;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  cursor: pointer;
}

/* "Iniciar/Finalizar pelo motorista" (sessão 38) — mesma pílula de
   "Sugerir ordem", cor azul-primário em vez de laranja pra não confundir
   com sugestão de rota: isso aqui é operar a viagem no lugar do
   motorista. */
.botao-acao-motorista {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 7px 10px;
  border: 1px dashed #c7d9f7;
  border-radius: 8px;
  background: var(--azul-claro);
  color: var(--azul-primario);
  font-size: 11.5px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
}
.botao-acao-motorista .ico { width: 14px; height: 14px; }
.botao-acao-motorista:hover { background: var(--azul-primario); color: #fff; border-color: var(--azul-primario); }
.botao-acao-motorista:disabled { opacity: 0.6; cursor: default; }

/* Sessão 126: a rolagem da coluna subiu da lista de cards pro `.kanban-corpo`,
   que envolve os cards de HOJE mais as gavetas de dia futuro. Se cada um
   rolasse por conta própria, uma coluna com sábado e domingo abertos teria
   três barras de rolagem aninhadas dentro de 288px. `flex: 1 0 auto` na
   lista de hoje preserva o que o `flex: 1` fazia antes — o espaço vazio
   abaixo do último card continua sendo zona de soltura, que é como se
   arrasta pra uma coluna quase vazia —, mas sem impedir que ela cresça além
   da altura visível quando as gavetas empurram. */
.kanban-corpo {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}
.kanban-corpo::-webkit-scrollbar { width: 8px; }
.kanban-corpo::-webkit-scrollbar-track { background: transparent; }
.kanban-corpo::-webkit-scrollbar-thumb { background: var(--linha-editorial); border-radius: 999px; }
.kanban-corpo::-webkit-scrollbar-thumb:hover { background: #d7cabf; }
.kanban-corpo { scrollbar-color: var(--linha-editorial) transparent; }

.kanban-cards {
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 9px;
  flex: 1 0 auto;
  min-height: 90px;
}

.kanban-card {
  background: #fff;
  border: 1px solid var(--linha-editorial);
  border-radius: var(--raio);
  padding: 11px 12px;
  cursor: grab;
  display: flex;
  gap: 10px;
  align-items: flex-start;
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.05);
  transition: border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

.kanban-card:hover { border-color: #d7cabf; transform: translateX(1px); box-shadow: 0 4px 10px rgba(16, 24, 40, 0.08); }
.kanban-card.arrastando { opacity: 0.4; }
.kanban-card.concluida { background: #f8fafc; }
.kanban-card.concluida .kanban-card-texto strong { text-decoration: line-through; color: var(--texto-secundario); }
.kanban-card.concluida .kanban-ordem { background: #eef2f6; color: var(--texto-secundario); }

/* "Ocultar entregues" (sessão 105). É só isto mesmo: esconder por CSS mantém
   os cards no DOM, e o cálculo de `ordem` do drag-and-drop depende deles
   estarem lá (ver Kanban.aplicarOcultarConcluidas). */
.quadro-oculta-concluidas .kanban-card.concluida { display: none; }
.kanban-ocultas {
  margin: 4px 2px 0;
  padding: 6px 8px;
  border: 1px dashed var(--borda);
  border-radius: 8px;
  font-size: 0.75rem;
  color: var(--texto-secundario);
  text-align: center;
}
/* Entregue/não entregue com a cor de estado (design-system.md §4) no lugar
   do cinza único — pedido do usuário: sem cor, "concluída" e "não entregue"
   pareciam a mesma coisa até ler o texto pequeno. */
.kanban-card.entregue .kanban-ordem { background: var(--verde); color: #fff; }
.kanban-card.nao_entregue .kanban-ordem { background: var(--vermelho); color: #fff; }

/* Próxima entrega do motorista em rota — mesmo acento laranja usado no
   restante do app pra "onde a ação está acontecendo agora". */
.kanban-card.em-andamento {
  background: var(--laranja-fundo);
  border-color: var(--laranja);
  border-left: 3px solid var(--laranja);
  box-shadow: 0 2px 8px rgba(242, 107, 58, 0.18);
}

/* ALTO-002 (docs/ROUTE-SYSTEM-AUDIT.md): destaque temporário ao chegar do
   mapa (clique num marcador) — some sozinho, não é um estado persistente
   como .em-andamento. */
.kanban-card.kanban-card-destacado {
  outline: 2px solid var(--laranja);
  outline-offset: 2px;
  transition: outline-color 1.5s ease;
}

.kanban-card-texto span.kanban-card-badge-atual {
  display: inline-flex;
  width: fit-content;
  align-items: center;
  gap: 4px;
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  background: var(--laranja);
  border-radius: 5px;
  padding: 2px 7px;
  margin-top: 4px;
}

/* Segunda tentativa de uma entrega que não saiu (sessão 94). Usa o par
   texto/fundo/borda de "atenção" (--amarelo-*, DSG-011) e não o laranja
   sólido do badge acima: os dois podem aparecer no MESMO card, e dois
   blocos sólidos disputando atenção fazem o gestor não ler nenhum. Aqui é
   contexto ("já falhou uma vez, foi remarcada"), não estado do agora. */
.kanban-card-texto span.kanban-card-reagendada {
  display: inline-flex;
  width: fit-content;
  align-items: center;
  gap: 4px;
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  font-size: 11px;
  font-weight: 600;
  color: var(--amarelo-texto);
  background: var(--amarelo-fundo);
  border: 1px solid var(--amarelo-borda);
  border-radius: 5px;
  padding: 2px 7px;
  margin-top: 4px;
}


.kanban-card-acoes { display: flex; flex-direction: column; gap: 2px; flex-shrink: 0; }

.kanban-card-alca {
  color: var(--texto-secundario);
  background: none;
  border: none;
  cursor: pointer;
  padding: 2px;
  border-radius: 5px;
  display: flex;
}

.kanban-card-alca:hover { color: var(--laranja); background: var(--laranja-fundo); }
.kanban-card-alca[data-remover]:hover { color: var(--vermelho); background: #fef2f2; }
/* Concluir pelo gestor (sessão 38) — mesma semântica de cor de status do
   resto do app: verde = entregue, vermelho = não entregue (regra técnica
   de cor, ver rules/design-system.md §4). */
.kanban-card-alca-ok:hover { color: var(--verde); background: #f0fdf4; }

/* TASK-131/VIS-026: no desktop o `title` já serve de dica (hover) — o
   rótulo só aparece em toque (≤900px, ver bloco A11Y-002 abaixo), onde
   também diferencia o botão "Atribuir" do de Observação (mesmo ícone
   `#i-nota`, sem isso os dois eram indistinguíveis no celular). Precisa
   vir ANTES do bloco A11Y-002 no arquivo: a media query também declara
   `display: inline` pra essa classe, e por empate de especificidade
   quem vem depois no CSS vence — se este `display: none` ficasse depois,
   anularia o `inline` mesmo dentro do próprio ≤900px. */
.kanban-card-alca-texto { display: none; font-size: 11px; font-weight: 600; white-space: nowrap; }
.kanban-card-alca[data-editar] { gap: 4px; }

/* A11Y-002 (docs/PERFORMANCE-ACCESSIBILITY.md): abaixo de 900px o quadro
   passa a ser operado por toque (premissa original citava `.painel-aberta`
   como o overlay mobile — DSG-036 confirmou que essa classe é CSS morto
   hoje; o gatilho real é só a largura da viewport). `.kanban-coluna-excluir`
   (26×26) e `.kanban-card-alca` (ícone + padding:2px, ~22-24px) ficam abaixo
   do alvo de toque recomendado (WCAG 2.5.8 pede 24×24 mínimo — passam
   raspando; a prática comum de touch UI é 44×44, ver `--alvo-toque`).

   TASK-121/DSG-040 ampliou este bloco: `.card-item-desativar`, `.kanban-
   select`, `.mapa-filtro-limpar`/`.mapa-filtro-minimizar` e `.botao-icone`
   entraram aqui pela mesma razão. `.card-item-atribuir` também — mas note:
   o relatório original (DSG-040) descreveu essa classe como "a alternativa
   touch ao drag-and-drop"; não é — ela estiliza `#d-registrar-motorista`
   (select de registrar viagem no card do motorista), nunca esteve em
   `kanban.js` (conferido via `git log -S`). A alternativa real ao
   drag-and-drop é o select "Atribuir a" (`#mep-mover-para`, dentro de
   `#modal-editar-parada`) — corrigido aqui via `.mep-campo select`, que
   `.card-item-atribuir` não cobria. Ver TASK-121 § Registro de execução.

   Sessão 127 (pedido do usuário: "os botões são de difícil acesso"):
   medido ao vivo — `.kanban-card-alca` renderizava 36px de altura com
   `padding:10px` sozinho, ainda abaixo dos 44px. Trocado por
   `min-height`/`min-width` explícitos (`--alvo-toque`), que GARANTE o
   alvo em vez de aproximar por padding + tamanho do ícone somados —
   mesma régua de `.kanban-coluna-excluir`, que só chegava a 40px. */
@media (max-width: 900px) {
  .kanban-coluna-excluir { width: var(--alvo-toque); height: var(--alvo-toque); }
  .kanban-card-alca {
    padding: 10px;
    min-width: var(--alvo-toque);
    min-height: var(--alvo-toque);
    justify-content: center;
  }
  .card-item-atribuir { min-height: var(--alvo-toque); }
  .kanban-select { min-height: var(--alvo-toque); }
  .card-item-desativar {
    min-width: var(--alvo-toque);
    min-height: var(--alvo-toque);
    align-items: center;
    justify-content: center;
  }
  .mapa-filtro-limpar {
    min-height: var(--alvo-toque);
    display: inline-flex;
    align-items: center;
    padding: 4px 2px;
  }
  .mapa-filtro-minimizar {
    min-width: var(--alvo-toque);
    min-height: var(--alvo-toque);
    align-items: center;
    justify-content: center;
  }
  .botao-icone {
    min-width: var(--alvo-toque);
    min-height: var(--alvo-toque);
    align-items: center;
    justify-content: center;
  }
  .mep-campo select { min-height: var(--alvo-toque); }
  .kanban-card-alca-texto { display: inline; }
}
.kanban-card-alca-erro:hover { color: var(--vermelho); background: #fef2f2; }
.kanban-card-alca .ico { width: 16px; height: 16px; }

.kanban-card-texto { min-width: 0; flex: 1; }
.kanban-card-texto strong { display: flex; align-items: center; gap: 4px; font-size: 13px; }
.kanban-card-texto strong .ico { color: var(--texto-secundario); }

.kanban-card-texto span.kanban-card-obs {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  width: fit-content;
  font-size: 11.5px;
  color: var(--amarelo-texto);
  background: var(--amarelo-fundo);
  border-radius: 5px;
  padding: 2px 6px;
  margin-top: 4px;
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
}

.kanban-card-texto span.kanban-card-nota-motorista {
  color: #1b3b73;
  background: #e0e7ff;
}

/* UI-002 (docs/ROUTE-UX-UI.md): justificativa de atraso é, por definição,
   um sinal de problema — tinha o MESMO badge azul da nota casual do
   motorista, diferindo só pelo ícone a 12px (quase imperceptível num
   escaneamento rápido). Cor de alerta própria, na mesma família de
   vermelho já usada pro resto do produto (erro/excluir/não entregue). */
.kanban-card-texto span.kanban-card-atraso {
  color: #9f1c1c;
  background: #fee2e2;
}

/* MÉDIO-001/SIM-003 (docs/ROUTE-SYSTEM-AUDIT.md, docs/REAL-WORLD-
   SIMULATION.md): "atrasada" é PROATIVO (a entrega ainda está pendente,
   passou do horário combinado) — diferente de `.kanban-card-atraso`
   acima, que é a justificativa que o motorista escreve DEPOIS de concluir.
   Mesma família de vermelho, mas com o card inteiro marcado (borda), não
   só um badge de texto — é o sinal de maior prioridade possível no
   quadro: uma entrega que precisa de decisão AGORA. */
.kanban-card.atrasada {
  border-color: #f3a5a5;
  box-shadow: 0 0 0 1px #f3a5a5 inset;
}
.kanban-card-texto span.kanban-card-atrasada-agora {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 7px;
  border-radius: 999px;
  color: #9f1c1c;
  background: #fee2e2;
  font-size: 11px;
  font-weight: 700;
  width: fit-content;
}
.kanban-card-texto span.kanban-card-atrasada-agora .ico { width: 12px; height: 12px; }

.kanban-card-texto span.kanban-card-horario {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 11px;
  font-weight: 700;
  color: var(--texto-secundario);
  margin-top: 2px;
}
.kanban-card-texto span.kanban-card-horario .ico { width: 12px; height: 12px; }
.kanban-card.entregue .kanban-card-texto span.kanban-card-horario { color: var(--verde); }
.kanban-card.nao_entregue .kanban-card-texto span.kanban-card-horario { color: var(--vermelho); }

/* DESP-001 (docs/DISPATCH-UX.md): chip de bairro/cidade separado do
   endereço completo — antes só dava pra identificar a região lendo o
   endereço inteiro de cada card. Precisa do prefixo qualificado completo
   (regra técnica 104/CONTEXTO-IA.md): `.kanban-card-texto span` sozinho já
   tem especificidade 0,1,1 e vence uma classe nova declarada sem esse
   prefixo, mesmo vindo depois no arquivo. */
/* DESP-003 (docs/DISPATCH-UX.md): sugestão de veículo por proximidade,
   nunca vinculante — só um chip informativo, mesma régua de especificidade
   (regra técnica 104/CONTEXTO-IA.md) dos irmãos abaixo. */
.kanban-card-texto span.kanban-card-sugestao {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 11px;
  color: var(--azul-info);
  font-weight: 600;
}
.kanban-card-texto span.kanban-card-sugestao .ico { width: 12px; height: 12px; }

/* Segunda sugestão (sessão 61): o carro que JÁ ESTÁ NA RUA mais perto.
   Verde em vez do azul-info da sugestão comum — as duas aparecem uma
   embaixo da outra no mesmo card, e na mesma cor viravam duas linhas
   indistinguíveis. Verde é o "está acontecendo agora" do resto do app
   (mesma leitura de rota em campo). Mesma régua de especificidade dos
   irmãos (regra técnica 104). */
.kanban-card-texto span.kanban-card-sugestao-rodando { color: var(--verde); }

/* Preferência de veículo de quem solicitou — laranja (é escolha de gente,
   não cálculo do sistema como as duas sugestões acima, que são azul/verde).
   Mesma régua de especificidade dos irmãos (regra técnica 104). */
.kanban-card-texto span.kanban-card-preferencia { color: var(--laranja); }

/* TETO DE LARGURA DOS CHIPS DO CARD (sessão 104, relato do usuário: "as
   linhas estão passando a caixa").

   Todo chip aqui é `inline-flex`, que dimensiona pelo CONTEÚDO — sem um
   teto, um bairro comprido ("CIDADE PARQUE ALVORADA · Guarulhos") cresce
   além da coluna de texto e passa POR BAIXO dos ícones de ação da direita.
   O `text-overflow: ellipsis` que esses spans já herdam nunca entra em
   ação nesse caso: quem estourou foi a CAIXA, não o texto dentro dela.
   Medido no relato: chip de 212px numa coluna de 196px, invadindo 15px.

   Regra única em vez de `max-width` espalhado por cada classe: o card ganha
   chip novo com frequência (7 nasceram só nesta sessão e nas anteriores), e
   cada um seria uma chance nova de repetir o mesmo bug.

   Prefixo qualificado obrigatório (regra técnica 104): `.kanban-card-texto
   span` sozinho já tem especificidade 0,1,1 e venceria uma classe solta
   declarada depois. */
.kanban-card-texto span[class*="kanban-card-"] { max-width: 100%; }

/* `block`, não `inline-flex`, pra ganhar o "…" de verdade: `text-overflow`
   só age em container de bloco — num flex o texto vira item anônimo,
   inatingível pelo CSS, e o corte sai no meio da palavra ("Guarull") em vez
   de "Guarulhos…". É a linha mais comprida do card (bairro + cidade), então
   é onde isso aparece. O ícone volta a ser inline-block, alinhado à mão. */
.kanban-card-texto span.kanban-card-bairro {
  display: block;
  font-size: 11px;
  color: var(--texto-secundario);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kanban-card-texto span.kanban-card-bairro .ico {
  width: 12px;
  height: 12px;
  display: inline-block;
  vertical-align: -2px;
  margin-right: 3px;
}

.kanban-card-texto span.kanban-card-detalhe {
  display: inline-flex;
  align-items: center;
  min-width: 0;
  flex-wrap: wrap;
  gap: 3px;
  font-size: 11px;
  color: var(--texto-secundario);
}
.kanban-card-texto span.kanban-card-detalhe .ico { width: 12px; height: 12px; }
.kanban-card-texto span.kanban-card-espera-atencao { color: var(--amarelo); font-weight: 700; }
.kanban-card-texto span.kanban-card-espera-urgente { color: var(--vermelho); font-weight: 700; }

.kanban-card-texto span.kanban-card-solicitante {
  display: block;
  font-size: 11px;
  color: var(--texto-secundario);
  font-style: italic;
  margin-top: 2px;
}

/* Abre a foto de comprovante de entrega (TASK-010) — botão, não link, porque
   busca autenticada (fetch + blob), <a href> puro não funciona aqui. */
.kanban-card-pod {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 4px;
  padding: 0;
  border: none;
  background: none;
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--laranja);
  cursor: pointer;
  text-align: left;
}
.kanban-card-pod .ico { width: 14px; height: 14px; }
.kanban-card-pod:hover { text-decoration: underline; }
.kanban-card-pod:disabled { color: var(--texto-secundario); cursor: wait; }

.kanban-card-texto span {
  display: block;
  font-size: 11.5px;
  color: var(--texto-secundario);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.kanban-ordem {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--laranja-fundo);
  color: var(--laranja);
  font-size: 11px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.kanban-coluna-vazia {
  padding: 22px 12px;
  text-align: center;
  font-size: 12px;
  color: var(--texto-secundario);
  border: 1.5px dashed var(--linha-editorial);
  border-radius: var(--raio);
  line-height: 1.6;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.kanban-coluna-vazia .ico { width: 20px; height: 20px; }

.kanban-filtro-vazio {
  width: 100%;
  padding: 32px 16px;
  text-align: center;
  font-size: 13px;
  color: var(--texto-secundario);
}

/* ---------- Login (inspirado no "Login9" — hero com ondas + form) ---------- */

.tela-login {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: #eaf1fd;
}

.login-card {
  display: flex;
  flex-direction: column;
  background: #fff;
  border-radius: 26px;
  box-shadow: 0 24px 60px -12px rgba(15, 32, 62, 0.35);
  padding: 8px;
  width: clamp(300px, 90vw, 480px);
  overflow: hidden;
}

.login-hero,
.login-form { flex: 1 1 50%; }

.login-hero {
  position: relative;
  border-radius: 20px;
  overflow: hidden;
  min-height: 190px;
  display: flex;
  align-items: flex-start;
  background: var(--azul-rail);
}

.login-hero-texto {
  position: relative;
  z-index: 2;
  padding: 22px 24px 0;
  color: #fff;
}

.login-hero-marca {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 800;
  font-size: 20px;
  letter-spacing: -0.01em;
}

.login-hero-marca .ico { width: 22px; height: 22px; }

.login-hero-texto p {
  margin: 8px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  max-width: 230px;
  color: rgba(255, 255, 255, 0.92);
}

.ocean {
  height: 52%;
  min-height: 100px;
  width: 100%;
  position: absolute;
  bottom: 0;
  left: 0;
  overflow: hidden;
}

.wave {
  /* `?v=2` força quem já tem a onda azul antiga em cache do navegador a
     baixar a nova (laranja) — o arquivo não está em ARQUIVOS_ESSENCIAIS do
     service worker, então subir a versão do cache dele não resolveria. */
  background: url(/assets/icons/wave.svg?v=2) repeat-x;
  background-size: 1600px 100%;
  position: absolute;
  left: 0;
  bottom: 0;
  width: 6400px;
  height: 100%;
  animation: onda 8s cubic-bezier(0.36, 0.45, 0.63, 0.53) infinite;
  transform: translate3d(0, 0, 0);
}

.wave:nth-of-type(2) {
  opacity: 0.85;
  animation:
    onda 8s cubic-bezier(0.36, 0.45, 0.63, 0.53) -0.15s infinite,
    inchar 8s ease -1.4s infinite;
}

@keyframes onda { 0% { margin-left: 0; } 100% { margin-left: -1600px; } }
@keyframes inchar { 0%, 100% { transform: translate3d(0, -22px, 0); } 50% { transform: translate3d(0, 5px, 0); } }

@media (prefers-reduced-motion: reduce) {
  .wave { animation: none; }
}

.login-form {
  padding: 28px 22px 22px;
  display: flex;
  flex-direction: column;
}

.login-form h3 { margin: 0 0 4px; font-size: 19px; }

.login-form-nota {
  margin: 0 0 20px;
  color: var(--texto-secundario);
  font-size: 12.5px;
}

.login-link-motorista {
  display: block;
  text-align: center;
  margin-top: 16px;
  font-size: 13px;
  font-weight: 600;
  color: var(--azul-primario);
  text-decoration: none;
}

.login-link-motorista:hover { text-decoration: underline; }

@media (min-width: 560px) {
  .login-card { flex-direction: row; padding: 8px 0 8px 8px; width: clamp(300px, 90vw, 780px); }
  .login-hero { min-height: unset; }
  .login-form { padding: 34px 40px; justify-content: center; }
}

.campo { margin-bottom: 16px; flex: 1; }

.campo label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 6px;
}

.campo-ajuda { font-weight: 400; color: var(--texto-secundario); font-size: 12px; }

.campo input,
.campo select,
.campo textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--borda);
  border-radius: 8px;
  font-size: 14px;
  font-family: inherit;
  background: #fff;
  color: var(--texto);
  resize: vertical;
}

/* TASK-122 (UX-072): sem `flex-wrap` nem `min-width:0` nos filhos, a linha
   de 3 campos "Data · A partir de · Até (janela)" (363px de largura
   intrínseca) estourava uma caixa de 282px a 360px de viewport — o "Até"
   saía pela borda do modal, que não rola na horizontal (regra deliberada,
   ver "O que NÃO fazer" do achado: rolagem horizontal em formulário
   esconde o defeito em vez de corrigir). `flex-basis:110px` quebra em 2+1
   no celular e mantém os 3 numa linha só no desktop, sem precisar de media
   query. O achado sugeria 140px; medido ao vivo (`agent-browser`,
   1440×900) o `.modal-conteudo` de "Nova entrega" tem só 420px úteis pra
   3 campos + 2 gaps — 140px quebrava a 3ª linha pro desktop também (3×140
   + 24 = 444 > 420), regressão que o critério de aceite pedia pra não
   ter. 110px cabe nos dois tamanhos (3×110+24=354 ≤ 420 no desktop;
   2×110+12=232 ≤ 282 no celular). */
.linha-campos { display: flex; gap: 12px; flex-wrap: wrap; }
.linha-campos > * { flex: 1 1 110px; min-width: 0; }
.linha-campos input,
.linha-campos select { width: 100%; min-width: 0; }

/* Rótulo que quebra em 2 linhas desalinhava o campo vizinho da mesma linha.
   Medido ao vivo a 390px: em "Nova entrega", "Categoria da carga ·
   obrigatório" ficava 16px mais baixo que "Marca"; em "Novo destino", o
   input do CEP ("preenche cidade e bairro") ficava 17px mais baixo que o de
   "Número". Não é exclusividade de um modal — acontece em qualquer par
   lado a lado em que um rótulo cabe numa linha e o outro não, e é parte do
   "muita coisa se sobrepõe" relatado no celular.

   Alinhar pelo CONTROLE, e não pelo topo do rótulo, resolve pra qualquer
   texto, em qualquer largura, sem media query e sem encurtar rótulo nenhum:
   o rótulo cresce pra ocupar a sobra e o controle fica sempre embaixo.
   A regra do `> span` cobre o formato em que o controle mora DENTRO do
   `<label>` (Categoria/Marca, com o `.seletor-tags` como filho do label);
   nos campos comuns esse seletor simplesmente não casa com nada. */
.linha-campos > .campo { display: flex; flex-direction: column; }
.linha-campos > .campo > label { display: flex; flex-direction: column; flex: 1; }
.linha-campos > .campo > label > span:first-child { flex: 1; }

/* Input + botão de ação colados (ex.: telefone do destino → abrir WhatsApp).
   Botão do tamanho do input (mesma altura de .campo input), não o
   quadradinho pequeno de .botao-icone sozinho num header de modal. */
.campo-com-botao { display: flex; gap: 8px; align-items: stretch; }
.campo-com-botao input { flex: 1; min-width: 0; }
.campo-botao-whatsapp {
  align-self: stretch;
  border: 1px solid var(--borda);
  border-radius: 8px;
  padding: 0 12px;
}
.campo-botao-whatsapp:hover { color: var(--verde); border-color: var(--verde); }

.campo-checkbox {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 12px;
  cursor: pointer;
}

.campo-checkbox input { width: auto; }

/* Grupo de rádio "Menu no celular" (Configurações) — mesma pílula flex do
   checkbox, lado a lado; em telas estreitas empilha (o bloco-config já
   guarda pra 2 colunas quando cabe). */
.opcoes-nav-mobile { display: flex; flex-wrap: wrap; gap: 8px 20px; }
.opcoes-nav-mobile .campo-checkbox { margin-bottom: 0; }

.alerta-cnh {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  font-weight: 700;
  margin-top: 2px;
}
.alerta-cnh .ico { flex-shrink: 0; }

.alerta-cnh.vencida { color: var(--vermelho); }
.alerta-cnh.vencendo { color: var(--amarelo); }

.btn-primario {
  width: 100%;
  padding: 11px;
  background: var(--laranja);
  color: #fffaf4;
  border: none;
  border-radius: 8px;
  font-weight: 700;
  font-size: 14px;
  cursor: pointer;
  font-family: inherit;
  box-shadow: 0 7px 16px rgba(242, 107, 58, 0.18);
  transition: background 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
}

.btn-primario:hover { background: var(--laranja-hover); transform: translateY(-1px); box-shadow: 0 10px 21px rgba(242, 107, 58, 0.23); }
.btn-primario:active { transform: translateY(0); }
.btn-primario:disabled { background: #f3c3ac; box-shadow: none; transform: none; cursor: not-allowed; }
.btn-auto { width: auto; padding: 10px 20px; }

.btn-secundario {
  padding: 10px 18px;
  background: #fff;
  color: var(--texto);
  border: 1px solid var(--linha-editorial);
  border-radius: 8px;
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  font-family: inherit;
  transition: border-color 0.18s ease, color 0.18s ease, background 0.18s ease;
}

.btn-secundario:hover { border-color: #b6c3bd; color: var(--navy); background: #fbfbf7; }

.erro-login {
  color: var(--vermelho);
  font-size: 13px;
  margin-top: 12px;
  display: none;
}

/* ---------- Modais ---------- */

.modal {
  border: none;
  border-radius: 14px;
  padding: 0;
  box-shadow: var(--sombra-alta);
  width: min(460px, calc(100vw - 32px));
  color: var(--texto);
  animation: modal-entrar 200ms cubic-bezier(0.23, 1, 0.32, 1);
}

.modal-largo { width: min(920px, calc(100vw - 32px)); }
.modal::backdrop {
  background: rgba(17, 45, 74, 0.4);
  backdrop-filter: blur(3px);
  animation: modal-fundo-entrar 200ms ease;
}

@keyframes modal-entrar {
  from { opacity: 0; transform: scale(0.96) translateY(10px); }
  to { opacity: 1; transform: none; }
}
@keyframes modal-fundo-entrar {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* TASK-123 (UX-073): `86vh` não acompanha o teclado virtual nem a barra do
   navegador mobile (o "v" é a viewport ideal, fixa) — `dvh` (dynamic
   viewport height) recalcula quando a UI do navegador muda de tamanho.
   Suporte: Safari 15.4+/Chrome 108+ (baseline do projeto); navegador sem
   suporte ignora a 2ª declaração e fica com `86vh`, fallback natural do
   CSS (nunca declarar só `dvh` sozinho). */
.modal-corpo { display: flex; flex-direction: column; max-height: min(86vh, 760px); max-height: min(86dvh, 760px); }

.modal-topo {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 18px 20px;
  border-bottom: 1px solid var(--borda);
}

.modal-topo h3 { margin: 0; font-size: 17px; }
.modal-topo p { margin: 4px 0 0; font-size: 12.5px; opacity: 0.85; }
.modal-topo > div:first-child { flex: 1; }

.modal-topo-azul {
  /* Mesmo gradiente navy do card de despacho da Visão geral e do cabeçalho
     de coluna do quadro (DSG-016) — antes era --azul-primario sólido, a
     única tela ainda na paleta de antes da sessão 33. */
  background: linear-gradient(155deg, var(--navy), var(--navy-2));
  color: #fff;
  border-bottom: none;
  align-items: center;
}

.modal-limite { font-weight: 400; font-size: 12px; opacity: 0.8; }

.botao-icone {
  background: transparent;
  border: none;
  cursor: pointer;
  color: var(--texto-secundario);
  padding: 4px;
  border-radius: 6px;
  display: flex;
  align-self: flex-start;
}

.botao-icone:hover { background: var(--fundo-painel); color: var(--texto); }
.botao-icone.claro { color: rgba(255, 255, 255, 0.85); }
.botao-icone.claro:hover { background: rgba(255, 255, 255, 0.18); color: #fff; }

.modal-conteudo { padding: 20px; overflow-y: auto; flex: 1; }

/* TASK-123 (UX-073): `#modal-novo` (Novo destino/motorista/veículo,
   cadastro.html) tem um `<form class="painel-novo">` ENTRE `.modal-corpo`
   e `.modal-conteudo` — `display:block` por padrão quebra a cadeia flex
   (`.modal-conteudo{flex:1}` fica inerte porque não é filho direto do
   flex container), o form cresce até o conteúdo inteiro (750px+ num pai de
   ~550px) e o `.modal-rodape` (dentro do form) sai empurrado pra fora da
   viewport — sem botão de salvar visível. `#modal-editar-parada`
   (painel.html) não tem esse problema porque `.modal-conteudo` é filho
   DIRETO de `.modal-corpo` lá, sem elemento no meio. */
.modal-corpo > form.painel-novo { display: flex; flex-direction: column; flex: 1; min-height: 0; }

.modal-rodape {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: flex-end;
  align-items: center;
  padding: 14px 20px;
  border-top: 1px solid var(--borda);
  background: var(--fundo-painel);
  border-radius: 0 0 14px 14px;
}

/* Desativar/reativar fica isolado à esquerda do rodapé — ação de outra
   natureza (não é "cancelar"/"salvar"), separado pra evitar clique errado. */
.modal-rodape .btn-perigo { margin-right: auto; }

.rodape-erro { flex: 1; color: var(--vermelho); font-size: 13px; }

/* ---------- Modal "Nova entrega"/"Nova coleta" (pedido do usuário: o
   pop-up padrão estava simples demais — cabeçalho com ícone, rótulos em
   micro-caixa-alta, campos maiores, e o par volumes/nota fiscal virou uma
   linha só, como data/hora, pra parecer menos formulário empilhado). */
.modal-nova-parada .modal-topo {
  align-items: center;
  gap: 14px;
  padding: 20px 20px 16px;
}

.modal-nova-parada-icone {
  width: 42px;
  height: 42px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 11px;
  background: var(--laranja-fundo);
  color: var(--laranja);
}
.modal-nova-parada-icone .ico { width: 21px; height: 21px; }

.modal-nova-parada .modal-topo h3 {
  font-family: "Space Grotesk", "Inter", system-ui, sans-serif;
  font-size: 19px;
  letter-spacing: -0.02em;
}
.modal-nova-parada .modal-topo p { color: var(--texto-secundario); font-size: 12px; }

.modal-nova-parada .campo label {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--texto-secundario);
  font-weight: 700;
}

/* O rótulo aqui é MAIÚSCULA + letter-spacing, e o `.campo-ajuda` herdava os
   dois: a dica entrava colada na mesma linha maiúscula do rótulo e o
   conjunto lia como UMA frase só. Em "Prioridade" isso chegava a inverter o
   sentido — "PRIORIDADE MÁXIMA VAI PRO TOPO DA FILA DE TRANSPORTE" parece
   informar que a prioridade ATUAL é máxima, quando é só a legenda de uma
   das opções. No desktop cabia na mesma linha e a cor mais clara bastava
   pra separar; a 390px quebra em duas linhas e a pista visual some.

   Vira linha própria, em caixa normal e sem letter-spacing: o rótulo volta
   a ser um rótulo curto e a dica volta a ser dica. Efeito colateral
   desejado: como TODA dica passa a ocupar uma linha só sua, dois campos
   lado a lado na mesma `.linha-campos` ganham rótulos de altura previsível
   (ver a regra de alinhamento abaixo). */
.modal-nova-parada .campo-ajuda {
  display: block;
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
  font-size: 11px;
  line-height: 1.35;
  margin-top: 2px;
}

.modal-nova-parada .campo input,
.modal-nova-parada .campo textarea {
  border-radius: var(--raio);
  padding: 11px 13px;
}

/* ---------- Wizard de importação ---------- */

.passos { display: flex; gap: 6px; list-style: none; margin: 0; padding: 0; }

.passo {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.7);
  padding-right: 8px;
}

.passo span {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 1.5px solid rgba(255, 255, 255, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11.5px;
}

.passo.ativo { color: #fff; }
.passo.ativo span { background: #fff; color: var(--navy); border-color: #fff; }
.passo.concluido span { background: rgba(255, 255, 255, 0.3); color: #fff; }

.passo-painel { display: none; }
.passo-painel.ativo { display: block; }

.area-drop {
  border: 2px dashed #c7d3e6;
  border-radius: 12px;
  padding: 36px 20px;
  text-align: center;
  background: #fbfcfe;
}

.area-drop.sobre { border-color: var(--laranja); background: var(--laranja-fundo); }

.opcoes-import {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-width: 300px;
  margin: 0 auto;
  background: var(--laranja);
  border-radius: var(--raio);
  overflow: hidden;
  padding: 4px;
}

.opcao-import {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 14px 16px;
  background: transparent;
  color: #fff;
  border: none;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  border-radius: 7px;
  font-family: inherit;
}

.opcao-import:hover { background: rgba(255, 255, 255, 0.16); }

.area-drop-nota { margin: 18px 0 0; font-size: 13px; color: var(--texto-secundario); }
.area-drop-nota.ok { color: var(--verde); font-weight: 600; }

.dica-rodape {
  margin: 16px 0 0;
  padding: 12px 14px;
  background: var(--marfim);
  border-radius: 9px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--texto);
}

.secao-nota { margin: 0 0 16px; font-size: 13px; color: var(--texto-secundario); line-height: 1.6; }

/* Etiqueta de ação na revisão da importação (v1.63.0): "atualiza" um destino
   existente vs. "novo" cadastro. Segue a semântica de cor da §4 do
   design-system — azul/info é seleção-ação (rotina, a maioria das linhas do
   round-trip), amarelo é atenção (vai nascer um cadastro, e linha sem ID Neo
   é a única que duplica se o mesmo arquivo for importado duas vezes). */
.etiqueta-import {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.etiqueta-import.atualiza { background: var(--azul-claro); color: var(--azul-primario-hover); }
.etiqueta-import.novo { background: var(--amarelo-fundo); color: var(--amarelo-texto); }

/* Nível de acesso no card da tela Equipe (v1.64.0). Supervisor usa o laranja
   da marca porque é o nível que MANDA na operação — mesma cor dos botões de
   ação primária; operador fica no cinza neutro do fundo do painel, que lê
   como "padrão", não como alerta. Deliberadamente fora da semântica de
   estado da §4 do design-system (verde/amarelo/vermelho): nível não é
   status, e pintar um usuário de amarelo sugeriria problema. */
.etiqueta-nivel {
  display: inline-block;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.etiqueta-nivel.supervisor { background: var(--laranja-fundo); color: var(--laranja-hover); }
.etiqueta-nivel.operador { background: var(--fundo-painel); color: var(--texto-secundario); }

.card-item-nota { font-size: 11.5px; color: var(--texto-secundario); white-space: nowrap; }

.resumo-arquivo {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
  padding: 12px 14px;
  background: var(--fundo-painel);
  border-radius: 9px;
  font-size: 13px;
  margin-bottom: 18px;
}

.resumo-arquivo b { display: block; font-size: 11px; color: var(--texto-secundario); font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; }

.tabela-rolagem { overflow: auto; max-height: 260px; border: 1px solid var(--borda); border-radius: 9px; }
.tabela-rolagem.alta { max-height: 360px; }

.tabela-previa { border-collapse: collapse; font-size: 12.5px; width: 100%; }

.tabela-previa th,
.tabela-previa td {
  border-bottom: 1px solid var(--borda);
  border-right: 1px solid var(--borda);
  padding: 7px 10px;
  text-align: left;
  white-space: nowrap;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tabela-previa th {
  background: var(--fundo-painel);
  font-weight: 700;
  position: sticky;
  top: 0;
  z-index: 1;
}

.tabela-previa tr.linha-cabecalho td { background: var(--marfim); color: var(--texto); font-weight: 700; }

/* Log de acessos (Configurações, sessão 120) — bolinha de status dentro da
   `.tabela-previa` acima. Mesma ideia de `.vg-ponto-vivo` (Visão geral),
   mas com dois estados em vez de um só sempre-verde. */
.acesso-status-ponto {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 4px;
  vertical-align: middle;
}
.acesso-status-ponto.online { background: var(--verde); }
.acesso-status-ponto.offline { background: var(--texto-secundario); opacity: 0.45; }

/* MÉDIO-003: tabela de ranking em Entregas — mesma `.tabela-previa` da
   importação. Ganhou colunas de expediente na sessão 130 (Dias com rota,
   Horas ociosas, Horas extras) e passou de 6 pra 9 colunas — a rolagem
   horizontal própria virou rolagem OBRIGATÓRIA pro usuário mesmo em tela
   cheia (achado do usuário, sessão 130: "nao quero que scrolle"). Em vez de
   rolar, a tabela usa largura FIXA por coluna (`table-layout: fixed`) com
   o cabeçalho livre pra quebrar em 2 linhas (`white-space: normal`, ao
   contrário do `nowrap` padrão de `.tabela-previa`) — cada coluna cabe no
   espaço que tem, nunca empurra a próxima pra fora da tela. Motorista
   ganha a maior fatia (nome é o dado mais longo, ex.: "EDMILSON DA SILVA
   OLIVERA"); as 8 colunas de número/hora dividem o resto igualmente. */
.ent-ranking-tabela-wrap { overflow-x: visible; }
.ent-ranking-tabela-wrap .tabela-previa {
  table-layout: fixed;
  font-size: 11.5px;
}
.ent-ranking-tabela-wrap .tabela-previa th,
.ent-ranking-tabela-wrap .tabela-previa td {
  white-space: normal;
  overflow-wrap: break-word;
  max-width: none;
  padding: 6px 6px;
}
.ent-ranking-tabela-wrap .tabela-previa th:first-child,
.ent-ranking-tabela-wrap .tabela-previa td:first-child {
  width: 20%;
}

.grade-mapeamento { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
.grade-mapeamento .campo { margin-bottom: 0; }

.revisao-barra {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
  gap: 12px;
}

.marcar-todos { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; cursor: pointer; }
.revisao-contagem { font-size: 13px; color: var(--texto-secundario); }

/* Navegação no celular tem 2 modos (Configurações → "Menu no celular",
     preferência por DISPOSITIVO em localStorage["neo_nav_mobile"], não por
     conta — pedido do usuário: no Safari do iPhone a barra de endereço
     TAMBÉM fica embaixo e colide com o tab bar). Aplicado em
     `<html data-nav-mobile="tabbar|sidebar">` por um script inline no
     `<head>` de cada página, antes deste CSS carregar (evita flash trocando
     de layout depois do primeiro paint). Padrão "tabbar": as regras abaixo
     empilham o grid em 2 linhas e viram o rail numa barra horizontal
     embaixo. "sidebar": nenhuma regra `:not([data-nav-mobile="sidebar"])`
     abaixo se aplica — o app mantém o mesmo rail vertical do desktop
     (regras base, topo do arquivo), só mais estreito pela tela. */
@media (max-width: 900px) {
  html:not([data-nav-mobile="sidebar"]) .app,
  html:not([data-nav-mobile="sidebar"]) .app.sidebar-aberta,
  html:not([data-nav-mobile="sidebar"]) .app.rail-expandida,
  html:not([data-nav-mobile="sidebar"]) .app.rail-expandida.sidebar-aberta {
    grid-template-columns: 1fr;
    grid-template-rows: 1fr auto;
  }
  /* Sem isso a ordem do DOM (rail antes de area-principal) jogaria o rail
     pra linha 1 do grid — grid-row explícito garante o rail embaixo mesmo
     sem mexer no HTML. */
  html:not([data-nav-mobile="sidebar"]) .app > .rail { grid-row: 2; }
  html:not([data-nav-mobile="sidebar"]) .app > .area-principal { grid-row: 1; }
  /* Cadastro/Configurações/Relatórios usam .pagina-config (não
     .area-principal) como conteúdo, com height:100vh fixo pro scroll
     interno próprio (regra base, linha ~867) — em 100vh ignoraria a linha
     1fr do grid e ficaria por baixo do tab bar. Troca pra 100% da área do
     grid (viewport menos o tab bar) só no modo tab bar; "sidebar" mantém o
     height:100vh da regra base, igual ao desktop. */
  html:not([data-nav-mobile="sidebar"]) .app > .pagina-config {
    grid-row: 1;
    height: 100%;
    min-height: 0;
  }
  .painel.painel-aberta {
    position: fixed;
    inset: 0;
    z-index: 2000;
    width: auto;
  }
  .grade-mapeamento { grid-template-columns: 1fr; }

  /* Rail vira tab bar inferior no mobile — navegação horizontal com rótulo
     sempre visível (padrão nativo de app), em vez do rail vertical estreito
     replicado do desktop espremido em 68px. Expandir/recolher
     (#btn-expandir-rail) só faz sentido no rail vertical, some aqui. Só no
     modo "tabbar" (padrão) — ver comentário no topo desta media query;
     modo "sidebar" deixa o rail intocado (regras base do topo do arquivo). */
  /* TASK-125 (UX-071): sem `flex-wrap` e com `overflow:hidden` (herdado da
     regra base do `.rail`), quando a soma das larguras mínimas dos itens
     passa da viewport o excedente simplesmente saía da tela — em 360px,
     "Configurações" e "Sair" (os últimos itens) ficavam com 0px visíveis e
     INALCANÇÁVEIS, sem plano B nenhum de logout no celular (`#btn-perfil`
     é o único caminho de sair da conta). `overflow-x:auto` deixa o
     excedente rolável em vez de cortado — não resolve a descoberta (nada
     avisa que há mais itens à direita), mas resolve o alcance, que é o
     P1. `scrollbar-width:none`/`::-webkit-scrollbar{display:none}`
     escondem a barra (nativo de tab bar, o `scroll-snap-type:x
     proximity` já dá o feedback tátil de "parei num item"). */
  html:not([data-nav-mobile="sidebar"]) .rail,
  html:not([data-nav-mobile="sidebar"]) .rail.expandida {
    flex-direction: row;
    align-items: stretch;
    justify-content: space-evenly;
    width: 100%;
    height: auto;
    padding: 4px 2px calc(4px + env(safe-area-inset-bottom, 0px));
    gap: 0;
    box-shadow: 0 -2px 10px rgba(15, 32, 62, 0.2);
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
  }
  html:not([data-nav-mobile="sidebar"]) .rail::-webkit-scrollbar { display: none; }

  /* `.rail-secao` some junto com o botão de expandir: na tab bar horizontal
     um rótulo de grupo viraria mais um item flex roubando espaço dos ícones
     — e como `#btn-expandir-rail` está escondido aqui, quem tivesse
     `neo_rail_expandida=1` salvo não teria como desfazer (BUG-022).
     `#btn-perfil` (Sair) idem, desde a sessão 127 — mora na folha "Mais"
     agora (`#btn-perfil-mais`, mesmo clique via `.rail-logo` em main.js);
     sem escondê-lo aqui ele continuaria como um 6º item na tab bar, do
     lado do botão que já leva pra ele. */
  html:not([data-nav-mobile="sidebar"]) #btn-expandir-rail,
  html:not([data-nav-mobile="sidebar"]) #btn-perfil,
  html:not([data-nav-mobile="sidebar"]) .rail-secao,
  html:not([data-nav-mobile="sidebar"]) .rail.expandida .rail-secao,
  html:not([data-nav-mobile="sidebar"]) .rail-spacer {
    display: none;
  }

  html:not([data-nav-mobile="sidebar"]) .rail-icon,
  html:not([data-nav-mobile="sidebar"]) .rail.expandida .rail-icon,
  html:not([data-nav-mobile="sidebar"]) .rail-logo,
  html:not([data-nav-mobile="sidebar"]) .rail.expandida .rail-logo {
    flex: 1 1 0;
    flex-shrink: 0; /* TASK-125 — não encolher, rolar (ver .rail acima) */
    max-width: 96px; /* 88px cortava "Controle de Rotas" em "Controle de Ro…" — faltavam ~2px pro rótulo */
    flex-direction: column;
    width: auto;
    height: auto;
    min-height: 48px;
    padding: 6px 2px;
    border-radius: var(--raio);
    gap: 2px;
    margin-top: 0;
    background: transparent;
    scroll-snap-align: start;
  }

  html:not([data-nav-mobile="sidebar"]) .rail-icon.ativo { background: var(--azul-rail-ativo); }

  /* Contador ancorado no canto do item da tab bar — o posicionamento do
     rail vertical (translate fixo) não serve aqui, porque o item virou
     coluna (ícone + rótulo) e tem largura variável. */
  html:not([data-nav-mobile="sidebar"]) .rail-icon { position: relative; }
  html:not([data-nav-mobile="sidebar"]) .rail-contador,
  html:not([data-nav-mobile="sidebar"]) .rail.expandida .rail-contador {
    position: absolute;
    top: 2px;
    right: 50%;
    transform: translateX(22px);
    margin-left: 0;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    background: var(--azul-rail-ativo);
    font-size: 9.5px;
  }

  html:not([data-nav-mobile="sidebar"]) .rail-icon .ico,
  html:not([data-nav-mobile="sidebar"]) .rail-logo .ico { width: 22px; height: 22px; }

  html:not([data-nav-mobile="sidebar"]) .rail-label,
  html:not([data-nav-mobile="sidebar"]) .rail.expandida .rail-label {
    display: block;
    font-size: 10px;
    line-height: 1.1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
  }
}

/* ---------- "Mais" e atribuição rápida (sessão 127, mobile) ---------- */
/* Pedido do usuário: "a navegação mobile... os botões são de difícil
   acesso, o kanban é confuso pra navegar, não dá pra ver o versionamento".
   Três correções na mesma leva — ver a nota do botão "Mais" em painel.html:
   1. a tab bar tinha 10 itens rolando sem nenhum indício de que havia mais
      (TASK-125/UX-071 já registrava isso como resolvido só pela metade:
      "não resolve a descoberta, resolve o alcance"). Reduzida a 4 +
      "Mais", que abre a folha abaixo com o resto.
   2. `.topbar-versao` continua escondida ≤600px (decisão de espaço que
      segue válida — cabeçalho de celular é apertado), mas agora mora
      também dentro da folha "Mais", sempre alcançável.
   3. "Sair" era o ÚLTIMO item da tab bar, atrás de 9 outros — mudou pra
      dentro da folha, primeiro item alcançável sem rolar em telas
      normais. */
.rail-icon-mais { display: none; }

@media (max-width: 900px) {
  html:not([data-nav-mobile="sidebar"]) .rail-icon-secundario { display: none; }
  html:not([data-nav-mobile="sidebar"]) .rail-icon-mais { display: flex; }
}

.modal-mais { width: min(360px, calc(100vw - 32px)); }
.mais-lista { display: flex; flex-direction: column; gap: 4px; padding: 4px 0; }
/* `.rail-icon` de propósito (reaproveita ícone+padding+hover já definidos
   pro rail) — só o LAYOUT muda pra linha horizontal cheia, alvo de toque
   generoso (a régua `--alvo-toque` já usada no resto do mobile). */
/* `#modal-mais .mais-item`, não só `.mais-item.rail-icon`: a regra mobile
   de `.rail-icon` (linha ~4570, `flex-direction: column`, ícone empilhado
   sobre o rótulo — o formato da TAB BAR) tem a mesma especificidade e vem
   DEPOIS no arquivo, então vencia a de baixo e empilhava o ícone aqui
   também, onde o formato certo é linha (lista vertical de itens, não
   grade de ícones). Prefixar com o id do modal é a forma mais simples de
   garantir que a folha "Mais" nunca herda a densidade da tab bar por
   acidente, sem precisar duplicar `html:not([data-nav-mobile="sidebar"])`
   nem brigar com a ORDEM das regras no arquivo. */
#modal-mais .mais-item {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
  width: 100%;
  /* `max-width: none` pelo MESMO motivo do `flex-direction: row` acima, e
     esquecido quando ele foi escrito: a regra da tab bar limita `.rail-icon`
     a 96px (lá são ~5 ícones dividindo a largura da tela) e isso vazava pra
     cá, onde cada item ocupa uma linha inteira. Passou despercebido porque
     rótulo de UMA palavra não tem onde quebrar — "Jornada", "Cadastro",
     "Configurações" transbordavam os 96px e pareciam certos. Só "Lançamento
     manual" e "Painel de parede" quebravam, e viraram duas e três linhas
     empilhadas (achado ao validar as seções novas, sessão 139). */
  max-width: none;
  min-height: var(--alvo-toque);
  padding: 11px 14px;
  border-radius: 10px;
  color: var(--texto);
  text-decoration: none;
}
/* Rótulo de seção da folha "Mais" — mesmas três seções do rail (sessão
   139). Fundo claro aqui, ao contrário do `.rail-secao`, que vive sobre o
   navy do rail: o modal tem fundo de app, então a cor tem de vir de
   `--texto-secundario` e não do azul claro do rail, senão o rótulo quase
   some. O primeiro não leva o respiro de cima (já está colado no cabeçalho
   do modal). */
#modal-mais .mais-secao {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--texto-secundario);
  padding: 14px 14px 4px;
}
#modal-mais .mais-secao:first-child { padding-top: 4px; }
#modal-mais .mais-item:hover { background: var(--azul-claro); color: var(--texto); }
#modal-mais .mais-item .ico { width: 20px; height: 20px; flex-shrink: 0; }
#modal-mais .mais-item span { font-size: 14.5px; font-weight: 600; line-height: 1.3; }
/* `#modal-mais` de novo aqui: `.mais-sair` sozinho (especificidade de 1
   classe) perderia a cor pra `#modal-mais .mais-item` (id + classe, mais
   específico) mesmo vindo depois no arquivo — especificidade maior sempre
   vence, não importa a ordem. */
#modal-mais .mais-versao {
  margin-top: 6px;
  border-top: 1px solid var(--borda);
  border-radius: 0;
  padding-top: 16px;
  color: var(--texto-secundario);
}
#modal-mais .mais-versao strong { color: var(--texto); }
#modal-mais .mais-sair { color: var(--vermelho); }
#modal-mais .mais-sair:hover { background: #fef2f2; color: var(--vermelho); }

/* Atribuição rápida (kanban.js::abrirAtribuicaoRapida) — lista de destinos
   como botões grandes, um por linha, sem select e sem "Salvar" pra rolar
   até. */
.modal-atribuir-rapido { width: min(420px, calc(100vw - 32px)); }
.atr-lista { display: flex; flex-direction: column; gap: 6px; }
.atr-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  width: 100%;
  min-height: 52px;
  padding: 12px 14px;
  border: 1px solid var(--borda);
  border-radius: 10px;
  background: var(--fundo-app);
  font-family: inherit;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--texto);
  text-align: left;
  cursor: pointer;
}
.atr-item:hover, .atr-item:active { background: var(--azul-claro); border-color: var(--azul-primario); }
.atr-item:disabled { opacity: 0.5; cursor: default; }
.atr-item .ico { width: 19px; height: 19px; flex-shrink: 0; color: var(--texto-secundario); margin-top: 2px; }
/* Nome e aviso empilhados (não lado a lado): num diálogo de 420px, o selo
   de aviso ("falta escolher o motorista deste veículo") lado a lado com o
   nome espremia o nome pra 1-2 caracteres visíveis antes do ellipsis. */
.atr-item-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.atr-item-nome { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.atr-item-aviso {
  align-self: flex-start;
  font-size: 11px;
  font-weight: 700;
  color: var(--vermelho);
  background: #fef2f2;
  padding: 3px 8px;
  border-radius: 999px;
  white-space: normal;
}
.atr-item-alerta { border-color: var(--vermelho); }
.atr-editar-completo {
  display: block;
  width: 100%;
  margin-top: 12px;
  padding: 10px;
  border: none;
  background: transparent;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--laranja);
  text-align: center;
  cursor: pointer;
}
.atr-editar-completo:hover { text-decoration: underline; }

.relatorio-filtros-spacer { flex: 1; }

/* A folha de impressão da tela Entregas é um documento PRÓPRIO
   (`#ent-impressao`, montado por `main.js::montarFolhaImpressao`), não a
   tela impressa. Só existe no papel. */
#ent-impressao, #dash-impressao { display: none; }

/* Impressão. Duas partes, e a diferença entre elas é a lição da sessão 141:

   1. As páginas do rail compartilhado (Relatórios/Cadastro/Configurações,
      ver js/rail.js) seguem imprimindo a PRÓPRIA tela — ali funciona
      porque o shell é raso (`.pagina-config` com um scroll só).
   2. A tela Entregas passou a imprimir um documento separado. Imprimir o
      shell do painel exigia neutralizar, uma a uma, as regras de altura e
      scroll de CADA ancestral (`.app` grid 100vh → `.area-principal` flex
      overflow:hidden → `#vista-entregas` overflow-y:auto). Bastou uma
      dessas nascer DEPOIS deste bloco pra folha sair em branco — foi o que
      aconteceu: `#vista-entregas { overflow-y: auto }` (o redesign
      editorial) não estava previsto aqui, e o gestor só descobriu ao
      imprimir. Esconder `.app` inteiro e mostrar um bloco próprio tira
      essa classe de defeito do caminho: nenhuma regra de layout futura do
      painel pode voltar a esvaziar a folha. */
@media print {
  .rail, .pagina-config-topo, .relatorio-filtros, #btn-imprimir, #btn-exportar-xlsx { display: none !important; }
  .app { display: block; height: auto; }
  .app > .pagina-config { height: auto; overflow: visible; }

  /* A troca é comandada por uma classe que `montarFolhaImpressao` põe no
     body e o `afterprint` tira — não por um seletor que tenta adivinhar o
     estado da tela. Assim as OUTRAS telas do painel seguem imprimindo como
     antes, e um Ctrl+P disparado pelo teclado (sem passar pelo botão) não
     encontra uma folha vazia no lugar do conteúdo. */
  body.imprimindo-entregas .app { display: none !important; }
  body.imprimindo-entregas #ent-impressao { display: block !important; }

  /* Detalhe por motorista (sessão 148): mesma mecânica, e por um motivo a
     mais — a tabela vive num `<dialog>`, e mandar imprimir com ele aberto
     leva o backdrop e a tela atrás pra folha. */
  body.imprimindo-detalhe .app { display: none !important; }
  body.imprimindo-detalhe #modal-dash-detalhe { display: none !important; }
  body.imprimindo-detalhe #dash-impressao { display: block !important; }

  @page { margin: 12mm; }
  body { background: #fff; }

  .imp-topo { margin-bottom: 14px; border-bottom: 2px solid #111; padding-bottom: 8px; }
  .imp-topo h1 { margin: 0 0 4px; font-size: 16pt; }
  .imp-periodo { margin: 0; font-size: 10pt; font-weight: 600; }
  .imp-totais { margin: 2px 0 0; font-size: 9pt; color: #444; }

  /* Faixa de resumo executivo (sessão 152, pedido do usuário: "pense que
     essa impressao pdf quero que seja um relatorio para entregar para os
     diretores") — o número de 5 segundos ANTES da tabela linha a linha,
     pra quem não opera o sistema não precisar somar coluna pra entender
     "como foi o período". */
  .imp-resumo-grid { display: flex; flex-wrap: wrap; gap: 18px; margin-bottom: 16px; padding: 10px 0; border-bottom: 1px solid #ccc; }
  .imp-resumo-item { min-width: 90px; }
  .imp-resumo-item span { display: block; font-size: 7pt; text-transform: uppercase; letter-spacing: 0.03em; color: #666; margin-bottom: 2px; }
  .imp-resumo-item strong { display: block; font-size: 13pt; }

  .imp-tabela { width: 100%; border-collapse: collapse; margin-bottom: 14px; font-size: 8pt; }
  .imp-tabela caption { text-align: left; font-size: 11pt; font-weight: 700; padding-bottom: 5px; }
  .imp-tabela th, .imp-tabela td { border: 1px solid #999; padding: 3px 5px; text-align: left; vertical-align: top; }
  .imp-tabela thead th { background: #eee; font-size: 7.5pt; text-transform: uppercase; letter-spacing: 0.02em; }
  .imp-tabela .num { text-align: right; white-space: nowrap; }
  /* Repete o cabeçalho quando a tabela atravessa a quebra de página —
     tabela longa sem isso vira colunas sem nome da segunda folha em diante. */
  .imp-tabela thead { display: table-header-group; }
  .imp-tabela tr { break-inside: avoid; }
  /* Destaca quem está bem acima da média do PRÓPRIO grupo impresso (ver
     `montarFolhaImpressao`) — o sinal que interessa a quem só lê o
     relatório, não opera a tela: "quem precisa de atenção", não o número
     cru de cada um. */
  .imp-tabela .imp-atencao { font-weight: 700; color: #92400e; }
  .imp-rodape { margin-top: 4px; font-size: 7.5pt; color: #666; }

  /* A viagem e a tabela dela não se separam: o bloco quebrado ao meio deixa
     um cabeçalho órfão no pé de uma folha e as paradas na seguinte. */
  .imp-viagem { break-inside: avoid; margin-bottom: 12px; }
  .imp-viagem h2 { margin: 0 0 3px; font-size: 10.5pt; border-bottom: 1px solid #111; padding-bottom: 2px; }
  .imp-viagem-resumo { margin: 0 0 5px; font-size: 8.5pt; color: #333; }
  .imp-vazio { font-size: 9pt; color: #555; }
}

/* Histórico de odômetro no modal de editar veículo (TASK-028) — lista das
   últimas leituras com botão de remover, pra corrigir um erro de digitação
   sem precisar de SQL direto no banco. */
.bloco-odometro { margin-top: 8px; padding-top: 16px; border-top: 1px solid var(--borda); }
.bloco-odometro h4 { margin: 0 0 10px; font-size: 14px; }
.odometro-item-texto strong { display: block; font-size: 13px; }
.odometro-item-texto span { display: block; font-size: 12px; color: var(--texto-secundario); }

/* Toast — feedback de "salvo com sucesso" (ver Toast em js/util.js). Fixo no
   canto, some sozinho. Só existe o estado de sucesso e de erro por enquanto;
   novos usos podem adicionar outra variação .toast-<tipo>. */
.toast {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 3000;
  padding: 12px 18px;
  border-radius: var(--raio);
  box-shadow: var(--sombra-alta);
  font-size: 14px;
  font-weight: 600;
  color: #fff;
  background: var(--texto);
  opacity: 0;
  transform: translateY(12px);
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.toast-visivel { opacity: 1; transform: translateY(0); }
.toast-sucesso { background: var(--verde); }
.toast-erro { background: var(--vermelho); }

@media (max-width: 900px) {
  .toast { left: 16px; right: 16px; bottom: 16px; text-align: center; }
}

/* Selo de "modo piloto ligado" no topo de Configurações. É uma configuração
   perigosa de esquecer ativa (a operação para de receber aviso e ninguém
   percebe), então precisa ser visível fora do bloco que a controla. */
.selo-modo-piloto {
  margin: 0 0 16px;
  padding: 10px 14px;
  border-radius: var(--raio);
  background: var(--laranja-fundo);
  border: 1px solid var(--laranja);
  color: var(--texto);
  font-size: 13.5px;
  font-weight: 600;
}

.bloco-config-nota-alerta {
  color: var(--laranja-hover);
  font-weight: 600;
}

/* Modal de editar parada do quadro (kanban.js::abrirEdicaoParada). */
.mep-grade {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 12px;
  margin-bottom: 12px;
}

.mep-campo {
  display: block;
  margin-bottom: 12px;
}

.mep-campo > span {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--texto-secundario);
  margin-bottom: 4px;
}

.mep-campo input,
.mep-campo select,
.mep-campo textarea {
  width: 100%;
  font-family: inherit;
  font-size: 14px;
}

.mep-grade .mep-campo { margin-bottom: 0; }

/* ROT-002: prévia da sequência sugerida (js/kanban.js::abrirPreviaOrdem). */
.mpo-lista {
  margin: 0;
  padding-left: 22px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 320px;
  overflow-y: auto;
}
.mpo-lista li { font-size: 13.5px; padding: 2px 0; }
.mpo-lista li.mpo-sem-coord { color: var(--texto-secundario); font-style: italic; }

/* ═══════════════════════════════════════════════════════════════════
   Configurações — coluna única centralizada (sessão 42)

   O problema: `.pagina-config-corpo` travava em 940px com `margin: 0`, ou
   seja, ancorado à ESQUERDA. Num monitor de 1730px sobravam ~560px mortos à
   direita, e a grade de 2 colunas espalhava cards pequenos por essa faixa —
   nada liderava a leitura, tudo tinha o mesmo peso.

   A decisão (do usuário): assumir a largura menor como proposital. Cada
   seção da barra lateral é uma página focada, centralizada, com medida de
   leitura confortável (~65ch) e campos maiores. O vazio vira margem, não
   sobra.

   Junto disso, os "cards" deixam de ser caixas: aqui um ajuste é
   cabeçalho + explicação + controle, separados por ritmo e um filete, não
   por borda+sombra+fundo em cima de outro card (a lista de empresas e a de
   usuários são `.card-item` DENTRO de `.pagina-config-card` — card
   aninhado).

   Tudo escopado em `.config-focada` porque `pagina-config-*`/`bloco-config`
   também servem o cadastro.html, fora do escopo deste pedido.
   ═══════════════════════════════════════════════════════════════════ */

.config-focada .pagina-config-corpo {
  max-width: 680px;      /* ~65ch no corpo de 15px */
  margin-inline: auto;
  padding: 40px 24px 96px;
  gap: 0;                /* o ritmo passa a vir das seções, não do gap */
}

/* Seção deixa de ser card: sem fundo, sem borda, sem sombra. O que separa
   é espaço + um filete — e o filete some na última, pra não fechar a
   página com uma linha solta. */
.config-focada .pagina-config-card {
  background: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  padding: 0;
  border-bottom: 1px solid var(--linha-editorial);
  padding-block: 32px;
}
.config-focada .pagina-config-card:last-child { border-bottom: none; }
.config-focada .pagina-config-card-compacta { padding: 0; padding-block: 32px; }

/* Uma seção por vez: as grades viram pilha. */
.config-focada .config-grade-2col,
.config-focada .config-grade-utilitarios {
  display: block;
}

.config-focada .bloco-config {
  display: block;
  padding: 0;
  border-bottom: none;
}

/* Mais espaço ACIMA do título que abaixo — o título pertence ao que vem
   depois dele, não ao que veio antes. */
.config-focada .pagina-config-card h4 {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 6px;
  font-size: 16px;
  letter-spacing: -0.01em;
  color: var(--texto);
}
.config-focada .pagina-config-card h4 .ico { color: var(--laranja); }

/* `.bloco-config-texto p` sem classe: os blocos "compactos" (interruptores)
   escrevem a explicação num <p> cru, diferente das seções maiores que usam
   `.bloco-config-nota`. Os dois são a mesma coisa na tela. */
.config-focada .bloco-config-nota,
.config-focada .bloco-config-texto > p {
  margin: 0 0 18px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--texto-secundario);
  max-width: 60ch;
}

/* O bloco compacto empilhava por flex com `height: 100%` (fazia sentido
   quando era um card numa grade de alturas iguais). Em coluna única isso
   não tem função. */
.config-focada .pagina-config-card-compacta .bloco-config {
  height: auto;
  gap: 0;
}

/* Campos maiores, largura inteira: o pedido era "campos maiores", e numa
   coluna de 680px um input de 110px não tem por que existir. */
.config-focada .form-empresa {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 10px;
  align-items: stretch;
}
.config-focada .form-empresa input,
.config-focada .form-empresa select {
  width: 100%;
  min-width: 0;
  padding: 11px 13px;
  font-size: 14.5px;
  border-radius: 9px;
}
.config-focada .form-empresa button { grid-column: 1 / -1; justify-self: start; }

/* Caixa de permissão e nota de ajuda ocupam a linha inteira, igual ao botão.
   Sem isso caem numa célula de ~190px e o rótulo longo ("Pode gerenciar
   Cadastro (destinos, motoristas e veículos)") quebra palavra por palavra
   numa coluna altíssima — apareceu na tela Equipe (v1.64.0). */
.config-focada .form-empresa .campo-checkbox,
.config-focada .form-empresa .bloco-config-nota { grid-column: 1 / -1; }

/* A regra de campo acima (`.config-focada .form-empresa input`) é mais
   específica que a global `.campo-checkbox input { width: auto }`, então a
   CAIXA de marcar também esticava pra 100% e jogava o rótulo pra fora da
   borda. Precisa dos 3 níveis de classe pra vencer. */
.config-focada .form-empresa .campo-checkbox input {
  width: auto;
  flex: none;
}

.config-focada .bloco-config select,
.config-focada .bloco-config input[type="text"],
.config-focada .bloco-config input[type="number"],
.config-focada .bloco-config input[type="time"],
.config-focada .bloco-config textarea {
  width: 100%;
  padding: 11px 13px;
  font-size: 14.5px;
  border-radius: 9px;
}

/* Interruptor: alvo de clique da linha inteira, não só do quadradinho. */
.config-focada .campo-checkbox {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  margin: 0 0 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-size: 14px;
  cursor: pointer;
}
.config-focada .campo-checkbox:hover { border-color: var(--laranja); }
.config-focada .campo-checkbox input { flex: none; margin: 0; }

.config-focada .lista-empresas,
.config-focada .lista-mensagens-rapidas,
.config-focada #lista-usuarios { margin-bottom: 14px; }

.config-focada .whatsapp-template { margin-bottom: 18px; }

/* Bloco perigoso (limpar quadro / apagar histórico): o único lugar da tela
   que ganha superfície própria — aqui a caixa não é decoração, é aviso de
   que a ação não tem volta. */
.config-focada .bloco-config-perigo {
  padding: 18px;
  border: 1px solid var(--vermelho);
  border-radius: 12px;
  background: #fef4f3;
}
.config-focada .bloco-config-perigo h4 .ico { color: var(--vermelho); }

@media (max-width: 860px) {
  .config-focada .pagina-config-corpo { padding: 24px 16px 72px; }
}

/* Categoria e marca sempre em CAIXA ALTA (pedido do usuário, sessão 96 —
   "mesmo digitando normal deve ficar HOSPITAL, UPA"). O `text-transform`
   sozinho é só pintura: quem garante o dado é o backend
   (`_normalizar_tags` / `normalizar_categoria_com`) e, no caso das tags, o
   próprio chip já entra maiúsculo (`util.js::SeletorTags`). Isto aqui
   existe pra que o campo não mostre uma coisa e grave outra ENQUANTO a
   pessoa digita — sem ele, o gestor digita "hospital", vê "hospital" e o
   sistema salva "HOSPITAL". */
.campo-caixa-alta,
.seletor-tags-campo input { text-transform: uppercase; }
.campo-caixa-alta::placeholder,
.seletor-tags-campo input::placeholder { text-transform: none; }

/* "Aguardando liberação" na coluna do quadro (sessão 96) — o gestor precisa
   saber POR QUE a rota está parada, senão o recurso só faz o alerta de
   atraso sumir e a demora vira mistério. Mesmo âmbar do aviso de atraso
   (`.kanban-coluna-atrasada`), porque é a mesma família de informação
   "atenção, não erro" — o que muda é a frase, não a gravidade. */
.kanban-coluna-aguardando {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--amarelo-texto);
  background: var(--amarelo-fundo);
  border-bottom: 1px solid var(--amarelo-borda);
}

/* Carro na garagem carregando pra sair de novo (sessão 104). AZUL, não
   âmbar: âmbar no quadro significa "algo está atrasando" (aguardando
   liberação, coluna carregada de outro dia, hora estourada), e recarga é
   trabalho acontecendo no plano — o carro vai voltar pra rua. Pintar de
   âmbar faria o gestor tratar como problema e escalar outro veículo, que é
   exatamente o que este aviso existe pra evitar. */
.kanban-coluna-recarga {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  color: #1d4ed8;
  background: var(--azul-claro);
  border-bottom: 1px solid #bfdbfe;
}

/* Veículo que não voltou à garagem na última viagem (sessão 140). ÂMBAR, ao
   contrário da recarga logo acima: aqui o carro NÃO está disponível como a
   coluna vazia sugere — quem escalar essa placa de manhã vai escalar um
   veículo que está na casa de alguém. É a mesma família de "atenção" do
   aguardando liberação, e o mesmo par de tokens. */
.kanban-coluna-pernoite {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--amarelo-texto);
  background: var(--amarelo-fundo);
  border-bottom: 1px solid var(--amarelo-borda);
}

/* Coluna de veículo planejada pra amanhã, mostrada hoje ao lado da coluna
   de hoje do mesmo carro (sessão 105). Translúcida de propósito — pedido
   do usuário ("ela ficar meio transparente mostrando que não é do dia
   atual") — pra não competir visualmente com a coluna que É de hoje, mas
   sem escondê-la (o gestor ainda precisa ler o conteúdo pra soltar carga
   nela). Mesmos tokens neutros de `.kanban-card-dia-futuro`: é agenda, não
   problema. */
.kanban-coluna-outro-dia { opacity: 0.72; }
.kanban-coluna-outro-dia:hover { opacity: 1; }
.kanban-coluna-futuro {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--texto-secundario);
  background: var(--fundo-painel);
  border-bottom: 1px solid var(--linha-editorial);
}

/* "Livre pra quem chegar" (sessão 105) — mesma linha visual dos selects de
   `.kanban-controles` (borda/fonte), mas como rótulo de checkbox, não
   select. Desabilitado (com motorista já escolhido) fica opaco igual aos
   demais controles desabilitados do quadro. */
.kanban-liberar-motorista {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px 8px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--texto);
  cursor: pointer;
}
.kanban-liberar-motorista.desabilitado { color: var(--texto-secundario); cursor: not-allowed; }
.kanban-liberar-motorista input { margin: 0; }
.kanban-liberar-motorista .ico { flex-shrink: 0; }

/* Prioridade e horário no card do quadro (sessão 96). O gestor varre a Fila
   de transporte de cima a baixo decidindo o que despachar primeiro — o que
   decide isso precisa saltar, não estar diluído na linha de "·" junto de
   volumes e nota fiscal, que era onde o horário morava. */
.kanban-card-marcadores { display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 0 1px; }

.kanban-card-prioridade,
.kanban-card-prioridade-baixa,
.kanban-card-dia-atrasado,
.kanban-card-dia-futuro,
.kanban-card-hora {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.kanban-card-prioridade {
  color: var(--vermelho-texto, #991b1b);
  background: var(--vermelho-fundo, #fee2e2);
}
/* Cinza neutro de propósito (sessão 102, pedido do usuário: "uma cor que
   não remete a urgência") — é o oposto semântico do badge de prioridade
   máxima acima, então não pode competir visualmente com ele nem com o
   âmbar de horário/atraso. Mesmos tokens neutros de `--texto-secundario`/
   `--fundo-painel` que o resto do quadro já usa pra "informativo, sem
   urgência" (ex.: rótulo "sem motorista definido"). */
.kanban-card-prioridade-baixa {
  color: var(--texto-secundario);
  background: var(--fundo-painel);
}
/* Âmbar, não vermelho: ter hora marcada é um compromisso, não um problema —
   o vermelho fica reservado pra prioridade e pra parada já atrasada, senão
   a coluna inteira vira alerta e nada mais chama atenção. */
.kanban-card-hora {
  color: var(--amarelo-texto);
  background: var(--amarelo-fundo);
}
/* Etiquetas de DIA na Fila de transporte (sessão 104), com pesos visuais
   opostos de propósito:
   — "Desde 03/09" é dívida: o pedido atravessou o dia sem dono. Âmbar, o
     mesmo peso de "tem compromisso marcado", nunca o vermelho de
     prioridade (que é decisão do gestor, não consequência do tempo).
   — "Para sáb 06/09" é agenda, não problema: cinza neutro, mesmos tokens
     de `.kanban-card-prioridade-baixa`. Pintar o planejamento de urgência
     é exatamente o que faria o gestor parar de confiar nas cores da
     coluna. */
.kanban-card-dia-atrasado {
  color: var(--amarelo-texto);
  background: var(--amarelo-fundo);
}
.kanban-card-dia-futuro {
  color: var(--texto-secundario);
  background: var(--fundo-painel);
}

/* Borda esquerda marca o card prioritário na varredura vertical, sem
   depender de ler o badge. */
.kanban-card.prioritaria { border-left: 3px solid var(--vermelho, #dc2626); }

/* Ações de adm no detalhe da viagem (sessão 104): corrigir KM e estornar.
   Discretas de propósito e no RODAPÉ do card — são a exceção do dia, não o
   que o adm veio fazer aqui; com peso de botão primário virariam convite a
   desfazer viagem por engano. O de estornar é o único vermelho, porque é o
   que reabre o dia de um carro. */
.ent-viagem-card-adm {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--borda);
}
/* Log de alterações (sessão 141) — a tela própria e o bloco dentro do
   detalhamento da viagem. Os dois mostram o MESMO registro, então usam o
   mesmo vocabulário visual: nome em negrito, nível numa etiqueta, quando à
   direita, o que mudou embaixo. */
.alt-lista { display: flex; flex-direction: column; gap: 8px; }

.alt-item {
  padding: 12px 14px;
  border: 1px solid var(--linha-editorial);
  border-radius: var(--raio);
  background: var(--fundo-app);
}
.alt-item-topo { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.alt-item-topo strong { font-size: 14px; }

/* A etiqueta de NÍVEL é o ponto da tela: "deixando bem explícito que foi
   feito por esse nível de acesso". Âmbar, não cinza — é informação de
   atenção (alguém com acesso limitado mexeu), não metadado decorativo. */
.alt-nivel {
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--amarelo-fundo);
  border: 1px solid var(--amarelo-borda);
  color: var(--amarelo-texto);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.alt-quando { margin-left: auto; font-size: 12px; color: var(--texto-secundario); }
.alt-acao { margin: 6px 0 0; font-size: 13px; font-weight: 600; }
.alt-descricao { margin: 2px 0 0; font-size: 13px; color: var(--texto-secundario); }
/* Afago pro card clicável (sessão 150) — mesmo padrão de "quem clica sabe
   que tem mais" que a v1.143.0 já usa nos cartões e células do Dashboard. */
.alt-ver-viagem {
  margin: 8px 0 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--vg-orange);
}

/* Aviso ANTES do clique, no bloco de ações da viagem: quem não é adm precisa
   saber que a ação vai para o log e para o grupo — descobrir isso depois de
   feita é surpresa ruim. */
.ent-viagem-aviso-log {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  margin: 0 0 4px;
  font-size: 12px;
  color: var(--amarelo-texto);
}

.ent-viagem-alteracoes { margin-top: 12px; }
.ent-viagem-alteracoes > span {
  display: block;
  margin-bottom: 6px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--texto-secundario);
}
.ent-alteracoes-lista { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.ent-alteracoes-lista li {
  padding: 8px 10px;
  border-left: 3px solid var(--amarelo-borda);
  background: var(--fundo-painel);
  border-radius: 0 var(--raio) var(--raio) 0;
  font-size: 12.5px;
}
.ent-alteracao-nivel { color: var(--amarelo-texto); font-weight: 700; }
.ent-alteracao-quando { color: var(--texto-secundario); }
.ent-alteracao-detalhe { display: block; color: var(--texto-secundario); }

/* Pernoite fora da garagem (sessão 140) — mora na mesma fileira dos botões
   de adm da viagem, mas é um seletor: a resposta tem três estados e precisa
   mostrar qual está valendo. `min-height` igual ao `.botao-sutil` vizinho
   pra não desalinhar a fileira; sem largura fixa, porque "Ficou na casa do
   motorista" é o rótulo mais longo e cortá-lo esconderia a diferença entre
   as duas opções de pernoite. */
.ent-viagem-pernoite {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--texto-secundario);
}
.ent-viagem-pernoite select {
  min-height: 36px;
  padding: 6px 10px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--fundo-app);
  color: var(--texto);
  font-size: 12px;
}
.botao-sutil {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 36px;
  padding: 6px 12px;
  border: 1px solid var(--borda);
  border-radius: 8px;
  background: var(--fundo-app);
  color: var(--texto-secundario);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.botao-sutil:hover { background: var(--fundo-painel); }
.botao-sutil:disabled { opacity: 0.5; cursor: default; }
.botao-sutil-perigo { color: #991b1b; border-color: #fecaca; }
.botao-sutil-perigo:hover { background: #fee2e2; }

/* ---- Fila de transporte: blocos por dia + chips de foco (sessão 104) ----
   A Fila junta o que ficou de trás, o de hoje e o que já está marcado pros
   próximos dias. Numa lista corrida de 30+ cards o gestor não consegue
   responder "quanto é de hoje?" sem contar card a card — que é justamente a
   pergunta que ele faz pra dividir entre os carros do dia. */
.fila-grupo {
  position: sticky;   /* o rótulo do bloco acompanha a rolagem: com 20 cards
                         abertos, sem isto o gestor perde a referência de
                         qual dia está lendo no meio do caminho */
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  margin: 10px 0 6px;
  padding: 5px 8px;
  border: 0;
  border-radius: 8px;
  background: var(--fundo-painel);
  color: var(--texto-secundario);
  font: inherit;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  cursor: pointer;
}
.fila-grupo:first-child { margin-top: 0; }
.fila-grupo.atrasado { color: var(--amarelo-texto); background: var(--amarelo-fundo); }
/* Vermelho só aqui e no badge do card: é o bloco do que o gestor marcou à
   mão como "fura a fila". Se outro bloco ganhar vermelho, este deixa de
   significar alguma coisa. */
.fila-grupo.prioridade { color: #991b1b; background: #fee2e2; }
.fila-grupo-contador {
  margin-left: auto;
  padding: 0 6px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.07);
  font-size: 11px;
}
.fila-grupo-seta { transition: transform 0.15s ease; }
.fila-grupo.fechado .fila-grupo-seta { transform: rotate(-90deg); }


/* Tempos dos alertas em Configurações (sessão 96). Cada campo é um número
   pequeno com um rótulo em frase ("avisar depois de ___ e repetir a cada
   ___"): o rótulo à esquerda é o que diz o que o número significa, e sem
   ele quatro caixinhas numéricas em sequência seriam indistinguíveis. */
.alerta-campo {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1 1 100%;
  font-size: 14px;
}
.alerta-campo > span { flex: 1; }
.alerta-campo input { width: 90px; flex: none; }

@media (max-width: 600px) {
  .alerta-campo { flex-wrap: wrap; }
}

/* ---------- Dashboards (sessão 96) ----------
   Tela de leitura, não de operação: o gestor abre pra entender o período e
   levar números pra uma reunião. Por isso respira mais que o quadro (que é
   denso de propósito) e usa cartões grandes no topo — a pergunta "como foi o
   mês" se responde com meia dúzia de números antes de qualquer gráfico. */
.dash-cabecalho {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
}
.dash-titulo { margin: 0; font-size: 22px; }
.dash-subtitulo { margin: 4px 0 0; color: var(--texto-fraco, #64748b); font-size: 14px; }
.dash-filtros { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.dash-filtros label { display: flex; align-items: center; gap: 6px; font-size: 13px; }

.dash-cartoes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 10px;
  margin-bottom: 14px;
}
/* Padding e fonte menores que o cartão padrão do projeto (sessão 148): são
   OITO numa faixa só, acima de todos os gráficos, então cada 4px de altura
   aqui é 4px a menos pra segunda fileira de painéis. */
.dash-cartao {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 14px;
  border: 1px solid var(--borda, #e2e8f0);
  border-radius: 12px;
  background: #fff;
}
.dash-cartao-rotulo { font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--texto-fraco, #64748b); }
.dash-cartao-valor { font-size: 24px; line-height: 1.1; }
.dash-cartao-nota { font-size: 11px; color: var(--texto-fraco, #64748b); }
/* Só a taxa de sucesso ganha cor — é a única métrica desta tela que tem
   "bom" e "ruim". Colorir km ou volumes sugeriria que existe um alvo, e não
   existe: mais km não é melhor nem pior sem contexto. */
.dash-cartao-bom .dash-cartao-valor { color: var(--verde, #16a34a); }
.dash-cartao-atencao .dash-cartao-valor { color: var(--amarelo); }
.dash-cartao-ruim .dash-cartao-valor { color: var(--vermelho); }

/* Teto de 3 colunas (sessão 148, relato do usuário: "a tela de dashboard fica
   incompleta, só dá pra ver tudo se eu tirar o zoom mas fica tudo muito
   pequeno").

   O `auto-fit` sozinho é uma armadilha em tela grande e em zoom out: quanto
   mais largura disponível, MAIS colunas ele cria, cada uma no mínimo do
   `minmax`. Tirar o zoom pra caber a página inteira aumentava a largura em
   px CSS, o grid respondia com 5-6 colunas e os gráficos encolhiam junto com
   a fonte — o oposto do que a pessoa queria ao tirar o zoom. Com o teto, a
   largura extra vira painel MAIOR, não painel a mais.

   360px → 400px no mínimo pelo mesmo relato: com 360 o nome do motorista
   ("ROGERIO DOS SANTOS OLIVEIRA") chegava cortado no eixo das barras
   horizontais. */
.dash-grade {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
  gap: 16px;
}
@media (min-width: 1280px) {
  .dash-grade { grid-template-columns: repeat(3, 1fr); }
}
.dash-painel {
  padding: 16px;
  border: 1px solid var(--borda, #e2e8f0);
  border-radius: 12px;
  background: #fff;
}
.dash-painel h3 { margin: 0 0 12px; font-size: 15px; }
/* Ressalva de recorte do painel (`CONT-017`) — some junto com o `h3` quando
   o conteúdo é escondido, porque descreve o gráfico, não a seção. */
.dash-painel-nota { margin: -8px 0 10px; font-size: 11px; color: var(--texto-fraco, #64748b); }
.dash-painel-topo .dash-painel-nota { margin: 0; flex-basis: 100%; }
.dash-painel-largo { grid-column: 1 / -1; }
/* Altura no container, não no canvas: o Chart.js redimensiona o canvas
   sozinho (`maintainAspectRatio: false`) e sem uma altura definida no pai ele
   cresce a cada redesenho.

   `clamp(mínimo, proporcional, máximo)` em vez do px fixo (sessão 148,
   relato do usuário: "a parte debaixo está pela metade de todo o dashboard,
   não está responsivo"). A tela era responsiva na LARGURA e cega pra ALTURA:
   260px de gráfico num monitor de 900px de altura empurra a segunda fileira
   toda pra fora, e o corte cai bem no meio dos painéis. Com `vh` os gráficos
   acompanham a janela — encolhem no notebook e crescem no monitor grande.

   Os limites existem pelos dois extremos: abaixo de ~190px uma barra
   horizontal com 5 motoristas fica ilegível, e acima do máximo o gráfico
   só ganha espaço em branco (a série não fica mais legível por isso). */
.dash-grafico { position: relative; height: clamp(190px, 24vh, 260px); }
.dash-painel-largo .dash-grafico { height: clamp(210px, 28vh, 300px); }

/* Desde a sessão 148 o painel sem dados SOME da grade (ver `desenhar` em
   js/dashboard.js) — este texto só aparece no painel marcado
   `data-manter-vazio`, que não pode sumir porque hospeda o atalho do
   Detalhe. Nele a regra antiga continua valendo: "sem dados no período" é
   uma resposta, um quadro em branco parece defeito. */
.dash-grafico-vazio::after {
  content: attr(data-vazio);
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--texto-fraco, #64748b);
  font-size: 13px;
}

/* Ganhou 2 colunas na sessão 130 (Horas ociosas/extras, pedido do usuário
   depois de ver o mesmo em Relatórios — "nao quero que scrolle") — mesma
   régua de `.ent-ranking-tabela-wrap` (style.css): largura fixa por coluna
   e cabeçalho livre pra quebrar em 2 linhas, nunca rolagem horizontal. */
/* Cabeçalho de painel com ação à direita (sessão 148): hoje só o painel de
   jornada por motorista usa, pra hospedar o atalho do Detalhe ao lado do
   título. `gap` + `flex-wrap` porque o título é longo e, num painel estreito,
   é melhor o botão cair pra linha de baixo do que espremer as duas coisas. */
.dash-painel-topo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}
.dash-painel-topo h3 { margin: 0; }
/* Botão de ação dentro de painel: menor que o padrão da tela, porque divide
   a linha com o título e não é a ação principal da página. */
.btn-pequeno { padding: 6px 10px; font-size: 12px; gap: 6px; }
/* Os filtros do modal não dividem espaço com mais nada (diferente da faixa
   do topo, que tem motorista + 3 botões), então ficam à esquerda e sem
   esticar. */
/* ── Modo apresentação (sessão 148) ─────────────────────────────────────
   "Tela cheia de um modo que possa ser visualizado em uma reunião ou tv".
   Duas camadas, e as duas são necessárias:

   1. `requestFullscreen()` tira a moldura do NAVEGADOR (abas, barra de
      endereço) — é o que faz caber numa TV sem parecer um site aberto.
   2. Esta classe tira a moldura do APP (rail e topbar). Sem ela, a tela
      cheia só esticaria o mesmo layout, com o menu lateral ocupando 200px
      de uma TV a 4 metros de distância, que ninguém vai clicar.

   A classe existe separada do fullscreen de propósito: se o navegador negar
   a tela cheia (iframe sem permissão, política do sistema), o modo
   apresentação ainda funciona — só com a barra do navegador por cima. */
body.dash-apresentacao .rail,
body.dash-apresentacao .topbar { display: none !important; }
body.dash-apresentacao .app { grid-template-columns: 1fr; }
body.dash-apresentacao .area-conteudo { padding: 16px 20px; }
/* Os gráficos crescem com a janela (ver o `clamp` de `.dash-grafico`), e em
   tela cheia a janela É a tela: numa TV 1080p o teto de 260px deixaria metade
   do espaço em branco, então em apresentação ele sobe junto. */
body.dash-apresentacao .dash-grafico { height: clamp(220px, 27vh, 420px); }
body.dash-apresentacao .dash-painel-largo .dash-grafico { height: clamp(240px, 30vh, 460px); }
/* Números maiores: a leitura é de longe, não a um palmo do monitor. */
body.dash-apresentacao .dash-cartao-valor { font-size: 32px; }
body.dash-apresentacao .dash-cartao-rotulo,
body.dash-apresentacao .dash-cartao-nota { font-size: 12px; }

/* "Tela cheia" some enquanto ESTÁ em tela cheia — os dois no mesmo canto se
   sobrepunham, e um botão que promete o estado atual não tem o que fazer. */
body.dash-apresentacao #dash-tela-cheia { display: none; }

.dash-sair-apresentacao { display: none; }
/* Canto INFERIOR direito, não o superior: em cima ficam os filtros (que
   continuam usáveis na apresentação) e o botão cobria o "90 dias". Embaixo
   não disputa espaço com nada e continua alcançável mesmo se a página rolar,
   porque é `fixed`. */
body.dash-apresentacao .dash-sair-apresentacao {
  display: inline-flex;
  position: fixed;
  bottom: 16px;
  right: 20px;
  z-index: 60;
  background: #fff;
  box-shadow: 0 2px 10px rgba(15, 23, 42, 0.18);
}

.dash-detalhe-filtros { justify-content: flex-start; margin-bottom: 16px; }
.dash-detalhe-acoes { display: flex; gap: 8px; margin-left: auto; }

/* Número clicável da tabela do Detalhe (sessão 148) — abre QUAIS são. É um
   `<button>` de verdade (teclado e leitor de tela de graça), pintado como
   link pra não virar uma fileira de botões dentro da tabela. */
.dash-celula-link {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--azul, #2f6fdb);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.dash-celula-link:hover { color: var(--laranja, #e2653c); }
.dash-celula-lista { margin: 0; padding: 0; list-style: none; }
.dash-celula-lista li {
  padding: 8px 0;
  border-bottom: 1px solid var(--borda, #e2e8f0);
  font-size: 13px;
}
.dash-celula-lista li:last-child { border-bottom: 0; }
.dash-celula-sub { display: block; font-size: 11.5px; color: var(--texto-fraco, #64748b); }

.dash-tabela-caixa { overflow-x: visible; }
.dash-tabela { width: 100%; border-collapse: collapse; font-size: 12px; table-layout: fixed; }
.dash-tabela th, .dash-tabela td { padding: 6px 6px; text-align: right; white-space: normal; overflow-wrap: break-word; }
.dash-tabela th:first-child, .dash-tabela td:first-child { text-align: left; width: 16%; }
.dash-tabela thead th { border-bottom: 1px solid var(--borda, #e2e8f0); color: var(--texto-fraco, #64748b); font-weight: 600; }
.dash-tabela tbody tr:nth-child(even) { background: #f8fafc; }
.dash-vazio { color: var(--texto-fraco, #64748b); text-align: center; padding: 24px; }

@media (max-width: 700px) {
  .dash-grade { grid-template-columns: 1fr; }
  .dash-grafico { height: 220px; }
}

/* ---------------------------------------------------------------------------
   Jornada do motorista (sessão 132) — a linha do tempo do dia, por motorista.

   Reaproveita a moldura da Visão geral (`.visao-geral`, `.vg-intro`,
   `.vg-cards`): é a mesma família de tela (leitura operacional do dia), e
   inventar um segundo cabeçalho só pra ela seria divergir do padrão local à
   toa (coding-standards §1). O que é próprio daqui é a LISTA e o LOG.

   Semântica de cor segue design-system §4, sem inventar: amarelo = atenção
   (parado, é o que o encarregado precisa enxergar), verde = ok (em rota),
   cinza = neutro (sem rota / fora do turno).
   --------------------------------------------------------------------------- */

.jor-campo-data {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--texto-secundario);
}
.jor-campo-data input {
  border: 1px solid var(--borda);
  border-radius: 8px;
  padding: 8px 10px;
  font: inherit;
  color: var(--texto);
  background: #fff;
}

.jor-lista-secao { margin-top: 26px; }
.jor-lista-secao .vg-overline { display: inline-block; margin-bottom: 10px; }

.jor-item {
  background: #fff;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  margin-bottom: 8px;
  overflow: hidden;
  /* Folga pro `scrollIntoView` do toggle (js/jornada.js): sem ela o item
     encosta na borda de baixo da janela — e no celular a tab bar fixa (~64px)
     comeria justamente o fim do log que o scroll acabou de revelar. */
  scroll-margin-bottom: 80px;
}
.jor-item[open] { box-shadow: var(--sombra); }

.jor-linha {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  cursor: pointer;
  /* A LINHA INTEIRA é o alvo do clique (pedido do usuário: "onde eu
     clicasse e aparecesse"), não só um ícone de seta. */
  min-height: var(--alvo-toque);
  list-style: none;
}
/* Marcador nativo do <summary> some nos dois motores — a seta própria
   (`.jor-seta`) já diz o estado, e o padrão do navegador desalinharia o
   flex. */
.jor-linha::-webkit-details-marker { display: none; }
.jor-linha::marker { content: ""; }
.jor-linha:hover { background: var(--azul-claro); }
.jor-item[open] .jor-linha { border-bottom: 1px solid var(--borda); }

.jor-avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 700;
  font-size: 13px;
}

.jor-identificacao { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
.jor-identificacao strong {
  font-size: 14px;
  color: var(--vg-navy);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.jor-marcadores { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }

.jor-etiqueta {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.04em;
  padding: 2px 7px;
  border-radius: 999px;
  border: 1px solid transparent;
}
.jor-etiqueta-parado {
  background: var(--amarelo-fundo);
  color: var(--amarelo-texto);
  border-color: var(--amarelo-borda);
}
.jor-etiqueta-em_rota {
  background: var(--vg-verde-fundo);
  color: var(--vg-verde);
  border-color: var(--vg-verde);
}
.jor-etiqueta-sem_rota {
  background: var(--fundo-painel);
  color: var(--texto-secundario);
  border-color: var(--borda);
}
/* "Não é motorista" (sessão 136) — azul de INFORMAÇÃO, não amarelo: não é
   atenção nem problema, é só uma categoria diferente de pessoa. Usar amarelo
   aqui competiria com o "parado" real dos motoristas (design-system §4). */
.jor-etiqueta-externo {
  background: var(--vg-azul-fundo);
  color: var(--vg-azul);
  border-color: var(--vg-azul);
}

.jor-placa, .jor-aviso { font-size: 11.5px; font-weight: 600; color: var(--texto-secundario); }
.jor-aviso { color: var(--amarelo-texto); }

.jor-numeros {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
  flex-shrink: 0;
  text-align: right;
}
/* O cronômetro que corre agora é o número mais importante da tela — é a
   pergunta que ela responde. */
.jor-destaque { font-size: 14px; font-weight: 800; color: var(--amarelo-texto); }
.jor-total { font-size: 11.5px; font-weight: 600; color: var(--texto-secundario); }

.jor-seta { flex-shrink: 0; color: var(--texto-secundario); transition: transform 0.15s ease; }
.jor-item[open] .jor-seta { transform: rotate(180deg); }

.jor-log { padding: 10px 14px 14px; background: var(--fundo-painel); }

.jor-bloco {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 8px 12px;
  border-left: 3px solid var(--borda);
  background: #fff;
  border-radius: 0 8px 8px 0;
  margin-bottom: 6px;
}
.jor-bloco:last-child { margin-bottom: 0; }
.jor-bloco-parado { border-left-color: var(--amarelo); background: var(--amarelo-fundo); }
.jor-bloco-rota { border-left-color: var(--vg-verde); }
/* Bloco em curso: o "agora" do motorista. Contorno em vez de outra cor —
   a cor já está ocupada dizendo parado/em rota (design-system §4). */
.jor-bloco-curso { outline: 1px dashed var(--texto-secundario); outline-offset: -1px; }
/* Bloco de ROTA abre o detalhamento da viagem (sessão 148). Só ele é
   clicável — "parado" não é viagem, não tem o que abrir —, então o bloco
   precisa DIZER isso antes do clique: cursor, realce no hover e foco
   visível pra quem chega por teclado. */
.jor-bloco-clicavel { cursor: pointer; }
.jor-bloco-clicavel:hover { background: var(--fundo-hover, #f1f5f9); }
.jor-bloco-clicavel:focus-visible { outline: 2px solid var(--azul, #2f6fdb); outline-offset: -2px; }
/* Fora do turno não é ocioso: some pro fundo em vez de competir por
   atenção com o que aconteceu dentro do expediente. */
.jor-bloco-fora { opacity: 0.65; background: #fff; border-left-color: var(--borda); }

.jor-bloco-horas {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 12.5px;
  color: var(--vg-navy);
  flex-shrink: 0;
  min-width: 105px;
}
.jor-bloco-texto { flex: 1; font-size: 12.5px; color: var(--texto); min-width: 0; }
.jor-bloco-extra {
  display: inline-block;
  margin-left: 6px;
  font-size: 11px;
  font-weight: 700;
  color: var(--vermelho);
}
.jor-bloco-duracao {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 12.5px;
  color: var(--texto-secundario);
  flex-shrink: 0;
}

.jor-vazio {
  margin: 0;
  padding: 14px;
  font-size: 13px;
  color: var(--texto-secundario);
  background: #fff;
  border: 1px dashed var(--borda);
  border-radius: var(--raio);
}

@media (max-width: 600px) {
  /* No celular o nome e o cronômetro empilham: lado a lado, o nome
     truncaria em 3 letras. */
  .jor-linha { flex-wrap: wrap; position: relative; padding-right: 40px; }
  .jor-numeros { align-items: flex-start; text-align: left; width: 100%; padding-left: 46px; }
  /* Com o `wrap` acima, a seta cairia sozinha numa terceira linha, colada na
     esquerda — longe do que ela controla. Fixa no canto, onde o polegar já
     espera um "expandir". */
  .jor-seta { position: absolute; top: 14px; right: 12px; }
  .jor-bloco { flex-wrap: wrap; gap: 4px 10px; }
  .jor-bloco-horas { min-width: 0; }
  .jor-bloco-texto { flex-basis: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .jor-seta { transition: none; }
}

/* ---------------------------------------------------------------------------
   Lançamento manual de viagem (sessão 134) — registrar o que já aconteceu.

   Formulário, não painel de leitura: por isso NÃO usa `.vg-cards`. Reaproveita
   só a moldura de cabeçalho (`.visao-geral`/`.vg-intro`) pra tela não parecer
   de outro produto. A tabela de paradas é o centro — campos dentro de células,
   como o usuário pediu ("em formato de tabela").
   --------------------------------------------------------------------------- */

/* Rótulo que só existe pra leitor de tela (cabeçalho da coluna de remover, que
   é um ícone). Não havia utilitário desses no projeto até aqui. */
.sr-apenas {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.lanc-form { margin-top: 20px; }

.lanc-bloco {
  background: #fff;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 18px;
  margin-bottom: 16px;
}
.lanc-bloco h2 {
  margin: 0 0 4px;
  font-size: 15px;
  color: var(--vg-navy);
}

.lanc-ajuda, .lanc-nota {
  margin: 6px 0 14px;
  font-size: 12.5px;
  color: var(--texto-secundario);
  line-height: 1.45;
}
/* Aviso de KM sem veículo — é impedimento, não dica. */
.lanc-nota {
  margin: 12px 0 0;
  color: var(--amarelo-texto);
  background: var(--amarelo-fundo);
  border: 1px solid var(--amarelo-borda);
  border-radius: 8px;
  padding: 8px 10px;
  font-weight: 600;
}

.lanc-campos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
  margin-top: 14px;
}
.lanc-campo-largo { grid-column: 1 / -1; }

.lanc-campos label,
.lanc-tabela label {
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--texto-secundario);
  /* Item de grid nasce com `min-width: auto`, que se recusa a encolher abaixo
     da largura INTRÍNSECA do conteúdo. `input[type=date]`/`[type=time]` têm
     intrínseca larga no Chrome (o widget de calendário/relógio), então sem
     isto o grid estourava a caixa em ~73px no celular — e como `.lanc-bloco`
     não rola, os campos da direita ficavam cortados e inalcançáveis. */
  min-width: 0;
}
.lanc-campos input,
.lanc-campos select {
  border: 1px solid var(--borda);
  border-radius: 8px;
  padding: 9px 10px;
  font: inherit;
  color: var(--texto);
  background: #fff;
  min-height: var(--alvo-toque);
  /* Par do `min-width: 0` acima: sem largura explícita, o input volta a
     pedir a intrínseca dele e desfaz a correção. */
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
}
.lanc-campos input:focus-visible,
.lanc-campos select:focus-visible,
.lanc-tabela input:focus-visible,
.lanc-tabela select:focus-visible {
  outline: 2px solid var(--laranja);
  outline-offset: 1px;
}

/* Tabela larga em tela estreita: rola só ela, nunca a página
   (design-system §6 — o corpo nunca rola na horizontal). */
.lanc-tabela-caixa { overflow-x: auto; }

.lanc-tabela {
  width: 100%;
  border-collapse: collapse;
  min-width: 720px;
}
.lanc-tabela th {
  text-align: left;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: var(--texto-secundario);
  text-transform: uppercase;
  padding: 0 8px 8px;
  border-bottom: 1px solid var(--borda);
}
.lanc-tabela td {
  padding: 8px;
  border-bottom: 1px solid var(--borda);
  vertical-align: middle;
}
.lanc-tabela tr:last-child td { border-bottom: 0; }

.lanc-tabela input,
.lanc-tabela select {
  width: 100%;
  border: 1px solid var(--borda);
  border-radius: 8px;
  padding: 8px 9px;
  font: inherit;
  color: var(--texto);
  background: #fff;
  min-height: var(--alvo-toque);
}

.lanc-col-num {
  width: 34px;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--texto-secundario);
  text-align: center;
}
.lanc-col-tipo { width: 150px; }
.lanc-col-situacao { width: 140px; }
.lanc-col-obs { width: 200px; }
.lanc-col-acao { width: 44px; text-align: center; }

/* "novo · fica só nesta viagem": o gestor precisa VER, antes de salvar, que
   digitou um lugar fora do cadastro — senão um erro de digitação em "CAROL"
   vira parada avulsa silenciosa e some dos agrupamentos por destino. */
.lanc-marca-avulso {
  display: inline-block;
  margin-top: 4px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--amarelo-texto);
  background: var(--amarelo-fundo);
  border: 1px solid var(--amarelo-borda);
  border-radius: 999px;
  padding: 2px 7px;
}

.lanc-acoes {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
}

@media (max-width: 600px) {
  .lanc-bloco { padding: 14px; }
  .lanc-campos { grid-template-columns: 1fr 1fr; }
  .lanc-campo-largo { grid-column: 1 / -1; }
  .lanc-acoes button { flex: 1; }
}
