/* ═══════════════════════════════════════════════════════════════════════════
   provador.css — a pele do modal do "Provar em você".

   O QUE MUDA EM RELAÇÃO À IMPLEMENTAÇÃO DE REFERÊNCIA, item a item, porque a
   lista É o trabalho deste arquivo:

     véu           #000000d9            ->  chapa off-white, opaca
     superfície    branco / dark:gray   ->  --vl-bg (#F4F1EC)
     raio          11px                 ->  --raio (8px), o do DNA
     tipografia    Playfair + Inter,        Poppins 500 nos títulos e Inter no
                   via CDN do Google        corpo, as duas já auto-hospedadas
     botão         pílula maiúscula         .btn — roxo cheio, raio do DNA,
                   negrito, teal #11a3c0    caixa alta proibida
     fechar        X do Material sobre      o MESMO controle do painel, na mesma
                   #8080802e                faixa em que conteúdo não passa
     ícones        estrela amarela      ->  nenhum
     resultado     pillarbox preto      ->  proporção nativa, sem barra
     marcação      ausente              ->  obrigatória, colada, pintada depois
     easing        do Tailwind          ->  --ease-out / --dur-*, a assinatura
     altura        600px fixo           ->  --vh-unit; vh e dvh proibidos aqui

   A CHAPA É OPACA DE PROPÓSITO, e é a única superfície desta página que é. O
   painel é vidro porque ele é LEITURA SOBRE O FILME — a tomada continuar
   visível atrás é o argumento dele. O provador é ferramenta: ele substitui a
   vista enquanto dura. É essa opacidade que também torna verdadeiro o
   aria-modal e permite que a marcação de origem do palco fique coberta, porque
   não há imagem gerada visível atrás dela aqui. A única que existe nesta tela é
   o resultado, e ele carrega a própria.
   ═════════════════════════════════════════════════════════════════════════ */

.pv {
  /* O PARÁGRAFO É MAIS LARGO AQUI DENTRO, E SÓ AQUI DENTRO.
     Pedido do dono, olhando a política. Medido antes: 450px de bloco davam 50
     caracteres por linha — apertado para leitura corrida, cuja faixa confortável
     é 45 a 75 com o ótimo perto de 66. A coluna já tinha 640px, então quem
     limitava não era ela: era --leitura-max, e o parágrafo parava em 450 deixando
     190px vagos dentro da própria coluna. 600px põem o corpo em ~66.

     POR QUE SOBRESCREVER O TOKEN AQUI E NÃO NO tokens.css: --leitura-max é global
     e governa também os blocos de texto da landing, que assentam SOBRE o vídeo e
     têm contraste, véu e posição medidos um a um. Alargá-los mudaria o pixel que
     cada medição daquelas cobriu. O modal tem fundo próprio e nenhuma dessas
     amarras — é o único lugar onde a medida pode crescer sem reabrir nada.

     Herda para a camada da política junto: #pvTermos é descendente de #provador. */
  --leitura-max: 600px;

  position: fixed;
  inset: 0;
  z-index: var(--z-provador, 60);
  /* CHAPA A 50%, POR PEDIDO DO DONO. Era var(--vl-bg) sólido.
     O desfoque NÃO é enfeite e não veio junto por gosto: sem ele o texto assenta
     sobre imagem em movimento e o contraste passa a depender de qual quadro está
     por baixo. É a mesma lição que o véu do painel já pagou — lá o desfoque
     decide quanto DETALHE atravessa, e é ele que deixa a média da vizinhança
     estável o bastante para a tinta ter contra o que medir.
     Ver PROVADOR/CHAPA_A_50 no _progress: as consequências estão medidas lá. */
  background: color-mix(in srgb, var(--vl-bg) 50%, transparent);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  color: var(--vl-ink);
  font-family: var(--f-body);
}
/* Navegador sem backdrop-filter volta à chapa sólida em vez de entregar texto
   sobre vídeo cru. Degradar para MENOS transparência é seguro; o contrário não. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .pv { background: var(--vl-bg); }
}
.pv:focus { outline: none; }

/* O trilho não rola por trás. Mesma trava do painel, e as duas convivem: com o
   provador aberto por cima do painel, as duas classes ficam no <html>. */
.provador-aberto { overflow: hidden; }

/* A CAMADA DE VOO SOME ENQUANTO ISTO ESTÁ ABERTO.
   --z-flight é 90 e o provador é 60: sem esta regra o símbolo pousaria POR CIMA
   da chapa, no meio do modal, congelado onde a rolagem o deixou. Não é
   esconder erro de empilhamento — a camada de voo é a marca em viagem sobre a
   tomada, e a tomada não está na tela agora.
   !important porque handoff.js escreve estilo inline no elemento a cada tique,
   e regra de folha não vence atributo. Mesmo motivo de .painel-aberto .rail. */
.provador-aberto .flight { visibility: hidden !important; }

/* ── A BARRA ──────────────────────────────────────────────────────────────
   Mesma altura da barra da página, e pela mesma razão do painel: é a faixa por
   onde conteúdo não passa, e é por isso que o Fechar mora nela. Quem não pode
   ser coberto — nem cobrir — não mora na camada que rola. */
