/*
  Sem framework, de propósito: o site é o produto e a velocidade dele é fator de
  ranqueamento. Carregar 200 KB de CSS para usar uma grade trabalha contra a fatia.

  Pele "Aconchego" — portada de docs/atys-modulo-imobiliario-site-template.html
  (linhas 11-826). --brand, --brand-ink, --on-brand, --brand-wash, --brand-soft e
  --brand-line NÃO estão aqui: são inline, por site, em partials/tema.blade.php
  (BrandPalette::from()) — este arquivo só os consome.

  A animação de entrada por rolagem do protótipo (.reveal, regra no fim deste arquivo) é
  opcional na spec (§7) e só existe condicionada a `.js-reveal` no <html> — classe que o
  script do fim do <body> (S5d) só acrescenta depois que o IntersectionObserver que ele cria
  está de pé. Sem isso, um elemento marcado `.reveal` ficaria invisível para sempre em vez de
  só sem entrada suave.
*/

:root {
  color-scheme: light;

  --bg: #F7F4EF;
  --surface: #FFFFFF;
  --surface-2: #F2EDE5;
  --surface-3: #E9E2D7;
  --ink: #2B2621;
  --ink-2: #574F46;
  --muted: #8A8176;
  --line: #E6DFD4;
  --line-2: #D5CBBC;

  --serif: "Fraunces", Georgia, "Times New Roman", serif;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --r: 4px;
  --r-sm: 2px;

  --sh-1: 0 1px 2px rgba(58, 44, 30, .04), 0 3px 10px rgba(58, 44, 30, .05);
  --sh-2: 0 2px 4px rgba(58, 44, 30, .05), 0 14px 32px rgba(58, 44, 30, .11);
  --sh-3: 0 24px 60px rgba(40, 30, 20, .20);

  --ease: cubic-bezier(.2, .7, .2, 1);
  --hdr: 68px;
}

/*
  Fraunces, self-hosted (S5b-D4): nada de fonts.googleapis.com/fonts.gstatic.com na página
  servida — só um WOFF2 em public/fonts/, subset latino, da distribuição oficial do Google
  Fonts (repositório google/fonts, licença SIL OFL — LICENSE-fraunces.txt ao lado).

  Um arquivo só, não dois: esta versão da Fraunces (v38) é uma fonte VARIÁVEL — o próprio
  Google serve o mesmo WOFF2 pros pesos 600 e 700 (testado: os quatro pesos 400/600/700/900
  do css2 apontam pro mesmo arquivo), com o eixo `wght` resolvido pelo navegador a partir do
  `font-weight` de cada @font-face. `font-weight: 600 700` é o range que cobre os dois pesos
  que este CSS usa (h1/h2/h3 em 500 caem no peso mais próximo do range, 600).

  font-display: swap para o texto aparecer com a fonte do sistema antes da @font-face
  chegar, em vez de invisível (FOIT).
*/
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 600 700;
  font-display: swap;
  src: url("/fonts/fraunces-latin-var.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

* { box-sizing: border-box; }
/*
  Fix (revisão final): `scroll-padding-top` sem par era um `scroll-behavior` que levava o alvo
  para debaixo do cabeçalho. Esta fatia introduziu os ÚNICOS links de âncora do site (`/#sobre`
  e `/#contato`, no `.nav` e no `.mnav`); numa home mais longa que a do demo — a partir do
  momento em que o alvo fica abaixo da dobra — o navegador encosta o topo da seção em y=0, e o
  `.site-header` (sticky, `--hdr` de altura) cobre o começo dela. Em `#contato` é pior: a seção
  é `.section-colada` (`padding-top: 0`), então o card inteiro some sob o cabeçalho.

  `--hdr` muda dentro do @media do cabeçalho (68px → 60px) e o cálculo acompanha sozinho. Os
  16px são a folga para o alvo não nascer colado na borda de baixo do cabeçalho.
*/
html { scroll-behavior: smooth; scroll-padding-top: calc(var(--hdr) + 16px); }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.6 var(--sans);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-family: var(--serif); font-weight: 500; letter-spacing: -.01em; line-height: 1.15; margin: 0; }
p { margin: 0; }
a { color: inherit; }
button { font: inherit; color: inherit; }
img { max-width: 100%; }

/*
  Revisão final: o anel era `var(--brand)` cru. Marca clara sobre o fundo creme (o caso que a
  S5a documentou) dava um foco que não se via — e o indicador de foco tem piso de contraste
  próprio na WCAG (1.4.11, 3:1). `--focus` é a marca já escurecida até cruzar esse piso
  (BrandPalette::foco), então o anel continua sendo a cor do cliente.

  O `box-shadow` branco preenche a folga do `outline-offset`: sobre fundo escuro — hero com
  foto, lightbox — quem garante o contraste é ele, porque ali é o `--focus` (escuro) que
  desaparece. Os dois juntos funcionam nos dois fundos, sem o CSS precisar saber em qual está.
*/
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; box-shadow: 0 0 0 2px var(--surface); }

.wrap { max-width: 1240px; margin: 0 auto; padding: 0 24px; }

/* Ícone consumido via <svg class="i"><use href="/img/icones.svg#i-bed"></use></svg>. */
.i {
  width: 18px; height: 18px; flex: none;
  stroke: currentColor; fill: none; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
}

.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ---------- legado que sobrevive à pele ----------
   Cinco classes de fora do protótipo Aconchego, usadas pelo formulário de contato e pelo
   Alpine da galeria — nada aqui mudou de nome ou de regra. */

/* Honeypot: fora do fluxo de leitura de tela, sem depender de display:none (padrão que bots já detectam). */
.fora-da-tela { position: absolute; left: -9999px; }

.consentimento { flex-direction: row !important; align-items: flex-start; gap: .5rem !important; }
.consentimento input { width: auto; }

