/* ============================================================
   Rúben Marques — Climatização · site v1 (verão)
   Paleta reversível travada: nuvem/tinta/azul/quente
   ============================================================ */

@font-face{
  font-family:'Outfit';
  src:url('../assets/fonts/outfit.woff2') format('woff2');
  font-weight:100 900;
  font-display:swap;
}

/* Space Grotesk — SÓ o nome no hero. Alojada aqui como a Outfit, não puxada do
   Google: são menos duas ligações a um domínio de terceiros no caminho crítico,
   e o nome é das primeiras coisas a pintar. Subconjunto latino (22 KB), que é
   onde vive o «ú» de Rúben; os outros subconjuntos não fazem falta a este site. */
@font-face{
  font-family:'Space Grotesk';
  src:url('../assets/fonts/space-grotesk.woff2') format('woff2');
  font-weight:300 700;
  font-display:swap;
}

:root{
  /* ESCALA TIPOGRÁFICA — uma por situação, não uma por sítio (26-ago-2026).
     Antes: 50 corpos distintos espalhados por 127 declarações. As diferenças de
     meio pixel (12 vs 12,5 vs 13) não eram hierarquia, eram ruído acumulado. */
  --t-selo:11px;          /* etiquetas, selos, estrelas, maiúsculas pequenas */
  --t-legenda:12.5px;     /* legendas, contadores, notas de rodapé */
  --t-rotulo:13.5px;      /* chips, rótulos de campo, avisos */
  --t-corpo:14.5px;       /* o corpo padrão do site */
  --t-corpo-lg:15px;      /* corpo destacado, telefone, descrições */
  --t-base:16px;          /* body, ofício do hero */
  --t-destaque:17.5px;    /* títulos pequenos de painel */
  --t-painel:21px;        /* títulos de painel e de gaveta */
  --t-nome:28px;          /* o nome dele no hero */

  --t-frase:clamp(30px,4.4vw,58px);        /* as duas frases-manifesto */
  --t-titulo:clamp(29px,3.9vw,50px);       /* título de secção */
  --t-sub:clamp(23px,2.5vw,34px);          /* subtítulo e valor grande */
  --t-citacao:clamp(19px,1.9vw,26px);      /* citação e título de cartão */
  --t-lede:clamp(15.5px,1.3vw,17.5px);     /* o lede de qualquer secção */
  --t-botao:clamp(14px,1.05vw,16px);       /* etiqueta de botão */
  --t-numero:clamp(12px,1vw,13.5px);       /* numeração de passo */


  --respiro:clamp(76px,9vw,128px);   /* o respiro de TODAS as secções (26-ago-2026).
                                        Antes eram quatro valores — 120, 124, 129,6 e 132px —
                                        a fazer exatamente o mesmo trabalho. */

  /* TRACKING — uma regra por situação, não um valor por sítio (26-ago-2026).
     Antes: 19 valores distintos. O mesmo corpo de 13px tinha quatro trackings
     diferentes conforme o sítio, o que não é hierarquia nenhuma. */
  --ls-titulo:-.02em;     /* títulos grandes: quanto maior, mais apertado */
  --ls-apertado:-.01em;   /* subtítulos e corpo destacado */
  --ls-corpo:.02em;       /* corpo e botões — quase neutro */
  --ls-solto:.06em;       /* rótulos curtos, não em maiúsculas */
  --ls-alta:.12em;        /* MAIÚSCULAS pequenas */
  --ls-alta-lg:.17em;     /* MAIÚSCULAS muito pequenas, que precisam de mais ar */

  --t-frase-mob:clamp(29px,8.6vw,44px);
  --t-titulo-mob:clamp(27px,7.6vw,35px);
  --t-sub-mob:clamp(22px,6.6vw,28px);
  --t-citacao-mob:clamp(18px,5.2vw,25px);

  --nuvem:#F7FAFC;
  --tinta:#122430;
  --azul:#1F78D0;
  --azul-escuro:#175A9E;
  --azul-claro:#7CBDF0;
  --quente:#D95F33;
  --hairline:rgba(18,36,48,.12);
  --tinta-60:rgba(18,36,48,.64);
  --sombra-texto:0 1px 26px rgba(20,60,110,.45), 0 1px 3px rgba(20,60,110,.3);
  --ease:cubic-bezier(.33,1,.36,1);
  --salto:cubic-bezier(.34,1.56,.64,1);
  --ease-gaveta:cubic-bezier(.32,.72,0,1); /* curva de sheet iOS (Ionic) — gavetas/painéis */
}

*{ margin:0; padding:0; box-sizing:border-box; }
html{ scroll-behavior:smooth; scroll-padding-top:90px; }
body{
  background:var(--nuvem);
  color:var(--tinta);
  font-family:Outfit,-apple-system,"Segoe UI",system-ui,sans-serif;
  -webkit-font-smoothing:antialiased;
  font-size:var(--t-base);
  line-height:1.5;
}
/* trava de scroll SEM overflow:hidden — hidden anula o scrollbar-gutter e a página
   encolhia ~10px quando a barra nascia no fim da intro (ou ao abrir gaveta/sala).
   Com o body fixed o documento fica sem altura de scroll e o gutter mantém-se;
   o top é compensado por JS (travaScroll/destravaScroll) p/ não saltar ao topo. */