.pv__barra {
  position: absolute;
  inset: 0 0 auto 0;
  height: var(--nav-h);
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding: 0 max(env(safe-area-inset-right), var(--s-6))
           0 max(env(safe-area-inset-left), var(--s-6));
  background: var(--vl-bg);
  box-shadow: inset 0 -1px 0 var(--vl-rule);
}
.pv__rotulo {
  font-family: var(--f-display);
  font-weight: 500;
  font-size: var(--t-label);
  letter-spacing: var(--tk-label);
  line-height: var(--lh-label);
  color: var(--vl-ink-mute);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* O CONTROLE DE FECHAR DO PAINEL, sem inventar um segundo idioma de fechamento
   na mesma página. Só o display muda: aqui ele está sempre presente. */
.pv__fechar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  min-height: var(--tap-min);
  font: 500 15px/1.2 var(--f-body);
  letter-spacing: .01em;
  white-space: nowrap;
  color: var(--vl-ink);
  background: var(--vl-bg);
  border: 1px solid var(--vl-rule);
  border-radius: var(--raio);
  padding: 10px var(--s-5);
  cursor: pointer;
  transition: background-color var(--dur-quick) var(--ease-out),
              color var(--dur-quick) var(--ease-out);
}
.pv__fechar:hover {
  background: var(--vl-purple);
  color: var(--vl-on-purple);
  border-color: var(--vl-purple);
}
.pv__fechar:focus-visible { outline: 2px solid var(--vl-purple); outline-offset: 3px; }

/* ── O ROLO ───────────────────────────────────────────────────────────────
   A caixa COMEÇA ABAIXO DA BARRA por inset, não por enchimento. Enchimento só
   afasta o conteúdo na posição inicial: rolando, o texto sobe por dentro dele.
   Foi blocker no painel (73,2% das posições de rolagem com linha sob a barra a
   390x844) e a correção veio junto com a regra. Ela vale aqui inteira. */
.pv__rolo {
  position: absolute;
  inset: var(--nav-h) 0 0 0;
  overflow-y: auto;
  overscroll-behavior: contain;      /* a rolagem do modal não vaza para o trilho */
  -webkit-overflow-scrolling: touch;
}
.pv__col {
  width: min(var(--container-pct), 640px);
  margin: 0 auto;
  padding: var(--s-10) 0 calc(var(--s-16) + env(safe-area-inset-bottom));
}

.pv__titulo {
  font-family: var(--f-display);
  font-weight: 500;
  font-size: var(--t-md);
  letter-spacing: var(--tk-md);
  line-height: var(--lh-md);
  color: var(--vl-ink);
  margin-bottom: var(--s-8);
}
.pv__sub {
  font-family: var(--f-display);
  font-weight: 500;
  font-size: var(--t-sm);
  letter-spacing: var(--tk-sm);
  line-height: var(--lh-sm);
  color: var(--vl-ink);
}
/* ── RITMO VERTICAL DO TEXTO LONGO ────────────────────────────────────────
   Pedido do dono: aumentar a distância entre os itens. Medido antes, e o que a
   medição mostrou é maior que espaçamento — era HIERARQUIA:

       título da seção  ->  primeiro parágrafo     32px
       parágrafo        ->  parágrafo              32px
       parágrafo        ->  TÍTULO DA SEÇÃO SEGUINTE  0px   <- aqui

   Tudo chapado em 32, e o título de seção COLADO no último parágrafo da seção
   anterior. Um título que encosta no texto de cima pertence visualmente a ele,
   e era por isso que "2. Fluxo técnico" parecia continuação do bloqueio de
   download em vez de começo de assunto novo.

   Os três vãos agora são distintos e crescem na ordem certa:

       24px  título -> o texto DELE          (o mais curto: eles são um bloco só)
       40px  parágrafo -> parágrafo          (respiro de leitura)
       64px  parágrafo -> título seguinte    (o corte entre assuntos)

   Os seletores de irmão são de propósito: o vão grande vale só para título que
   VEM DEPOIS de texto corrido. O primeiro título de cada passo do modal não é
   corte de assunto nenhum e continua sem margem herdada.

   Escopo dentro de .pv: nada disto alcança a landing. */
.pv__col .corpo { margin-top: var(--s-10); }
.pv__col .corpo + .pv__sub { margin-top: var(--s-16); }
.pv__col .pv__sub + .corpo { margin-top: var(--s-6); }
.pv__col .corpo + .pv__motor { margin-top: var(--s-16); }

.pv__dica {
  color: var(--vl-ink-mute);
  margin-top: var(--s-3);
  max-width: var(--leitura-max);
}
.pv__acoes { margin-top: var(--s-6); }
.pv__btn { margin-top: var(--s-8); }

/* Botão de texto: mesma tipografia do corpo, sublinhado, sem virar segundo
   botão sólido competindo com o principal. */
