/* Folha de estilo do painel.

   Mínima e escrita à mão: a stack prevê HTMX, mas nenhuma AC desta story tem
   interação, e nada aqui é baixado da rede. Sem framework CSS — o painel é
   single-user e server-rendered. */

:root {
  --cor-fundo: #faf8f5;
  --cor-cartao: #fff;
  --cor-texto: #2b2622;
  --cor-suave: #6f665e;
  --cor-borda: #e2dbd2;
  --cor-destaque: #8a5a2b;
  --cor-erro: #a3341f;
  --raio: 0.5rem;
  --sombra: 0 1px 2px rgb(43 38 34 / 6%), 0 1px 3px rgb(43 38 34 / 4%);

  /* DUAS larguras, e a distinção é a razão de a tela de achados ter ficado
     estrangulada: 48rem é a medida de LEITURA (um formulário mais largo que isto só
     afasta o rótulo do campo), mas a grelha de achados não é leitura — é varrer
     dezenas de miniaturas, e ali cada centímetro é mais uma coluna. Com a medida de
     leitura aplicada ao painel inteiro, uma tela de 1280px mostrava DUAS colunas e
     deixava metade do ecrã vazio, com 278 achados a exigir 139 linhas de scroll. */
  --largura-max: 48rem;
  --largura-larga: 84rem;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--cor-fundo);
  color: var(--cor-texto);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  line-height: 1.6;
}

.site-header {
  align-items: center;
  border-bottom: 1px solid var(--cor-borda);
  display: flex;
  justify-content: space-between;
  padding: 1rem 1.5rem;
}

.site-brand {
  color: var(--cor-destaque);
  font-weight: 700;
  letter-spacing: 0.02em;
  /* Empurra navegação e "Sair" para a direita. Sem isto, o `space-between` do
     header espalharia os três filhos e a navegação flutuaria no meio, longe
     tanto da marca quanto do controle a que pertence. */
  margin-right: auto;
  text-decoration: none;
}

.site-nav {
  display: flex;
  gap: 1rem;
  margin-right: 1rem;
}

.site-nav-link {
  color: var(--cor-suave);
  font-size: 0.9rem;
  text-decoration: none;
}

.site-nav-link:hover {
  color: var(--cor-destaque);
}

.site-main {
  margin: 0 auto;
  max-width: var(--largura-max);
  padding: 2rem 1.5rem;
}

/* As telas que MOSTRAM (achados, buscas, histórico) pedem largura; as que LEEM e
   escrevem (login) ficam na medida de leitura. Modificador no `<main>` e não uma
   regra por página: o dia de acrescentar uma tela larga é uma classe no template, e
   não mais uma linha aqui. Os formulários lá dentro têm o seu próprio `max-width`, e
   por isso continuam estreitos mesmo num `<main>` largo. */
.site-main-larga {
  max-width: var(--largura-larga);
}

/* --- Botões: um vocabulário só ------------------------------------------------
   Antes, cada ação inventava o seu: "Editar" era link, "Desativar" tinha uma borda,
   "Rodar agora" outra, e o "Cadastrar" era o único preenchido. O resultado é o que se
   vê no ecrã — três pesos visuais para três ações do mesmo nível, e nada a dizer qual
   é a principal. Duas classes, e a escolha passa a ser semântica: `-primario` para a
   ação que a tela existe para fazer, `-secundario` para o resto. */
.botao {
  border-radius: 0.375rem;
  cursor: pointer;
  display: inline-block;
  font: inherit;
  font-size: 0.9rem;
  line-height: 1.2;
  padding: 0.45rem 0.85rem;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
}

.botao-primario {
  background: var(--cor-destaque);
  border: 1px solid var(--cor-destaque);
  color: var(--cor-fundo);
  font-weight: 600;
}

.botao-primario:hover {
  filter: brightness(1.1);
}

.botao-secundario {
  background: var(--cor-cartao);
  border: 1px solid var(--cor-borda);
  color: var(--cor-texto);
}

.botao-secundario:hover {
  border-color: var(--cor-destaque);
  color: var(--cor-destaque);
}

h1 {
  font-size: 1.75rem;
  margin: 0 0 0.5rem;
}

.lead {
  font-size: 1.05rem;
  margin: 0 0 1rem;
}

.note {
  color: var(--cor-suave);
  font-size: 0.95rem;
  margin: 0;
}

/* Sair mora num <form method="post">, não num link: um GET que encerra sessão é
   disparado por qualquer <img> de terceiro e por qualquer pre-fetch do browser.
   O form desfaz o visual de botão que o header não quer. */
.logout-form {
  margin: 0;
}

.logout-button {
  background: none;
  border: 1px solid var(--cor-borda);
  border-radius: 0.25rem;
  color: var(--cor-suave);
  cursor: pointer;
  font: inherit;
  font-size: 0.9rem;
  padding: 0.25rem 0.75rem;
}

.logout-button:hover {
  border-color: var(--cor-destaque);
  color: var(--cor-destaque);
}

/* Estreito de propósito: o formulário tem um campo só, e esticá-lo até a
   `--largura-max` do painel daria a um campo de senha a largura de uma tabela
   de achados. */
.login-form {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-width: 22rem;
}