.sucesso { color: #1a7f37; font-weight: 600; }
.erro { color: #c0392b; }

[x-cloak] { display: none !important; }

/* ---------- botões, chips, links ---------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 42px; padding: 0 18px;
  border: 1px solid var(--line-2); border-radius: var(--r);
  background: var(--surface); color: var(--ink);
  font: 600 14px/1 var(--sans); text-decoration: none; white-space: nowrap; cursor: pointer;
  transition: background .2s, border-color .2s, color .2s, box-shadow .25s, transform .2s var(--ease);
}
.btn:hover { border-color: var(--ink-2); box-shadow: var(--sh-1); }
.btn:active { transform: translateY(1px); }
.btn-brand { background: var(--brand); border-color: var(--brand); color: var(--on-brand); }
.btn-brand:hover {
  background: var(--brand-ink); border-color: var(--brand-ink);
  box-shadow: 0 6px 18px color-mix(in oklab, var(--brand) 30%, transparent);
}
.btn-lg { height: 50px; padding: 0 22px; font-size: 15px; }
.btn-sm { height: 34px; padding: 0 12px; font-size: 13px; }
.btn-block { width: 100%; }
.btn-icon { width: 42px; padding: 0; }

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: 34px; padding: 0 12px;
  border: 1px solid var(--line-2); border-radius: 6px;
  background: var(--surface); color: var(--ink-2);
  font: 500 13px/1 var(--sans); text-decoration: none; white-space: nowrap; cursor: pointer;
  transition: border-color .2s, color .2s, background .2s, box-shadow .2s, transform .2s var(--ease);
}
.chip:hover { border-color: var(--ink-2); color: var(--ink); }
.chip small { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.chip .i { width: 14px; height: 14px; }
.chip[aria-pressed="true"] {
  border-color: var(--brand); background: var(--brand-wash); color: var(--brand-ink);
}
.chip[aria-pressed="true"] small { color: var(--brand-ink); }
.chip:disabled { opacity: .45; cursor: not-allowed; border-color: var(--line-2); color: var(--ink-2); }
.chip-x .i { transition: transform .25s var(--ease); }
.chip-x:hover .i { transform: rotate(90deg); }
@keyframes chipIn { from { opacity: 0; transform: scale(.85); } }

select.chip {
  appearance: none; padding-right: 32px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238A8176' stroke-width='1.5' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; background-size: 14px;
}

.link-more {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--brand-ink); font-weight: 600; font-size: 14px; text-decoration: none;
}
.link-more .i { width: 16px; height: 16px; transition: transform .3s var(--ease); }
.link-more:hover .i { transform: translateX(4px); }

.eyebrow {
  display: inline-flex; align-items: center; gap: 10px;
  font: 600 11px/1 var(--sans); letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
}
.eyebrow::before { content: ""; width: 18px; height: 1px; background: var(--brand); }

/* ---------- foto placeholder ---------- */

.ph {
  --wx: 58%;
  position: relative; overflow: hidden;
  background: radial-gradient(50% 60% at var(--wx) 30%, rgba(255, 245, 225, .45), transparent 70%), var(--g);
}
.ph::before {
  content: ""; position: absolute; left: var(--wx); top: 16%; width: 22%; height: 44%;
  transform: translateX(-50%);
  background:
    linear-gradient(90deg, transparent calc(50% - .5px), rgba(255, 255, 255, .55) 50%, transparent calc(50% + .5px)),
    linear-gradient(180deg, rgba(255, 250, 240, .72), rgba(255, 250, 240, .22));
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .45);
}
.ph::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 30%;
  background: linear-gradient(180deg, rgba(60, 40, 20, .10), rgba(60, 40, 20, .24));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18);
}
.ph-1 { --g: linear-gradient(160deg, #E9DCC8 0%, #CBB293 55%, #9C7F60 100%); --wx: 62%; }
.ph-2 { --g: linear-gradient(155deg, #DDE3D6 0%, #AFBBA2 55%, #7C8A72 100%); --wx: 24%; }
.ph-3 { --g: linear-gradient(165deg, #F0D9C4 0%, #D7A785 50%, #A56B4E 100%); --wx: 68%; }
.ph-4 { --g: linear-gradient(160deg, #E4E1DA 0%, #BDB6AA 55%, #8B8275 100%); --wx: 34%; }
.ph-5 { --g: linear-gradient(170deg, #D6E0E6 0%, #A9BAC4 50%, #6F8290 100%); --wx: 52%; }
.ph-6 { --g: linear-gradient(160deg, #EFE3CF 0%, #D9C09A 55%, #AD8B5E 100%); --wx: 20%; }
.ph-7 { --g: linear-gradient(175deg, #C9D6DE 0%, #E8D9C2 45%, #B79A78 100%); --wx: 64%; }
.ph-8 { --g: linear-gradient(160deg, #E8D6CF 0%, #C7A79B 55%, #946F63 100%); --wx: 40%; }

/* ---------- cabeçalho ---------- */

.site-header {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  border-bottom: 1px solid transparent;
  transition: border-color .25s, box-shadow .25s, transform .35s var(--ease);
}
@media (prefers-reduced-motion: no-preference) {
  .site-header { backdrop-filter: saturate(1.2) blur(10px); -webkit-backdrop-filter: saturate(1.2) blur(10px); }
}
.site-header.is-scrolled { border-bottom-color: var(--line); box-shadow: 0 6px 18px rgba(58, 44, 30, .05); }
/*
  Fix (fechamento S5d): resíduo da decisão que fez a flutuação do `.mnav` depender do script
  (comentário do `.mnav` abaixo) — o `.site-header` continuava `position: sticky` mesmo sem
  JavaScript, com o `.mnav` em fluxo empurrando a própria altura do cabeçalho para 290px (375,
  quatro links + WhatsApp). Sticky e 290px juntos grudavam isso no topo pra sempre: medido a
  375 sem script, cabeçalho (0..290) mais a barra fixa (743..812) tomavam 359 dos 812px da
  tela, o botão "Buscar" do hero caía inteiro debaixo da barra fixa (y=750..800), e a âncora
  `/#sobre` — que só existe por causa desta fatia — parava em y=76 com o cabeçalho cobrindo
  até 290: 214px do começo da seção ficavam enterrados. `position: static` sem `.js-menu` tira
  o cabeçalho da equação: ele rola para fora como conteúdo normal, e os três sintomas somem
  juntos. Com `.js-menu` (script rodando) nada muda — o cabeçalho segue ~68px/60px e sticky
  como sempre foi.

  `#menu-btn` some junto: sem script aquele `<button>` não faz nada (só o script amarra o
  clique), e um botão morto visível é anunciado por leitor de tela como se funcionasse.
*/
html:not(.js-menu) .site-header { position: static; }
html:not(.js-menu) #menu-btn { display: none; }
.hdr { height: var(--hdr); display: flex; align-items: center; justify-content: space-between; gap: 24px; }

.brandmark { display: flex; align-items: center; gap: 10px; text-decoration: none; color: var(--ink); }
.brandmark .logo { height: 36px; width: auto; display: block; }
.brandmark .mono {
  width: 36px; height: 36px; display: grid; place-items: center;
  border: 1px solid var(--brand); border-radius: var(--r-sm); color: var(--brand);
  font-family: var(--serif); font-size: 19px;
}
.brandmark b { display: block; font-family: var(--serif); font-weight: 500; font-size: 19px; line-height: 1.1; }
.brandmark small { display: block; font-size: 11px; color: var(--muted); letter-spacing: .04em; }

.nav { display: flex; align-items: center; gap: 28px; }
/*
  :not(.btn) é o que deixa o botão de WhatsApp (um <a class="btn btn-brand">, não um link
  comum) entrar no .nav sem herdar o sublinhado nem o padding:6px 0 abaixo — sem isso, ".nav
  a" (especificidade 0,1,1) vence ".btn" (0,1,0) e esmaga a altura/o padding do botão.
*/
.nav a:not(.btn), .nav button:not(.btn) {
  position: relative; padding: 6px 0; border: 0; background: none; cursor: pointer;
  color: var(--ink-2); font-weight: 500; font-size: 14.5px; text-decoration: none;
  transition: color .2s;
}
.nav a:not(.btn)::after, .nav button:not(.btn)::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: var(--brand); transform: scaleX(0); transform-origin: left;
  transition: transform .35s var(--ease);
}
.nav a:not(.btn):hover, .nav button:not(.btn):hover { color: var(--ink); }
.nav a:not(.btn):hover::after, .nav button:not(.btn):hover::after { transform: scaleX(1); }
.nav a[aria-current="true"] { color: var(--ink); }
.nav a[aria-current="true"]::after { height: 2px; transform: scaleX(1); }

.hdr-mobile { display: none; gap: 8px; }

/*
  Fix (revisão final, achado crítico 1): a FLUTUAÇÃO do menu depende do script, a existência
  dele não. Antes, `position: absolute; top: 100%` estava aqui na regra base — e como o
  `#menu-btn` é um <button> sem form e sem href, que só faz algo com JavaScript, um visitante
  sem script ganhava um painel de 227px sobreposto ao hero (a 375px: y=78..305, por cima do
  eyebrow, do <h1> e de parte do lead), z-index 40, sem NENHUM jeito de fechar. Isso falsifica
  a S5d-D2 e o R2 da spec, que prometem degradar para "links empilhados".

  Agora o padrão dentro do @media é o fluxo normal: o painel empurra o conteúdo para baixo,
  como o `.nav` que ele substitui fazia antes desta fatia. A sobreposição só entra sob
  `.js-menu` no <html> — o mesmo mecanismo de `.js-reveal` (linha 1134) e de `.js-indicador`
  (linha 416), classe que o script do fim do <body> só acrescenta depois de amarrar o clique
  do botão. Sem script: sem classe, sem flutuação, nada tapado.
*/
.mnav {
  display: none;
  background: var(--surface); border-bottom: 1px solid var(--line);
  padding: 8px 16px 16px;
}
/*
  Sombra e animação vivem aqui junto da flutuação, não na base: as duas só fazem sentido para
  um painel que paira sobre o conteúdo. Em fluxo, a borda de baixo já separa o menu do hero.
*/
.js-menu .mnav {
  position: absolute; left: 0; right: 0; top: 100%;
  box-shadow: var(--sh-2); animation: rise .3s var(--ease);
}
.mnav a, .mnav button {
  display: block; width: 100%; text-align: left; padding: 12px 0; border: 0; background: none;
  border-bottom: 1px solid var(--line); text-decoration: none; font-size: 16px; cursor: pointer;
}

/* ---------- hero e busca ---------- */

.hero { position: relative; min-height: clamp(480px, 58vh, 640px); display: flex; align-items: center; overflow: hidden; color: #fff; }
/*
  Revisão final: `.hero-bg` era só a `<div>` decorativa do protótipo (um gradiente fazendo as
  vezes de foto). No site real ela é o `<img>` do hero (ver hero.blade.php: a foto é um <img>
  para o `hero_image_url` não ter contexto CSS por onde escapar) — daí `object-fit: cover`,
  que só afeta o elemento substituído. O gradiente continua aqui e serve de fundo enquanto a
  foto não chega, ou se ela falhar.
*/
.hero-bg {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  background:
    radial-gradient(55% 80% at 80% 28%, rgba(255, 226, 180, .55), transparent 62%),
    linear-gradient(118deg, #2E2620 0%, #5A4636 42%, #A8835F 78%, #D9B68C 100%);
}
@media (prefers-reduced-motion: no-preference) {
  .hero-bg { animation: kenburns 18s ease-out both; }
  @keyframes kenburns { from { transform: scale(1.07); } to { transform: scale(1); } }
}
.hero-bg::before {
  content: ""; position: absolute; right: 9%; top: 12%; width: 22%; height: 62%;
  background:
    linear-gradient(90deg, transparent calc(50% - .5px), rgba(255, 240, 215, .4) 50%, transparent calc(50% + .5px)),
    linear-gradient(180deg, transparent calc(40% - .5px), rgba(255, 240, 215, .4) 40%, transparent calc(40% + .5px)),
    linear-gradient(180deg, rgba(255, 238, 205, .38), rgba(255, 238, 205, .08));
  box-shadow: inset 0 0 0 1px rgba(255, 240, 215, .35);
}
.hero-bg::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 26%;
  background: linear-gradient(180deg, rgba(30, 20, 12, .15), rgba(30, 20, 12, .4));
}
.hero-shade { position: absolute; inset: 0; background: linear-gradient(90deg, rgba(26, 20, 15, .74) 0%, rgba(26, 20, 15, .38) 55%, rgba(26, 20, 15, .06) 100%); }
.hero-content { position: relative; width: 100%; padding-top: 48px; padding-bottom: 48px; }
.hero .eyebrow { color: rgba(255, 255, 255, .75); }
.hero .eyebrow::before { background: rgba(255, 255, 255, .7); }
/*
  Revisão final: `animation: rise` saiu do h1 e da `.lead` (e da `.search`, abaixo). A §7 da
  spec só autoriza a animação de entrada ABAIXO da dobra — estes três nascem na primeira
  tela, e `rise` começa em `opacity: 0`: com o CSS já baixado e o JS atrasado, o maior
  elemento da home nasce invisível e o LCP é medido depois da animação, não antes.
*/
.hero h1 { font-size: clamp(34px, 5vw, 58px); font-weight: 400; max-width: 16ch; margin: 16px 0 14px; }
.hero h1 em { font-style: italic; color: #F3DDBD; }
.hero .lead { max-width: 48ch; color: rgba(255, 255, 255, .84); font-size: 17px; margin-bottom: 28px; }
@keyframes rise { from { opacity: 0; transform: translateY(16px); } }

/*
  Hero sem foto (S5b §4.1, "sem imagem, fundo com a marca"): o fundo é a própria marca e o
  texto sai em --on-brand — o par que a BrandPalette escolhe comparando contraste, e o único
  jeito de o hero de um cliente com marca amarela não ficar branco sobre amarelo. Sem esta
  variante o `color: #fff` de `.hero` (que existe para o caso com foto, sobre o véu escuro)
  valia também aqui, sobre o creme da página: 1,06:1.

  As cores derivadas do texto secundário usam `opacity` sobre currentColor em vez de
  `rgba(255,255,255,…)`: --on-brand pode ser o tom ESCURO, e branco translúcido sobre uma
  marca clara seria invisível de novo.
*/
.hero-marca { background: var(--brand); color: var(--on-brand); }
.hero-marca .eyebrow { color: inherit; opacity: .78; }
.hero-marca .eyebrow::before { background: currentColor; }
.hero-marca .lead { color: inherit; opacity: .86; }
.hero-marca h1 em { color: inherit; }

.search {
  display: grid; grid-template-columns: auto minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1fr) auto; align-items: stretch;
  max-width: 1020px; padding: 10px;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--sh-2);
  transition: box-shadow .35s var(--ease), transform .35s var(--ease);
  /*
    Revisão final: sem `animation: rise` aqui — a busca do hero é o segundo elemento da
    primeira tela, e a §7 da spec só admite animação de entrada abaixo da dobra (ver o
    comentário em `.hero h1`).
  */
  /*
    Fix round 1 (revisão da Task 4): o comentário anterior dizia que `.search` precisava do
    próprio respiro porque era um parcial SOLTO, sem `.wrap` nem seção ao redor — premissa
    que a Task 4 derrubou ao aninhar a busca dentro de `.hero-content` (com hero) ou do
    `.wrap` do fallback sem hero (sem hero). As DUAS já centralizam a coluna e reservam
    espaço; o `auto` horizontal que sobrou centralizava só a `.search` (1020px) dentro da
    coluna inteira (até 1192px) — descolando-a até 86px à esquerda do `h1`/`.lead`, que
    ocupam a largura cheia e não têm `max-width`. Só `margin-top` fica: colapsa com o
    `margin-bottom` da `.lead` (28px, quando ela existe) e dá o mesmo respiro quando não
    existe (sem subtítulo, ou no fallback sem hero — onde o `<h1>` não tem margem própria).
    Sem `margin-bottom` aqui: o respiro abaixo já é o `padding-bottom` de `.hero-content`
    (48px) ou de `.section` no fallback (64px) — margem própria dobraria o espaço.
  */
  margin: 28px 0 0;
}
.search:focus-within { box-shadow: var(--sh-3); transform: translateY(-2px); }

.seg {
  position: relative; display: inline-grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  padding: 3px; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r);
  align-self: center;
}
.seg button {
  position: relative; z-index: 1; height: 44px; padding: 0 18px;
  border: 0; border-radius: 3px; background: none; cursor: pointer;
  color: var(--ink-2); font: 600 14px/1 var(--sans);
  transition: color .3s;
}
.seg button[aria-pressed="true"] { color: var(--on-brand); }
/*
  Task 4: o `.seg` do protótipo estiliza `<button>` — a busca do hero desta fatia usa dois
  <a> (mantêm `href` como fallback de navegação sem JavaScript). Mesma régua visual do botão,
  seletor estendido para `a`.

  Fix round 1: o atributo de estado deixou de ser decorativo — o Alpine de busca-hero.blade.php
  liga/desliga de verdade conforme a finalidade escolhida (venda/aluguel).

  Revisão final: o atributo era `aria-pressed`, inválido num <a> (é estado de `role="button"`).
  Agora é `aria-current` — "page" na barra de filtros (o link aponta pra página em que se está)
  e "true" na busca do hero (escolha ainda não navegada). O seletor casa pela PRESENÇA do
  atributo: nas duas views ele só existe no selecionado.

  COMO A SELEÇÃO É PINTADA — este trio de regras é o ponto mais denso do arquivo, e este
  comentário é o mapa dele. As duas `.seg` do site (a busca do hero, em busca-hero.blade.php,
  e a barra de filtros da listagem, em filtros.blade.php:45) têm HOJE um `.seg-ind` — a
  listagem ganhou o dela na Task 5. Não existe mais `.seg` sem indicador no site; o que existe
  é `.seg` sem JAVASCRIPT, e é para ela que as duas primeiras regras servem.

  1. `.seg a[aria-current]` (logo abaixo) pinta o selecionado de sólido. É o estado de
     PARTIDA, o que o HTML entrega: sem script, sem medição, sem indicador posicionado — o
     preenchimento é a única indicação de escolha que resta, e ele sempre está lá.
  2. `.seg.js-indicador a[aria-current]` (mais abaixo) TIRA esse preenchimento, e só na `.seg`
     em que o script de layout.blade.php confirmou ter um `.seg-ind` E um item com
     `aria-current` para medir. A partir daí quem marca a escolha é o indicador, como no
     protótipo (lá o preenchimento nunca existiu: `.seg button[aria-pressed="true"]` só muda a
     COR do texto).
  3. `.seg-ind` é a peça que desliza.

  A troca entre 1 e 2 existe porque os dois sinais competiam: o preenchimento marcava a
  escolha do SERVIDOR e o indicador a escolha CORRENTE, e um clique que trocasse a finalidade
  sem recarregar a página (o Alpine da busca do hero) deixava os dois em lugares diferentes —
  o não selecionado preenchido, o selecionado só com o indicador embaixo do outro.
*/
.seg a {
  position: relative; z-index: 1; height: 44px; padding: 0 18px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 3px; color: var(--ink-2); font: 600 14px/1 var(--sans);
  text-decoration: none; transition: color .3s, background .3s;
}
.seg a:hover { color: var(--ink); }
.seg a[aria-current] {
  background: var(--brand); color: var(--on-brand);
  box-shadow: 0 2px 8px color-mix(in oklab, var(--brand) 32%, transparent);
}
.seg a[aria-current]:hover { color: var(--on-brand); }
/*
  Passo 2 do mapa acima. `.js-indicador` entra numa `.seg` ESPECÍFICA (não no `<html>`, ao
  contrário de `.js-reveal` e de `.js-menu`): layout.blade.php a acrescenta só na `.seg` que
  tem `.seg-ind` E um item com `aria-current` para medir, e só depois de medir. O escopo por
  elemento é o que garante que uma página sem JavaScript — ou uma `.seg` futura sem indicador
  — nunca perca o preenchimento, a única indicação de escolha que lhe resta.
*/
.seg.js-indicador a[aria-current] {
  background: none; box-shadow: none;
}
.seg-ind {
  position: absolute; top: 3px; bottom: 3px; left: 0; width: 0;
  background: var(--brand); border-radius: 3px;
  box-shadow: 0 2px 8px color-mix(in oklab, var(--brand) 32%, transparent);
  transition: transform .4s var(--ease), width .4s var(--ease);
}
/*
  Task 5 fix: a regra do protótipo mirava só o <button> — a listagem usa <a> (links de
  navegação reais, com aria-current="page" vindo do servidor, decisão do projeto), então a
  classe .seg-sm sem o seletor "a" não fazia nada ali. Mesma especificidade que ".seg a"
  (0,1,1 cada), e esta regra vem DEPOIS no arquivo — vence por ordem de cascata, sem precisar
  de especificidade maior. Não toca em ".seg a[aria-current]" nem em
  ".seg.js-indicador a[aria-current]" (acima): aquelas cuidam só de cor/fundo/sombra, nunca de
  tamanho da caixa, então o preenchimento sólido sem JavaScript continua intacto.
*/
.seg-sm a, .seg-sm button { height: 30px; padding: 0 14px; font-size: 13px; }
.search .seg { margin-right: 10px; }

.field {
  position: relative; display: flex; flex-direction: column; justify-content: center;
  padding: 6px 16px; border-left: 1px solid var(--line); border-radius: var(--r-sm);
  transition: background .25s, box-shadow .25s;
}
.search .seg + .field { border-left-color: transparent; }
.field label {
  display: flex; align-items: center; gap: 6px; margin-bottom: 5px;
  font: 600 10.5px/1 var(--sans); letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
  transition: color .25s;
}
.field label .i { width: 13px; height: 13px; }
/* Revisão final: sem `outline: none`. O `:focus-within` abaixo pinta a CAIXA do campo, o que
   ajuda a ver onde se está mas usa `--brand-line`/`--brand-wash` — tons claros de propósito,
   que não cumprem o piso de contraste do indicador de foco. Deixar o outline global aparecer
   é o que garante o piso; a moldura continua como reforço. */
.field input, .field select {
  width: 100%; padding: 0; border: 0; background: transparent; appearance: none;
  font: 500 15px/1.3 var(--sans); color: var(--ink); cursor: pointer;
}
.field input { cursor: text; }
.field .chev { position: absolute; right: 12px; bottom: 12px; width: 14px; height: 14px; color: var(--muted); pointer-events: none; transition: transform .3s var(--ease); }
.field:focus-within {
  background: var(--surface-2);
  box-shadow: inset 0 0 0 1px var(--brand-line), 0 0 0 3px var(--brand-wash);
}
.field:focus-within label { color: var(--brand-ink); }
.field:focus-within .chev { transform: rotate(180deg); color: var(--brand); }

.btn-search { position: relative; overflow: hidden; height: auto; min-height: 54px; margin-left: 10px; padding: 0 26px; }
.btn-search::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: -60%; width: 40%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .3), transparent);
  transform: skewX(-18deg);
}
.btn-search .i { transition: transform .3s var(--ease); }
.btn-search:hover .i { transform: scale(1.12) rotate(-10deg); }

/* Aqui ficavam `.quick` e `.qchip`, a fila de atalhos ("2 quartos", "até 500 mil") que o
   protótipo desenhava sob a busca do hero. A busca real oferece finalidade, localização e tipo
   e nada mais: os atalhos precisariam de contagem por faceta para não prometer resultado que
   não existe, e isso nunca foi construído. Nenhuma view emitiu as classes em momento nenhum. */

/* ---------- seções ---------- */

.section { padding: 64px 0; }
/*
  Task 4: o protótipo zera o padding-top de uma seção que vem colada na anterior com
  `style="padding-top:0"` inline. Nada de style="" nesta página: é o mesmo invariante que
  hero.blade.php respeita para o `hero_image_url` não ter contexto CSS pra escapar (ver
  SecoesDaHomeTest::test_url_da_imagem_nao_escapa_para_css, que afirma a ausência de QUALQUER
  atributo style="" na página inteira) — então esta é uma classe modificadora, não inline.
*/
.section-colada { padding-top: 0; }
.section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 24px; }
.section-head h2 { font-size: clamp(24px, 3vw, 32px); margin-top: 10px; }
.section-head p { color: var(--ink-2); margin-top: 6px; }
.band { background: var(--surface-2); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }

/* Sem `.grid-3` aqui: o Aconchego usa `.grid-4` na home e `.grid-auto` na listagem, e quem
   monta grade de três colunas é o Prisma, com CSS próprio em prisma.css. */
.grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px; }
.grid-auto { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 20px; }

/* .regions: variação de .grid-4 pro bloco "por bairro" da home, com comportamento móvel
   próprio (ver §responsivo) — nome fora do vocabulário combinado com as Tasks 4-6, sem
   regra própria aqui em cima, só nas media queries abaixo. Registrado no relatório da task. */

/* ---------- card de imóvel ---------- */

.card {
  display: flex; flex-direction: column; height: 100%;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden;
  color: inherit; text-decoration: none; box-shadow: var(--sh-1);
  transition: transform .4s var(--ease), box-shadow .4s var(--ease), border-color .4s;
}
.card:hover { transform: translateY(-3px); box-shadow: var(--sh-2); border-color: var(--line-2); }
.card:focus-visible { outline-offset: 3px; }
.card-media { position: relative; aspect-ratio: 4 / 3; overflow: hidden; background: var(--surface-3); }
.card-media .ph { position: absolute; inset: 0; transition: transform .9s var(--ease); }
.card:hover .card-media .ph { transform: scale(1.045); }
/* Task 5: a foto REAL do imóvel (o protótipo só tinha o placeholder `.ph` acima, porque é
   uma demonstração estática) — mesmo enquadramento e o mesmo zoom no hover, para a capa de
   verdade não desalinhar do card sem foto. Mesma ideia de `.about-media img` (Task 4). */
.card-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .9s var(--ease); }
.card:hover .card-media img { transform: scale(1.045); }
.card-media::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(20, 15, 10, .22), transparent 45%);
  opacity: 0; transition: opacity .4s;
}
.card:hover .card-media::after { opacity: 1; }
.card-photos {
  position: absolute; right: 10px; bottom: 10px; z-index: 1;
  display: inline-flex; align-items: center; gap: 5px; padding: 4px 8px;
  background: rgba(255, 255, 255, .92); border-radius: var(--r-sm);
  font-size: 11.5px; font-weight: 600; color: var(--ink-2);
  opacity: 0; transform: translateY(4px); transition: opacity .35s, transform .35s var(--ease);
}
.card-photos .i { width: 13px; height: 13px; }
.card:hover .card-photos, .card:focus-visible .card-photos { opacity: 1; transform: none; }

.badge {
  position: absolute; top: 10px; left: 10px; z-index: 1;
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 8px;
  background: rgba(255, 255, 255, .95); color: var(--ink); border-radius: var(--r-sm);
  font: 600 10.5px/1 var(--sans); letter-spacing: .08em; text-transform: uppercase;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .08);
}
.badge-new::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--brand); animation: ping 2.4s infinite; }
.badge-muted { background: rgba(43, 38, 33, .84); color: #fff; }
@keyframes ping {
  0% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--brand) 50%, transparent); }
  70%, 100% { box-shadow: 0 0 0 7px transparent; }
}

.card-body { position: relative; flex: 1; display: flex; flex-direction: column; gap: 3px; padding: 14px 16px 16px; }
.card-body::before {
  content: ""; position: absolute; top: -1px; left: 16px; right: 16px; height: 2px;
  background: var(--brand); transform: scaleX(0); transform-origin: left;
  transition: transform .5s var(--ease);
}
.card:hover .card-body::before { transform: scaleX(1); }
.price {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  font: 700 19px/1.25 var(--sans); letter-spacing: -.01em; font-variant-numeric: tabular-nums;
}
.price small { font-size: 13px; font-weight: 500; color: var(--muted); }
.price .lbl { font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); margin-right: 6px; }
.price.dual { font-size: 16px; }
.card-go { width: 18px; height: 18px; color: var(--brand); opacity: 0; transform: translateX(-6px); transition: opacity .35s, transform .35s var(--ease); }
.card:hover .card-go { opacity: 1; transform: none; }
.card-cost { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.card-cost b { color: var(--ink-2); font-weight: 600; white-space: nowrap; }
/* Tipo · bairro do card — "meta" porque a mesma faixa serve pra qualquer resumo curto que
   não seja preço nem specs (o protótipo chamava .pcard-title). Fix round 1 (Task 5): virou
   `<h3>` (heading pra grade de cards não ficar muda pra leitor de tela) — `font`/
   `font-weight`/`letter-spacing` aqui anulam a regra `h1, h2, h3 { font-family: var(--serif);
   font-weight: 500; letter-spacing: -.01em; }` do topo do arquivo, pra manter a MESMA
   aparência que tinha como `<div>`. */
.meta {
  font: 14px/1.6 var(--sans); font-weight: 400; letter-spacing: normal;
  color: var(--ink-2); margin-bottom: 10px;
}
.card-specs {
  display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: auto; padding-top: 10px;
  border-top: 1px solid var(--line); font-size: 13px; color: var(--ink-2); font-variant-numeric: tabular-nums;
}
.card-specs span { display: inline-flex; align-items: center; gap: 5px; }
.card-specs .i { width: 15px; height: 15px; color: var(--muted); }

/* ---------- regiões ---------- */

.region-card {
  display: block; height: 100%; overflow: hidden; text-decoration: none; color: inherit;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--sh-1);
  transition: transform .4s var(--ease), box-shadow .4s var(--ease);
}
.region-card:hover { transform: translateY(-3px); box-shadow: var(--sh-2); }
.region-card-media { position: relative; aspect-ratio: 3 / 2; overflow: hidden; }
.region-card-media .ph { position: absolute; inset: 0; transition: transform .9s var(--ease); }
.region-card:hover .region-card-media .ph { transform: scale(1.05); }
.region-card-body { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 16px; }
.region-card-body b { display: block; font-family: var(--serif); font-weight: 500; font-size: 18px; }
.region-card-body small { color: var(--muted); font-size: 13px; }
.region-card-arrow {
  width: 30px; height: 30px; display: grid; place-items: center; flex: none;
  border: 1px solid var(--line-2); border-radius: var(--r); color: var(--ink-2);
  transition: background .3s, color .3s, border-color .3s;
}
.region-card-arrow .i { width: 15px; height: 15px; transition: transform .35s var(--ease); }
.region-card:hover .region-card-arrow { background: var(--brand); border-color: var(--brand); color: var(--on-brand); }
.region-card:hover .region-card-arrow .i { transform: translateX(2px); }
.also { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 20px; }
.also > span { font-size: 13px; color: var(--muted); margin-right: 4px; }