.pv__link {
  display: inline-block;
  min-height: var(--tap-min);
  background: none;
  border: 0;
  padding: var(--s-3) 0;
  font: 400 var(--t-body)/var(--lh-body) var(--f-body);
  color: var(--vl-purple);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.pv__link:hover { color: var(--vl-ink); }
.pv__link:focus-visible { outline: 2px solid var(--vl-purple); outline-offset: 3px; }

/* ── O MARCADOR DA PENDÊNCIA ──────────────────────────────────────────────
   NÃO É UMA VERSÃO PROVISÓRIA DO TEXTO. É um aviso de que o texto não existe, e
   ele é feio de propósito: uma redação plausível no lugar da política seria
   exatamente a coisa que alguém publica por engano achando que já estava
   pronta. Some inteiro quando a política chegar. */
.pv__pendencia {
  border: 2px dashed var(--vl-purple);
  border-radius: var(--raio);
  padding: var(--s-5);
  margin-bottom: var(--s-8);
  background: rgb(74 0 122 / .04);
}
.pv__pendencia p { font-size: var(--t-body); line-height: var(--lh-body); }
.pv__pendencia p + p { margin-top: var(--s-3); }
.pv__pendencia code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .92em;
}
.pv__pendencia-tag {
  font-family: var(--f-display);
  font-weight: 500;
  font-size: 13px !important;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--vl-purple);
  margin-bottom: var(--s-3);
}
.pv__motor { color: var(--vl-ink-mute); }

/* ── O ACEITE ─────────────────────────────────────────────────────────────
   Caixa desmarcada, ação afirmativa, botão bloqueado até marcar. O alvo é o
   rótulo inteiro, não só o quadradinho de 16px. */
.pv__aceite {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  min-height: var(--tap-min);
  padding: var(--s-2) 0;
  cursor: pointer;
  max-width: var(--leitura-max);
}
.pv__caixa {
  flex: none;
  width: 22px;
  height: 22px;
  margin-top: 2px;
  accent-color: var(--vl-purple);
  cursor: pointer;
}
.pv__caixa:focus-visible { outline: 2px solid var(--vl-purple); outline-offset: 3px; }
.pv__aceite-texto {
  font-size: var(--t-body);
  line-height: var(--lh-body);
  color: var(--vl-ink-soft);
}
[data-pendencia] .pv__aceite-texto,
.pv__aceite-texto[data-pendencia] { color: var(--vl-ink-mute); font-style: italic; }

/* ── BOTÃO DESABILITADO: ROXO REBAIXADO, NÃO CINZA ────────────────────────
   Decisão do dono. O cinza (--vl-rule com tinta apagada) sempre esteve aqui e
   estava certo enquanto o botão era pequeno; quando "Gerar look" virou um
   quadrado de 176px, o mesmo cinza passou a ler como "quebrado" em vez de
   "ainda não". O peso visual mudou, o significado não.

   O TOM FOI MEDIDO, não escolhido no olho. Texto branco sobre roxo rebaixado é
   exatamente onde o contraste cai, e o rótulo tem 17px — texto normal, limiar
   4,5. A curva, misturando roxo com o fundo:
       80% -> rgb(108,48,145)  contraste 8,50   (2,6x mais claro que o cheio)
       70% -> rgb(125,72,156)  contraste 6,40   (4,0x)   <- escolhido
       60% -> rgb(142,96,168)  contraste 4,78   (5,9x)
       50% -> rgb(159,121,179) contraste 3,58   REPROVA
   O 60% apaga mais e passaria, mas por 0,28 — e este arquivo acabou de registrar
   o custo de trabalhar com margem de arredondamento. O 70% apaga o suficiente
   para não parecer clicável e mantém folga real.

   Misturar com --vl-ink-mute em vez do fundo foi testado e descartado: dá
   rgb(81,30,114), só 1,4x mais claro que o roxo cheio — indistinguível.

   @supports mantém o PAR junto. Sem color-mix, fundo e tinta voltam os dois ao
   cinza original; separá-los deixaria branco sobre cinza claro.

   ALCANCE: as duas únicas .btn desabilitadas do projeto são deste modal —
   "Autorizo" e "Gerar look". Nenhum botão da landing nasce desabilitado. */
.btn:disabled,
.pv__btn:disabled {
  background: var(--vl-rule);
  color: var(--vl-ink-faint);
  cursor: not-allowed;
}
@supports (background: color-mix(in srgb, red 50%, blue)) {
  .btn:disabled,
  .pv__btn:disabled {
    background: color-mix(in srgb, var(--vl-purple) 70%, var(--vl-bg));
    color: var(--vl-on-purple);
  }
}

/* ── O ENVIO ──────────────────────────────────────────────────────────────
   É ARQUIVO, NÃO CÂMERA. Sem `capture`, sem permissão de mídia, sem escolha
   entre dois caminhos: a integração só suporta envio de arquivo hoje. */
.pv__envio { margin-top: var(--s-6); }
.pv__solta {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 128px;
  padding: var(--s-6);
  border: 1px dashed var(--vl-rule);
  border-radius: var(--raio);
  background: var(--vl-card);
  color: var(--vl-ink);
  font-size: var(--t-body);
  cursor: pointer;
  transition: border-color var(--dur-quick) var(--ease-out),
              background-color var(--dur-quick) var(--ease-out);
}
.pv__solta:hover { border-color: var(--vl-purple); }
.pv__solta:focus-within { outline: 2px solid var(--vl-purple); outline-offset: 3px; }
/* O input existe e é focável — só não é ele que se desenha. Esconder com
   display:none o tiraria da ordem de tabulação e o rótulo deixaria de abrir o
   seletor pelo teclado. */
.pv__arquivo {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}
.pv__solta-texto { font-family: var(--f-display); font-weight: 500; }
.pv__solta-nome { font-size: var(--t-caption); color: var(--vl-ink-mute); }