body.com-intro, body.travado{ position:fixed; left:0; right:0; }
img{ max-width:100%; }
::selection{ background:var(--azul); color:#fff; }

/* ---------- scrollbar no tema (slim, azul da marca) ---------- */
/* overflow-y:scroll força o espaço da barra DESDE O ZERO — a largura nunca muda,
   só o polegar aparece quando o scroll desbloqueia (o track é transparente).
   ⚠️ Testado: scrollbar-gutter:stable NÃO chega — o Chromium ignora-o no main frame
   quando o documento fica sem altura de scroll (body fixed na intro/gaveta/sala). */
html{ overflow-y:scroll; overflow-x:hidden; scrollbar-width:thin; scrollbar-color:rgba(31,120,208,.55) transparent; }
::-webkit-scrollbar{ width:11px; height:11px; }
::-webkit-scrollbar-track{ background:transparent; }
::-webkit-scrollbar-thumb{
  background:rgba(31,120,208,.5);
  border-radius:999px;
  border:3px solid transparent;
  background-clip:padding-box;
}
::-webkit-scrollbar-thumb:hover{
  background:rgba(31,120,208,.78);
  border:3px solid transparent;
  background-clip:padding-box;
}

a:focus-visible, button:focus-visible, input:focus-visible{
  outline:2px solid var(--azul); outline-offset:3px; border-radius:4px;
}

/* ---------- o céu vivo (fixed, atrás de tudo) ---------- */
/* altura em lvh (viewport GRANDE): no telemóvel a barra do browser recolhe/expande ao
   rolar e mudava a altura de um fixed inset:0 → o vídeo "clicava" de posição no scroll.
   Com lvh o céu cobre sempre o máximo possível e NUNCA redimensiona durante o scroll. */
.ceu{
  position:fixed; top:0; left:0; right:0; z-index:0;
  height:100vh; height:100lvh;
  transform:translateY(100%);
  overflow:hidden;
}
/* Fora do hero e do fecho, o céu é ESCONDIDO — deixa de existir como camada composta
   por baixo da folha. Era isto que "aparecia" em scroll rápido (checkerboarding do
   compositor mostrava a única camada GPU por baixo). O JS liga/desliga a classe. */
.ceu.oculto{ visibility:hidden; }
.ceu video{
  position:absolute; left:50%; top:50%;
  width:104%; height:104%;
  object-fit:cover;
  transform:translate(-50%,-50%);
}
/* O céu vertical do telemóvel NÃO é centrado: é ancorado ao topo.
   A camada é `lvh` de propósito (ver acima). Só que `lvh` é maior do que a área
   visível enquanto as barras do browser estão à vista — 56 px no aparelho do
   Santiago, até 120 noutros. Um vídeo centrado nessa caixa fica com o seu centro
   por baixo do centro do que se vê, e o enquadramento sai deslocado de forma
   diferente em cada telemóvel. Ancorado em `y = 0`, que é o único ponto que não
   se mexe quando as barras aparecem e desaparecem, o enquadramento é o mesmo em
   todo o lado. Continua em `lvh`, portanto nunca abre faixa branca em baixo. */
@media (orientation:portrait){
  .ceu.ceu-vertical video{
    top:0; left:50%;
    width:100%; height:100%;
    transform:translateX(-50%);
  }
}
.ceu-scrim{
  position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(180deg, rgba(20,50,95,.20) 0%, rgba(20,50,95,.06) 38%, rgba(20,50,95,0) 60%);
}
/* orla esfumada da maré — irmã fixed, acompanha em vh */
.orla-intro{
  position:fixed; left:0; right:0; top:-2px; height:22vh; z-index:1;
  pointer-events:none;
  transform:translateY(100vh);
  background:linear-gradient(180deg, var(--nuvem) 0%, var(--nuvem) 10%, rgba(247,250,252,.6) 50%, rgba(247,250,252,0) 100%);
}
/* will-change só DURANTE a intro — depois nem o céu nem a orla precisam de camada GPU
   permanente (era combustível para o bleed e custava bateria/memória sem ganho). */
body.com-intro .ceu, body.com-intro .orla-intro{ will-change:transform; }

/* ---------- navbar ---------- */
.nav{
  position:fixed; top:0; left:0; right:0; z-index:50;
  height:76px;
  display:flex; align-items:center; gap:30px;
  padding:0 28px;
  color:var(--tinta);
  background:transparent;
  opacity:0;
  pointer-events:none;
  transition:background .35s ease, color .35s ease, box-shadow .35s ease, opacity .4s ease;
}
.nav--solida{
  background:rgba(247,250,252,.94);
  color:var(--tinta);
  box-shadow:0 1px 0 var(--hairline);
  backdrop-filter:blur(8px);
  -webkit-backdrop-filter:blur(8px);
  opacity:1;
  pointer-events:auto;
}
.nav-marca{
  display:flex; align-items:center; gap:11px;
  color:inherit; text-decoration:none;
  opacity:0; pointer-events:none;
  transition:opacity .3s ease;
}
.nav--solida .nav-marca{ opacity:1; pointer-events:auto; }
/* a marca — wordmark no desktop, ligadura RM no mobile.
   O translateY compensa o acento e o descendente do q: o SVG e mais alto que
   as maiusculas, logo centra-lo pela caixa deixava o nome oticamente alto. */
.nav-marca .marca-nome{ height:24px; width:auto; display:block; transform:translateY(5%); }
.nav-marca .marca-rm{ height:30px; width:auto; display:none; }
.nav-links{ display:flex; gap:26px; }
.nav-links a{
  color:inherit; text-decoration:none;
  font-size:var(--t-corpo); font-weight:500; opacity:.92;
  transition:opacity .2s;
}
.nav-links a:hover{ opacity:1; text-decoration:underline; text-underline-offset:6px; text-decoration-thickness:1px; }
.nav-dir{ margin-left:auto; display:flex; align-items:center; gap:20px; }
/* ⚠️ 28-ago-2026: «bora tirar o numero de telemovel da navbar». O telefone continua
   no hero («ou liga: 915 100 172»), no rodape e na /contactos - saiu SO da barra,
   onde era a terceira chamada a accao a competir com o laranja. A regra fica para
   quando o `.nav-tel` voltar a ser preciso. */
.nav-tel{ display:none; }
.nav-tel--antigo{
  color:inherit; text-decoration:none;
  font-weight:700; font-size:var(--t-corpo-lg); letter-spacing:var(--ls-corpo);
}
.nav-tel:hover{ text-decoration:underline; text-underline-offset:5px; }
.nav-orc{ padding:.68em 1.35em; font-size:var(--t-corpo); }
.nav-menu{
  display:none;
  width:38px; height:38px;
  background:none; border:none; cursor:pointer;
  flex-direction:column; align-items:center; justify-content:center; gap:5px;
  color:inherit;
}
.nav-menu span{ display:block; width:19px; height:2px; background:currentColor; border-radius:2px; transition:transform .3s var(--ease); }
.nav-menu[aria-expanded="true"] span:first-child{ transform:translateY(3.5px) rotate(45deg); }
.nav-menu[aria-expanded="true"] span:last-child{ transform:translateY(-3.5px) rotate(-45deg); }
/* ---------- menu móvel: o cartão ----------
   Não é uma gaveta que toma o ecrã — é um cartão pequeno que se abre DEBAIXO do
   polegar, no canto do botão que lhe deu origem. Vidro sobre o céu (a mesma matéria
   da navbar sólida), hairline, e um ponto quente na página onde já estamos.
   Fecha ao tocar fora, ao rolar e com Esc. */
.nav-movel{
  display:none;
  position:fixed; top:56px; right:12px; left:auto; z-index:49;
  width:min(58vw,206px);
  flex-direction:column; gap:0;
  padding:6px;
  background:rgba(247,250,252,.8);
  backdrop-filter:blur(22px) saturate(1.4);
  -webkit-backdrop-filter:blur(22px) saturate(1.4);
  border:1px solid rgba(18,36,48,.07);
  border-radius:16px;
  box-shadow:0 1px 2px rgba(18,36,48,.05), 0 18px 44px rgba(16,38,68,.17);
  transform-origin:100% 0;
  transform:scale(.95) translateY(-6px);
  opacity:0; visibility:hidden;
  transition:opacity .16s ease, transform .18s var(--ease), visibility 0s linear .18s;
}
.nav-movel.aberto{
  opacity:1; visibility:visible;
  transform:none;
  transition:opacity .2s ease, transform .34s var(--ease-gaveta), visibility 0s;
}
.nav-movel a{
  position:relative;
  display:block;
  padding:11px 12px 11px 20px;
  color:var(--tinta); text-decoration:none;
  font-size:var(--t-corpo-lg); font-weight:500; letter-spacing:var(--ls-apertado);
  border-radius:10px;
  opacity:0; transform:translateY(-5px);
  transition:opacity .001s, transform .001s, background .18s ease;
}
.nav-movel.aberto a{
  opacity:1; transform:none;
  transition:opacity .3s ease, transform .34s var(--ease), background .18s ease;
}
/* as linhas pousam uma a seguir à outra — 26ms de intervalo, o suficiente para se sentir */
.nav-movel.aberto a:nth-child(1){ transition-delay:.02s,.02s,0s; }
.nav-movel.aberto a:nth-child(2){ transition-delay:.05s,.05s,0s; }
.nav-movel.aberto a:nth-child(3){ transition-delay:.08s,.08s,0s; }
.nav-movel.aberto a:nth-child(4){ transition-delay:.11s,.11s,0s; }
.nav-movel.aberto a:nth-child(5){ transition-delay:.14s,.14s,0s; }
.nav-movel a:active{ background:rgba(18,36,48,.055); }
/* onde já estamos */
.nav-movel a[aria-current="page"]{ font-weight:600; }
.nav-movel a[aria-current="page"]::before{
  content:'';
  position:absolute; left:8px; top:50%;
  width:4px; height:4px; margin-top:-2px;
  border-radius:50%; background:var(--quente);
}
/* o gesto que mais interessa no telemóvel fica em último e destacado */
.nav-movel-tel{
  margin-top:5px; padding-top:13px;
  border-top:1px solid var(--hairline);
  border-radius:0 0 10px 10px;
  color:var(--quente);
  font-weight:600;
}
/* o véu: quase nada — só o suficiente para o cartão respirar */
body.com-menu::after{
  content:'';
  position:fixed; inset:0; z-index:48;
  background:rgba(16,38,68,.14);
  backdrop-filter:blur(1.5px);
  -webkit-backdrop-filter:blur(1.5px);
  animation:veu-entra .22s ease both;
}
@keyframes veu-entra{ from{ opacity:0 } to{ opacity:1 } }
/* Com o menu aberto, o Clima do canto SAI DE CENA.
   Antes esta regra escurecia só `.clima-bola` — o disco laranja — e isso chegava quando o
   canto era um disco e mais nada. Agora o canto é uma caixa BRANCA de 330px com um campo
   de escrever: por cima do véu do menu (z-index 48 contra os 55 dela) ficava o objeto mais
   luminoso do ecrã, a competir com o menu inteiro. Some, e volta quando o menu fecha.
   ⚠️ O `:has(.clima-bola)` não é decoração: sem ele esta regra (0,2,1) perde para
   `.clima-launch:has(.clima-bola.nasceu)` (0,3,0), que acende a caixa. */
body.com-menu .clima-launch:has(.clima-bola){ opacity:0; pointer-events:none; }

/* ---------- hero ---------- */
.hero{
  position:relative; z-index:2;
  /* svh (viewport PEQUENO, estável): dvh muda quando a barra do browser recolhe ao
     rolar → o hero mudava de altura e a página inteira "clicava". svh nunca mexe. */
  height:100vh; height:100svh;
  display:flex; align-items:center; justify-content:center;
  text-align:center;
  overflow:clip; /* a vinheta ::before estende-se -12% p/ os lados — sem isto criava scroll-x no telemóvel */
}
.hero-copy{ position:relative; width:min(92%,880px); padding-bottom:4vh; }
.hero-copy::before{
  content:'';
  position:absolute; inset:-14% -12%;
  pointer-events:none;
  background:radial-gradient(ellipse 62% 58% at 50% 54%, rgba(16,38,68,.22), rgba(16,38,68,.07) 60%, rgba(16,38,68,0) 76%);
  opacity:0;
}
body:not(.com-intro) .hero-copy::before{ opacity:1; transition:opacity 1s ease; }
.hero-copy > *{ position:relative; }
.frase{
  position:relative;
  font-size:var(--t-frase);
  font-weight:500;
  line-height:1.12;
  letter-spacing:var(--ls-apertado);
}
.frase .camada{ display:block; }
.frase .camada.b{
  position:absolute; inset:0;
  color:#fff;
  opacity:0;
  text-shadow:var(--sombra-texto);
}
.frase .camada.a{ color:var(--tinta); }
.frase .l1{ display:block; }
.frase .l1 span{ display:inline-block; opacity:0; transform:translateY(12px); }
.frase .l2{ display:block; font-weight:600; opacity:0; transform:translateY(16px); margin-top:.1em; }
.frase .seg{ display:inline-block; transition:opacity .35s ease; }
/* O nome sai da linha corrida e passa a ler-se como a marca (26-ago-2026).
   Antes era «Rúben Marques, Climatização e soluções AVAC» tudo ao mesmo corpo,
   e o nome afogava-se. Agora são duas linhas: o nome em cima, o ofício em baixo.
   O ofício fica em CAIXA DE FRASE, na fonte da casa, sem separador e a um
   tamanho que se lê — a versão em caps com tracking («CLIMATIZAÇÃO · AVAC») está
   podada no guia como tell de logótipo feito por IA. */
.hero-sub{
  margin-top:20px;
  font-weight:500;
  color:#fff;
  text-shadow:var(--sombra-texto);
  opacity:0;
  display:flex; flex-direction:column; align-items:center;
  gap:6px;
}
.hero-nome{
  font-family:'Space Grotesk',Outfit,-apple-system,"Segoe UI",system-ui,sans-serif;
  font-size:var(--t-nome);
  font-weight:600;
  letter-spacing:var(--ls-apertado);
  line-height:1.1;
}
.hero-oficio{
  font-size:var(--t-base);
  font-weight:500;
  opacity:.86;
}
.hero-acoes{
  margin-top:28px;
  display:flex; align-items:center; justify-content:center; gap:22px; flex-wrap:wrap;
  flex-direction:column;
  opacity:0;
}
/* ---- o campo aberto do hero (ver o comentário no index.html) ---- */
.hero-pedido{ width:min(100%,520px); }
.hero-pedido-rot{
  display:block; margin-bottom:10px;
  font-size:var(--t-rotulo); font-weight:600; color:#fff;
  text-shadow:var(--sombra-texto);
}
/* A caixa é BRANCA e opaca, não vidro: por cima de nuvens brancas um campo translúcido
   deixa de se ler como campo — vira uma mancha. Opaco, lê-se à primeira e o contraste do
   texto que a pessoa escreve deixa de depender do fotograma que calhar. */
.hero-pedido-caixa{
  display:flex; align-items:center; gap:8px;
  padding:7px 7px 7px 20px;
  background:#fff;
  border-radius:999px;
  box-shadow:0 18px 44px -20px rgba(10,25,45,.5), 0 2px 8px rgba(10,25,45,.14);
}
.hero-pedido-txt{
  flex:1 1 auto; min-width:0;
  border:0; background:none; outline:none;
  font-family:inherit; font-size:var(--t-corpo); color:var(--tinta);
  padding:12px 0;
}
.hero-pedido-txt::placeholder{ color:var(--tinta-60); opacity:.72; }
/* ⚠️ 27-ago-2026, apanhado por ele ao clicar: «fica uma cena azul à volta».
   O `outline:none` ali em cima NÃO chegava. A regra global do site.css:118
   (`input:focus-visible{ outline:2px solid var(--azul) }`) tem mais especificidade do que
   uma classe sem estado, portanto ganhava — e desenhava um retângulo azul de cantos
   redondos DENTRO da pílula branca, ao lado do anel laranja que já marca o foco.
   Duas marcas de foco no mesmo objeto, uma delas fora da palete.
   Mata-se com o mesmo estado, e o foco continua bem visível: quem o mostra é o anel
   laranja da pílula inteira, que é maior e é da casa. */
.hero-pedido-txt:focus-visible{ outline:none; }
.hero-pedido-caixa:focus-within{ box-shadow:0 18px 44px -20px rgba(10,25,45,.5), 0 0 0 3px rgba(217,95,51,.55); }
/* OPÇÃO B, escolhida a 27-ago-2026. Ele deixou entre a A (seta) e a B (palavra) e disse
   «escolhe tu». Fica a B: a seta não diz o que acontece a seguir, «Pedir orçamento» diz — e
   é a MESMA palavra da navbar e do menu, portanto o site promete a mesma coisa em todo o
   lado. O alvo cresce de 46px de círculo para uma pastilha inteira, e o laranja ganha o peso
   que perdia num círculo pequeno, sem entrar um segundo botão no hero. */
.hero-pedido-btn{
  flex:0 0 auto;
  border:0; cursor:pointer; font-family:inherit;
  padding:13px 22px; border-radius:999px;
  /* 28-ago-2026, visto por ele: «o pedir orcamento do hero devia tar a preto e ta a
     branco a letra». Estava mesmo: #fff aqui contra `var(--tinta)` no `.btn-cta` da
     navbar e no do fim. Era o unico laranja do site com letra branca. Alem de destoar,
     branco sobre #D95F33 da 3,0:1 e nao passa o AA de 4,5:1; a tinta da 8,3:1. */
  background:var(--quente); color:var(--tinta);
  font-size:var(--t-corpo); font-weight:600; line-height:1.2;
  white-space:nowrap;
  transition:transform .2s var(--ease), background .2s ease;
}
@media (hover:hover) and (pointer:fine){
  .hero-pedido-btn:hover{ background:#C4522A; }
}
.hero-pedido-btn:active{ transform:scale(.97); }
/* o botão vive DENTRO da pílula, e um outline azul encostado ao branco da caixa some-se
   com o anel laranja do :focus-within. Branco por dentro do laranja: vê-se de longe e
   distingue-se de quando é o campo que está focado. */
.hero-pedido-btn:focus-visible{ outline:2px solid #fff; outline-offset:-4px; border-radius:999px; }
.hero-tel{
  color:#fff; text-decoration:none;
  font-size:var(--t-corpo-lg);
  text-shadow:var(--sombra-texto);
}
.hero-tel strong{ font-weight:700; text-decoration:underline; text-underline-offset:4px; text-decoration-thickness:1px; }
.hero-tel:hover strong{ text-decoration-thickness:2px; }
.hero-prova{
  margin-top:22px;
  font-size:var(--t-rotulo); letter-spacing:var(--ls-corpo);
  color:#fff;
  /* Sombra PRÓPRIA, mais apertada que a --sombra-texto partilhada.
     Medido no site publicado: o branco desta linha sobre o frame mais claro do céu dava
     1,28:1 no desktop e 1,24:1 no mobile. A --sombra-texto tem 26 px de desfoque — chega
     para o H1, que é grande e grosso, mas a 13 px espalha-se de mais e não segura nada.
     Esta tem um núcleo opaco de 2 px colado à letra, que é o que dá a aresta. */
  /* A terceira camada, de 22 px, saiu a 26-ago-2026 — e a razao e estranha mas e
     medida. Um desfoque conta como parte do elemento pintado: com ela, esta linha
     de 345x19 px era registada com 29 250 px2 de area, mais do que a maior palavra
     da frase (24 336). Isso fazia dela o «maior elemento» da pagina aos olhos da
     Google, e como e a ULTIMA coisa da coreografia a acender, era ela que parava o
     cronometro. Sem a camada larga volta a ser a frase a contar. As duas camadas
     apertadas ficam: sao elas que dao a aresta ao branco sobre as nuvens. */
  text-shadow:
    0 1px 2px rgba(8,26,48,.92),
    0 0 7px rgba(8,26,48,.82);
  opacity:0;
}

/* ---------- botões ---------- */
.btn{
  font-family:inherit; border:none; cursor:pointer;
  border-radius:999px;
  text-decoration:none;
  display:inline-block;
}
.btn-cta{
  /* 🔴 28-ago-2026: esta regra nunca declarou `border` nem `border-radius`. Nos 19 `<a>` do
     site isso não se via, porque uma âncora não tem borda nativa. Nos 21 `<button>` via-se:
     ficavam com o `border:2px outset` e os cantos vivos que o browser dá por defeito — um
     botão cinzento-3D dentro de um site de pílulas. Só saltou à vista quando nasceu a secção
     dos BTU, que é o primeiro `<button class="btn-cta">` sozinho num fundo claro e largo.
     Declarar aqui corrige os 21 de uma vez; quem já tinha raio por outra classe (`.nav-orc`)
     continua igual, porque declara o mesmo valor. */
  border:0; border-radius:999px; cursor:pointer;
  font-family:inherit;
  background:var(--quente);
  color:var(--tinta);
  font-weight:600;
  font-size:var(--t-botao);
  letter-spacing:var(--ls-corpo);
  padding:.9em 1.8em;
  box-shadow:0 8px 28px rgba(15,30,50,.22);
  transition:transform .25s var(--ease), box-shadow .25s var(--ease);
}
/* hover só onde há rato — em touch o tap prendia o estado levantado */
@media (hover:hover) and (pointer:fine){
  .btn-cta:hover{ transform:translateY(-2px); box-shadow:0 14px 36px rgba(15,30,50,.28); }
}
/* pressão: resposta imediata (o site "ouviu") — soltar volta ao ritmo base */
.btn-cta:active{ transform:translateY(0) scale(.97); transition-duration:.12s; }

/* ---------- a folha de conteúdo ---------- */
.folha{
  position:relative; z-index:2;
  isolation:isolate;
  background:var(--nuvem);
  color:var(--tinta);
}
.folha-orla{
  position:absolute; top:-88px; left:0; right:0; height:88px;
  pointer-events:none;
  background:linear-gradient(180deg, rgba(247,250,252,0) 0%, rgba(247,250,252,.65) 55%, var(--nuvem) 100%);
}
/* A saida e mais longa do que a entrada (.folha-orla, 88px) de proposito: em cima o branco
   esta a CHEGAR e o olho aceita o corte curto; em baixo dissolve-se sobre nuvens, que tem
   textura, e a 88px o degrade lia-se como uma faixa em vez de uma passagem. */
.folha-fim{
  position:absolute; bottom:-132px; left:0; right:0; height:132px;
  pointer-events:none;
  background:linear-gradient(180deg,
    var(--nuvem) 0%, rgba(247,250,252,.82) 28%,
    rgba(247,250,252,.46) 58%, rgba(247,250,252,.16) 82%, rgba(247,250,252,0) 100%);
}
.sec{ padding:var(--respiro) 0; }
.sec-inner{ width:min(92%,1180px); margin:0 auto; }
.sec-cab h2, .sec-sobre h2{
  font-size:var(--t-titulo);
  font-weight:600;
  line-height:1.08;
  letter-spacing:var(--ls-apertado);
}
.sec-lede{
  margin-top:16px;
  font-size:var(--t-lede);
  color:var(--tinta-60);
  max-width:56ch;
}

/* ---------- serviços · o leque ---------- */
.leque{
  display:flex; gap:12px;
  margin-top:clamp(36px,4.5vw,56px);
  height:clamp(400px,50vh,500px);
}
.leque-painel{
  position:relative;
  flex:1; min-width:0;
  border-radius:18px;
  overflow:hidden;
  cursor:pointer;
  transition:flex .55s var(--ease);
  box-shadow:0 16px 48px rgba(15,30,50,.14);
}
/* o aberto tem de puxar bem mais do que os fechados, senão eles comem-lhe a
   largura e a copy quebra em cinco linhas. Vinha de quando eram cinco painéis;
   com quatro (manutenção+reparação+limpeza fundidas) o 3.2 continua a assentar. */
.leque-painel.ativa{ flex:3.2; }
/* o painel inteiro leva à página do serviço (ver js/leque.js), por isso o aberto
   continua a ser um alvo — já não é `cursor:default`. */
.leque-painel:focus{ outline:none; }
.leque-painel:focus-visible{ outline:2px solid var(--quente); outline-offset:-4px; }
/* sem esta regra o <article tabindex="0"> ficava com o anel preto por omissão do
   Chrome por cima da foto — o "outline preto" que aparecia às vezes. */
/* a fatia fechada das bombas de calor: puxada para onde está a unidade — ao
   centro esta foto é só cortinado e não se percebia o que era. Só no desktop,
   que no telemóvel o azulejo é largo e mostra a sala toda. */
.leque-painel--bombas:not(.ativa) img{ object-position:74% 42%; }
/* por CLASSE e não por nth-child: as bombas eram o 5º painel na home e depois
   da fusão do trio da manutenção passaram a ser o 4º — e na página de Loures o 4º
   é outra foto. Amarrado à posição, este corte ia parar ao cartão errado. */
.leque-painel img{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  /* as bombas são o único painel com object-position próprio: ao abrir, a regra
     deixava de valer e a foto SALTAVA de 74%/42% para o centro. Com transição,
     desliza como as outras. */
  transition:object-position .55s var(--ease);
}
.leque-scrim{
  position:absolute; inset:0;
  background:linear-gradient(180deg, rgba(18,36,48,0) 34%, rgba(18,36,48,.28) 62%, rgba(18,36,48,.74) 100%);
}
.leque-rotulo{
  position:absolute; left:50%; bottom:22px;
  transform:translateX(-50%) rotate(180deg);
  writing-mode:vertical-rl;
  color:#fff;
  font-size:var(--t-rotulo); font-weight:600; letter-spacing:var(--ls-solto);
  white-space:nowrap;
  text-shadow:0 1px 12px rgba(10,25,45,.6);
  opacity:1;
  /* ENTRA atrasado: só depois de o texto horizontal ter saído de cena. Ver a nota grande
     em baixo — o atraso vive aqui, no estado fechado, e não na regra do painel aberto. */
  transition:opacity .28s ease .2s;
  pointer-events:none;
}
/* SAI já: quando o painel abre, o rótulo vertical some antes de tudo o resto. */
.leque-painel.ativa .leque-rotulo{ opacity:0; transition:opacity .14s ease 0s; }

/* 🔴 29-ago-2026 — a sequência de troca entre o rótulo vertical e o texto do painel.
   Ele apanhou isto ao vivo, a fechar um painel: «o texto vai encolhendo... primeiro deve
   desaparecer o texto, e depois é que aparece o vertical, senão fica um efeito estranho».
   Tinha razão e eram DOIS defeitos no mesmo sítio:

   1) O atraso de .18s estava na regra base do `.leque-conteudo`, e um atraso escrito aí
      aplica-se NAS DUAS DIREÇÕES. Ao abrir servia (o texto esperava pelo painel); ao
      fechar ficava a segurar o texto durante .18s enquanto o rótulo vertical já entrava,
      e viam-se os dois sobrepostos no mesmo canto.
      Agora cada sentido tem o seu tempo: a saída é imediata e rápida (.15s, sem atraso, na
      regra base) e a entrada é que espera (.26s, na regra `.ativa`).

   2) Com `left` e `right` colados às margens, a caixa do texto encolhia junto com o painel
      e o parágrafo refluía — era o «encolher» que ele viu. No estado fechado a largura
      passa a ser fixa: o texto deixa de refluir e o `overflow:hidden` do painel corta-o
      enquanto ele desaparece. Ao abrir volta a `right:26px`, e como só surge .26s depois
      (com o painel já quase aberto), a mudança não se vê. */
.leque-conteudo{
  position:absolute; left:26px; bottom:22px;
  width:320px; max-width:calc(100% - 52px);
  color:#fff;
  opacity:0; transform:translateY(10px);
  transition:opacity .15s ease 0s, transform .25s var(--ease) 0s;
}
.leque-painel.ativa .leque-conteudo{
  opacity:1; transform:none;
  right:26px; width:auto; max-width:none;
  transition:opacity .34s ease .26s, transform .4s var(--ease) .26s;
}
.leque-num{
  display:block;
  font-size:var(--t-legenda); font-weight:600; letter-spacing:var(--ls-alta);
  color:#E97742;
  margin-bottom:8px;
  font-variant-numeric:tabular-nums;
}
.leque-conteudo h3{
  font-size:var(--t-citacao);
  font-weight:600;
  letter-spacing:var(--ls-apertado);
  white-space:nowrap;
}
.leque-conteudo p{
  margin-top:6px;
  font-size:var(--t-corpo); line-height:1.5;
  color:rgba(255,255,255,.86);
  max-width:38ch;
}
.leque-cta{
  margin-top:14px;
  background:none; border:none; cursor:pointer;
  font-family:inherit;
  font-size:var(--t-rotulo); font-weight:600;
  color:#fff;
  padding:0;
  text-decoration:underline;
  text-underline-offset:5px;
  text-decoration-thickness:1px;
  transition:text-decoration-thickness .2s ease;
}
@media (hover:hover) and (pointer:fine){
  .leque-cta:hover{ text-decoration-thickness:2px; }
}
.leque-cta:active{ opacity:.65; }
/* X do azulejo expandido (só aparece no mobile, no painel .expandida) */
.leque-fechar{
  display:none;
  position:absolute; top:12px; right:12px; z-index:4;
  width:38px; height:38px; border-radius:50%;
  align-items:center; justify-content:center;
  background:rgba(9,20,36,.55); color:#fff;
  border:none; cursor:pointer;
  -webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px);
  transition:transform .16s var(--ease);
}
.leque-fechar:active{ transform:scale(.88); }
.leque-fechar svg{ width:18px; height:18px; display:block; }

/* A listra dos negócios, por baixo do leque (29-ago-2026).
   O leque responde a «que serviços fazem?»; esta linha responde a «servem o meu tipo de
   espaço?», que é outra pergunta e por isso merece lugar próprio em vez de ficar escondida
   dentro de um dos painéis.
   Pastilhas de texto e NÃO cartões com fotografia: os seis painéis logo acima já são a
   imagem desta secção, e uma segunda parede de fotos a seguir competia com eles em vez de
   os completar. Na /servicos é ao contrário — lá esta secção tem H2 próprio e leva fotos,
   porque lá é uma secção a sério e não o remate de outra. */
.leque-tipos{ margin-top:clamp(26px,3.4vw,40px); }
.leque-tipos-rotulo{
  margin:0 0 14px;
  font-size:var(--t-rotulo);
  font-weight:600;
  color:var(--tinta-60);
}
.leque-tipos-lista{ display:flex; flex-wrap:wrap; gap:8px; }
.leque-tipos-lista a{
  display:inline-flex; align-items:center;
  padding:9px 15px;
  border:1px solid rgba(15,30,50,.14);
  border-radius:999px;
  background:rgba(255,255,255,.6);
  color:var(--tinta);
  font-size:14.5px; font-weight:500; line-height:1;
  text-decoration:none;
  transition:border-color .22s ease, background .22s ease, transform .22s ease;
}
@media (hover:hover) and (pointer:fine){
  .leque-tipos-lista a:hover{
    border-color:var(--quente);
    background:#fff;
    transform:translateY(-1px);
  }
}
.leque-tipos-lista a:focus-visible{ outline:2px solid var(--quente); outline-offset:3px; }
@media (max-width:860px){
  .leque-tipos{ margin-top:22px; }
  .leque-tipos-lista{ gap:7px; }
  .leque-tipos-lista a{ padding:8px 13px; font-size:13.5px; }
}

/* entrada — os painéis sobem à vez quando a secção aparece */
.leque:not(.revelado) .leque-painel{ opacity:0; }
.leque.revelado .leque-painel{ animation:leque-entra .82s var(--salto) both; }
.leque.revelado .leque-painel:nth-child(2){ animation-delay:.10s; }
.leque.revelado .leque-painel:nth-child(3){ animation-delay:.20s; }
.leque.revelado .leque-painel:nth-child(4){ animation-delay:.30s; }
.leque.revelado .leque-painel:nth-child(5){ animation-delay:.40s; }
@keyframes leque-entra{
  from{ opacity:0; transform:translateY(52px); }
  to{ opacity:1; transform:none; }
}

/* ---------- serviços · palco cinemático (preso ao scroll) ---------- */
/* ---------- equipamento · anatomia comandada pelo scroll ---------- */
.sec-equipamento{
  --equipamento-scroll:clamp(1050px,135vh,1450px);
  position:relative;
  height:calc(100svh + var(--equipamento-scroll));
  background:var(--nuvem);
  color:var(--tinta);
}
.equipamento-track{ height:100%; }
.equipamento-sticky{
  position:sticky; top:0;
  height:100vh; height:100svh;
  overflow:hidden;
  isolation:isolate;
  background:var(--nuvem);
}
.equipamento-frase{
  position:absolute; z-index:2;
  top:clamp(74px,8.5vh,94px);
  left:max(4vw,calc((100vw - 1180px) / 2));
  width:min(92vw,980px);
  font-size:var(--t-frase);
  font-weight:600;
  line-height:.96;
  letter-spacing:var(--ls-titulo);
  text-wrap:balance;
}
.equipamento-palavra{
  display:inline-block;
  opacity:0;
  transform:translateY(.32em);
  will-change:transform,opacity;
}
.equipamento-media{
  position:absolute; z-index:1;
  left:50%; top:clamp(192px,21.5vh,230px);
  bottom:clamp(16px,2.5vh,28px);
  width:min(94vw,1420px);
  transform:translateX(-50%);
}
.equipamento-poster,
.equipamento-canvas,
.equipamento-estatico{
  position:absolute; inset:0;
  display:block;
  width:100%; height:100%;
  object-fit:contain;
  object-position:50% 0;
}
.equipamento-poster{ opacity:1; transition:opacity .18s linear; }
.equipamento-canvas{
  opacity:0;
  background:var(--nuvem);
  transition:opacity .18s linear;
}
.equipamento-media.tem-frame .equipamento-poster{ opacity:0; }
.equipamento-media.tem-frame .equipamento-canvas{ opacity:1; }
.equipamento-estatico{ display:none; }

/* selo de marcas — canto inferior esquerdo (secção de equipamento + hero de serviços) */
.marcas-selo{
  position:absolute; z-index:3;
  left:max(4vw,calc((100vw - 1180px) / 2));
  bottom:clamp(20px,3.4vh,38px);
  display:flex; flex-direction:column; gap:10px;
  pointer-events:none;
  /* entra só no fim da animação (JS controla opacity/transform) */
  opacity:0; transform:translateY(12px);
  will-change:opacity, transform;
}
.marcas-selo-txt{
  font-size:var(--t-legenda); font-weight:600;
  letter-spacing:var(--ls-solto); text-transform:uppercase;
  color:var(--tinta-60);
}
.marcas-selo-logos{ display:flex; align-items:center; gap:22px; }
.marcas-selo .selo-logo{ display:inline-flex; color:var(--tinta); opacity:.78; }
.marcas-selo .selo-logo svg{ display:block; fill:currentColor; }
.marcas-selo .selo-mitsubishi svg{ width:92px; height:auto; }
.marcas-selo .selo-daikin svg{ width:78px; height:auto; }
@media (max-width:860px){
  .marcas-selo{ left:18px; bottom:clamp(14px,2.4vh,24px); gap:8px; }
  .marcas-selo-txt{ font-size:var(--t-selo); letter-spacing:var(--ls-solto); }
  .marcas-selo-logos{ gap:18px; }
  .marcas-selo .selo-mitsubishi svg{ width:76px; }
  .marcas-selo .selo-daikin svg{ width:64px; }
}

.sec-palco{ position:relative; }
.palco-titulo{
  position:absolute; z-index:2; top:clamp(6rem,13vh,7.5rem); left:0; right:0;
  width:min(92%,1180px); margin:0 auto;
  color:#fff; font-size:var(--t-sub); font-weight:600;
  line-height:1.1; letter-spacing:var(--ls-apertado);
}
.palco-titulo-mob{ display:none; }

/* o track alto dá a duração do "pin"; o palco fica colado (sticky) */
.palco-track{ position:relative; height:calc(var(--passos) * 100vh); }
.palco-stage{
  position:sticky; top:0; height:100vh; overflow:hidden;
  display:flex; align-items:center;
}
.palco-bg{ position:absolute; inset:0; z-index:0; background:var(--tinta); }
.palco-img{ position:absolute; inset:0; opacity:0; transition:opacity 1s var(--ease); will-change:opacity; }
.palco-img.is-active{ opacity:1; }
.palco-img img{ width:100%; height:100%; object-fit:cover; }
.palco-veu{
  position:absolute; inset:0; z-index:1; pointer-events:none;
  background:
    linear-gradient(90deg, rgba(12,26,42,.95) 0%, rgba(12,26,42,.8) 38%, rgba(15,42,74,.44) 72%, rgba(20,62,112,.2) 100%),
    linear-gradient(0deg, rgba(9,20,36,.9) 0%, rgba(9,20,36,.08) 52%, rgba(9,20,36,.42) 100%);
}
.palco-conteudo{ position:relative; z-index:2; width:min(92%,1180px); margin:0 auto; }
.palco-passos{ position:relative; min-height:clamp(15rem,32vh,20rem); max-width:44rem; }
.palco-passo{
  position:absolute; inset:0 auto auto 0; width:100%;
  opacity:0; transform:translateY(26px);
  transition:opacity .55s var(--ease), transform .7s var(--ease);
  pointer-events:none;
}
.palco-passo.is-active{ opacity:1; transform:none; pointer-events:auto; }
.palco-nome{
  font-size:var(--t-titulo); font-weight:600; line-height:1.05; letter-spacing:var(--ls-apertado);
  color:#fff; margin-bottom:1rem; max-width:16ch;
}
.palco-desc{ color:rgba(255,255,255,.82); font-size:var(--t-lede); line-height:1.6; max-width:42ch; }
.palco-cta{
  margin-top:1.5rem; display:inline-block;
  background:none; border:none; cursor:pointer; font-family:inherit;
  font-size:var(--t-corpo); font-weight:600; color:#fff; padding:0;
  text-decoration:underline; text-underline-offset:6px; text-decoration-thickness:1px;
  transition:text-decoration-thickness .2s ease, color .2s ease;
}
.palco-cta:hover{ text-decoration-thickness:2px; color:var(--quente); }
.palco-pe{
  display:flex; align-items:center; gap:1.5rem;
  margin-top:clamp(2.2rem,4vw,3.4rem); max-width:44rem;
}
.palco-prog{ position:relative; flex:1; height:2px; background:rgba(255,255,255,.18); overflow:hidden; border-radius:2px; }
.palco-barra{ position:absolute; inset:0; background:var(--quente); transform-origin:left; transform:scaleX(0); }
.palco-indice{ color:rgba(255,255,255,.55); font-variant-numeric:tabular-nums; font-size:var(--t-corpo); letter-spacing:var(--ls-solto); white-space:nowrap; }

/* timeline do método (mobile) — o fio do percurso; escondida no desktop */
.metodo-fio{ display:none; }

@media (max-width:860px){
  .palco-track{ display:none; }
  .palco-titulo-mob{
    display:block;
    width:min(92%,1180px); margin:0 auto clamp(22px,5vw,32px);
    padding-top:clamp(56px,10vw,84px);
    font-size:var(--t-titulo-mob); font-weight:600; line-height:1.1; letter-spacing:var(--ls-apertado);
    color:var(--tinta);
  }

  /* o fio: track cinzenta + preenchimento laranja controlado por --fio-fill (0→1) via scroll */
  .metodo-fio{
    display:block; list-style:none;
    position:relative;
    width:min(92%,1180px); margin:0 auto;
    padding-bottom:clamp(40px,11vw,64px);
    --fio-fill:0;
  }
  .metodo-fio::before,
  .metodo-fio::after{
    content:""; position:absolute; left:18px; width:2px;
    top:var(--fio-top,0); border-radius:2px; z-index:0;
  }
  .metodo-fio::before{ height:var(--fio-len,0); background:var(--hairline); }
  .metodo-fio::after{
    height:calc(var(--fio-len,0) * var(--fio-fill));
    background:linear-gradient(180deg, var(--quente), #E8794F);
    box-shadow:0 0 14px rgba(217,95,51,.28);
  }

  .mfio-passo{
    position:relative;
    display:grid; grid-template-columns:38px 1fr; column-gap:16px;
    padding-bottom:clamp(26px,7vw,40px);
  }
  .mfio-passo:last-child{ padding-bottom:0; }

  .mfio-no{
    grid-column:1; justify-self:center; align-self:start;
    width:38px; height:38px; border-radius:50%;
    display:grid; place-items:center;
    background:var(--nuvem);
    border:2px solid var(--hairline);
    color:var(--tinta-60);
    font-weight:600; font-size:var(--t-legenda); letter-spacing:var(--ls-solto);
    font-variant-numeric:tabular-nums;
    position:relative; z-index:2;
    transition:background .5s var(--ease), color .5s var(--ease),
               border-color .5s var(--ease), box-shadow .5s var(--ease),
               transform .5s var(--salto);
  }
  .mfio-passo.aceso .mfio-no{
    background:var(--quente); border-color:var(--quente); color:var(--tinta);
    box-shadow:0 6px 18px rgba(217,95,51,.32);
    transform:scale(1.08);
  }

  .mfio-corpo{ grid-column:2; padding-top:8px; }
  .mfio-tit{
    font-size:var(--t-destaque); font-weight:600; letter-spacing:var(--ls-apertado); line-height:1.18;
    color:var(--tinta-60);
    transition:color .5s var(--ease);
  }
  .mfio-passo.aceso .mfio-tit{ color:var(--tinta); }
  .mfio-desc{
    position:relative;
    margin-top:6px; font-size:var(--t-corpo); line-height:1.55;
    color:var(--tinta-60); max-width:36ch;
  }
  /* camada-fantasma: reserva a altura total (sem salto de layout) e fica na árvore
     de acessibilidade (color:transparent, não visibility:hidden) para ser lida */
  .mfio-desc-medida{ color:transparent; }
  /* camada visível: o texto que se "escreve" por cima, letra a letra */
  .mfio-desc-live{ position:absolute; inset:0; color:var(--tinta-60); }
  /* cursor a piscar só enquanto escreve */
  .mfio-desc.a-escrever .mfio-desc-live::after{
    content:''; display:inline-block;
    width:2px; height:1.02em; margin-left:2px; vertical-align:-2px;
    background:var(--quente); border-radius:1px;
    animation:mfio-cursor .85s steps(1) infinite;
  }
  @keyframes mfio-cursor{ 0%,100%{ opacity:1; } 50%{ opacity:0; } }
}

/* ============================================================
   MÉTODO · janelas numeradas (home)
   Cinco janelas lado a lado; a aberta mostra a obra, as fechadas esperam.
   Substituiu o palco preso ao scroll porque a secção anterior — o equipamento —
   já é presa ao scroll, e dois mecanismos iguais seguidos matavam-se um ao outro.
   O palco (.sec-palco / .metodo-fio, acima) continua vivo na página Sobre.
   ============================================================ */
/* mesma razão da .sec-faq: é uma secção plana que pode cruzar-se com a camada fixa do céu */
.sec-metodo{ position:relative; z-index:1; padding:var(--respiro) 0; background:var(--nuvem); }
.metodo-cab{ width:min(92%,1180px); margin:0 auto clamp(30px,4vw,48px); }
.metodo-cab h2{
  font-size:var(--t-titulo); font-weight:600; line-height:1.08;
  letter-spacing:var(--ls-titulo); color:var(--tinta); max-width:18ch;
}
.metodo-cab p{
  margin-top:14px; color:var(--tinta-60);
  font-size:var(--t-lede); line-height:1.6; max-width:46ch;
}

.jan{
  width:min(92%,1180px); margin:0 auto;
  display:flex; gap:3px;
  height:clamp(420px,58vh,600px);
  border-radius:18px; overflow:hidden;
  background:var(--tinta);            /* o fundo vira a juntagem entre janelas */
  box-shadow:0 24px 60px -28px rgba(18,36,48,.42);
}

.jan-p{
  position:relative; flex:1 1 0; min-width:0; overflow:hidden;
  background:var(--tinta);
  opacity:0;
  /* a entrada é animação, não transição: se fosse transição, o atraso escalonado
     colava-se também ao flex-grow e as janelas fechavam com atraso umas das outras */
  transition:flex-grow .82s var(--ease-gaveta);
}
.jan.entrou .jan-p{
  animation:jan-entrar .7s var(--ease) both;
  animation-delay:calc(var(--i) * 80ms);
}
@keyframes jan-entrar{
  from{ opacity:0; transform:translateY(20px); }
  to{ opacity:1; transform:none; }
}
.jan-p.is-open{ flex-grow:2.9; }

.jan-foto{ position:absolute; inset:0; z-index:0; }
.jan-foto img{
  width:100%; height:100%; object-fit:cover; object-position:var(--pos,50% 50%);
  transform:scale(1.08);
  /* fotos claras precisam de descer mais para a janela fechada não ficar
     pálida ao lado das outras — daí o brilho ser afinável por janela */
  filter:saturate(.4) brightness(var(--brilho-fechada,.62)) contrast(1.08);
  transition:filter .9s var(--ease), transform 1.4s var(--ease);
}
.jan-p.is-open .jan-foto img{
  filter:saturate(1) brightness(.95) contrast(1.02);
  transform:scale(1);
}

.jan-veu{
  position:absolute; inset:0; z-index:1; pointer-events:none;
  background:
    /* faixa de cima: o número tem de se ler mesmo quando a foto ali é céu claro */
    linear-gradient(180deg, rgba(9,20,36,.62) 0, rgba(9,20,36,0) 92px),
    linear-gradient(0deg,
      rgba(9,20,36,.92) 0%, rgba(9,20,36,.62) 32%,
      rgba(9,20,36,.14) 64%, rgba(9,20,36,.2) 100%);
}

.jan-corpo{
  position:relative; z-index:2; height:100%;
  display:flex; flex-direction:column; justify-content:space-between;
  padding:clamp(18px,1.8vw,26px);
}

.jan-no{
  font-size:var(--t-numero); font-weight:600; letter-spacing:var(--ls-alta);
  font-variant-numeric:tabular-nums;
  color:rgba(255,255,255,.5);
  /* o número cai muitas vezes sobre a zona clara da foto (céu, parede branca) —
     sem sombra desaparece, sobretudo o laranja da janela aberta */
  text-shadow:0 1px 10px rgba(9,20,36,.65);
  transition:color .5s var(--ease);
}
.jan-p.is-open .jan-no{ color:var(--quente); }

.jan-tit{ margin:0; }
.jan-bt{
  appearance:none; background:none; border:none; padding:0; margin:0;
  font-family:inherit; text-align:left; cursor:pointer;
  font-size:var(--t-painel); font-weight:600; line-height:1.16;
  letter-spacing:var(--ls-apertado); color:rgba(255,255,255,.9);
  transition:font-size .82s var(--ease-gaveta), color .4s var(--ease);
}
.jan-bt::after{ content:""; position:absolute; inset:0; z-index:5; }  /* a janela toda é o alvo */
.jan-bt:focus-visible{ outline:none; }
.jan-p:has(.jan-bt:focus-visible){ outline:2px solid var(--quente); outline-offset:-3px; }
.jan-p.is-open .jan-bt{ font-size:var(--t-sub); color:#fff; }

.jan-painel{
  display:grid; grid-template-rows:0fr;
  transition:grid-template-rows .7s var(--ease-gaveta);
}
.jan-p.is-open .jan-painel{ grid-template-rows:1fr; }
.jan-painel > div{ overflow:hidden; }
.jan-desc{
  margin-top:12px; max-width:34ch;
  color:rgba(255,255,255,.84); font-size:var(--t-botao); line-height:1.6;
  opacity:0; transform:translateY(8px);
  transition:opacity .5s var(--ease) .12s, transform .6s var(--ease) .12s;
}
.jan-p.is-open .jan-desc{ opacity:1; transform:none; }

/* o convite — só na janela aberta e só quando o rato lá está.
   Vive dentro do painel que colapsa, por isso o espaço já está reservado:
   ao aparecer não empurra nada. Fica acima do alvo de clique da janela (z-index 5)
   ou os cliques nunca lhe chegavam. */
.jan-cta{
  position:relative; z-index:6;
  margin-top:16px;
  display:inline-flex; align-items:center; gap:.4em;
  background:none; border:none; padding:0; cursor:pointer; font-family:inherit;
  font-size:var(--t-rotulo); font-weight:600; color:#fff;
  text-decoration:underline; text-underline-offset:5px; text-decoration-thickness:1px;
  opacity:0; transform:translateY(6px); pointer-events:none;
  transition:opacity .35s var(--ease), transform .45s var(--ease),
             text-decoration-thickness .2s ease;
}
.jan-cta span{ transition:transform .3s var(--ease); }
.jan-p.is-open:hover .jan-cta,
.jan-p.is-open:focus-within .jan-cta{
  opacity:1; transform:none; pointer-events:auto;
}
@media (hover:hover) and (pointer:fine){
  .jan-cta:hover{ text-decoration-thickness:2px; }
  .jan-cta:hover span{ transform:translateX(3px); }
}
.jan-cta:active{ opacity:.65; }
/* sem rato — ou no layout empilhado — o convite vive sempre na janela aberta,
   senão em touch não havia forma de lá chegar */
@media (hover:none), (max-width:860px){
  .jan-p.is-open .jan-cta{ opacity:1; transform:none; pointer-events:auto; }
}

/* o fio de tempo — enche enquanto a janela está aberta, é o que dá vida à secção */
.jan-prog{
  position:absolute; left:0; right:0; bottom:0; z-index:3; height:3px;
  background:rgba(255,255,255,.16); opacity:0;
  transition:opacity .4s var(--ease);
}
.jan-p.is-open .jan-prog{ opacity:1; }
.jan-prog i{
  display:block; height:100%; width:100%;
  background:linear-gradient(90deg, var(--quente), #E8794F);
  transform-origin:left; transform:scaleX(0);
}
.jan-p.is-open .jan-prog i{ animation:jan-encher var(--dwell,5000ms) linear forwards; }
.jan.pausada .jan-p.is-open .jan-prog i{ animation-play-state:paused; }
.jan.pausada .jan-p.is-open .jan-prog{ opacity:.55; }
@keyframes jan-encher{ from{ transform:scaleX(0); } to{ transform:scaleX(1); } }

@media (max-width:860px){
  .jan{
    flex-direction:column; gap:2px;
    height:clamp(520px,80vh,660px);
    border-radius:14px;
  }
  .jan-p.is-open{ flex-grow:4.2; }
  .jan-corpo{ padding:16px 18px; }
  .jan-bt{ font-size:var(--t-base); }
  .jan-p.is-open .jan-bt{ font-size:var(--t-painel); }
  .jan-desc{ font-size:var(--t-corpo-lg); margin-top:8px; max-width:40ch; }
  .jan-cta{ font-size:var(--t-corpo); margin-top:14px; }
  /* o texto fica igual, mas o dedo passa a ter um alvo de 44px */
  .jan-cta::before{ content:""; position:absolute; inset:-13px -16px; }
  .jan-foto img{ filter:saturate(.3) brightness(var(--brilho-fechada,.5)); }
}

@media (prefers-reduced-motion:reduce){
  .jan-p, .jan-foto img, .jan-bt, .jan-painel, .jan-desc, .jan-cta{ transition-duration:.01ms; }
  .jan-p.is-open .jan-prog i{ animation:none; transform:scaleX(1); }
  .jan.entrou .jan-p{ animation-delay:0ms; }
}

/* ---------- sobre — a chapa de caracteristicas, sobre o video ---------- */
.sec-sobre{
  position:relative;
  background:var(--tinta);
  color:var(--nuvem);
  overflow:hidden;
}
/* 🚫 27-ago-2026 — AQUI ESTEVE UM DEGRADÊ DE ENTRADA E SAÍDA NESTA SECÇÃO, e foi VETADO por
   ele mal o viu ao vivo: «que merda é esta aqui? Mete isto como tava antes… parece um filme
   de terror.» E tinha razão.
   O pedido era legítimo («falta a transição entre uma secção normal e a secção dos números»),
   a execução é que não existe. Tentei três: branco a esbater para transparente (deu uma névoa
   cinzenta suja), rampa de cor curta (leu-se como bordo desfocado) e rampa de cor longa (deu
   uma vinheta pesada que transformou a secção numa faixa esborratada). O problema é de fundo:
   uma placa escura de página inteira, com vídeo por trás, entre duas secções claras, NÃO se
   dissolve — qualquer rampa entre quase-branco e quase-preto lê-se como borrão.
   ⚠️ NÃO REPETIR sem uma ideia diferente. Se a transição voltar à mesa, o caminho não é
   esbater a aresta: é a secção de baixo (ou de cima) trazer algo que entre por dentro do
   escuro, ou a placa deixar de ser de bordo a bordo. A aresta limpa é uma decisão, não um
   descuido — é o que dá a esta secção o peso de placa. */
.sobre-fundo{ position:absolute; inset:0; pointer-events:none; }
.sobre-video{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  opacity:0;
  transition:opacity 1.1s var(--ease);
}
.sobre-video.acesa{ opacity:1; }
/* o veu da o chao de leitura a esquerda (onde vive o texto) e fecha as arestas */
.sobre-veu{
  position:absolute; inset:0;
  background:
    linear-gradient(90deg,
      rgba(18,36,48,.90) 0%, rgba(18,36,48,.74) 26%,
      rgba(18,36,48,.32) 46%, rgba(18,36,48,.40) 57%,
      rgba(18,36,48,.42) 92%, rgba(18,36,48,.30) 100%),
    linear-gradient(180deg,
      rgba(18,36,48,.42) 0%, rgba(18,36,48,0) 22%,
      rgba(18,36,48,0) 76%, rgba(18,36,48,.48) 100%);
}
.sobre-grelha{
  position:relative;
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(320px,42%);
  gap:clamp(40px,6vw,104px);
  align-items:center;
}
.sobre-cta{ margin-top:clamp(22px,2.6vw,32px); font-size:var(--t-corpo); }
/* duas saídas na mesma linha: pedir orçamento (primária) e ir à página da equipa (secundária) */
.sobre-acoes{ display:flex; flex-wrap:wrap; align-items:baseline; gap:clamp(24px,3vw,38px); }
/* .80 e não menos: por cima de vídeo o contraste mede-se pelo pior fotograma — a este
   tamanho (14,5px) abaixo disto o mínimo de 4,5:1 deixa de estar garantido. */
.sobre-cta--sec{
  color:rgba(247,250,252,.80);
  text-decoration-color:rgba(247,250,252,.45);
  transition:color .2s ease, text-decoration-color .2s ease, text-decoration-thickness .2s ease;
}
@media (hover:hover) and (pointer:fine){
  .sobre-cta--sec:hover{ color:#fff; text-decoration-color:rgba(247,250,252,.85); }
}

/* 27-ago-2026: deixou de ser uma tabela de rotulo + valor e passou a FRASES, uma por
   filete — as mesmas afirmacoes da .sf-lista da /sobre. Os nomes das classes ficaram
   iguais de proposito: a entrada escalonada abaixo (.sec-sobre.revelada) ja estava
   afinada e nao ha razao para lhe mexer. */
.sobre-chapa{ margin:0; padding:0; list-style:none; }
.chapa-linha{
  display:flex; align-items:center; flex-wrap:wrap; gap:6px 12px;
  padding:clamp(14px,1.6vw,20px) 0;
  border-top:1px solid rgba(247,250,252,.17);
  font-size:clamp(17px,1.35vw,19.5px);
  font-weight:600; line-height:1.35;
  letter-spacing:-.012em;
  color:#fff;
  text-wrap:balance;
  /* frase branca por cima de video: o contraste mede-se pelo pior fotograma, e a sombra
     e que garante o chao — a mesma receita que ja segurava os rotulos pequenos. */
  text-shadow:0 1px 20px rgba(12,24,33,.9), 0 1px 3px rgba(12,24,33,.55);
  opacity:0; transform:translateY(10px);
  transition:opacity .7s var(--ease), transform .7s var(--ease);
}
.chapa-linha:last-child{ border-bottom:1px solid rgba(247,250,252,.17); }
.sec-sobre.revelada .chapa-linha{ opacity:1; transform:none; }
.sec-sobre.revelada .chapa-linha:nth-child(1){ transition-delay:.06s; }
.sec-sobre.revelada .chapa-linha:nth-child(2){ transition-delay:.18s; }
.sec-sobre.revelada .chapa-linha:nth-child(3){ transition-delay:.30s; }
.sec-sobre.revelada .chapa-linha:nth-child(4){ transition-delay:.42s; }
.chapa-estrelas{ display:flex; gap:3px; color:var(--quente); font-size:var(--t-selo); font-style:normal; }
.chapa-estrelas i{
  font-style:normal;
  opacity:0; transform:scale(.5);
  transition:opacity .35s var(--ease), transform .35s var(--salto);
}
.sec-sobre.revelada .chapa-estrelas i{ opacity:1; transform:none; }
.sec-sobre.revelada .chapa-estrelas i:nth-child(1){ transition-delay:.34s; }
.sec-sobre.revelada .chapa-estrelas i:nth-child(2){ transition-delay:.42s; }
.sec-sobre.revelada .chapa-estrelas i:nth-child(3){ transition-delay:.50s; }
.sec-sobre.revelada .chapa-estrelas i:nth-child(4){ transition-delay:.58s; }
.sec-sobre.revelada .chapa-estrelas i:nth-child(5){ transition-delay:.66s; }

.marca{
  display:inline-flex; align-items:center;
  color:rgba(247,250,252,.6);
  opacity:0; transform:translateY(8px);
  transition:opacity .6s var(--ease), transform .6s var(--ease), color .35s ease;
}
@media (hover:hover) and (pointer:fine){
  .marca:hover{ color:rgba(247,250,252,.95); }
}
.marca svg{ display:block; fill:currentColor; }
.marca-mitsubishi svg{ width:105px; height:32px; }
.marca-daikin svg{ width:100px; height:22px; }
/* .marca continua a servir a pagina sobre.html; na home ja nao ha marcas nesta seccao */

/* ⚠️ AQUI ESTAVAM 178 LINHAS DE CSS MORTO, tiradas a 26-ago-2026 depois de confirmar zero
   ocorrências em todo o HTML e JS do site:
     · «portfólio — duas linhas de obras (marquee infinito)»: .obras, .obras-linha, .obras-fita,
       .obra, .obra-cap e @keyframes obras-passa. Nunca chegaram a ser usados.
     · «MÉTODO · TRÊS CARTÕES FOTOGRÁFICOS»: .sec-metodo--cartoes e toda a família .mv-*.
       O bloco que vem a seguir diz-se a si próprio «Substitui os cartões de foto cheia com
       véu» — a versão substituída ficou cá dentro mais de um mês.
   Se alguma delas fizer falta outra vez, está no histórico. */

/* ---------- testemunhos ---------- */
.test-agregado{
  margin-top:18px;
  display:inline-flex; align-items:center; gap:9px;
  font-weight:600; font-size:var(--t-corpo-lg);
}
.g-logo{ font-weight:700; letter-spacing:var(--ls-corpo); }
.g-logo b:nth-child(1){ color:#4285F4; }
.g-logo b:nth-child(2){ color:#EA4335; }
.g-logo b:nth-child(3){ color:#FBBC05; }
.g-logo b:nth-child(4){ color:#4285F4; }
.g-logo b:nth-child(5){ color:#34A853; }
.g-logo b:nth-child(6){ color:#EA4335; }
.estrelas{
  color:var(--quente);
  letter-spacing:var(--ls-alta-lg);
  font-size:var(--t-corpo);
}
.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
}
/* o pódio — a carta do meio à frente, as outras recolhidas atrás */
.podio{
  position:relative;
  height:clamp(320px,30vw,352px);
  margin-top:clamp(40px,5vw,64px);
}
.t-carta{
  position:absolute; top:0; left:50%;
  width:min(470px,46%);
  margin:0;
  background:#fff;
  border:1px solid var(--hairline);
  border-radius:20px;
  padding:28px 32px 26px;
  /* antes da secção entrar: baralho junto ao centro */
  transform:translateX(-50%) translateY(22px) scale(.94);
  opacity:0;
  transition:transform .65s var(--ease), opacity .5s ease, box-shadow .5s ease;
}
/* as cartas abrem em leque quando a secção entra no ecrã */
.podio.revelado .pos-centro{
  transform:translateX(-50%);
  opacity:1;
  z-index:3;
  box-shadow:0 30px 80px rgba(15,30,50,.16);
}
.podio.revelado .pos-esq,
.podio.revelado .pos-dir{
  opacity:.5;
  z-index:1;
  cursor:pointer;
}
.podio.revelado .pos-esq{ transform:translateX(calc(-50% - 76%)) translateY(36px) scale(.86) rotate(-2.2deg); }
.podio.revelado .pos-dir{ transform:translateX(calc(-50% + 76%)) translateY(36px) scale(.86) rotate(2.2deg); }
.podio.revelado .pos-esq:hover, .podio.revelado .pos-esq:focus-visible{
  opacity:.85;
  transform:translateX(calc(-50% - 76%)) translateY(27px) scale(.875) rotate(-1.3deg);
}
.podio.revelado .pos-dir:hover, .podio.revelado .pos-dir:focus-visible{
  opacity:.85;
  transform:translateX(calc(-50% + 76%)) translateY(27px) scale(.875) rotate(1.3deg);
}
.t-estrelas{
  display:flex; gap:3px;
  color:var(--quente);
  font-size:var(--t-corpo);
  margin-bottom:14px;
}
.t-carta blockquote{
  margin:0;
  font-size:var(--t-lede);
  line-height:1.6;
}
.t-carta figcaption{
  margin-top:16px;
  position:relative;
  padding-top:12px;
  font-weight:600; font-size:var(--t-corpo);
}
.t-carta figcaption span{ font-weight:400; font-size:var(--t-legenda); color:var(--tinta-60); }
.t-carta figcaption::before{
  content:'';
  position:absolute; top:0; left:0;
  width:30px; height:2px;
  background:var(--quente);
  border-radius:2px;
}
/* gestos de chegada ao centro: estrelas pousam uma a uma, o traço assina */
.podio.revelado .chegou .t-estrelas b{ animation:estrela-pousa .4s var(--salto) both; }
.podio.revelado .chegou .t-estrelas b:nth-child(1){ animation-delay:.14s; }
.podio.revelado .chegou .t-estrelas b:nth-child(2){ animation-delay:.22s; }
.podio.revelado .chegou .t-estrelas b:nth-child(3){ animation-delay:.30s; }
.podio.revelado .chegou .t-estrelas b:nth-child(4){ animation-delay:.38s; }
.podio.revelado .chegou .t-estrelas b:nth-child(5){ animation-delay:.46s; }
@keyframes estrela-pousa{
  from{ opacity:0; transform:translateY(-8px) scale(.4); }
  to{ opacity:1; transform:none; }
}
.podio.revelado .chegou figcaption::before{ animation:traco-assina .45s .55s var(--ease) both; }
@keyframes traco-assina{
  from{ width:0; }
  to{ width:30px; }
}
/* navegação do carrossel de testemunhos — só existe no telemóvel */
.podio-nav{ display:none; }

/* ---------- fecho no céu ---------- */
.sec-final{
  position:relative; z-index:1;
  min-height:78vh; min-height:78svh;
  display:flex; align-items:center; justify-content:center;
  text-align:center;
  color:#fff;
  padding:var(--respiro) 0;
}
.sec-final::before{
  content:'';
  position:absolute; inset:0;
  pointer-events:none;
  background:radial-gradient(ellipse 70% 55% at 50% 52%, rgba(16,38,68,.32), rgba(16,38,68,.10) 62%, rgba(16,38,68,0) 78%);
}
/* o balcão — a conversa de conversão vive já na página */
.fim-wrap{
  position:relative;
  width:min(92%,1040px);
  display:flex; flex-direction:column; align-items:center;
  gap:clamp(26px,3.5vw,38px);
}
.fim-copy h2{
  font-size:var(--t-titulo);
  font-weight:600;
  line-height:1.1;
  letter-spacing:var(--ls-apertado);
  text-shadow:var(--sombra-texto);
}
.fim-copy p{
  margin-top:10px;
  font-size:var(--t-lede);
  /* A LEDE DO FECHO, nas três páginas que a têm. Estava a 2,5:1 sobre o frame mais claro
     das nuvens, contra os 4,5 da fasquia. Duas causas somadas: o `opacity:.94` dilui o
     branco, e a --sombra-texto tem 26 px de desfoque — segura um H1 grosso, mas nesta
     lede espalha-se e não faz aresta nenhuma.
     A cura é a mesma do «Desde 2011» e das citações do hero: núcleo opaco de 2 px colado
     à letra. Não é véu por baixo do texto, que é a regra da casa para esta fotografia. */
  text-shadow:
    0 1px 2px rgba(8,26,48,.92),
    0 0 7px rgba(8,26,48,.78),
    0 1px 22px rgba(8,26,48,.5);
}
/* O título está centrado na página (eixo 720 num ecrã de 1440) e o cartão do Clima estava a
   675: com `justify-content:center` num flex de dois filhos, o que fica centrado é o PAR, e os
   dois botões de Ligar/WhatsApp empurravam o cartão 45px para a esquerda. Como o cartão é uma
   massa branca de 560px e os botões são dois círculos leves, o olho lê o cartão como o objeto
   e vê-o fora do eixo do título. Grelha de três colunas com laterais iguais: o cartão fica no
   eixo da página, os botões vivem na coluna da direita. */
.fim-palco{
  display:grid;
  grid-template-columns:1fr min(560px,100%) 1fr;
  align-items:center;
  gap:clamp(20px,3vw,34px);
  width:100%;
}
.fim-palco > .fim-chat{ grid-column:2; }
.fim-palco > .fim-contactos{ grid-column:3; justify-self:start; }
.fim-chat{
  width:min(560px,100%);
  background:rgba(247,250,252,.97);
  color:var(--tinta);
  border-radius:22px;
  box-shadow:0 30px 90px rgba(10,25,45,.38);
  padding:18px 24px 20px;
  display:flex; flex-direction:column;
  text-align:left;
}
.fim-cab{
  display:flex; align-items:center; gap:9px;
  font-size:var(--t-rotulo); font-weight:600; letter-spacing:var(--ls-corpo);
  color:var(--tinta-60);
  padding-bottom:11px;
  border-bottom:1px solid var(--hairline);
}
/* ---------- a marca do Clima ----------
   Aqui esteve um ponto a pulsar («ao vivo»), com o nome e o papel na mesma
   linha, no mesmo tamanho, separados por um ponto do meio. Era exatamente o
   desenho que qualquer pessoa reconhece como feito por IA: o pontinho a
   respirar é o cliché, e «Clima · atendente virtual» a um só corpo não é um
   nome, é uma etiqueta. Agora há uma marca e uma hierarquia — o nome tem
   tamanho de nome, e o papel vive por baixo, mais pequeno e mais claro.
   A marca é o ar a sair de uma grelha, não uma bolha de conversa nem um
   brilhozinho: três traços de comprimentos diferentes, os de cima e de baixo
   a enrolar. Diz do que isto trata sem dizer «IA». */
.fim-marca{
  flex:0 0 auto; width:30px; height:30px; border-radius:9px;
  display:grid; place-items:center;
  color:var(--quente);
  background:rgba(217,95,51,.10);
  border:1px solid rgba(217,95,51,.18);
}
.fim-marca svg{ width:19px; height:19px; }
.fim-nome{
  display:flex; flex-direction:column; gap:1px;
  font-size:var(--t-destaque); font-weight:600; letter-spacing:-.012em;
  line-height:1.15; color:var(--tinta);
}
.fim-papel{
  font-size:var(--t-legenda); font-weight:500; letter-spacing:0;
  color:var(--tinta-60);
}
/* aqui a conversa não vive numa janela mas dentro de um cartão da página: em vez de reservar
   sempre a altura máxima (e abrir um vazio antes de haver conversa), o cartão começa à
   medida da saudação e cresce até ao limite, passando a rolar a partir daí */
.fim-chat .chat-log{ flex:0 0 auto; height:auto; max-height:clamp(230px,32vh,300px); padding:12px 2px 6px; }
.fim-chat .msg{ color:var(--tinta); }
.fim-chat .pensa span{ background:rgba(18,36,48,.5); }
.fim-chat .chip{
  background:#fff;
  border:1px solid var(--hairline);
  color:var(--tinta);
}
@media (hover:hover) and (pointer:fine){
  .fim-chat .chip:hover{ background:var(--quente); border-color:var(--quente); }
}
.fim-chat .chat-input{ color:var(--tinta); }
/* 2,41:1 a .4 — chumbava o AA. .58 dá 4,52:1 sobre o mesmo fundo. */
.fim-chat .chat-input::placeholder{ color:rgba(18,36,48,.58); }
.fim-chat .chat-send{ border:1px solid var(--hairline); background:#fff; }
.fim-chat .chat-send-ponto{ background:var(--azul); }
.fim-chat .msg a{ color:var(--tinta); text-underline-offset:3px; }
/* contactos diretos — pequenos, ao lado */
.fim-contactos{
  display:flex; flex-direction:column;
  gap:16px;
}
.fim-cont{
  display:flex; flex-direction:column; align-items:center; gap:6px;
  color:#fff; text-decoration:none;
  font-size:var(--t-selo); font-weight:500; letter-spacing:var(--ls-solto);
  opacity:.92;
  text-shadow:0 1px 10px rgba(15,35,65,.5);
  transition:opacity .25s ease;
}
@media (hover:hover) and (pointer:fine){
  .fim-cont:hover{ opacity:1; }
}
.fim-ico{
  width:46px; height:46px; border-radius:50%;
  border:1px solid rgba(255,255,255,.55);
  background:rgba(16,38,68,.22);
  display:flex; align-items:center; justify-content:center;
  transition:transform .25s var(--ease), background .25s ease, border-color .25s ease;
}
.fim-cont svg{ width:20px; height:20px; }
@media (hover:hover) and (pointer:fine){
  .fim-cont:hover .fim-ico{
    transform:translateY(-3px);
    background:rgba(247,250,252,.18);
    border-color:#fff;
  }
}
.fim-cont:active .fim-ico{ transform:scale(.94); transition-duration:.15s; }

/* ---------- rodapé ---------- */
.rodape{
  position:relative; z-index:2;
  background:var(--tinta);
  color:var(--nuvem);
  padding:56px 0 0;
  overflow:hidden;         /* o nome ao fundo encosta às duas margens */
}
.rodape-inner{
  width:min(92%,1180px); margin:0 auto;
  display:flex; justify-content:space-between; align-items:flex-start;
  gap:40px; flex-wrap:wrap;
}
.rodape-marca{ display:flex; gap:16px; align-items:center; }
.rodape-marca .marca-rm-rodape{ width:auto; height:38px; display:block; color:var(--nuvem); }
.rodape-marca p{ font-weight:600; max-width:24ch; line-height:1.45; }
.rodape-dados{
  text-align:right;
  font-size:var(--t-corpo); line-height:1.75;
  color:rgba(247,250,252,.72);
}
.rodape-dados a{ color:inherit; text-underline-offset:4px; }
.rodape-dados a:hover{ color:var(--nuvem); }

/* ── Saltar para o conteúdo ───────────────────────────────────────────────────
   Primeiro alvo do Tab. Fica fora do ecrã até receber foco; aí desce e pousa
   abaixo do topo, com contraste próprio — sobre o céu do hero um link claro
   desaparecia. Conta como SEO, não é só bondade: é sinal de qualidade lido. */
.skip{
  position:fixed; top:0; left:12px; z-index:120;
  transform:translateY(-140%);
  padding:11px 18px;
  background:var(--tinta); color:var(--nuvem);
  font-family:inherit;
  font-size:var(--t-corpo); font-weight:600; line-height:1;
  border-radius:0 0 10px 10px;
  text-decoration:none;
  transition:transform .18s var(--ease);
}
.skip:focus-visible{ transform:translateY(0); outline:2px solid var(--quente); outline-offset:2px; }
@media (prefers-reduced-motion:reduce){ .skip{ transition:none; } }

/* ── Mapa do site ─────────────────────────────────────────────────────────────
   O rodapé tinha cinco links e nenhum era de navegação. As fichas de serviço e
   os guias só se alcançavam por dentro do texto — o guia da água tinha DUAS
   páginas a ligar-lhe, contra dezasseis do /sobre. Isto dá a cada página uma
   entrada em todas as páginas, que é como o Googlebot e os crawlers de LLM
   descobrem o que existe e inferem o que importa.
   Fica em linha própria, e não como coluna dos dados: cinco colunas na mesma
   fila espremiam a marca e liam-se como directório, não como rodapé. */
.rodape-mapa{
  width:min(92%,1180px); margin:44px auto 0;
  padding-top:34px;
  border-top:1px solid rgba(247,250,252,.11);
  display:grid; gap:30px 40px;
  /* O número de grupos MUDA à medida que o site cresce, e um número fixo aqui parte-se
     sempre que ele muda: com três colunas o quarto grupo caía sozinho para uma segunda
     linha; com quatro fixas aconteceu o mesmo ao quinto («Para o seu negócio», 28-ago-2026,
     quando as tipologias saíram da coluna Serviços). O `auto-fit` conta os grupos sozinho
     e enche a linha — 160px é o mínimo em que os rótulos ainda quebram bem. */
  grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
}
@media (max-width:1060px){
  .rodape-mapa{ grid-template-columns:repeat(2,minmax(0,1fr)); gap:28px 32px; }
}
/* As páginas-documento (guias, privacidade) não têm o bloco de morada e horário, por isso o
   mapa é o primeiro do rodapé. Aí a linha de cima separava o mapa de NADA, com uma faixa de
   ~100px de vazio por cima dela — uma régua a dividir escuro de escuro. */
.rodape > .rodape-mapa:first-child{ margin-top:0; padding-top:0; border-top:0; }
.rodape-mapa .rodape-col-tit{
  font-family:inherit;
  font-size:var(--t-selo); font-weight:700; letter-spacing:var(--ls-alta); text-transform:uppercase;
  color:rgba(247,250,252,.42);
  margin:0 0 12px;
}
.rodape-mapa ul{ list-style:none; margin:0; padding:0; }
.rodape-mapa li + li{ margin-top:8px; }
.rodape-mapa a{
  color:rgba(247,250,252,.78);        /* 8,1:1 sobre a tinta */
  font-size:var(--t-corpo); line-height:1.5;
  text-decoration:none;
  text-underline-offset:4px;
}
.rodape-mapa a:hover,
.rodape-mapa a:focus-visible{ color:var(--nuvem); text-decoration:underline; }
.rodape-mapa a[aria-current="page"]{ color:var(--nuvem); font-weight:600; }
@media (max-width:720px){
  /* Duas colunas, não uma: os guias têm cinco entradas e em coluna única o
     rodapé passava a ser a parte mais alta da página no telemóvel. */
  .rodape-mapa{ grid-template-columns:repeat(2,minmax(0,1fr)); gap:26px 22px; }
  .rodape-mapa a{ font-size:var(--t-corpo); }
  /* Com quatro grupos, duas colunas fecham em 2×2 e ninguém fica órfão. A regra
     anterior punha o último à largura toda — fazia sentido com três grupos, com
     quatro deixava o rodapé desalinhado. Os guias, que são a coluna de títulos mais
     longos, ficam por baixo dos serviços, que também partem em duas linhas. */
}

.rodape-legal{
  width:min(92%,1180px); margin:44px auto 0;
  font-size:var(--t-legenda);
  color:rgba(247,250,252,.42);
  /* A bola do Clima ocupa 84px a contar da direita (right:24 + 60 de disco).
     Quando a margem livre do contentor e menor do que isso, a ponta direita
     desta linha — onde vive o selo — entrava por baixo do disco. Reservamos
     so o que falta: acima de ~1400px a conta da zero e o selo mantem-se
     alinhado com a coluna dos dados, como deve. */
  padding-right:max(0px, calc(104px - (100% - min(92%,1180px)) / 2));
}

/* ---------- o nome ao fundo — a marca a fechar a página ----------
   O logótipo à escala máxima, encostado às duas margens, com o CÉU do topo do
   site por dentro das letras: o site abre no céu e fecha no céu.

   · É o mesmo desenho da navbar. As letras são um RECORTE (mask-image) sobre o
     vídeo — não há tipografia nova, não há imagem do nome, não há peso extra
     de fonte. Só a máscara (7,5 KB) e um vídeo de 480p.
   · Decorativo: o nome já está em texto ali ao lado, na razão social. Vai com
     aria-hidden e fica FORA da ordem de leitura.
   · Contraste MEDIDO com o vídeo a tocar (59 fotogramas do loop), dentro das
     letras e contra a tinta: mediana 9,3:1, percentil 5 do pior fotograma
     5,6:1, píxel mais escuro 3,85:1. No telemóvel 8,7 / 4,0 / 3,12. Acima do
     mínimo de 3:1 para texto grande sem precisar de chapa por baixo — mas é
     por isto que a fonte do recorte não se troca sem voltar a medir.       */
.marca-fim{
  margin-top:38px;
  line-height:0;            /* sem esta linha sobra o descenso da caixa de texto */
  /* É desenho, não é alvo. Sem isto o <video> fica por cima do canto onde a bola
     do Clima vive e passa a ser ele a responder ao elementFromPoint — nas páginas
     curtas, onde a bola ainda está acesa sobre o rodapé, isso comia-lhe o clique. */
  pointer-events:none;
}
.marca-fim .mf-ceu{
  display:block; width:100%;
  aspect-ratio:5165 / 945;  /* a caixa justa à tinta do desenho */
  /* O CHÃO, a custo zero: sem JS o <video> não tem src nem poster, e sem isto o
     nome ficaria um vazio recortado na tinta. As três paradas são a MÉDIA
     medida do próprio poster por faixas (topo #4ea0d1, meio #b3bed0,
     fundo #b3bdcc) — é o mesmo céu, reduzido a três cores. */
  background:linear-gradient(180deg,#4ea0d1 0%,#b3bed0 46%,#b3bdcc 100%);
  -webkit-mask:url(/assets/marca-nome.svg) 0 0/100% 100% no-repeat;
          mask:url(/assets/marca-nome.svg) 0 0/100% 100% no-repeat;
}
.marca-fim .mf-ceu > *{ display:block; width:100%; height:100%; object-fit:cover; }

/* Telemóvel: o nome parte-se em dois andares.
   Numa linha só, a 375px fica a 67px de altura — lê-se, mas deixa de ser
   monumento; partido, cada palavra chega a ~130px. É a MESMA máscara noutro
   desenho (ver scripts/marca-mascara.mjs), para continuar a ser um elemento e
   UM vídeo: duas palavras em dois elementos seriam dois descodificadores a
   correr o mesmo ficheiro num telemóvel. */
@media (max-width:700px){
  .marca-fim{ margin-top:30px; }
  .marca-fim .mf-ceu{
    /* tem de bater CERTO com o viewBox do marca-nome-2l.svg: a máscara vai com
       mask-size:100% 100%, por isso um rácio errado estica as letras */
    aspect-ratio:2841 / 1965;
    -webkit-mask-image:url(/assets/marca-nome-2l.svg);
            mask-image:url(/assets/marca-nome-2l.svg);
  }
}

/* ============================================================
   CHAT — kit partilhado
   ============================================================ */
.chat-log{
  flex:1; min-height:0;
  overflow-y:auto;
  overscroll-behavior:contain;
  display:flex; flex-direction:column; gap:12px;
  padding:6px 2px;
  scrollbar-width:none;
  -webkit-mask:linear-gradient(180deg, transparent, #000 14px, #000 calc(100% - 14px), transparent);
  mask:linear-gradient(180deg, transparent, #000 14px, #000 calc(100% - 14px), transparent);
}
.chat-log::-webkit-scrollbar{ display:none; }
/* A conversa assenta no fundo, como numa aplicação de mensagens: sem isto a saudação fica
   presa ao topo e abre-se um poço vazio até aos chips. Quando a conversa cresce e passa a
   altura da caixa, o `auto` colapsa sozinho e o scroll volta ao comportamento normal. */
.chat-log > *:first-child{ margin-top:auto; }
.msg{
  font-size:var(--t-corpo); line-height:1.55;
  animation:msg-in .4s var(--ease) both;
  max-width:94%;
}
/* O bot separa a resposta do convite por uma linha em branco, e o montaTexto() faz de cada
   parágrafo um bloco. A margem aqui é 8px e o intervalo entre mensagens é 12px (.chat-log):
   os pedaços de uma mesma resposta TÊM de ficar mais juntos do que duas mensagens, senão a
   segunda metade lê-se como uma segunda mensagem do bot.
   `pre-line` faria isto sozinho em CSS — e ao contrário: a linha em branco vale uma altura de
   linha inteira, ~22px, quase o dobro do intervalo entre mensagens. */
.msg-p{ display:block; }
.msg-p + .msg-p{ margin-top:8px; }
/* Linhas de uma enumeração dentro do MESMO parágrafo. O intervalo é pequeno de propósito:
   a lista tem de ler-se como um bloco só, senão cada item parece um parágrafo novo e
   desfaz-se o efeito de varrer com o olho. O recuo alinha o texto que passa para a linha
   seguinte por baixo do texto, e não por baixo do ponto. */
.msg-l{ display:block; }
.msg-l + .msg-l{ margin-top:3px; }
/* Só os ITENS levam recuo pendente — a linha de fecho que vem depois da lista não é item,
   e com o recuo a sua segunda linha alinhava como se continuasse um ponto. */
.msg-li{ padding-left:14px; text-indent:-14px; }
@keyframes msg-in{
  from{ opacity:0; transform:translateY(7px); }
  to{ opacity:1; transform:translateY(0); }
}
.msg-user{
  align-self:flex-end;
  background:var(--quente);
  color:var(--tinta);
  font-weight:500;
  padding:8px 14px;
  border-radius:14px 14px 4px 14px;
  max-width:84%;
}
.caret{
  display:inline-block;
  width:2px; height:1em;
  margin-left:1px;
  vertical-align:-.14em;
  background:currentColor;
  animation:caret .9s steps(1) infinite;
}
@keyframes caret{
  0%,49%{ opacity:.85; }
  50%,100%{ opacity:0; }
}
.pensa{
  display:inline-flex; gap:5px;
  padding:4px 0;
  animation:msg-in .3s var(--ease) both;
}
.pensa span{
  width:5px; height:5px; border-radius:50%;
  background:currentColor; opacity:.45;
  animation:blink 1.3s ease-in-out infinite;
}
.pensa span:nth-child(2){ animation-delay:.18s; }
.pensa span:nth-child(3){ animation-delay:.36s; }
@keyframes blink{
  0%,100%{ opacity:.3; transform:translateY(0); }
  40%{ opacity:1; transform:translateY(-2px); }
}
.chat-chips{
  display:flex; flex-wrap:wrap; gap:10px;
  padding:10px 0 2px;
}
.chip{
  font-family:inherit;
  font-size:var(--t-rotulo); font-weight:500;
  padding:.58em 1.15em;
  border-radius:999px;
  cursor:pointer;
  transition:background .25s ease, border-color .25s ease, color .25s ease, transform .25s var(--ease);
  animation:msg-in .4s var(--ease) both;
}
@media (hover:hover) and (pointer:fine){
  .chip:hover{ transform:translateY(-1px); }
}
.chip:active{ transform:scale(.96); transition-duration:.12s; }
.chat-inputrow{
  display:flex; align-items:center; gap:10px;
  border-top:1px solid var(--hairline);
  padding-top:12px; margin-top:8px;
}
.chat-input{
  flex:1; min-width:0;
  background:none; border:none; outline:none;
  font-family:inherit;
  font-size:var(--t-corpo);
}
.chat-input:focus-visible{ outline:none; }
.chat-inputrow:focus-within{ border-top-color:rgba(31,120,208,.55); }
.chat-send{
  width:34px; height:34px;
  border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  cursor:pointer;
  flex:0 0 auto;
  background:none;
  transition:transform .16s var(--ease);
}
.chat-send:active{ transform:scale(.9); }
.chat-send-ponto{
  width:10px; height:10px; border-radius:50%;
  transition:transform .25s var(--ease);
}
@media (hover:hover) and (pointer:fine){
  .chat-send:hover .chat-send-ponto{ transform:translateY(-3px); }
}
.fechar{
  width:32px; height:32px;
  display:flex; align-items:center; justify-content:center;
  background:none; border:none; cursor:pointer;
  border-radius:50%;
  transition:color .25s ease, background .25s ease, transform .16s var(--ease);
}
.fechar:active{ transform:scale(.88); }

/* ---------- gaveta de conversão (desce do topo) ---------- */
.gaveta-scrim{
  position:fixed; inset:0; z-index:69;
  background:rgba(10,22,35,.28);
}
.gaveta{
  position:fixed; top:0; left:50%; z-index:70;
  width:min(720px,100%);
  height:min(560px,88dvh);
  /* --desvio: quanto a gaveta se encosta à esquerda para abrir lugar ao Clima ao lado.
     Zero enquanto está sozinha — ver «Formulário + Clima ao mesmo tempo», mais abaixo. */
  --desvio:0px;
  transform:translate(calc(-50% - var(--desvio)),-108%);
  background:var(--nuvem);
  color:var(--tinta);
  border-radius:0 0 26px 26px;
  box-shadow:none;
  display:flex; flex-direction:column;
  transition:transform .38s var(--ease), box-shadow .38s ease, width .38s var(--ease); /* fechar: mais rápido */
}
.gaveta.aberta{
  transform:translate(calc(-50% - var(--desvio)),0);
  box-shadow:0 40px 120px rgba(10,25,45,.35);
  transition:transform .55s var(--ease-gaveta), box-shadow .55s ease, width .45s var(--ease-gaveta); /* abrir: curva de sheet */
}
.gaveta-ceu{
  position:relative;
  display:flex; justify-content:space-between; align-items:flex-start;
  padding:24px 30px 20px;
  color:#fff;
  background:url('../assets/ceu-A-poster-480.jpg') center 32%/cover;
}
/* A gaveta nasce fechada, mas o fundo dela descarrega na mesma — um `background`
   nao sabe que o elemento esta fora do ecra. No PC sai de graca (o hero ja trouxe
   este ficheiro). No telemovel o hero traz o ceu VERTICAL, e esta faixa de 400 px
   estava a puxar 120 KB so para si. */
@media (max-width:860px){
  .gaveta-ceu{ background-image:url('../assets/ceu-A-poster-480.jpg'); }
}
.gaveta-ceu::before{
  content:'';
  position:absolute; inset:0;
  background:linear-gradient(180deg, rgba(16,38,68,.38), rgba(16,38,68,.14));
}
.gaveta-ceu-txt{ position:relative; }
.gaveta-ceu h2{ font-size:var(--t-painel); font-weight:600; letter-spacing:var(--ls-apertado); }
.gaveta-ceu p{ margin-top:3px; font-size:var(--t-rotulo); opacity:.92; }
.gaveta-x{ position:relative; color:#fff; }
.gaveta-x:hover{ background:rgba(255,255,255,.14); }
.gaveta-corpo{
  flex:1; min-height:0;
  display:flex; flex-direction:column;
  padding:16px 30px 22px;
}
.gaveta .chat-input{ color:var(--tinta); }
/* era .4 = 2,41:1 sobre a --nuvem da gaveta. .58 dá 4,52:1 e passa o AA. */
.gaveta .chat-input::placeholder{ color:rgba(18,36,48,.58); }
.gaveta .msg{ color:var(--tinta); }
.gaveta .pensa span{ background:rgba(18,36,48,.5); }
.gaveta .chip{
  background:#fff;
  border:1px solid var(--hairline);
  color:var(--tinta);
}
@media (hover:hover) and (pointer:fine){
  .gaveta .chip:hover{ background:var(--quente); border-color:var(--quente); }
}
.gaveta .chat-send{ border:1px solid var(--hairline); background:#fff; }
.gaveta .chat-send-ponto{ background:var(--azul); }
.gaveta-orla{ display:none; }

/* ── Formulário de orçamento (a alternativa ao chat na gaveta) ─────────────────
   Herda a linguagem que já lá estava: as opções são as pastilhas do chat com
   caixa de toque a sério, e o azul só marca o que está escolhido. Um OU outro,
   nunca os dois — trocar com scripts/form-orcamento.mjs [--reverter]. */
/* A gaveta tem altura fixa (560px / 88dvh) e o corpo não rola: o chat safava-se porque o
   .chat-log tinha scroll próprio. Aqui o scroll vive DENTRO do ecrã visível, e o pé com os
   botões fica sempre no sítio — num formulário, ter de rolar para encontrar o «Continuar»
   é o defeito que faz a pessoa desistir. */
/* O chat cabia em 560px porque mostra uma bolha de cada vez. Um formulário mostra a escolha
   toda ao mesmo tempo — a 560px o 1.º ecrã nascia já com scroll e a 3.ª opção aparecia
   cortada ao meio, que se lê como página mal feita antes de se ler como lista. */
.gaveta:has(.oc){ height:min(690px,90dvh); }
/* Enviado o pedido, o formulário sai e sobra uma resposta de cinco linhas: manter os 690px
   deixava 350px de cartão vazio por baixo da boa notícia. Encolhe ao que tem. */
.gaveta:has(.oc[hidden]){ height:auto; max-height:90dvh; }
.gaveta-corpo:has(.oc){ overflow:hidden; }
.oc{ display:flex; flex-direction:column; flex:1; min-height:0; }
/* `display:flex` numa classe ganha ao `display:none` que o browser dá ao [hidden]. Sem esta
   linha, o `form.hidden = true` do envio não escondia nada e o cliente ficava a ver o
   formulário POR BAIXO do resultado. Regra: sempre que se declara display numa classe que
   também pode levar [hidden], declara-se o par. */
.oc[hidden]{ display:none; }
/* 🔴 30-ago-2026, visto nos OLHOS. A gaveta subiu para 690px na esperança de que todos os
   ecrãs coubessem, e o corpo ficou em `overflow:hidden` a assumir que sim. Deixou de ser
   verdade: o ecrã do espaço com «Mais do que uma» aberto passa a altura, e o campo «Quais?»
   ficava cortado a meio — invisível e inalcançável, com o rodapé por cima dele. É o mesmo
   defeito do painel de apoio («nem sequer dá para dar scroll»), pela mesma causa: um filho
   que cresce dentro de um pai que corta.
   Quem rola é o ECRÃ, não o corpo — se rolasse o corpo, o «Continuar» fugia com o conteúdo.
   O cabeçalho dos passos e os botões são `flex:none` e ficam onde estão. */
.oc-ecra:not([hidden]){
  flex:1 1 auto; min-height:0; overflow-y:auto;
  /* Tentei aqui um esbatimento no fundo para o corte se ler como «há mais para baixo».
     Saiu pior nos OLHOS: com a folga a mais, o ecrã nascia já rolado e era o TÍTULO que
     aparecia cortado ao meio no topo. Quem resolve isto é o pinta(), que repõe o scroll no
     princípio a cada troca de ecrã — não mais CSS. */
  padding-bottom:2px;
}
.oc-passos{
  flex:none;
  display:flex; align-items:center; gap:7px;
  padding-bottom:14px; margin-bottom:16px;
  border-bottom:1px solid var(--hairline);
}
.oc-conta{
  font-size:var(--t-selo); font-weight:600; letter-spacing:var(--ls-solto); text-transform:uppercase;
  color:rgba(18,36,48,.5); margin-right:auto;
}
.oc-pt{ width:22px; height:3px; border-radius:2px; background:var(--hairline); transition:background .3s var(--ease); }
.oc-pt.feito{ background:var(--azul); }

/* o campo-mel tem de ser inalcançável, não invisível: display:none faz alguns
   robôs desconfiarem, e um `hidden` normal ainda apanha o Tab */
.oc-mel{ position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden; }

/* só um ecrã está visível de cada vez, por isso é ele que leva o scroll */
.oc-ecra{ border:0; padding:0 2px 0 0; margin:0; min-width:0; flex:1; min-height:0; overflow-y:auto; }
.oc-tit{ font-size:var(--t-painel); font-weight:600; letter-spacing:var(--ls-apertado); color:var(--tinta); padding:0; }
.oc-tit:focus-visible{ outline:2px solid var(--azul); outline-offset:4px; border-radius:4px; }
.oc-lede{ font-size:var(--t-corpo); line-height:1.5; color:rgba(18,36,48,.62); margin:6px 0 0; }
.oc-grupo{ margin-top:18px; }
.oc-rot{
  display:block; margin-bottom:9px;
  font-size:var(--t-rotulo); font-weight:600; color:var(--tinta);
}
.oc-aj{ display:block; margin-top:6px; font-size:var(--t-legenda); color:rgba(18,36,48,.5); }

.oc-ops{ display:grid; gap:8px; }
.oc-ops--duas{ grid-template-columns:1fr 1fr; }
.oc-ops--tres{ grid-template-columns:repeat(3,1fr); }
.oc-ops--curtas{ grid-template-columns:repeat(auto-fit,minmax(104px,1fr)); }
/* «Mais do que uma» não é mais uma divisão da lista: é a opção que troca o resto do ecrã.
   Entre caixas de uma linha ficava órfã e três vezes mais alta — à largura toda lê-se como
   o que é, uma escolha de outra natureza, e a descrição cabe ao lado do nome. */
.oc-ops--curtas .oc-op:last-child{ grid-column:1 / -1; display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; }
.oc-ops--curtas .oc-op:last-child .oc-op-d{ margin-top:0; }
.oc-op{
  display:block; position:relative;
  padding:11px 13px;
  background:#fff; border:1px solid var(--hairline); border-radius:12px;
  cursor:pointer;
  transition:border-color .2s ease, background .2s ease, box-shadow .2s ease;
}
.oc-op input{ position:absolute; opacity:0; width:0; height:0; }
.oc-op-n{ display:block; font-size:var(--t-corpo); font-weight:500; color:var(--tinta); line-height:1.3; }
.oc-op-d{ display:block; margin-top:3px; font-size:var(--t-legenda); line-height:1.4; color:rgba(18,36,48,.55); }
@media (hover:hover) and (pointer:fine){
  .oc-op:hover{ border-color:rgba(31,120,208,.45); }
}
.oc-op:has(input:checked){
  border-color:var(--azul);
  background:rgba(31,120,208,.06);
  box-shadow:inset 0 0 0 1px var(--azul);
}
/* o foco do teclado tem de se ver mesmo quando o rádio está escondido */
.oc-op:has(input:focus-visible){ outline:2px solid var(--azul); outline-offset:2px; }

/* AS CAIXAS DOS COMPLEMENTOS — 30-ago-2026.
   🔴 Visto nos OLHOS: o cartão de opção nasceu para RÁDIOS, onde só há uma escolha e o cartão
   aceso já a comunica. Nos complementos pode marcar-se as duas, ou nenhuma — e sem um quadrado
   visível o ecrã lia-se exatamente como o anterior, «escolhe um destes». O quadrado é a única
   coisa na página que diz «podes marcar mais do que um, ou seguir sem marcar nada». */
.oc-op:has(input[type="checkbox"]){ padding-left:42px; }
.oc-op:has(input[type="checkbox"])::before{
  content:""; position:absolute; left:13px; top:13px;
  width:18px; height:18px; border-radius:5px;
  border:1.5px solid rgba(18,36,48,.32); background:#fff;
  transition:border-color .2s ease, background .2s ease;
}
.oc-op:has(input[type="checkbox"]:checked)::before{ border-color:var(--azul); background:var(--azul); }
/* o visto desenha-se com duas bordas de um retângulo virado — sem SVG e sem fonte de ícones */
.oc-op:has(input[type="checkbox"]:checked)::after{
  content:""; position:absolute; left:19px; top:16px;
  width:5px; height:9px; border:solid #fff; border-width:0 2px 2px 0;
  transform:rotate(45deg);
}

.oc-campo{
  width:100%; box-sizing:border-box;
  padding:11px 13px;
  font-family:inherit; font-size:var(--t-corpo-lg); color:var(--tinta);
  background:#fff; border:1px solid var(--hairline); border-radius:12px;
  outline:none;
  transition:border-color .2s ease;
}
.oc-campo--curto{ max-width:150px; }
.oc-campo::placeholder{ color:rgba(18,36,48,.38); }
.oc-campo:focus-visible{ border-color:var(--azul); box-shadow:inset 0 0 0 1px var(--azul); }
textarea.oc-campo{ resize:vertical; min-height:64px; line-height:1.5; }

.oc-erro{ display:block; margin-top:7px; font-size:var(--t-rotulo); color:var(--quente); font-weight:500; }
.oc-erro[hidden]{ display:none; }   /* o mesmo par: sem isto sobravam 7px de margem fantasma */
.tem-erro .oc-op, .tem-erro .oc-campo{ border-color:var(--quente); }

.oc-pe{
  flex:none;
  display:flex; gap:10px; align-items:center;
  padding-top:16px; margin-top:4px;
  border-top:1px solid var(--hairline);
}
.oc-bt{
  font-family:inherit; font-size:var(--t-corpo); font-weight:600;
  padding:.72em 1.5em; border-radius:999px; cursor:pointer; border:1px solid transparent;
  transition:background .25s ease, transform .2s var(--ease), opacity .2s ease;
}
.oc-bt--frente{ background:var(--quente); color:var(--tinta); }
/* Os dois botões de ação viajam juntos, encostados à direita. O `margin-left:auto` vive AQUI e
   não no «Continuar»: assim, esconder o disco do Clima (páginas sem assistente, ou o par já
   aberto) não desmonta o alinhamento do pé. */
.oc-pe-acao{ display:flex; align-items:center; gap:10px; margin-left:auto; }

/* ── O atalho para o Clima ────────────────────────────────────────────────────
   Era um link cinzento — «Não sabes responder? Pergunta ao Clima» — e texto apagado ao lado de
   um botão laranja lê-se como nota de rodapé, não como ajuda a sério. Isto é o MESMO objeto da
   bola do canto, à escala do pé: tinta por fundo, a ligadura em nuvem. Um objeto reconhece-se
   e clica-se; uma linha de texto apagado ignora-se.
   Continua a NÃO competir com o «Continuar»: é um disco de 40px sem cor de ação ao lado de uma
   cápsula laranja — hierarquia pelo tamanho e pela cor, não por o esconder. */
.oc-clima{
  position:relative;
  flex:none;
  /* 42px = a altura exata do «Continuar» e do «Voltar». A 40 ficava dois pixels mais baixo e
     os três deixavam de ser um conjunto — vê-se, mesmo sem se saber porquê. */
  width:42px; height:42px; padding:0;
  border:0; border-radius:50%;
  background:var(--tinta); color:var(--nuvem);
  display:inline-flex; align-items:center; justify-content:center;
  cursor:pointer;
  box-shadow:0 4px 14px rgba(10,25,45,.2);
  transition:transform .2s var(--ease), box-shadow .2s ease;
}
/* Com o aro (o mesmo do disco do canto) e a esta escala, a ligadura preenche o disco. Sem o
   aro e a 66%, a marca ficava perdida no meio de um círculo escuro e vazio. */
.oc-clima svg{ width:82%; height:82%; }
/* 🚫 27-ago-2026 — ESTE anel era o que ele estava a ver quando disse «tens aquela bola, a bola
   a pescar, que já te disse que é para proibirmos… não interessa a cor, mas é para proibir»,
   e a seguir «isto é para apagar, para acabar. Acabou-se. Não quero mais isso.»
   O disco fica; o anel a pulsar sai. O argumento que aqui estava escrito — que num telemóvel
   sem hover é preciso dizer «isto mexe» — perdeu para a ordem dele, e sem grande pena: um
   anel a pulsar encostado a um botão é o cliché número um dos produtos de IA, que é
   precisamente o que este site não pode cheirar.
   PARA REPOR: devolver o ::before com `animation:oc-clima-pulso 3.4s ease-out infinite 2s` e
   os keyframes que estavam a seguir (densidade .42, alcance 10px — calibrados para 42px sobre
   fundo quase branco, NÃO reaproveitar a curva da bola do canto). */
/* (A classe `usado`, posta pelo orcamento.js ao primeiro clique, calava o anel depois de
   cumprida a missão. Já não há anel para calar; a classe continua a ser posta e não faz mal.) */

/* A dica sobe do disco (nunca desce): o pé está encostado ao fundo da gaveta e para baixo
   ficaria cortada. */
.oc-clima::after{
  content:attr(data-dica);
  position:absolute; bottom:calc(100% + 9px); left:50%;
  transform:translateX(-50%) translateY(4px);
  padding:6px 11px; border-radius:999px;
  background:var(--tinta); color:var(--nuvem);
  font-size:var(--t-legenda); font-weight:500; letter-spacing:var(--ls-corpo); white-space:nowrap;
  box-shadow:0 6px 18px rgba(10,25,45,.24);
  opacity:0; pointer-events:none;
  transition:opacity .2s ease, transform .2s var(--ease);
}
@media (hover:hover) and (pointer:fine){
  .oc-clima:hover{ transform:translateY(-2px); box-shadow:0 9px 22px rgba(10,25,45,.3); }
  .oc-clima:hover::after{ opacity:1; transform:translateX(-50%) translateY(0); }
}
/* quem chega por teclado vê a mesma dica — senão o disco é um botão sem nome visível */
.oc-clima:focus-visible{ outline:2px solid var(--azul); outline-offset:3px; }
.oc-clima:focus-visible::after{ opacity:1; transform:translateX(-50%) translateY(0); }
/* A dica de uma vez (orcamento.js troca o texto e põe esta classe ao chegar ao ecrã do
   espaço). É a MESMA cápsula do hover, de propósito: além de dizer que há um assistente,
   ensina onde a etiqueta aparece — e no telemóvel, onde não há hover, é a única vez que
   aquele texto se lê. */
.oc-clima.a-ensinar::after{ opacity:1; transform:translateX(-50%) translateY(0); }
.oc-clima:active{ transform:scale(.94); }
.oc-aviso-projeto{
  margin:16px 0 0; padding:12px 14px;
  background:rgba(31,120,208,.06); border-left:3px solid var(--azul); border-radius:0 10px 10px 0;
  font-size:var(--t-rotulo); line-height:1.5; color:rgba(18,36,48,.72);
}
@media (max-width:520px){
  /* a 375px cabem os três na mesma linha (88 + 40 + 137 = 265 em 335 de largura útil) — foi
     por isso que o atalho deixou de ser uma frase: uma frase nunca coube. */
  .oc-pe{ flex-wrap:wrap; }
}
.oc-bt--frente:disabled{ opacity:.6; cursor:default; }
.oc-bt--tras{ background:none; border-color:var(--hairline); color:rgba(18,36,48,.7); }
@media (hover:hover) and (pointer:fine){
  .oc-bt--frente:not(:disabled):hover{ transform:translateY(-1px); }
  .oc-bt--tras:hover{ border-color:rgba(18,36,48,.3); color:var(--tinta); }
}
.oc-bt:active{ transform:scale(.97); }

.oc-fim{ padding:8px 0 4px; }
.oc-fim:focus-visible{ outline:none; }
.oc-fim-tit{ font-size:var(--t-painel); font-weight:600; letter-spacing:var(--ls-apertado); color:var(--tinta); margin:0; }
.oc-fim.falhou .oc-fim-tit{ color:var(--quente); }
.oc-fim-txt{ margin:8px 0 0; font-size:var(--t-corpo); line-height:1.55; color:rgba(18,36,48,.7); }
.oc-fim-gama{
  margin-top:18px; padding:16px 18px;
  background:rgba(31,120,208,.07); border-left:3px solid var(--azul); border-radius:0 12px 12px 0;
  font-size:var(--t-painel); font-weight:600; letter-spacing:var(--ls-titulo); color:var(--tinta);
}
.oc-fim-recap{ margin:8px 0 0; font-size:var(--t-rotulo); color:rgba(18,36,48,.62); }
.oc-fim-nota{ margin:12px 0 0; font-size:var(--t-legenda); line-height:1.5; color:rgba(18,36,48,.5); }

@media (max-width:520px){
  /* três colunas a 375px dão pastilhas de 88px — «O mais depressa possível» não cabe
     e parte em quatro linhas. Duas colunas respiram, e a última ocupa a linha toda. */
  .oc-ops--tres{ grid-template-columns:1fr 1fr; }
  .oc-ops--tres .oc-op:last-child:nth-child(odd){ grid-column:1 / -1; }
  .oc-tit{ font-size:var(--t-destaque); }
}

/* ---------- Clima — bola do canto ---------- */
/* ============================================================
   O CLIMA DE APOIO — «o céu» (27-ago-2026, escolha dele)
   Antes era um SELO: disco mudo no canto e, ao abrir, um círculo de 600px com o nome a girar
   na orla. Três defeitos medidos a olhar: o círculo CORTAVA o próprio texto, desperdiçava ~40%
   da área nos quatro cantos, e tapava o telefone e a ponta do campo do hero.
   Agora é uma CAIXA DE ESCREVER no canto que abre um cartão com uma faixa do céu do site.
   Referência dada por ele: a Joia (SolJoria) e o Limpo (Nura). O que elas tinham e este não:
   cabeçalho com nome E função · a saída humana à vista logo em cima · a resposta numa bolha ·
   pastilhas de sugestão · botão redondo com seta em vez de um ponto · rodapé legal assinado.
   🚫 Zero monograma RM: decisão de 22-ago, vai sempre «Rúben Marques» por extenso.
   ============================================================ */
.clima-launch{
  position:fixed; right:24px; bottom:24px; z-index:55;
  width:min(330px, calc(100vw - 48px));
  display:flex; align-items:center; gap:8px;
  background:#fff; border-radius:999px; padding:6px 6px 6px 18px;
  box-shadow:0 16px 44px -18px rgba(10,25,45,.55), 0 2px 8px rgba(10,25,45,.16);
  /* SEM transição no transform — e desta vez a sério. O comentário já dizia isto e a linha
     por baixo dizia o contrário: o rodape.js escreve o transform a cada frame de scroll e
     uma transição punha a caixa sempre a correr atrás do valor certo. A entrada faz-se por
     `@keyframes clima-nasce` mais abaixo, que larga a propriedade quando acaba. */
  /* 🚨 28-ago-2026, dito por ele: «o chatbot ta tipo a bugar quando aparece».
     Medido fotograma a fotograma DENTRO da pagina (por fora o round-trip come a
     animacao e mente): a opacidade transicionava bem, 0 -> 1 em ~470ms, mas o
     `transform` ficava em `none` do principio ao fim. A caixa nao entrava - MATERIALIZAVA-SE,
     em fade puro, num sitio do ecra onde nao estava nada. E isso que se le como bug.
     Os `@keyframes clima-nasce` so correm UMA vez, quando a bola nasce; a reentrada
     depois de o hero a esconder nao tinha gesto nenhum.
     ⚠️ E o gesto NAO pode vir do `transform`: o rodape.js escreve-lhe
     `bola.style.transform` a cada frame de scroll perto do rodape (a variavel la
     chama-se `bola`, mas e este mesmo elemento) e uma transicao punha a caixa sempre
     a correr atras do valor certo. Foi por isso que o transform saiu daqui.
     A saida e a propriedade `translate` INDIVIDUAL: e distinta de `transform` e
     compoe-se com ela em vez de lhe disputar o valor. O rodape continua a mandar no
     `transform`, isto manda no `translate`, e nao se pisam. */
  transition:opacity .28s ease, translate .42s var(--salto), box-shadow .25s ease;
}
/* ⚠️ A caixa é agora um alvo REAL, com fundo e largura: ao contrário da etiqueta antiga
   (invisível mas a comer cliques por cima do rodapé), esta vê-se, portanto recebe ponteiro
   como qualquer outro controlo. Quem a esconde é a classe `.escondido`, e essa continua a
   cortar os eventos ao contentor e ao botão. */
.clima-launch{ pointer-events:auto; }
/* ⚠️ EXPERIÊNCIA, 27-ago-2026 — ideia dele: «será que no chatbot devíamos pôr RESPOSTA
   IMEDIATA, à frente do "pergunte-nos alguma coisa"? O único problema é o espaço. Como é que
   íamos caber isso aí?»
   Contas: a caixa tem 330px, o campo fica com ~240 e o placeholder já ocupa ~195. Na mesma
   linha NÃO cabe. Cabe por CIMA — uma etiqueta pousada no topo, que não rouba um pixel ao
   campo e custa ~26px de altura ao canto.
   🚫 Sem bola, sem ponto a pulsar: as bolas de estado estão proibidas no site desde 27-ago.
   É só a palavra.
   Se ele aprovar, isto passa de `content` no CSS para markup real nas 15 páginas — uma
   promessa comercial deve estar no HTML, não pendurada num pseudo-elemento. */
.clima-launch::before{
  content:"Resposta imediata";
  position:absolute; left:16px; bottom:calc(100% + 9px);
  background:#fff; color:var(--tinta);
  padding:5px 12px; border-radius:999px;
  font-size:10.5px; font-weight:600;
  letter-spacing:var(--ls-alta); text-transform:uppercase;
  box-shadow:0 10px 26px -14px rgba(10,25,45,.55), 0 1px 4px rgba(10,25,45,.12);
  white-space:nowrap; pointer-events:none;
}
.clima-semente{
  flex:1 1 auto; min-width:0;
  border:0; background:none; outline:none;
  font-family:inherit; font-size:14.5px; color:var(--tinta);
  padding:11px 0;
}
.clima-semente::placeholder{ color:var(--tinta-60); opacity:.8; }
.clima-semente:focus-visible{ outline:none; }
.clima-launch:focus-within{
  box-shadow:0 16px 44px -18px rgba(10,25,45,.55), 0 0 0 3px rgba(217,95,51,.5);
}
.clima-bola{ pointer-events:auto; }
/* com o contentor escondido nada lá dentro recebe cliques (senão ficava um campo
   invisível mas escrevível no canto) */
.clima-launch.escondido .clima-bola,
.clima-launch.escondido .clima-semente{ pointer-events:none; }
/* ⚠️ Quem APAGA a caixa (`.escondido`, menu aberto) mora lá em baixo, a seguir à regra que a
   acende — ver «O QUE APAGA A CAIXA». Não voltar a pôr essas regras aqui: perdem. */

/* ---------- a saída humana, DENTRO do painel ----------
   Uma linha logo abaixo do cabeçalho, antes da conversa: «Prefere falar com uma
   pessoa?» e, ao lado, o número e o WhatsApp. Vive nas duas portas do Clima — a sala
   redonda (o disco do canto) e a gaveta do orçamento.

   Numa instalação de ar condicionado a pergunta que traz alguém ao site costuma ser
   «quanto custa e quando podem vir», e há quem não a queira fazer a uma máquina. A
   escolha oferece-se no momento em que ela se põe: o painel já está aberto, já se vê
   com quem se vai falar. Antes de abrir, o canto continua a ser só o disco.

   UMA CÁPSULA COM DOIS SEGMENTOS e não duas pastilhas: numa linha estreita, com a
   pergunta ao lado, duas pastilhas eram três objetos a disputar o mesmo olhar.

   As duas portas têm fundos opostos — a sala é tinta, a gaveta é nuvem — por isso a
   cápsula é neutra aqui e ganha cor no contexto, exatamente como já acontece com os
   `.chip` deste site. */
.clima-humano{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  margin-bottom:10px;
}

/* `flex:none` não é decorativo: sem ele a cápsula encolhe como qualquer item flexível
   e, com a pergunta ao lado num painel estreito, desce abaixo do próprio conteúdo — o
   `overflow:hidden` do arredondamento corta o «WhatsApp» a meio da palavra. Quem
   encolhe é a pergunta, que sabe partir em duas linhas. */
.clima-atalhos{
  flex:none;
  display:flex; align-items:stretch; overflow:hidden;
  border-radius:999px;
  border:1px solid currentColor;
}
.clima-pil{
  display:inline-flex; align-items:center; justify-content:center;
  padding:6px 11px; white-space:nowrap; text-decoration:none;
  font-size:var(--t-legenda); font-weight:500; letter-spacing:var(--ls-corpo);
  color:inherit;
  transition:color .25s var(--ease), background .25s var(--ease);
}
.clima-pil + .clima-pil{ box-shadow:inset 1px 0 0 currentColor; }
.clima-pil:focus-visible{ outline:2px solid currentColor; outline-offset:-2px; }
/* largura mínima no segmento do número: a etiqueta troca para «Copiado» no computador
   e sem isto a cápsula encolhia no instante do clique, fugindo de debaixo do rato. */
.clima-pil[href^="tel:"]{ min-width:7.8em; }

/* a sala redonda: tinta por fundo, nuvem por letra — a mesma régua dos chips de lá.
   O fio do meio repete o valor do contorno e não o `currentColor` da pílula: herdado,
   saía com o brilho da LETRA e a cápsula ficava com um risco branco no meio, mais
   forte do que a sua própria borda. */
/* ⚠️ A sala deixou de ser escura a 27-ago: passou a cartão branco com faixa de céu. A saída
   humana vive agora numa tira clara logo debaixo do cabeçalho, e a régua é a mesma da gaveta:
   fundo claro, letra em tinta. As regras escuras que estavam aqui não se aplicam a nada. */
.clima-sala .clima-humano{
  margin:0; padding:11px 16px 11px 18px;
  background:#F1F5F8;
}
.clima-sala .clima-humano-txt{ color:var(--tinta-60); font-size:var(--t-legenda); }
.clima-sala .clima-atalhos{ color:rgba(18,36,48,.18); background:#fff; }
.clima-sala .clima-pil{ color:var(--tinta); font-weight:600; }
.clima-sala .clima-pil + .clima-pil{ box-shadow:inset 1px 0 0 rgba(18,36,48,.18); }
@media (hover:hover) and (pointer:fine){
  .clima-sala .clima-pil:hover{ background:rgba(18,36,48,.06); }
}
/* a gaveta: o contrário, nuvem por fundo e tinta por letra */
.gaveta .clima-atalhos{ color:rgba(18,36,48,.22); }
.gaveta .clima-pil{ color:var(--tinta); }
.gaveta .clima-pil + .clima-pil{ box-shadow:inset 1px 0 0 rgba(18,36,48,.22); }
@media (hover:hover) and (pointer:fine){
  .gaveta .clima-pil:hover{ background:rgba(18,36,48,.06); }
}
/* verde de confirmação, e ganha aos dois hovers acima de propósito: quem copia está
   com o rato em cima da pílula, e sem isto a regra do hover apagava a única
   confirmação que há de que o número foi para a área de transferência. */
.clima-sala .clima-pil.copiado, .clima-sala .clima-pil.copiado:hover,
.gaveta .clima-pil.copiado, .gaveta .clima-pil.copiado:hover{
  color:#3ddc97; background:transparent;
}
/* a sala passou a fundo claro: o verde claro deixou de se ler nela e leva o mesmo da gaveta */
.gaveta .clima-pil.copiado, .gaveta .clima-pil.copiado:hover,
.clima-sala .clima-pil.copiado, .clima-sala .clima-pil.copiado:hover{ color:#12764a; }
.clima-bola{
  position:relative; flex:0 0 auto;
  width:38px; height:38px;
  border-radius:50%;
  border:none; padding:0;
  background:var(--quente); color:#111;
  display:grid; place-items:center;
  font-size:17px; line-height:1;
  cursor:pointer;
  transition:background .2s ease, transform .18s var(--ease);
}
@media (hover:hover) and (pointer:fine){
  .clima-bola:hover{ background:#C4522A; }
}
.clima-bola:active{ transform:scale(.93); }
.clima-bola:focus-visible{ outline:2px solid #fff; outline-offset:-4px; }
/* A ENTRADA é agora do contentor inteiro, não do botão: o que nasce é a caixa toda.
   A classe `.nasceu` continua a ser posta pelo JS no BOTÃO em seis ficheiros
   (site.js, clima.js, sobre.js, servicos.js, portfolio.js, ficha.js) — em vez de mexer nos
   seis, é o botão que manda no pai por `:has`, com um travão para quem não o suporte. */
.clima-launch{ opacity:0; transform:translateY(96px); }
/* 🚨 A entrada é uma ANIMAÇÃO, não uma transição, e a diferença não é de estilo.
   O `js/rodape.js` escreve `style.transform` nesta caixa A CADA FRAME de scroll (o nome
   gigante do rodapé empurra-a para cima). Se o transform tiver transição, cada frame arranca
   uma transição nova e a caixa passa a perseguir o valor certo com atraso — aos solavancos,
   e com `--salto` ainda por cima a fazer ressalto. Com `animation` sem `fill`, o movimento de
   entrada acontece e depois LARGA a propriedade: o inline do rodapé passa a mandar sozinho e
   o acompanhamento fica a 1:1. (`fill:both` estragaria isto — ficaria a ganhar ao inline.) */
.clima-launch:has(.clima-bola.nasceu){
  opacity:1; transform:none;
  animation:clima-nasce .9s var(--salto);
}
@keyframes clima-nasce{
  from{ opacity:0; transform:translateY(96px); }
  to{ opacity:1; transform:translateY(0); }
}
@supports not selector(:has(*)){
  .clima-launch{ opacity:1; transform:none; }
}

/* ============================================================
   O QUE APAGA A CAIXA — e porque é que vive AQUI e não lá em cima
   ============================================================
   🚨 Medido ao vivo a 27-ago-2026, nas 15 páginas: a caixa ficava ACESA por trás do painel
   aberto. O JS fazia o seu trabalho (`.escondido` estava lá, e os cliques até morriam), mas
   `.clima-launch.escondido` pesa (0,2,0) e a regra que acende, `.clima-launch:has(.clima-bola
   .nasceu)`, pesa (0,3,0) — o `:has()` herda a especificidade do argumento mais pesado. Não há
   ordem que salve uma regra mais fraca.
   Cura: as regras que apagam repetem o mesmo `:has(.clima-bola.nasceu)`, ficam em (0,4,0)/(0,4,1)
   e vêm DEPOIS. Quem mexer nisto tem de manter as duas coisas — o peso e o sítio.

   Quando é que a caixa deve sumir:
   · painel do Clima aberto (`.escondido`, posto pelo JS de todas as páginas);
   · na home, secções onde o Clima já está a falar noutro sítio do ecrã (balcão do fecho);
   · menu móvel aberto — ver a regra em `body.com-menu` na secção da navegação. */
.clima-launch.escondido:has(.clima-bola.nasceu){ opacity:0; translate:0 14px; pointer-events:none; }
/* 🚫 27-ago-2026, ordem dele: «esquece essas bolas… isto é para apagar, para acabar.
   Acabou-se. Não quero mais isso.» — dito das bolas de estado a pulsar, e o halo do
   lançador do Clima é a mesma família. É também o cliché número um dos produtos de IA.
   A bola do canto FICA; deixa é de respirar. O JS continua a pôr-lhe a classe `respira`
   (seis ficheiros: site.js, clima.js, sobre.js, servicos.js, portfolio.js, ficha.js) e
   isso não faz mal nenhum — é aqui que se decide se ela pulsa.
   PARA REPOR, se algum dia mudar de ideias: devolver a `animation` abaixo. */
.clima-bola.respira::after{ content:none; }
/* `.clima-disco` foi o disco escuro com a ligadura RM lá dentro. Saiu a 27-ago com o selo:
   já não há disco e já não há monograma. O JS não lhe toca em lado nenhum. */

/* ---------- Clima — a sala circular (lógica da tinta) ---------- */
.clima-scrim{
  position:fixed; inset:0; z-index:75;
}
.clima-sala{
  position:fixed; right:24px; bottom:24px; z-index:76;
  width:392px; max-width:calc(100vw - 48px);
  /* ALTURA PELO CONTEÚDO, com teto. A altura fixa é o que fazia o poço vazio: três mensagens
     numa caixa alta deixam meio painel às moscas. Assim nasce do tamanho da conversa e só
     depois trava e passa a rolar. */
  height:auto; max-height:calc(100vh - 48px); max-height:calc(100dvh - 48px);
  /* 🔴 O PAINEL TEM DE SER FLEX, E NUNCA FOI. Queixa dele, 29-ago-2026: «o assistente virtual
     está todo fodido, assim que passa de 2 mensagens para de funcionar», e depois «nem sequer
     dá para dar scroll».
     Medido: `.clima-sala` era `display:block`. O `.chat-log` já tinha `flex:1; min-height:0;
     overflow-y:auto` — mas sem contentor flex isso não vale NADA: o log cresce com o conteúdo,
     nunca fica mais alto do que a própria caixa, e por isso nunca ganha barra. A conversa batia
     no `max-height` e era o `overflow:hidden` daqui a cortá-la, sem scroll em lado nenhum.
     À 3.ª mensagem no telemóvel o campo de escrita ficava 116 px ABAIXO do fundo do ecrã.
     As regras do estado `acompanha` (`.clima-log{flex:0 1 auto}`, `.chat-inputrow{margin-top:auto}`)
     já pressupunham flex desde sempre — faltava só declará-lo. */
  display:flex; flex-direction:column;
  border-radius:20px;
  background:#fff;
  color:var(--tinta);
  border:none;
  box-shadow:0 30px 80px -22px rgba(10,25,45,.6);
  overflow:hidden;
  transform-origin:100% 100%;
  /* a abrir: sobe e cresce do canto de onde nasceu, para o gesto ler como CONTINUAÇÃO da
     caixa e não como um painel que apareceu do nada */
  transform:translateY(14px) scale(.94);
  opacity:0;
  pointer-events:none;
  transition:transform .24s var(--ease), opacity .18s ease; /* fechar: mais rápido */
}
.clima-sala.aberta{
  transform:translateY(0) scale(1);
  opacity:1;
  pointer-events:auto;
  transition:transform .44s var(--ease), opacity .3s ease;
}
.clima-inner{
  position:relative;
  display:flex; flex-direction:column; min-height:0;
  padding:0;
}
/* A FAIXA DE CÉU. É a fotografia do site, não um bloco de cor — é o que faz este painel ser
   deste site. O scrim garante o branco por cima em qualquer fotograma do poster.
   O enquadramento a 62%: a 38% caía na parte lisa e lia-se como um cinzento qualquer. */
.clima-cab{
  position:relative;
  display:flex; align-items:flex-start; gap:10px;
  padding:16px 16px 14px 18px;
  color:#fff;
  background:url('../assets/ceu-A-poster-480.jpg') center 62%/cover;
}
.clima-cab::before{
  content:''; position:absolute; inset:0;
  background:linear-gradient(180deg, rgba(12,28,46,.42), rgba(12,28,46,.64));
}
.clima-cab > *{ position:relative; }
.clima-ident{ display:block; }
.clima-nome{ display:block; font-weight:600; font-size:var(--t-corpo-lg); letter-spacing:-.01em; }
.clima-selo{
  display:block; margin-top:1px;
  font-size:10.5px; letter-spacing:.09em; text-transform:uppercase; font-weight:500;
  color:rgba(255,255,255,.84);
}
.clima-x{ margin-left:auto; color:rgba(255,255,255,.8); }
.clima-x:hover{ color:#fff; }
/* 🔴 28-ago-2026, com ecrã dele à frente: «as letras estão quase a sair do campo, este
   campo está mal feito». Estava mesmo. A caixa tinha `border-radius:999px` — desenho de
   PÍLULA de uma linha — mas mede 95px de altura, porque leva o texto em cima e os botões
   (microfone, enviar) em baixo. Com 999px os cantos viram semicírculos de 47px e a curva
   come o espaço horizontal exactamente à altura onde a primeira linha de texto está:
   media-se 6px entre o fim do campo e o bordo, já dentro da curva.
   REGRA: uma caixa que cresce em altura não pode ter raio de pílula. O raio passa a ser
   fixo e o padding dá folga real ao texto. */
.clima-sala .chat-inputrow{
  margin:0 16px; padding:9px 9px 9px 14px;
  border:1px solid rgba(18,36,48,.16); border-radius:22px;
}
.clima-sala .chat-inputrow:focus-within{ border-color:rgba(217,95,51,.6); }
.clima-sala .chat-input{ color:var(--tinta); }
.clima-sala .chat-input::placeholder{ color:var(--tinta-60); opacity:.85; }
.clima-sala .msg{ color:var(--tinta); }
/* a resposta do bot passa a viver numa BOLHA e não em texto nu no fundo: é o que a Joia e o
   Limpo têm, e é o que separa uma conversa de um parágrafo */
.clima-sala .msg-bot{
  background:#F1F5F8; border-radius:16px;
  padding:12px 15px;
}
.clima-sala .msg-user{ background:var(--quente); color:#111; }
.clima-sala .pensa span{ background:rgba(18,36,48,.45); }
.clima-sala .chip{
  background:#fff;
  border:1px solid rgba(18,36,48,.16);
  color:var(--tinta);
  font-size:var(--t-legenda);
  padding:.5em 1em;
}
@media (hover:hover) and (pointer:fine){
  .clima-sala .chip:hover{ background:rgba(18,36,48,.05); border-color:rgba(18,36,48,.3); }
}
/* O BOTÃO DE ENVIAR deixa de ser um ponto. Redondo, laranja, com seta: alvo maior e diz o que
   faz. ⚠️ O `.chat-send-ponto` é o <span> que já está no HTML das três janelas; aqui vira a
   própria seta por `::before`, para não ter de mexer no marcador de 16 páginas. */
.clima-sala .chat-send{
  width:40px; height:40px;
  background:var(--quente); color:#111; border:none;
}
@media (hover:hover) and (pointer:fine){
  .clima-sala .chat-send:hover{ background:#C4522A; }
  .clima-sala .chat-send:hover .chat-send-ponto{ transform:none; }
}
.clima-sala .chat-send-ponto{
  width:auto; height:auto; border-radius:0; background:none;
  font-size:17px; line-height:1;
}
.clima-sala .chat-send-ponto::before{ content:'\2192'; }
.clima-sala .msg a{ color:var(--tinta); text-underline-offset:3px; }
/* o botão principal, como no Limpo: quem já sabe o que quer não tem de escrever nada */
.clima-cta{
  display:block; margin:12px 16px 0; padding:13px 16px;
  border:0; border-radius:999px; cursor:pointer;
  background:var(--quente); color:#111;
  font-family:inherit; font-size:14.5px; font-weight:600; text-align:center; text-decoration:none;
  transition:background .2s ease;
}
@media (hover:hover) and (pointer:fine){
  .clima-cta:hover{ background:#C4522A; }
}
.clima-cta:focus-visible{ outline:2px solid var(--tinta); outline-offset:2px; }
.clima-sala .clima-log{ padding:14px 16px 4px; min-height:0; }
.clima-sala .chat-chips{ padding:0 16px 12px; }
.clima-sala .chat-privacidade{
  padding:12px 16px 14px; margin:0;
  color:var(--tinta-60); text-align:center;
}

/* ── Formulário + Clima ao mesmo tempo ────────────────────────────────────────
   Quem encalha numa pergunta do formulário («pé-direito?», «quantas pessoas?»)
   precisa de VER a pergunta enquanto lê a resposta. Por isso os dois deixaram de
   se excluir: com o formulário aberto, a sala larga a forma de disco e vem viver
   AO LADO — nunca por cima, nunca a substituir. O formulário não se toca (o DOM
   fica onde estava, e com ele o passo, as escolhas e o que já foi escrito).

   Emparelham só quando a gaveta traz o FORMULÁRIO. Com o chatbot de conversão lá
   dentro seriam dois chats lado a lado, que não é ajuda nenhuma — aí continuam a
   excluir-se, como sempre.

   A composição fica centrada no ecrã: nuvem à esquerda (o que se preenche),
   tinta à direita (quem responde). São os dois fundos opostos que o site já usa
   para distinguir as duas portas do Clima; juntos, lêem-se como um par. */
:root{
  --par-form:min(720px,58vw);
  --par-chat:min(420px,34vw);
  --par-gap:16px;
}
.gaveta.acompanhada{
  --desvio:calc((var(--par-gap) + var(--par-chat)) / 2);
  width:var(--par-form);
}
.clima-sala.acompanha{
  /* ancorada pela DIREITA nos dois estados: `right:auto` não interpola, e sem um
     comprimento dos dois lados o regresso ao canto era um salto. */
  right:calc(50% - (var(--par-form) + var(--par-gap) + var(--par-chat)) / 2);
  top:0; bottom:auto;
  width:var(--par-chat); max-width:none;
  /* ⚠️ Aqui a altura é FIXA de propósito, ao contrário do painel solto: emparelhado, ele é a
     coluna ao lado de um formulário alto, e uma coluna que encolhe com o conteúdo lê-se como
     desalinhamento. O poço que isto abria já está resolvido em baixo (`.clima-log{flex:0 1}`),
     que encosta a conversa ao cabeçalho e manda a caixa de escrita para o fundo. */
  height:min(690px,90dvh);
  border-radius:0 0 26px 26px;
  border:none;
  box-shadow:0 40px 120px rgba(8,20,35,.45);
  /* Escala a partir do CANTO VIRADO PARA O FORMULÁRIO — que é o lado de onde a pessoa o
     chamou. Antes crescia sempre do canto inferior direito do ecrã e voltava para lá, para
     um sítio de onde nunca tinha vindo.
     Cheguei a medir o botão em JS para acertar o ponto exato e deitei fora: no instante da
     abertura a gaveta está a deslizar 218px para a esquerda E a sala está a mudar de disco
     para painel — medir dois alvos em movimento dava a origem 370px ao lado. Uma âncora fixa
     no canto certo lê-se igual e não depende de nada. */
  transform-origin:0 100%;
  transform:scale(.12);
  transition:transform .38s var(--ease), opacity .25s ease;
}
.clima-sala.acompanha.aberta{
  transform:scale(1);
  transition:transform .5s var(--ease), opacity .3s ease;
}
/* emparelhado o painel é uma coluna a partir do topo do ecrã: sem o botão de orçamento, que
   é justamente o que já está aberto ao lado */
.clima-sala.acompanha .clima-cta{ display:none; }
/* A saída humana existe nos dois painéis. Lado a lado ficavam duas cápsulas iguais com o
   mesmo número a 400px uma da outra — lê-se como erro, não como insistência. Fica a do
   formulário, que é a que está no caminho de quem está a preencher. */
.clima-sala.acompanha .clima-humano{ display:none; }
/* No disco a conversa assenta no fundo, como numa app de mensagens, e o vazio por cima
   lê-se como a curva do círculo. Num painel de 690px o mesmo vazio são 400px de nada ao
   lado de um formulário cheio — parece um painel que não carregou. Aqui a conversa começa
   em cima, encostada ao cabeçalho, e é a caixa de escrita que desce para o fundo; o
   espaço que sobra fica ENTRE as duas, que é onde ninguém repara nele. */
.clima-sala.acompanha .clima-log{ flex:0 1 auto; }
.clima-sala.acompanha .clima-log > *:first-child{ margin-top:0; }
.clima-sala.acompanha .chat-inputrow{ margin-top:auto; }
/* Com o Clima já aberto ao lado, o disco é um botão que abre o que já está aberto. Desaparece
   mas NÃO sai do sítio: `visibility` em vez de `display`, por duas razões. O pé deixa de dar um
   salto de 42px sempre que o Clima abre e fecha; e o JS continua a poder MEDIR onde ele está,
   que é de onde o painel tem de nascer (com `display:none` a caixa é zero e a origem caía no
   canto — foi exatamente esse o bug). */
.gaveta.acompanhada .oc-clima{ visibility:hidden; pointer-events:none; }
/* A troca de painel para disco (fecha-se a gaveta e a sala fica sozinha) é rara e
   não vale um morph: pisca-se de um para o outro. */
.clima-sala.a-trocar{ opacity:0; transition:opacity .16s ease; }

/* ============================================================
   MOBILE
   ============================================================ */
@media (max-width:860px){
  html{ scroll-padding-top:74px; }

  .nav{ height:64px; padding:0 16px; gap:14px; }
  .nav-links{ display:none; }
  .nav-tel{ display:none; }
  /* no mobile a barra nao tem espaco para o nome inteiro ao lado do CTA e do
     menu — passa a ligadura, que e para isso que existe */
  .nav-marca .marca-nome{ display:none; }
  .nav-marca .marca-rm{ display:block; }
  .rodape-marca .marca-rm-rodape{ height:30px; }
  .nav-orc{ padding:.62em 1.1em; font-size:var(--t-rotulo); }
  .nav-menu{ display:flex; }
  .nav-movel{ display:flex; }

  .frase{ font-size:var(--t-frase-mob); }
  /* no telemóvel o par encolhe junto, e o espaço entre as duas linhas encolhe
     com ele: a 6px o descritor descolava-se do nome a este corpo */
  .hero-sub{ margin-top:16px; gap:3px; }
  .hero-nome{ font-size:var(--t-painel); }
  .hero-oficio{ font-size:var(--t-rotulo); }
  .hero-acoes{ margin-top:24px; gap:14px; flex-direction:column; }
  /* a 375px o exemplo ia cortado a meio da última palavra: menos goteira à esquerda e
     um corpo abaixo do de leitura (é um exemplo, não copy) e cabe inteiro. */
  /* OPÇÃO B AO TELEMÓVEL. Medido a 375px: campo e botão de palavra não cabem lado a lado —
     o «Pedir orçamento» saía do ecrã. Empilham, e a caixa deixa de ser pílula para ser um
     retângulo de cantos largos. Custa uma linha de altura ao hero e é o preço da opção;
     em troca o alvo passa a ter a largura toda, que ao polegar vale mais do que um
     círculo de 42px. */
  /* 🚨 27-ago-2026, ao vivo no telemóvel dele: «essa coisa de pedir orçamento aqui tá muito
     grande… tens que reduzir o tamanho disso». Estava: empilhada, campo por cima e pastilha de
     largura toda por baixo, ~113px de altura dentro de um hero de 812px, e com a caixa do Clima
     a aparecer ao mesmo tempo lá em baixo eram DUAS caixas brancas no mesmo ecrã.
     Volta à linha única e o botão volta a ser seta — ~56px, METADE. A palavra «Pedir orçamento»
     fica no DESKTOP, onde cabe e onde ele a escolheu; aqui não cabe sem empilhar, e empilhar é
     exatamente o que estava a inchar o hero. Quem diz o que vai acontecer é o rótulo por cima,
     «Diz-nos o que precisas.», que a versão empilhada também dependia dele.
     O `font-size:0` esconde a palavra sem a tirar do DOM — continua a ser lida por quem usa
     leitor de ecrã, e é ela que dá o nome acessível ao botão. */
  .hero-pedido-caixa{
    flex-direction:row; align-items:center; gap:6px;
    border-radius:999px; padding:6px 6px 6px 18px;
  }
  .hero-pedido-txt{ font-size:14.5px; padding:11px 0; }
  .hero-pedido-btn{
    width:44px; height:44px; flex:0 0 44px;
    padding:0; border-radius:50%;
    display:grid; place-items:center;
    font-size:0;
  }
  .hero-pedido-btn::after{ content:'\2192'; font-size:19px; font-weight:600; line-height:1; }
  /* «De Lisboa para todo o Portugal continental» é longa: a 12,5px num ecrã de
     360 sobravam 14px de margem de cada lado e a linha ficava a beijar o bordo.
     A 12px respira; e se ainda assim não couber, o `balance` parte-a em duas
     linhas de peso igual em vez de deixar uma palavra órfã em baixo. */
  .hero-prova{ margin-top:18px; font-size:var(--t-legenda); text-wrap:balance; }

  /* serviços no telemóvel: grelha 2×2 de azulejos-foto — menu completo à vista.
     toque num azulejo → expande e ocupa a secção toda; X (canto sup. dir.) volta atrás. */
  .leque{ display:grid; grid-template-columns:1fr 1fr; gap:10px; height:auto; margin-top:26px; }
  .leque-painel{ flex:none; height:clamp(148px,42vw,190px); border-radius:16px; cursor:pointer; }
  .leque-painel.ativa{ flex:none; height:clamp(148px,42vw,190px); }
  /* 🔴 Esta regra nasceu quando eram CINCO painéis: o quinto esticava a toda a largura para
     não ficar órfão na grelha de duas colunas. A 29-ago-2026 passaram a SEIS e a regra ficou
     a estragar exactamente o que existia para evitar — o quinto ocupava a linha inteira e
     empurrava o sexto para uma linha só para ele, dando 2+2+1+1.
     Passa a disparar só quando o quinto é mesmo o último (`:last-child`), que é a condição
     que a regra sempre quis dizer. Com um número par de painéis não faz nada; com cinco
     volta a fazer o que fazia. Fica assim imune à próxima vez que a lista mudar de tamanho. */
  .leque:not(.tem-expandida) .leque-painel:nth-child(5):last-child{
    grid-column:1 / -1;
    height:clamp(118px,32vw,152px);
  }
  /* era :nth-child(5) — com a fusão dos três cartões passaram a ser quatro painéis e a
     regra ficou a apontar para um painel que já não existe. A classe não se engana. */
  .leque-painel--bombas:not(.ativa) img{ object-position:50% 42%; }
  .leque-rotulo{
    left:15px; right:15px; bottom:13px; top:auto;
    transform:none; writing-mode:horizontal-tb;
    font-size:var(--t-corpo-lg); font-weight:600; opacity:1;
    /* o azulejo tem 138px: «Manutençao e reparaçao» saia cortado a meio da
       palavra, sem reticencias. Quebra em duas linhas, ancorado em baixo. */
    white-space:normal; line-height:1.15;
  }
  .leque-painel.ativa .leque-rotulo{ opacity:1; }
  .leque-conteudo{ display:none; }
  .leque-scrim{
    background:linear-gradient(180deg, rgba(18,36,48,0) 40%, rgba(18,36,48,.34) 66%, rgba(18,36,48,.8) 100%);
  }

  /* --- azulejo expandido --- */
  .leque.tem-expandida .leque-painel:not(.expandida){ display:none; }
  .leque-painel.expandida{
    grid-column:1 / -1;
    height:clamp(380px,72vh,560px);
    cursor:default;
  }
  .leque-painel.expandida .leque-rotulo{ opacity:0; }
  .leque-painel.expandida .leque-conteudo{
    display:block;
    position:absolute; left:22px; right:22px; bottom:22px;
    opacity:1; transform:none;
  }
  .leque-painel.expandida .leque-conteudo h3{ font-size:var(--t-painel); white-space:normal; }
  .leque-painel.expandida .leque-conteudo p{ margin-top:8px; font-size:var(--t-corpo); max-width:none; }
  .leque-painel.expandida .leque-cta{ margin-top:16px; font-size:var(--t-corpo); }
  .leque-painel.expandida .leque-scrim{
    background:linear-gradient(180deg, rgba(18,36,48,0) 30%, rgba(18,36,48,.5) 60%, rgba(18,36,48,.88) 100%);
  }
  .leque-painel.expandida .leque-fechar{ display:flex; }
  /* durante o crescimento (.a-animar) o conteúdo e o X ficam escondidos e entram depois */
  .leque-painel.expandida .leque-conteudo,
  .leque-painel.expandida .leque-fechar{ transition:opacity .3s ease; }
  .leque-painel.expandida.a-animar .leque-conteudo,
  .leque-painel.expandida.a-animar .leque-fechar{ opacity:0; }
  /* mobile: a entrada com translateY (leque-entra, fill:both) fixava transform:none e
     matava a animação de expandir. Aqui a entrada é só por opacidade → transform livre. */
  .leque.revelado .leque-painel{ animation:none; opacity:1; transition:opacity .5s ease; }

  .sec-equipamento{ --equipamento-scroll:clamp(820px,120vh,1050px); }
  .equipamento-frase{
    top:72px; left:18px;
    width:calc(100% - 36px);
    font-size:var(--t-titulo-mob);
    line-height:.98;
  }
  /* O fotograma é landscape e o ecrã é vertical: a máquina ficava a flutuar dentro de uma
     caixa de 560px quase toda vazia. Agora a caixa tem a altura do próprio fotograma,
     centra-se no espaço entre a frase e o selo, e a câmara aproxima-se — o JS afasta-a à
     medida que as peças se separam (--equip-zoom), para o objeto encher sempre o ecrã. */
  .equipamento-media{
    top:57%; bottom:auto;
    width:100vw; max-width:none;
    aspect-ratio:16/9; height:auto;
    transform:translate(-50%,-50%) scale(var(--equip-zoom,1.34));
    transform-origin:50% 50%;
  }
  .equipamento-poster,
  .equipamento-canvas,
  .equipamento-estatico{ object-position:50% 50%; }

  .sec-cab h2 br, .sec-sobre h2 br{ display:none; }
  .sec-cab h2, .sec-sobre h2{ font-size:var(--t-titulo-mob); }
  .sobre-grelha{ grid-template-columns:1fr; gap:clamp(30px,7vw,42px); }
  .sobre-cta{ margin-top:20px; }
  /* frase corrida no telemovel: as estrelas passam a viver ao fim da propria frase,
     por isso ja nao ha o vazio de ~146px que as deixava a flutuar entre linhas. */
  .chapa-linha{ padding:13px 0; gap:5px 10px; font-size:17px; }
  /* no telemovel a copy atravessa o fotograma todo: veu uniforme, sem lado escuro */
  .sobre-veu{
    background:linear-gradient(180deg,
      rgba(18,36,48,.80) 0%, rgba(18,36,48,.50) 26%,
      rgba(18,36,48,.47) 62%, rgba(18,36,48,.72) 100%);
  }

  /* sem hover no telemóvel: rótulos ficam sempre visíveis, discretos */
  .obra-cap{ opacity:1; transform:none; padding:24px 13px 11px; }
  .obra-cap strong{ font-size:var(--t-rotulo); }
  .obra-cap span{ font-size:var(--t-selo); }

  /* testemunhos no telemóvel: CÉU DE VOZES — uma voz nítida ao centro,
     outras a assomar do céu (cortadas nas bordas = há mais); rotação lenta.
     Reaproveita as classes pos-esq/centro/dir como slots verticais cima/centro/baixo. */
  .sec-testemunhos{
    background:
      radial-gradient(120% 70% at 80% 6%, rgba(255,255,255,.85), transparent 58%),
      radial-gradient(150% 90% at 10% 98%, rgba(124,189,240,.26), transparent 55%),
      linear-gradient(178deg, #DCEEFB 0%, #EAF4FC 44%, var(--nuvem) 100%);
  }
  .podio{
    position:relative; display:block;
    height:min(66svh,470px);
    margin-top:22px;
    overflow:clip;                 /* corta as vozes distantes nas bordas = horizonte */
  }
  /* cada carta deixa de ser caixa: texto direto no céu, centrado, em slot absoluto */
  .t-carta{
    position:absolute; top:50%; left:0; right:0;
    width:auto; margin:0;
    background:none; border:none; border-radius:0;
    padding:0 14px;
    display:flex; flex-direction:column; align-items:center; gap:13px;
    text-align:center;
    transform:translateY(-50%) scale(1);
    transition:transform 1.1s var(--ease), opacity 1.1s ease, filter 1.1s ease;
  }
  /* slots — o -50% centra a voz no seu ponto; o deslocamento afasta-a e corta-a */
  .podio.revelado .pos-centro{
    transform:translateY(-50%) scale(1);
    opacity:1; filter:none; z-index:3; box-shadow:none;
  }
  .podio.revelado .pos-esq{
    transform:translateY(calc(-50% - 220px)) scale(.6);
    opacity:.2; filter:blur(2.2px); z-index:1; box-shadow:none;
    cursor:default;
  }
  .podio.revelado .pos-dir{
    transform:translateY(calc(-50% + 220px)) scale(.6);
    opacity:.2; filter:blur(2.2px); z-index:1; box-shadow:none;
    cursor:default;
  }
  /* NEUTRALIZAR o hover/focus do pódio desktop no mobile. As regras
     .pos-esq/.pos-dir:hover/:focus-visible NÃO têm media query (especificidade
     0,4,0 > 0,3,0 do slot base) — sem isto, tocar/focar uma voz fá-la "voar"
     para a posição de pódio (translateX + rotate) e parte o layout. Fixa no slot. */
  .podio.revelado .pos-centro:hover,
  .podio.revelado .pos-centro:focus-visible{
    transform:translateY(-50%) scale(1);
  }
  .podio.revelado .pos-esq:hover,
  .podio.revelado .pos-esq:focus-visible{
    transform:translateY(calc(-50% - 220px)) scale(.6); opacity:.2;
  }
  .podio.revelado .pos-dir:hover,
  .podio.revelado .pos-dir:focus-visible{
    transform:translateY(calc(-50% + 220px)) scale(.6); opacity:.2;
  }
  /* durante o "wrap" invisível (baixo→cima), a voz esbate por completo */
  .t-carta.saindo{ opacity:0 !important; transition:opacity .5s ease !important; }
  /* antes de revelar: tudo apagado (entrada suave via transição dos slots) */
  .podio:not(.revelado) .t-carta{ opacity:0; }

  /* texto no céu — estrelas e legenda centradas, sem o traço lateral da carta */
  .t-estrelas{ justify-content:center; font-size:var(--t-destaque); margin:0; }
  .t-carta blockquote{
    font-size:var(--t-citacao);
    font-weight:500; line-height:1.36; letter-spacing:var(--ls-apertado);
    max-width:22ch; text-wrap:balance;
  }
  .pos-esq blockquote, .pos-dir blockquote{ display:block; }
  .t-carta figcaption{ margin:0; padding:0; font-size:var(--t-corpo-lg); }
  .t-carta figcaption::before{ display:none; }
  .t-carta figcaption span{ display:block; font-size:var(--t-legenda); }

  .sec-final{ min-height:64vh; min-height:64svh; padding:96px 0; }
  /* no telemóvel volta a ser uma coluna só: `flex-direction` já não pega numa grelha */
  .fim-palco{ grid-template-columns:minmax(0,1fr); gap:22px; justify-items:center; }
  .fim-palco > .fim-chat,
  .fim-palco > .fim-contactos{ grid-column:1; justify-self:center; }
  .fim-chat{ padding:16px 18px 18px; }
  .fim-chat .chat-log{ height:auto; max-height:clamp(220px,34vh,280px); }
  .fim-contactos{ flex-direction:row; gap:30px; }

  .rodape-inner{ flex-direction:column; gap:28px; }
  .rodape-dados{ text-align:left; }
  /* a bola do Clima vive fixa no canto (bottom:16 + 60px de altura). No fim da
     pagina essa faixa cai em cima da linha legal — e o link de Privacidade,
     que e obrigatorio (DL 7/2004), ficava tapado e impossivel de tocar.
     O rodape abre espaco por baixo para o texto nunca entrar nessa faixa. */
  .rodape{ padding-bottom:96px; }
  /* aqui a folga e vertical, nao horizontal: a linha legal ja passa por cima
     da bola, e a reserva a direita so espremia o texto num ecra estreito */
  .rodape-legal{ padding-right:0; }

  .gaveta{
    width:100%;
    height:100dvh;
    border-radius:0;
  }
  .gaveta-ceu{ padding:18px 20px 16px; }
  .gaveta-corpo{ padding:14px 20px 18px; }
  .gaveta-orla{ display:none; }

  /* a caixa do canto toma a largura toda do ecrã: ao polegar, um alvo de bordo a bordo vale
     mais do que uma caixa curta encostada à direita */
  .clima-launch{ right:14px; left:14px; bottom:14px; width:auto; }
  .clima-scrim{ background:rgba(8,18,30,.5); }
  .clima-sala{
    right:0; left:0; bottom:0;
    width:100%; max-width:none;
    /* continua a nascer do conteúdo, com teto: é a mesma cura do poço vazio, e no telemóvel
       vale a dobrar porque 86dvh de painel para três mensagens era meio ecrã em branco */
    height:auto; max-height:92dvh;
    border-radius:22px 22px 0 0;
    border:none;
    transform-origin:50% 100%;
    transform:translateY(103%);
    opacity:1;
  }
  .clima-sala.aberta{ transform:translateY(0); transition:transform .5s var(--ease-gaveta), opacity .32s ease; }
  .clima-sala .clima-log > *:first-child{ margin-top:0; }

  /* ── o par no telemóvel: um em cima do outro, nunca sobrepostos ──
     Não há largura para os pôr lado a lado, e empurrar o formulário para fora do
     ecrã seria o mesmo que fechá-lo. Empilham-se: o formulário em cima (é o que
     se está a fazer), a conversa em baixo (é a consulta), com uma fresta de
     fundo entre os dois para se lerem como duas coisas. O formulário fica com a
     fatia maior — a resposta do Clima são duas ou três linhas, a pergunta do
     formulário são três opções e um campo. */
  .gaveta.acompanhada{
    --desvio:0px;
    width:100%;
    height:58dvh;
    border-radius:0 0 22px 22px;
  }
  /* A 375×812 metade do ecrã não chega para o formulário INTEIRO: com o cabeçalho de céu,
     a linha do telefone e o rodapé todos de pé, sobravam 90px para a pergunta — a pessoa
     ficava a rolar dentro de uma janelinha. Acompanhada, a gaveta emagrece: o subtítulo é
     uma apresentação (já foi lida) e o telefone passa para o painel do Clima. O que fica é
     o que interessa: a pergunta e os botões. */
  .gaveta.acompanhada .gaveta-ceu{ padding:13px 20px 13px; }
  .gaveta.acompanhada .gaveta-ceu h2{ font-size:var(--t-destaque); }
  .gaveta.acompanhada .gaveta-ceu p{ display:none; }
  .gaveta.acompanhada .clima-humano{ display:none; }
  .clima-sala.acompanha{
    right:0; left:0; top:auto; bottom:0;
    width:100%;
    height:40dvh;
    border-radius:22px 22px 0 0;
    border:none;
    /* no telemóvel a gaveta está POR CIMA desta folha: a origem é o topo, não o canto */
    transform-origin:50% 0;
    transform:scale(.12);
  }
  /* aqui a saída humana é a do Clima: é o único painel que a mostra */
  .clima-sala.acompanha .clima-humano{ display:flex; }
  /* O aviso de dados fica UMA vez. Empilhados, os dois painéis são a mesma superfície e a
     linha da gaveta está a 16px daqui, com o mesmo texto e o mesmo link — repeti-la custava
     as 44px que faltavam à saudação, que aparecia cortada a meio da primeira frase. */
  .clima-sala.acompanha .chat-privacidade{ display:none; }
  .clima-sala.acompanha.aberta{ transform:scale(1); }
  /* a pega da folha que sobe: vive DENTRO da faixa de céu, e por isso é branca e não escura */
  .clima-cab::after{
    content:'';
    position:absolute; top:7px; left:50%;
    transform:translateX(-50%);
    width:40px; height:4px; border-radius:999px;
    background:rgba(255,255,255,.5);
  }
  .clima-cab{ padding-top:19px; }
}

/* ============================================================
   REDUCED MOTION
   ============================================================ */
@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior:auto; }
  .sec-equipamento{ height:auto; }
  .equipamento-sticky{
    position:relative;
    height:auto; min-height:100svh;
    display:flex; flex-direction:column;
    justify-content:center;
    padding:clamp(88px,12vh,124px) 4vw 56px;
  }
  .equipamento-frase{
    position:relative; top:auto; left:auto;
    width:min(100%,1040px);
  }
  .equipamento-palavra{ opacity:1; transform:none; will-change:auto; }
  .equipamento-media{
    position:relative; top:auto; left:auto;
    bottom:auto;
    width:min(100%,1420px); margin:24px auto 0;
    aspect-ratio:16/9;
    transform:none;
  }
  .equipamento-poster,
  .equipamento-canvas{ display:none; }
  .equipamento-estatico{ display:block; position:relative; }
  .chapa-linha, .chapa-estrelas i, .marca{ transition:none; opacity:1; transform:none; }
  .sobre-video{ transition:none; }
  .marcas-selo{ opacity:1; transform:none; }
  .t-carta{ transition:none; }
  .podio.revelado .chegou .t-estrelas b,
  .podio.revelado .chegou figcaption::before{ animation:none; }
  .podio:not(.revelado) .t-carta{ opacity:1; }
  .podio.revelado .t-carta,
  .podio.revelado .pos-centro.chegou{ animation:none; }
  .fim-marca{ transition:none; }
  .fim-ico{ transition:none; }
  .msg, .chip, .pensa{ animation:none; }
  .caret{ animation:none; opacity:0; }
  .pensa span{ animation:none; opacity:.55; transform:none; }
  /* ⚠️ A caixa do canto nasce com `transform:translateY(96px)`. Se aqui se puser
     `transform:none` sem mais nada, ela fica VISÍVEL e no sítio antes de o JS a acender —
     é o mesmo alçapão que já custou uma folha do Clima aberta por cima do site inteiro.
     Por isso o que muda é só a TRANSIÇÃO; quem a levanta continua a ser a classe `.nasceu`. */
  .clima-launch, .clima-launch:has(.clima-bola.nasceu){ transition:opacity .4s ease; animation:none; }
  .clima-launch{ transform:none; translate:none; }
  .clima-bola{ transition:background .2s ease; }
  /* (os dois anéis a pulsar saíram do site a 27-ago; estas linhas ficam só como rede caso
     alguém os reponha e se esqueça do movimento reduzido) */
  .clima-bola.respira::after{ animation:none; }
  .oc-clima::before{ animation:none; }
  /* 🚨 27-ago-2026 — BUG QUE ESTAVA EM PRODUÇÃO, em TODAS as páginas.
     No desktop a sala fechada esconde-se por duas vias: `transform:scale(.12)` E `opacity:0`.
     No telemóvel (@media max-width:860px) esconde-se só por UMA: `transform:translateY(103%)`,
     com `opacity:1`. Esta linha anulava o transform — e mais nada o segurava. Resultado:
     quem tem «reduzir movimento» ligado (Acessibilidade → Movimento no iPhone, e o mesmo no
     Android e no Windows) abria o site no telemóvel e via a gaveta escura do Clima aberta
     por cima da página inteira, a 698px de altura e z-index 76. E como o JS a deixa `inert`,
     nem sequer se conseguia fechar: o site ficava a olhar para a pessoa, mudo.
     Apanhado por acidente a tirar screenshots com `reducedMotion:'reduce'` — e note-se que o
     `elementFromPoint` NÃO o denunciava, porque `inert` tira o elemento do hit-testing. Só se
     via a olhar para a imagem.
     A cura é a que a `.gaveta` aqui ao lado já usava: quando não há movimento, quem esconde
     é a opacidade. Vale para os dois tamanhos, porque no desktop já era assim. */
  .clima-sala, .clima-sala.aberta{ transition:opacity .25s ease; transform:none; }
  .clima-sala{ opacity:0; pointer-events:none; }
  .clima-sala.aberta{ opacity:1; pointer-events:auto; }
  .clima-inner, .clima-sala.aberta .clima-inner{ transition:opacity .25s ease; }
  .gaveta, .gaveta.aberta{ transition:opacity .3s ease; }
  .gaveta{ opacity:0; pointer-events:none; }
  .gaveta.aberta{ opacity:1; pointer-events:auto; transform:translate(calc(-50% - var(--desvio)),0); }
  /* o par também aparece e desaparece, sem deslizar */
  .clima-sala.acompanha, .clima-sala.acompanha.aberta{ transform:none; transition:opacity .25s ease; }
  .clima-sala.acompanha{ opacity:0; }
  .clima-sala.acompanha.aberta{ opacity:1; }
  .btn-cta, .chip, .chat-send-ponto, .clima-disco{ transition:none; }
  /* menu: aparece e desaparece, sem escala nem cascata */
  .nav-movel{ transform:none; transition:opacity .2s ease, visibility 0s; }
  .nav-movel.aberto{ transform:none; transition:opacity .2s ease, visibility 0s; }
  .nav-movel a, .nav-movel.aberto a{ transform:none; transition:none; transition-delay:0s; }
  .nav-movel a{ opacity:1; }
  body.com-menu::after{ animation:none; }
  /* pressões sem movimento — o feedback fica nos estados de cor/opacidade */
  .btn-cta:active, .chip:active, .chat-send:active, .fechar:active,
  .leque-fechar:active, .clima-bola:active .clima-disco,
  .fim-cont:active .fim-ico{ transform:none; }
  .chat-send, .fechar, .leque-fechar{ transition:none; }
  .serv-foto img{ transition:opacity .2s ease; }
  .leque:not(.revelado) .leque-painel{ opacity:1; }
  .leque.revelado .leque-painel{ animation:none; }
}

/* ---------- leque: link "Saber mais" para a ficha do serviço ---------- */
.leque-mais{
  margin-top:14px; margin-left:18px;
  display:inline-block;
  font-size:var(--t-rotulo); font-weight:600;
  color:rgba(255,255,255,.72);
  text-decoration:underline;
  text-underline-offset:5px;
  transition:color .3s ease;
}
.leque-mais:hover, .leque-mais:focus-visible{ color:#fff; }

/* ============================================================
   SELO SOLJORIA no fim do rodapé
   Snippet oficial: marca\kit\fim-do-site-selo-cliente.html (variante fundo
   escuro). Cores fixas no SVG de propósito — são as da SolJoria, não as do
   cliente, e não devem seguir o currentColor deste site.
   ============================================================ */
/* o selo vive NA linha legal, na outra ponta — uma linha só para ele lia-se
   como acrescento solto. No mobile a linha quebra e ele passa para baixo. */
.rodape-legal{
  display:flex; flex-wrap:wrap; align-items:center;
  justify-content:space-between; gap:10px 28px;
}
.sj-selo{
  display:inline-flex; align-items:center; gap:6px;
  font-family:'Plus Jakarta Sans',system-ui,sans-serif;
  font-size:var(--t-legenda); font-weight:600; line-height:1;
  color:#FAF6EF; text-decoration:none;
  /* .75 é o valor do kit e não é gosto: a .6 o «sol» âmbar caía para 3,57:1
     sobre a tinta — abaixo do mínimo para 12px. A .75 dá 4,89:1. */
  opacity:.75;
  transition:opacity .25s ease;
}
.sj-selo:hover,
.sj-selo:focus-visible{ opacity:1; }
.sj-selo svg{ height:11px; width:auto; display:block; }
.sj-selo .sj-sol{ color:#F2A516; }

/* ============================================================
   TESTE 01-ago-2026 — duas peças emprestadas ao demo Prumo
   Bloco auto-contido: apagar daqui até ao fim do ficheiro reverte
   tudo. Não toca em HTML nem em JS.

   (1) NAVBAR EM PÍLULA — a barra deixa de encostar às três margens
       e passa a flutuar. A geometria vive aqui; o estado (--solida
       ao rolar, --ceu no topo das páginas com céu) continua a ser
       decidido pelo JS de cada página, sem alterações.
   (2) BARRA DE PROGRESSO DE LEITURA — 3px em quente no fio do topo.
       Sem JS: usa scroll-driven animations (animation-timeline).
       Onde o browser não suporta, o @supports não aplica nada e a
       barra simplesmente não existe.
   ============================================================ */

/* ---------- (1) a pílula ---------- */
.nav{
  top:12px;
  left:16px; right:16px;
  /* 28-ago-2026 - ESCOLHA DELE, depois de ver as tres ao vivo (?nav=1|2|3).
     Era 1240px fixos e media-se um buraco de ~430px entre «Contactos» e o lado
     direito: a barra tinha largura a mais para o que leva dentro, sobretudo depois
     de o Portfolio sair da navegacao (27-ago) e sobrarem tres links. Com
     `max-content` a pilula passa a ter exactamente a largura do que transporta e o
     `margin-inline:auto` centra-a. Mediu 567px em vez de 1240px.
     ⚠️ Ele pediu para MANTER o «Pedir orcamento» e o PT/EN, ao contrario do que a
     maquete da opcao 2 mostrava: «faz a dois, mas com o pedir orcamento e tambem
     com o botao pt en». Nao voltar a tira-los. */
  max-width:max-content;
  margin-inline:auto;          /* left+right+max-width => centra */
  height:66px;
  padding:0 12px 0 24px;
  /* «deixa algum espaco entre as paginas, a marca e a parte de cta+pt/en».
     Numa pilula com a largura do conteudo o `gap` e a UNICA coisa que separa as tres
     zonas: nao ha espaco livre para o `margin-left:auto` do `.nav-dir` distribuir.
     Fica bem acima do gap interno do `.nav-dir` (20px) para as tres zonas se lerem
     como tres e nao como uma fila de seis coisas. */
  gap:clamp(34px,4.6vw,64px);
  border-radius:999px;
  /* a borda existe já no estado transparente para a caixa não crescer
     2px no instante em que a pílula materializa */
  border:1px solid transparent;
}
.nav--solida{
  /* mais translúcida do que a barra encostada (.94): uma pílula que
     flutua tem de deixar ver o que passa por baixo, senão é uma barra
     com cantos redondos.
     ⚠️ Medido nos OLHOS: a .78 e sem `brightness`, ao passar por cima da
     secção escura do Método o vidro escurecia com ela e o texto em tinta
     ficava lodoso. Um material claro tem de CLAREAR o que está por baixo,
     não acompanhá-lo — daí o brightness a puxar para cima. */
  background:rgba(247,250,252,.84);
  backdrop-filter:blur(18px) saturate(1.5) brightness(1.12);
  -webkit-backdrop-filter:blur(18px) saturate(1.5) brightness(1.12);
  border-color:rgba(255,255,255,.55);
  box-shadow:
    0 1px 0 rgba(255,255,255,.75) inset,   /* o brilho no lábio de cima */
    0 2px 6px rgba(16,38,68,.06),
    0 12px 32px rgba(16,38,68,.13);        /* a sombra que a levanta da página */
}

@media (max-width:860px){
  /* ⚠️ O `max-width:max-content` da pilula do PC tem de ser DESFEITO aqui.
     Ele escolheu a pilula encolhida so para o computador («isto e mais para o PC do
     que para o telemovel»), mas o `max-content` nao sabe de larguras: apanhou tambem
     o telemovel e a barra caiu de 355px para 298px, com 38px de margem de cada lado
     em vez de 10. No telemovel a barra leva menos coisas dentro (marca, CTA e o
     tres-riscas), por isso o conteudo nunca chega as bordas e a pilula encolhia
     sozinha. Aqui a largura manda-se a bordo, nao se pede ao conteudo. */
  .nav{ top:10px; left:10px; right:10px; max-width:none; height:58px; padding:0 8px 0 16px; }
  /* o cartão do menu estava ancorado à barra encostada (top:56) — agora
     alinha pela aresta de baixo da pílula (10+58) com 8px de folga */
  .nav-movel{ top:76px; right:10px; }

  /* VIDRO MAIS BARATO NO TELEMÓVEL.
     Medido (Chrome, CPU a 4×, 210 frames de scroll): com blur(18)+saturate+
     brightness caíam 28 frames por passagem (13,6%) e o p95 ia a 47ms; com o
     vidro em conta caem 15 (7,4%) e o p95 fica em 35ms. Metade do atropelo.
     Um `backdrop-filter` num elemento fixo é reamostrado a CADA frame, e é o
     único que está vivo durante o scroll normal (os outros do site vivem em
     painéis que abrem). O raio do desfoque é o que custa — o brightness é uma
     conta por pixel e fica, que é ele que impede o vidro de escurecer por cima
     das secções escuras. */
  .nav--solida{
    backdrop-filter:blur(10px) brightness(1.1);
    -webkit-backdrop-filter:blur(10px) brightness(1.1);
    background:rgba(247,250,252,.90);
  }

  /* ?nav=encostada — a pílula volta a encostar ao topo, só para comparar no
     telemóvel a sério. Ver a nota no foco.js. */
  /* ⚠️ top:3px e não 0: a barra de progresso vive nos primeiros 3px do ecrã.
     Com a nav encostada a 0 a linha laranja caía-lhe em cima e lia-se como
     defeito em vez de indicador. Assim a faixa de cima fica exactamente
     preenchida pela barra, sem sobra nem sobreposição. */
  .nav-encostada .nav{
    top:3px; left:0; right:0; max-width:none;
    height:64px; border-radius:0; padding:0 16px; border:0;
  }
  .nav-encostada .nav--solida{ box-shadow:0 1px 0 var(--hairline); }
  .nav-encostada .nav-movel{ top:66px; right:12px; }
}

/* ---------- (2) a barra de progresso ---------- */
@supports (animation-timeline: scroll()){
  body::before{
    content:'';
    position:fixed; top:0; left:0; right:0; height:3px;
    z-index:52;                 /* acima da nav (50) e do selo (51),
                                   abaixo da bola do Clima (55) e da gaveta (69) */
    pointer-events:none;
    background:var(--quente);
    transform:scaleX(0);
    transform-origin:0 50%;
    animation:rm-leitura linear both;
    animation-timeline:scroll(root block);
    transition:opacity .25s ease;
  }
  @keyframes rm-leitura{ to{ transform:scaleX(1); } }

  /* Enquanto a intro corre ou o scroll está travado (gaveta, sala, menu)
     o body é position:fixed, o documento fica sem altura de scroll e a
     linha do tempo colapsa para 0 — a barra esvaziava-se de repente à
     frente de quem estava a ler. Some em vez de saltar. */
  body.com-intro::before,
  body.travado::before{ opacity:0; }
}

/* ---------- (3) fora a barra do lado ----------
   Fica só a do topo. O `overflow-y:scroll` do topo do ficheiro MANTÉM-SE: era
   ele que impedia a página de encolher ~10px quando a barra nascia no fim da
   intro. Com a barra a zero de largura o espaço é sempre zero, portanto a
   garantia continua de pé — só que agora não se vê nada.
   ⚠️ Escopado a `html`. A regra genérica lá em cima continua a valer para os
   contentores que rolam por dentro (carrosséis), que precisam da sua barra. */
html{ scrollbar-width:none; }
html::-webkit-scrollbar{ width:0; height:0; }

/* ---------- (4) FOCO: como o texto entra ----------
   Portado do soljoria v2 (`bandeira/src/styles/foco.css`). Um gesto só: o texto
   chega DESFOCADO, 12px abaixo, e a lente puxa o foco.

   Duas escalas, como no original:
   · BLOCO (ledes, parágrafos) — desfoca-se inteiro, de uma vez.
   · PALAVRA (títulos) — parte-se em palavras que entram em cascata. Só títulos:
     um parágrafo palavra a palavra deixa de ser entrada e passa a ser espera.

   Calibre próprio: no v2 o desfoque do título é 14px para títulos de 80px. Aqui
   os h2 andam nos 30–48px, e 14px de desfoque a essa escala já não lê como
   profundidade de campo, lê como ecrã avariado. Daí 9px (e 7 no telemóvel,
   onde o h2 desce aos 26px).

   Quem põe as classes é o `js/foco.js` — o CSS só as pinta. Sem JS a página
   fica exatamente como está hoje, que é o que a Google e os LLMs leem. */
:root{
  --foco-blur:6px;
  --foco-blur-t:9px;
  --foco-sobe:12px;
  --foco-dur:.9s;
  --foco-dur-t:1s;
  --foco-passo:42ms;    /* atraso por palavra */
  --foco-max:12;        /* teto de palavras escalonadas */
  --ease-luz:cubic-bezier(.16,1,.3,1);
}

/* BLOCO */
.foco{
  opacity:0;
  filter:blur(var(--foco-blur));
  transform:translateY(var(--foco-sobe));
  transition:opacity var(--foco-dur) var(--ease-luz),
             filter var(--foco-dur) var(--ease-luz),
             transform var(--foco-dur) var(--ease-luz);
}
.foco.in{ opacity:1; filter:blur(0); transform:none; }
/* assente: o filtro SAI. Um elemento com `filter` fica promovido a camada
   própria enquanto o filtro lá estiver, mesmo a blur(0) — é pagar GPU para
   sempre por um gesto de um segundo, e o texto em repouso chega a rasterizar
   mais magro do que devia. */
.foco.pousado{ filter:none; transition:none; }

/* PALAVRA — o bloco marcado `.pals` não se anima a si próprio, delega nas
   palavras; senão o título entrava duas vezes e via-se. */
.pals{ opacity:1; filter:none; transform:none; transition:none; }
.pal{ display:inline-block; opacity:0; }
.pals.in .pal{
  opacity:1;
  animation:focoPal var(--foco-dur-t) var(--ease-luz) backwards;
  /* Teto: um título de 20 palavras a 42ms dava 840ms só de atraso e a última
     chegava depois de a pessoa já ter lido a primeira linha. */
  animation-delay:calc(min(var(--i,0), var(--foco-max)) * var(--foco-passo));
}
@keyframes focoPal{
  from{ opacity:0; filter:blur(var(--foco-blur-t)); transform:translateY(var(--foco-sobe)); }
  to{ opacity:1; filter:blur(0); transform:none; }
}

/* NO TELEMÓVEL O GESTO PERDE O DESFOQUE.
   Desfocar texto obriga a rasterizá-lo de novo a cada nível de blur, e numa
   descida a fio isso acontece sete vezes (4 títulos + 3 blocos). Medido: sem o
   foco.js caíam 22 frames por passagem em vez de 28. Fica a mesma entrada —
   opacidade e 9px de subida, que é o «fade in» do pedido — sem a conta.
   No PC, onde há folga, o desfoque mantém-se: é ele que faz o gesto. */
@media (max-width:860px){
  :root{ --foco-sobe:9px; --foco-passo:34ms; }
  .foco{
    filter:none;
    transition:opacity var(--foco-dur) var(--ease-luz),
               transform var(--foco-dur) var(--ease-luz);
  }
  .pals.in .pal{ animation-name:focoPalMovel; }
  @keyframes focoPalMovel{
    from{ opacity:0; transform:translateY(var(--foco-sobe)); }
    to{ opacity:1; transform:none; }
  }
}

/* Movimento reduzido: o texto está lá, assente, sem gesto nenhum. */
@media (prefers-reduced-motion: reduce){
  .foco, .foco.in{ opacity:1; filter:none; transform:none; transition:none; }
  .pal{ opacity:1; }
  .pals.in .pal{ animation:none; }
}

/* ---------- (5) BOTÕES DE VIDRO — TESTE ----------
   O botão de vidro do Prumo é branco a 10% com uma orla a 20%, e funciona
   porque vive sobre uma FOTO ESCURA: é o fundo que lhe dá o contorno. Este
   site tem três contextos, e cada um pede a sua matéria — copiar a receita
   tal e qual dava um botão invisível na folha clara.

   · fundo escuro / foto  → vidro branco (a receita do Prumo)
   · folha clara (nuvem)  → vidro tingido de tinta
   · CTA                  → vidro em terracota

   Interruptor (posto pelo foco.js):
   · sem parâmetro        → tudo em vidro, CTAs incluídos
   · ?vidro=secundarios   → só os não-CTA; os CTAs ficam sólidos como hoje
   · ?vidro=nenhum        → nada, o site como está publicado
   ------------------------------------------------------------------ */

/* ===== não-CTA sobre fundo escuro: os textos sublinhados viram pastilha ===== */
.vidro-tudo .leque-cta,
.vidro-secundarios .leque-cta,
.vidro-tudo .palco-cta,
.vidro-secundarios .palco-cta,
.vidro-tudo .sobre-cta--sec,
.vidro-secundarios .sobre-cta--sec{
  display:inline-flex; align-items:center; gap:.45em;
  padding:.62em 1.15em;
  border-radius:999px;
  background:rgba(255,255,255,.13);
  border:1px solid rgba(255,255,255,.30);
  backdrop-filter:blur(10px);
  -webkit-backdrop-filter:blur(10px);
  color:#fff;
  text-decoration:none;
  transition:background .25s var(--ease), border-color .25s var(--ease), transform .25s var(--ease);
}
@media (hover:hover) and (pointer:fine){
  .vidro-tudo .leque-cta:hover,
  .vidro-secundarios .leque-cta:hover,
  .vidro-tudo .palco-cta:hover,
  .vidro-secundarios .palco-cta:hover,
  .vidro-tudo .sobre-cta--sec:hover,
  .vidro-secundarios .sobre-cta--sec:hover{
    background:rgba(255,255,255,.22);
    border-color:rgba(255,255,255,.45);
    transform:translateY(-1px);
    color:#fff;
  }
}

/* ===== não-CTA sobre a folha clara: telefone e linhas de contacto ===== */
/* ⚠️ Sem backdrop-filter dentro da navbar: a pílula JÁ é um vidro, e um vidro
   dentro de outro é uma segunda amostragem por frame a troco de nada — o que
   se vê por trás do botão já é o desfoque do pai. */
.vidro-tudo .nav--solida .nav-tel,
.vidro-secundarios .nav--solida .nav-tel,
.vidro-tudo .nav-movel-tel,
.vidro-secundarios .nav-movel-tel{
  display:inline-flex; align-items:center; justify-content:center; gap:.45em;
  padding:.5em 1em;
  border-radius:999px;
  background:rgba(18,36,48,.06);
  border:1px solid rgba(18,36,48,.15);
  color:var(--tinta);
  text-decoration:none;
  transition:background .22s var(--ease), border-color .22s var(--ease);
}
.vidro-tudo .nav-movel-tel,
.vidro-secundarios .nav-movel-tel{
  margin-top:8px; border-top:1px solid rgba(18,36,48,.15);
  color:var(--quente-escuro, #A8451F);
  border-color:rgba(217,95,51,.35);
  background:rgba(217,95,51,.10);
}
@media (hover:hover) and (pointer:fine){
  .vidro-tudo .nav--solida .nav-tel:hover,
  .vidro-secundarios .nav--solida .nav-tel:hover{
    background:rgba(18,36,48,.10); text-decoration:none;
  }
}
/* o «ou ligue: 915 100 172» do hero — é o telefone mais visível do site
   inteiro e tinha-me escapado da lista. Sobre o céu, logo vidro branco.
   A sombra de texto sai: dentro da pastilha já não faz falta e só suja. */
.vidro-tudo .hero-tel,
.vidro-secundarios .hero-tel{
  display:inline-flex; align-items:center; gap:.4em;
  padding:.62em 1.15em;
  border-radius:999px;
  background:rgba(255,255,255,.13);
  border:1px solid rgba(255,255,255,.30);
  backdrop-filter:blur(10px);
  -webkit-backdrop-filter:blur(10px);
  text-shadow:none;
  transition:background .25s var(--ease), border-color .25s var(--ease);
}
.vidro-tudo .hero-tel strong,
.vidro-secundarios .hero-tel strong{ text-decoration:none; }
@media (hover:hover) and (pointer:fine){
  .vidro-tudo .hero-tel:hover,
  .vidro-secundarios .hero-tel:hover{
    background:rgba(255,255,255,.22); border-color:rgba(255,255,255,.45);
  }
  .vidro-tudo .hero-tel:hover strong,
  .vidro-secundarios .hero-tel:hover strong{ text-decoration:none; }
}

/* as linhas de contacto dos Contactos (telefone e WhatsApp) — vivem sobre o
   céu, logo levam o vidro branco. O ícone já era um círculo com orla; aqui a
   linha inteira passa a ser a pastilha e o círculo perde a orla própria para
   não haver duas orlas encaixadas uma na outra. */
.vidro-tudo .ct-linha,
.vidro-secundarios .ct-linha{
  background:rgba(255,255,255,.12);
  border:1px solid rgba(255,255,255,.28);
  backdrop-filter:blur(10px);
  -webkit-backdrop-filter:blur(10px);
  border-radius:999px;
  padding:8px 20px 8px 8px;
}
.vidro-tudo .ct-linha .ct-ico,
.vidro-secundarios .ct-linha .ct-ico{
  border-color:transparent;
  background:rgba(255,255,255,.14);
}
@media (hover:hover) and (pointer:fine){
  .vidro-tudo .ct-linha:hover,
  .vidro-secundarios .ct-linha:hover{
    background:rgba(255,255,255,.2);
    border-color:rgba(255,255,255,.45);
  }
}

/* o telefone sobre o céu (nav--ceu, páginas com hero de fundo) leva o vidro branco */
.vidro-tudo .nav--ceu .nav-tel,
.vidro-secundarios .nav--ceu .nav-tel{
  display:inline-flex; align-items:center;
  padding:.5em 1em; border-radius:999px;
  background:rgba(255,255,255,.14);
  border:1px solid rgba(255,255,255,.32);
  backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
  text-decoration:none;
}

/* ===== CTA em vidro terracota =====
   ⚠️ Aqui está o compromisso, e não é de gosto. A 18% de preenchimento (o
   equivalente ao vidro do Prumo) o texto em tinta deixa de ser legível sobre
   as secções escuras, porque quem garantia o contraste era o laranja cheio.
   A .58 continua a deixar passar o fundo — vê-se o conteúdo a correr por
   trás — mas o preenchimento ainda manda no contraste. Números medidos na
   secção abaixo desta. */
.vidro-tudo .btn-cta{
  background:rgba(217,95,51,.58);
  border:1px solid rgba(217,95,51,.85);
  backdrop-filter:blur(12px) saturate(1.3);
  -webkit-backdrop-filter:blur(12px) saturate(1.3);
  color:var(--tinta);
  box-shadow:0 8px 28px rgba(217,95,51,.22);
}
@media (hover:hover) and (pointer:fine){
  .vidro-tudo .btn-cta:hover{
    background:rgba(217,95,51,.72);
    border-color:var(--quente);
  }
}
/* dentro da pílula da navbar o CTA não leva desfoque próprio (mesma razão
   do telefone: o pai já é vidro) */
.vidro-tudo .nav .btn-cta{
  backdrop-filter:none; -webkit-backdrop-filter:none;
  background:rgba(217,95,51,.82);
}

/* ============================================================
   O PAINEL DÁ LUGAR À CONVERSA
   23-ago-2026. Medido no painel circular em 1440×900: o log tinha 136 px de 598 — 23% do
   círculo para a conversa, e 77% para cromo que está sempre lá. Com o Clima a responder com
   mais substância (guias do site, causas de avaria), a bolha da própria pergunta da pessoa
   aparecia CORTADA A MEIO pela máscara do log. Ela escrevia e não via o que tinha escrito.

   Nada desaparece: encolhe. A diferença não é de vocabulário — uma zona que some de repente
   lê-se como falha, uma que recolhe lê-se como o painel a afastar-se para a conversa caber.
   O movimento é curto e a curva é a da casa.

   Dois estados, postos por js/chat-nucleo.js no contentor do log:
     .conversa-viva — a primeira mensagem já foi enviada (não volta atrás na sessão)
     .a-escrever    — há texto por enviar na caixa
   ============================================================ */

/* Barra dos contactos: é uma porta de saída para quem prefere falar com uma pessoa, e essa
   escolha faz-se ao chegar. Quem já escreveu escolheu ficar — e o telefone continua a sair
   nas respostas do Clima sempre que é a resposta certa. */
.clima-humano{
  overflow:hidden;
  max-height:60px;
  transition:max-height .44s var(--ease), opacity .26s ease, margin-bottom .44s var(--ease);
}
.conversa-viva .clima-humano{
  max-height:0;
  opacity:0;
  margin-bottom:0;
  pointer-events:none;
}

/* Atalhos: servem para ARRANCAR. Assim que ela escreve a primeira letra já escolheu outro
   caminho, e três pastilhas valem uma linha e meia de leitura. Voltam quando a caixa
   esvazia — não se perde nada, só sai da frente enquanto estorva. */
.chat-chips{
  overflow:hidden;
  max-height:120px;
  transition:max-height .38s var(--ease), opacity .22s ease, padding .38s var(--ease);
}
.a-escrever .chat-chips,
.conversa-viva .chat-chips{
  max-height:0;
  opacity:0;
  padding-top:0; padding-bottom:0;
  pointer-events:none;
}

/* Aviso de RGPD: tem de estar inteiro e legível ANTES do primeiro envio — é aí que serve.
   Depois disso, o consentimento já foi dado com a mensagem, e ficam os dois links: a página
   de Privacidade e a assinatura da casa. */
.chat-priv-frase{
  display:block;
  max-height:4em;
  margin-bottom:2px;
  overflow:hidden;
  transition:max-height .44s var(--ease), opacity .24s ease, margin-bottom .44s var(--ease);
}
.conversa-viva .chat-priv-frase{
  max-height:0;
  opacity:0;
  margin-bottom:0;
}
/* ⚠️ O separador FICA. Escondê-lo colava os dois links um ao outro — lia-se
   «PrivacidadeAssistente por soljoria», que parece um erro de composição. Visto no ecrã, não
   no código: com a frase em bloco por cima, o «·» nunca chega a abrir linha nenhuma. */

/* A bolha do utilizador é laranja cheio, e os 14 px de fade do log não chegam para a
   dissolver: encostada ao cabeçalho, lia-se como uma faixa cortada a régua. Com a conversa
   viva há espaço para respirar — o fade sobe para 26 px e o corte passa a ser um esbatido. */
.conversa-viva .clima-log{
  -webkit-mask:linear-gradient(180deg, transparent, #000 26px, #000 calc(100% - 14px), transparent);
  mask:linear-gradient(180deg, transparent, #000 26px, #000 calc(100% - 14px), transparent);
}

/* Quem pediu menos movimento recebe o mesmo resultado, sem a transição. O ganho de espaço
   não é decoração — é legibilidade — por isso não se desliga com a animação. */
@media (prefers-reduced-motion: reduce){
  .clima-humano,
  .chat-chips,
  .chat-priv-frase{ transition:none; }
}


/* ═══════════════════════════════════════════════════════════════════════
   AS VOZES NO HERO — as avaliacoes do Google, a rodar

   Encaixe escolhido: coluna a direita, hero quieto. A regra que manda em
   tudo o resto: o .hero-copy nao sabe que isto existe. Por isso a coluna e
   ABSOLUTA nos dois formatos — no desktop encostada a direita, ao nivel do
   olhar; no telemovel numa faixa em baixo, onde o hero ja tinha ceu vazio.
   Se fosse um irmao em fluxo, o flex do .hero re-centrava tudo e o miolo
   subia — que e precisamente o que ele pediu para nao acontecer.
   ═══════════════════════════════════════════════════════════════════════ */
.hero-vozes{
  position:absolute; z-index:3;
  right:clamp(20px,3.4vw,54px); top:50%;
  transform:translateY(-50%);
  width:clamp(250px,24vw,340px);
  pointer-events:none;
}
/* Havia aqui uma «pista» alta com as vozes vizinhas a assomar desfocadas por
   cima e por baixo, e uma mascara a esbate-las nas bordas. Saiu a 24-ago-2026.
   Aquilo funciona sobre um fundo liso; sobre a fotografia das nuvens NAO: texto
   pequeno, desfocado e com sombra escura da uma mancha cinzenta, e o `clip` da
   caixa cortava-a a direito dos dois lados. Lia-se como um quadrado sujo a
   volta das avaliacoes — que e exatamente o que ele viu e mandou apagar.
   Agora esta uma voz de cada vez. Sem mascara e sem `clip`, porque nao ha nada
   para cortar: quem nao esta no centro esta a zero. */
.hv-pista{
  position:relative;
  height:150px;
}
.hv-voz{
  position:absolute; top:50%; left:0; right:0;
  display:flex; flex-direction:column; align-items:flex-start; gap:5px;
  text-align:left;
  color:#fff;
  /* A MESMA sombra apertada da linha do «Desde 2011», e pela mesma razao: a
     --sombra-texto tem 26 px de desfoque, que segura um H1 grosso mas a 14 px
     espalha-se e nao segura nada. Isto e texto pequeno e branco por cima de
     nuvens brancas — o nucleo opaco de 2 px colado a letra e o que da a aresta. */
  text-shadow:
    0 1px 2px rgba(8,26,48,.92),
    0 0 7px rgba(8,26,48,.78),
    0 1px 22px rgba(8,26,48,.5);
  /* A que sai ACABA de sair antes de a seguinte comecar a chegar. Com as duas a
     atravessar-se num crossfade de 1,1 s, ficava mais de um segundo com DUAS
     citacoes legiveis no mesmo sitio — texto branco por cima de texto branco,
     sobre nuvens brancas. Lia-se como uma mancha, nao como uma avaliacao.
     A ordem dos atrasos segue a ordem das propriedades: transform, opacity. */
  transition:transform 1.1s var(--ease,cubic-bezier(.22,1,.36,1)), opacity .48s ease;
}
.hv-voz.centro{ transition-delay:0s,.52s; }
.hv-voz q{ quotes:'\00AB' '\00BB'; font-size:var(--t-destaque); font-weight:500; line-height:1.42; max-width:23ch; }
.hv-voz .hv-quem{ font-size:var(--t-legenda); opacity:.86; }
.hv-voz .hv-estrelas{ font-size:var(--t-legenda); letter-spacing:var(--ls-alta); color:#FFC46B; }

/* Uma de cada vez. A que chega sobe de baixo, a que sai continua a subir e
   apaga-se — o movimento de sempre, so que agora quem nao esta no centro esta
   invisivel em vez de esbatido. */
.hv-voz{ opacity:0; }
.hv-voz.centro{ transform:translateY(-50%); opacity:1; z-index:3; }
.hv-voz.cima{ transform:translateY(calc(-50% + 14px)); opacity:0; z-index:1; }   /* a proxima, ainda por baixo */
.hv-voz.baixo{ transform:translateY(calc(-50% - 14px)); opacity:0; z-index:1; }  /* a que saiu, ja por cima */
.hv-voz.fora{ transform:translateY(calc(-50% + 14px)); opacity:0; z-index:0; }
.hv-voz.saindo{ opacity:0 !important; transition:opacity .5s ease !important; }

/* entra depois de a intro pousar o resto do hero, nao ao mesmo tempo */
.hero-vozes{ opacity:0; transition:opacity .9s ease; }
body:not(.com-intro) .hero-vozes{ opacity:1; }

/* ─── telemovel: faixa em baixo ─────────────────────────────────────────
   Em pe nao ha lado — 390 px nao dao para um miolo e uma coluna. As vozes
   vao para a faixa de ceu vazio por baixo do «Desde 2011», centradas. */
@media (max-width:860px){
  /* Em pe, o hero deixa de ser «uma coisa centrada e outra colada ao fundo».
     O copy centrava-se no ecra inteiro e as vozes estavam presas ao rodape, o
     que punha um mar de azul vazio em cima e as avaliacoes em cima do banco de
     nuvens do fundo — que e a transicao para a folha, o pior sitio para pousar
     texto branco. Passam a ser UMA coluna, encostada ao alto: titulo, nome,
     botao, prova e avaliacoes, tudo no azul limpo, e as nuvens ficam livres. */
  .hero{
    flex-direction:column; justify-content:flex-start; align-items:center;
    padding-top:clamp(96px,15svh,140px); padding-bottom:0;
  }
  .hero-copy{ padding-bottom:0; }
  .hero-vozes{
    position:static; transform:none;
    right:auto; left:auto; top:auto; bottom:auto;
    width:100%; margin-top:clamp(34px,6.5svh,60px);
  }
  .hv-pista{ height:132px; }
  .hv-voz{ align-items:center; text-align:center; padding:0 18px; }
  .hv-voz q{ font-size:var(--t-base); max-width:25ch; }
  .hv-voz .hv-quem{ font-size:var(--t-legenda); }
}

/* telemovel BAIXO (640 px e menos): medido, a faixa ficava a 5 px da linha do
   «Desde 2011». Encolhe e volta a haver ar entre as duas coisas. */
@media (max-width:860px) and (max-height:700px){
  .hv-pista{ height:112px; }
  .hv-voz q{ font-size:var(--t-corpo-lg); }
}

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


/* ============================================================
   MÉTODO · passos em cartão dividido  (.sec-metodo--passos)
   Substitui os cartões de foto cheia com véu. O que muda, e porquê:
   o texto sai de cima da fotografia. A foto passa a ser um objeto
   ao lado da frase, e não um fundo escurecido por baixo dela — é a
   anatomia do método da Nura, que é a referência que ele deu.
   Sem véu, sem branco sobre imagem, sem cartão preto.
   ============================================================ */
.sec-metodo--passos{ padding-bottom:var(--respiro); }

.mp-lista{
  list-style:none; margin:0; padding:0;
  width:min(92%,1180px); margin-inline:auto;
  display:flex; flex-direction:column; gap:clamp(18px,2.2vw,30px);
}
.mp-etapa{ position:relative; }

.mp-cartao{
  display:grid; grid-template-columns:1.02fr .98fr;
  align-items:stretch;
  min-height:clamp(300px,38svh,378px);
  background:#fff;
  border:1px solid var(--hairline);
  border-radius:clamp(18px,1.7vw,22px);
  overflow:hidden;
  box-shadow:0 18px 44px -34px rgba(18,36,48,.34);
  transition:box-shadow .5s var(--ease), transform .5s var(--ease);
}
.mp-etapa.acesa .mp-cartao{
  box-shadow:0 26px 60px -34px rgba(18,36,48,.46);
}

/* a foto troca de lado ao meio: sem isto são três blocos iguais em fila */
.mp-etapa:nth-child(even) .mp-cartao{ grid-template-columns:.98fr 1.02fr; }
.mp-etapa:nth-child(even) .mp-foto{ order:2; }

.mp-foto{ position:relative; overflow:hidden; background:var(--tinta); }
.mp-foto img{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; object-position:var(--pos,50% 50%);
}

.mp-corpo{
  display:flex; flex-direction:column; justify-content:center;
  padding:clamp(26px,3.4vw,52px);
}
/* so o numero. O rotulo que aqui esteve («primeiro passo») dizia o mesmo
   que o numero ja diz, e punha um segundo tom a competir com o laranja. */
.mp-id{
  margin:0 0 16px; display:flex; align-items:center; gap:12px;
  font-size:clamp(22px,1.85vw,28px); font-weight:600; line-height:1;
  letter-spacing:-.02em; color:var(--quente);
  font-variant-numeric:tabular-nums;
}
.mp-id b{ font-weight:600; }
/* 🚫 27-ago-2026: aqui havia um filete curto a seguir ao número. Ordem dele, com o cursor em
   cima dele: «estas eyebrows… apaga isto. Deixa só o número. São muito típicas da IA.»
   Sai também a animação do traço, mais abaixo (`.mp-etapa.acesa .mp-id::after`). */
.mp-tit{
  margin:0; font-size:var(--t-sub); font-weight:600;
  line-height:1.1; letter-spacing:var(--ls-titulo); color:var(--tinta);
  max-width:16ch; text-wrap:balance;
}
.mp-desc{
  margin:14px 0 0; font-size:var(--t-lede); line-height:1.6;
  color:var(--tinta-60); max-width:38ch;
}

/* ---------- a entrada, em quatro tempos ----------
   O fade de bloco que aqui estava era invisível: o cartão inteiro subia 22px e
   acendia, tudo ao mesmo tempo, e lia-se como «não tem animação nenhuma».
   Agora o CARTÃO já está posto — é a janela — e o conteúdo é que chega:
   a fotografia abre-se de fora para dentro, e o número, o traço, o título e a
   descrição entram atrás dela, escalonados. Só clip-path, opacity e transform;
   nada disto mexe no layout da página. */
/* A fotografia ENTRA no cartão: desliza da borda para dentro, e é o próprio
   cartão (que tem overflow:hidden) que a recorta enquanto ela chega. Depois o
   número, o traço, o título e a descrição sobem atrás dela, escalonados.

   Tudo em @keyframes e não em transições, por duas razões: o fim de cada gesto
   fica escrito num sítio só, e uma animação pode ser AGARRADA e posta a meio
   (`getAnimations()[i].currentTime`) — que é como se vê um gesto de um segundo
   sem ter de o apanhar a voar. */
@keyframes mpEntraFoto{ from{ transform:translateX(var(--de,-101%)); } to{ transform:none; } }
@keyframes mpSobe{ from{ opacity:0; transform:translateY(15px); } to{ opacity:1; transform:none; } }
@keyframes mpTraco{ from{ transform:scaleX(0); } to{ transform:scaleX(1); } }

.mp-foto{ transform:translateX(var(--de,-101%)); }
.mp-etapa:nth-child(even){ --de:101%; }
.mp-etapa.acesa .mp-foto{ animation:mpEntraFoto .95s var(--ease) both; }

.mp-id,.mp-tit,.mp-desc{ opacity:0; }
.mp-etapa.acesa .mp-id{ animation:mpSobe .62s var(--ease) .16s both; }
.mp-etapa.acesa .mp-tit{ animation:mpSobe .62s var(--ease) .26s both; }
.mp-etapa.acesa .mp-desc{ animation:mpSobe .62s var(--ease) .36s both; }

/* (o traço que aqui entrava a crescer saiu com a eyebrow, ver .mp-id acima) */

/* ---------- e depois de entrar, continua vivo ----------
   Uma secção que faz um gesto e morre lê-se como parada dois segundos depois.
   A fotografia fica a derivar devagar, como ar a passar: 34 s por volta, menos
   de 1% de deslocação. É uma transform composta — não repinta, não faz layout —
   e pára sozinha quando o cartão sai do ecrã, porque a classe sai com ele. */
@keyframes mpDeriva{
  0%  { transform:scale(1.06) translate3d(-.7%, .2%,0); }
  50% { transform:scale(1.06) translate3d( .7%,-.5%,0); }
  100%{ transform:scale(1.06) translate3d(-.7%, .2%,0); }
}
.mp-foto img{ transform:scale(1.06); }
.mp-etapa.acesa .mp-foto img{ animation:mpDeriva 34s ease-in-out infinite; }
.mp-etapa:nth-child(even).acesa .mp-foto img{ animation-direction:reverse; animation-duration:41s; }

.sem-js .mp-foto{ transform:none; }
.sem-js .mp-id,.sem-js .mp-tit,.sem-js .mp-desc{ opacity:1; }
.sem-js .mp-id::after{ transform:none; }
@media (prefers-reduced-motion: reduce){
  .mp-foto{ transform:none; }
  .mp-id,.mp-tit,.mp-desc{ opacity:1; animation:none; }
  .mp-id::after{ transform:none; animation:none; }
  .mp-foto img,.mp-etapa.acesa .mp-foto img{ transform:none; animation:none; }
}

@media (max-width:860px){
  .mp-lista{ width:min(92%,560px); gap:16px; }
  .mp-cartao,
  .mp-etapa:nth-child(odd) .mp-cartao{
    grid-template-columns:minmax(112px,.78fr) minmax(0,1.22fr);
    grid-template-rows:1fr;
    min-height:230px;
    border-radius:18px;
  }
  .mp-etapa:nth-child(even) .mp-cartao{
    grid-template-columns:minmax(0,1.22fr) minmax(112px,.78fr);
    grid-template-rows:1fr;
    min-height:230px;
    border-radius:18px;
  }
  /* 30-ago-2026 — em mobile, a fotografia e o texto continuam lado a lado,
     como no desktop. Empilhá-los tornava os três passos numa secção de mais de
     1 600 px e obrigava a um scroll inteiro só para ler o método. */
  .mp-etapa:nth-child(even) .mp-foto{ order:2; }
  .mp-foto{ aspect-ratio:auto; min-height:100%; }
  .mp-corpo{ padding:18px 14px 20px; }
  .mp-id{ margin-bottom:8px; }
  .mp-id b{ font-size:22px; }
  .mp-tit{ font-size:16px; line-height:1.16; max-width:none; }
  .mp-desc{ margin-top:9px; font-size:13px; line-height:1.45; max-width:none; }
}

/* ---------- idioma na navbar ----------
   Links reais entre as versões PT e EN. A língua atual fica em tinta cheia;
   a outra continua discreta, mas já não parece nem se comporta como desativada. */
.nav-idioma{
  display:flex; align-items:center; gap:2px;
  font-size:var(--t-legenda); font-weight:600; letter-spacing:.06em;
  padding:4px; border-radius:999px;
  border:1px solid var(--hairline);
}
.nav-idioma-on,
.nav-idioma-off{
  display:block; padding:3px 8px; border-radius:999px;
  font:inherit; line-height:1; border:0; background:none;
  text-decoration:none;
}
.nav-idioma-on{ background:var(--tinta); color:#fff; }
.nav-idioma-off{ color:var(--tinta-60); opacity:.76; cursor:pointer; transition:color .2s var(--ease), opacity .2s var(--ease); }
.nav-idioma-off:hover,
.nav-idioma-off:focus-visible{ color:var(--tinta); opacity:1; }
.nav--ceu .nav-idioma{ border-color:rgba(255,255,255,.34); }
.nav--ceu .nav-idioma-on{ background:rgba(255,255,255,.92); color:var(--tinta); }
.nav--ceu .nav-idioma-off{ color:#fff; }
@media (max-width:860px){
  .nav-idioma{ padding:3px; font-size:11px; }
  .nav-idioma-on,
  .nav-idioma-off{ padding:3px 6px; }
}

/* ---------- leque no telemóvel: o sinal de que dá para tocar ----------
   Um azulejo com uma foto e um nome não diz a ninguém que abre. No rato há o
   cursor e o crescimento do painel ao lado; no dedo não há nada. O «+» é o
   mesmo sinal dos cartões da página de serviços — e quando o azulejo abre, quem
   fica no canto é o × que já lá estava. Só no telemóvel: no desktop a
   composição está aprovada e não se lhe mexe. */
.leque-sinal{ display:none; }
@media (max-width:860px){
  .leque-sinal{
    position:absolute; z-index:4;
    top:11px; right:11px;
    width:30px; height:30px;
    border-radius:50%;
    display:grid; place-items:center;
    color:#fff;
    border:1px solid rgba(255,255,255,.5);
    background:rgba(9,20,36,.42);
    -webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px);
    pointer-events:none;
    transition:opacity .25s ease;
  }
  .leque-sinal svg{ width:14px; height:14px; display:block; }
  /* aberto, quem manda no canto é o × */
  .leque-painel.expandida .leque-sinal{ opacity:0; }
}
@media (max-width:860px) and (prefers-reduced-motion: reduce){
  .leque-sinal{ transition:none; }
}

/* ============================================================
   FAQ · o acordeão CANÓNICO do site.
   Já havia duas cópias idênticas deste padrão: .sb-faq-* no sobre.css e
   .fs-faq-* no ficha.css. Uma terceira cópia privada para a home era o mesmo
   erro do site-inverno-v2 (a segunda cópia nunca recebe as correções da
   primeira), por isso este vive no site.css, que TODAS as páginas carregam.
   Quando houver mão, sobre.html e as fichas de serviço trocam de prefixo e
   as duas cópias antigas caem.
   ============================================================ */
/* ⚠️ `position:relative; z-index:1` NÃO É DECORAÇÃO — sem isto a secção DESAPARECE.
   O céu do hero (.ceu) é uma camada `position:fixed; z-index:0` que o js/site.js volta a
   mostrar quando `scrollY + innerHeight > finalTopo`, ou seja assim que o balcão final entra
   no ecrã. A FAQ é a secção IMEDIATAMENTE antes dele: sem posicionamento, pintava por baixo do
   céu e via-se a nuvem no lugar das perguntas — só os «+» (que são `position:relative`)
   sobreviviam. Apanhado a 27-ago-2026 a olhar para a página, não no código: as medidas diziam
   fundo `--nuvem`, texto a `rgb(18,36,48)` e opacidade 1, e estava tudo certo. O que estava
   errado era quem pintava por cima. */
.sec-faq{ position:relative; z-index:1; padding:clamp(72px,9vh,110px) 0 clamp(76px,9.5vh,120px); background:var(--nuvem); }
.sec-faq .sec-inner{ width:min(92%,820px); }
.faq-lista{
  margin-top:clamp(34px,4vw,46px);
  border-top:1px solid var(--hairline);
}
.faq-item{ border-bottom:1px solid var(--hairline); }
.faq-q{
  width:100%;
  display:flex; align-items:center; justify-content:space-between; gap:22px;
  padding:21px 2px;
  background:none; border:none; cursor:pointer;
  font-family:inherit; text-align:left;
  font-size:clamp(16px,1.35vw,18.5px);
  font-weight:600; letter-spacing:-.01em;
  color:var(--tinta);
}
.faq-mais{
  position:relative;
  width:16px; height:16px; flex:0 0 auto;
  transition:transform .4s var(--ease);
}
.faq-mais::before, .faq-mais::after{
  content:'';
  position:absolute; left:0; top:7px;
  width:16px; height:2px; border-radius:2px;
  background:var(--azul);
}
.faq-mais::after{ transform:rotate(90deg); }
.faq-item.aberto .faq-mais{ transform:rotate(45deg); }
/* ⚠️ `grid-template-rows:0fr` esconde À VISTA mas NÃO tira da ordem de tabulação: os links
   dentro de respostas FECHADAS continuavam a apanhar o teclado — paragens invisíveis (WCAG
   2.4.7). `visibility:hidden` tira-os; o atraso deixa a animação de fecho ver-se. */
.faq-corpo{
  display:grid; grid-template-rows:0fr; visibility:hidden;
  transition:grid-template-rows .45s var(--ease), visibility 0s linear .45s;
}
.faq-item.aberto .faq-corpo{ grid-template-rows:1fr; visibility:visible; transition-delay:0s; }
.faq-txt{ overflow:hidden; }
.faq-txt p{
  padding:0 2px 22px;
  font-size:15.5px; line-height:1.66;
  color:var(--tinta-60);
  max-width:60ch;
}
/* cada resposta liga à página que a desenvolve: é assim que a autoridade
   circula em vez de ficar presa na home (guia-websites/10-SEO.md, fase 3). */
.faq-txt p.faq-link{ padding-top:2px; }
.faq-link a{
  font-weight:600; color:var(--azul); text-decoration:none;
  border-bottom:1px solid transparent;
  transition:border-color .3s var(--ease);
}
.faq-link a:hover, .faq-link a:focus-visible{ border-bottom-color:currentColor; }
@media (prefers-reduced-motion:reduce){
  .faq-mais, .faq-corpo{ transition:none; }
}


/* ============================================================
   O CARRIL DE PASSOS DA GAVETA  (.pd-carril)
   26-ago-2026. A gaveta voltou a ser conversa (ver scripts/form-orcamento.mjs) e o que lhe
   faltava — e a da Nura tem — era a pessoa VER onde está. Três etiquetas por cima do log.

   ⚠️ «O contacto» é o SEGUNDO passo, não o último. Uma conversa que se interrompe a meio com o
   contacto já dado ainda deixa uma lead; sem ele perde-se tudo o que a pessoa escreveu. É a
   mesma ordem da Nura e é pela mesma razão — não é estética.

   ⚠️ O carril NÃO é o assunto. Vive a 13 px, sem cor cheia, e o passo cumprido ganha um visto
   com UMA pulsação curta. Uma animação vistosa a cada etapa transforma um pedido de orçamento
   numa slot machine, e à terceira ninguém a quer ver.
   ============================================================ */
.pd-carril{
  flex:none;
  display:flex; align-items:center; flex-wrap:wrap;
  gap:9px;
  margin:0 0 14px; padding:0;
  list-style:none;
}
.pd-carril li{
  display:flex; align-items:center; gap:7px;
  font-size:13px; font-weight:600;
  letter-spacing:var(--ls-corpo);
  color:rgba(18,36,48,.42);
  transition:color .42s var(--ease);
}
.pd-ponto{
  position:relative;
  display:block; width:16px; height:16px; flex:none;
  border-radius:50%;
  box-shadow:inset 0 0 0 1.5px rgba(18,36,48,.22);
  transition:box-shadow .42s var(--ease), background-color .42s var(--ease);
}
/* o traço que liga — some abaixo dos 420 px (ver ao fundo) */
.pd-carril li + li::before{
  content:''; width:clamp(10px,2.4vw,22px); height:1px; flex:none;
  margin-right:1px;
  background:rgba(18,36,48,.18);
}

.pd-carril li.agora{ color:var(--azul-escuro); }
.pd-carril li.agora .pd-ponto{
  background:var(--azul);
  box-shadow:inset 0 0 0 1.5px var(--azul), 0 0 0 3px rgba(31,120,208,.16);
}

/* o passo cumprido: o disco cede o lugar ao visto, e dá uma pulsação só */
.pd-carril li.feito{ color:rgba(18,36,48,.62); }
.pd-carril li.feito .pd-ponto{
  background:rgba(31,120,208,.13);
  box-shadow:inset 0 0 0 1.5px rgba(31,120,208,.28);
  animation:pdCumprido .46s var(--ease);
}
.pd-carril li.feito .pd-ponto::after{
  content:''; position:absolute; inset:0;
  background:no-repeat center/9px 9px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M1.6 6.4l3 3 5.8-6.6' fill='none' stroke='%23175A9E' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  animation:pdVisto .32s var(--ease) .12s both;
}
@keyframes pdCumprido{ 0%{ transform:scale(1) } 42%{ transform:scale(1.09) } 100%{ transform:scale(1) } }
@keyframes pdVisto{ from{ opacity:0; transform:scale(.6) } to{ opacity:1; transform:scale(1) } }

@media (max-width:860px){
  .pd-carril{ gap:8px; margin-bottom:12px; }
  .pd-carril li{ font-size:12.5px; }
}
/* ⚠️ A 375 px os três passos não cabem numa linha; o que passa para a segunda leva o TRAÇO à
   frente, pendurado na margem a ligar coisa nenhuma. Lia-se como defeito. */
@media (max-width:420px){
  .pd-carril li + li::before{ display:none; }
  .pd-carril{ gap:8px 13px; }
}

/* ⚠️ CINCO PASSOS, E CINCO PALAVRAS NÃO CABEM. 29-ago-2026: o carril passou de três para cinco
   (Espaço · Serviço · Zona · Quando · Contacto) e a 375 px isso são duas ou três linhas de
   etiquetas a comer meia gaveta, com a conversa empurrada para fora do ecrã.

   A saída não é encolher a letra até ninguém a ler. É a que o formulário do concorrente também
   usa, e é a certa: **abaixo dos 560 px só o passo ATIVO tem palavra.** Os outros ficam pontos.
   Vê-se onde se está, vê-se quantos faltam, e cabe tudo numa linha.
   Os que já estão feitos continuam com o visto — é a prova visível de que a conversa andou. */
@media (max-width:560px){
  .pd-carril{ flex-wrap:nowrap; gap:0 7px; }
  .pd-carril li{ font-size:12.5px; gap:0; min-width:0; }
  /* o rótulo vive num span próprio (.pd-rot) de propósito: um nó de texto solto não se
     esconde por CSS, e era assim que estava até 29-ago-2026 */
  .pd-carril .pd-rot{ display:none; }
  /* o passo ATIVO tem palavra; e o ÚLTIMO mantém a dele quando tudo ficou feito, senão o fim da
     conversa era cinco vistos sem uma única palavra a dizer o que aconteceu (visto nos OLHOS) */
  .pd-carril li.agora,
  .pd-carril li.feito:last-child{ gap:7px; min-width:0; }
  .pd-carril li.agora .pd-rot,
  .pd-carril li.feito:last-child .pd-rot{
    display:block;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  }
}
@media (prefers-reduced-motion:reduce){
  .pd-carril li, .pd-ponto{ transition:none; }
  .pd-carril li.feito .pd-ponto, .pd-carril li.feito .pd-ponto::after{ animation:none; }
}


/* ============================================================
   A CALCULADORA NA HOME  (.sec-calc / .calc-*)
   26-ago-2026. O site não tinha uma única porta para a calculadora. Esta é a porta, e não
   anuncia a ferramenta: FAZ a primeira pergunta dela. Responder já é entrar.

   ⚠️ Prefixo .calc- e não .cx-: as três propostas desenhadas usavam .cx- e chocavam entre si.

   A placa é TINTA por decisão de ritmo: equipamento, método e FAQ são três secções seguidas
   em --nuvem, e sem esta quebra o fundo da home era uma folha só do meio para baixo.
   ============================================================ */
.sec-calc{ position:relative; z-index:1; padding:clamp(70px,8.5vh,104px) 0 clamp(74px,9vh,112px); background:var(--nuvem); }

.calc-placa{
  position:relative;
  background:var(--tinta); color:#fff;
  border-radius:clamp(18px,1.7vw,24px);
  overflow:hidden;
  box-shadow:0 24px 60px -30px rgba(18,36,48,.44);
  padding:clamp(32px,3.8vw,58px) clamp(28px,3.6vw,56px) 0;
}

.calc-copy{ display:grid; grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr); gap:clamp(24px,3vw,54px); align-items:center; }

.calc-quem{
  grid-column:1 / -1;
  display:flex; align-items:center; gap:9px;
  margin:0 0 clamp(16px,1.8vw,22px);
  font-size:var(--t-legenda); font-weight:500; letter-spacing:var(--ls-solto);
  color:rgba(255,255,255,.62);              /* 6,91:1 sobre --tinta */
}
.calc-ponto{
  flex:none; width:7px; height:7px; border-radius:50%;
  background:var(--azul-claro); box-shadow:0 0 0 3px rgba(124,189,240,.18);
}

/* A pergunta é o H2 e leva o filete azul de 2px do balão do Clima — é a mesma peça a
   continuar do outro lado da porta, sem costura. */
.calc-tit{
  margin:0; padding-left:clamp(14px,1.2vw,18px);
  border-left:3px solid var(--azul-claro);
  font-size:var(--t-titulo); font-weight:600;
  line-height:1.05; letter-spacing:var(--ls-titulo);
  color:#fff;                                /* 15,90:1 */
  max-width:15ch; text-wrap:balance;
}
.calc-lede{
  margin:0;
  font-size:var(--t-lede); line-height:1.62;
  color:rgba(255,255,255,.72);               /* 8,85:1 */
  max-width:46ch;
}

/* as seis opções: as pastilhas da calculadora, na placa escura */
.calc-opcoes{ display:flex; flex-wrap:wrap; gap:10px; margin:clamp(26px,3vw,38px) 0 clamp(26px,3vw,36px); }
.calc-op{
  /* <button>, não <a>: abrem a gaveta do site com a resposta já dada */
  appearance:none; -webkit-appearance:none; margin:0;
  font-family:inherit; cursor:pointer;
  display:inline-flex; align-items:baseline; gap:7px;
  padding:.78em 1.3em;
  border:1px solid rgba(255,255,255,.26);
  border-radius:999px;
  background:transparent; color:#fff;
  font-size:15.5px; font-weight:500; line-height:1.2;
  letter-spacing:var(--ls-corpo);
  text-decoration:none; white-space:nowrap;
  transition:transform .24s var(--ease), background-color .22s ease, color .22s ease, border-color .22s ease;
}
.calc-op small{ font-size:13px; color:rgba(255,255,255,.6); transition:color .22s ease; }
@media (hover:hover) and (pointer:fine){
  .calc-op:hover{ transform:translateY(-2px); background:#fff; border-color:#fff; color:var(--tinta); }
  .calc-op:hover small{ color:var(--tinta-60); }
}
.calc-op:active{ transform:translateY(0) scale(.97); transition-duration:.11s; }
.calc-op:focus-visible{ outline:2px solid var(--azul-claro); outline-offset:3px; }

.calc-pe{
  display:flex; flex-wrap:wrap; align-items:baseline; justify-content:space-between;
  gap:10px clamp(16px,2vw,30px);
  border-top:1px solid rgba(255,255,255,.14);
  padding:clamp(15px,1.7vw,20px) 0 clamp(20px,2.2vw,28px);
}
.calc-escape{
  /* era um <a> e passou a <button> (abre a gaveta em vez de ir para a calculadora):
     sem este reset vinha com o fundo e a moldura do browser — a mancha branca. */
  appearance:none; -webkit-appearance:none;
  background:none; border:0; padding:0; margin:0;
  font-family:inherit; letter-spacing:inherit; cursor:pointer;
  font-size:var(--t-rotulo); font-weight:600; color:#fff;
  text-decoration:underline; text-underline-offset:5px; text-decoration-thickness:1px;
  transition:text-decoration-thickness .2s ease;
}
.calc-escape:hover{ text-decoration-thickness:2px; }
.calc-escape:focus-visible{ outline:2px solid var(--azul-claro); outline-offset:3px; border-radius:4px; }
/* O rótulo de IA e o aviso de que o contacto é pedido. Fica ANTES do clique de propósito:
   a calculadora só mostra o número depois do nome e do contacto, e escondê-lo era vender
   uma coisa e entregar outra. */
.calc-nota{
  margin:0; max-width:64ch;
  font-size:var(--t-legenda); line-height:1.55;
  color:rgba(255,255,255,.6);                /* 6,53:1 */
}

/* ============================================================
   A PLACA DO ESPAÇO SOBRE AS NUVENS (fecho da home, 27-ago-2026)
   As regras acima nasceram para a placa ESCURA: pastilha vazada, contorno e letra brancos.
   Sobre nuvens isso desaparece — branco sobre branco. Ordem dele: «mudamos de cor para ficar
   branco.» Ou seja o inverso: a pastilha é que passa a ser a mancha branca, e a letra escura.
   Ganha-se contraste sem véu nenhum por baixo, que é a regra da casa para esta fotografia.
   ============================================================ */
/* o título desta secção é uma pergunta comprida: sem travão ia a 1030px de linha única e
   lia-se como uma manchete de jornal. Travado, cai em duas linhas equilibradas. */
.sec-final .fim-copy h2{ max-width:20ch; margin-inline:auto; }
/* a lede não pode ser mais larga do que o título que serve: assim ficava uma pirâmide ao
   contrário, com a linha pequena a atravessar o ecrã por baixo da grande travada. */
.sec-final .fim-copy p{ max-width:60ch; margin-inline:auto; }
.calc-opcoes--ceu{ justify-content:center; }
/* AS PASTILHAS SOBRE O CÉU — BRANCAS, com a tinta da casa. Laranja só a que está sob o rato.
   ⚠️ ISTO JÁ DEU DUAS VOLTAS NO MESMO DIA, 27-ago-2026, e a segunda é a que vale:
     · de manhã, a olhar para a secção antiga (a do espaço): «mete-os todos assim laranja e a
       escrita preta» → ficaram laranja cheio;
     · à noite, a olhar para a secção nova (a do serviço): «se calhar aqui devia ficar branco,
       os botões… mete os botões a branco, melhor, como tava antes».
   Não é indecisão: o que mudou entre as duas foi o CONTEÚDO. Seis pastilhas curtas de espaço
   («Sala», «Quarto») aguentam laranja cheio; cinco nomes de serviço são o dobro do texto, e
   cinco blocos laranja cheios sobre nuvens passam de acento a mancha.
   Antes de voltar a mexer, ler as duas ordens acima.
   Contraste: a tinta #122430 sobre branco dá ~15:1, com folga. No hover a pastilha passa a
   laranja e a letra a #111 (5,1:1) — nunca branco sobre laranja, que dá 3,7 e reprova. */
.calc-opcoes--ceu .calc-op{
  background:#fff;
  border-color:#fff;
  color:var(--tinta);
  font-weight:600;
  box-shadow:0 10px 26px -14px rgba(10,25,45,.55);
}
.calc-opcoes--ceu .calc-op small{ color:rgba(18,36,48,.66); }
@media (hover:hover) and (pointer:fine){
  .calc-opcoes--ceu .calc-op:hover{
    background:var(--quente); border-color:var(--quente); color:#111;
    box-shadow:0 16px 34px -14px rgba(10,25,45,.62);
  }
  .calc-opcoes--ceu .calc-op:hover small{ color:rgba(17,17,17,.76); }
}
/* o pé volta ao branco com sombra, como o resto do texto que vive sobre a fotografia */
.calc-pe--ceu{
  justify-content:center; text-align:center;
  border-top:0; padding-top:0;
  flex-direction:column; align-items:center;
  gap:clamp(14px,1.8vw,20px);
}
/* ⚠️ 27-ago-2026 — o mesmo defeito da lede, e a mesma cura. Estes dois textos vivem sobre
   nuvens com sombras LARGAS (26px no escape, 14px na nota): um desfoque desses segura um H1
   grosso, mas a 12,5 e 13,5px espalha-se e não faz aresta nenhuma — sobre o fotograma claro
   das nuvens, ao desktop, o rótulo do AI Act quase não se lia. Passa a receita já validada
   na lede: núcleo opaco de 2px colado à letra, mais dois halos a segurar o resto.
   E a nota perde o `.92` de opacidade — diluir branco sobre branco não ajuda ninguém. */
.calc-pe--ceu .calc-escape{
  text-shadow:
    0 1px 2px rgba(8,26,48,.92),
    0 0 7px rgba(8,26,48,.78),
    0 1px 22px rgba(8,26,48,.5);
}
.calc-pe--ceu .calc-nota{
  color:#fff;
  text-shadow:
    0 1px 2px rgba(8,26,48,.92),
    0 0 7px rgba(8,26,48,.78),
    0 1px 22px rgba(8,26,48,.5);
  max-width:58ch;
}
/* sem o cartão de conversa, o palco só leva os dois contactos: centram-se */
.fim-palco--so-contactos{ grid-template-columns:1fr; justify-items:center; margin-top:clamp(18px,2.4vw,28px); }
.fim-palco--so-contactos > .fim-contactos{ grid-column:1; justify-self:center; flex-direction:row; gap:clamp(22px,3vw,38px); }


@media (max-width:860px){
  .sec-calc{ padding:clamp(52px,7vh,76px) 0 clamp(54px,7.5vh,82px); }
  .calc-placa{ padding:clamp(28px,7vw,36px) clamp(22px,5.6vw,30px) 0; }
  .calc-copy{ grid-template-columns:1fr; gap:clamp(16px,3.4vh,22px); align-items:start; }
  .calc-tit{ font-size:var(--t-titulo-mob); max-width:100%; padding-left:12px; }
  .calc-lede{ max-width:100%; font-size:15px; padding-bottom:0; }
  /* ⚠️ A 375 px seis pastilhas a embrulhar davam quatro filas esfarrapadas e alvos de
     larguras diferentes. Grelha de duas colunas, altura igual, e a última a ocupar a linha. */
  .calc-opcoes{ display:grid; grid-template-columns:1fr 1fr; gap:9px; margin:22px 0 20px; }
  .calc-op{
    display:flex; flex-wrap:wrap; align-items:center; align-content:center;
    gap:0 7px; min-height:52px; padding:11px 15px;
    font-size:15px; white-space:normal;
  }
  .calc-op small{ flex-basis:100%; margin-top:2px; }
  .calc-op--largo{ grid-column:1 / -1; }
  .calc-pe{ flex-direction:column; align-items:flex-start; gap:11px; padding:15px 0 22px; }
  /* na versão do céu tudo está centrado; sem isto o «É outra coisa» ficava encostado à
     esquerda com a nota centrada por baixo, e lia-se como dois blocos desalinhados. */
  .calc-pe--ceu{ align-items:center; text-align:center; }
  .calc-opcoes--ceu .calc-op{ justify-content:center; text-align:center; }
  /* ⚠️ Com nomes curtos são CINCO numa grelha de duas colunas, portanto o último fica sempre
     órfão: sozinho na terceira fila, a meia largura, encostado à esquerda. Ocupa a linha toda
     e a grelha fecha (2 · 2 · 1 larga). E as pastilhas passam a preencher a célula: com texto
     de comprimentos diferentes, `inline-flex` deixava-as com larguras desencontradas dentro
     de células iguais, que é o desalinho que se vê antes de se perceber porquê. */
  .calc-opcoes--ceu .calc-op{ width:100%; }
  .calc-opcoes--ceu .calc-op:last-child{ grid-column:1 / -1; }
}
@media (prefers-reduced-motion:reduce){
  .calc-op{ transition:none; }
  .calc-op:hover{ transform:none; }
}


/* A intro não largou o body a tempo (ver o watchdog no index.html): a página tem de ficar
   utilizável na mesma — com scroll, com navbar clicável e com o botão do hero à vista. */
body[data-intro-falhou] .nav{ opacity:1; pointer-events:auto; }
body[data-intro-falhou] .hero-acoes{ opacity:1; transform:none; }
/* ⚠️ 27-ago: acender a navbar não chegava. A `.nav` nasce com `color:var(--tinta)` e o hero
   da home é céu claro — os links, o telefone e o menu ficavam a PRETO por cima das nuvens,
   quase ilegíveis. É o mesmo caso das páginas com hero de fundo, que usam `.nav--ceu`.
   Enquanto a navbar não é sólida (topo do hero), veste o branco; ao ganhar a pílula com o
   scroll, volta à tinta. */
body[data-intro-falhou] .nav:not(.nav--solida){ color:#fff; }
body[data-intro-falhou] .nav:not(.nav--solida) .nav-idioma{ border-color:rgba(255,255,255,.34); }
body[data-intro-falhou] .nav:not(.nav--solida) .nav-idioma-on{ background:rgba(255,255,255,.92); color:var(--tinta); }
body[data-intro-falhou] .nav:not(.nav--solida) .nav-idioma-off{ color:#fff; }


/* O «Pedir orçamento» dentro do menu do telemóvel. Faltava em todas as páginas: o hambúrguer
   É o menu abaixo dos 860 px, e o CTA principal do site não estava lá dentro. */
.nav-movel-orc{
  width:100%;
  margin:4px 0 2px;
  justify-content:center;
  font-size:var(--t-corpo-lg);
}
/* o `.nav-movel a` genérico pinta-o de tinta e tira-lhe o fundo — o CTA tem de ganhar */
.nav-movel a.nav-movel-orc{ color:var(--tinta); padding:12px 16px; text-align:center; }

/* O botão de pedir orçamento no cabeçalho da página de contactos. */
.ct-cab-acao{ margin:clamp(20px,2.4vw,28px) 0 0; }

/* ============================================================
   O LANÇADOR VOLTA A SER BOLA — 28-ago-2026
   ============================================================
   Decisão dele: «o que é que achas de mudarmos o design do chatbot para ser tipo normal?
   Deixamos apenas aquele [campo] escrito no hero. No telemóvel ocupa bué espaço e fica bué
   feio. E já gerou alguns bugs, e continua a gerar.»

   Ele tem razão, e a caixa larga foi ideia da casa, não dele. O rasto que deixou em quatro
   dias: apareceu por cima do hero; ficou acesa por trás do painel aberto em 17 páginas
   (guerra de especificidade com `:has()`); o menu só lhe apagava o disco e não a caixa;
   entrou sem gesto nenhum porque os keyframes só correm à nascença; e obrigou a inventar a
   etiqueta «Resposta imediata» para justificar a largura. Cinco correções para um elemento
   cujo trabalho é estar quieto num canto.
   A razão de fundo é a que ele deu no primeiro dia: **o hero JÁ é a caixa de texto**. Duas
   caixas a pedir a mesma coisa é redundância, e no telemóvel a de baixo tapava a morada do
   rodapé (visto em screenshot, não deduzido).

   ⚠️ Isto é CSS e só CSS. O `<form>` com o `<input>` continua no HTML das 15 páginas e o
   JS não muda: assim volta-se atrás numa linha se ele mudar de ideias, e não há 15 ficheiros
   a re-editar. O `.clima-semente` fica `display:none` — com o contentor já sem largura, um
   campo escondido não é alcançável nem por teclado.

   ⚠️ O GLIFO MUDA, e é de propósito. Um disco laranja com uma SETA no canto inferior direito
   é, na esmagadora maioria dos sites, o botão de «voltar ao topo». Dentro da caixa a seta
   lia-se como «enviar» porque tinha um campo à esquerda; sozinha, passa a mentir. Entra um
   balão de conversa, por `mask` de um SVG embutido — herda a cor do botão e continua sem
   tocar no HTML. O `aria-label` do botão já diz «Falar com o Clima», portanto o leitor de
   ecrã nunca dependeu do desenho. */
.clima-launch{
  width:auto; padding:0; border-radius:50%;
  background:transparent; box-shadow:none;
}
.clima-launch::before{ content:none; }        /* a etiqueta «Resposta imediata» sai com a caixa */
.clima-launch:focus-within{ box-shadow:none; }  /* o anel de foco passa a ser do botão */
.clima-semente{ display:none; }
.clima-bola{
  width:56px; height:56px; font-size:0;
  box-shadow:0 14px 34px -14px rgba(10,25,45,.6), 0 2px 8px rgba(10,25,45,.18);
}
.clima-bola > span{ display:none; }           /* a seta do HTML, que agora mentiria */
/* ⚠️ O seletor leva o `.clima-launch` à frente de propósito: pesa (0,2,1) e assim BATE a
   `.clima-bola.respira::after{ content:none }` da linha ~2275, que tem o mesmo peso mas vem
   antes. Com o `.clima-bola::after` simples (0,1,1) a regra da respiração ganhava e o
   `content` ficava `none` — a bola aparecia laranja e VAZIA, sem erro nenhum na consola.
   É a mesma armadilha da guerra de `:has()` que já se pagou neste ficheiro: neste sítio
   nunca basta escrever a regra depois, tem de se lhe dar o peso. */
.clima-launch .clima-bola::after{
  /* 🔴 O `data:` URI TEM de vir percent-encoded. Com os `<`, `>` e espacos em cru o `url()`
     parte-se em silencio: nao ha erro na consola, a mascara fica vazia e o resultado e uma
     bola laranja SEM icone nenhum — foi exactamente o que apareceu no primeiro deploy. */
  content:""; width:25px; height:25px;
  background:currentColor;
  -webkit-mask:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M12%203C6.9%203%203%206.5%203%2010.8c0%202.4%201.2%204.5%203.2%205.9v3.6l3.3-1.8c.8.2%201.6.3%202.5.3%205.1%200%209-3.5%209-7.8S17.1%203%2012%203z'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M12%203C6.9%203%203%206.5%203%2010.8c0%202.4%201.2%204.5%203.2%205.9v3.6l3.3-1.8c.8.2%201.6.3%202.5.3%205.1%200%209-3.5%209-7.8S17.1%203%2012%203z'/%3E%3C/svg%3E") center/contain no-repeat;
}
.clima-bola:focus-visible{ outline:2px solid var(--tinta); outline-offset:3px; }
@media (max-width:860px){
  /* o bloco do telemóvel esticava a caixa de bordo a bordo (`left` E `right`): sem isto a
     bola ficava centrada a meio do ecrã em vez de ancorada ao canto. */
  .clima-launch{ left:auto; right:16px; bottom:16px; width:auto; }
}

/* ============================================================
   O CTA DO HERO NO TELEMÓVEL — 28-ago-2026
   ============================================================
   Duas queixas dele que eu andei a medir MAL, e vale a pena dizer como, para não repetir:

   1) «o CTA continua bué grande, o COMPRIMENTO tá bué grande». Comprimento = LARGURA.
      Andei rondas a medir a ALTURA (113px → 56px) e a responder-lhe que estava feito.
      Nunca era disso que ele falava: a caixa media 345px, ou seja 92% da largura de um
      ecrã de 375. Passa a ter um teto e a ficar centrada.

   2) «a seta tá desalinhada, tá em baixo em vez de estar no meio». Eu media o CÍRCULO
      dentro da caixa e dava 0,0px de desvio — e estava certo, e era irrelevante. O que
      ele vê é o GLIFO dentro do círculo. O `→` é texto: a tinta assenta perto da linha
      de base, e numa caixa de linha de 19px mede 16,4 × 19,0 — fica visualmente abaixo
      do centro por mais centrado que o botão esteja. É tipografia, não geometria, e
      nenhum `place-items:center` a corrige.
      🔴 REGRA: um ícone dentro de um disco não se faz com um caractere. Faz-se com
      desenho, que tem centro geométrico. Aqui vai por máscara SVG, como na bola do Clima.
      O `data:` URI vai percent-encoded — em cru o `url()` parte-se em silêncio.
      ⚠️ O seletor leva o `.hero-pedido-caixa` à frente para pesar (0,2,1) e bater a regra
      original do bloco do telemóvel, que tem o mesmo peso mas vem antes. */
@media (max-width:860px){
  .hero-pedido-caixa{
    max-width:300px;          /* era 345px, 92% do ecrã */
    margin-left:auto; margin-right:auto;
  }
  .hero-pedido-caixa .hero-pedido-btn::after{
    content:""; display:block;
    width:20px; height:20px;
    background:currentColor;
    -webkit-mask:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M4.5%2012h15M13.5%206l6%206-6%206'%20fill='none'%20stroke='black'%20stroke-width='2.4'%20stroke-linecap='round'%20stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat;
    mask:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M4.5%2012h15M13.5%206l6%206-6%206'%20fill='none'%20stroke='black'%20stroke-width='2.4'%20stroke-linecap='round'%20stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat;
  }
}

/* ============================================================
   A PONTE DOS BTU — 28-ago-2026
   ============================================================
   Uma faixa curta entre o método e o AVAC. É de propósito a secção mais BAIXA da página:
   não é um destino, é uma porta que se abre de passagem. Se ganhasse altura de secção
   inteira passava a competir com o método e com o AVAC, que são o conteúdo a sério.
   Fundo `--nuvem` para se separar do que vem antes e depois sem introduzir cor nova.
   ⚠️ `position:relative` + `z-index:1` obrigatórios: sem eles a camada fixa `.ceu`
   engole a secção. Já aconteceu com a `.sec-faq`, com a `.sv-cinco` e com a banda de
   marcas do /sobre — é a armadilha mais repetida deste ficheiro. */
.sec-btu{
  position:relative; z-index:1;
  /* 28-ago-2026, ordem dele: «mete com o fundo azul» e «tira os traços, estão dois traços
     ali». Os traços eram o `border-top` e o `border-bottom` que separavam a faixa do que
     vinha antes e depois — com o azul deixam de fazer falta, porque a cor já separa.
     O azul é o `--azul` da casa, a cor principal deste site (é um céu), não uma cor nova. */
  /* ⚠️ 28-ago: «o azul que meteste era para ser um azul ESCURO, não esse azul». O
     `--azul` (#1F78D0) é a cor de link e foco desta casa — vivo, feito para 14px de
     texto, não para encher uma faixa inteira. Aqui entra o azul de céu profundo, que
     assenta entre o `--azul` e a `--tinta` (#122430) e não introduz cor nova nenhuma. */
  background:#103C67;
  color:#fff;
  padding:clamp(34px,5vw,54px) 0;
}
.sec-btu h2{ color:#fff; }
.sec-btu p{ color:rgba(255,255,255,.84); }
.sec-btu-inner{
  display:flex; align-items:center; justify-content:space-between;
  gap:clamp(18px,3vw,44px); flex-wrap:wrap;
}
.sec-btu h2{
  margin:0 0 6px; font-size:clamp(21px,2.5vw,30px); line-height:1.15; letter-spacing:-.02em;
}
.sec-btu-txt{ flex:1 1 min(520px,100%); }
.sec-btu p{ margin:0; font-size:var(--t-corpo); max-width:46ch; }
.sec-btu-accoes{ display:flex; align-items:center; gap:clamp(12px,2vw,20px); flex-wrap:wrap; }
@media (max-width:860px){
  /* no telemóvel empilha e a acção fica em baixo, larga o suficiente para o polegar */
  .sec-btu-inner{ flex-direction:column; align-items:flex-start; gap:18px; }
  .sec-btu-accoes{ width:100%; }
  .sec-btu .btn-cta{ flex:1 1 auto; text-align:center; }
}

/* ⚠️ Ajuste ÓPTICO da bola do Clima, não geométrico: o balão está centrado a régua, mas a
   cauda cai para baixo-esquerda e puxa a massa do desenho para esse lado. Um pixel para a
   direita e um para cima devolve o centro ao olho. É o mesmo princípio de um triângulo de
   «play» dentro de um círculo, que nunca se centra pela caixa. */
.clima-launch .clima-bola::after{ transform:translate(1px,-1px); }

/* ============================================================
   O VIDRO DA BARRA SAI NO TELEMÓVEL — 28-ago-2026
   ============================================================
   Queixa dele, repetida: «o site está a travar bué a descer, no telemóvel».

   O que está MEDIDO e é facto:
     · em repouso, no hero, o site custa 2,0% de CPU (÷4). Parado não queima nada.
     · a rolar as três primeiras secções custa ~23%, e a repartição é layout 0,1%,
       estilo 5,6%, script 1,2% — sobram ~16% que não são nenhum dos três. Isso é
       PINTURA e composição.

   ⚠️ O que NÃO está provado: qual dos pintores é o caro. Tentei isolar por cenários e os
   números desta máquina são inúteis — duas corridas da MESMA configuração deram 12,2% e
   23,3%, e o cenário «sem backdrop-filter» deu pior que a base, o que é impossível. Com
   ruído maior que o sinal não se conclui nada, e fica dito em vez de inventado.

   O que se faz mesmo assim, e porquê: `backdrop-filter: blur(18px) saturate(1.5)
   brightness(1.12)` numa barra FIXA por cima de um vídeo em movimento é o caso mais caro
   que este efeito tem — obriga a refiltrar a região a cada fotograma, e não há cache
   possível porque o que está por baixo muda sempre. É a causa nº1 conhecida de scroll a
   arrastar em telemóvel. No telemóvel a barra já é 84% opaca: sobe-se para 96% e o vidro
   sai. A diferença a olho é mínima; a diferença para o compositor é uma camada filtrada a
   menos por fotograma.
   No computador FICA: há potência de sobra e o vidro é parte da cara do site.
   👉 A confirmação tem de vir do telemóvel dele. Esta máquina não a pode dar. */
@media (max-width:860px){
  /* 🔴 O SELETOR É `.nav--solida` E NÃO `.nav`. Escrito como `.nav`, este bloco pintava a
     barra de branco TAMBÉM no estado transparente — o que ela é sobre o hero da /servicos,
     onde a marca «RM» e os links são BRANCOS. Resultado: branco sobre branco, a marca
     desaparecia. Queixa dele à letra: «na secção de serviços, quando estou no topo, o RM e
     a navbar ficam brancas». A barra só ganha fundo quando ganha a classe `--solida`; um
     override de fundo tem de viver dentro dessa condição, nunca acima dela. */
  .nav--solida{
    backdrop-filter:none; -webkit-backdrop-filter:none;
    background:rgba(247,250,252,.96);
  }
}

/* ============================================================
   O ENVIAR DEIXA DE SER UM PONTO AZUL — 28-ago-2026
   ============================================================
   🔴 Apanhado num screenshot da gaveta no telemóvel: o botão de enviar era um `.chat-send`
   branco com um `.chat-send-ponto` de `background:#1F78D0` lá dentro — literalmente uma
   BOLA AZUL, que é das poucas coisas explicitamente banidas deste site (a mesma razão que
   tirou os pontos de estado). Passou despercebido porque na /contactos já tinha sido
   substituído por uma seta em fevereiro, mas a gaveta da home nunca foi tocada — a mesma
   classe, dois destinos, e só um corrigido.
   Fica igual ao resto da casa: disco laranja com a seta DESENHADA (máscara SVG), nunca o
   caractere `→`, que assenta na linha de base e cai abaixo do centro do disco.
   O `data:` URI vai percent-encoded: em cru o `url()` parte-se sem dar erro. */
.chat-send{
  background:var(--quente); border:0;
  display:grid; place-items:center; cursor:pointer;
}
.chat-send .chat-send-ponto{
  background:var(--tinta);
  width:18px; height:18px; border-radius:0;
  -webkit-mask:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M4.5%2012h15M13.5%206l6%206-6%206'%20fill='none'%20stroke='black'%20stroke-width='2.4'%20stroke-linecap='round'%20stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M4.5%2012h15M13.5%206l6%206-6%206'%20fill='none'%20stroke='black'%20stroke-width='2.4'%20stroke-linecap='round'%20stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat;
}

/* ============================================================
   A SETA DO HERO, A CAUSA A SÉRIO — 28-ago-2026
   ============================================================
   🔴 Terceira volta nisto, e as duas primeiras falharam por eu medir a coisa errada.
   Medi o CÍRCULO dentro da caixa (0,0px, certo e irrelevante). Depois troquei o glifo por
   desenho, porque um `→` de texto assenta na linha de base. Continuava torto. A causa real,
   vista só ao ampliar 4× o que ELE vê:

   O `.hero-pedido-btn` é `display:grid; place-items:center` e tem lá dentro DUAS coisas:
   o texto «Pedir orçamento» (escondido com `font-size:0`) e o `::after` com a seta.
   `font-size:0` põe o texto a zero de altura mas NÃO o tira da grelha — ele continua a
   ocupar a sua célula. Com duas células empilhadas, o `place-items:center` centra CADA UMA
   na sua linha, e a seta, que é a de baixo, cai abaixo do centro do círculo. Medido: ~4,5px
   em baixo e ~2,5px à direita, num círculo de 44px. É perfeitamente visível, e ele viu-o
   três vezes enquanto eu respondia que estava centrado.

   🔴 REGRA: `font-size:0` esconde texto, não o remove do layout. Num contentor de grelha ou
   flex, o texto escondido continua a ser um item e continua a empurrar os outros. Para
   centrar mesmo, o ícone sai do fluxo — `position:absolute` com `inset:0; margin:auto`, que
   centra contra a CAIXA e não contra os irmãos.
   (A segunda meia-verdade: o desenho também não estava centrado no seu viewBox — ia de 2,8 a
   20,2 em 24, centro 11,5. Corrigido para 3,3–20,7, centro 12. Vale meio pixel, mas os meios
   pixéis somam-se aos 2,5.) */
.hero-pedido-caixa .hero-pedido-btn{ position:relative; }
.hero-pedido-caixa .hero-pedido-btn::after{
  position:absolute; inset:0; margin:auto;
}

/* ============================================================
   MEGA-MENU — «Serviços» e «Onde trabalhamos» na navbar.
   Maqueta aprovada por ele a 29-ago (lab/navbar.html); a marcação é escrita pelo
   scripts/navbar.mjs a partir do /servicos e das zonas, e o comportamento vive no
   js/navbar.js. Aqui só a cara.

   ⚠️ Prefixo `mg-` nos filhos (mg-cartao, mg-solucao, mg-concelhos). A maqueta chamava-lhes
   `.cartao`, `.solucao` e `.concelhos` — nomes genéricos que num ficheiro partilhado por 46
   páginas iam colidir com o primeiro componente que tivesse a mesma ideia. As classes de
   estrutura (`.mega`, `.mega-cel`, `.mega-painel`) ficaram como estavam: são só do menu.
   ============================================================ */

/* os dois links que abrem painel. Herdam o resto de `.nav-links > a`. */
.nav-abre{ display:inline-flex; align-items:center; gap:7px; }
.nav-abre[aria-expanded="true"]{ background:rgba(18,36,48,.06); color:var(--azul); }
.mg-seta{
  width:9px; height:9px;
  border-right:1.6px solid currentColor; border-bottom:1.6px solid currentColor;
  transform:translateY(-2px) rotate(45deg);
  transition:transform .3s var(--ease);
  opacity:.5;
}
.nav-abre[aria-expanded="true"] .mg-seta{ transform:translateY(1px) rotate(-135deg); opacity:1; }

/* 🔴 O PAINEL ALINHA-SE PELA ESQUERDA DA BARRA E MEDE-SE PELO CONTEÚDO.
   A primeira versão era centrada e sempre com 1240px, e viu-se logo na primeira
   renderização porque estava mal: nove concelhos numa caixa dessas ficam a boiar, com
   buracos enormes entre as colunas e um quarto do painel vazio. Um menu não é um cartaz —
   encosta-se ao que o abriu e ocupa o que precisa. Daí a largura por menu. */
.mega{
  position:fixed; top:78px; left:calc(50% - min(94vw,1240px)/2);
  transform:translateY(-8px);
  z-index:59;
  background:#fff; border-radius:26px;
  box-shadow:0 26px 70px rgba(15,35,65,.20), 0 1px 0 rgba(255,255,255,.8) inset;
  padding:10px;
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity .3s var(--ease), transform .38s var(--ease), visibility 0s .38s;
}
.mega.aberto{
  opacity:1; visibility:visible; pointer-events:auto;
  transform:translateY(0); transition-delay:0s;
}
#megaServicos{ width:min(94vw,1240px); }
#megaZonas{ width:min(94vw,780px); }

/* o primeiro passo: a fila de células que escolhe.
   ⚠️ `flex:0 0 auto` e não `flex:1`: com 1fr cada, a célula escolhida virava uma barra azul
   de meio painel e lia-se como um campo de formulário, não como uma escolha. */
.mega-fila{ display:flex; gap:4px; padding:6px 6px 2px; }
.mega-cel{
  flex:0 0 auto; text-align:left; font:inherit; cursor:pointer;
  text-decoration:none; /* ⚠️ passaram de <button> a <a> e vieram sublinhadas de origem */
  background:none; border:0; border-radius:18px;
  padding:16px 20px;
  display:flex; align-items:baseline; gap:10px;
  color:var(--tinta-60);
  transition:background .28s var(--ease), color .28s var(--ease);
}
.mega-cel b{ font-weight:500; font-size:16.5px; color:inherit; }
.mega-cel i{ font-style:normal; font-size:12.5px; color:var(--tinta-40); }
.mega-cel:hover{ background:rgba(18,36,48,.045); color:var(--tinta); }
.mega-cel[aria-current="true"]{ background:rgba(31,120,208,.09); color:var(--tinta); }
.mega-cel[aria-current="true"] b{ color:var(--azul-escuro); }

/* o segundo passo: o que aparece por baixo.
   🔴 A TROCA É UM CRUZAMENTO, NÃO UM CORTE. A primeira versão fazia `display:none` para
   `block` com um keyframe a subir, e ele viu logo: «a brutalidade é muito forte». Um
   `display` que muda não tem meio-termo — o painel antigo desaparece num frame e o novo
   salta para o lugar, e a caixa toda muda de altura ao mesmo tempo. Passaram a coexistir em
   camadas: o antigo desvanece enquanto o novo aparece, e a ALTURA é animada à parte (o JS
   mede o painel que entra). Três coisas suaves em vez de um estalo. */
.mega-corpo{
  position:relative; overflow:hidden;
  margin:2px 10px 0;
  transition:height .52s var(--ease);
}
.mega-painel{
  position:absolute; top:0; left:0; width:100%;
  padding-bottom:14px;
  opacity:0; transform:translateY(9px);
  pointer-events:none;
  transition:opacity .30s var(--ease), transform .52s var(--ease);
}
.mega-painel.on{ opacity:1; transform:none; pointer-events:auto; }

/* os serviços: fotografia com o nome lá dentro, como o leque da home.
   `auto-fit` e não um número fixo de colunas: eram quatro de manhã e são seis à tarde. */
.mg-cartoes{ display:grid; grid-template-columns:repeat(auto-fit,minmax(0,1fr)); gap:12px; }
.mg-cartao{
  position:relative; display:block; text-decoration:none; color:#fff;
  aspect-ratio:4/3.1; border-radius:18px; overflow:hidden; background:#0f2233;
}
/* 🔴 O PAINEL DOS ACOMPANHAMENTOS SÃO DOIS CARTÕES NUMA GRELHA FEITA PARA SEIS.
   A `.mg-cartoes` é `auto-fit` com `aspect-ratio:4/3.1`: com seis filhos dá cartões
   de 190x147, com dois dá 594x460 — mais do TRIPLO da altura. Medido a 1440: o
   menu saltava de 299px para 612px de altura só por se passar o rato na terceira
   célula, e os dois complementos ficavam a gritar mais alto que os seis serviços,
   que é o contrário da ordem que eles têm na página.
   A largura mantém-se (dois cartões deitados, como a faixa da própria página); o
   que se trava é a ALTURA, para bater certo com a fila de serviços do lado.
   ⚠️ Isto vive no site.css e não no complementos.css de propósito: o menu está em
   164 páginas e o complementos.css só carrega nas que têm a faixa. */
#mgAcomp .mg-cartao{ aspect-ratio:auto; height:clamp(132px,10.5vw,160px); }

.mg-cartao img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; transition:transform .8s var(--ease); }
.mg-cartao:hover img{ transform:scale(1.05); }
.mg-cartao span{
  position:absolute; inset:auto 0 0 0; padding:16px 16px 15px; z-index:1;
  font-size:15.5px; font-weight:500; line-height:1.25; text-shadow:var(--sombra-texto);
  background:linear-gradient(180deg,rgba(14,34,60,0) 0%,rgba(14,34,60,.62) 62%,rgba(14,34,60,.82) 100%);
}

/* as soluções: o MESMO cartão, em ponto mais pequeno. Ordem dele: «no que fazemos temos os
   cartões com a escrita lá dentro; gostava que fizesses o mesmo para as soluções».
   ⚠️ A primeira versão tinha miniatura de 40px e três colunas, e as duas coisas estavam mal
   — só se viu renderizado: a 40px a fotografia é lama (não se distingue um hotel de um
   ginásio, e então para que serve?), e três colunas num painel de 1240px deixam buracos de
   170px. Cinco enchem a largura.
   ⚠️ 3/2 e não 4/3: são dez e não quatro, e com o cartão mais alto o painel passava dos
   600px — o «menu muito grande» que ele queria evitar. O recorte é por altura, não por gosto. */
.mg-solucoes{ display:grid; grid-template-columns:repeat(5,1fr); gap:11px; }
.mg-solucao{
  position:relative; display:block; text-decoration:none; color:#fff;
  aspect-ratio:3/2; border-radius:15px; overflow:hidden; background:#0f2233;
}
.mg-solucao img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; transition:transform .8s var(--ease); }
.mg-solucao:hover img{ transform:scale(1.06); }
.mg-solucao span{
  position:absolute; inset:auto 0 0 0; padding:13px 13px 12px; z-index:1;
  font-size:14.5px; font-weight:500; line-height:1.25; text-shadow:var(--sombra-texto);
  background:linear-gradient(180deg,rgba(14,34,60,0) 0%,rgba(14,34,60,.60) 58%,rgba(14,34,60,.84) 100%);
}

/* os concelhos: só texto, três por coluna, encostado à esquerda.
   Sem imagem de propósito — aqui procura-se uma palavra, e procura-se com os olhos a saltar.
   Vinte e quatro fotografias de céu não distinguiriam Loures de Odivelas. */
.mg-concelhos{
  display:grid; grid-template-rows:repeat(3,auto); grid-auto-flow:column;
  grid-auto-columns:minmax(0,206px); justify-content:start; gap:2px 6px;
}
.mg-concelhos a{
  display:block; text-decoration:none; color:var(--tinta);
  font-size:15px; padding:8px 12px; border-radius:11px;
  transition:background .2s var(--ease), color .2s var(--ease);
}
.mg-concelhos a:hover{ background:rgba(18,36,48,.045); color:var(--azul-escuro); }

.mega-pe{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  margin-top:6px; padding:14px 22px 8px; border-top:1px solid var(--hairline);
  font-size:13.5px; color:var(--tinta-40);
}
.mega-pe a{ color:var(--azul-escuro); text-decoration:none; font-size:14.5px; }
.mega-pe a:hover{ text-decoration:underline; text-underline-offset:4px; }

/* Abaixo dos 1080px a `.nav-links` já está escondida e o menu é o do telemóvel — os painéis
   não têm por onde ser abertos, e um elemento invisível de 1240px à espera é peso e é risco
   de aparecer num scroll horizontal. `display:none` fecha o assunto.
   ⚠️ O caminho para a /zonas no telemóvel está no `.nav-movel`, que o scripts/navbar.mjs
   também escreve — sem ele, o telemóvel ficava sem porta nenhuma para as zonas. */
@media (max-width:1080px){ .mega{ display:none; } }
@media (prefers-reduced-motion: reduce){
  .mega, .mega-corpo, .mega-painel, .mg-cartao img, .mg-solucao img{ transition-duration:.01ms; }
}