.login-label {
  color: var(--cor-suave);
  font-size: 0.9rem;
}

.login-input {
  border: 1px solid var(--cor-borda);
  border-radius: 0.25rem;
  font: inherit;
  padding: 0.5rem;
}

.login-input:focus {
  border-color: var(--cor-destaque);
  outline: 2px solid var(--cor-destaque);
  outline-offset: 1px;
}

.login-button {
  background: var(--cor-destaque);
  border: none;
  border-radius: 0.25rem;
  color: var(--cor-fundo);
  cursor: pointer;
  font: inherit;
  font-weight: 600;
  padding: 0.5rem 1rem;
}

.form-error {
  color: var(--cor-erro);
  font-size: 0.95rem;
  margin: 0 0 1rem;
}

/* --- Buscas ---------------------------------------------------------------- */

.searches-table {
  border-collapse: collapse;
  margin: 0 0 2rem;
  width: 100%;
}

.searches-table th,
.searches-table td {
  border-bottom: 1px solid var(--cor-borda);
  padding: 0.5rem 0.75rem 0.5rem 0;
  text-align: left;
  vertical-align: top;
}

.searches-table th {
  color: var(--cor-suave);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* As frases obrigatórias como PÍLULAS, e não texto plano como o preço ao lado: são
   dois portões diferentes — o preço vai no pedido, as palavras filtram do nosso lado
   —, e a badge é o que os distingue de relance. O invólucro guarda-as numa linha só
   até faltar espaço; aí `flex-wrap` deixa-as descer, com `gap` a separá-las, em vez
   de se colarem umas às outras. `inline-flex` (e não `flex`) para no card mobile a
   célula ser um item ao lado do rótulo do `data-label`, não um bloco por baixo. */
.searches-obrigatorias {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.3rem;
}

/* Pílula: raio grande, borda suave e a cor de destaque no texto — a mesma cor do
   "Editar", que diz "isto é do domínio da busca". Menor que o corpo para caber várias
   sem pesar a linha. Tokens de `:root`, sem cor nova.

   Sem `white-space: nowrap`: o campo aceita frases longas (até ao teto de validação),
   e mantê-las numa linha só faria uma frase comprida esticar para fora da célula e
   arrastar a página de lado no card estreito. `overflow-wrap: anywhere` parte a frase
   comprida em vez de a deixar transbordar, e `max-width: 100%` prende a pílula à
   largura da célula. As frases curtas (o caso normal) cabem numa linha na mesma. */
.searches-obrigatoria {
  background: var(--cor-cartao);
  border: 1px solid var(--cor-borda);
  border-radius: 999px;
  color: var(--cor-destaque);
  font-size: 0.8rem;
  line-height: 1.5;
  max-width: 100%;
  overflow-wrap: anywhere;
  padding: 0.05rem 0.55rem;
}

/* Estreito como o `.login-form`, e pelo mesmo motivo: são dois campos curtos, e
   esticá-los até a `--largura-max` do painel daria a um termo de busca a largura
   da tabela inteira. */
.search-form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  max-width: 26rem;
}

.search-field {
  border: none;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin: 0;
  padding: 0;
}

.search-label {
  color: var(--cor-suave);
  font-size: 0.9rem;
  padding: 0;
}

.search-input {
  border: 1px solid var(--cor-borda);
  border-radius: 0.25rem;
  font: inherit;
  padding: 0.5rem;
}

.search-input:focus {
  border-color: var(--cor-destaque);
  outline: 2px solid var(--cor-destaque);
  outline-offset: 1px;
}

/* O par país + número: dois controlos que são UM campo. Lado a lado numa linha,
   com o número a ficar com o espaço que sobra — o indicativo tem largura fixa e
   previsível, o número não. `wrap` para o ecrã estreito não os espremer. */