/* ---------- sobre, depoimentos, contato, rodapé ---------- */

.about { display: grid; grid-template-columns: 1.1fr .9fr; gap: 72px; align-items: center; }
.about h2 { font-size: clamp(26px, 3.2vw, 36px); margin: 12px 0 16px; }
.about p { color: var(--ink-2); max-width: 56ch; }
.about p + p { margin-top: 12px; }
.stats { display: flex; gap: 40px; margin-top: 28px; padding-top: 22px; border-top: 1px solid var(--line); }
.stat b { display: block; font-family: var(--serif); font-weight: 500; font-size: 30px; line-height: 1.1; }
.stat span { font-size: 13px; color: var(--muted); }
.about-media { position: relative; isolation: isolate; }
/* Task 4: a foto real de about_image_url (quando o cliente tem uma). A moldura (4/3, raio,
   sombra) é declarada aqui e em nenhum outro lugar: `sobre.blade.php` põe SEMPRE um `<img>`
   dentro de `.about-media`, nunca o placeholder `.ph` — a seção inteira só existe quando há
   `aboutImageUrl`. A regra `.about-media .ph` que acompanhava esta daqui vinha do protótipo e
   não casava com marcação nenhuma. */
/* `height: auto` explícito pela mesma razão de `.gallery-track img` (ver lá): hoje esta `<img>`
   não traz atributo de dimensão e a altura já era `auto`, então a declaração não muda pixel
   nenhum — ela impede que acrescentar `width`/`height` à marcação um dia desfaça o
   `aspect-ratio` em silêncio. */
