/**
 * vitrine.css — folha única da vitrine pública (PRD-UV-002, Componente 11).
 * Consumida por publico/paginas/home.php, anuncio.php, termos.php, privacidade.php,
 * erro-404.php e pelo <head> emitido por publico/helpers.php::cabecalhoPublico().
 *
 * Esta task (TASK-002) entrega só o esqueleto: tokens, reset mínimo e as regras
 * transversais (usadas por mais de uma página). As seções demarcadas abaixo são
 * preenchidas pelas tasks de front que rodam na mesma onda — cada uma só ACRESCENTA
 * o próprio bloco, sem reescrever o que já existe aqui.
 */

:root{
  /* PRD-UV-009 — identidade "Carmim Noturno": :root repontado para derivar dos tokens
     oficiais de assets/identidade/tokens.css (carregado ANTES desta folha). */

  /* aliases 1:1 — mesmo papel semântico dos dois lados */
  --fundo: var(--preto);
  --fundo-card: var(--superficie);
  --borda: var(--hairline);
  --texto: var(--marfim);
  --texto-sec: var(--greige);

  /* WhatsApp: cor de marca de TERCEIRO (reconhecimento do app), fora da paleta oficial.
     Não deriva de tokens.css. Mesmo valor de hoje. */
  --whats:#166534;
  --whats-texto:#f5f1ea;

  /* --dourado e --dourado-texto: REMOVIDOS. O hex antigo acumulava 5 papéis semânticos que os
     tokens oficiais distinguem (link, borda de hover, CTA sólido, valor, selo Ouro). Um alias
     único faria o carmim inundar a tela, o que a IDENTIDADE.md proíbe. Ver tabela de
     mapeamento token a token na seção Frontend / Interface da PRD Técnica.
     --erro e --erro-fundo: REMOVIDOS por COLISÃO DE NOME com tokens.css (ver Achado 2). Não
     redeclarar, não aliasar aqui — os "var(--erro)" espalhados pelo arquivo resolvem contra
     tokens.css sozinhos, por cascata. */
}

/* ===== Reset mínimo (comum às três telas da maquete) ===== */
*{box-sizing:border-box;}
body{margin:0;background-color:var(--fundo);
     background-image:radial-gradient(60% 40% at 50% 0%, rgba(143,29,59,.10), transparent 70%);
     background-repeat:no-repeat;color:var(--texto);font-family:var(--f-corpo);
     min-height:100vh;}
a{color:var(--carmim-texto);}

/* Anel de foco único da casca (R1) — substitui os três outline ad-hoc que existiam em
   .seletor-cidade select:focus, .btn-confirmar:focus e .btn-sair:focus. Fica junto do reset,
   no topo do arquivo, para que qualquer bloco posterior herde por cascata. Contraste
   champagne/superfície = 9,70:1. */
a:focus-visible, button:focus-visible, select:focus-visible, [tabindex]:focus-visible{
  outline:2px solid var(--champagne); outline-offset:3px; border-radius:2px;
}

/* Kill-switch central de prefers-reduced-motion (PRD-UV-011, TASK-001, DT-015) — ÚNICO ponto
   do arquivo que trata essa preferência; nenhum componente implementa guard próprio, aqui
   cobre os cinco. Usa .01ms, NUNCA 0: duração zero pode não disparar transitionend/
   animationend em alguns motores, e a TASK-006 (painel de cidade) depende desse evento para
   fechar — 0 aqui criaria um travamento silencioso lá. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;
    animation-iteration-count:1!important;
    transition-duration:.01ms!important;
    scroll-behavior:auto!important;
  }
}

/* ===== Regras transversais (Componente 11 — "Adições necessárias") ===== */

/* imagem real cobrindo o placeholder enquanto carrega; o placeholder fica atrás
   e reaparece sozinho quando o onerror esconde o <img> */
.card-anuncio .foto img, .card-destaque .foto img, .foto-principal img {
  width:100%; height:100%; object-fit:cover; position:relative; z-index:1;
}
/* PRD-UV-009 (Componente 7): decisão do DT-008 (monograma "E") SUPERADA pelo documento
   canônico da identidade — o placeholder passa a ser o pino da marca (docs/identidade/
   logo-pino.svg), em marca d'água discreta sobre o fundo quente do card/galeria. A cor
   agora vem do `fill` literal do próprio SVG (ver publico/partials/card-anuncio.php e
   publico/paginas/anuncio.php) — sem `color` aqui (--dourado foi removido do :root).
   aspect-ratio trava a proporção 120:140 do viewBox do pino sem depender do atributo
   height do SVG. Registro formal do débito superado: TASK-009 desta PRD.
   Os quatro pontos de uso (card-destaque, card-anuncio, galeria .foto-principal,
   .miniaturas button) tinham width/height/opacity próprios calibrados para o monograma
   quadrado antigo — removidos nesta task para que os 46%/.14 daqui cheguem visíveis em
   todos eles (Teste 2 do packet: "marca d'água discreta (14%)... ocupando ~46% da
   largura"), com o contêiner pai (position:relative em todos) centralizando via inset:0. */
.foto-placeholder { position:absolute; inset:0; margin:auto; width:46%; aspect-ratio:120/140;
                    opacity:.14; z-index:0; }
.gate-travado { overflow:hidden; }

/* O gate nasce oculto: quem revela é o JS. Sem JS ele nunca aparece. */
#overlay-gate[hidden] { display:none; }

/* Botão de contato antes do número ser montado: precisa PARECER pendente —
   SEM cair abaixo do contraste mínimo. Com opacity .55 o par --whats-texto sobre
   --whats, composto sobre --fundo-card, cai para ~3.49:1 (abaixo de 4.5:1) justamente
   no CTA que gera a receita. O corte calculado é .71; usamos .8 (~5.08:1). */
