/* painel/assets/shell.css — shell do Painel da Loja.
 *
 * Mobile-first de verdade: tudo abaixo é escrito para 375px, e só a partir de
 * 900px o layout vira sidebar + conteúdo largo. Nada de framework — os tokens
 * são os mesmos do admin (--bg, --sidebar, --primary, --accent) para que os
 * dois painéis pareçam o mesmo produto.
 */

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

:root {
  --bg:        #f4f1ec;
  --panel:     #ffffff;
  --sidebar:   #1a1210;
  --primary:   #b8211a;
  --primary2:  #8c1713;
  --accent:    #e8a020;
  --text:      #1a1a1a;
  --muted:     #7a756f;
  --border:    #e2ddd6;
  --success:   #1a7a4a;
  --danger:    #b8211a;
  --warning:   #c47a00;
  --sidebar-w: 240px;
  --nav-h:     58px;   /* barra inferior */
  --top-h:     56px;   /* barra superior */
  --radius:    14px;
  /* Escala de espaçamento. Nasceu com a camada de desktop: vários lugares
     precisaram de espaços maiores que os do celular ao mesmo tempo, e o mesmo
     literal repetido em dez regras diverge na primeira vez que uma delas for
     ajustada sozinha. Vale para o que o desktop tocou; o resto do arquivo
     segue com os valores que já tinha. */
  --sp-1:  4px;
  --sp-2:  8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --sp-6: 32px;
  /* Cinza de texto secundário do card. --muted (#7a756f) sobre branco dá 4.7:1
     — passa raspando no AA e some no reflexo de uma tela de loja. */
  --muted-2:   #6b665f;
  /* Altura segura da barra inferior, incluindo a área do gesto do iPhone. */
  --nav-total: calc(var(--nav-h) + env(safe-area-inset-bottom, 0px));
}

html { -webkit-text-size-adjust: 100%; }

body {
  font-family: 'DM Sans', system-ui, -apple-system, sans-serif;
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  /* Impede que a barra inferior cubra o fim do conteúdo. */
  padding-bottom: var(--nav-total);
  overflow-x: hidden;          /* nenhuma tela do painel rola na horizontal */
}

a { color: inherit; }

/* ── Barra superior ─────────────────────────────────────────────────────── */