/* ── A PRÉVIA DO QUE FOI ESCOLHIDO ────────────────────────────────────────
   object-fit: contain, e não cover: aqui a pessoa está conferindo SE MANDOU a
   foto certa, e cover cortaria justamente cabeça ou pés — que é o que a
   instrução logo acima pede que apareçam ("de corpo inteiro, de frente"). Uma
   prévia que corta o que o texto exige seria a página se contradizendo.

   A altura é teto, não medida fixa: retrato bate nos 180px e o resto acompanha
   pela razão real do arquivo; paisagem fica mais baixa e não estica. Sem
   width/height fixos e sem aspect-ratio — foi altura em porcentagem e
   aspect-ratio que fizeram a miniatura vazar da placa no WebKit, e a lição
   escrita no README é deixar o conteúdo mandar quando ele pode. */
.pv__previa {
  display: block;
  max-width: 100%;
  max-height: 180px;
  width: auto;
  height: auto;
  border-radius: calc(var(--raio) - 2px);
  /* Xadrez discreto por trás: PNG com transparência sobre a chapa clara ficaria
     indistinguível do fundo, e a pessoa não saberia se mandou o arquivo errado. */
  background:
    conic-gradient(from 90deg, #0000 25%, rgb(0 0 0 / .05) 0 50%, #0000 0 75%, rgb(0 0 0 / .05) 0)
    0 0 / 16px 16px;
}
/* COM A PRÉVIA NA TELA, A PLACA ABRAÇA A IMAGEM — pedido do dono.
   Antes ela ocupava a largura inteira da coluna e sobrava tanta chapa branca em
   volta da foto que a moldura parecia solta dela: medido a 1400x1100, 640px de
   placa para 336px de imagem.

   fit-content e não uma largura fixa: quem decide o tamanho é a foto, que já é
   governada pela altura da janela na regra mais abaixo. A placa só acompanha.

   SÓ COM A PRÉVIA. Antes de escolher, o alvo continua ocupando a largura toda —
   ali ele é uma área para clicar e soltar arquivo, e encolhê-la seria tornar o
   alvo menor justamente quando ele é a única coisa a fazer na tela. */
.pv__solta:has(.pv__previa:not([hidden])) {
  padding: var(--s-4);
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
}

/* ── COM A PRÉVIA NA TELA, O TEXTO SAI DA VISTA — E SÓ DA VISTA ───────────
   Pedido do dono: escolhida a imagem, nem "Escolher imagem" nem o nome do
   arquivo precisam aparecer. A prévia já diz as duas coisas para quem enxerga.

   NÃO É display:none, e a diferença é a razão desta regra existir:

   · "Escolher imagem" é o NOME ACESSÍVEL do controle. A <label> envolve o
     <input type=file>, e o nome do controle vem do texto dela. Com display:none
     o rótulo fica sem texto e o seletor vira um botão sem nome — quem usa leitor
     de tela ouviria "botão de upload de arquivo" e mais nada, num modal cujo
     ponto inteiro é escolher um arquivo.
   · O nome do arquivo é a confirmação TEXTUAL de que a escolha deu certo, e é
     ela que sustenta o alt="" da prévia logo acima. Apagá-la dos dois lugares
     deixaria quem não enxerga sem nenhuma confirmação além do role=status.

   Mesma técnica de .visualmente-oculto (layout.css): sai da vista, fica na
   árvore. O dono pediu que não APARECESSE, não que deixasse de existir. */
.pv__solta:has(.pv__previa:not([hidden])) .pv__solta-texto,
.pv__solta:has(.pv__previa:not([hidden])) .pv__solta-nome,
/* ── COM A IMAGEM NA TELA, O CABEÇALHO TAMBÉM SAI ────────────────────────
   Pedido do dono: escolhida a imagem, "Provar em você.", "Envie a sua imagem."
   e a dica de formato deixam de ser necessários, e o espaço vai para a prévia.

   MESMA técnica de clipe, e aqui ela não é preferência — é obrigação:
   #pvTitulo é o alvo do aria-labelledby do <div role="dialog">. Com display:none
   o diálogo ficaria SEM NOME ACESSÍVEL, e um leitor de tela anunciaria só
   "diálogo". A regra some com o texto da vista e o mantém na árvore; era isso
   que o pedido queria dizer. */
.pv__col:has(.pv__previa:not([hidden])) .pv__titulo,
.pv__col:has(.pv__previa:not([hidden])) .pv__sub,
.pv__col:has(.pv__previa:not([hidden])) .pv__dica {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

/* A PRÉVIA OCUPA O ESPAÇO QUE OS TEXTOS DEIXARAM — E PARA ANTES DE COMER O BOTÃO.
   A primeira versão desta regra usava uma FRAÇÃO da altura (58vh). Medido a
   1280x800: a prévia foi a 464px e empurrou o "Gerar look" para 40px ABAIXO da
   dobra do rolo. Trocar texto por uma imagem grande e esconder a ação principal
   não é otimizar espaço — é mudar de problema.

   O teto agora é DERIVADO, não escolhido. Dentro do rolo, tudo o que não é a
   prévia soma ~372px (a linha da peça com o botão, os vãos e o enchimento), e o
   rolo em si é a janela menos a barra do topo (68px). Logo o maior valor que
   ainda deixa o botão à vista é: altura - 372 - 68 = altura - 440.

   Os 440px são a soma de caixas MEDIDAS na tela, não um palpite — mas continuam
   sendo uma soma escrita à mão, e é isso que esta nota registra: se a linha da
   peça mudar de altura, este número precisa ser remedido.

   O TETO FIXO DE 560px SAIU, por pedido do dono: a prévia cresce e encolhe com a
   altura da janela, sem parede no meio do caminho. Eu tinha posto o 560 para a
   imagem não virar pôster de página inteira, e medido a 1400x1100 era ele quem
   travava — a conta pedia 660px, o min() entregava 560, e sobravam 164px de
   folga inútil abaixo do botão.

   Sem ele nada fica sem controle, e é por construção: a conta desconta o que
   permanece na tela, então o botão continua visível por definição; e numa tela
   muito alta e estreita quem passa a mandar é o max-width de 100%, que segura a
   imagem pela largura da coluna antes de a altura importar. O max() continua
   sendo o piso para telas curtas, onde o rolo volta a rolar. */
.pv__col:has(.pv__previa:not([hidden])) .pv__previa {
  max-height: max(180px, calc(100 * var(--vh-unit) - 440px));
}

/* ── A PEÇA À VISTA ───────────────────────────────────────────────────────
   Mesma placa e mesmo raio das miniaturas da rolagem. O fundo branco de pixel
   real do PNG de origem não aparece: o que se exibe é o recorte 4:5, dentro de
   uma moldura da própria paleta. */
/* ── A PEÇA E O BOTÃO, LADO A LADO ────────────────────────────────────────
   Pedido do dono: o nome do produto ABAIXO da miniatura, e "Gerar look" AO LADO
   dela, do mesmo tamanho.

   As duas medidas vivem em variáveis aqui e são consumidas pela placa, pela
   imagem e pelo botão. O bloco de celular mais abaixo só troca os valores —
   antes ele redefinia a largura da imagem direto, e com o botão amarrado a ela
   isso deixaria os dois de tamanhos diferentes no celular. Um número, um dono.

   flex-wrap existe para telas muito estreitas: quando as duas colunas não cabem
   lado a lado, o botão desce inteiro em vez de espremer a placa — encolher a
   miniatura é o que faz a peça deixar de ser reconhecível, e essa lição o
   .troca da rolagem já pagou. */
/* ── CARROSSEL DE PEÇAS ───────────────────────────────────────────────────
   As placas continuam quadradas e o lado sai de um número só (--pv-quad). O que
   mudou é que agora são VÁRIAS e o botão desceu para a linha de baixo, ocupando
   a largura toda — é o desenho que o dono anexou.

   ROLAGEM NATIVA, não um carrossel de JS. O rolador é overflow-x com scroll-snap:
   funciona com dedo, com trackpad, com roda e com teclado sem uma linha de
   script, e o JS só entra para as setas e para saber quando escondê-las. Um
   carrossel que reimplementa rolagem quebra o gesto que o aparelho já sabe fazer.

   scrollbar-width: none esconde a barra e NÃO tira a rolagem: o conteúdo continua
   alcançável por gesto, por roda e por Tab, que é o que importa. As setas existem
   para quem usa ponteiro grosso e não tem gesto horizontal fácil. */
.pv__escolha {
  --pv-quad: 176px;
  margin-top: var(--s-6);
}
.pv__carrossel { position: relative; }
.pv__pecas {
  display: flex;
  gap: var(--s-2);
  list-style: none;
  margin: 0;
  /* O ENCHIMENTO HORIZONTAL É O QUE FAZ O ANEL DA PRIMEIRA PLACA APARECER.
     O anel é box-shadow com 3px de spread, ou seja desenhado FORA da caixa. Num
     rolador com overflow-x, o que está fora da caixa na borda de início é
     recortado — e em scrollLeft 0 não há para onde rolar para revelá-lo. Era por
     isso que só a PRIMEIRA aparecia cortada: as outras têm o vão do vizinho como
     folga, ela não tinha nada. 8px cobrem os 3px do anel com sobra.
     scroll-padding acompanha para o snap parar no mesmo lugar que a vista. */
  padding: var(--s-1) var(--s-2);
  scroll-padding-inline: var(--s-2);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  overscroll-behavior-x: contain;   /* não arrasta a camada de trás junto */
}
.pv__pecas::-webkit-scrollbar { display: none; }
.pv__pecas > li { flex: none; scroll-snap-align: start; }

/* AS SETAS FLUTUAM SOBRE AS BORDAS, fora do rolador — dentro dele rolariam com
   o conteúdo que servem para rolar. O degradê atrás avisa que há mais adiante:
   a borda cortada no meio de uma placa já diz "continua", e a seta confirma. */
.pv__seta {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 56px;
  border: 0;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.pv__seta--antes  { left: 0;  background: linear-gradient(to right, var(--vl-bg) 40%, transparent); }
.pv__seta--depois { right: 0; background: linear-gradient(to left,  var(--vl-bg) 40%, transparent); }
.pv__seta::after {
  content: '';
  width: 12px; height: 12px;
  border-top: 2px solid var(--vl-purple);
  border-right: 2px solid var(--vl-purple);
}
.pv__seta--antes::after  { transform: rotate(-135deg); margin-left: 4px; }
.pv__seta--depois::after { transform: rotate(45deg);   margin-right: 4px; }
.pv__seta:focus-visible { outline: 2px solid var(--vl-purple); outline-offset: -4px; }

/* O BOTÃO OCUPA A LARGURA TODA, embaixo. Ele deixou de ser quadrado quando
   deixou de ter uma placa só ao lado para acompanhar. */
.pv__escolha .pv__btn {
  display: block;
  width: 100%;
  margin-top: var(--s-6);
  text-align: center;
}

/* A PLACA VIROU BOTÃO. Era <figure>; agora é escolha, e escolha precisa de
   estado visível, de alvo de toque e de foco próprio — os três abaixo. */
/* A PLACA É A IMAGEM, e mais nada. Pedido do dono: sem nome à vista, e a foto
   preenchendo o quadrado inteiro com os cantos arredondados. Saíram o
   enchimento, o fundo e a coluna — não havia mais o que empilhar. */
.pv__peca {
  display: block;
  margin-top: 0;
  padding: 0;
  border: 0;
  border-radius: var(--raio);
  width: var(--pv-quad);
  height: var(--pv-quad);
  max-width: 100%;
  cursor: pointer;
  transition: box-shadow var(--dur-quick) var(--ease-out);
  overflow: hidden;              /* é ele que arredonda a foto nos cantos */
}
/* TRÊS ESTADOS DISTINTOS, e a distinção é a mesma da troca de looks da rolagem:
   hover eleva, foco ganha halo claro por fora do anel, selecionado ganha o anel
   roxo. O halo do foco existe porque anel roxo sobre anel roxo seria invisível
   justamente quando a pessoa está navegando por teclado. */
.pv__peca:hover { box-shadow: 0 6px 16px rgb(26 10 36 / .14); }
.pv__peca[aria-pressed="true"] { box-shadow: 0 0 0 3px var(--vl-purple); }
.pv__peca:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--vl-purple), 0 0 0 6px var(--vl-bg);
}
/* A IMAGEM PREENCHE O QUADRADO INTEIRO.
   Voltou para COVER: com a legenda fora e o enchimento fora, o pedido é que a
   foto complete a placa, e contain deixaria faixas vazias nos lados.

   height: 100% AQUI É SEGURO, e a diferença com o caso que mordeu este projeto
   no WebKit importa: lá a altura do pai vinha de aspect-ratio, que o WebKit não
   trata como definida para resolver porcentagem. Aqui .pv__peca tem height em
   PIXEL, vindo de --pv-quad. Porcentagem sobre altura em pixel é resolvida por
   qualquer motor.

   O QUE ISTO CUSTA, E FICA REGISTRADO: cover CORTA o que não for quadrado. As
   três miniaturas novas são quadradas e não perdem nada; mini-look.jpg é 320x400
   e perde ~20% no topo e na base. Uma versão quadrada dela resolve — é asset,
   não código. */
.pv__peca-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* O NOME SAI DA VISTA, NÃO DA ÁRVORE.
   Ele era o texto do <button>, ou seja o NOME ACESSÍVEL do controle. Removê-lo
   de verdade deixaria quatro botões que um leitor de tela anuncia como "botão",
   "botão", "botão", "botão" — e a imagem ao lado tem alt vazio de propósito,
   porque a informação estava no texto. Mesma técnica de .visualmente-oculto. */
.pv__peca-nome {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}
/* (A segunda regra de .pv__peca-nome saiu daqui: era a tipografia da legenda
   visível, e ficou órfã quando o nome saiu da vista. Ela vinha DEPOIS da regra
   de clipe, com a mesma especificidade — inofensiva porque não declarava
   position nem clip-path, mas este arquivo já pagou três vezes por regra
   duplicada em que a última escrita vence. Sobra de regra não fica.) */

/* ── A ESPERA ─────────────────────────────────────────────────────────────
   As seis etapas existem todas no documento; a viva é a que está acesa. As
   outras ficam legíveis e apagadas em vez de sumirem, para a espera ter forma:
   dá para ver quanto já passou e quanto falta sem nenhum número inventado. */
/* ── A TRILHA VERTICAL CRESCE, NO MESMO RELÓGIO DA BARRA ──────────────────
   Antes cada passo tinha a própria borda e só UM ficava roxo por vez: o roxo
   pulava de um passo para o outro em vez de avançar. Nos screenshots do dono
   parecia cumulativo, mas era a transição de cor entre os dois — os 320ms em
   que a borda de cima ainda não tinha apagado.

   Agora a lista carrega UMA trilha só, em duas camadas: a cinza inteira, e a
   roxa por cima crescendo de 0 a 100% da altura. A duração é a MESMA variável
   que a barra horizontal usa (--pv-teto, escrita pelo provador.js), então as
   duas não podem sair de sincronia — não há dois números para manter iguais.

   Animação de CSS e não rAF: a página promete 0% de CPU parada, e o laço dela
   continua dormindo enquanto isto corre. */
.pv__etapas {
  position: relative;
  margin-top: var(--s-8);
}
.pv__etapas::before,
.pv__etapas::after {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 2px;
  border-radius: 2px;
}
.pv__etapas::before { bottom: 0; background: var(--vl-rule); }
.pv__etapas::after  { height: 0; background: var(--vl-purple); }
.pv__etapas.is-correndo::after {
  animation: pvTrilho var(--pv-teto) linear forwards;
}
@keyframes pvTrilho { from { height: 0; } to { height: 100%; } }

.pv__etapa {
  display: grid;
  gap: 2px;
  padding: var(--s-3) 0 var(--s-3) var(--s-6);
  color: var(--vl-ink-faint);
  transition: color var(--dur-base) var(--ease-out);
}
.pv__etapa b {
  font-family: var(--f-display);
  font-weight: 500;
  font-size: var(--t-body);
}
.pv__etapa span { font-size: var(--t-caption); line-height: var(--lh-caption); }
/* TRÊS ESTADOS, E ELES SÃO CUMULATIVOS. Antes só existiam "vivo" e "não vivo",
   então um passo já cumprido voltava a parecer pendente assim que o seguinte
   acendia — a tela desfazia o que tinha acabado de dizer. Agora o que passou
   fica marcado como feito, e é isso que a trilha roxa por cima confirma. */
.pv__etapa.is-feita { color: var(--vl-ink-soft); }
.pv__etapa.is-viva  { color: var(--vl-ink); }

/* A BARRA MEDE O TEMPO GASTO DO ORÇAMENTO, e não o progresso do motor: o motor
   não informa progresso nenhum. Uma barra que fingisse isso seria a mesma
   desonestidade que o loader desta página existe para não cometer — lá o traço
   anda com bytes concluídos, e aqui o que existe para medir é o relógio.
   Chegar ao fim É o tempo esgotado, e é isso que acontece na mesma hora. */
.pv__tempo {
  margin-top: var(--s-8);
  height: 2px;
  background: var(--vl-rule);
  border-radius: 2px;
  overflow: hidden;
}
.pv__tempo > i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--vl-purple);
}
/* SEM RECUO DE 75000ms. Aquele número era config.PROVADOR.tetoMs escrito uma
   segunda vez, num arquivo que não importa o config — a regra 3 do config.js diz
   que número repetido é defeito. E o recuo era pior que inútil: se um dia o teto
   mudasse no config e este arquivo não, a barra passaria a mentir CALADA sobre
   quanto tempo resta. Sem ele, --pv-teto ausente torna a animação inválida e a
   barra fica parada em zero — falha visível, que é o que se conserta. */