.about-media img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--r); box-shadow: var(--sh-2); }
.about-media::before {
  content: ""; position: absolute; inset: 16px -16px -16px 16px; z-index: -1;
  border: 1px solid var(--line-2); border-radius: var(--r);
  transition: transform .6s var(--ease);
}
.about-media:hover::before { transform: translate(-4px, -4px); }

/*
  auto-fit, não repeat(3, 1fr): dois é o mínimo que o bloco de depoimentos exige, e é tão
  caso normal quanto três — uma coluna vazia sobrando lê-se como falta. auto-fit colapsa a
  faixa sem depoimento e deixa as que existem (2 ou 3, o teto vem do repository) esticarem
  para preencher a largura. É por isso que .testimonials tem grade própria, e não reaproveita
  a de `.grid-4` ao lado.
*/
.testimonials { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 20px; }

.testimonial {
  position: relative; height: 100%; display: flex; flex-direction: column; justify-content: space-between; gap: 22px;
  padding: 26px 24px 22px; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--sh-1);
}
.testimonial::before {
  content: "\201C"; position: absolute; top: 4px; right: 18px;
  font-family: var(--serif); font-size: 72px; line-height: 1; color: var(--brand-soft);
}
.testimonial blockquote { margin: 0; font-family: var(--serif); font-size: 17px; line-height: 1.55; color: var(--ink); max-width: 34ch; }
.who { display: flex; align-items: center; gap: 12px; padding-top: 16px; border-top: 1px solid var(--line); }
.who b { display: block; font-size: 14px; }
.who small { display: block; font-size: 12.5px; color: var(--muted); }
.avatar {
  width: 40px; height: 40px; flex: none; display: grid; place-items: center; border-radius: 50%;
  background: var(--surface-2); border: 1px solid var(--line-2); color: var(--ink-2);
  font: 600 13px/1 var(--sans); overflow: hidden;
}
/* Sem variante `.avatar.ph`: no protótipo o avatar do depoimento era um bloco de gradiente,
   e aqui `depoimentos.blade.php` põe sempre as INICIAIS num `<span class="avatar">` (ou, com
   foto, um `<img class="depoimento-foto">` — ver o comentário abaixo). Nenhum elemento chega
   a ter `avatar` e `ph` juntos, então as duas regras que existiam aqui eram mortas. */