.app-top {
  position: sticky; top: 0; z-index: 60;
  height: var(--top-h);
  background: var(--sidebar);
  color: #fff;
  display: flex; align-items: center; gap: 12px;
  padding: 0 16px;
}
.app-top .logotype { font-family: 'Syne', sans-serif; font-weight: 800; font-size: 1.05rem; letter-spacing: -.4px; }
.app-top .logotype span { color: var(--accent); }
.app-top .page-title {
  font-family: 'Syne', sans-serif; font-weight: 700; font-size: 1rem;
  flex: 1; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.app-top .top-action {
  width: 40px; height: 40px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 10px; border: none; background: transparent;
  color: rgba(255,255,255,.75); font-size: 1.15rem; cursor: pointer;
  text-decoration: none;
}
.app-top .top-action:active { background: rgba(255,255,255,.12); }

/* O "voltar" vale nas duas telas. Ficava escondido no desktop por causa da
   sidebar, mas a sidebar leva à seção — não de volta ao ponto exato de onde
   a pessoa veio (a lista já filtrada por carro ou moto). Sem ele, sair das
   fotos de um anúncio exigia rolar até o fim da página. */
.app-top .back-link { display: inline-flex; }

/* ── Faixa de impersonação ──────────────────────────────────────────────── */

.impersonate-bar {
  position: sticky; top: var(--top-h); z-index: 59;
  background: var(--accent); color: #2a1c00;
  font-size: .8rem; font-weight: 600;
  padding: 8px 16px;
  display: flex; align-items: center; gap: 10px; justify-content: space-between;
}
.impersonate-bar a { color: #2a1c00; text-decoration: underline; white-space: nowrap; }

/* ── Conteúdo ───────────────────────────────────────────────────────────── */

.content { padding: 16px; max-width: 1180px; margin: 0 auto; }

.section-title {
  font-family: 'Syne', sans-serif; font-weight: 700; font-size: .95rem;
  margin: 22px 0 10px;
}
.section-title:first-child { margin-top: 4px; }

/* ── Barra de navegação inferior (celular) ──────────────────────────────── */

.bottom-nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 70;
  height: var(--nav-total);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  background: var(--panel);
  border-top: 1px solid var(--border);
  display: flex;
}
.bottom-nav .nav-item {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px;
  min-height: 44px;                 /* alvo de toque confortável */
  text-decoration: none;
  color: var(--muted);
  font-size: .66rem; font-weight: 500;
  position: relative;
  -webkit-tap-highlight-color: transparent;
}
.bottom-nav .nav-item .icon { font-size: 1.2rem; line-height: 1; }
.bottom-nav .nav-item.active { color: var(--primary); font-weight: 700; }
.bottom-nav .nav-item:active { background: rgba(0,0,0,.04); }

/* Contador de leads não lidos. */
.nav-badge {
  position: absolute; top: 4px; left: 50%; margin-left: 4px;
  background: var(--primary); color: #fff;
  font-size: .6rem; font-weight: 700; line-height: 1;
  padding: 3px 5px; border-radius: 20px; min-width: 16px; text-align: center;
}
/* Número que é só novidade, sem nada vencendo por trás: mesmo lugar e mesmo
   tamanho, sem o vermelho de urgência. Se tudo fosse vermelho, o vermelho
   deixaria de querer dizer alguma coisa. */
.nav-badge.neutro { background: var(--muted); }
/* Ponto no "Mais" da barra inferior: o contador de avisos mora dentro do
   sheet, e sem esta marca ninguém saberia que há algo lá. */
.nav-item.tem-novidade .icon { position: relative; }
.nav-item.tem-novidade .icon::after {
  content: ''; position: absolute; top: -1px; right: -4px;
  width: 7px; height: 7px; border-radius: 50%; background: var(--primary);
}

/* ── Sidebar (desktop) ──────────────────────────────────────────────────── */

.side-nav { display: none; }

/* ── Cards ──────────────────────────────────────────────────────────────── */

.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 14px;
}
.card-header {
  padding: 14px 16px; border-bottom: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
.card-title { font-family: 'Syne', sans-serif; font-weight: 700; font-size: .95rem; }
.card-body { padding: 16px; }

/* ── KPIs ───────────────────────────────────────────────────────────────── */

.stats-grid {
  display: grid; gap: 10px;
  grid-template-columns: repeat(2, 1fr);   /* dois por linha já no celular */
  margin-bottom: 6px;
}
.stat-card {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 14px;
}
.stat-icon {
  width: 34px; height: 34px; border-radius: 9px; margin-bottom: 8px;
  display: flex; align-items: center; justify-content: center; font-size: 1rem;
}
.stat-icon.red { background: #fff0f0; } .stat-icon.blue { background: #f0f4ff; }
.stat-icon.green { background: #f0fff6; } .stat-icon.gold { background: #fff9f0; }
.stat-value { font-family: 'Syne', sans-serif; font-size: 1.4rem; font-weight: 700; line-height: 1; }
.stat-label { font-size: .74rem; color: var(--muted); margin-top: 3px; }
.stat-sub   { font-size: .72rem; color: var(--muted); margin-top: 6px; }

/* Barra de uso de cota. */
.quota-bar { height: 5px; background: var(--border); border-radius: 3px; overflow: hidden; margin-top: 8px; }
.quota-fill { height: 100%; background: var(--success); border-radius: 3px; }
.quota-fill.warn { background: var(--warning); }
.quota-fill.full { background: var(--danger); }

/* ── Card de veículo (substitui a tabela no celular) ────────────────────── */
/*
 * Uma linha por veículo, sem fileira de botões. As áreas do card é que são os
 * alvos: a FOTO leva às fotos, o TEXTO leva à edição, e "⋯" abre o resto.
 * Isso tirou ~100px de cada card — numa tela de 812px passam a caber seis
 * veículos em vez de dois, que é o que uma loja de 60 carros precisa.
 *
 * A regra de exibição é: só o que foge do normal aparece. "No ar" é o estado
 * de 12 em 12 anúncios da loja típica, então não vira etiqueta; o que está
 * pausado é que fica apagado e marcado.
 */

.v-list { display: grid; gap: 8px; }

.v-card-wrap {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius); overflow: hidden;
  transition: opacity .15s;
}
.v-card {
  display: flex; gap: 12px; padding: 10px;
  align-items: center; position: relative;
}

/* Anúncio pausado: o card inteiro perde cor. Não é só estética — é o sinal
   que substitui a etiqueta "fora do ar" em todo card. A etiqueta "pausado"
   continua ali por baixo, para quem não distingue a diferença de opacidade. */
.v-card-wrap.pausado { background: #fbfaf9; }
.v-card-wrap.pausado .v-thumb-link,
.v-card-wrap.pausado .v-title,
.v-card-wrap.pausado .v-price { opacity: .5; }

/* ── Foto ─────────────────────────────────────────────────────────────── */

.v-thumb-link {
  position: relative; z-index: 2;   /* acima do link esticado do título */
  flex-shrink: 0; display: block; line-height: 0;
  /* O "＋ foto" da caixa vazia é texto dentro de <a>: sem isto o navegador o
     sublinha, e o convite vira link de rodapé. */
  text-decoration: none;
  border-radius: 9px; overflow: hidden;
  -webkit-tap-highlight-color: transparent;
}
.v-thumb {
  width: 92px; height: 69px;
  border-radius: 9px; object-fit: cover; background: var(--bg);
  display: block;
}
.v-thumb.placeholder {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px; color: #b07d1a; font-size: 1.1rem; font-weight: 700; line-height: 1;
  padding-bottom: 10px;   /* deixa a base livre para a faixa "pausado" */
}
.v-thumb.placeholder small { font-size: .62rem; font-weight: 600; letter-spacing: .3px; }
/* Sem foto é problema de venda, não detalhe: a caixa vira convite âmbar e o
   toque já leva para o envio. Antes isso era uma etiqueta de texto a mais. */
.v-thumb-link.vazio .v-thumb { background: #fff6e5; border: 1px dashed #e8c37a; }

/* Anúncio sem direito a foto (o avulso grátis do PF). Cinza e não âmbar: a
   cor é que separa "falta foto, faça algo" de "aqui não cabe foto". Sem
   pointer-events para o toque atravessar até o link esticado do card — a
   miniatura deixa de levar à galeria, mas não vira buraco morto. */
.v-thumb-link.bloqueado { pointer-events: none; z-index: auto; }
.v-thumb.placeholder.bloqueado {
  background: var(--bg); border: 1px solid var(--border);
  color: var(--muted); font-size: .95rem;
}

.v-fotos-num {
  position: absolute; right: 3px; bottom: 2px; z-index: 1;
  min-width: 16px; padding: 0 4px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 8px; background: rgba(20,16,14,.66); color: #fff;
  font-size: .62rem; font-weight: 700; line-height: 1.5;
}
.v-fotos-num[hidden] { display: none; }

/* Selo de destaque sobre a foto: ★ dourado, ★★ vermelho para super. A
   contagem de estrelas carrega o sentido sem depender da cor. */
.v-selo {
  position: absolute; left: 4px; top: 4px;
  padding: 1px 5px; border-radius: 7px;
  font-size: .62rem; line-height: 1.5; letter-spacing: -.5px;
  color: #fff; text-shadow: 0 1px 1px rgba(0,0,0,.3);
}
.v-selo[hidden] { display: none; }
/* Quatro degraus. Grátis e normal ficam em cinza porque são a base, não uma
   conquista: em cor forte eles competiriam com o Destaque, que é o produto que
   a AutoSerra vende. */
.v-selo.gratis   { background: #6f6a64; }
.v-selo.normal   { background: rgba(0,0,0,.32); }
.v-selo.destaque { background: var(--warning); }
.v-selo.super    { background: var(--primary); }

/* Marcadores dos outros cantos da foto. Ficam aqui, e não no corpo do card,
   porque cada etiqueta no corpo custa uma linha de 24px multiplicada por todo
   o estoque. Sobre a foto, custam zero. */
/* Faixa e não pastilha: numa miniatura de 92px a pastilha disputava espaço
   com o "+ foto" do anúncio sem imagem. A faixa atravessa a base inteira,
   nunca esbarra em nada e ainda serve de fundo para o contador de fotos. */
.v-pausado {
  position: absolute; left: 0; right: 0; bottom: 0; height: 15px;
  display: flex; align-items: center; padding-left: 5px;
  background: rgba(20,16,14,.72); color: #fff;
  font-size: .56rem; font-weight: 700; letter-spacing: .4px;
  text-transform: uppercase;
}
.v-pausado[hidden] { display: none; }
/* A faixa tem 92px e o contador de fotos fica por cima da ponta direita dela.
   Sem reservar esse espaço o rótulo passa POR BAIXO do contador e some pela
   metade — foi o que aconteceu com "aguardando pgto", que virou "AGUARDANDO"
   com um 2 em cima. Os rótulos são curtos por isso; o motivo inteiro vive no
   title=. */
.v-pausado { white-space: nowrap; overflow: hidden; padding-right: 24px; }
/* Cor por motivo, e não decoração: âmbar é o que depende de uma ação de
   dinheiro (mesma cor do "＋ foto" e do Destaque), vermelho é o que saiu do ar
   sozinho. Escuro continua sendo o pausado — o único que a chave resolve.
   A palavra carrega o sentido inteiro sozinha: quem não distingue as cores lê
   "expirado" do mesmo jeito. */
.v-pausado.aguardando { background: var(--warning); }
.v-pausado.expirado   { background: var(--danger); }
.v-integrado {
  position: absolute; right: 4px; top: 4px;
  font-size: .68rem; line-height: 1;
  padding: 2px; border-radius: 6px; background: rgba(255,255,255,.85);
}

/* ── Corpo ────────────────────────────────────────────────────────────── */

.v-body { flex: 1; min-width: 0; }
/* Duas linhas no máximo: o nome comprido ("MERCEDES-BENZ GLA 200 CGI") não
   pode ser cortado a ponto de dois carros do mesmo modelo ficarem iguais na
   lista, mas também não pode empurrar o card para o dobro da altura. */
.v-title {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; color: inherit; text-decoration: none;
  font-weight: 600; font-size: .88rem; line-height: 1.25;
}
/* Link esticado: cobre o card todo, então tocar em qualquer lugar que não
   seja a foto ou os controles abre a edição. */
.v-stretch::after {
  content: ''; position: absolute; z-index: 1;
  /* Os quatro lados antes do inset: iOS 14.0 e anteriores não conhecem
     `inset`, e sem isto o card inteiro deixaria de ser tocável nesses
     aparelhos (só o texto do título continuaria levando à edição). */
  top: 0; right: 0; bottom: 0; left: 0;
  inset: 0;
}
/* Versão em até duas linhas. Uma linha só cortava justamente o fim ("6.2 V8 LT1
   GASOLINA STING…"), e o fim é o que distingue os carros do mesmo modelo — era
   mostrar a versão sem mostrar a versão. Duas linhas cobrem o catálogo inteiro
   (99,4% do estoque tem até 56 caracteres, e a média é 32) e custam ~15px só
   em quem passa de uma. */
.v-versao {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: .76rem; line-height: 1.2; margin-top: 1px;
  color: var(--text); opacity: .75;
}
.v-card-wrap.pausado .v-versao { opacity: .38; }
.v-meta {
  font-size: .78rem; color: var(--muted-2); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.v-linha-preco {
  display: flex; align-items: baseline; gap: 8px; margin-top: 3px;
}
.v-price { font-family: 'Syne', sans-serif; font-weight: 700; font-size: .98rem; white-space: nowrap; }
.v-vistas { font-size: .74rem; color: var(--muted-2); white-space: nowrap; }
/* Agrupa 👁 / WhatsApp / telefone / ✉ — no celular é a mesma fileira de antes
   (flex de gap 8, igual à linha do preço que a contém); no desktop vira a
   coluna de desempenho, que é o que permite comparar dois anúncios de relance
   sem ler número por número. */
.v-metricas { display: flex; align-items: baseline; gap: 8px; min-width: 0; flex-wrap: nowrap; }
/* Cliques nos botões de contato (WhatsApp e telefone). Um pouco maiores que a
   visualização e em verde: entre os números da linha, são os que representam
   alguém querendo falar. */
.v-contato { font-size: .78rem; font-weight: 600; color: #1e8e3e; white-space: nowrap; }
/* Marca do WhatsApp em vez do balão genérico. O símbolo vem embutido como data
   URI (é o mesmo glifo do Font Awesome que o site já usa) em vez de carregar a
   fonte de ícones inteira: o painel não tem Font Awesome, e puxar a biblioteca
   toda por causa de um ícone contraria o motivo de ele ser leve. */
/* Os glifos são usados no card do estoque e nos números das Estatísticas — as
   duas telas falam do mesmo evento, e ícone diferente para a mesma coisa faz
   parecer medida diferente. Por isso as classes são .ico-*, não .v-*. */
.ico-zap, .ico-tel { display: inline-flex; align-items: center; gap: 3px; }
.ico-zap::before, .ico-tel::before {
  content: ''; width: 14px; height: 14px; flex-shrink: 0;
  background-repeat: no-repeat; background-position: center; background-size: contain;
}
.ico-zap::before { background-image: url("data:image/svg+xml,%3Csvg fill='%231e8e3e' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M380.9 97.1C339 55.1 283.2 32 223.9 32c-122.4 0-222 99.6-222 222 0 39.1 10.2 77.3 29.6 111L0 480l117.7-30.9c32.4 17.7 68.9 27 106.1 27h.1c122.3 0 224.1-99.6 224.1-222 0-59.3-25.2-115-67.1-157zm-157 341.6c-33.2 0-65.7-8.9-94-25.7l-6.7-4-69.8 18.3L72 359.2l-4.4-7c-18.5-29.4-28.2-63.3-28.2-98.2 0-101.7 82.8-184.5 184.6-184.5 49.3 0 95.6 19.2 130.4 54.1 34.8 34.9 56.2 81.2 56.1 130.5 0 101.8-84.9 184.6-186.6 184.6zm101.2-138.2c-5.5-2.8-32.8-16.2-37.9-18-5.1-1.9-8.8-2.8-12.5 2.8-3.7 5.6-14.3 18-17.6 21.8-3.2 3.7-6.5 4.2-12 1.4-32.6-16.3-54-29.1-75.5-66-5.7-9.8 5.7-9.1 16.3-30.3 1.8-3.7.9-6.9-.5-9.7-1.4-2.8-12.5-30.1-17.1-41.2-4.5-10.8-9.1-9.3-12.5-9.5-3.2-.2-6.9-.2-10.6-.2-3.7 0-9.7 1.4-14.8 6.9-5.1 5.6-19.4 19-19.4 46.3 0 27.3 19.9 53.7 22.6 57.4 2.8 3.7 39.1 59.7 94.8 83.8 35.2 15.2 49 16.5 66.6 13.9 10.7-1.6 32.8-13.4 37.4-26.4 4.6-13 4.6-24.1 3.2-26.4-1.3-2.5-5-3.9-10.5-6.6z'/%3E%3C/svg%3E"); }
/* O telefone acompanha a marca do WhatsApp: emoji colorido ao lado de glifo
   monocromático faz os dois números parecerem coisas diferentes, quando são o
   mesmo gesto por canais diferentes. */
/* Envelope no mesmo tratamento do WhatsApp e do telefone: os três botões do
   card de e-mail são canais de contato, e canal com aparência diferente parece
   fazer outra coisa. */
.ico-email::before { background-image: url("data:image/svg+xml,%3Csvg fill='%231e8e3e' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M502.3 190.8c3.9-3.1 9.7-.2 9.7 4.7V400c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V195.6c0-5 5.7-7.8 9.7-4.7 22.4 17.4 52.1 39.5 154.1 113.6 21.1 15.4 56.7 47.8 92.2 47.6 35.7.3 72-32.8 92.3-47.6 102-74.1 131.6-96.3 154-113.7zM256 320c23.2.4 56.6-29.2 73.4-41.4 132.7-96.3 142.8-104.7 173.4-128.7 5.8-4.5 9.2-11.5 9.2-18.9v-19c0-26.5-21.5-48-48-48H48C21.5 64 0 85.5 0 112v19c0 7.4 3.4 14.3 9.2 18.9 30.6 23.9 40.7 32.4 173.4 128.7 16.8 12.2 50.2 41.8 73.4 41.4z'/%3E%3C/svg%3E"); width: 15px; height: 15px; }
.ico-email { display: inline-flex; align-items: center; gap: 3px; }
.ico-email::before { content: ''; flex-shrink: 0; background-repeat: no-repeat; background-position: center; background-size: contain; }
.ico-tel::before { background-image: url("data:image/svg+xml,%3Csvg fill='%231e8e3e' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M497.39 361.8l-112-48a24 24 0 0 0-28 6.9l-49.6 60.6A370.66 370.66 0 0 1 130.6 204.11l60.6-49.6a23.94 23.94 0 0 0 6.9-28l-48-112A24.16 24.16 0 0 0 122.6.61l-104 24A24 24 0 0 0 0 48c0 256.5 207.9 464 464 464a24 24 0 0 0 23.4-18.6l24-104a24.29 24.29 0 0 0-14.01-27.6z'/%3E%3C/svg%3E"); width: 13px; height: 13px; }
/* Contatos do anúncio. z-index acima do link esticado do card, senão o toque
   cairia na edição em vez de abrir os contatos daquele veículo. */
.v-leads {
  position: relative; z-index: 2;
  display: inline-flex; align-items: center; gap: 4px;
  font-size: .82rem; color: var(--muted); text-decoration: none; white-space: nowrap;
  /* Padding com margem negativa: aumenta o alvo de toque sem empurrar o
     preço nem deslocar a linha. */
  padding: 4px 5px; margin: -4px -5px;
}
/* O envelope é maior que o número: ele é o que se procura de relance na
   lista, o número só é lido depois de achá-lo. */
.v-leads-ico { font-size: 1.15rem; line-height: 1; }
/* Há contato sem ler: o número fica vermelho e ganha um ponto. Era uma
   pastilha "1 novo", que numa linha de 375px empurrava o preço para duas
   linhas — informação que cabe num ponto não merece quebrar o preço. */
.v-leads.novos { color: var(--primary); font-weight: 700; }
.v-leads.novos::after {
  content: ''; display: inline-block;
  width: 7px; height: 7px;
  border-radius: 50%; background: var(--primary);
}
.v-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 5px; }
.v-tags:empty { display: none; }

/* ── Controles ────────────────────────────────────────────────────────── */

.v-controles {
  position: relative; z-index: 2;
  flex-shrink: 0; display: flex; flex-direction: column; gap: 2px;
}
/* 38px: menor que os 44px do resto do app porque são dois alvos empilhados
   num card de 96px, e o que está em volta deles (o card inteiro) leva para a
   edição — errar o toque abre a tela certa, não destrói nada. */
.v-btn-icone {
  width: 38px; height: 38px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border: 0; border-radius: 8px; background: transparent;
  color: var(--muted); font-size: 1rem; line-height: 1;
  text-decoration: none; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.v-btn-icone:active { background: var(--bg); }
/* Ações que só aparecem no desktop. No celular o card tem três alvos e mais
   nada (a regra inteira está no comentário lá em cima) — botão a mais ali
   seria justamente o que foi tirado para caber seis veículos na tela. */
.so-desktop { display: none; }

/* ── Selo do tipo de anúncio ─────────────────────────────────────────────── */
/*
 * O degrau dito por PALAVRA, e não por um símbolo de 7px: num monitor "🎁" e
 * "•" eram a mesma mancha cinza, e o grátis é justamente o que a loja precisa
 * reconhecer para ver que ali cabe uma venda.
 *
 * É componente do painel e não peça do card: o formulário do anúncio mostra o
 * mesmo selo, porque quem clica num anúncio da lista tem de reencontrar ali
 * exatamente o que viu aqui. O HTML das duas telas sai de seloAnuncioHtml().
 */
.selo-anuncio {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 9px; border-radius: 20px;
  font-size: .72rem; font-weight: 700; letter-spacing: .2px;
  white-space: nowrap; max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  border: 1px solid transparent; vertical-align: middle;
}
/* As cores são as que o painel já usa, e não um vocabulário novo: âmbar é o
   Destaque em toda a interface (.chip-destaque), o vermelho discreto é o
   degrau de cima (.chip-super), e o cinza sólido do grátis é o mesmo #6f6a64
   do chip da foto (.v-selo.gratis).
   Azul foi tentado no grátis e descartado: aqui azul significa "veio do
   integrador", e o selo passaria a dizer duas coisas.
   Grátis é PREENCHIDO e Normal contornado — os dois cinza, porque são a base
   da escada; o peso é o que os separa sem inventar cor. */
.selo-anuncio.gratis   { background: #6f6a64;    color: #fff;             border-color: #6f6a64; }
.selo-anuncio.normal   { background: transparent; color: var(--muted-2);  border-color: var(--border); }
.selo-anuncio.destaque { background: #fff9f0;    color: var(--warning);   border-color: #f5daa0; }
.selo-anuncio.super    { background: #fff0f0;    color: var(--primary);   border-color: #f5c0c0; }

/* Linha do formulário que abriga o selo: sem isto o texto e a pastilha ficam
   com bases diferentes e a frase parece torta. */
.linha-selo { margin-top: 14px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.selo-nota { color: var(--muted); }

/* O selo como rótulo de uma opção de rádio (a escolha do tipo de anúncio da
   loja PJ). Precisa dos dois seletores de duas classes: `.radio span` impõe
   .9rem a qualquer span dentro do rádio e venceria o tamanho do selo, que tem
   de ser o mesmo do card — a opção que se escolhe aqui é o que se reconhece
   lá. */
.radio .radio-rotulo { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.radio .selo-anuncio { font-size: .72rem; }

/* No CARD ele é exclusivo do desktop: no celular o selo continua sendo o chip
   sobre a foto, e uma linha a mais custaria altura em todo o estoque. Só o
   card esconde — no formulário o selo vale em qualquer largura, porque ali há
   um anúncio só e a altura não se multiplica. */
.v-card .selo-anuncio { display: none; }
.v-preco-col { display: inline-flex; flex-direction: column; align-items: flex-start; min-width: 0; }
/* Excluir fica discreto de propósito: é a única ação irreversível do card e
   não deveria ser o elemento mais chamativo dele. */
.v-btn-icone.excluir { font-size: .8rem; color: #c9c3bc; }
.v-btn-icone.excluir:active { background: #fff0f0; color: var(--danger); }

/* ── Botões ─────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 44px; padding: 11px 18px;
  border-radius: 10px; border: none; cursor: pointer;
  font-family: 'DM Sans', sans-serif; font-size: .88rem; font-weight: 600;
  text-decoration: none; text-align: center;
  transition: opacity .15s, transform .08s;
  -webkit-tap-highlight-color: transparent;
}
.btn:active { transform: scale(.975); }
.btn-primary   { background: var(--primary); color: #fff; }
.btn-secondary { background: var(--border);  color: var(--text); }
.btn-danger    { background: var(--danger);  color: #fff; }
.btn-ghost     { background: transparent; color: var(--text); border: 1.5px solid var(--border); }
/* "sm" é só visual (fonte e cantos menores): no celular o alvo continua com
   44px de altura. Só no desktop, onde há mouse, ele encolhe de verdade. */
.btn-sm  { min-height: 44px; padding: 7px 12px; font-size: .8rem; border-radius: 8px; }
.btn-block { width: 100%; }
.btn[disabled], .btn.disabled { opacity: .45; pointer-events: none; }

/* Linha de ações que não quebra feio no celular. */
.btn-row { display: flex; gap: 8px; }
.btn-row .btn { flex: 1; }

/* "X" de excluir sobreposto a uma miniatura (fotos do anúncio e da loja).
 *
 * Discreto em repouso, forte quando tocado. Numa grade de 12 fotos, doze
 * círculos escuros e opacos viravam o elemento mais chamativo da tela — os
 * botões de apagar pesavam mais que as próprias fotos, que são o conteúdo.
 *
 * O alvo continua com 32px e não encolheu junto com o visual: quem erra o
 * toque cai numa confirmação, mas quem não consegue acertar o botão fica sem
 * conseguir apagar. Discrição é da cor, não do tamanho.
 */
.btn-excluir-foto {
  width: 32px; height: 32px; border-radius: 50%;
  background: transparent; color: #fff; border: 0;
  font-size: .8rem; font-weight: 700; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  /* Sem disco de fundo: o que dava peso ao botão era o círculo, não o ✕. A
     sombra dupla é o que o mantém legível tanto sobre foto clara quanto
     escura, sem pintar nada por trás. */
  text-shadow: 0 1px 3px rgba(0,0,0,.85), 0 0 6px rgba(0,0,0,.55);
  transition: background .15s;
}
/* No toque (e no hover do desktop) ele assume o que é: ação destrutiva. */
.btn-excluir-foto:hover  { background: rgba(20,16,14,.55); }
.btn-excluir-foto:active { background: var(--danger); text-shadow: none; }
.btn-excluir-foto:focus-visible { outline: 2px solid #fff; outline-offset: 1px; }

/* Referências de preço abaixo do campo Preço (FIPE / faixa do AutoSerra).
   Discreto de propósito: orienta, não compete com o valor que o lojista
   está digitando. */
.ref-preco {
  margin-top: 8px; padding: 10px 12px;
  background: var(--bg); border: 1px solid var(--border); border-radius: 10px;
  display: grid; gap: 6px;
}
.ref-linha {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px;
  font-size: .78rem; line-height: 1.35;
}
.ref-rotulo { color: var(--muted); min-width: 84px; }
.ref-valor  { font-weight: 700; }
.ref-obs    { color: var(--muted); font-size: .72rem; }

/* Grid de opcionais (estoque/form.php) — 1 coluna no mobile, 2 no meio do
   caminho, 3 só no desktop largo.
   O salto para 3 é em 1200px e não em 900px porque a partir de 900px entra a
   sidebar de 240px: um monitor de 900px deixa ~620px de conteúdo, e em 3
   colunas quase todo rótulo quebra em duas linhas ("Assistente para partidas
   em subidas", "Ar condicionado digital").
   O divisor de grupo atravessa a linha inteira — em coluna única ele
   ocuparia uma célula só e pareceria mais um item da lista. */
.opcionais-grid {
  display: grid; gap: 2px 18px;
}
.opcionais-grid > .group-divider { grid-column: 1 / -1; }

@media (min-width: 600px) {
  .opcionais-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1200px) {
  .opcionais-grid { grid-template-columns: repeat(3, 1fr); }
}

/* ── Galeria de fotos (estoque/fotos.php e loja/fotos.php) ──────────────── */
/* As duas telas usam a mesma marcação e o mesmo assets/fotos.js. */

.fotos-grid {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;
}
/* touch-action:manipulation deixa o fotos.js decidir entre arraste e rolagem
   sem o navegador disparar duplo-toque para dar zoom no meio do gesto. */
.foto-card {
  margin: 0; position: relative; touch-action: manipulation;
}
.foto-card img {
  width: 100%; aspect-ratio: 4/3; object-fit: cover;
  display: block; background: var(--bg);
}
.foto-capa { position: absolute; top: 8px; left: 8px; }
.foto-remover { position: absolute; top: 8px; right: 8px; }

/* Arrastar fotos — o card sai do grid e flutua torto sob o dedo; o
   placeholder tracejado marca onde ele vai cair. */
.foto-arrastando {
  position: fixed; z-index: 200; pointer-events: none;
  transform: rotate(4deg) scale(1.04);
  box-shadow: 0 14px 28px rgba(20,16,14,.35);
  transition: none;
}
.foto-placeholder {
  aspect-ratio: 4/3;
  border: 2px dashed var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

/* Botão flutuante "novo anúncio". */
.fab {
  position: fixed; right: 16px; z-index: 65;
  bottom: calc(var(--nav-total) + 14px);
  width: 54px; height: 54px; border-radius: 50%;
  background: var(--primary); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.6rem; text-decoration: none; border: none; cursor: pointer;
  box-shadow: 0 6px 18px rgba(184,33,26,.35);
}

/* ── Formulários ────────────────────────────────────────────────────────── */

.form-group { margin-bottom: 16px; }
.form-label {
  display: block; font-size: .75rem; font-weight: 600; letter-spacing: .4px;
  text-transform: uppercase; color: var(--muted); margin-bottom: 6px;
}
.form-control {
  width: 100%; padding: 12px 14px;
  border: 1.5px solid var(--border); border-radius: 10px;
  font-family: 'DM Sans', sans-serif;
  font-size: 16px;            /* 16px evita o zoom automático do iOS ao focar */
  color: var(--text); background: #fff; outline: none;
  transition: border-color .15s, box-shadow .15s;
}
.form-control:focus { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(184,33,26,.1); }
.form-control[readonly], .form-control[disabled] { background: #f6f4f1; color: var(--muted); }
select.form-control { appearance: none; -webkit-appearance: none; background-image: none; }
textarea.form-control { resize: vertical; min-height: 96px; }
.form-hint { font-size: .74rem; color: var(--muted); margin-top: 5px; }
/* Uma coluna no celular, sempre. */
.form-row { display: grid; gap: 14px; grid-template-columns: 1fr; }

/* Botão de mostrar/ocultar senha — mesmo padrão do login.php. */
.senha-wrap { position: relative; }
.senha-wrap .form-control { padding-right: 52px; }
.senha-toggle {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 42px; height: 42px; border: none; background: none; cursor: pointer;
  font-size: 1.1rem; color: var(--muted);
}

/* Interruptor ativo/inativo. */
.switch { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; min-height: 44px; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch .track {
  width: 46px; height: 27px; border-radius: 20px; background: var(--border);
  position: relative; transition: background .18s; flex-shrink: 0;
}
.switch .track::after {
  content: ''; position: absolute; top: 3px; left: 3px;
  width: 21px; height: 21px; border-radius: 50%; background: #fff;
  transition: transform .18s; box-shadow: 0 1px 3px rgba(0,0,0,.25);
}
.switch input:checked + .track { background: var(--success); }
.switch input:checked + .track::after { transform: translateX(19px); }

/* Caixa de marcar / opção única — para escolhas de conteúdo do anúncio
   (opcionais, único dono, tipo de destaque). Diferente do .switch, que é só
   para ligar/desligar um estado do sistema (ex.: publicado). */
.checkbox, .radio {
  display: flex; align-items: center; gap: 10px; cursor: pointer; min-height: 44px;
}
.checkbox input, .radio input {
  width: 20px; height: 20px; flex-shrink: 0; accent-color: var(--primary); cursor: pointer;
}
.checkbox span, .radio span { font-size: .9rem; }
.checkbox:has(input:disabled), .radio:has(input:disabled) { cursor: not-allowed; opacity: .5; }
.checkbox input:disabled, .radio input:disabled { cursor: not-allowed; }

/* Divisor dentro de um card, para separar grupos de opções (ex.: opcionais
   principais vs. os demais) sem o peso visual do .section-title. */
.group-divider {
  margin: 16px 0 6px; padding-top: 12px; border-top: 1px solid var(--border);
  font-size: .76rem; font-weight: 600; color: var(--muted);
  text-transform: uppercase; letter-spacing: .4px;
}

/* ── Chips / status ─────────────────────────────────────────────────────── */

.chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 10px; border-radius: 20px;
  font-size: .72rem; font-weight: 600;
  background: var(--bg); color: var(--muted); border: 1px solid var(--border);
}
.chip-ativo    { background: #edfaf3; color: var(--success); border-color: #a8e6c3; }
.chip-inativo  { background: #f5f5f5; color: var(--muted); }
.chip-destaque { background: #fff9f0; color: var(--warning); border-color: #f5daa0; }
/* Mesmo tom para "super destaque" e "não lido": os dois são o alerta vermelho
   discreto do painel. Um seletor só, para o valor não viver em dois lugares. */
.chip-super,
.lead-chip-naolido { background: #fff0f0; color: var(--primary); border-color: #f5c0c0; }
.chip-integrador { background: #f0f4ff; color: #2b4a9b; border-color: #c3d0f0; }
/* Aviso que a loja ainda não abriu. */
.chip-novo { background: #fdeceb; color: var(--primary); border-color: #f3c9c6; }

/* Chip escondida pelo JS (ex.: anúncio sem destaque). O [hidden] do navegador
   não vence o display:inline-flex acima, então precisa ser explícito. */
.chip[hidden] { display: none; }

/* Filtros rápidos que rolam na horizontal — a ÚNICA rolagem lateral permitida. */
.chip-scroller {
  display: flex; gap: 8px; overflow-x: auto; padding: 2px 16px 10px;
  margin: 0 -16px;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.chip-scroller::-webkit-scrollbar { display: none; }
.chip-scroller .chip { flex-shrink: 0; min-height: 34px; text-decoration: none; }
.chip-scroller .chip.active { background: var(--primary); color: #fff; border-color: var(--primary); }
/* Contagem dentro do chip: mais pesada que o rótulo, porque é o número que se
   compara de relance entre um chip e outro. */
.chip-num { font-weight: 700; opacity: .8; }
.chip.active .chip-num { opacity: 1; }
/* Chip sem nada dentro continua na fila, apagado: escondê-lo faria a fila
   mudar de tamanho a cada filtro e a loja perderia a referência de onde tocar. */
.chip-zero { opacity: .45; }

/* ── Alertas ────────────────────────────────────────────────────────────── */

.alert {
  padding: 12px 14px; border-radius: 10px; font-size: .85rem;
  margin-bottom: 14px; display: flex; gap: 9px; align-items: flex-start; line-height: 1.5;
}
.alert-success { background: #edfaf3; color: var(--success); border: 1px solid #a8e6c3; }
.alert-danger  { background: #fff0f0; color: var(--danger);  border: 1px solid #f5c0c0; }
.alert-warning { background: #fff9f0; color: var(--warning); border: 1px solid #f5daa0; }
/* Alerta com botão de ação (as pendências). Em 375px o botão ao lado do texto
   espreme a frase numa coluna de 40% da tela — "Seus anúncios estão / fora do
   ar" quebrado no meio. Abaixo de 520px ele desce e ocupa a linha. */
@media (max-width: 520px) {
  .alert { flex-wrap: wrap; }
  .alert > .btn { width: 100%; margin-top: 10px; justify-content: center; }
}
.alert-info    { background: #f0f4ff; color: #2b4a9b;        border: 1px solid #c3d0f0; }
/* Mesmo caso das chips: display:flex acima vence o [hidden] do navegador. */
.alert[hidden] { display: none; }

/* Contador "3/10 no ar" do topo da listagem — vira classe porque o JS troca
   a cor quando a cota enche ou libera. */
.cota-ok    { font-size: .78rem; color: var(--muted); }
.cota-cheia { font-size: .78rem; color: var(--danger); font-weight: 600; }

/* ── Barra da listagem ──────────────────────────────────────────────────── */
/*
 * Duas peças no mesmo invólucro. O RESUMO ("63 carros · 12/20 no ar") vale nas
 * duas telas. As FERRAMENTAS (busca, situação, ordem) só no desktop: no celular
 * elas moram no sheet do ⚙️, que é o certo para o polegar, e no mouse não é —
 * esconder o filtro atrás de um ícone que abre um diálogo cobra três gestos de
 * quem filtra o dia inteiro.
 *
 * A barra é um <form> PRÓPRIO, irmão do form do sheet. Não são os mesmos campos
 * duplicados: cada form envia só os seus, então não há como os dois brigarem
 * pelo mesmo `name` num submit.
 */
.estoque-barra { margin-bottom: 12px; }
.estoque-toolbar { display: none; }
.lista-resumo {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  font-size: .85rem; color: var(--muted);
}
.lista-resumo a { color: var(--primary); font-weight: 600; }

/* ── Bottom sheet (filtros e ações) ─────────────────────────────────────── */
/*
 * Substitui o dropdown: no celular um menu ancorado ao botão fica minúsculo e
 * longe do polegar. O sheet sobe de baixo, ocupa a metade inferior e tem o
 * botão de confirmar fixo no rodapé.
 */

.sheet-backdrop {
  position: fixed; z-index: 90;
  /* Os quatro lados antes do inset, mesmo motivo do .v-stretch: iOS 14.0 e
     anteriores não conhecem `inset`, e um backdrop sem dimensão não escurece
     a tela nem recebe o toque que fecha o sheet — o menu ficaria só fechável
     pelo botão "Fechar". */
  top: 0; right: 0; bottom: 0; left: 0;
  inset: 0;
  background: rgba(0,0,0,.45);
  opacity: 0; pointer-events: none; transition: opacity .22s;
}
.sheet-backdrop.open { opacity: 1; pointer-events: auto; }

.sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 91;
  background: var(--panel);
  border-radius: 18px 18px 0 0;
  max-height: 88vh;
  display: flex; flex-direction: column;
  transform: translateY(100%);
  transition: transform .26s cubic-bezier(.32,.72,0,1);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  /* Reforço: além de tirar da tela pelo transform, o sheet fechado não deve
     capturar clique nenhum. Sem isso, um navegador que atrase o transform (ou
     ignore parte da folha de estilo) deixa os itens do sheet — Financeiro,
     Fotos da loja, Sair etc. — clicáveis por cima do conteúdo normal da
     página, na faixa onde o sheet ficaria fixado (fim da tela). Sem
     visibility aqui de propósito: cortaria a animação de fechar.*/
  pointer-events: none;
}
.sheet.open { transform: translateY(0); pointer-events: auto; }
.sheet-handle {
  width: 38px; height: 4px; border-radius: 3px; background: var(--border);
  margin: 10px auto 4px; flex-shrink: 0;
}
.sheet-header {
  padding: 6px 18px 12px; border-bottom: 1px solid var(--border); flex-shrink: 0;
  display: flex; align-items: center; justify-content: space-between;
}
.sheet-title { font-family: 'Syne', sans-serif; font-weight: 700; font-size: 1rem; }
.sheet-body { padding: 16px 18px; overflow-y: auto; flex: 1; -webkit-overflow-scrolling: touch; }
.sheet-footer {
  padding: 12px 18px; border-top: 1px solid var(--border); flex-shrink: 0;
  display: flex; gap: 10px; background: var(--panel);
}
.sheet-footer .btn { flex: 1; }

/* Item de menu dentro do sheet (ações do veículo, "Mais"). */
.sheet-item {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 4px; min-height: 48px;
  text-decoration: none; color: var(--text); font-size: .92rem;
  border-bottom: 1px solid var(--border);
}
.sheet-item:last-child { border-bottom: none; }
.sheet-item .icon { font-size: 1.15rem; width: 24px; text-align: center; flex-shrink: 0; }
.sheet-item.danger { color: var(--danger); }
.sheet-item:active { background: var(--bg); }

/* Enquanto a ação do menu está no ar, nada mais pode ser tocado: dois toques
   seguidos em "Destaque" mandariam duas escritas e a segunda leria a cota
   antes de a primeira ter contado. */
.sheet.ocupado { pointer-events: none; opacity: .6; }

/* ── Segmentado (tipo de anúncio) ───────────────────────────────────────── */
/*
 * Três opções mutuamente exclusivas, e a escolha é UMA — por isso segmentado
 * e não três interruptores: dois interruptores permitiriam ligar destaque e
 * super ao mesmo tempo, estado que o banco não representa.
 */
.seg {
  display: flex; gap: 6px;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 12px; padding: 4px;
}
/* `hidden` sozinho não vence um display: flex declarado — sem esta linha o
   seletor continuava na tela ao lado do nome do plano. */
.seg[hidden] { display: none; }
.seg-opt {
  flex: 1; min-height: 48px; padding: 8px 6px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  border: 0; border-radius: 9px; background: transparent; color: var(--text);
  font-family: 'DM Sans', sans-serif; font-size: .84rem; font-weight: 600;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background .15s, color .15s;
}
.seg-opt small { font-size: .68rem; font-weight: 500; color: var(--muted); }
.seg-opt.active { background: var(--primary); color: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.12); }
.seg-opt.active small { color: rgba(255,255,255,.75); }
.seg-opt:disabled { opacity: .4; cursor: not-allowed; }
.seg-opt:not(.active):not(:disabled):active { background: var(--border); }

/* ── Toast ──────────────────────────────────────────────────────────────── */
/*
 * Sobe acima da bottom-nav E do FAB — os dois ficam no canto de baixo, e um
 * toast centrado na largura toda passa por cima do "+" no celular.
 */
.toast {
  position: fixed; left: 50%; z-index: 120;
  bottom: calc(var(--nav-total) + 82px);
  transform: translate(-50%, 12px);
  max-width: min(420px, calc(100vw - 32px));
  padding: 12px 18px; border-radius: 10px;
  background: var(--sidebar); color: #fff;
  font-size: .86rem; font-weight: 500; line-height: 1.4; text-align: center;
  box-shadow: 0 6px 20px rgba(0,0,0,.22);
  opacity: 0; pointer-events: none; transition: opacity .22s, transform .22s;
}
.toast.open { opacity: 1; transform: translate(-50%, 0); }
.toast-erro { background: var(--danger); }

@media (min-width: 900px) {
  .toast { bottom: 26px; }
}

/* ── Estado vazio ───────────────────────────────────────────────────────── */

.empty-state { text-align: center; padding: 56px 20px; }
.empty-icon { font-size: 3rem; margin-bottom: 14px; }
.empty-state h2 { font-family: 'Syne', sans-serif; font-size: 1.15rem; font-weight: 700; margin-bottom: 8px; }
.empty-state p { color: var(--muted); font-size: .88rem; line-height: 1.6; margin-bottom: 22px; max-width: 380px; margin-left: auto; margin-right: auto; }

/* Linha de números de um anúncio (ranking das Estatísticas). Mesmo verde e
   mesma ordem do card do estoque; a visualização fica cinza porque é o
   denominador, não o resultado. */
.metrica-linha { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; font-size: .8rem; }
.metrica-linha .ico-olho { color: var(--muted); }
.metrica-linha .ico-zap, .metrica-linha .ico-tel,
.stat-canais .ico-zap, .stat-canais .ico-tel { color: #1e8e3e; font-weight: 600; }
.metrica-linha .ico-mail, .stat-canais .ico-mail { color: var(--primary); font-weight: 600; }
.stat-canais { display: flex; align-items: center; gap: 10px; }

/* ── Financeiro ─────────────────────────────────────────────────────────── */

/* Resumo do que está em aberto. Some quando não há nada devendo — ver o
   comentário no index.php. */
.fin-resumo {
  background: var(--panel); border: 1px solid var(--border); border-left: 3px solid var(--warning);
  border-radius: var(--radius); padding: 14px 16px; margin-bottom: 14px;
}
.fin-resumo.vencido { border-left-color: var(--danger); }
.fin-resumo-valor { font-family: 'Syne', sans-serif; font-size: 1.5rem; font-weight: 700; line-height: 1.1; }
.fin-resumo-txt { font-size: .8rem; color: var(--muted); margin-top: 4px; }
.fin-emdia {
  font-size: .85rem; color: var(--muted);
  padding: 10px 14px; margin-bottom: 14px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
}

.fin-card { margin: 0 0 10px; }
.fin-topo { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.fin-descr { font-size: .9rem; font-weight: 600; line-height: 1.35; }
.fin-descr-tipo { display: block; font-size: .7rem; font-weight: 500; color: var(--muted); }
/* O chip nunca quebra em duas linhas: "Em aberto" partido no meio vira um
   borrão ao lado do título. */
.fin-topo .chip { white-space: nowrap; flex-shrink: 0; }
.chip-aberto  { background: #f0f4ff; color: #2b4a9b; border-color: #c3d0f0; }
.chip-vencido { background: #fff0f0; color: var(--danger); border-color: #f0c3c3; }

/* Anúncio vinculado à cobrança — marca, modelo, placa. */
.fin-veiculo { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; padding: 8px 10px;
              background: var(--bg); border-radius: 8px; font-size: .9rem; }
.fin-veiculo-icon { font-size: 1.2rem; flex-shrink: 0; }
.fin-veiculo-info { flex: 1; min-width: 0; }
.fin-veiculo-nome { font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fin-veiculo-placa { font-size: .8rem; color: var(--muted); margin-top: 2px; }
.fin-veiculo-link { text-decoration: none; color: var(--muted); font-size: 1rem; flex-shrink: 0;
                   transition: color 200ms; }
.fin-veiculo-link:hover { color: var(--text); }
.fin-veiculo-vazio { font-size: .85rem; color: var(--muted); margin-bottom: 12px; font-style: italic; }

/* Vencimento e Recebimento lado a lado: é assim que se confere um extrato
   contra o banco — a mesma cobrança, dois momentos. Em duas colunas mesmo no
   celular; separar em linhas empilhadas desfaz a comparação. */
.fin-grade { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.fin-bloco { background: var(--bg); border-radius: 10px; padding: 10px 12px; }
.fin-bloco.ok { background: #f2f8f4; }
.fin-bloco.vazio .fin-data, .fin-bloco.vazio .fin-valor { color: var(--muted); font-weight: 500; }
.fin-rotulo { font-size: .68rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.fin-data  { font-size: .95rem; font-weight: 600; margin-top: 4px; }
.fin-valor { font-family: 'Syne', sans-serif; font-size: 1.02rem; font-weight: 700; margin-top: 1px; }
.fin-dif   { font-size: .7rem; color: var(--muted); margin-top: 3px; }

.fin-obs { font-size: .8rem; color: var(--muted); margin-top: 10px; line-height: 1.5; }
.fin-acoes { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.fin-form-nota { display: inline; }
/* O número da cobrança é referência para falar com o suporte, não informação
   de primeira ordem: vai para o fim da linha, discreto. */
.fin-id { margin-left: auto; font-size: .72rem; color: var(--muted); }
.fin-nota { margin-top: 16px; font-size: .78rem; color: var(--muted); line-height: 1.5; }

/* ── Integrador: cartão de sincronização ────────────────────────────────── */

.sync-card { margin: 0 0 12px; }
.sync-topo { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.sync-data { font-weight: 600; font-size: .92rem; }

/* Duas colunas no celular, quatro a partir de 480px. Com quatro em 375px o
   rótulo "Não mapeados" quebra em três linhas e desalinha a fileira. */
.sync-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
             gap: 10px; margin-top: 14px; }
@media (min-width: 480px) { .sync-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.sync-item { background: var(--bg); border-radius: 10px; padding: 10px 8px; text-align: center; }
.sync-num { font-family: 'Syne', sans-serif; font-size: 1.15rem; font-weight: 700;
            line-height: 1.1; min-height: 1.2em; }
.sync-lbl { font-size: .72rem; color: var(--muted); margin-top: 4px; }
.sync-novo  { color: var(--success); }
.sync-atu   { color: var(--muted); }
.sync-barra { color: var(--muted); margin: 0 2px; font-weight: 400; }
.sync-zero  { color: var(--muted); font-weight: 400; }
.sync-alerta { color: var(--danger); }

/* O número dos não mapeados abre a lista: é botão de verdade (foco e teclado),
   com cara de link para não competir com os botões de ação da página. */
.sync-link { background: none; border: 0; padding: 0; font: inherit; color: var(--danger);
             text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.sync-nota .sync-link { font-size: .8rem; font-weight: 600; white-space: nowrap; }

.sync-legenda { font-size: .72rem; color: var(--muted); margin-top: 8px; text-align: center; }
.sync-legenda strong { color: var(--success); }

.sync-nota { font-size: .8rem; line-height: 1.5; border-radius: 8px; padding: 10px 12px; margin-top: 12px; }
.sync-nota-alerta { background: #fff0f0; color: #8a2b2b; }
.sync-nota-limite { background: #fff9f0; color: #7a5312; }
.sync-nota a { color: inherit; font-weight: 600; }

.sync-msg { background: var(--bg); border-radius: 8px; padding: 10px 12px; margin-top: 12px;
            font-size: .82rem; line-height: 1.5; color: var(--muted); }

.sync-rodape { margin-top: 20px; padding: 12px; background: var(--bg); border-radius: 8px;
               font-size: .8rem; color: var(--muted); line-height: 1.5; }

.sync-explica { font-size: .82rem; color: var(--muted); line-height: 1.55; margin-bottom: 14px; }
.sync-lista-item { font-size: .82rem; line-height: 1.5; padding: 8px 0;
                   border-bottom: 1px solid var(--border); overflow-wrap: anywhere; }
.sync-lista-item:last-child { border-bottom: none; }
.sync-lista-item strong { color: var(--primary); margin-right: 4px; }

/* Nome do anúncio no menu do card (PF). Ocupa o lugar do seletor de tipo, e
   por isso tem a mesma altura de respiro que ele. */
.menu-plano { background: var(--bg); border-radius: 10px; padding: 12px 14px; }
.menu-plano[hidden] { display: none; }
.menu-plano-nome { display: block; font-weight: 600; font-size: .92rem; }
.menu-plano-sub  { display: block; font-size: .78rem; color: var(--muted); margin-top: 3px; }
.menu-plano-sub[hidden] { display: none; }

/* Aviso de quilometragem provavelmente digitada em milhares. Âmbar e não
   vermelho: é uma pergunta, não uma recusa — o Salvar continua liberado. */
.aviso-km {
  background: #fff9f0; border: 1px solid #f5daa0; color: #7a5312;
  border-radius: 8px; padding: 8px 10px; margin-top: 6px; line-height: 1.5;
}
.aviso-km[hidden] { display: none; }
.aviso-km strong { color: inherit; }
.aviso-km .km-corrige {
  background: none; border: 0; padding: 0; font: inherit; color: inherit;
  font-weight: 700; text-decoration: underline; cursor: pointer;
}

/* ── Escolha do anúncio avulso (PF) ─────────────────────────────────────── */
/* Cartões de opção, não um <select>: são três ou quatro linhas com preço e o
   que cada uma inclui, e num select isso tudo caberia numa linha só de texto. */

.plano-lista { display: grid; gap: 10px; }
.plano-opt {
  display: flex; align-items: flex-start; gap: 12px;
  background: var(--panel); border: 1.5px solid var(--border);
  border-radius: var(--radius); padding: 14px; cursor: pointer;
}
/* :has ainda não é universal, então a borda de selecionado não pode ser o único
   sinal — o próprio radio marcado já diz, e a borda é reforço onde funciona. */
.plano-opt:has(input:checked) { border-color: var(--primary); background: #fffaf9; }
.plano-opt input { margin-top: 3px; width: 20px; height: 20px; flex-shrink: 0; accent-color: var(--primary); }
.plano-corpo { flex: 1; min-width: 0; }
.plano-topo { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.plano-nome { font-weight: 600; font-size: .95rem; }
.plano-preco { font-family: 'Syne', sans-serif; font-weight: 700; font-size: 1rem; white-space: nowrap; }
.plano-preco.gratis { color: var(--success); }
.plano-detalhe { display: block; font-size: .8rem; color: var(--muted); margin-top: 4px; line-height: 1.45; }
.plano-nota { margin-top: 16px; font-size: .8rem; color: var(--muted); line-height: 1.55; }

/* ── Lista de anúncios fora do ar (PF) ──────────────────────────────────── */

.renov-lista { display: grid; gap: 8px; }
.renov-item {
  display: flex; align-items: center; gap: 12px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 12px 14px; text-decoration: none; color: inherit; min-height: 56px;
}
.renov-item:active { background: var(--bg); }
.renov-ico { font-size: 1.3rem; flex-shrink: 0; }
.renov-corpo { flex: 1; min-width: 0; }
.renov-nome { display: block; font-weight: 600; font-size: .92rem;
              overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.renov-estado { display: block; font-size: .78rem; color: var(--muted); margin-top: 2px; }
.renov-estado.fora { color: var(--danger); }
.renov-seta { color: var(--muted); flex-shrink: 0; }

/* ── Dicas de venda (tela de avisos) ────────────────────────────────────── */
/* Lista com marcador próprio: o ul padrão do reset não
   tem bullet, e sem nenhuma marca as cinco frases viram um bloco de texto. */
.dicas { margin-top: 18px; }
.dicas-lista { list-style: none; display: grid; gap: 12px; }
.dicas-lista li { position: relative; padding-left: 18px; font-size: .85rem; line-height: 1.55; color: var(--muted); }
.dicas-lista li::before { content: '▸'; position: absolute; left: 0; top: 0; color: var(--warning); }
.dicas-lista strong { color: var(--text); }
.dicas-lista a { color: var(--primary); font-weight: 600; }

/* ── Contrato ───────────────────────────────────────────────────────────── */

.cota-plano {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-family: 'Syne', sans-serif; font-weight: 700; font-size: .95rem;
  margin: 22px 0 10px;
}
.cota-valor { font-family: 'Syne', sans-serif; font-size: 1.25rem; font-weight: 700; margin: -6px 0 10px; }
.cota-titulo { font-size: .8rem; font-weight: 600; margin-bottom: 10px; }
.cota-grupo  { font-size: .78rem; color: var(--muted); margin: 10px 0 6px; }
.cota-grade  { display: flex; gap: 8px; flex-wrap: wrap; }
.cota-box {
  flex: 1 1 0; min-width: 84px; text-align: center;
  background: var(--bg); border-radius: 10px; padding: 10px 8px;
}
.cota-num { font-family: 'Syne', sans-serif; font-size: 1.3rem; font-weight: 700; line-height: 1; color: var(--primary); }
.cota-num.ouro { color: var(--warning); }
.cota-rot { font-size: .7rem; color: var(--muted); margin-top: 3px; }
.cota-fotos { font-size: .8rem; color: var(--muted); margin-top: 12px; }
.cota-servicos { font-size: .85rem; line-height: 1.6; }
/* Os chips seguem na mesma frase: com display:flex eles viravam bloco e
   empurravam a categoria para a linha de baixo, separando-a do "em 1
   categoria:" que a apresenta. */
.cota-chips { display: inline; }
.cota-chips .chip { margin: 0 2px; vertical-align: baseline; }

/* ── Paginação ──────────────────────────────────────────────────────────── */

.pagination { display: flex; gap: 6px; justify-content: center; align-items: center; padding: 18px 0 6px; flex-wrap: wrap; }
.page-btn {
  min-width: 40px; height: 40px; padding: 0 10px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 9px; border: 1px solid var(--border);
  background: var(--panel); color: var(--text); text-decoration: none; font-size: .85rem;
}
.page-btn.active { background: var(--primary); color: #fff; border-color: var(--primary); }
/* Ponta que não leva a lugar nenhum: continua ocupando o lugar para a barra
   não encolher, mas sem convidar ao toque. */
.page-btn.disabled { opacity: .3; pointer-events: none; }
.link-mais { font-size: .8rem; color: var(--primary); font-weight: 600; text-decoration: none; }
.pagination-resumo { text-align: center; font-size: .78rem; color: var(--muted); padding-bottom: 6px; }
@media (max-width: 430px) {
  /* Nove botões não cabem em 375px: as páginas a duas de distância saem, e
     sobram « ‹ n-1 n n+1 › » — o suficiente para andar e para saltar às pontas. */
  .page-far { display: none; }
}

/* ── Desktop ────────────────────────────────────────────────────────────── */

@media (min-width: 900px) {
  body { padding-bottom: 0; display: flex; }

  .bottom-nav { display: none; }
  .fab { display: none; }

  .side-nav {
    display: flex; flex-direction: column;
    width: var(--sidebar-w); flex-shrink: 0;
    background: var(--sidebar); color: #fff;
    position: fixed; top: 0; bottom: 0; left: 0; z-index: 100;
    overflow-y: auto;
  }
  .side-nav .sidebar-logo { padding: 26px 22px 20px; border-bottom: 1px solid rgba(255,255,255,.06); }
  .side-nav .logotype { font-family: 'Syne', sans-serif; font-size: 1.35rem; font-weight: 800; }
  .side-nav .logotype span { color: var(--accent); }
  .side-nav .sidebar-logo small { display: block; color: rgba(255,255,255,.3); font-size: .7rem; text-transform: uppercase; letter-spacing: .5px; margin-top: 2px; }
  .side-nav nav { flex: 1; padding: 12px 0; }
  .side-nav .nav-item {
    display: flex; align-items: center; gap: 12px;
    padding: 10px 22px; color: rgba(255,255,255,.6);
    text-decoration: none; font-size: .87rem; font-weight: 500;
    border-left: 3px solid transparent; position: relative;
  }
  .side-nav .nav-item .icon { font-size: .95rem; width: 20px; text-align: center; }
  .side-nav .nav-item:hover { background: rgba(255,255,255,.05); color: #fff; }
  .side-nav .nav-item.active { background: rgba(184,33,26,.2); color: #fff; border-left-color: var(--primary); }
  .side-nav .nav-badge { position: static; margin-left: auto; }
  .side-nav .sidebar-footer { padding: 16px 22px; border-top: 1px solid rgba(255,255,255,.06); }

  .app-wrap { margin-left: var(--sidebar-w); flex: 1; min-width: 0; }

  .app-top { background: var(--panel); color: var(--text); border-bottom: 1px solid var(--border); height: 60px; padding: 0 28px; }
  .app-top .logotype { display: none; }
  /* O cabeçalho do desktop é claro: a seta precisa de cor de texto, senão
     fica branca sobre branco. */
  .app-top .back-link { color: var(--text); margin-left: -10px; }
  .app-top .back-link:active { background: var(--bg); }
  .app-top .page-title { font-size: 1.05rem; }
  .app-top .top-action { color: var(--muted); }
  .impersonate-bar { top: 60px; }

  /* 1180px era o teto do card-linha de celular e nunca subiu, então num
     monitor de 1440 sobravam ~250px vazios de cada lado. 1520 e não
     `none`: acima disso a linha do card fica tão larga que o olho perde
     o começo da linha seguinte. */
  .content { padding: 26px 32px; max-width: 1520px; }

  .stats-grid { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 16px; }
  .form-row.col2 { grid-template-columns: 1fr 1fr; }
  .form-row.col3 { grid-template-columns: 1fr 1fr 1fr; }
  .btn-row { justify-content: flex-start; }
  .btn-row .btn { flex: 0 0 auto; }
  .btn-sm { min-height: 36px; }

  /* ── Estoque: a lista larga ───────────────────────────────────────────
   * Uma coluna, e o card cresce em vez de multiplicar.
   *
   * O que havia aqui antes eram duas colunas do card de celular, e isso
   * desperdiçava a largura de duas formas ao mesmo tempo: a miniatura
   * continuava com 92px, e o preço de cada coluna caía numa posição
   * diferente — a lista não podia ser lida em varredura vertical, que é o
   * único jeito de olhar 60 anúncios. Uma coluna com colunas internas de
   * largura fixa dá o contrário: o preço do 12º anúncio cai exatamente onde
   * caiu o do 1º.
   */
  .v-list { grid-template-columns: 1fr; gap: var(--sp-3); }

  .v-card { padding: var(--sp-3) var(--sp-4); gap: var(--sp-4); }

  /* 128x96 e não a foto grande do painel antigo: a 201px de altura cabiam
     dois anúncios por tela, que é o motivo de o painel antigo ser cansativo
     de percorrer. Aqui a foto dobra de área e a linha continua com ~120px,
     então dá para reconhecer o carro E ver o estoque. */
  .v-thumb { width: 128px; height: 96px; border-radius: 10px; }
  .v-thumb-link { border-radius: 10px; }
  .v-thumb.placeholder { font-size: 1.4rem; }

  /* Os marcadores da foto crescem junto. Dimensionados para 92px, numa
     miniatura de 128px eles viravam sujeira ilegível no canto. */
  .v-fotos-num { font-size: .7rem; right: 5px; bottom: 4px; }
  .v-selo      { font-size: .72rem; left: 6px; top: 6px; padding: 2px 7px; }
  .v-pausado   { height: 18px; font-size: .62rem; padding-left: 7px; }

  /* Identificação à esquerda; preço e desempenho em colunas fixas à direita. */
  .v-ident { min-width: 0; }
  .v-metricas { gap: var(--sp-3); }
  .v-controles { justify-content: flex-end; }

  /* A tipografia do card era toda de celular e o breakpoint não encostava em
     nenhuma linha dela. */
  .v-title   { font-size: 1.02rem; -webkit-line-clamp: 1; }
  .v-versao  { font-size: .84rem; -webkit-line-clamp: 1; }
  .v-meta    { font-size: .82rem; margin-top: 3px; }
  .v-price   { font-size: 1.2rem; }
  .v-vistas  { font-size: .78rem; }
  .v-contato { font-size: .84rem; }
  .v-leads   { font-size: .86rem; }

  /* Ações à mostra. No celular elas moram no "⋯" porque não há espaço nem
     ponteiro; aqui há os dois, e pausar um anúncio deixa de custar um toque,
     um diálogo e um segundo toque. O "⋯" continua para o resto (excluir,
     trocar o tipo de anúncio), que não deve estar a um clique de distância. */
  .v-controles { flex-direction: row; gap: var(--sp-1); }
  .so-desktop { display: inline-flex; }

  /* O card responde ao mouse — e responde à vista. A primeira versão mudava
     só o tom da borda e um sopro de sombra: numa lista de cards brancos sobre
     bege, isso é invisível a menos de meio metro da tela. Agora são quatro
     sinais somados, porque um sozinho sempre some em alguma tela: uma faixa
     vermelha na borda esquerda (a mesma marca que o card de e-mail usa para
     "não lido", então não é vocabulário novo), a borda inteira escurecendo,
     sombra de verdade, e o card subindo 1px. */
  .v-card-wrap {
    transition: border-color .14s, box-shadow .14s, transform .14s, opacity .15s;
    border-left: 3px solid var(--border);
  }
  .v-card-wrap:hover {
    border-color: #c8bfb2;
    border-left-color: var(--primary);
    box-shadow: 0 4px 16px rgba(26,18,16,.13);
    transform: translateY(-1px);
  }
  /* O título acompanha: é ele que o clique abre, então é ele que responde. */
  .v-card-wrap:hover .v-title { color: var(--primary); }
  /* Os alvos reais ficam mais fortes que o card, senão o realce do card os
     apaga justamente quando o ponteiro chega neles. */
  .v-card { cursor: pointer; }
  .v-btn-icone:hover { background: #ece7e0; color: var(--text); }
  .v-btn-icone.excluir:hover { background: #fff0f0; color: var(--danger); }
  .v-thumb-link:hover .v-thumb { filter: brightness(1.06); }

  /* Quem prefere menos movimento fica sem o deslocamento; o resto do realce
     continua, porque ele é informação e não enfeite. */
  @media (prefers-reduced-motion: reduce) {
    .v-card-wrap { transition: none; }
    .v-card-wrap:hover { transform: none; }
  }

  /* ── Selo escrito do tipo de anúncio ───────────────────────────────── */

  /* No desktop o chip da foto sai de cena: com o selo escrito ao lado do preço,
     manter os dois seria dizer a mesma coisa duas vezes e sujar a miniatura,
     que aqui é grande o bastante para valer como foto. */
  .v-selo { display: none; }

  .v-card .selo-anuncio { display: inline-flex; margin-bottom: 3px; }

  /* ── Barra de ferramentas da listagem ──────────────────────────────── */

  .estoque-barra { display: flex; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-4); }
  .estoque-toolbar { display: flex; align-items: center; gap: var(--sp-3); flex: 1; min-width: 0; }
  .estoque-toolbar .form-control { font-size: .88rem; padding: 9px 12px; }
  .estoque-toolbar .tb-busca  { flex: 1 1 260px; max-width: 400px; }
  .estoque-toolbar .tb-select {
    width: auto; min-width: 152px; flex: 0 0 auto; padding-right: 30px;
    /* select.form-control zera a seta do sistema (appearance:none) e não põe
       outra no lugar. No sheet o campo é largo e isso passa; numa barra, um
       select sem seta é indistinguível de um campo de texto. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%237a756f' d='M0 0h12L6 8z'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 11px center; background-size: 9px;
  }
  .lista-resumo { flex: 0 0 auto; gap: var(--sp-3); white-space: nowrap; }
  /* Um caminho só para filtrar: com a barra à mostra, o ⚙️ do topo abriria um
     segundo diálogo para dizer a mesma coisa — e os dois podendo discordar. */
  .app-top .top-action[data-sheet="sheet-filtros"] { display: none; }

  /* O sheet vira um diálogo centrado no desktop. */
  .sheet {
    left: 50%; bottom: auto; top: 50%;
    transform: translate(-50%, -46%) scale(.98);
    width: min(520px, 92vw); border-radius: 16px;
    opacity: 0; transition: opacity .18s, transform .18s;
    max-height: 84vh;
  }
  .sheet.open { transform: translate(-50%, -50%) scale(1); opacity: 1; }
  .sheet-handle { display: none; }
}

/* ── Desktop largo: as colunas alinhadas do estoque ─────────────────────── */
/*
 * 1280px não é número redondo escolhido a esmo, é onde a conta fecha: a
 * sidebar leva 240, os respiros do conteúdo 64, e o card precisa de 128 de
 * foto + 164 de ações + 362 de preço/desempenho + os vãos entre eles. Só a
 * partir daí sobra largura para a identificação do veículo.
 *
 * Abaixo disso as colunas fixas não cabem, e o `minmax(0, 1fr)` da coluna da
 * esquerda faz exatamente o que promete: colapsa para ZERO, e o nome do carro
 * DESAPARECE do card. Foi o que aconteceu ao testar em 1000px. Entre 900 e
 * 1279 o card continua grande (foto de 128, corpo maior, ações à mostra), mas
 * com o corpo empilhado como no celular — que é a forma certa nessa largura.
 */
@media (min-width: 1280px) {
  /* Larguras FIXAS, não `auto`: cada card é o seu próprio grid, então coluna
     dimensionada pelo conteúdo cai num x diferente a cada linha — foi o que
     aconteceu na primeira tentativa (o preço caía em 869, 911 e 953px conforme
     o tamanho do nome do carro). Coluna que muda de lugar a cada linha obriga a
     ler card por card, que é justamente o que a lista larga existe para evitar. */
  .v-body { display: grid; grid-template-columns: minmax(0, 1fr) 362px; align-items: center; gap: var(--sp-4); }
  /* align-items: center e não baseline — a coluna da esquerda agora empilha o
     selo escrito sobre o preço, e alinhar pela primeira linha de base deixaria
     os números de desempenho colados no selo em vez de no preço. */
  .v-linha-preco {
    display: grid; grid-template-columns: 170px 180px;
    align-items: center; gap: var(--sp-3); margin-top: 0;
  }
  .v-preco-col { width: 100%; }
  /* .v-price é nowrap: sem o corte, um valor fora de escala (um cadastro com
     zeros a mais, que existe no banco) atravessaria por cima da coluna de
     desempenho. 170px cobrem "R$ 1.500.000,00" com folga; acima disso o corte
     é a degradação certa — o número está errado de qualquer jeito. */
  .v-price { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
  /* O número de botões varia por card (integrador não tem "editar", PF vencido
     não tem "pausar"), e sem largura fixa o "⋯" cairia numa coluna diferente em
     cada linha. Alinhados à direita, ele é sempre o último e sempre no mesmo x. */
  .v-controles { min-width: 164px; }
}

/* Quem prefere menos movimento não recebe as transições do sheet. */
@media (prefers-reduced-motion: reduce) {
  .sheet, .sheet-backdrop, .btn, .toast, .seg-opt { transition: none; }
}

/* ── Contatos (leads) ──────────────────────────────────────────────────────
 * O card segue o do estoque: informação no corpo, e só dois controles-ícone no
 * canto. A primeira versão tinha WhatsApp vermelho, um select de status e dois
 * botões-fantasma por card — doze vezes na tela, tudo disputando atenção, e
 * "Abrir" com o mesmo aspecto de um botão que salvava.
 */
.lead-lista { display: grid; gap: 10px; }

.lead-card {
  position: relative;                 /* âncora do link esticado */
  background: var(--panel);
  border: 1px solid var(--border);
  border-left: 3px solid transparent; /* existe sempre; só troca de cor */
  border-radius: var(--radius);
  padding: 14px 16px;
}
.lead-card[data-lido="0"] { border-left-color: var(--primary); }

.lead-topo { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; }
.lead-nome { flex: 1; min-width: 0; font-weight: 600; color: var(--text); text-decoration: none; }
.lead-quando { font-size: .8rem; color: var(--muted); flex: 0 0 auto; }

/* Mesmo motivo do .v-stretch do estoque: os quatro lados antes do `inset`,
   que o iOS 14.0 e anteriores não conhecem. */
.lead-stretch::after { content: ''; position: absolute; z-index: 1; top: 0; right: 0; bottom: 0; left: 0; inset: 0; }

.lead-veiculo { display: flex; gap: 10px; align-items: center; background: var(--bg); padding: 8px 10px; border-radius: 8px; margin-bottom: 8px; }
.lead-veiculo img { width: 52px; height: 39px; object-fit: cover; border-radius: 5px; flex: 0 0 auto; }
.lead-veiculo-nome { font-size: .84rem; font-weight: 600; line-height: 1.3; }
.lead-veiculo-meta { font-size: .78rem; color: var(--muted); }

/* Acima do link esticado, senão o toque no "ver anúncio" abriria o contato. */
.lead-link { position: relative; z-index: 2; color: var(--muted); }

.lead-msg  { margin: 0 0 8px; font-size: .87rem; line-height: 1.45; color: var(--text); }
.lead-nota { margin: 0 0 8px; font-size: .8rem; color: var(--muted); border-left: 2px solid var(--border); padding-left: 8px; }

/* Borda vermelha = não lido. Era só atributo; virou classe também porque o JS
   liga e desliga no lugar, sem recarregar a lista. */
.lead-card.nao-lido { border-left-color: var(--primary); }
.lead-card.em-quarentena { border-left-color: var(--warning); background: #fffdf8; }
.lead-card.saindo { opacity: 0; transform: translateX(12px); transition: opacity .24s, transform .24s; }

/* Fila de ações do card: um toque, uma consequência. Alvo de 40px, que é o
   mínimo confortável no polegar — a régua vem do estoque. */
.lead-acoes { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.lead-btn {
  width: 40px; height: 40px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--panel); color: var(--text);
  font-size: 1.05rem; line-height: 1; cursor: pointer; text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.lead-btn:active { background: var(--bg); }
/* Os glifos de canal são os mesmos do card do estoque (.ico-zap/.ico-tel), para
   WhatsApp e telefone terem uma cara só no painel inteiro. */
.lead-btn.ico-zap::before, .lead-btn.ico-tel::before, .lead-btn.ico-email::before { width: 18px; height: 18px; }
.lead-btn.ico-zap, .lead-btn.ico-tel, .lead-btn.ico-email { gap: 0; }
/* Telefone à mostra: é o dado que a loja copia quando não quer clicar em nada. */
.lead-contato { margin-left: auto; font-size: .78rem; color: var(--muted); white-space: nowrap; }

.lead-vermais {
  border: 0; background: none; padding: 0; margin: -4px 0 8px;
  font: inherit; font-size: .8rem; font-weight: 600; color: var(--primary); cursor: pointer;
}
.lead-quarentena {
  background: #fff9f0; border: 1px solid #f5daa0; color: var(--warning);
  border-radius: 8px; padding: 10px 12px; font-size: .8rem; line-height: 1.5; margin-bottom: 10px;
}
/* <button> vira linha de menu igual às <a> irmãs: sem o reset, o navegador
   desenha borda e fundo próprios e a fileira fica desalinhada. */
button.sheet-item {
  width: 100%; background: none; border: 0;
  border-bottom: 1px solid var(--border);
  text-align: left; font: inherit; cursor: pointer;
}