.pv__tempo.is-correndo > i {
  animation: pvTempo var(--pv-teto) linear forwards;
}
@keyframes pvTempo { from { width: 0; } to { width: 100%; } }

/* ── O RESULTADO ──────────────────────────────────────────────────────────
   PROPORÇÃO NATIVA, SEM BARRA. A imagem manda na caixa: largura limitada,
   altura automática. Sem caixa fixa não há tarja preta para preencher e não há
   esticão — é o mesmo pillarbox que saiu do vídeo principal, e ele não volta. */
/* A <figure> deixou de ser uma placa. Ela tinha fundo, raio e overflow:hidden
   porque a marcação vivia POR CIMA da imagem e precisava de uma caixa que a
   recortasse junto. Com a marcação em fluxo abaixo, esse recorte passaria a
   cortar a própria legenda contra a borda, e o fundo apareceria como uma faixa
   atrás dela. Agora quem carrega o raio é a imagem, e a figure é só o agrupador
   — que é o papel dela no DNA: manter imagem e marcação inseparáveis. */
.pv__saida {
  position: relative;            /* âncora do botão de tela cheia */
  margin-top: var(--s-6);
  width: max-content;
  max-width: 100%;
}

/* ── BOTÃO DE TELA CHEIA ──────────────────────────────────────────────────
   Sobre o canto da imagem, com chapa própria: a foto que vem do motor pode ser
   clara ou escura em qualquer canto, e um ícone sem fundo ficaria invisível em
   metade dos resultados. A chapa resolve sem medir pixel por resultado.
   44px de alvo, que é a régua deste projeto. */