/*
  Task 4: a foto do depoimento manteve o nome de classe ANTIGO (`.depoimento-foto`, não
  `.avatar`) de propósito — DepoimentosNaHomeTest::test_com_foto_mostra_a_imagem_com_src_escapado
  (pré-existente, fora dos arquivos desta task) afirma a string literal
  `<img class="depoimento-foto"`. Mesmo círculo de 40px do `.avatar`, nome antigo preservado.
*/
.depoimento-foto {
  width: 40px; height: 40px; flex: none; border-radius: 50%; object-fit: cover;
  border: 1px solid var(--line-2);
}

.contact-cta {
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 32px;
  padding: 40px 44px; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--sh-1);
  position: relative; overflow: hidden;
}
.contact-cta::after { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 2px; background: var(--brand); }
.contact-cta h2 { font-size: clamp(24px, 3vw, 32px); }
.contact-cta p { color: var(--ink-2); margin-top: 8px; }
.contact-cta-actions { display: flex; gap: 10px; flex-wrap: wrap; }

.site-footer { border-top: 1px solid var(--line); padding: 44px 0 28px; color: var(--ink-2); font-size: 14px; }
.foot { display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: 32px; }
.foot h3 { font: 600 11px/1 var(--sans); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); margin-bottom: 14px; }
.foot a { display: block; text-decoration: none; padding: 3px 0; transition: color .2s; }
.foot a:hover { color: var(--brand-ink); }
.foot .creci { display: inline-block; margin-top: 14px; padding: 5px 9px; border: 1px solid var(--line-2); border-radius: var(--r-sm); font-size: 12.5px; font-variant-numeric: tabular-nums; }
.foot-bottom { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-top: 36px; padding-top: 18px; border-top: 1px solid var(--line); font-size: 12.5px; color: var(--muted); }

/* ---------- listagem ---------- */

.crumbs { display: flex; flex-wrap: wrap; gap: 6px; padding: 22px 0 10px; font-size: 13px; color: var(--muted); }
.crumbs a { text-decoration: none; transition: color .2s; }
.crumbs a:hover { color: var(--ink); }
.crumbs span[aria-hidden] { color: var(--line-2); }
.list-head h1 { font-size: clamp(26px, 3.4vw, 38px); }
.list-head p { color: var(--ink-2); margin-top: 6px; }

.filterbar {
  position: sticky; top: var(--hdr); z-index: 30; margin-top: 18px; padding: 12px 0;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.fb-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.fb-row .seg { margin-right: 4px; }
.fb-count { margin-left: auto; margin-right: 4px; font-size: 14px; color: var(--ink-2); white-space: nowrap; }
.fb-count b, .num { font-variant-numeric: tabular-nums; color: var(--ink); transition: color .35s; }

.applied { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; min-height: 58px; padding: 12px 0; }
.linkish {
  border: 0; background: none; padding: 4px 2px; cursor: pointer;
  color: var(--brand-ink); font-size: 13px; font-weight: 600;
  text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--brand-line);
  transition: text-decoration-color .2s;
}
.linkish:hover { text-decoration-color: currentColor; }

.pager { display: flex; justify-content: center; gap: 6px; padding: 40px 0 72px; }
/* O sprite só tem uma seta (aponta pra direita) — "Anterior" reaproveita a mesma, espelhada. */
.pager-prev { transform: scaleX(-1); }
.pager a {
  min-width: 40px; height: 40px; padding: 0 12px; display: grid; place-items: center;
  border: 1px solid var(--line-2); border-radius: var(--r); background: var(--surface);
  color: var(--ink-2); text-decoration: none; font-variant-numeric: tabular-nums;
  transition: border-color .2s, box-shadow .2s, color .2s;
}
.pager a:hover { border-color: var(--ink-2); color: var(--ink); box-shadow: var(--sh-1); }
.pager a[aria-current="page"] { background: var(--brand); border-color: var(--brand); color: var(--on-brand); }
/*
  Task 5: o protótipo marca a página atual num `<a>` mesmo (`aria-current="page"` num link
  que aponta pra própria URL). A paginação desta fatia usa `<span>` pra página atual e pros
  extremos desabilitados (Anterior/Próxima no limite) — não-interativos de propósito, pra um
  leitor de tela não anunciar como link algo que não navega. Mesma moldura de `.pager a`,
  seletor por atributo em vez de reaproveitar a classe.
*/
.pager span[aria-current="page"], .pager span[aria-disabled="true"] {
  min-width: 40px; height: 40px; padding: 0 12px; display: grid; place-items: center;
  border: 1px solid var(--line-2); border-radius: var(--r); font-variant-numeric: tabular-nums;
}
.pager span[aria-current="page"] { background: var(--brand); border-color: var(--brand); color: var(--on-brand); }
.pager span[aria-disabled="true"] { color: var(--line-2); }