.phone-group {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.phone-country {
  flex: 0 0 auto;
}

.phone-national {
  /* `min-width: 0` porque um `<input>` em flex tem largura intrínseca e sem isto
     recusa encolher, empurrando o `<select>` para fora no telemóvel. */
  flex: 1 1 10rem;
  min-width: 0;
}

/* Esconde do olho e NÃO do leitor de tela: o `<select>` de país precisa de rótulo
   próprio (o `<label for="sms_to">` acima nomeia o número, não o indicativo), mas
   um "País" impresso ali duplicaria o que a própria opção já diz. `display: none`
   ou `hidden` o tirariam também da árvore de acessibilidade, que é o oposto. */
.visually-hidden {
  border: 0;
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

/* A caixa e o nome no mesmo `<label>`: clicar no nome marca a caixa, que é o
   alvo grande que um alvo de 13px não oferece. */
.search-check {
  align-items: center;
  display: flex;
  gap: 0.5rem;
}

.search-button {
  align-self: flex-start;
  background: var(--cor-destaque);
  border: none;
  border-radius: 0.25rem;
  color: var(--cor-fundo);
  cursor: pointer;
  font: inherit;
  font-weight: 600;
  padding: 0.5rem 1rem;
}

/* O erro de campo cola no campo, e não no rodapé do formulário como o
   `.form-error` do login (que tem um campo só, e portanto um lugar só onde o
   erro pode ser). Com dois campos, a margem de baixo herdada separaria a
   mensagem justamente do input a que ela se refere. */
.search-field .form-error {
  margin: 0;
}

/* O único link dentro de uma tabela do painel — os do header são navegação, e
   por isso são discretos. Aqui o sublinhado fica: numa célula cheia de texto, um
   "Editar" apenas colorido faz distinguir marrom de preto ser o requisito para
   saber que ali se clica. */
.searches-action {
  color: var(--cor-destaque);
  font-size: 0.9rem;
}

/* "Editar" e "Desativar" são as duas ações da MESMA linha e ficam na mesma linha:
   o `nowrap` é o que impede a célula de as quebrar em duas e fazer parecerem dois
   passos a cumprir. A `.search-actions` abaixo resolve isto com `display: flex`,
   e aqui isso seria trocar um problema por outro: um `<td>` com `display: flex`
   deixa de ser célula para o box model da tabela — o browser passa a gerar uma
   célula anônima à volta dele — e perde de quebra o `vertical-align: top` que a
   regra de `.searches-table td` acabou de lhe dar. Nada disso ficaria vermelho em
   teste nenhum: o sintoma é a coluna a desalinhar-se, e só se vê olhando. */
/* As três ações da linha lado a lado, e não empilhadas: "Rodar agora" quebrava para
   uma segunda linha e parecia um passo a cumprir depois de "Desativar". `flex` num
   `<td>` faria o browser gerar uma célula anônima à volta e perder o
   `vertical-align`; num `<div>` dentro dela, não. */
.searches-actions-group {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.searches-actions {
  white-space: nowrap;
}

/* O `<form>` existe por causa do POST, não do layout: como bloco ele quebraria a
   linha e empurraria o botão para debaixo do "Editar". O `inline-block` põe-no de
   volta no fluxo da célula, e a margem à esquerda é o vão entre os dois. */
.searches-toggle-form {
  display: inline-block;
  margin: 0 0 0 0.75rem;
}

/* Espelha `.logout-button`, e pelo mesmo motivo: é um botão de `<form method=post>`
   que não pode parecer o bloco de cor do `.search-button`. Alternar uma busca é
   ação de linha, não a ação primária da página — pintá-lo de `--cor-destaque` daria
   a cada linha da tabela um botão mais chamativo que o "Cadastrar busca". */
.searches-toggle {
  background: none;
  border: 1px solid var(--cor-borda);
  border-radius: 0.25rem;
  color: var(--cor-suave);
  cursor: pointer;
  font: inherit;
  font-size: 0.9rem;
  padding: 0.15rem 0.6rem;
}

.searches-toggle:hover {
  border-color: var(--cor-destaque);
  color: var(--cor-destaque);
}

/* Gravar e desistir lado a lado, e não empilhados como o resto do
   `.search-form`: são a mesma decisão, tomada de uma vez, e a coluna do
   formulário os apresentaria como se fossem dois passos a cumprir. */
.search-actions {
  align-items: center;
  display: flex;
  gap: 1rem;
}

/* "Cancelar" não compete com "Guardar alterações": o secundário é texto e o
   primário é o bloco de cor. Dois controles com a mesma ênfase obrigariam a ler
   os dois antes de achar aquele a que se veio. */
.search-cancel {
  color: var(--cor-suave);
  font-size: 0.9rem;
}

.search-cancel:hover {
  color: var(--cor-destaque);
}

/* --- Achados --------------------------------------------------------------- */

/* O filtro é uma linha de controles curtos, não um formulário empilhado como o de
   cadastro: os três selects e o "Filtrar" respondem juntos ("mostre-me isto"), e
   lado a lado é como se lê essa combinação de relance. `flex-wrap` deixa-os
   descerem para uma segunda linha num ecrã estreito em vez de esticar a página.
   `align-items: flex-end` alinha o botão à base dos selects, e não ao topo dos
   rótulos acima deles. */
.findings-filter {
  align-items: flex-end;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 0 0 1.5rem;
}

/* Cada select empilha rótulo sobre a caixa: o `<label>` embrulha os dois, então
   clicar no nome foca o select — o mesmo alvo grande que `.search-check` dá às
   caixas do cadastro. */
.findings-filter-field {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.findings-filter-label {
  color: var(--cor-suave);
  font-size: 0.85rem;
}

/* Reusa a moldura do `.search-input` (borda, raio, fonte herdada): o select nasce
   com a fonte e a caixa do sistema, estranhas ao resto do painel. */
.findings-filter-select {
  border: 1px solid var(--cor-borda);
  border-radius: 0.25rem;
  font: inherit;
  padding: 0.4rem 0.5rem;
}

.findings-filter-select:focus {
  border-color: var(--cor-destaque);
  outline: 2px solid var(--cor-destaque);
  outline-offset: 1px;
}

/* A GRELHA de achados. `auto-fill` + `minmax` em vez de um número fixo de colunas:
   o browser decide quantas cabem — 2 no telemóvel, 6 num ecrã largo —, sem uma media
   query por degrau.

   `11rem` e não `15rem`: a miniatura só precisa de dizer "é uma secretária escura" ou
   "é uma caixa da IKEA", e isso lê-se pequeno. Cada rem a menos é mais uma coluna, e
   numa rodada de 278 achados a diferença entre 2 e 6 colunas é entre 139 e 46 linhas
   de scroll — é a diferença entre triar e desistir. */
.findings-grid {
  display: grid;
  gap: 0.75rem;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  list-style: none;
  margin: 1.25rem 0 0;
  padding: 0;
}

.finding-card {
  background: var(--cor-cartao);
  border: 1px solid var(--cor-borda);
  border-radius: var(--raio);
  box-shadow: var(--sombra);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: border-color 0.12s, transform 0.12s;
}

.finding-card:hover {
  border-color: var(--cor-destaque);
  transform: translateY(-2px);
}

/* O card tratado fica esmaecido — não riscado nem escondido: o achado continua útil
   (o link ainda abre o anúncio), só já foi visto. Riscá-lo diria "descartado", e
   escondê-lo seria a exclusão que a curadoria recusa. O emblema carrega a marca
   textual; esta cor é o reforço de relance, não a única pista.

   `:hover` devolve a opacidade: rever um tratado é um gesto legítimo, e um card que
   fica apagado ao passar o rato parece desligado. */
.finding-treated {
  opacity: 0.5;
}

.finding-treated:hover {
  opacity: 1;
}

/* DESCARTADO: mais apagado que o tratado e dessaturado, porque as duas decisões não
   são a mesma. Tratado é um resultado ("lidei com isto") e continua a merecer o olhar;
   descartado é ruído que a pessoa mandou embora — e agora FICA na grelha, cinzento,
   até a próxima rodada, em vez de sumir debaixo do dedo de quem clicou.

   `grayscale` na foto e não só opacidade: numa grelha de miniaturas coloridas, meia
   opacidade ainda salta à vista. Sem cor, o card sai do caminho sem sair da tela.

   `:hover`/`:focus-within` devolvem tudo: mudar de ideia é o ponto de ele ainda estar
   aqui, e um card que continua apagado enquanto se mexe nele parece desligado. O
   `focus-within` é o que faz isso valer para quem chega pelo teclado, e não só para
   quem tem rato. */
.finding-discarded {
  filter: grayscale(100%);
  opacity: 0.4;
}

.finding-discarded:hover,
.finding-discarded:focus-within {
  filter: none;
  opacity: 1;
}

/* A transição é a razão de o Diego ter pedido isto: sem ela o card SALTA de normal
   para cinzento e a mudança lê-se como um glitch — com ela, vê-se o que aconteceu.
   Curta de propósito: 150ms informa, 400ms atrasa quem está a varrer 100 cards.

   `prefers-reduced-motion` respeitado: para quem pediu menos movimento, o estado final
   é o mesmo e só a animação sai. */
.finding-card {
  transition: opacity 150ms ease-out, filter 150ms ease-out;
}

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

.finding-thumb-link {
  display: block;
  line-height: 0;
  overflow: hidden;
  position: relative;
}

/* `aspect-ratio` + `object-fit: cover` e não altura livre: sem isto cada foto traria
   a sua proporção, a grelha ficaria serrilhada e os preços saltariam de linha — o
   oposto de uma tela que se lê de relance. O recorte é aceitável porque a miniatura é
   uma pista, não a avaliação: quem decide abre o anúncio. */
.finding-thumb {
  aspect-ratio: 1 / 1;
  background: var(--cor-fundo);
  display: block;
  object-fit: cover;
  width: 100%;
}

/* Mesmo espaço que a foto ocuparia, para o card sem imagem não encolher e desalinhar
   a grelha. */
.finding-thumb-empty {
  align-items: center;
  color: var(--cor-suave);
  display: flex;
  font-size: 0.75rem;
  justify-content: center;
  line-height: 1;
}

/* O emblema flutua SOBRE a foto, e não numa linha própria: numa grelha densa cada
   linha de texto empurra o card inteiro para baixo, e "Tratado" só precisa de ser
   visto — não de ocupar altura. O pendente não tem emblema nenhum: é o estado neutro
   e a maioria, e marcá-lo encheria a grelha de ruído. */
/* FAIXA diagonal no canto, e não uma pílula: a marca de estado tinha de gritar (o
   pedido foi "quase invisível"). Uma banda atravessa o canto superior esquerdo da
   foto, rodada -45°, e o `overflow: hidden` do `.finding-thumb-link` corta-lhe as
   pontas — o mesmo desenho do "VENDIDO". `pointer-events: none` para não roubar o
   clique da foto. Cor neutra = tratado; as classes abaixo trocam-na. */
.finding-badge {
  background: rgb(43 38 34 / 92%);
  box-shadow: 0 2px 4px rgb(0 0 0 / 28%);
  color: #fff;
  /* A banda é mais LARGA que o texto de propósito: medido, "DESCARTADO" (o rótulo mais
     longo) tem ~142px e as pontas rodadas perdem ~15px no recorte do canto. Com a banda
     a 180px o texto centra-se com margem dos dois lados e a parte visível mostra-o
     inteiro; "GOSTEI"/"TRATADO" sobram folgados. Texto == banda cortava a última letra. */
  font-size: 0.56rem;
  font-weight: 700;
  left: -54px;
  letter-spacing: 0.02em;
  padding: 0.16rem 0;
  pointer-events: none;
  position: absolute;
  text-align: center;
  text-transform: uppercase;
  top: 20px;
  transform: rotate(-45deg);
  width: 180px;
  z-index: 1;
}

/* O emblema do descartado em vermelho-terra e não no castanho do tratado: são duas
   decisões diferentes, e dois emblemas iguais com texto diferente obrigariam a LER
   para distinguir — que é o oposto de uma grelha que se varre de relance. Reusa a cor
   de perigo do vocabulário, a mesma da zona de perigo. */
.finding-badge-descartado {
  background: rgb(163 52 31 / 95%);
}

/* O sim da triagem. Verde e não o castanho do painel: ele tem de se distinguir do
   "Tratado" (o emblema neutro) sem hesitação, porque os dois convivem na mesma grelha
   durante o pente fino — um a dizer "falta ver", o outro "já vi". */
.finding-badge-gostei {
  background: rgb(45 106 79 / 95%);
}

.finding-body {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.55rem 0.6rem 0.6rem;
}

/* O preço é o maior texto do card: com a foto, é o par que decide "vale a pena
   olhar". */
.finding-price {
  font-size: 1.05rem;
  font-weight: 700;
  margin: 0;
  /* À direita: numa coluna de cards, os preços alinham e comparam-se de relance. */
  text-align: right;
}

/* UMA linha de metadata, e não três: plataforma, data e busca em três parágrafos
   cinzentos empurravam o card para 600px de altura e afogavam o preço. O `title` traz
   o resto ao passar o rato — e o que decide triagem é a foto e o preço, não a hora
   exata em que o radar passou. */
/* Plataforma · título numa linha. Flex e não texto corrido porque só o TÍTULO trunca:
   a plataforma ("OLX") é curta e aparece inteira — se a linha truncasse junta, um
   título longo comeria o "OLX" e o card não diria de onde é. */
.finding-meta {
  align-items: baseline;
  color: var(--cor-suave);
  display: flex;
  font-size: 0.78rem;
  gap: 0.3rem;
  margin: 0;
  min-width: 0;
}

.finding-plat {
  flex-shrink: 0;
}

.finding-plat::after {
  color: var(--cor-borda);
  content: " ·";
}

/* O título é quem cede: cresce até ao limite do card e corta com "…". O `min-width: 0`
   no pai é o que deixa o flex encolher abaixo do conteúdo — sem ele, um título longo
   esticaria o card e reintroduziria o scroll horizontal. */
.finding-titulo {
  color: var(--cor-texto);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* O local, abaixo do nome: menor e mais apagado — é contexto, não decisão. */
.finding-local {
  color: var(--cor-suave);
  font-size: 0.72rem;
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.finding-open {
  color: var(--cor-destaque);
  font-size: 0.8rem;
  margin-top: 0.1rem;
}

/* O comentário RECOLHIDO num `<details>`, e é a mudança que devolve o card ao
   tamanho de um card: a textarea + "Guardar" em TODOS ocupavam metade da altura, para
   uma ação que se usa numa mão-cheia de achados. `<details>` é HTML puro — sem uma
   linha de JS, que é o que o "quase sem JavaScript" da stack pede. */
.finding-extra {
  border-top: 1px solid var(--cor-borda);
  margin-top: 0.4rem;
  padding-top: 0.4rem;
}

.finding-extra > summary {
  color: var(--cor-suave);
  cursor: pointer;
  font-size: 0.78rem;
  list-style: none;
}

.finding-extra > summary::-webkit-details-marker {
  display: none;
}

.finding-extra > summary:hover {
  color: var(--cor-destaque);
}

/* O aviso de que há nota guardada tem de aparecer com o `<details>` FECHADO — senão
   recolher o comentário esconderia a existência dele, e a nota que a pessoa escreveu
   sumiria da tela sem nada a denunciar. */
.finding-has-note > summary::after {
  content: " •";
  color: var(--cor-destaque);
}

.finding-actions {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-top: 0.4rem;
}


.findings-treat-form,
.findings-comment-form {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin: 0;
}

.findings-comment-label {
  color: var(--cor-suave);
  font-size: 0.85rem;
}

/* Espelha o `.search-input` no visual, mas é textarea: `resize: vertical` deixa
   crescer uma nota longa sem alargar a coluna (um `resize: both` esticaria a
   célula e desalinharia a tabela). `font: inherit` porque a textarea nasce com
   fonte monoespaçada do browser, estranha ao resto do painel. */
/* `width: 100%` + `box-sizing` e NAO `min-width`: o card e estreito, e um minimo
   fixo (que servia na celula larga da tabela) faria a textarea transbordar para fora
   da borda do card. `resize: vertical` deixa crescer uma nota longa sem alargar o
   card e desalinhar a grelha. `font: inherit` porque a textarea nasce monoespacada. */
.findings-comment {
  border: 1px solid var(--cor-borda);
  border-radius: 0.25rem;
  box-sizing: border-box;
  font: inherit;
  font-size: 0.9rem;
  padding: 0.35rem 0.5rem;
  resize: vertical;
  width: 100%;
}

.findings-comment:focus {
  border-color: var(--cor-destaque);
  outline: 2px solid var(--cor-destaque);
  outline-offset: 1px;
}

/* --- Zona de perigo ----------------------------------------------------------
   Separada por uma borda e no fim da página: o que se faz aqui não tem desfazer, e
   não deve estar no caminho de quem veio guardar uma chave. A cor de erro é o único
   uso dela fora de uma mensagem de erro — e é deliberado: é a mesma linguagem
   ("cuidado") aplicada a uma ação em vez de a um aviso. */
.perigo {
  border-top: 1px solid var(--cor-borda);
  margin-top: 3rem;
  padding-top: 1.5rem;
}

.perigo-titulo {
  color: var(--cor-erro);
  font-size: 1.1rem;
  margin: 0 0 1rem;
}

.perigo-acao {
  border: 1px solid var(--cor-borda);
  border-radius: var(--raio);
  margin-bottom: 1rem;
  max-width: 34rem;
  padding: 0.85rem 1rem;
}

.perigo-acao-titulo {
  font-size: 0.95rem;
  margin: 0 0 0.35rem;
}

.perigo-aviso {
  background: #fdf3f1;
  border-radius: 0.25rem;
  color: var(--cor-erro);
  font-size: 0.85rem;
  margin: 0.5rem 0 0;
  padding: 0.4rem 0.6rem;
}

/* Campo e botão lado a lado: são um gesto só — escrever a palavra e confirmar. */
.perigo-form {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0.75rem 0 0;
}

.perigo-form .search-input {
  flex: 1 1 12rem;
  min-width: 0;
}

.perigo-ok {
  color: var(--cor-destaque);
  font-size: 0.9rem;
  margin: 0 0 1rem;
}

/* O terceiro botão do vocabulário, e o único que grita: a borda vermelha é o que
   distingue "apagar" de "guardar" antes de a pessoa ler o rótulo. Preenchido só no
   hover — um botão vermelho sólido parado na página puxa o olho para a coisa mais
   perigosa da tela. */
.botao-perigo {
  background: var(--cor-cartao);
  border: 1px solid var(--cor-erro);
  color: var(--cor-erro);
  font-weight: 600;
}

.botao-perigo:hover {
  background: var(--cor-erro);
  color: var(--cor-fundo);
}

/* Descartar e "Curar" na mesma linha: um sai da frente, o outro abre a curadoria.
   `space-between` para o descarte ficar longe do "Curar" — são a ação destrutiva e a
   construtiva do mesmo card, e encostá-las convida ao clique errado. */
.finding-triagem {
  align-items: center;
  border-top: 1px solid var(--cor-borda);
  display: flex;
  gap: 0.5rem;
  justify-content: space-between;
  margin-top: 0.4rem;
  padding-top: 0.4rem;
}

.finding-descartar-form {
  margin: 0;
}

/* Discreto até se aproximar: é o botão MAIS clicado da triagem, então tem de estar
   sempre à mão — mas um botão vermelho sólido em cada um de 100 cards faria a grelha
   inteira gritar. Cinzento em repouso, vermelho no hover. */
.finding-descartar {
  background: none;
  border: 1px solid transparent;
  border-radius: 0.375rem;
  color: var(--cor-suave);
  cursor: pointer;
  font: inherit;
  /* Mais discretos, a pedido: o rótulo encolhe e apaga — a decisão está na foto e no
     título, não no peso destes botões. A cor viva só chega no hover/toque. */
  font-size: 0.68rem;
  opacity: 0.75;
  padding: 0.1rem 0.3rem;
}

.finding-descartar:hover {
  background: #fdf3f1;
  border-color: var(--cor-erro);
  color: var(--cor-erro);
  opacity: 1;
}

/* O gémeo do descartar, e a simetria é o desenho: mesmo tamanho, mesmo peso, mesma
   discrição em repouso. São as duas metades de UMA decisão, e um deles a gritar
   inclinaria a triagem — a cor só aparece no toque, para cada um dizer o que é. */
.finding-gostar {
  background: none;
  border: 1px solid transparent;
  border-radius: 0.375rem;
  color: var(--cor-suave);
  cursor: pointer;
  font: inherit;
  /* Mais discretos, a pedido: o rótulo encolhe e apaga — a decisão está na foto e no
     título, não no peso destes botões. A cor viva só chega no hover/toque. */
  font-size: 0.68rem;
  opacity: 0.75;
  padding: 0.1rem 0.3rem;
}

.finding-gostar:hover {
  background: #eef6f1;
  border-color: #2d6a4f;
  color: #2d6a4f;
  opacity: 1;
}

/* A `.finding-triagem` é o PAR — Descartar e Gostar, e mais nada. Os dois repartem a
   linha em vez de se espremerem contra um terceiro: `space-around` dá-lhes o mesmo
   peso, que é o que a decisão é (não e sim, sem favorito). A gaveta do "Tratar" é
   irmã, não filha, e vem por baixo. */
.finding-triagem > form {
  flex: 1;
}

.finding-triagem .finding-descartar,
.finding-triagem .finding-gostar {
  align-items: center;
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
  line-height: 1.25;
  width: 100%;
}

/* O ícone acima da palavra: é o que dá aos dois a MESMA altura (medido: "Descartar"
   partia numa 2a linha e "Gostar" não, e os gémeos ficavam desalinhados por 28px) e o
   que faz o alvo do polegar valer o card inteiro em vez de uma linha de 12px. */
.finding-acao-icone {
  font-size: 0.9rem;
  line-height: 1;
}

/* A palavra numa linha só. Medido: "Não gostar" mede ~57px num botão com 66px de
   texto — cabe —, mas o browser quebra no espaço à mínima folga e aí este botão fica
   28px mais alto que o gémeo. Os dois são UMA decisão: desalinhados, não se leem como
   par. Se um dia um rótulo não couber, é o rótulo que muda, não esta linha. */
.finding-triagem .finding-descartar span:not(.finding-acao-icone),
.finding-triagem .finding-gostar span:not(.finding-acao-icone) {
  white-space: nowrap;
}

/* O `.finding-extra` vem logo a seguir à `.finding-triagem`, que já traz a borda de
   cima: uma segunda linha aqui desenharia um risco duplo dentro do card. */
.finding-extra {
  border-top: none;
  margin-top: 0.15rem;
  padding-top: 0;
}

/* --- TELEMÓVEL ---------------------------------------------------------------
   A usuária vai garimpar no telefone: é ali que o painel tem de funcionar, e era
   ali que ele estava pior. Medido num iPhone (390px) antes desta secção existir:

   - o header transbordava: "Configurações" cortado ao meio e o "Sair" FORA do ecrã,
     sem forma de sair da sessão;
   - a tabela de buscas forçava a página a 1030px de largura — scroll horizontal no
     ecrã inteiro, o pecado capital do telemóvel;
   - a grelha de achados dava UM card por ecrã (a foto sozinha ocupava 700 dos 844px):
     triar 100 achados eram 100 scrolls de tela cheia.

   O alvo aqui não é "caber": é TRIAR. Dois cards por ecrã e a mão no polegar. */
@media (max-width: 40rem) {
  /* O header envolve em vez de cortar. `flex-wrap` sozinho não chegava: o
     `margin-right: auto` da marca empurrava a navegação para fora antes de a linha
     partir. */
  .site-header {
    flex-wrap: wrap;
    gap: 0.5rem;
    padding: 0.75rem 1rem;
  }

  .site-brand {
    /* Sem `margin-right: auto`: no telemóvel ele empurrava a navegação para fora do
       ecrã em vez de a deixar quebrar para a linha de baixo. */
    margin-right: 0;
    /* `nowrap` porque "garimpo-vintage" partia em duas linhas no meio do hífen. */
    white-space: nowrap;
  }

  .site-nav {
    /* Ocupa a linha toda e distribui: os quatro destinos cabem em duas linhas em vez
       de saírem pela direita. */
    flex: 1 0 100%;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-right: 0;
    order: 3;
  }

  .site-main {
    padding: 1rem;
  }

  h1 {
    font-size: 1.35rem;
    margin-bottom: 0.35rem;
  }

  /* DOIS cards por ecrã (medido: 390 - 32 de padding = 358px; 2 × 8.5rem + gap
     cabem, 3 não). É a diferença entre triar e desistir — o mesmo argumento que
     levou o desktop de 2 para 6 colunas, aplicado ao ecrã onde ela vai estar.
     A foto de ~160px ainda diz "é uma cómoda escura", que é tudo o que a triagem
     pede: quem decide abre o anúncio. */
  .findings-grid {
    gap: 0.5rem;
    grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  }

  .finding-body {
    padding: 0.4rem 0.45rem 0.5rem;
  }

  .finding-price {
    font-size: 0.95rem;
  }

  .finding-meta {
    font-size: 0.7rem;
  }

  /* Alvos de dedo, não de rato: 44px é o mínimo do guia da Apple, e "Descartar" é o
     botão mais clicado da triagem — errá-lo abre o anúncio numa aba nova. */
  .finding-descartar,
  .finding-extra > summary {
    font-size: 0.75rem;
    min-height: 2.2rem;
    padding: 0.45rem 0.3rem;
  }

  /* O filtro come um terço do ecrã antes do primeiro achado. Os três selects passam a
     dividir a linha em vez de empilhar, e o rótulo encolhe. */
  .findings-filter {
    gap: 0.4rem;
  }

  .findings-filter-field {
    flex: 1 1 8rem;
  }

  .findings-filter-label {
    font-size: 0.7rem;
  }

  /* A TABELA de buscas vira CARDS empilhados. Cinco colunas não cabem em 390px, e as
     duas saídas fáceis são as duas erradas: deixar a tabela esticar arrasta a PÁGINA
     inteira de lado (media: 1030px), e prendê-la num `overflow-x` esconde a última
     coluna — que é justamente a das AÇÕES. Medido: com o scroll interno, o "Rodar
     agora" ficava fora do ecrã, atrás de um arrastar que ninguém descobre, e a tela
     passava a mostrar uma busca que não se consegue correr.

     Empilhar resolve os dois: cada linha é um bloco, cada célula uma linha rotulada
     pelo `data-label` do template, e as ações ficam à vista no fim do card. */
  .searches-table thead {
    /* `clip-path` e não `display: none`: o cabeçalho continua a existir para o leitor
       de tela (que ainda navega a tabela como tabela), e some só do olho — o rótulo
       visível passa a ser o `data-label`.

       Mas o `clip-path` recorta o DESENHO e não o LAYOUT: medido, o `<thead>` continuava
       a medir 433px e a esticar a página a 449 num ecrã de 390 — invisível e a arrastar
       tudo de lado, que é o pior dos dois mundos. As quatro linhas abaixo tiram-no do
       fluxo de verdade (é o padrão `.visually-hidden`, e é o que faltava). */
    clip-path: inset(50%);
    height: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
  }

  .searches-table,
  .searches-table tbody,
  .searches-table tr,
  .searches-table td {
    display: block;
    width: auto;
  }

  .searches-table tr {
    background: var(--cor-cartao);
    border: 1px solid var(--cor-borda);
    border-radius: var(--raio);
    margin-bottom: 0.75rem;
    padding: 0.6rem 0.75rem;
  }

  .searches-table td {
    border-bottom: none;
    display: flex;
    gap: 0.75rem;
    justify-content: space-between;
    padding: 0.15rem 0;
  }

  /* A célula de palavras obrigatórias VAZIA some do card, e não fica uma faixa em
     branco: no card cada `<td>` é uma linha `flex` com padding, e mesmo sem
     `data-label` o `td::before` resolve `attr(...)` para "" e ainda ocupa espaço.
     Como quase toda busca não filtra por palavras, essa faixa apareceria em quase
     todos os cards. `display: none` só aqui (o card já não é tabela, não há coluna
     a desalinhar) mantém a ausência a ser mesmo ausência, como no desktop. */
  .searches-table td.searches-obrigatorias-vazia {
    display: none;
  }

  /* O rótulo vem do `data-label` do `<td>`: é o `<thead>` escondido, devolvido linha a
     linha. Sem isto, o card seria "Comoda Luis XV / OLX, Vinted / 200 € / Ativa" —
     quatro valores sem nome. */
  .searches-table td::before {
    color: var(--cor-suave);
    content: attr(data-label);
    font-size: 0.8rem;
    white-space: nowrap;
  }

  /* A célula de ações não leva rótulo nem alinhamento de par: são botões, e o
     `space-between` os empurraria para os cantos opostos do card. */
  .searches-table td.searches-actions {
    border-top: 1px solid var(--cor-borda);
    display: block;
    margin-top: 0.4rem;
    padding-top: 0.5rem;
    white-space: normal;
  }

  .searches-table td.searches-actions::before {
    content: none;
  }

  /* Botões de dedo: ocupam a linha e ficam altos o suficiente para não se errar. */
  .searches-actions-group {
    gap: 0.5rem;
  }

  .searches-actions-group .botao {
    flex: 1 1 auto;
    padding: 0.55rem 0.5rem;
  }

  /* Formulários ocupam a largura toda: um `max-width: 26rem` num ecrã de 390px já é
     a largura toda, mas o `.perigo-acao` e o `.login-form` não eram. */
  .search-form,
  .login-form,
  .perigo-acao {
    max-width: none;
  }
}

/* --- Histórico: o link que leva à confirmação de apagar -----------------------
   Link e não botão, e é isso que a cor diz: ele NÃO apaga — leva à tela que
   pergunta. A cor de erro é o vocabulário de perigo do painel (a mesma da zona de
   perigo), e o peso normal é o que o impede de gritar em cada linha de uma tabela
   que se lê de relance. */
.history-apagar {
  color: var(--cor-erro);
  font-size: 0.85rem;
  text-decoration: none;
  white-space: nowrap;
}

.history-apagar:hover {
  text-decoration: underline;
}

/* --- Histórico: o aviso de "a plataforma deu, o filtro comeu" ----------------
   Aparece só quando `vistos > 0` e `novos == 0`. Não é erro — a rodada correu bem —,
   e por isso não usa a cor de perigo: é um SINAL de que o filtro pode estar apertado
   demais, ou escrito com um erro de dedo. Sem ele, essa linha lia-se exatamente como
   "a plataforma não tinha nada", e uma busca partida ficava invisível para sempre. */
.history-filtrou {
  background: #f3ece2;
  border-radius: 0.25rem;
  color: var(--cor-suave);
  font-size: 0.75rem;
  margin-left: 0.35rem;
  padding: 0.1rem 0.35rem;
  white-space: nowrap;
}

/* "Já vistos": os anúncios passaram nos filtros e o radar já os conhecia — o estado
   NORMAL de quem corre todo dia. Discreto de propósito, e visualmente distinto do
   "filtrado" ao lado: aquele pede atenção (a busca pode estar partida), este só
   explica um zero que de outro modo pareceria defeito. */
.history-conhecidos {
  background: var(--cor-fundo);
  border: 1px solid var(--cor-borda);
  border-radius: 0.25rem;
  color: var(--cor-suave);
  font-size: 0.75rem;
  margin-left: 0.35rem;
  padding: 0.1rem 0.35rem;
  white-space: nowrap;
}

/* "Rodar todas": o botão e a nota lado a lado, com a nota a quebrar no telemóvel.
   `align-items: center` para a nota alinhar pelo meio do botão e não pelo topo. */
.searches-run-all {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 0 0 1rem;
}