.pv__zoom {
  position: absolute;
  top: var(--s-3);
  right: var(--s-3);
  width: var(--tap-min);
  height: var(--tap-min);
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  color: var(--vl-ink);
  background: rgb(255 255 255 / .82);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  transition: background-color var(--dur-quick) var(--ease-out);
}
.pv__zoom:hover { background: rgb(255 255 255 / .95); }
.pv__zoom:focus-visible { outline: 2px solid var(--vl-purple); outline-offset: 2px; }
/* UM ÍCONE POR ESTADO, trocado por CSS. O JS não desenha nada — ele só escreve
   a classe, e por isso o ícone continua certo mesmo quando quem saiu da tela
   cheia foi o navegador, sem passar por nós. */
.pv__zoom-fechar { display: none; }
.pv__saida.is-cheia .pv__zoom-abrir { display: none; }
.pv__saida.is-cheia .pv__zoom-fechar { display: block; }

/* ── TELA CHEIA DE RESERVA (sem a API do navegador — iPhone) ──────────────
   Cobre a janela e centraliza. A marcação de origem vai junto porque é irmã
   dentro desta mesma <figure>: em tela cheia ela continua colada à imagem, que
   é a promessa do DNA. */
.pv__saida.is-cheia {
  position: fixed;
  inset: 0;
  z-index: var(--z-provador, 60);
  margin: 0;
  width: auto;
  max-width: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  padding: var(--s-4);
  background: var(--vl-bg);
}
.pv__saida.is-cheia .pv__saida-img { max-height: calc(100% - 48px); max-width: 100%; }