/*
  Revisão final: `.empty` nascia `display: none`, visível só sob `.is-empty` — classe que o
  protótipo alternava por JavaScript no invólucro da listagem e que ninguém porta aqui (as
  duas regras de `.is-empty` eram letra morta). No site real quem decide é o Blade: o bloco só
  é RENDERIZADO quando não há resultado, então ele nasce visível.
*/
.empty { padding-bottom: 72px; }
.empty-box {
  margin: 8px 0 40px; padding: 36px 24px; text-align: center;
  background: var(--surface); border: 1px dashed var(--line-2); border-radius: var(--r);
}
.empty-ic {
  width: 52px; height: 52px; margin: 0 auto 16px; display: grid; place-items: center;
  border: 1px solid var(--line-2); border-radius: 50%; color: var(--brand);
}
.empty-ic .i { width: 22px; height: 22px; }
.empty-box h2 { font-size: 24px; }
.empty-box p { color: var(--ink-2); margin: 8px auto 0; max-width: 52ch; }
.empty-box s { color: var(--muted); }

/* ---------- painel de filtros ---------- */

/*
  Task 5: o painel de filtros da listagem é um `<dialog>` NATIVO — não o `.sheet-backdrop` +
  classe `.is-sheet-open` alternada no `<body>` que o protótipo usa (mecanismo de JS que
  ninguém portou: pertencia a uma página única simulando três telas, ver o relatório da
  Task 3). As duas regras existiam aqui até o fix round 1, mortas (nada no código desta fatia
  bota `.is-sheet-open` em lugar nenhum) — removidas no fix round 2 junto com a limpeza
  abaixo, pra não sobrar regra nenhuma descrevendo um mecanismo que não existe mais.

  Fix round 2: `dialog.sheet` (sem showModal() — o `<dialog open>` que sai direto do
  servidor, pra quem não roda JavaScript) fica em FLUXO NORMAL: `position: static` desfaz o
  `position: absolute; margin: auto` que o agente do usuário aplica a TODO `<dialog>` aberto,
  com ou sem `showModal()` — sem essa troca, mesmo o painel sem JavaScript nenhum flutuava
  por cima do conteúdo, permanentemente (achado da revisão). A aparência de painel flutuante
  (fixo, sombra, `::backdrop`, largura de 440px, bottom sheet no mobile) só entra com
  `.is-modal` — classe que `abrirPainelFiltros()` acrescenta ao chamar `showModal()` e
  `fecharPainelFiltros()` remove ao fechar (`filtros.blade.php`). `::backdrop` nunca existe
  fora do estado `:modal` de qualquer forma (só `showModal()` cria o backdrop), mas o seletor
  por classe deixa a regra explícita sobre QUANDO ela deveria existir, sem depender de
  lembrar essa regra do navegador.
*/
.sheet { display: flex; flex-direction: column; background: var(--surface); }
dialog.sheet {
  position: static; inset: auto; margin: 0; border: 0; padding: 0; color: inherit;
  width: auto; box-shadow: none;
}
/*
  Revisão final, medido no navegador: FECHADO o painel continuava ocupando a página. O
  `display: flex` de `.sheet` é regra de AUTOR e vence o `dialog:not([open]) { display: none }`
  do agente do usuário (origem autor ganha da origem do agente, independente de
  especificidade) — então tirar `.is-modal` ao fechar tirava a flutuação, mas deixava o painel
  inteiro em fluxo normal, abaixo dos filtros. Esta regra devolve o comportamento nativo sem
  perder o fallback sem JavaScript: lá o `<dialog>` NASCE com `open` e continua em fluxo.
*/
dialog.sheet:not([open]) { display: none; }
/*
  Fix (conferência final, achado importante 4): `dialog.sheet` (acima) desfaz `position`,
  `inset`, `margin`, `border`, `padding` e `width` do agente do usuário, mas não tocava em
  `height`, `max-width` nem `max-height` — e o agente aplica `height: fit-content` a TODO
  `<dialog>` (aberto ou não) e, só ao entrar em `:modal` (isto é, junto com `.is-modal`),
  `max-width`/`max-height: calc(100% - 6px - 2em)`. Sem uma declaração de autor pra essas três
  propriedades, o valor do agente prevalece por eliminação — medido: gaveta de 440×601 em vez
  de 440×900 a 1280 (o `height: fit-content` ignora o `top:0; right:0; bottom:0` que pediria a
  altura cheia) e bottom sheet indo só até 339 em vez de 375 a 375 (o `max-width` do agente
  cortava o `width: 100%` do media query abaixo). `height: auto` devolve o cálculo por
  `top`/`bottom`; `max-width`/`max-height: none` tiram o teto do agente — o `max-height: 88vh`
  do bottom sheet, no `@media (max-width: 760px)` abaixo, continua valendo por vir depois no
  arquivo.
*/
.sheet.is-modal {
  position: fixed; z-index: 61; top: 0; right: 0; bottom: 0; width: min(440px, 100%);
  height: auto; max-width: none; max-height: none;
  box-shadow: var(--sh-3);
}
.sheet.is-modal::backdrop { background: rgba(30, 24, 18, .4); }
.grab { display: none; width: 36px; height: 4px; margin: 8px auto 0; border-radius: 2px; background: var(--line-2); }
.sheet-head { display: flex; align-items: center; justify-content: space-between; padding: 18px 24px; border-bottom: 1px solid var(--line); }
.sheet-head h2 { font-size: 22px; }
.sheet-body { flex: 1; overflow: auto; padding: 0 24px 16px; }
.fgroup { padding: 22px 0; border-bottom: 1px solid var(--line); }
.fgroup:last-child { border-bottom: 0; }
.fgroup h3 { font: 600 11px/1 var(--sans); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); margin-bottom: 14px; }
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
/* Aqui ficavam `.histo` (o histograma de preço do protótipo, com as barras dentro da faixa
   escolhida em `.histo span.in`) e `.range-labels` (os rótulos das pontas). O filtro real de
   preço são dois `<select>` de valor — sem controle de faixa, sem gráfico —, e desenhar a
   distribuição exigiria uma agregação por site que o Vitrine não calcula. */
.sheet-foot { display: flex; gap: 12px; padding: 14px 24px calc(14px + env(safe-area-inset-bottom)); border-top: 1px solid var(--line); }
.sheet-foot .btn-brand { flex: 1; }

/* ---------- imóvel ---------- */

.gallery { display: grid; grid-template-columns: 65fr 35fr; gap: 8px; height: clamp(320px, 42vw, 520px); }
.gallery-side { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; gap: 8px; }
.gallery-tile { position: relative; overflow: hidden; border-radius: var(--r); cursor: zoom-in; border: 0; padding: 0; background: var(--surface-3); }
/* Task 6: o protótipo só tinha o placeholder `.ph`; a galeria real usa `<img>` — sem esta
   regra a foto não preenche/recorta o ladrilho (mesma lacuna que `.card-media img`, Task 5).
   As regras de `.ph` que existiam aqui foram apagadas depois: `base/partials/galeria.blade.php`
   emite `<img>` nos dois ramos (com e sem contador), então nenhum `.ph` chega a entrar num
   `.gallery-tile`. O placeholder só vive onde o template é dono da marcação — card e regiões. */
.gallery-tile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .9s var(--ease); }
.gallery-tile:hover img { transform: scale(1.035); }
.gallery-all { position: absolute; right: 12px; bottom: 12px; z-index: 1; }
.gallery-m { display: none; position: relative; }
.gallery-track { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; }
.gallery-track::-webkit-scrollbar { display: none; }
/* Task 6: mesmo motivo de `.gallery-tile img` acima — o carrossel mobile embrulha cada foto
   num <button> (pra abrir a lightbox), que o protótipo não tinha. */
.gallery-track button { flex: 0 0 100%; scroll-snap-align: start; border: 0; padding: 0; background: none; cursor: zoom-in; }
/*
  `height: auto` não é redundância. `base/partials/galeria.blade.php` emite `width="1200"
  height="900"` como ATRIBUTO no `<img>` (e deve: é o que reserva a caixa antes da foto
  chegar, evitando salto de layout). Atributo de dimensão vira hint de apresentação no CSS, e
  esta regra declarava só `width` — então o `height` do atributo sobrevivia, a altura ficava
  DEFINIDA, e `aspect-ratio` era simplesmente ignorado. Medido a 375px antes da correção: cada
  slide do carrossel com 1200px de altura em vez de 281, uma foto gigante recortada antes de o
  visitante chegar ao título. `height: auto` devolve a altura ao `aspect-ratio`.

  O protótipo nunca mostrou isso porque lá o slide era `<div class="ph">`, que não tem atributo
  de dimensão nenhum — mesma origem de toda esta família de defeitos.
*/
.gallery-track img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; }
.gallery-count {
  position: absolute; right: 12px; bottom: 12px; padding: 5px 9px; border-radius: var(--r-sm);
  background: rgba(255, 255, 255, .94); font-size: 12.5px; font-weight: 600; font-variant-numeric: tabular-nums;
}