.btn-contato[aria-disabled="true"] { opacity:.8; cursor:progress; }

/* ===== TASK-005 — Home por cidade (cabeçalho/seletor, destaques, grid, paginação,
   texto institucional, estado vazio) — mockup/home-cidade.html ===== */

/* ===== Header ===== */
header.topo{border-bottom:1px solid var(--borda);}
.topo-inner{max-width:1200px;margin:0 auto;padding:16px 20px;display:flex;align-items:center;
            justify-content:space-between;gap:16px;flex-wrap:wrap;}
/* PRD-UV-009 — wordmark em dois pesos (publico/partials/wordmark.php).
   PRD-UV-011 (TASK-002) — lockup horizontal: .wordmark vira o contêiner em LINHA (pino +
   bloco de texto); o antigo flex-direction:column migrou para .wordmark-texto, que empilha
   .wordmark-elas/.wordmark-resto. gap:15px = metade da largura do ícone (30px), regra do
   IDENTIDADE.md — NÃO os 14px da demo desatualizada do brandbook (ver Notas Técnicas da
   TASK-002). .pino-marca não herda .foto-placeholder (position:absolute;inset:0, outro
   contexto) — dimensão própria, fixa. */
.wordmark{display:inline-flex;align-items:center;gap:15px;text-decoration:none;
          white-space:nowrap;}
.wordmark-texto{display:inline-flex;flex-direction:column;gap:3px;}
.pino-marca{width:30px;aspect-ratio:120/140;flex:0 0 auto;}
.wordmark-elas{font-family:var(--f-display);font-weight:700;font-size:1.05rem;color:var(--marfim);}
.wordmark-resto{font-family:var(--f-display);font-weight:400;font-size:.52rem;
    letter-spacing:.32em;color:var(--carmim-texto);text-transform:uppercase;}