/* A tela cheia NATIVA precisa do mesmo tratamento: o navegador põe o elemento
   sozinho na tela, mas não o centraliza nem limita a imagem. */
.pv__saida:fullscreen {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  padding: var(--s-4);
  width: 100%;
  max-width: none;
  background: var(--vl-bg);
}
.pv__saida:fullscreen .pv__saida-img { max-height: calc(100% - 48px); max-width: 100%; }
/* ── BLOQUEIO DE DOWNLOAD DA IMAGEM GERADA ────────────────────────────────
   A política declara que a função de download é desativada por padrão, e estas
   três linhas são metade do que sustenta essa frase (a outra metade é o
   draggable="false" na marcação e o menu de contexto barrado no provador.js).

   -webkit-touch-callout é a que mais importa e é a menos conhecida: no iOS, o
   toque longo sobre uma imagem abre o menu nativo com "Salvar em Fotos", e ele
   NÃO passa pelo evento contextmenu — bloquear só o contextmenu deixaria o
   celular, que é onde a maior parte das pessoas vai usar isto, sem bloqueio
   nenhum.

   O QUE ISTO É, E O QUE NÃO É. É dissuasão, não cofre: captura de tela,
   ferramentas de desenvolvedor e o próprio data URI na memória continuam
   existindo, e nenhuma linha de CSS alcança isso. A política foi redigida com
   esse limite escrito — prometer bloqueio absoluto seria a mesma classe de
   frase falsa que tirou "exclusão dos arquivos" do texto. */