/*
  Task 6: lightbox da galeria do imóvel — não existia protótipo algum pra portar (o HTML de
  referência só tinha `data-toast="galeria"`, um placeholder de demonstração sem overlay
  real), então o vocabulário é novo.

  `[x-cloak]` (topo do arquivo), não uma classe de estado tipo `.sheet.is-modal`, é o que
  impede este overlay de cobrir a página quando o Alpine não roda — ver o comentário em
  `partials/galeria.blade.php` sobre por que aqui, ao contrário do painel de filtros, ficar
  escondida para sempre sem JavaScript é o comportamento certo.
*/
.lightbox {
  position: fixed; inset: 0; z-index: 80;
  display: flex; align-items: center; justify-content: center;
  background: rgba(20, 16, 12, .92);
}
.lightbox img { max-width: min(92vw, 1200px); max-height: 86vh; width: auto; height: auto; object-fit: contain; }
.lightbox-close, .lightbox-prev, .lightbox-next {
  position: absolute; display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%;
  background: rgba(255, 255, 255, .12); color: #fff; cursor: pointer; transition: background .2s;
}
.lightbox-close:hover, .lightbox-prev:hover, .lightbox-next:hover { background: rgba(255, 255, 255, .22); }
.lightbox-close { top: 16px; right: 16px; }
.lightbox-prev, .lightbox-next { top: 50%; transform: translateY(-50%); }
.lightbox-prev { left: 16px; }
.lightbox-next { right: 16px; }
.lightbox-close .i, .lightbox-prev .i, .lightbox-next .i { width: 22px; height: 22px; stroke-width: 1.8; }
.lightbox-prev .i { transform: scaleX(-1); }

.prop-layout { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 56px; align-items: start; padding-top: 32px; padding-bottom: 72px; }
.prop-title h1 { font-size: clamp(26px, 3.2vw, 36px); max-width: 24ch; }
.prop-title .where { display: flex; align-items: center; gap: 6px; margin-top: 10px; color: var(--ink-2); }
.prop-title .where .i { width: 16px; height: 16px; color: var(--brand); }

.facts { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; margin-top: 22px; padding-top: 22px; border-top: 1px solid var(--line); }
.facts .price { font: 700 32px/1.1 var(--sans); letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
/* Task 6, fix round 2: `.price.dual` (duas classes, acima) e `.facts .price` (duas classes,
   aqui) empatam em especificidade — quem vem DEPOIS no arquivo ganha o empate, e `.facts
   .price` vem depois, então o preço duplo (venda + aluguel) do `.facts` saía em 32px em vez
   dos 16px reduzidos. Três classes bate duas independente da ordem no arquivo — não depende
   de vir depois de `.facts .price` (nem da versão dela dentro do media query mobile, linha
   949: especificidade decide antes de qualquer media query entrar em jogo). */
.facts .price.dual { font-size: 16px; }
.facts .cost { margin-top: 6px; font-size: 14px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.copy { font-variant-numeric: tabular-nums; }
.copy .ok { display: none; color: var(--brand); }
.copy.is-done { border-color: var(--brand); color: var(--brand-ink); background: var(--brand-wash); }
.copy.is-done .ok { display: inline; animation: chipIn .3s var(--ease); }
.copy.is-done .cp { display: none; }

.specs {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); gap: 1px; margin-top: 22px;
  background: var(--line); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; box-shadow: var(--sh-1);
}
.spec { padding: 14px 16px; background: var(--surface); }
.spec .i { width: 20px; height: 20px; color: var(--brand); margin-bottom: 8px; }
.spec b { display: block; font-size: 16px; font-variant-numeric: tabular-nums; }
.spec span { font-size: 12.5px; color: var(--muted); }

.block { padding: 40px 0; border-bottom: 1px solid var(--line); }
.block:last-child { border-bottom: 0; }
.block h2 { font-size: 24px; margin-bottom: 16px; }
.block > p { color: var(--ink-2); max-width: 68ch; }
.block > p + p { margin-top: 12px; }
.tags { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; }
.tag {
  display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 12px;
  border: 1px solid var(--line); border-radius: 6px; background: var(--surface); font-size: 13.5px; color: var(--ink-2);
}
.tag .i { width: 14px; height: 14px; color: var(--brand); }

.plan, .map { border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; background: var(--surface); box-shadow: var(--sh-1); }
.plan { padding: 20px; }
/* A planta abre em nova aba (sem JS, ver planta.blade.php) — mesmo cursor de "ampliar" que
   `.gallery-tile` já usa na galeria, pro clique parecer o que é: ver a imagem maior. */
.plan a { display: block; cursor: zoom-in; }
.plan svg { display: block; width: 100%; height: auto; }
/*
  Conferência final, C1: no protótipo o bloco de localização era SÓ um `<svg>` desenhado à
  mão, e um `.map` estático bastava. Esta fatia pôs uma `<img>` de verdade dentro do mesmo
  `.map` e promoveu o `<svg>` a sobreposição — mas sem contexto de posicionamento o desenho
  virou uma segunda caixa 387px ABAIXO da imagem: o círculo, o anel e o rótulo não marcavam
  nada, e o bloco inteiro ficava com 947px em vez de 560px.

  `position: relative` aqui e `absolute; inset: 0` no `<svg>` fazem o desenho cobrir
  exatamente a caixa da `<img>` — a `<img>` é o único filho no fluxo, então a caixa de
  conteúdo do `.map` É a da imagem, nos dois viewports. `height: 100%` (não `auto`) porque
  um `<svg>` absoluto não tira altura do viewBox.
*/
.map { position: relative; }
.map svg { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
/*
  Conferência final, C2 e M1: o `img { max-width: 100% }` global corta a LARGURA, mas o
  atributo `height` do HTML continua valendo como altura usada — uma prancha A3 de
  2480x1754 renderizava 734x1754, com as cotas ilegíveis. A regra que dava `height: auto`
  cobria só `svg` (o protótipo não tinha `<img>` nenhuma aqui). E, sem `display: block`, as
  duas `<img>` deixavam 7px de folga branca embaixo, do descender da linha de base — visível
  no rodapé da moldura do mapa quando a nota de aproximação não aparece.

  Largura diferente para cada uma, de propósito: o mapa PREENCHE a moldura (é um @2x pedido
  na medida exata do bloco), a planta não é ampliada além do próprio tamanho — esticar um
  raster de planta só borra cota.
*/
.plan img { display: block; max-width: 100%; height: auto; }
.map img { display: block; width: 100%; height: auto; }
.map-ring { transform-box: fill-box; transform-origin: center; animation: ring 3.4s ease-out infinite; }
/*
  Conferência final, I3: o rótulo "~500 m" mora aqui, e não num `<text>` do SVG, porque
  `font-size` dentro de um viewBox escala junto com o desenho — a 375 o corpo caía para
  5,54px. Em HTML ele tem 13px nos dois viewports. Centro do círculo = centro do `.map`
  (`cx="400" cy="190"` num viewBox de 800x380), então 50%/50% cai no lugar certo mesmo
  quando o SVG é letterboxado por uma imagem de proporção diferente.
*/
.map-scale {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  padding: 2px 9px; border-radius: 999px; background: var(--brand-wash);
  font-size: 13px; font-weight: 600; line-height: 1.45; color: var(--brand-ink);
  white-space: nowrap; pointer-events: none;
}
@keyframes ring { 0% { transform: scale(.92); opacity: .7; } 100% { transform: scale(1.3); opacity: 0; } }
.note { display: flex; align-items: center; gap: 8px; margin-top: 12px; font-size: 13.5px; color: var(--ink-2); }
.note .i { width: 16px; height: 16px; color: var(--muted); }

.aside { position: sticky; top: calc(var(--hdr) + 24px); }
.agent-card {
  padding: 24px; background: var(--surface);
  border: 1px solid var(--line); border-top: 2px solid var(--brand); border-radius: var(--r); box-shadow: var(--sh-2);
}
/*
  Aqui morava o cabeçalho de corretor do protótipo — `.agent` (retrato, nome, cargo) e
  `.online` (a bolinha verde "disponível agora", com o keyframe `pingGreen`). A caixa hospeda
  o formulário de lead de `base/partials/formulario-contato.blade.php`, que não emite nenhuma
  das duas: o Vitrine não carrega corretor nem presença, e o cliente da imobiliária nem sempre
  tem um. As regras nunca casaram com marcação nenhuma desde a primeira versão desta pele.

  A bolinha era o caso mais caro de deixar ficar: uma animação infinita anunciando
  disponibilidade humana que o produto não tem como saber. Ver o comentário de `.agent-card h2`
  mais abaixo, que conta a mesma troca do lado que FICOU.
*/
.stack { display: flex; flex-direction: column; gap: 10px; }
.divider { position: relative; margin: 22px 0 16px; border-top: 1px dashed var(--line-2); }
.divider span { position: absolute; left: 50%; top: 0; transform: translate(-50%, -50%); padding: 0 10px; background: var(--surface); font-size: 12px; color: var(--muted); white-space: nowrap; }
.input-l { display: block; font-size: 12.5px; font-weight: 600; color: var(--ink-2); margin-bottom: 5px; }
.input {
  width: 100%; height: 44px; padding: 0 12px;
  border: 1px solid var(--line-2); border-radius: var(--r); background: var(--surface);
  font: 15px var(--sans); color: var(--ink);
  transition: border-color .2s, box-shadow .25s;
}
.input:hover { border-color: var(--muted); }
/*
  Revisão final: sem `outline: none` aqui. O anel decorativo é `--brand-wash` (a marca a 9%
  sobre branco), que num tema claro é quase invisível — ele enfeita, não sinaliza foco. Quem
  sinaliza é o `:focus-visible` global, com `--focus` (piso de 3:1 contra o fundo), e
  desligar o outline deixava o campo do formulário de lead sem indicação nenhuma de foco.
*/
.input:focus { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-wash); }
/* O `.input` do protótipo era só campo de uma linha (44px fixos). A mensagem do formulário de
   lead é um <textarea>, que precisa crescer — mesma moldura, altura livre. */
textarea.input { height: auto; min-height: 96px; padding: 10px 12px; line-height: 1.5; resize: vertical; }
/*
  Revisão final: o `.agent-card` do protótipo era um card de corretor com um formulário curto;
  aqui ele hospeda o formulário de lead da página do imóvel (o título da seção, as mensagens
  de sucesso/erro e o fallback do <noscript>). Só o espaçamento do que o protótipo não tinha.
*/
.agent-card h2 { font-size: 20px; margin-bottom: 14px; }
.agent-card .sucesso, .agent-card .erro { font-size: 13.5px; }
.agent-card noscript p { font-size: 13px; color: var(--ink-2); }
.check { display: flex; align-items: flex-start; gap: 10px; font-size: 12.5px; color: var(--ink-2); line-height: 1.45; cursor: pointer; }
.check input { width: 16px; height: 16px; margin: 1px 0 0; flex: none; accent-color: var(--brand); }
.check a { color: var(--brand-ink); }

/* ---------- barra fixa do mobile ---------- */

.mobilebar { display: none; }

/* Reserva espaço pro conteúdo não ficar embaixo da barra fixa — só quando ela existe
   (layout.blade.php só a renderiza com WhatsApp configurado). :has() em vez de uma classe
   no <body> vinda do controller: nenhuma página precisa saber que a barra existe. */
@media (max-width: 760px) {
  body:has(.mobilebar) { padding-bottom: 76px; }
  .mobilebar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 45; display: flex; gap: 8px;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
    background: color-mix(in srgb, var(--surface) 94%, transparent);
    backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
    border-top: 1px solid var(--line); box-shadow: 0 -6px 20px rgba(58, 44, 30, .06);
  }
  .mobilebar .btn { flex: 1; min-width: 0; height: 48px; padding: 0 10px; gap: 6px; }
}