.seletor-cidade{position:relative;}
.seletor-cidade form{margin:0;display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
.seletor-cidade select{background:var(--fundo-card);color:var(--texto);
    border:1px solid var(--borda-controle);
    border-radius:2px;padding:10px 14px;font-size:.9rem;min-height:44px;min-width:180px;
    cursor:pointer;}
/* TASK-006 — painel de cidade em <dialog>: o gatilho novo se SOBREPÕE ao select (que continua
   a interface real sem JS/sem suporte a <dialog>), nunca o substitui. */
.seletor-cidade.painel-cidade-ativo select{pointer-events:none;}
.cidade-texto{font-size:.9rem;color:var(--texto-sec);padding:10px 4px;min-height:44px;
              display:flex;align-items:center;}

main{max-width:1200px;margin:0 auto;padding:24px 20px 60px;}

/* DT-009: linha de proposta de valor — discreta, texto corrido (não é hero), acima da faixa
   de destaques. Copy AINDA NÃO aprovada pelo Charles (ver relatório do LOTE-002). */
.faixa-valor{font-size:.85rem;color:var(--texto-sec);text-align:center;margin:0 0 28px;
    padding-bottom:16px;border-bottom:1px solid var(--borda);}
.faixa-valor strong{color:var(--texto);font-weight:600;}

/* ===== Destaques (faixa) ===== */
.secao-titulo{font-family:var(--f-display);font-size:1rem;font-weight:600;letter-spacing:.03em;
              color:var(--texto-sec);text-transform:uppercase;margin:0 0 14px;}
.faixa-destaques{display:flex;gap:14px;overflow-x:auto;padding-bottom:10px;margin-bottom:36px;
                  scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;}
.faixa-destaques::-webkit-scrollbar{height:6px;}
.faixa-destaques::-webkit-scrollbar-thumb{background:var(--borda);border-radius:3px;}
.card-destaque{flex:0 0 200px;scroll-snap-align:start;background:var(--fundo-card);
               border:1px solid var(--borda);border-radius:3px;overflow:hidden;text-decoration:none;
               color:var(--texto);display:block;}
/* PRD-UV-009 — "Card e galeria — fundo quente": duas camadas, radial de champagne a 10% no
   canto superior esquerdo sobre um linear escuro quente. Os stops #2a1c1f/#160f10 são hex
   literais previstos textualmente na PRD Técnica (composição do gradiente, não tokens da
   paleta) — substituem o par cinza-azulado antigo (#2a2d33/#1a1c21). O override de
   width/height/opacity de .foto-placeholder que existia aqui (56px/.4) foi removido: os
   46%/.14 do pino (Componente 7) agora chegam aqui via a regra base, sem duplicar valor. */
.card-destaque .foto{height:260px;
    background:radial-gradient(70% 60% at 0% 0%, rgba(217,185,138,.10), transparent 70%),
               linear-gradient(160deg,#2a1c1f,#160f10 70%);
    position:relative;display:flex;align-items:center;justify-content:center;}
/* .selo-destaque e .selo-plano vivem dentro de .selos-foto (bloco mais abaixo, correcao do
   achado C1 do gate de UX) — aqui so a aparencia de cada pilula; a posicao fica no container. */
.selo-destaque{background:var(--carmim);color:var(--marfim);
               font-size:.68rem;font-weight:700;padding:3px 8px;border-radius:4px;letter-spacing:.03em;}
/* DT-009: selo "verificada" — fica FORA do container dos selos de destaque/plano, no canto
   direito. O container reserva espaco para ele (.selos-foto tem right:40px — PRD-UV-009: o
   disco cresceu de 22px pra 24px, e o respiro cresceu 4px junto, na mesma edição, pra não
   reabrir a colisão medida na UV-002), entao os tres selos convivem sem sobreposicao em
   qualquer largura. */
.selo-verificada{position:absolute;top:8px;right:8px;width:24px;height:24px;border-radius:50%;
    background:var(--fundo-card);color:var(--champagne);border:1px solid var(--champagne);
    display:flex;align-items:center;justify-content:center;z-index:2;}
.selo-verificada svg{width:13px;height:13px;}
.card-destaque .info{padding:10px 12px 12px;}
/* DT-007: nowrap+ellipsis cortava nomes de 2-3 componentes (padrão real das anunciantes) já
   no primeiro nome. 2 linhas com line-clamp resolve sem esconder informação; min-height
   reserva o espaço das 2 linhas mesmo quando o nome cabe em 1, evitando cards de altura
   desigual na mesma faixa/grid. */
/* PRD-UV-009: nome do card passa pra Bodoni Moda — um dos três lugares em que a display é
   permitida na vitrine (os outros são h1.titulo-anuncio/h2.secao-titulo e o wordmark). Não
   mexe em -webkit-line-clamp/min-height/@media (DT-007 depende deles). */
.card-destaque .nome{font-family:var(--f-display);font-size:.92rem;font-weight:600;margin:0;
                      line-height:1.25;min-height:2.5em;
                      display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
                      overflow:hidden;}
/* O card reusa a MESMA estrutura interna do grid (linha-nome/idade/bairro/cache) — a
   maquete original desenhava um "meta" compacto só para a faixa, mas a task pede um único
   partial para os dois lugares (ver publico/partials/card-anuncio.php), então aqui só
   reduzimos a escala das mesmas classes em vez de duplicar o card em outro formato. */
.card-destaque .linha-nome{display:flex;justify-content:space-between;align-items:flex-start;gap:6px;}
.card-destaque .idade{font-size:.78rem;color:var(--texto-sec);white-space:nowrap;}
.card-destaque .bairro{font-size:.78rem;color:var(--texto-sec);margin:2px 0 4px;}
.card-destaque .cache{font-size:.85rem;font-weight:700;color:var(--champagne-texto);margin:0;}
.card-destaque .cache.combinar{color:var(--texto-sec);font-weight:600;font-size:.78rem;}

/* ===== Grid ===== */
.grid-anuncios{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:16px;}
.card-anuncio{background:var(--fundo-card);border:1px solid var(--borda);border-radius:3px;
              overflow:hidden;text-decoration:none;color:var(--texto);display:block;
              transition:border-color var(--dur-micro) var(--ease-marca),
                         transform var(--dur-micro) var(--ease-marca);}
/* PRD-UV-011 (TASK-004): hover só em dispositivo que TEM hover de verdade e ponteiro fino —
   sem isso o touchscreen mantém o estado "grudado" depois do toque, e o público é
   majoritariamente mobile. A regra inteira migrou pra cá (não só a elevação nova). */
@media (hover:hover) and (pointer:fine){
  .card-anuncio:hover{border-color:var(--carmim-claro);transform:translateY(-2px);}
}
/* PRD-UV-009 — fundo quente (mesma composição de .card-destaque .foto, ver comentário lá).
   Override de width/height/opacity de .foto-placeholder (48px/.35) removido pelo mesmo
   motivo. */
.card-anuncio .foto{aspect-ratio:3/4;
    background:radial-gradient(70% 60% at 0% 0%, rgba(217,185,138,.10), transparent 70%),
               linear-gradient(160deg,#2a1c1f,#160f10 70%);
    display:flex;align-items:center;justify-content:center;position:relative;}
.card-anuncio .info{padding:12px 14px 14px;}
.card-anuncio .linha-nome{display:flex;justify-content:space-between;align-items:flex-start;gap:6px;}
/* DT-007: mesmo critério do .card-destaque .nome — 2 linhas via line-clamp em vez de cortar
   com "…", altura reservada para não desnivelar os cards do grid.
   PRD-UV-009: mesma família display do .card-destaque .nome (ver comentário lá). */
.card-anuncio .nome{font-family:var(--f-display);font-size:1rem;font-weight:600;margin:0;
                     line-height:1.25;min-height:2.5em;
                     display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
                     overflow:hidden;}
.card-anuncio .idade{font-size:.85rem;color:var(--texto-sec);white-space:nowrap;}
.card-anuncio .bairro{font-size:.8rem;color:var(--texto-sec);margin:2px 0 8px;}
.card-anuncio .cache{font-size:.92rem;font-weight:700;color:var(--champagne-texto);margin:0;}
.card-anuncio .cache.combinar{color:var(--texto-sec);font-weight:600;font-size:.85rem;}

/* ===== Paginação ===== */
.paginacao{display:flex;justify-content:center;gap:8px;margin-top:32px;flex-wrap:wrap;}
.paginacao a, .paginacao span{min-width:44px;min-height:44px;display:flex;align-items:center;
    justify-content:center;border:1px solid var(--borda);border-radius:2px;text-decoration:none;
    color:var(--texto-sec);font-size:.9rem;}
.paginacao a:hover{border-color:var(--carmim-claro);color:var(--carmim-texto);}
.paginacao .atual{background:var(--carmim);color:var(--marfim);border-color:var(--carmim);
                   font-weight:700;}

/* ===== Texto institucional ===== */
.texto-institucional{margin-top:48px;padding-top:32px;border-top:1px solid var(--borda);
    color:var(--texto-sec);font-size:.9rem;line-height:1.7;max-width:760px;}
.texto-institucional h2{color:var(--texto);font-size:1.05rem;margin:0 0 12px;font-weight:600;}

/* ===== Estado vazio ===== */
.estado-vazio{text-align:center;padding:64px 20px;border:1px dashed var(--borda);border-radius:3px;
              color:var(--texto-sec);}
.estado-vazio svg{width:44px;height:44px;opacity:.3;margin-bottom:16px;}
.estado-vazio h2{color:var(--texto);font-size:1.1rem;margin:0 0 8px;}
.estado-vazio p{margin:0 0 20px;font-size:.9rem;}
.estado-vazio .lista-cidades{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;}
.estado-vazio .lista-cidades a{border:1px solid var(--borda);border-radius:2px;padding:10px 16px;
    text-decoration:none;color:var(--texto);font-size:.88rem;min-height:44px;display:flex;
    align-items:center;}
.estado-vazio .lista-cidades a:hover{border-color:var(--carmim-claro);color:var(--carmim-texto);}

/* ===== Rodapé ===== */
footer{border-top:1px solid var(--borda);margin-top:40px;}
.rodape-inner{max-width:1200px;margin:0 auto;padding:24px 20px;display:flex;gap:20px;
              flex-wrap:wrap;justify-content:space-between;align-items:center;color:var(--texto-sec);
              font-size:.82rem;}
.rodape-links{display:flex;gap:18px;flex-wrap:wrap;}
.rodape-links a{color:var(--texto-sec);text-decoration:none;}
.rodape-links a:hover{color:var(--carmim-texto);}

@media (max-width:600px){
  .grid-anuncios{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px;}
  .card-destaque{flex:0 0 150px;}
  .card-destaque .foto{height:200px;}
  main{padding:18px 14px 48px;}
  .texto-institucional{max-width:100%;}
  /* DT-007: card de 150px ainda corta o nome mais longo do seed ("Camila Duarte Alves")
     em 2 linhas — 3 linhas resolve sem precisar reduzir a fonte. */
  .card-destaque .nome, .card-anuncio .nome{-webkit-line-clamp:3;min-height:3.75em;}
}

/* ===== TASK-006 — Página do anúncio (trilha, galeria, cachê, contato, características,
   dados físicos, descrição, sticky mobile) — mockup/anuncio-detalhe.html ===== */

.trilha{font-size:.8rem;color:var(--texto-sec);margin:0 0 18px;}
.trilha a{color:var(--texto-sec);text-decoration:none;}
.trilha a:hover{color:var(--carmim-texto);}

.layout{display:grid;grid-template-columns:1.1fr .9fr;gap:32px;align-items:start;}

/* DT-006 (achado A2 do review do LOTE-002): o teto de altura da galeria só faz sentido no
   layout de 2 colunas — é aí que a foto alta cria o vazio ao lado da coluna de infos curta.
   Isolado num min-width para não afetar telas baixas em layout de 1 coluna (celular em
   paisagem, janela de desktop pouco alta), onde o aspect-ratio:3/4 sozinho já é adequado. */
@media (min-width:801px){
  .galeria .foto-principal, .galeria-vazia{max-height:calc(100vh - 170px);}
}

/* Gate de UX do LOTE-002 (michelangelo, achado 🔴 C1): sem teto no mobile, aspect-ratio:3/4
   na largura cheia do container empurra título/cachê/selo "verificada" para trás da barra
   fixa de contato (.sticky-mobile, ~127-140px) em telas baixas comuns (iPhone SE 375×667,
   iPhone 12/13 390×844, Android 360×800) — medido com getBoundingClientRect, sem rolar.
   min(52vh, 100vh - 300px) reserva espaço para header+breadcrumb (~118px) e para o título/
   selo ficarem acima da barra fixa nesses tamanhos, sem encolher demais em telas altas. */
@media (max-width:800px){
  .galeria .foto-principal, .galeria-vazia{max-height:min(38vh,calc(100vh - 340px));}
}

/* ----- Galeria ----- */
/* DT-006: aspect-ratio:3/4 sozinho rende ~827px de altura numa coluna de ~620px (1.1fr de
   1200px) — bem mais alto que a coluna de infos de um anúncio do plano grátis (1 foto,
   poucas/nenhuma característica, "Sobre" curto), sobrando um vazio grande abaixo do "Sobre"
   no desktop. max-height trava a foto num teto ligado ao viewport (em vez de deixar a
   galeria crescer livre pelo aspect-ratio), sacrificando um pouco do enquadramento 3:4 via
   o object-fit:cover que a <img> já usa — não depende de quanto a Onda 2 vai aumentar a
   coluna de infos (o plano grátis continua sendo o caso mínimo para sempre). No anúncio
   completo (mais características/dados físicos), a coluna de infos pode passar o teto da
   foto sem quebra — align-items:start deixa cada coluna crescer pelo próprio conteúdo. A
   regra não mexe em HTML/ordem — só se aplica no layout de 2 colunas (media query abaixo,
   ≥801px); no mobile (1 coluna) a foto volta a crescer só pelo aspect-ratio, sem depender de
   altura de viewport (celular em paisagem/tela baixa não tinha sido testado com o teto). */
/* PRD-UV-009 — fundo quente (mesma composição de .card-destaque .foto). Override de
   width/height/opacity de .foto-placeholder (72px/.6) removido pelo mesmo motivo dos cards. */
.galeria .foto-principal{aspect-ratio:3/4;
    background:radial-gradient(70% 60% at 0% 0%, rgba(217,185,138,.10), transparent 70%),
               linear-gradient(160deg,#2a1c1f,#160f10 70%);
    border-radius:3px;border:1px solid var(--borda);position:relative;overflow:hidden;
    margin-bottom:10px;}
/* PRD-UV-011 (TASK-005) — crossfade da troca de miniatura: assets/publico/vitrine.js marca
   #foto-principal-img com .trocando ANTES de trocar o src e remove no evento `load`/`error`
   nativo da própria <img> (sem preloader, sem novo <Image>). --dur-base/--ease-marca vêm da
   TASK-001, mesmo par usado na entrada do gate (ambos "superfície maior", ver tokens.css). */
#foto-principal-img{transition:opacity var(--dur-base) var(--ease-marca);}
#foto-principal-img.trocando{opacity:.35;}
.miniaturas{display:flex;gap:8px;overflow-x:auto;padding-bottom:4px;}
/* PRD-UV-009: mesmo fundo quente das fotos acima (contrato explícito: ".miniaturas button
   usa o mesmo par" de cinzas antigos, então sai junto). */
.miniaturas button{flex:0 0 64px;height:80px;min-width:44px;min-height:44px;
    background:radial-gradient(70% 60% at 0% 0%, rgba(217,185,138,.10), transparent 70%),
               linear-gradient(160deg,#2a1c1f,#160f10 70%);border:2px solid var(--borda);
    border-radius:2px;cursor:pointer;padding:0;position:relative;overflow:hidden;}
.miniaturas button.ativa{border-color:var(--carmim-claro);}
.miniaturas button img{width:100%;height:100%;object-fit:cover;position:relative;z-index:1;}

/* DT-006: mesmo teto de altura da foto principal (aplicado só no layout de 2 colunas, ver
   media query ≥801px abaixo) — sem foto nenhuma aprovada o vazio ao lado da coluna de infos
   seria ainda maior que com 1 foto.
   PRD-UV-009: mesmo fundo quente das outras três regras equivalentes (ver comentário em
   .galeria .foto-principal) — troca o var(--fundo-card) plano de antes. */
.galeria-vazia{aspect-ratio:3/4;
    background:radial-gradient(70% 60% at 0% 0%, rgba(217,185,138,.10), transparent 70%),
               linear-gradient(160deg,#2a1c1f,#160f10 70%);
    border:1px dashed var(--borda);
    border-radius:3px;display:flex;flex-direction:column;align-items:center;justify-content:center;
    gap:10px;color:var(--texto-sec);text-align:center;padding:20px;}
/* PRD-UV-009: decisão do DT-008 (monograma) SUPERADA — mesmo pino de marca dos outros
   pontos de fallback. Sem a classe .foto-placeholder (não há <img> por trás aqui) — cor
   agora vem do `fill` literal do SVG, sem `color` (--dourado foi removido do :root). */
.galeria-vazia svg{width:56px;height:56px;opacity:.14;}
.galeria-vazia p{margin:0;font-size:.85rem;}

/* ----- Info / cachê ----- */
.titulo-anuncio{font-family:var(--f-display);font-size:1.4rem;font-weight:700;margin:0 0 6px;}
/* DT-009: selo "verificada" perto do título — dado exposto só via publico/consultas.php
   (anuncio.php não ganhou consulta nova a `anunciantes`).
   PRD-UV-009: cor champagne-texto (11,48:1). Sem text-transform:uppercase — divergência
   deliberada do .cn-badge-verificada do brandbook: a frase é longa e caixa alta com
   tracking ficaria pesada. */
.selo-verificada-anuncio{display:inline-flex;align-items:center;gap:6px;font-size:.8rem;
    font-weight:600;color:var(--champagne-texto);margin:0 0 10px;}
.selo-verificada-anuncio svg{width:15px;height:15px;flex:0 0 auto;}
.subinfo{color:var(--texto-sec);font-size:.9rem;margin:0 0 18px;}
.cache-box{background:var(--fundo-card);border:1px solid var(--borda);border-radius:3px;
    padding:16px 18px;margin-bottom:20px;}
.cache-box .rotulo{font-size:.72rem;color:var(--greige);text-transform:uppercase;
    letter-spacing:.1em;font-weight:500;margin:0 0 4px;}
.cache-box .valor{font-size:1.5rem;font-weight:700;color:var(--champagne-texto);margin:0;}
.cache-box .valor.combinar{color:var(--texto);font-size:1.1rem;}
.cache-box .aceita-cartao{display:inline-flex;align-items:center;gap:6px;margin-top:8px;
    font-size:.8rem;color:var(--texto-sec);}

/* ----- Contato ----- */
/* PRD-UV-009 — radius R2 (containers vão a 3px, mesmo padrão de .dialogo/.estado-vazio/
   .cache-box/.dado-item já nesta folha). */
.caixa-contato{background:var(--fundo-card);border:1px solid var(--borda);border-radius:3px;
    padding:18px;margin-bottom:24px;}
.caixa-contato h2{font-size:.9rem;text-transform:uppercase;letter-spacing:.04em;
    color:var(--texto-sec);margin:0 0 14px;font-weight:600;}
.botoes-contato{display:flex;flex-direction:column;gap:10px;}
.btn-contato{min-height:48px;border-radius:2px;border:0;display:flex;align-items:center;
    justify-content:center;gap:10px;font-weight:700;font-size:.95rem;text-decoration:none;
    cursor:pointer;}
.btn-contato svg{width:20px;height:20px;flex:0 0 auto;}
.btn-whatsapp{background:var(--whats);color:var(--whats-texto);}
/* R8 — secundário: contorno já no estado padrão (não mais "borda neutra até o hover"). */
/* PRD-UV-011 (TASK-004): motion nos três estados que mudam de cor no :hover. .btn-whatsapp
   fica de fora — não tem :hover declarado hoje, transição sem mudança de estado não anima
   nada, e criar um hover pra ele está fora do escopo fechado com o dono. */
.btn-telefone{background:transparent;color:var(--texto);border:1px solid var(--carmim-claro);
    transition:background-color var(--dur-micro) var(--ease-marca),
               border-color var(--dur-micro) var(--ease-marca),
               color var(--dur-micro) var(--ease-marca);}
.btn-telefone:hover{background:var(--superficie-alta);border-color:var(--champagne);}
.aviso-noscript{color:var(--texto-sec);font-size:.82rem;margin:6px 0 0;}

.aviso-sem-contato{background:var(--erro-fundo);border:1px solid var(--erro);color:var(--erro-texto);
    border-radius:3px;padding:14px 16px;font-size:.85rem;display:flex;gap:10px;align-items:flex-start;}
.aviso-sem-contato svg{width:20px;height:20px;flex:0 0 auto;margin-top:1px;}
.aviso-sem-contato p{margin:0;color:var(--texto);}

/* ----- Características / dados físicos / descrição ----- */
.grupo-caract{margin-bottom:22px;}
.grupo-caract h2{font-size:.72rem;text-transform:uppercase;letter-spacing:.1em;
    color:var(--greige);margin:0 0 10px;font-weight:500;}
.lista-tags{display:flex;flex-wrap:wrap;gap:8px;}
.lista-tags span{background:var(--fundo-card);border:1px solid var(--borda);border-radius:20px;
    padding:6px 14px;font-size:.83rem;color:var(--texto);}

.dados-fisicos{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;margin-bottom:24px;}
.dado-item{background:var(--fundo-card);border:1px solid var(--borda);border-radius:3px;
    padding:12px 14px;}
.dado-item .rotulo{font-size:.72rem;color:var(--greige);text-transform:uppercase;
    letter-spacing:.1em;font-weight:500;margin:0 0 2px;}
.dado-item .valor{font-size:.95rem;margin:0;font-weight:600;}

.descricao{color:var(--texto);font-size:.92rem;line-height:1.7;margin-bottom:24px;}
.descricao h2{font-size:.72rem;text-transform:uppercase;letter-spacing:.1em;
    color:var(--greige);margin:0 0 10px;font-weight:500;}
.descricao p{margin:0;}

/* ----- Sticky mobile ----- */
.sticky-mobile{display:none;}

@media (max-width:800px){
  .layout{grid-template-columns:1fr;}
  /* Correção pós-michelangelo (auditoria pós-execução, achado C6): a barra sticky de
     contato mede ~127px reais (2 botões de 48px + gap 10px + padding 10px), mais
     env(safe-area-inset-bottom) em telas com notch — 110px de padding-bottom deixava o
     <footer> permanentemente coberto (rodapé inalcançável por toque no fim do scroll, em
     TODO carregamento mobile do anúncio com contato, que é o caminho feliz do produto).
     140px cobre a altura real medida + margem de segurança para variação de fonte/idioma
     do rótulo; footer também ganha a mesma margem, como segunda camada de proteção
     independente de acerto de pixel (mesmo que a altura da barra mude no futuro). */
  main{padding-bottom:calc(140px + env(safe-area-inset-bottom));}
  .sticky-mobile{display:flex;position:fixed;bottom:0;left:0;right:0;background:var(--fundo-card);
      border-top:1px solid var(--borda);padding:10px 14px;gap:10px;z-index:500;
      padding-bottom:calc(10px + env(safe-area-inset-bottom));}
  .sticky-mobile .btn-contato{flex:1;min-height:48px;}
  .sticky-mobile .aviso-sem-contato{flex:1;padding:10px 12px;}
  /* .sticky-mobile vem ANTES de <footer> no documento (publico/paginas/anuncio.php) só
     quando o anúncio tem contato — o combinador de irmão escopa a margem extra só para esse
     caso, sem empurrar o rodapé pra baixo à toa em home/termos/privacidade/anúncio-sem-
     contato, onde não existe barra fixa nenhuma cobrindo nada. */
  .sticky-mobile ~ footer{margin-bottom:calc(140px + env(safe-area-inset-bottom));}
}

/* ===== TASK-007 — Gate 18+ e páginas legais (overlay, diálogo, prosa institucional) —
   mockup/gate-18.html ===== */

/* ----- Overlay do gate ----- */
/* PRD-UV-009: fundo trocado pelo quase-preto oficial (--preto #120d0e) com alfa — valor
   literal previsto na PRD Técnica, não um token (o overlay não é uma superfície da paleta,
   é uma camada de bloqueio visual sobre a página). */
.overlay{position:fixed;inset:0;background:rgba(18,13,14,.88);z-index:1000;
         display:flex;align-items:center;justify-content:center;padding:20px;}
.dialogo{width:100%;max-width:440px;background:var(--fundo-card);border:1px solid var(--borda);
         border-radius:3px;padding:32px 28px;text-align:center;}
/* PRD-UV-011 (TASK-005) — entrada animada do overlay, só CSS. @keyframes (não transition):
   o disparo é o removeAttribute('hidden') que JÁ EXISTE em gate-maioridade.php:88 — o
   elemento sai direto de display:none, sem frame intermediário pra uma transition
   interpolar. Nenhuma linha de lógica sai do <script> inline do gate (proibição da task); o
   FECHAMENTO continua removeChild() síncrono, sem animação (decisão de produto — animar a
   saída exigiria atrasar a remoção e duplicar o guard de prefers-reduced-motion em JS, num
   componente protegido pelos specs adversariais 7c/7d). O kill-switch central de
   prefers-reduced-motion (topo do arquivo) já zera animation-duration para as duas regras
   abaixo — nenhum guard próprio aqui. */
@keyframes gate-entrada-overlay{from{opacity:0;}to{opacity:1;}}
@keyframes gate-entrada-dialogo{from{opacity:0;transform:translateY(8px);}to{opacity:1;transform:translateY(0);}}
#overlay-gate:not([hidden]){animation:gate-entrada-overlay var(--dur-base) var(--ease-marca);}
#overlay-gate:not([hidden]) .dialogo{animation:gate-entrada-dialogo var(--dur-base) var(--ease-marca);}
.icone-alerta{width:48px;height:48px;margin:0 auto 16px;color:var(--champagne);}
.dialogo h1{font-size:1.25rem;margin:0 0 12px;letter-spacing:.03em;}
.dialogo p.aviso{color:var(--texto-sec);font-size:.9rem;line-height:1.6;margin:0 0 22px;}
.badge-adulto{display:inline-block;border:1px solid var(--erro);color:var(--erro-texto);
    font-size:.72rem;font-weight:700;letter-spacing:.05em;padding:4px 10px;border-radius:4px;
    margin-bottom:18px;text-transform:uppercase;}
.acoes-gate{display:flex;flex-direction:column;gap:10px;margin-bottom:20px;}
/* PRD-UV-011 (TASK-004): .btn-confirmar/.btn-sair pertencem ao gate 18+, mas a transição é
   só de cor — não toca [hidden]/.gate-travado nem lógica nenhuma, decisão registrada na PRD
   Técnica (não ameaça os specs 7c/7d do gate). */
.btn-confirmar{min-height:48px;background:var(--carmim);color:var(--marfim);border:0;
    border-radius:2px;font-weight:700;font-size:.98rem;cursor:pointer;
    transition:background-color var(--dur-micro) var(--ease-marca),
               border-color var(--dur-micro) var(--ease-marca),
               color var(--dur-micro) var(--ease-marca);}
.btn-confirmar:hover{background:var(--carmim-escuro);}
.btn-sair{min-height:48px;background:transparent;color:var(--texto-sec);border:1px solid var(--borda);
    border-radius:2px;font-weight:600;font-size:.92rem;cursor:pointer;
    transition:background-color var(--dur-micro) var(--ease-marca),
               border-color var(--dur-micro) var(--ease-marca),
               color var(--dur-micro) var(--ease-marca);}
.btn-sair:hover{border-color:var(--erro);color:var(--erro-texto);}
.links-legais{font-size:.78rem;color:var(--texto-sec);margin:0;}
.links-legais a{color:var(--texto-sec);text-decoration:underline;}
.links-legais a:hover{color:var(--carmim-texto);}
.links-legais span.sep{margin:0 8px;opacity:.4;}

@media (max-width:400px){
  .dialogo{padding:26px 20px;}
}

/* ----- Aviso <noscript>: faixa NO FLUXO da página, nunca position:fixed cobrindo o
   viewport — sem JS o visitante lê o aviso e navega normalmente (não é um segundo gate). ----- */
.faixa-noscript{background:var(--erro-fundo);border-bottom:1px solid var(--erro);color:var(--texto);
    padding:12px 20px;font-size:.85rem;line-height:1.6;text-align:center;}
.faixa-noscript .badge-adulto{margin:0 8px 0 0;vertical-align:middle;}
.faixa-noscript a{color:var(--carmim-texto);}

/* ----- Páginas legais (termos.php / privacidade.php): reusam .titulo-anuncio/.subinfo
   (Componente 13) para o título e a data de atualização, e .texto-institucional
   (Componente 12) para o corpo — nenhuma classe nova de tipografia precisou ser criada. ----- */

/* ===== TASK-009 — Selo de plano na vitrine (Componente de UI 4, PRD-UV-005) =====
   Correção DT (achado C1, REVIEW-michelangelo pós-execução): a versão original colocava
   .selo-destaque no canto superior ESQUERDO e .selo-plano no canto OPOSTO, "para não
   sobrepor" — falso em telas estreitas (o plano Ouro tem destaque_home=1 E selo=1 ao
   mesmo tempo, então toda assinante do plano-topo tinha os dois selos ativos juntos, e nos
   cards de 168,5px (grid) e 150px (faixa) de largura a 375px eles colidiam: 4,7px e 23,2px
   de sobreposição, respectivamente — medidos com Playwright).
   Agora os dois vivem dentro de UM container (.selos-foto), sempre no canto superior
   esquerdo, empilhados em coluna (flex-direction:column) — colunas nunca competem por
   largura horizontal, então não existe combinação de card estreito + selo duplo que volte
   a sobrepor, em nenhuma largura entre 320px e 1920px.
   PRD-UV-009 (Componente 6): right:36px → 40px — o disco .selo-verificada cresceu de 22px
   pra 24px na mesma edição (ver comentário lá); as duas mudanças andam juntas, sempre,
   senão a colisão documentada acima volta. .selo-plano vira só o fallback defensivo
   (carmim sólido — nome de plano que não bate com "Ouro"/"Prata" degrada pra cá, nunca
   quebra); Ouro e Prata ganham modificador aditivo abaixo, mantendo a classe base. */
.selos-foto{position:absolute;top:8px;left:8px;right:40px;z-index:2;
  display:flex;flex-direction:column;align-items:flex-start;gap:4px;}
.selo-plano{background:var(--carmim);color:var(--marfim);
  font-size:.6rem;font-weight:700;padding:3px 7px;border-radius:3px;letter-spacing:.02em;
  min-height:20px;display:flex;align-items:center;gap:3px;max-width:100%;}
.selo-plano svg{width:10px;height:10px;flex:none;}
/* Ouro: fundo champagne, texto preto — 10,33:1. Fundo opaco, contraste independe da foto
   atrás (nunca esteve em risco, achado C2). */
.selo-plano-ouro{background:var(--champagne);color:var(--preto);}
/* Prata (achado C2, REVIEW-michelangelo): ÚNICO dos quatro badges do card sem fundo sólido —
   flutua sobre a <img> do anúncio. --prata (#cfc9c4) é ela própria clara: sobre um pixel
   claro de foto real (pele, roupa, ambiente) o contraste cru cai pra perto de 1:1, e o selo
   que a assinante PAGA pra ter some. Com o scrim a .75 o pior caso (pixel branco atrás) mede
   5,35:1. NUNCA transparent — critério de aceite 9b verifica o background-color computado.
   É .75, não .55: o precedente .foto-item .num-ordem usa .55 porque o texto dele é marfim;
   aqui o texto é a própria --prata clara, e .55 mede 2,59:1 (reprova). A leitura de marca
   "Prata = contorno prata" fica preservada: mesma borda, mesma cor de texto. */
.selo-plano-prata{
  background:rgba(18,13,14,.75); /* --preto a 75% de alfa — scrim sobre foto real (achado C2) */
  border:1px solid var(--prata);
  color:var(--prata);
}

/* ===== TASK-006 — Painel de cidade em <dialog> nativo (Componentes 9 e 10) =====
   O <select> segue como interface real quando não há suporte a <dialog>/showModal() ou JS
   desabilitado (RF-05, fallback via <form method="get">). Com suporte, #gatilho-cidade se
   sobrepõe ao select (que ganha .painel-cidade-ativo select{pointer-events:none} acima, perto
   da regra .seletor-cidade select — que NÃO foi tocada). */
#gatilho-cidade{display:none;}
.painel-cidade-ativo #gatilho-cidade{
  display:flex;position:absolute;inset:0;z-index:1;align-items:center;justify-content:space-between;
  gap:8px;background:var(--fundo-card);color:var(--texto);border:1px solid var(--borda-controle);
  border-radius:2px;padding:10px 14px;font-size:.9rem;font-family:var(--f-corpo);min-height:44px;
  min-width:180px;cursor:pointer;}
#gatilho-cidade svg{width:14px;height:14px;flex:0 0 auto;color:var(--texto-sec);}

.btn-ir-cidade{min-height:44px;padding:0 16px;background:var(--carmim);color:var(--marfim);
  border:0;border-radius:2px;font-weight:700;font-size:.85rem;cursor:pointer;}
.btn-ir-cidade:hover{background:var(--carmim-escuro);}

/* ----- Painel <dialog> ----- */
/* Achado real do Codex review (PRD-UV-011, ciclo 2): sem suporte nativo a <dialog>, o
   navegador não aplica a regra de user-agent `dialog:not([open]){display:none}` — e o JS já
   retorna cedo (typeof showModal !== 'function') sem aplicar .painel-cidade-ativo, deixando
   este elemento sem NENHUM controle de exibição. Sem a regra abaixo, o conteúdo do painel
   (título, lista, botão fechar) renderizaria inline na página, quebrando o fallback
   pretendido (só o <select> visível). Regra explícita, independente de suporte nativo. */
#dialog-cidade:not([open]){display:none;}
#dialog-cidade{width:100%;max-width:380px;padding:0;margin:auto;border:1px solid var(--borda);
  border-radius:3px;background:var(--fundo-card);color:var(--texto);}
#dialog-cidade::backdrop{background:rgba(18,13,14,.72);}
/* Trava o scroll do fundo enquanto o painel está aberto — o gate 18+ já faz isso com
   .gate-travado; sem o equivalente aqui, o mobile rola a vitrine atrás do painel. Classe
   aplicada/removida pelo JS junto de showModal()/close(). */
body.painel-cidade-aberto{overflow:hidden;}
#dialog-cidade[open]{animation:entrada-painel-cidade var(--dur-base) var(--ease-marca);}
/* .fechando vem DEPOIS de [open]: mesma especificidade, quem vence é a ordem. */
#dialog-cidade.fechando{animation:saida-painel-cidade var(--dur-base) var(--ease-marca) forwards;}
@keyframes entrada-painel-cidade{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:translateY(0);}}
@keyframes saida-painel-cidade{from{opacity:1;transform:translateY(0);}to{opacity:0;transform:translateY(10px);}}

.dialog-cidade-topo{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:18px 18px 14px;border-bottom:1px solid var(--borda);}
.dialog-cidade-topo h2{margin:0;font-family:var(--f-display);font-size:1.05rem;font-weight:600;}
#btn-fechar-cidade{min-width:44px;min-height:44px;display:flex;align-items:center;justify-content:center;
  background:transparent;border:0;border-radius:2px;color:var(--texto-sec);cursor:pointer;}
#btn-fechar-cidade:hover{color:var(--texto);}
#btn-fechar-cidade svg{width:18px;height:18px;}

.lista-cidades-painel{list-style:none;margin:0;padding:8px;max-height:min(60vh,420px);overflow-y:auto;}
.linha-cidade{display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:44px;
  padding:12px 10px;border:1px solid transparent;border-radius:2px;text-decoration:none;
  color:var(--texto);border-bottom:1px solid var(--hairline);}
.lista-cidades-painel li:last-child .linha-cidade{border-bottom:0;}
.linha-cidade:hover{background:var(--superficie-alta);}
/* Estado ATUAL — sinal permanente, não dependente de hover/foco. Reaproveita o padrão irmão
   .miniaturas button.ativa{border-color:var(--carmim-claro)} (vitrine.css:330), que é como o
   projeto já marca "o item que você está vendo". aria-current="page" (markup) resolve para
   leitor de tela; este border-color resolve para quem enxerga. */
.linha-cidade.atual{border-color:var(--carmim-claro);background:var(--superficie-alta);}
.linha-cidade.atual .linha-cidade-nome{font-weight:700;}
.linha-cidade-nome{font-size:.92rem;font-weight:500;}
.linha-cidade-contagem{font-size:.78rem;color:var(--texto-sec);white-space:nowrap;}