.pv__saida-img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: calc(62 * var(--vh-unit));
  border-radius: var(--raio);    /* era da <figure>, que deixou de ser placa */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

/* MARCAÇÃO DE ORIGEM sobre o resultado.
   IRMÃ POSTERIOR da imagem, dentro do <figure> que cria o contexto: pintada
   depois, logo por cima, sem depender de z-index e sem depender de opacidade.
   Lição do B2 — opacidade não protege contra camada opaca por cima; o que
   protege é a ordem de pintura.
   A redação é diferente da do vídeo de propósito: lá a pessoa é gerada, aqui a
   pessoa é real e a peça é que é simulação. */
/* ── A MARCAÇÃO SAI DE CIMA DA IMAGEM ─────────────────────────────────────
   Pedido do dono, com as duas telas à vista: ela estava em position:absolute
   sobre o canto inferior da imagem e encavalava a peça — no celular, onde o
   texto quebra em duas linhas, tapava uma faixa do vestido.

   Agora ela é IRMÃ EM FLUXO, logo abaixo da imagem. O que NÃO mudou é o que
   importa: continua dentro da MESMA <figure>, e continua sendo o último nó dela.
   A garantia do DNA nunca foi "a marcação fica por cima" — é que ela não pode
   ser separada da imagem que descreve. Mesma figure, pintada depois, sem
   depender de z-index nem de opacidade: quem levar a imagem leva a legenda.

   O opacity/visibility com !important ficam. Eles não são estética: são a trava
   contra alguém apagar a marcação por CSS, e valem em fluxo como valiam em
   posicionamento absoluto. */
.pv__marcacao {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-top: var(--s-3);
  color: var(--vl-ink-soft);
  font-size: 12px;
  line-height: 1.35;
  letter-spacing: .02em;
  max-width: 100%;
  opacity: 1 !important;
  visibility: visible !important;
}
.pv__marcacao i {
  display: block;
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: var(--vl-purple);
}

/* ── FALHA ────────────────────────────────────────────────────────────────
   Sete motivos, um layout. A saída de WhatsApp está em todos porque ela é a
   única coisa que continua funcionando quando o que quebrou é nosso. */
.pv__falha {
  font-size: var(--t-body);
  line-height: var(--lh-body);
  color: var(--vl-ink-soft);
  margin-top: var(--s-4);
  max-width: var(--leitura-max);
}
.pv__zap { margin-top: var(--s-6); }

/* ── A CAMADA 2 — A POLÍTICA ──────────────────────────────────────────────
   Modal dentro de modal: a mesma chapa, por cima da primeira, com barra e rolo
   próprios. Não é um painel lateral e não é um acordeão — abrir a política não
   pode fazer perder o lugar de quem estava no consentimento. */
.pv__termos {
  position: absolute;
  inset: 0;
  z-index: 3;
  background: var(--vl-bg);
}
.pv__termos:focus { outline: none; }

/* ── CELULAR ──────────────────────────────────────────────────────────────
   Nada de layout novo aqui: a coluna já é fluida e a barra já é a mesma da
   página. O que muda é só a folga, que aperta junto com o resto do DNA. */
@media (max-width: 734px) {
  .pv__col { padding-top: var(--s-8); }
  .pv__titulo { margin-bottom: var(--s-6); }
  /* Só o VALOR muda: a placa, a imagem e o botão derivam dele e continuam
     quadrados e do mesmo tamanho sem esta regra saber que o botão existe. */
  .pv__escolha { --pv-quad: 144px; }
  .pv__saida-img { max-height: calc(56 * var(--vh-unit)); }
}

/* ── SEM JS / MOVIMENTO REDUZIDO ──────────────────────────────────────────
   O modal simplesmente não existe nesses dois planos: provador.js não sobe, os
   gatilhos ficam com o href do WhatsApp que já está literal na marcação, e este
   nó nunca perde o [hidden]. A regra abaixo é a garantia de que ele não pode
   aparecer nem por acidente de cascata. */
.rm .pv,
.no-js .pv { display: none !important; }