/* ---------- responsivo ---------- */

@media (max-width: 1100px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .prop-layout { grid-template-columns: minmax(0, 1fr) 320px; gap: 32px; }
  .search { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto; row-gap: 8px; }
  .search .seg { justify-self: start; }
  .search .field:nth-of-type(2) { grid-column: 2 / 4; }
  .search .field:nth-of-type(3) { border-left-color: transparent; }
}

@media (max-width: 860px) {
  .about { grid-template-columns: 1fr; gap: 48px; }
  .prop-layout { grid-template-columns: 1fr; }
  .aside { position: static; }
  .foot { grid-template-columns: 1fr 1fr; }
  .foot > :first-child { grid-column: 1 / -1; }
  .contact-cta { grid-template-columns: 1fr; }
  .testimonials { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: minmax(280px, 82%); overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: 8px; }
  .testimonials > * { scroll-snap-align: start; }
}

@media (max-width: 760px) {
  :root { --hdr: 60px; }
  .wrap { padding: 0 16px; }

  /*
    S5d: o .nav vira menu hambúrguer no mobile, como no protótipo. O fallback anterior
    (deixar o .nav quebrar linha) existia porque o layout não carregava JavaScript nenhum;
    o script inline do fim do <body> passou a existir na S5d, e com Sobre/Contato são
    quatro links mais o WhatsApp — faixa demais na dobra do celular.

    Fix (conferência final, achado crítico 2): `padding: 10px 0` era shorthand — zera os
    QUATRO lados, inclusive esquerda/direita, que ninguém aqui queria tocar. `.hdr` está no
    mesmo elemento que `.wrap` (`<div class="wrap hdr">` em layout.blade.php), com a mesma
    especificidade (0,1,0); como esta regra vem DEPOIS de `.wrap { padding: 0 16px }` duas
    linhas acima, o shorthand vencia por completo e apagava a calha lateral que o `.wrap`
    tinha acabado de aplicar — a marca colava em x=0 e o botão de menu em x=375 (mesmo
    bug de cascata do `.contact-cta`, achado já corrigido noutro ponto desta fatia).
    `padding-top`/`padding-bottom` isolados tocam só o eixo vertical e deixam
    `padding-left`/`padding-right` como o `.wrap` os definiu.
  */
  .hdr { height: auto; padding-top: 10px; padding-bottom: 10px; }
  .nav { display: none; }
  .hdr-mobile { display: inline-flex; gap: 8px; }
  /*
    S5d-D2: sem o `hidden` no HTML (decisão da Task 2), a visibilidade do .mnav nasce toda do
    CSS. Fora desta media query ele fica `display:none` (regra base) — só aparece aqui
    dentro, e por padrão VISÍVEL: é o script do fim do <body> que o esconde depois de montado
    (`menu.hidden = true`), nunca o contrário.

    Visível aqui significa EM FLUXO, não sobreposto: a regra base não posiciona mais nada, e
    `position: absolute` só chega pela regra `.js-menu .mnav` (ver o comentário lá). Sem
    JavaScript o painel empurra o hero para baixo em vez de tapá-lo.
  */
  .mnav { display: block; }
  /*
    S5d-D2, fix: `[hidden]` é regra de UA (user-agent), e author sempre vence UA mesmo com
    especificidade igual — então SEM esta regra, a linha acima (`.mnav { display: block }`,
    especificidade 0,1,0, autor) continuaria ganhando de `[hidden] { display: none }` do
    navegador, e `menu.hidden = true` não escondia nada dentro deste media query. `.mnav[hidden]`
    (0,2,0) resolve subindo a especificidade no próprio CSS do site, sem precisar de
    `!important` nem tocar na regra base de cima (que o teste
    ChromeDoSiteTest::test_mnav_fica_escondido_fora_do_mobile_e_reaparece_dentro_do_media_query
    lê como texto).
  */
  .mnav[hidden] { display: none; }

  .hero { min-height: 0; }
  .hero-content { padding-top: 36px; padding-bottom: 28px; }
  .hero h1 { font-size: 32px; }
  .hero .lead { font-size: 15.5px; margin-bottom: 20px; }
  .search { grid-template-columns: 1fr; padding: 10px; row-gap: 0; }
  .search .seg { margin: 0 0 8px; display: grid; justify-self: stretch; }
  .search .field { border-left: 0; border-top: 1px solid var(--line); padding: 10px 12px; }
  .search .seg + .field { border-top-color: transparent; grid-column: auto; }
  .btn-search { margin: 8px 0 0; min-height: 50px; }

  .section { padding: 44px 0; }
  .grid-4 { grid-template-columns: 1fr; gap: 16px; }
  .regions {
    grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: 44%;
    overflow-x: auto; scroll-snap-type: x mandatory; margin: 0 -16px; padding: 0 16px 8px; scrollbar-width: none;
  }
  .regions > * { scroll-snap-align: start; }
  .region-card-arrow { display: none; }
  .region-card-body b { font-size: 16px; }
  .stats { gap: 24px; }
  .contact-cta { padding: 28px 22px; }

  .filterbar { position: static; margin: 0; padding: 0; background: none; border: 0; backdrop-filter: none; }
  .fb-row { display: none; }
  .applied { flex-wrap: nowrap; overflow-x: auto; margin-right: -16px; padding-right: 16px; scrollbar-width: none; }
  .mobile-count { display: block !important; font-size: 13.5px; color: var(--ink-2); padding-bottom: 12px; }
  .grid-auto { grid-template-columns: 1fr; gap: 16px; }

  .gallery { display: none; }
  .gallery-m { display: block; }
  .facts .price { font-size: 28px; }
  .block { padding: 32px 0; }

  /*
    Fix round 2 (Task 5): a aparência de bottom sheet — só faz sentido pra quem está vendo o
    painel como MODAL de verdade (`.is-modal`, ver o comentário da regra em cima). Sem
    JavaScript, o `<dialog open>` continua em fluxo normal mesmo no mobile (`dialog.sheet`
    cuida disso incondicionalmente, não só aqui dentro do media query) — não tem por que
    imitar bottom sheet num painel que não flutua.
  */
  .sheet.is-modal { top: auto; left: 0; width: 100%; max-height: 88vh; border-radius: 6px 6px 0 0; }
  .sheet.is-modal .grab { display: block; }
  .sheet-head { padding: 12px 20px 14px; }
  .sheet-body { padding: 0 20px 12px; }
  .sheet-foot { padding-left: 20px; padding-right: 20px; }
}

.mobile-count { display: none; }

/*
  S5d-D10: a animação só existe quando o script marcou o <html> com `.js-reveal`. Sem ele,
  `.reveal` não esconde nada — foi por isso que a S5b tirou a classe das views em vez de
  deixá-la solta (nenhuma delas usa `.reveal` ainda; a classe só ganha efeito quando alguma
  view passar a marcar um elemento com ela).
*/
.js-reveal .reveal { opacity: 0; transform: translateY(12px); transition: opacity .6s var(--ease), transform .6s var(--ease); }
.js-reveal .reveal.is-visivel { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; transition-delay: 0s !important; scroll-behavior: auto !important;
  }
}
