/* ==========================================================================
   Miguel Martins — Equipamentos Industriais
   Sistema de design conforme o Manual de Normas da marca.

   Paleta (Manual de Normas, pág. 6):
     COR PRINCIPAL    #19232A   Pantone 5395 C/U
     COR SECUNDÁRIA   #E6EEF0   Pantone 7541 C/U
     COR SECUNDÁRIA   #224F55   Pantone 2238 C/U
     COR SECUNDÁRIA   #5A9296   Pantone 5493 C/U

   Tipografia institucional: TASA Orbiter (pág. 7)
   Tipografia alternativa:   Arial / fonte de sistema (pág. 8)
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tipo de letra institucional (auto-alojado, licença OFL)
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "TASA Orbiter";
  src: url("../fonts/TASAOrbiter-Variable.ttf") format("truetype");
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   2. Tokens
   -------------------------------------------------------------------------- */
:root {
  /* Marca */
  --ink: #19232a;
  /* Mesma cor em componentes, para o escurecimento do cabeçalho da Striebig
     poder usar rgba() e acompanhar quando se troca de paleta. */
  --ink-rgb: 25, 35, 42;
  /* Realce de texto sobre fundos escuros. Aqui é o próprio tom médio; a
     paleta azul substitui-o por um mais claro, por causa do contraste. */
  --realce-escuro: #5a9296;
  --ink-90: #232f38;
  --ink-80: #33414c;
  --paper: #e6eef0;
  --paper-soft: #f2f7f8;
  --teal: #224f55;
  --teal-mid: #5a9296;
  --teal-deep: #16383d;
  --white: #ffffff;

  /* Neutros derivados */
  --muted: #5f6f79;
  --muted-2: #8a99a3;
  --line: #d5e0e4;
  --line-soft: #e7eef0;

  /* Fim de página — o rodapé real e o escuro que sobe por trás do cartão de
     contacto e passa pela newsletter. É um cinzento-ardósia e não a cor de
     tinta: a tinta é quase preta e fechava a página a martelo.

     O FADE VIVE SÓ NO RODAPÉ, de propósito. O escuro do fim são três peças
     empilhadas — o ::before do palco do contacto, a newsletter e o rodapé —
     e um gradiente em cada uma reiniciava três vezes, deixando uma costura
     visível em cada emenda. Assim as duas primeiras ficam lisas em --rodape e
     o gradiente arranca no rodapé exactamente nessa mesma cor: não há emenda
     nenhuma para ver, e a conta não depende da altura de peça nenhuma.

     Não é só da página inicial: o rodapé é o mesmo nas onze. */
  --rodape: #38404a;
  --rodape-baixo: #2b313a;
  /* Sobe de #93a7ad: sobre o ardósia aquele dava 4,19 e o mínimo é 4,5.
     Este dá 5,22 em cima e 6,50 no fundo do gradiente. */
  --rodape-texto: #a8bac0;
  /* A linha do copyright, um degrau mais apagada. O #6f8288 que aqui estava
     dava 3,99 sobre a tinta antiga — já chumbava antes de o rodapé mudar de
     cor, só se viu ao medir. Este dá 4,74 no ponto mais claro do gradiente. */
  --rodape-texto-fraco: #a0b1b7;

  /* Tipografia — TASA Orbiter nos títulos, Inter no texto corrido */
  --font-display: "TASA Orbiter", "Segoe UI", system-ui, sans-serif;
  --font-body: "Inter", system-ui, -apple-system, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;

  /* Escala fluida */
  --step--2: 0.76rem;
  --step--1: clamp(0.84rem, 0.81rem + 0.14vw, 0.92rem);
  --step-0: clamp(1rem, 0.97rem + 0.16vw, 1.08rem);
  --step-1: clamp(1.14rem, 1.07rem + 0.34vw, 1.35rem);
  --step-2: clamp(1.4rem, 1.26rem + 0.68vw, 1.85rem);
  --step-3: clamp(1.8rem, 1.53rem + 1.34vw, 2.7rem);
  --step-4: clamp(2.3rem, 1.8rem + 2.4vw, 3.9rem);
  --step-5: clamp(2.8rem, 2rem + 3.6vw, 5rem);

  /* Forma e espaço */
  --sidebar-w: 260px;
  /* O cabeçalho é a altura do logótipo mais 22px de folga em cima e em
     baixo. Amarrados assim, crescem juntos e a folga é sempre a mesma —
     dois clamp independentes acabavam por divergir e apertar o logótipo a
     certas larguras. 22px é a folga que o cabeçalho já tinha.
     A 1920 o logótipo passa de 34 para 44px (+29%) e o cabeçalho de 76 para
     88; ao telemóvel fica em 28px num cabeçalho de 72, um pouco mais baixo
     do que era. A razão do ficheiro é 6,263, por isso 44px de altura são
     276px de largura — cabem de sobra ao lado do botão do menu. */
  --logo-h: clamp(28px, 2.6vw, 44px);
  --head-h: calc(var(--logo-h) + 44px);
  /* Subiu de 1060px a 4 de Agosto de 2026: com a barra lateral a ocupar 260px,
     num ecrã de 1920 sobravam 1660px de espaço útil e o conteúdo parava nos
     1060, deixando 300px em branco de cada lado. Alargar não estica o texto —
     os blocos de leitura têm limite próprio em ch (.section-head 62ch,
     .prose 70ch, .page-head p 60ch, e os das marcas), por isso quem ganha são
     as grelhas, as fotografias e a vitrine. */
  --content-max: 1360px;
  --gutter: clamp(1.25rem, 4vw, 3.25rem);
  /* Cantos praticamente retos: a marca é geométrica e industrial.
     Botões são sempre retos (0); cartões e campos levam 2px só para não
     ficarem agressivos nas fotografias. */
  --radius: 2px;
  --radius-lg: 2px;

  --shadow-sm: 0 1px 2px rgba(25, 35, 42, 0.05), 0 2px 10px rgba(25, 35, 42, 0.05);
  --shadow: 0 14px 34px -16px rgba(25, 35, 42, 0.3);
  --shadow-lg: 0 36px 70px -30px rgba(25, 35, 42, 0.5);

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

/* Se a Inter não chegar a carregar, o texto cai para a fonte do sistema,
   que é a alternativa prevista no manual (pág. 8). */

/* --------------------------------------------------------------------------
   3. Reset / base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--head-h) + 16px);
  overflow-x: clip;
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.68;
  color: var(--ink);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
}

body.is-locked { overflow: hidden; }

img, svg, video, iframe { display: block; max-width: 100%; }
img, svg, video { height: auto; }

a { color: inherit; text-decoration: none; }
button, input, textarea, select { font: inherit; color: inherit; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.015em;
  margin: 0 0 0.55em;
  text-wrap: balance;
  color: var(--ink);
}
h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-2); }
h4 { font-size: var(--step-1); }

p { margin: 0 0 1.15em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

::selection { background: var(--teal); color: #fff; }

:focus-visible {
  outline: 3px solid var(--teal-mid);
  outline-offset: 3px;
  border-radius: 3px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 300;
  background: var(--teal);
  color: #fff;
  padding: 0.8rem 1.3rem;
  font-weight: 600;
}
.skip-link:focus { left: 0; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --------------------------------------------------------------------------
   4. Estrutura

   O site tem um só menu, em todas as páginas: barra lateral fixa que empurra o
   conteúdo, com o cabeçalho dentro da coluna. Secções 5 e 6. Cópia guardada em
   _backups/menu-striebig/.
   -------------------------------------------------------------------------- */
.shell {
  display: flex;
  align-items: flex-start;
  min-height: 100vh;
}

.content {
  flex: 1 1 auto;
  min-width: 0;
}

.wrap {
  width: 100%;
  max-width: var(--content-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: clamp(3rem, 7vw, 6rem); }
.section--tight { padding-block: clamp(2rem, 4vw, 3.25rem); }
.section--paper { background: var(--paper-soft); }
.section--ink { background: var(--ink); color: #c9d7db; }
.section--ink h2, .section--ink h3, .section--ink h4 { color: #fff; }
.section--teal { background: var(--teal); color: #cfe0e2; }
.section--teal h2, .section--teal h3 { color: #fff; }

.grid { display: grid; gap: clamp(1.1rem, 2.6vw, 2rem); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }

/* --------------------------------------------------------------------------
   5. MENU STRIEBIG — barra lateral
   -------------------------------------------------------------------------- */
.sidebar {
  position: sticky;
  top: 0;
  flex: 0 0 var(--sidebar-w);
  width: var(--sidebar-w);
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--white);
  /* Sombra em vez de filete, como no striebig.com (0 0 6px rgba(0,0,0,.5)) */
  box-shadow: 0 0 6px rgba(0, 0, 0, 0.5);
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Acima do cabeçalho (70) para a sombra chegar ao topo da página: em ecrã
     largo os dois não se sobrepõem, só a sombra é que entra por baixo dele. */
  z-index: 80;
  transition: margin-left 0.3s var(--ease);
}

/* Recolhida: sai para fora e o conteúdo ocupa a largura toda. */
html.nav-closed .sidebar { margin-left: calc(var(--sidebar-w) * -1); }

/* Navegação em lista, no modelo do striebig.com: itens em maiúsculas
   separados por filetes finos, sem botões nem fundos. Ao passar o rato muda
   apenas a cor do texto. */
.sidebar__nav {
  padding: 1.4rem 0 1rem;
  flex: 1 1 auto;
}

/* Título de grupo — a negrito e em caixa normal, como no striebig.com.
   Todos os títulos e itens do menu ficam numa só linha (nowrap). */
.nav-group {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  width: 100%;
  margin: 0;
  padding: 0.55rem 1.5rem;
  font-family: var(--font-body);
  font-size: 0.94rem;
  font-weight: 700;
  line-height: 1.35;
  text-align: left;
  white-space: nowrap;
  color: var(--ink);
  background: none;
  border: 0;
}

/* Quando é um botão de abrir/fechar ou uma ligação */
button.nav-group,
a.nav-group { cursor: pointer; transition: color 0.18s var(--ease); }
button.nav-group:hover,
a.nav-group:hover { color: var(--teal-mid); }
a.nav-group[aria-current="page"] { color: var(--teal); }

/* Símbolo de abrir/fechar maior, na escala do striebig.com (caixa de 14x18) */
.nav-group .chev {
  flex-shrink: 0;
  width: 19px;
  height: 19px;
  stroke-width: 1.9;
  color: var(--ink-80);
  transition: transform 0.25s var(--ease), color 0.18s var(--ease);
}
button.nav-group:hover .chev { color: var(--teal-mid); }
button.nav-group[aria-expanded="true"] .chev { transform: rotate(180deg); }

.nav-block + .nav-block { margin-top: 1.6rem; }
.nav-block > .nav-list[hidden] { display: none; }

.nav-list { list-style: none; margin: 0.25rem 0 0; padding: 0; }

/* Traços entre itens mais marcados, como no striebig.com: 1px do tom de tinta
   a 18% em vez de um cinzento quase invisível. */
.nav-list > li { border-bottom: 1px solid rgba(25, 35, 42, 0.18); }
.nav-list > li:first-child { border-top: 1px solid rgba(25, 35, 42, 0.18); }

.nav-list > li > a {
  display: block;
  padding: 0.72rem 1.5rem;
  font-size: 0.83rem;
  font-weight: 400;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink);
  transition: color 0.18s var(--ease);
}
.nav-list > li > a:hover { color: var(--teal-mid); }
.nav-list > li > a[aria-current="page"] { color: var(--teal); font-weight: 600; }

/* Itens dos grupos que abrem e fecham: caixa normal, não maiúsculas */
.nav-list--sub > li > a {
  text-transform: none;
  letter-spacing: 0.01em;
  font-size: 0.86rem;
}

/* Bloco de contactos destacado, como o bloco cinzento da referência */
.sidebar__contact {
  padding: 1.15rem 1.5rem 1.3rem;
  background: var(--paper);
  font-size: 0.82rem;
  color: var(--muted);
}
.sidebar__contact a {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.32rem 0;
  color: var(--ink);
  transition: color 0.18s var(--ease);
}
.sidebar__contact a:hover { color: var(--teal); }
.sidebar__contact svg { flex-shrink: 0; color: var(--muted-2); }
.sidebar__contact a:hover svg { color: var(--teal); }

/* Escolha de idioma, no fim da barra lateral */
.sidebar__lang {
  padding: 1.25rem 1.5rem 1.9rem;
  border-top: 1px solid var(--line-soft);
}
.sidebar__lang h2 {
  margin: 0 0 0.7rem;
  font-family: var(--font-body);
  font-size: 0.94rem;
  font-weight: 700;
  letter-spacing: 0;
  color: var(--ink);
}
.lang-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem 1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.lang-list a {
  display: inline-block;
  padding-bottom: 2px;
  border-bottom: 2px solid transparent;
  font-size: 0.82rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  transition: color 0.18s var(--ease), border-color 0.18s var(--ease);
}
.lang-list a:hover { color: var(--teal-mid); }
.lang-list a[aria-current="true"] {
  color: var(--teal);
  font-weight: 700;
  border-bottom-color: var(--teal);
}
/* Idioma ainda sem páginas publicadas */
.lang-list a[aria-disabled="true"] {
  color: var(--muted-2);
  cursor: not-allowed;
  opacity: 0.65;
}
.lang-list a[aria-disabled="true"]:hover { color: var(--muted-2); }

/* Ligações secundárias, sem filetes */
.sidebar__minor {
  padding: 1.15rem 1.5rem 1.4rem;
  font-size: 0.82rem;
}
.sidebar__minor a {
  display: block;
  padding: 0.28rem 0;
  color: var(--muted);
  transition: color 0.18s var(--ease);
}
.sidebar__minor a:hover { color: var(--teal); }

/* --------------------------------------------------------------------------
   6. Barra superior (mobile / tablet)
   -------------------------------------------------------------------------- */
/* Cabeçalho permanente: acompanha o scroll, botão de abrir/fechar à esquerda,
   logótipo à direita. Fica dentro da coluna de conteúdo, por isso alarga
   quando a barra lateral é recolhida. */
.site-head {
  position: sticky;
  top: 0;
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  height: var(--head-h);
  /* O mesmo --gutter que o conteúdo da página usa, em vez de um valor só
     dele: a 1920 dá 52px de cada lado em vez de 28, e o logótipo deixa de
     ficar encostado ao bordo. Ficando ligado ao token, acompanha sozinho se
     o espaçamento do site mudar. */
  padding-inline: var(--gutter);
  background: #fff;
  border-bottom: 1px solid var(--line);
}

.site-head__logo { display: flex; align-items: center; }
.site-head__logo img {
  height: var(--logo-h);
  width: auto;
}

/* Ícone de menu de 4 traços que se transforma em cruz */
.menu-toggle {
  position: relative;
  flex-shrink: 0;
  width: 32px;
  height: 22px;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
}
.menu-toggle span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  background: var(--ink);
  transition: transform 0.3s var(--ease), top 0.3s var(--ease),
    width 0.2s var(--ease), left 0.2s var(--ease), background-color 0.2s var(--ease);
}
.menu-toggle span:nth-child(1) { top: 0; }
.menu-toggle span:nth-child(2),
.menu-toggle span:nth-child(3) { top: 10px; }
.menu-toggle span:nth-child(4) { top: 20px; }
.menu-toggle:hover span { background: var(--teal); }

.menu-toggle[aria-expanded="true"] span:nth-child(1),
.menu-toggle[aria-expanded="true"] span:nth-child(4) {
  top: 10px; left: 50%; width: 0;
}
.menu-toggle[aria-expanded="true"] span:nth-child(2) { transform: rotate(45deg); }
.menu-toggle[aria-expanded="true"] span:nth-child(3) { transform: rotate(-45deg); }

.sidebar__backdrop {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 55;
  background: rgba(25, 35, 42, 0.5);
  opacity: 0;
  transition: opacity 0.3s var(--ease);
}
.sidebar__backdrop.is-active { display: block; opacity: 1; }

/* Abaixo de 1100px a barra lateral sobrepõe-se em vez de empurrar */
@media (max-width: 1099px) {
  .sidebar {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    height: 100dvh;
    width: min(320px, 86vw);
    margin-left: 0;
    transform: none;
    box-shadow: var(--shadow-lg);
    transition: transform 0.32s var(--ease);
    /* Abaixo do cabeçalho outra vez: aqui a gaveta sobrepõe-se mesmo ao
       cabeçalho, e taparia o botão X que serve para a fechar. */
    z-index: 60;
  }
  html.nav-closed .sidebar { margin-left: 0; transform: translateX(-101%); }
}

/* --------------------------------------------------------------------------
   7. Botões
   -------------------------------------------------------------------------- */
/* Botões retos e sóbrios: sem cantos redondos, sem salto no hover, sem
   sombra colorida. Só duas famílias — cheio e contornado — em fundo claro
   e em fundo escuro. */
.btn {
  --bg: var(--ink);
  --fg: #fff;
  --bd: var(--ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  padding: 0.85rem 1.6rem;
  background: var(--bg);
  color: var(--fg);
  border: 1px solid var(--bd);
  border-radius: 0;
  font-family: var(--font-body);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease),
    border-color 0.2s var(--ease);
}
.btn:hover { --bg: var(--teal); --bd: var(--teal); }

/* Contornado, para fundo claro */
.btn--outline { --bg: transparent; --fg: var(--ink); --bd: var(--line); }
.btn--outline:hover { --bg: transparent; --fg: var(--teal); --bd: var(--teal); }

/* Cheio, para fundo escuro */
.btn--mid { --bg: #fff; --fg: var(--ink); --bd: #fff; }
.btn--mid:hover { --bg: var(--teal-mid); --fg: var(--ink); --bd: var(--teal-mid); }

/* Contornado, para fundo escuro */
.btn--light { --bg: transparent; --fg: #fff; --bd: rgba(255, 255, 255, 0.4); }
.btn--light:hover { --bg: transparent; --fg: var(--teal-mid); --bd: var(--teal-mid); }

.btn--sm { padding: 0.6rem 1.1rem; font-size: 0.73rem; }
.btn--block { display: flex; width: 100%; }

.btn-row { display: flex; flex-wrap: wrap; gap: 0.75rem 1.25rem; align-items: center; }

/* Ligação simples ao lado de um botão — telefones e emails não precisam de
   caixa. Herda a cor do contexto, claro ou escuro. */
.inline-link {
  font-size: 0.88rem;
  color: inherit;
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.inline-link:hover { color: var(--teal-mid); border-color: var(--teal-mid); }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-family: var(--font-body);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--teal);
}
.section--ink .link-arrow, .section--teal .link-arrow { color: var(--teal-mid); }
.link-arrow svg { transition: transform 0.25s var(--ease); }
.link-arrow:hover svg { transform: translateX(5px); }

/* --------------------------------------------------------------------------
   9. Cabeçalhos de secção
   -------------------------------------------------------------------------- */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin: 0 0 0.9rem;
  font-family: var(--font-body);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--teal);
}
.eyebrow::before { content: ""; width: 26px; height: 2px; background: currentColor; }
.section--ink .eyebrow, .section--teal .eyebrow { color: var(--teal-mid); }

.section-head { max-width: 62ch; margin-bottom: clamp(1.75rem, 4vw, 3rem); }

.lead { font-size: var(--step-1); line-height: 1.55; color: var(--muted); }
.section--ink .lead, .section--teal .lead { color: #a8bcc1; }

/* --------------------------------------------------------------------------
   10. Hero
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  background: var(--ink);
  color: #c9d7db;
  overflow: hidden;
  isolation: isolate;
}
.hero__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  object-fit: cover;
  width: 100%; height: 100%;
  opacity: 0.5;
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(100deg, rgba(25, 35, 42, 0.97) 25%, rgba(25, 35, 42, 0.6) 100%);
}

.hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: center;
  padding-block: clamp(3rem, 7vw, 6rem);
}
@media (max-width: 860px) {
  .hero__inner { grid-template-columns: 1fr; }
}

.hero h1 { color: #fff; font-size: var(--step-5); line-height: 0.98; }
.hero h1 em { font-style: normal; color: var(--teal-mid); display: block; }
.hero p { max-width: 52ch; }

.hero__badge {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.4rem 0.95rem 0.4rem 0.75rem;
  margin-bottom: 1.4rem;
  border-left: 2px solid var(--teal-mid);
  background: rgba(255, 255, 255, 0.06);
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #dceaed;
}
.hero__badge .dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--teal-mid);
  animation: pulse 2.4s infinite;
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(90, 146, 150, 0.65); }
  70%  { box-shadow: 0 0 0 9px rgba(90, 146, 150, 0); }
  100% { box-shadow: 0 0 0 0 rgba(90, 146, 150, 0); }
}

/* Elemento gráfico: linhas hexagonais do manual */
.hexlines {
  position: absolute;
  pointer-events: none;
  color: rgba(255, 255, 255, 0.13);
  z-index: -1;
}
.hexlines svg { width: 100%; height: auto; }
.hexlines--hero { top: -18%; right: -22%; width: min(760px, 78%); }

/* Pilha de materiais (madeira · plástico · metal) */
.stack {
  position: relative;
  display: grid;
  place-items: center;
  min-height: clamp(280px, 34vw, 430px);
}
.stack img {
  position: absolute;
  width: clamp(150px, 20vw, 250px);
  filter: drop-shadow(0 26px 34px rgba(0, 0, 0, 0.45));
  /* 4s e não os 7s de antes: a 7s a subida eram 12px em 3,5s — 3,4px por
     segundo, devagar de mais para se dar pelo movimento. A 4s com 15px a
     velocidade média passa a 7,5px/s, que já se lê como levitação sem ficar
     nervoso. As demoras ficaram nos mesmos segundos de propósito: num ciclo
     mais curto valem mais fase, as lajes afastam-se mais umas das outras e é
     isso que faz notar que se mexem. */
  animation: float 4s ease-in-out infinite;
}
.stack img:nth-child(1) { transform: translateY(-31%); animation-delay: 0s; }
.stack img:nth-child(2) { transform: translateY(0);     animation-delay: 0.5s; }
.stack img:nth-child(3) { transform: translateY(31%);   animation-delay: 1s; }

@keyframes float {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -15px; }
}

/* --------------------------------------------------------------------------
   10b. Página inicial — conceito claro, branco dominante
   -------------------------------------------------------------------------- */
/* Banda de imagem de ponta a ponta, com um retângulo de texto sobreposto */
.hero-shot {
  position: relative;
  /* Sem cor de fundo. Havia aqui um #f2f3f4 igual ao fundo liso gravado na
     fotografia antiga, para não se ver o rectângulo dela sobre a secção. As
     sete do slideshow são fotografias de ponta a ponta, sem fundo liso
     nenhum, por isso esse cinzento deixou de ter razão de ser — e o branco é
     o que o resto da página faz (PADRAO-DE-DESIGN.md, 4). */
  /* Sem folga em cima: o bloco de texto encosta ao cabeçalho. */
  padding-block: 0 clamp(0.75rem, 2vw, 1.75rem);
  /* Sem enchimento lateral: a fotografia toma a largura toda que o <main> lhe
     dá, de ponta a ponta, como faz o .st-hero da striebig.html. Havia aqui um
     padding-left de até 85px, de quando a fotografia era estreita e vivia numa
     margem branca. */
}
/* A faixa ocupa o bloco todo: sem max-width, a largura é a que houver.

   ONDE ISTO CUSTA ALGUMA COISA: acima dos ~1700px de janela a faixa fica mais
   larga do que os 1440 dos ficheiros e a fotografia é esticada — 1,14x a 1920.
   Não há como fugir: seis das sete fontes são verticais de 1440 de largura, e
   1440 é o máximo que delas se tira sem inventar detalhe. Abaixo disso não há
   ampliação nenhuma. */
.hero-shot__frame {
  position: relative;
  width: 100%;
}
.hero-shot img {
  display: block;
  width: 100%;
  height: auto;
}

/* --- O slideshow ---------------------------------------------------------
   Sete fotografias no mesmo sítio, a render-se umas às outras.

   EM ECRÃ ESTREITO (até 720px) A PRIMEIRA FICA EM FLUXO NORMAL e é ela que dá
   altura ao palco; as outras seis ficam por cima, em posição absoluta. Aí a
   fotografia aparece inteira, na razão dela, sem corte nenhum. Acima disso
   manda a altura fixa que está mais abaixo e as sete passam todas a
   absolutas. */
.hero-shot__palco { position: relative; }

.hero-shot__foto:not(:first-child) {
  position: absolute;
  inset: 0;
  height: 100%;
  object-fit: cover;
  opacity: 0;
}

/* A troca só existe depois de o initSlideshow() marcar o palco, e é essa
   marca que evita o piscar: entre o CSS ser lido e o JavaScript correr não há
   regra nenhuma a esconder a primeira fotografia, por isso ela está lá desde
   o princípio. Sem JavaScript a marca nunca chega e fica a primeira, que é
   exactamente o que aqui estava antes. */
.hero-shot__palco.is-pronto .hero-shot__foto {
  opacity: 0;
  /* 0,5s e esta curva são os do resto do site — ver PADRAO-DE-DESIGN.md, 10. */
  transition: opacity 0.5s cubic-bezier(0, 0, 0.2, 1);
}
.hero-shot__palco.is-pronto .hero-shot__foto.is-visivel { opacity: 1; }

/* --- Altura da faixa -----------------------------------------------------
   As mesmas medidas do .st-hero da striebig.html: clamp(430px, 70vh, 700px).
   Sem isto a altura saía da razão das fotografias e a faixa comia o ecrã
   todo — 933px dos 992 visíveis a 1920.

   721px E NÃO 720: é o par exacto do @media (max-width: 720px) lá em baixo,
   que é onde o rectângulo do título deixa de estar sobreposto e passa para
   debaixo da fotografia. Os dois têm de andar juntos, senão há uma largura em
   que a fotografia é cortada sem ter texto nenhum por cima a justificá-lo.

   ABAIXO DE 721 NÃO HÁ ALTURA FIXA, e isto é de propósito. Na striebig.html o
   cabeçalho estreito continua a ter altura (clamp(300px, 46vh, 420px)) porque
   o título vive lá dentro e precisa de sítio. Aqui o título sai para fora, e
   uma altura fixa só serviria para cortar a fotografia a troco de nada: a
   390px seriam 388px de altura para uma fotografia deitada, ou seja quase
   metade da largura dela deitada fora.

   O SELECTOR TEM DE TER DUAS CLASSES. O .hero-shot img lá em cima diz
   height: auto e vale (0,1,1); um .hero-shot__foto sozinho vale (0,1,0) e
   perdia, media query ou não. Com o palco à frente fica (0,2,0) e ganha. E
   como empata com o .hero-shot__foto:not(:first-child), tem de vir DEPOIS
   dele — que é onde está. */
@media (min-width: 721px) {
  .hero-shot__palco { height: clamp(430px, 70vh, 700px); }

  .hero-shot__palco .hero-shot__foto {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Encostado ao topo e não ao centro. O corte muda de sentido conforme a
       janela — a 1920 a faixa é mais larga do que a razão da fotografia e
       sobra altura, a 1280 é o contrário e sobra largura. Quando o que sobra
       é altura, centrar tirava ~86px por cima, e nas fotografias 2, 4 e 7 é
       exactamente aí que estão as cabeças. Em baixo o que se perde é chão,
       tampos e primeiro plano. Quando o que sobra é largura o "top" não faz
       nada e manda o "center", que é o que se quer. */
    object-position: center top;
  }
}

/* --- Os pontos -----------------------------------------------------------
   Por baixo da fotografia e encostados à direita, para equilibrarem o
   rectângulo teal que está em cima à esquerda. Ficam sobre o branco da página
   e não sobre a fotografia: assim o contraste é sempre o mesmo, não depende
   da imagem que calhar por baixo, e não é preciso pôr-lhes uma pastilha
   escura por trás.

   Vivem dentro da moldura, a seguir ao palco — é o que lhes dá a largura e o
   alinhamento de graça, sem terem de saber quanto ela mede. E não são tapados
   pelas fotografias porque quem serve de referência às absolutas é o palco,
   que fica acima deles. Quem os cria é o initSlideshow(). */
.hero-shot__pontos {
  display: flex;
  justify-content: flex-end;
  gap: 0.15rem;
  margin-top: 0.35rem;
  /* Agora que a fotografia vai de ponta a ponta, sem isto os pontos ficavam
     colados à beira da página. É a mesma folga lateral do resto do site. */
  padding-right: var(--gutter);
}

/* Mesma conta dos pontos do carrossel das novidades: a bolinha tem 10px mas o
   botão tem 28, porque quem manda no tamanho é o alvo do dedo. O ponto da
   fotografia em que se está estica em cápsula, para se ver onde se está sem
   ter de distinguir bem as cores. */
.hero-shot__ponto {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.hero-shot__ponto::before {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: 9999px;
  background: var(--line);
  transition: background-color 0.22s var(--ease), width 0.22s var(--ease);
}
.hero-shot__ponto:hover::before { background: var(--muted-2); }
.hero-shot__ponto[aria-current="true"]::before { width: 26px; background: var(--teal); }
.hero-shot__ponto:focus-visible {
  outline: 3px solid var(--teal-mid);
  outline-offset: 2px;
  border-radius: 9999px;
}

/* Posicionado sobre a secção e não sobre a moldura da imagem: assim encosta ao
   cabeçalho e avança para a esquerda, ocupando a margem branca. */
.hero-shot__tag {
  position: absolute;
  top: 0;
  /* Recuado da esquerda, como a caixa vermelha do striebig.com. A percentagem
     é da secção, não da fotografia — desde que a fotografia passou a ocupar a
     largura toda, o rectângulo assenta inteiro sobre ela em vez de meio na
     margem branca. */
  left: clamp(1rem, 10.3%, 7.5rem);
  max-width: min(80%, 25rem);
  padding: clamp(1rem, 2.2vw, 1.9rem) clamp(1.2rem, 2.6vw, 2.3rem);
  background: var(--teal);
  color: #fff;
}
.hero-shot__tag h1 {
  margin: 0;
  color: #fff;
  font-size: clamp(1.15rem, 0.8rem + 1.3vw, 2.05rem);
  line-height: 1.1;
  letter-spacing: 0;
  text-transform: uppercase;
  text-wrap: balance;
}
/* Em ecrãs estreitos a imagem fica baixa demais para aguentar o retângulo
   por cima — passa a ficar logo a seguir. */
@media (max-width: 720px) {
  .hero-shot__tag { position: static; max-width: none; }
}


/* Linhas hexagonais muito ténues, sobre o branco */
.hexlines--light { color: rgba(34, 79, 85, 0.09); }

/* Pilha de materiais com ar entre as lajes.
   Em fluxo normal (coluna) e não em posição absoluta: as lajes têm alturas
   diferentes e margens transparentes desiguais, por isso deslocá-las por
   percentagem da própria altura fazia-as sobrepor-se em vez de separar. */
.stack--airy {
  /* Chega ao tamanho máximo já por volta dos 1010px: acima disso as lajes
     ficam constantes e a legenda por baixo mantém sempre a mesma relação
     de largura com elas. */
  /* O topo é o que a coluna aguenta sem passar do botão "O que fazemos":
     a pilha cresce 2,67x a largura da laje. A frase devolvida por baixo do
     logótipo deu mais altura à coluna da esquerda e subiu este limite. */
  --laje: clamp(130px, 15vw, 200px);
  /* folga visual pretendida entre lajes, já descontadas as margens
     transparentes de cada PNG (ver as duas regras nth-child abaixo).
     Nunca negativa: as lajes não se sobrepõem. A zero ficam encostadas, que é
     o mínimo possível sem se cavalgarem.
     As duas fracções abaixo foram conferidas nos próprios PNG a 4 de Agosto de
     2026 e estão exactas: a margem transparente de baixo do metal (0,1175) com
     a de cima da madeira (0,045) dá os 0,1625, e a da madeira (0,0625) com a
     do plástico (0,1275) dá os 0,19. Por isso o que aqui se escrever é mesmo
     o espaço visível entre lajes, ao pixel. */
  --folga: 0px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0;
  min-height: 0;
  padding-block: 0;
  /* O metal.png tem 15,1% de margem transparente no topo, ou seja 0,1375 da
     largura da laje. Sem este puxão a primeira laje ficava abaixo do topo do
     logótipo, em vez de arrancar ao mesmo nível. */
  margin-top: calc(var(--laje) * -0.1375);
}
/* Cada PNG tem margens transparentes diferentes, por isso uma margem negativa
   igual para as duas juntas dava folgas visuais desiguais (eram 5px e 10px).
   Aqui desconta-se a margem de baixo de uma mais a de cima da seguinte, medidas
   no próprio ficheiro, e sobra exatamente --folga em ambas. */
.stack--airy img:nth-child(2) { margin-top: calc(var(--folga) - var(--laje) * 0.1625); }
.stack--airy img:nth-child(3) { margin-top: calc(var(--folga) - var(--laje) * 0.19); }
.stack--airy img,
.stack--airy img:nth-child(1),
.stack--airy img:nth-child(2),
.stack--airy img:nth-child(3) {
  position: static;
  transform: none;
  width: var(--laje);
  filter: drop-shadow(0 22px 28px rgba(25, 35, 42, 0.14));
}
.stack--airy img:nth-child(1) { animation-delay: 0s; }
.stack--airy img:nth-child(2) { animation-delay: 0.55s; }
.stack--airy img:nth-child(3) { animation-delay: 1.1s; }

/* --- Bloco "A empresa" ---------------------------------------------------
   Duas colunas alinhadas pelo topo, para o símbolo e a pilha de materiais
   arrancarem à mesma altura: é isso que faz ler um como abstração do outro. */
/* As medidas subiram todas a 4 de Agosto de 2026, quando o --content-max
   passou de 1060 para 1360px. Com a caixa mais larga e os corpos de letra
   antigos ficavam 338px de vazio entre o fim do texto e o início dos
   materiais: 123 de sobra na coluna do texto, 88 de intervalo e 127 de folga
   à volta da pilha, que só media 164px numa coluna de 512. Mexeu-se nos três. */
.empresa__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.8fr);
  gap: clamp(2rem, 4vw, 4rem);
  /* stretch e não start: as duas colunas passam a ter a mesma altura, que é a
     da mais alta — a dos materiais. O topo continua a ser o mesmo nas duas,
     por isso o símbolo do logótipo e a pilha continuam a arrancar ao mesmo
     nível, que era o que o start garantia. */
  align-items: stretch;
}
/* Coluna de texto em flex para o botão poder ser empurrado até à base com
   margin-top: auto. É isso que o põe à altura da nota dos materiais, sem
   número mágico nenhum e em qualquer largura de ecrã. */
.empresa__texto {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
@media (max-width: 900px) {
  .empresa__grid { grid-template-columns: 1fr; gap: clamp(2.5rem, 8vw, 3.5rem); }
}

/* O logótipo abre o bloco e a frase vem por baixo, mais pequena do que era
   quando fazia de abertura sozinha — quem manda na entrada é a marca. */
.empresa__logo {
  display: block;
  width: min(100%, clamp(260px, 26vw, 400px));
  height: auto;
  margin-bottom: clamp(1.3rem, 2.2vw, 1.9rem);
}
/* O título fica sempre numa linha só. Medido na TASA Orbiter a 700, esta frase
   ocupa 20,98px de largura por cada 1px de corpo de letra, e é essa constante
   que manda aqui: em duas colunas a coluna do texto tem 473px a 1280 e 662px a
   1920, o que dá no máximo 22,5px e 31,5px de corpo. Daí os valores abaixo —
   se mudares a frase, o peso ou a fonte, esta conta tem de ser refeita.
   Sem max-width em ch: com nowrap ela só serviria para cortar a linha. */
.empresa__texto h2 {
  max-width: none;
  margin: 0 0 clamp(1.3rem, 2.2vw, 1.9rem);
  white-space: nowrap;
  font-size: clamp(1.05rem, 0.3rem + 1.32vw, 1.9rem);
}
/* Estas duas têm de vir DEPOIS da regra de cima: valem a mesma especificidade,
   por isso quem ganha é a última. Estavam antes e o título encolhia para o
   mínimo do clamp em vez de crescer. */
@media (max-width: 900px) {
  /* Em coluna única o título tem a largura toda e cabe maior numa linha: o
     limite é 4,38vw (largura útil a dividir pelos 20,98 por px de corpo). */
  .empresa__texto h2 { font-size: 4.2vw; }
}
/* Abaixo dos 600px uma linha só exigiria menos de 26px, o que depressa fica
   ilegível, por isso volta a partir. */
@media (max-width: 600px) {
  .empresa__texto h2 {
    white-space: normal;
    max-width: 18ch;
    font-size: clamp(1.35rem, 1.05rem + 1.5vw, 1.75rem);
  }
}
/* Os limites em ch subiram com os corpos de letra: é o que faz o texto chegar
   ao fim da coluna em vez de parar a meio dela. */
.empresa__texto .lead {
  max-width: 52ch;
  font-size: clamp(1.05rem, 0.92rem + 0.55vw, 1.38rem);
  line-height: 1.6;
}
/* O margin-bottom é o respiro mínimo até ao botão. Estava como padding-top no
   próprio link, o que servia enquanto ele era texto com uma seta; agora que é
   uma cápsula, um padding-top engordava o botão em vez de o afastar. Passou
   para cá, que é o irmão de cima, e o margin-top: auto do botão continua a
   fazer o resto. */
.empresa__corpo {
  margin-top: 1.35rem;
  margin-bottom: clamp(1.8rem, 3.2vw, 2.6rem);
  max-width: 58ch;
  font-size: 1.05rem;
  line-height: 1.8;
  color: var(--muted);
}
/* auto empurra o botão até à base da coluna, que tem a altura da coluna dos
   materiais — é assim que ele acaba à mesma altura da nota. Quando não sobra
   nada para o auto distribuir, quem garante o respiro é o margin-bottom do
   .empresa__corpo, aqui em cima. */
.empresa__link { margin-top: auto; }

/* A figura é uma coluna centrada: as lajes, a legenda e a nota partilham a
   mesma largura, para o filete não ficar muito mais largo do que o objecto
   que legenda. */
.empresa__materiais {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 0;
}

/* Legenda em três células separadas por filetes, na mesma linguagem da
   barra lateral — sem pastilhas nem marcadores. */
.stack-key {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  width: min(100%, 340px);
  list-style: none;
  margin: clamp(0.45rem, 0.9vw, 0.6rem) 0 0;
  padding: 0;
  border-top: 1px solid rgba(25, 35, 42, 0.18);
}
.stack-key li {
  padding: 0.7rem 0.2rem 0;
  text-align: center;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-80);
}
.stack-key li + li { border-left: 1px solid rgba(25, 35, 42, 0.18); }

/* Fica dentro da largura do filete da legenda, senão numa só linha ficava
   58px mais larga do que ele de cada lado. São sempre duas linhas. */
/* --muted e não --muted-2: a 15,2px sobre branco o --muted-2 dá 2,77 de
   contraste e o mínimo é 4,5. Já chumbava com a paleta antiga (#8a99a3 dava
   o mesmo), só se viu ao correr a lista de conferência do padrão. O --muted
   dá 5,94 e continua a ler-se como texto de terceiro plano.
   O --muted-2 fica para o que não é texto corrido: ícones, marcas de água e
   os idiomas por publicar, que são controlos inactivos e estão fora da
   regra. */
.empresa__nota {
  max-width: 34ch;
  margin: 0.55rem 0 0;
  font-size: 0.95rem;
  line-height: 1.6;
  text-align: center;
  text-wrap: balance;
  color: var(--muted);
}

/* Vitrines das marcas -----------------------------------------------------
   Cada marca começa com a máquina sozinha ao centro da faixa. Quando a faixa
   entra no ecrã, a máquina desliza para o seu lado e o texto aparece. Acontece
   uma vez só: não volta a fechar, e não há nada para clicar — quem dispara é
   o observador de scroll no main.js.

   Os estados estão escritos ao contrário do que parece natural, e de
   propósito: o estado por omissão do CSS é o ABERTO, e é a classe .js — posta
   pelo <head> antes de a página pintar — que recolhe a máquina. Assim, sem
   JavaScript, o texto e os botões para as páginas das marcas ficam à vista em
   vez de ficarem presos num estado que nada abriria. E como a classe .js entra
   antes da primeira pintura, não há lampejo do estado aberto.

   O lado da máquina alterna de vitrine para vitrine (vitrine--invertida). As
   colunas são as mesmas espelhadas, por isso o deslocamento que centra a
   máquina é o mesmo valor com o sinal trocado. */
.vitrines {
  display: grid;
  gap: clamp(3rem, 7vw, 6rem);
}

.vitrine {
  --folga: clamp(2rem, 5vw, 4.5rem);
  display: grid;
  grid-template-columns: 1.25fr 0.75fr;
  gap: var(--folga);
  align-items: stretch;
}
.vitrine--invertida { grid-template-columns: 0.75fr 1.25fr; }

/* --- Bloco da máquina --- */
.vitrine__gatilho {
  grid-column: 1;
  grid-row: 1;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  transition: transform 1.8s var(--ease);
}
.vitrine--invertida .vitrine__gatilho { grid-column: 2; }

/* Recolhida: a máquina ao centro da faixa. O deslocamento é metade do que
   sobra do outro lado dela, ou seja (coluna do texto + folga) / 2. Em
   percentagem da própria coluna isso dá largura/(2 x razão) + folga/2, e com
   a razão 1,25/0,75 = 5/3 a primeira parcela é exactamente 30%. Se mexeres na
   divisão das colunas, esta percentagem tem de ser refeita. */
.js .vitrine__gatilho { transform: translateX(calc(30% + var(--folga) / 2)); }
.js .vitrine--invertida .vitrine__gatilho { transform: translateX(calc(-30% - var(--folga) / 2)); }
.js .vitrine.is-aberta .vitrine__gatilho,
.js .vitrine--invertida.is-aberta .vitrine__gatilho { transform: translateX(0); }

/* O palco carrega a máquina, e não a fotografia directamente: a sombra do
   chão é um filho dele, por isso acompanha-a em vez de ficar para trás.
   A máquina tem um tamanho só, igual nos dois estados: ao deslizar não
   míngua nem cresce, e o movimento é puramente horizontal. */
.vitrine__palco {
  position: relative;
  display: block;
}
/* As fotografias vêm achatadas sobre branco: o multiply faz esse branco
   desaparecer e a máquina assenta directamente na página, sem caixa. */
.vitrine__foto {
  width: var(--larg-foto, 100%);
  height: auto;
  margin-inline: auto;
  mix-blend-mode: multiply;
}
/* Para fotografias com enquadramento muito mais quadrado do que as outras.
   Como todas ocupam a mesma largura de coluna, uma máquina fotografada quase
   ao quadrado sai muito mais alta e a faixa dela fica uma cabeça acima das
   restantes — a Comeva, a 1,166 de rácio, dava 635px contra os 370-418 das
   outras. A percentagem é o rácio dela a dividir pelo da mais alta das
   outras (1,166/1,771), o que lhe iguala a altura em qualquer largura. */
.vitrine__foto--quadrada { --larg-foto: 65.8%; }
/* Se alguma fotografia vier sobre fundo escuro, não serve assim: não há branco
   para desaparecer e o multiply escurece-a até ficar um rectângulo preto. Tem
   de vir recortada, com transparência, e ser achatada sobre branco pelo
   fotos-marcas.ps1. */

/* --- Painel de texto --- */
/* Fica sempre na grelha, mesmo escondido: é isso que impede a faixa de saltar
   de altura quando abre. O que o esconde é a opacidade, não o display.
   Leva o mesmo enchimento vertical do bloco da máquina — neste caso nenhum —
   para as duas caixas terem a mesma área útil: é o que faz o título arrancar
   ao nível do topo da máquina e o botão cair na base dela.
   Não leva visibility com atraso de transição, que foi a primeira tentativa:
   se a transição não chegasse a correr, o painel continuava a apanhar o
   teclado enquanto invisível. Quem trata disso é o atributo inert, posto pelo
   JavaScript, que não depende de tempo nenhum. */
.vitrine__painel {
  grid-column: 2;
  grid-row: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  max-width: 46ch;
  /* O atraso acompanha o deslize: entra quando a máquina vai a pouco mais de
     um terço do caminho e chega antes dela, para o texto assentar primeiro.
     Se mexeres nos 1,8s do deslize, mexe aqui na mesma proporção: o atraso é
     36% do deslize e a duração 44%. */
  transition: opacity 0.8s var(--ease) 0.65s, transform 0.8s var(--ease) 0.65s;
}
.vitrine--invertida .vitrine__painel { grid-column: 1; }
.vitrine__painel .btn { margin-top: auto; }

/* A entrada do texto leva o atraso definido no transition acima: sem ele, as
   duas coisas ao mesmo tempo liam-se como um salto. */
.js .vitrine__painel {
  opacity: 0;
  transform: translateX(1.75rem);
}
.js .vitrine--invertida .vitrine__painel { transform: translateX(-1.75rem); }
.js .vitrine.is-aberta .vitrine__painel,
.js .vitrine--invertida.is-aberta .vitrine__painel {
  opacity: 1;
  transform: none;
}

.vitrine__titulo {
  margin: 0;
  font-size: clamp(1.4rem, 0.95rem + 1.2vw, 2.1rem);
  line-height: 1.1;
}
.vitrine__origem {
  margin: 0.4rem 0 0;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
/* O margin-top: auto do botão é o amortecedor: se o texto crescer de mais,
   encolhe até zero e a partir daí é o painel que passa a mandar na altura da
   faixa, o que desalinha o botão da base da imagem. Convém deixá-lo positivo. */
.vitrine__corpo {
  margin: clamp(0.85rem, 1.8vw, 1rem) 0 clamp(1.1rem, 2.2vw, 1.35rem);
  font-size: 1rem;
  line-height: 1.72;
  color: var(--muted);
}

/* Em coluna única a máquina não tem para onde deslizar, por isso a vitrine
   passa a ser um bloco normal e o texto está sempre à vista. O JavaScript
   sabe deste mesmo limite e nem sequer observa as vitrines abaixo dele. */
@media (max-width: 820px) {
  .vitrine,
  .vitrine--invertida { grid-template-columns: 1fr; gap: clamp(1.5rem, 5vw, 2.25rem); }
  .js .vitrine__gatilho,
  .js .vitrine--invertida .vitrine__gatilho,
  .js .vitrine.is-aberta .vitrine__gatilho {
    grid-column: 1;
    transform: none;
  }
  .js .vitrine__painel,
  .js .vitrine--invertida .vitrine__painel,
  .js .vitrine.is-aberta .vitrine__painel {
    grid-column: 1;
    grid-row: 2;
    max-width: none;
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Nota sobre a ferramenta, discreta */
.tool-note {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1rem;
  padding: clamp(1.25rem, 3vw, 1.75rem);
  background: var(--paper);
  font-size: 0.95rem;
  color: var(--muted);
}
.tool-note strong { color: var(--ink); font-weight: 700; }
/* Não tem limite próprio como os outros blocos de leitura, e com o wrap mais
   largo a frase corria de ponta a ponta numa linha só. O 58ch dá 70 caracteres
   reais — a unidade ch é a largura do algarismo 0, mais larga do que a letra
   média, por isso o número que se escreve sai sempre curto. */
.tool-note span { max-width: 58ch; }

/* --------------------------------------------------------------------------
   11. Cabeçalho de página interior
   -------------------------------------------------------------------------- */
.page-head {
  position: relative;
  background: var(--ink);
  color: #b6c7cc;
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
  overflow: hidden;
  isolation: isolate;
}
.page-head h1 { color: #fff; max-width: 20ch; }
.page-head p { max-width: 60ch; font-size: var(--step-1); color: #a8bcc1; }
.page-head--teal { background: var(--teal); }

.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  align-items: center;
  list-style: none;
  margin: 0 0 1.1rem;
  padding: 0;
  font-size: 0.8rem;
  color: rgba(255, 255, 255, 0.55);
}
.breadcrumb li { display: flex; align-items: center; gap: 0.45rem; }
.breadcrumb li + li::before { content: "/"; opacity: 0.5; }
.breadcrumb a:hover { color: #fff; }

/* --------------------------------------------------------------------------
   12. Cartões
   -------------------------------------------------------------------------- */
.card {
  display: flex;
  flex-direction: column;
  padding: clamp(1.4rem, 2.6vw, 2rem);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  transition: transform 0.32s var(--ease), box-shadow 0.32s var(--ease),
    border-color 0.32s var(--ease);
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow); border-color: var(--teal-mid); }
.card h3 { margin-bottom: 0.5rem; }
.card p { color: var(--muted); font-size: 0.96rem; }
.card__foot { margin-top: auto; padding-top: 1.2rem; }

.card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 50px; height: 50px;
  margin-bottom: 1.15rem;
  background: var(--paper);
  color: var(--teal);
}
.card__num {
  font-family: var(--font-display);
  font-size: 1.3rem;
  font-weight: 700;
}

.section--ink .card {
  background: var(--ink-90);
  border-color: rgba(255, 255, 255, 0.1);
}
.section--ink .card p { color: #a8bcc1; }
.section--ink .card__icon { background: rgba(90, 146, 150, 0.18); color: var(--teal-mid); }
.section--ink .card:hover { border-color: var(--teal-mid); }

/* Blocos de marca */
.brand-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: center;
}
.brand-row + .brand-row { margin-top: clamp(2.5rem, 6vw, 5rem); padding-top: clamp(2.5rem, 6vw, 5rem); border-top: 1px solid var(--line); }
.section--ink .brand-row + .brand-row { border-top-color: rgba(255, 255, 255, 0.12); }

.brand-row__media {
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--paper);
  aspect-ratio: 4 / 3;
}
.brand-row__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s var(--ease); }
.brand-row:hover .brand-row__media img { transform: scale(1.04); }

.brand-tag {
  display: inline-block;
  padding: 0.28rem 0.7rem;
  margin-bottom: 1rem;
  border: 1px solid var(--teal-mid);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--teal);
}
.section--ink .brand-tag { color: var(--teal-mid); }

.tag-list { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 1.2rem 0 0; padding: 0; list-style: none; }
.tag-list li {
  padding: 0.28rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.section--ink .tag-list li { border-color: rgba(255, 255, 255, 0.18); color: #a8bcc1; }

/* Lista de características */
.feature-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.35rem; }
.feature-list li { display: flex; gap: 0.9rem; align-items: flex-start; }
.feature-list svg { color: var(--teal-mid); flex-shrink: 0; margin-top: 5px; }
.feature-list h4 { margin: 0 0 0.2rem; font-size: 1.02rem; }
.feature-list p { margin: 0; color: var(--muted); font-size: 0.94rem; }
.section--ink .feature-list p { color: #a8bcc1; }

/* --------------------------------------------------------------------------
   13. Números
   -------------------------------------------------------------------------- */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr));
  gap: clamp(1.25rem, 3vw, 2.5rem);
}
.stat { border-left: 2px solid var(--teal-mid); padding-left: 1.15rem; }
.stat__value {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2.2rem, 5vw, 3.4rem);
  font-weight: 700;
  line-height: 1;
  color: #fff;
  font-variant-numeric: tabular-nums;
}
.stat__value .plus { color: var(--teal-mid); }
.stat__label {
  display: block;
  margin-top: 0.5rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #8ea3a9;
}
.section--paper .stat__value { color: var(--ink); }
.section--paper .stat__label { color: var(--muted); }

/* --------------------------------------------------------------------------
   14. Catálogos e modelos
   -------------------------------------------------------------------------- */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-bottom: 2rem;
  padding: 0;
  border-bottom: 1px solid var(--line);
  width: 100%;
  gap: 0;
}
.tab {
  padding: 0.7rem 1.25rem;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  background: transparent;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.22s var(--ease), color 0.22s var(--ease);
}
.tab:hover { color: var(--teal); }
.tab[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--teal); }

.catalog-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 190px), 1fr));
  gap: clamp(0.9rem, 2vw, 1.35rem);
}
.catalog-card {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform 0.28s var(--ease), box-shadow 0.28s var(--ease), border-color 0.28s var(--ease);
}
.catalog-card:hover { transform: translateY(-4px); box-shadow: var(--shadow); border-color: var(--teal-mid); }
.catalog-card__thumb { aspect-ratio: 3 / 4; background: var(--paper-soft); overflow: hidden; }
.catalog-card__thumb img { width: 100%; height: 100%; object-fit: cover; object-position: top center; transition: transform 0.5s var(--ease); }
.catalog-card:hover .catalog-card__thumb img { transform: scale(1.04); }
.catalog-card__body {
  display: flex; align-items: center; justify-content: space-between; gap: 0.6rem;
  padding: 0.8rem 0.9rem;
  border-top: 1px solid var(--line-soft);
}
.catalog-card__title { font-size: 0.87rem; font-weight: 600; line-height: 1.3; }
.catalog-card__pdf {
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--teal); flex-shrink: 0;
}

.model-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 250px), 1fr));
  gap: clamp(1rem, 2.2vw, 1.75rem);
}
.model-card {
  display: flex; flex-direction: column;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
}
.model-card:hover { transform: translateY(-5px); box-shadow: var(--shadow); border-color: var(--teal-mid); }
/* Sem aspect-ratio: as sete fotografias partilham a moldura de 760x380, por
   isso é a fotografia que dá a altura à caixa — e dá a mesma às sete. */
.model-card__media {
  background: var(--paper-soft);
  display: grid; place-items: center;
  padding: 1.25rem;
}
/* Achatadas sobre branco, como as do menu (secção 6b): o multiply faz esse
   branco desaparecer contra o fundo da caixa. */
.model-card__media img {
  display: block;
  width: 100%;
  height: auto;
  mix-blend-mode: multiply;
  transition: transform 0.5s var(--ease);
}
.model-card:hover .model-card__media img { transform: scale(1.05); }
.model-card__body { padding: 1.1rem 1.35rem 1.35rem; display: flex; flex-direction: column; gap: 0.9rem; flex: 1; }
.model-card__body h3 { margin: 0; font-size: 1.35rem; }
.model-card__body .btn,
.model-card__body .link-arrow { align-self: flex-start; margin-top: auto; }

/* --------------------------------------------------------------------------
   15. Contactos e formulário
   -------------------------------------------------------------------------- */
.contact-card {
  padding: clamp(1.35rem, 2.6vw, 1.9rem);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  transition: transform 0.28s var(--ease), box-shadow 0.28s var(--ease), border-color 0.28s var(--ease);
}
.contact-card:hover { transform: translateY(-3px); box-shadow: var(--shadow); border-color: var(--teal-mid); }
.contact-card__label {
  margin-bottom: 0.7rem;
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--teal);
}
.contact-card__value {
  display: block;
  font-family: var(--font-display);
  font-size: 1.5rem; font-weight: 700; line-height: 1.2;
  word-break: break-word;
}
.contact-card__value:hover { color: var(--teal); }
.contact-card small { display: block; margin-top: 0.4rem; font-size: 0.76rem; color: var(--muted-2); }

.map-embed {
  width: 100%;
  aspect-ratio: 16 / 9;
  min-height: 320px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--paper);
}
.map-embed iframe { width: 100%; height: 100%; border: 0; }

.form-panel {
  padding: clamp(1.5rem, 3vw, 2.5rem);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
}
.form { display: grid; gap: 1rem; }
.form__row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); gap: 1rem; }
.field { display: grid; gap: 0.35rem; }
.field label { font-size: 0.82rem; font-weight: 600; }
.field input, .field textarea, .field select {
  width: 100%;
  padding: 0.8rem 0.95rem;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.field input:focus, .field textarea:focus, .field select:focus {
  outline: none;
  border-color: var(--teal);
  box-shadow: 0 0 0 4px rgba(34, 79, 85, 0.12);
}
.field textarea { min-height: 140px; resize: vertical; }
.field--check { display: flex; gap: 0.6rem; align-items: flex-start; }
.field--check input { width: auto; margin-top: 4px; flex-shrink: 0; }
.field--check label { font-weight: 400; font-size: 0.82rem; color: var(--muted); }
.field--check a { color: var(--teal); text-decoration: underline; }

.form__status { font-size: 0.88rem; font-weight: 600; }
.form__status[data-state="ok"] { color: #1f7a52; }
.form__status[data-state="error"] { color: #b3261e; }

/* --------------------------------------------------------------------------
   16. Faixa de chamada à ação
   -------------------------------------------------------------------------- */
.cta {
  position: relative;
  background: var(--teal);
  color: #cfe0e2;
  overflow: hidden;
  isolation: isolate;
}
.cta__inner {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: clamp(1.25rem, 3vw, 2.5rem);
  align-items: center;
}
.cta h2 { color: #fff; margin-bottom: 0.35rem; }
.cta p { margin: 0; }
.cta .btn-row { justify-content: flex-end; }
@media (max-width: 720px) { .cta .btn-row { justify-content: flex-start; } }

/* --------------------------------------------------------------------------
   17. Rodapé
   -------------------------------------------------------------------------- */
/* O gradiente arranca em --rodape, que é a cor lisa que vem de cima, e só
   daqui para baixo é que escurece. Ver o comentário dos tokens, na secção 2. */
.site-footer {
  background: linear-gradient(to bottom, var(--rodape), var(--rodape-baixo));
  color: var(--rodape-texto);
  font-size: 0.9rem;
  padding-top: clamp(2.5rem, 5vw, 4rem);
}
.footer__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: clamp(1.75rem, 4vw, 3rem);
}
.site-footer h4 {
  margin-bottom: 0.9rem;
  font-family: var(--font-body);
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase;
  color: #fff;
}
.site-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.55rem; }
.site-footer a:hover { color: var(--teal-mid); }
.site-footer address { font-style: normal; line-height: 1.75; }
.footer__logo { width: 172px; margin-bottom: 1rem; }

.footer__bottom {
  margin-top: clamp(2rem, 4vw, 3rem);
  padding-block: 1.25rem;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  display: flex; flex-wrap: wrap; gap: 0.75rem;
  justify-content: space-between; align-items: center;
  font-size: 0.8rem; color: var(--rodape-texto-fraco);
}
.footer__bottom a { text-decoration: underline; text-underline-offset: 3px; }

/* Barra rápida no telemóvel */
.quick-bar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 65;
  display: none;
  gap: 0.4rem;
  padding: 0.5rem;
  background: rgba(25, 35, 42, 0.97);
  backdrop-filter: blur(10px);
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}
.quick-bar a {
  flex: 1;
  display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem;
  padding: 0.7rem 0.4rem;
  font-size: 0.78rem; font-weight: 600;
  letter-spacing: 0.04em;
  color: #fff;
  background: rgba(255, 255, 255, 0.09);
}
.quick-bar a.is-primary { background: #fff; color: var(--ink); }

@media (max-width: 719px) {
  .quick-bar { display: flex; }
  body { padding-bottom: 64px; }
}

/* Estado vazio — secções à espera de conteúdo real */
.empty-state {
  padding: clamp(2rem, 5vw, 3.5rem);
  border: 1px dashed var(--line);
  background: var(--paper-soft);
  text-align: center;
}
.empty-state svg { color: var(--muted-2); margin: 0 auto 1.1rem; }
.empty-state h3 { margin-bottom: 0.5rem; }
.empty-state p { color: var(--muted); max-width: 52ch; margin-inline: auto; }

/* --------------------------------------------------------------------------
   18. Texto longo
   -------------------------------------------------------------------------- */
.prose { max-width: 70ch; }
.prose h2 { font-size: var(--step-2); margin-top: 2.25rem; }
.prose h3 { font-family: var(--font-body); font-size: 1.05rem; font-weight: 700; letter-spacing: 0; margin: 1.75rem 0 0.4rem; }
.prose p, .prose li { color: var(--muted); }
.prose ul, .prose ol { padding-left: 1.2rem; display: grid; gap: 0.55rem; margin-bottom: 1.4rem; }
.prose strong { color: var(--ink); }
.prose hr { border: 0; border-top: 1px solid var(--line); margin: 2.25rem 0; }

/* --------------------------------------------------------------------------
   19. Animação de entrada
   -------------------------------------------------------------------------- */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.65s var(--ease), transform 0.65s var(--ease);
  transition-delay: var(--delay, 0ms);
}
.js [data-reveal].is-visible { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .js [data-reveal] { opacity: 1; transform: none; }
  .stack img { animation: none; }
}

/* --------------------------------------------------------------------------
   21b. Paleta da marca, tirada do logótipo — À EXPERIÊNCIA, só na
   striebig.html

   Redefine os mesmos tokens da secção 2 num selector mais específico
   (html.tema-marca ganha ao :root, que é o mesmo elemento com menos peso),
   por isso não é preciso mexer em regra nenhuma: tudo o que já usa var()
   muda sozinho. Para desligar, tira-se a classe do <html>.

   DE ONDE VEM. Não é invenção: são as cores dos próprios ficheiros do
   logótipo, em assets/img/logo/.
     #16232B  o texto "Miguel Martins"        (mm-horizontal.svg)
     #075056  o símbolo, o hexágono           (mm-horizontal.svg)
     #469396  o tom secundário                (mm-horizontal-escuro.svg)
     #E3EDEF  o claro                         (mm-horizontal-escuro.svg)

   PORQUÊ MUDA ALGUMA COISA. O símbolo do logótipo tem 85% de saturação; o
   --teal que o site usava (#224F55) é uma versão lavada dele, e o --teal-mid
   (#5A9296) tem 36% onde o secundário do logótipo tem os mesmos 36% mas mais
   verde. A falta de presença não vinha da paleta estar errada — vinha de
   estar dessaturada face ao logótipo. Esta paleta devolve a saturação.

   O TOM VIVO. #14B0B5 é o matiz do símbolo (182°) levado a 80% de saturação
   e 39% de luz. Dá 6,04 com a tinta por cima, portanto serve de fundo a
   botões. O #1ECDD2 é o mesmo, mais claro, para texto de realce sobre o
   gradiente escuro — 4,68 contra o ponto mais claro dele. */
html.tema-marca {
  /* Do logótipo, tal e qual */
  --ink: #16232b;
  --ink-rgb: 22, 35, 43;
  --teal: #075056;
  --paper: #e3edef;

  /* Degraus derivados, no mesmo matiz */
  --ink-90: #1e2e38;
  --ink-80: #2c4049;
  --paper-soft: #f1f7f8;
  --teal-mid: #14b0b5;
  --teal-deep: #04383c;
  --realce-escuro: #1ecdd2;

  --muted: #4e6870;
  --muted-2: #86a0a6;
  --line: #d2e0e3;
  --line-soft: #e8f0f2;

  --shadow-sm: 0 1px 2px rgba(22, 35, 43, 0.05), 0 2px 10px rgba(22, 35, 43, 0.05);
  --shadow: 0 14px 34px -16px rgba(22, 35, 43, 0.3);
  --shadow-lg: 0 36px 70px -30px rgba(22, 35, 43, 0.5);
}

/* --------------------------------------------------------------------------
   21. Página da Striebig

   Tudo aqui leva o prefixo .st- e só é usado pela striebig.html. Fica num
   bloco só, para se poder apagar de uma vez sem tocar no resto da folha.
   -------------------------------------------------------------------------- */

/* --- Cabeçalho com filme -------------------------------------------------
   O filme cobre a faixa toda e o texto assenta por cima, como no homag.com.

   Não há cartaz. O fundo da secção é a cor de tinta, por isso o título já se
   lê antes de o vídeo pintar — e continua a ler-se se ele nunca chegar a
   tocar (dados móveis, movimento reduzido, JavaScript desligado). O filme
   entra depois, com um esbatimento, quando o browser diz que consegue tocá-lo.

   O vídeo arranca aos 57s e volta aos 57s quando acaba: o atributo loop do
   HTML não servia, porque reinicia sempre no zero. Quem trata disso é o
   initVideoHero() do main.js. */
/* A altura e a razão vivem em duas variáveis porque há uma faixa que muda as
   duas por largura (.st-hero--inteiro, mais abaixo). Escritas assim, o que
   manda é sempre o valor da variável e nunca a ordem das regras — que é a
   armadilha de sempre desta folha: com a mesma especificidade ganha a última,
   mesmo estando a outra dentro de uma media query. */
.st-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--ink);
  display: grid;
  align-items: center;
  min-height: var(--hero-min, clamp(430px, 70vh, 700px));
  aspect-ratio: var(--hero-ar, auto);
}
.st-hero__filme {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.9s var(--ease);
}
.st-hero__filme.is-pronto { opacity: 1; }

/* --- A fotografia por baixo do filme (.st-hero__cartaz) ------------------
   Nos cabeçalhos que têm as duas peças — martin.html e comeva.html — a
   fotografia é a rede de três casos: ecrãs abaixo dos 720px, onde o filme
   nunca é pedido; quem pede menos movimento; e quem não tem JavaScript.

   NAS LARGURAS EM QUE O FILME É PEDIDO ELA NÃO DEVE CHEGAR A VER-SE. O que
   se via era a fotografia a pintar primeiro e, um instante depois, o filme a
   aparecer por cima com um fotograma diferente — duas imagens à entrada da
   página, que é o piscar que o Diogo apanhou a 10 de Agosto de 2026.

   PORQUE É QUE ISTO É CSS E NÃO JAVASCRIPT: para não haver piscar nenhum, a
   fotografia tem de nascer escondida. O initVideoHero() só corre depois do
   HTML estar lido, e nessa altura ela já pode ter sido pintada — esconde-la
   aí seria trocar um piscar por outro. Só uma regra de estilo chega a tempo.

   Enquanto o filme carrega fica a cor de tinta do .st-hero, que é o que a
   striebig.html sempre teve. O escurecimento por cima é o mesmo, portanto o
   título e o subtítulo lêem-se na mesma desde o primeiro instante.

   OS 720px SÃO OS DO GUIÃO, não um valor à parte: o initVideoHero() carrega
   o filme a partir de 720 (`innerWidth < 720` desiste). Se um mudar, o outro
   tem de mudar com ele, senão há larguras que ficam sem imagem nenhuma.

   O `no-preference` faz o par com o `reduceMotion` do guião, que também
   desiste de carregar o filme. Sem ele, quem pede menos movimento ficava com
   o cabeçalho vazio.

   `.is-pronto` no selector não é enfeite: é preciso para ganhar à regra aqui
   em cima, que tem duas classes. */
@media (min-width: 720px) and (prefers-reduced-motion: no-preference) {
  .st-hero__cartaz.is-pronto { opacity: 0; }

  /* A porta de saída: se o filme não vier (404, formato recusado), o
     initVideoHero() põe esta classe e a fotografia volta ao seu lugar. */
  .st-hero__cartaz.is-pronto.is-fica { opacity: 1; }
}

/* Dois escurecimentos sobrepostos: um da esquerda, que é o lado onde o texto
   vive, e outro de baixo, que assenta a faixa no que vem a seguir. É este par
   que deixa ver a máquina à direita, onde não passa texto nenhum. Anda casado
   com o alinhamento: se o texto for para o meio ou para a direita, este
   degradé tem de ser refeito, senão o branco do título desaparece assim que
   passar um plano claro da oficina.

   REFEITO A 10 DE AGOSTO DE 2026, com o Diogo a pedir menos escuro. O que
   estava descia devagar, de 0,74 aos 36% até 0,24 aos 74% — uma rampa longa
   que tapava a máquina inteira E deixava o FIM do subtítulo (que acaba aos
   ~50% da faixa) pousado a meio da descida, que é o pior dos dois mundos.

   A forma nova segura até aos 52%, onde o texto acaba, e cai a pique logo a
   seguir. Fica muito mais claro à vista e NÃO CUSTA LEGIBILIDADE — contraste
   do subtítulo sobre o filme, medido pixel a pixel a 1920, no pior ponto de
   cada fotograma, com o degradé velho injectado ao lado do novo:

     fotograma      58s    86s    151s
     antes         5,97   5,47   3,68
     agora         6,03   5,53   3,71

   O título desce de 9,89 para 8,55 no pior fotograma, o que não incomoda
   ninguém a essa distância do mínimo. A 1100, onde o texto ocupa mais faixa,
   o subtítulo dá 5,19 e o título 7,66.

   MEDIR SÓ ONDE AS LETRAS ESTÃO, com Range.getClientRects(). A caixa de um
   <p> ocupa a largura toda mesmo quando o texto acaba a meio, e medi-la dá um
   falso alarme: a 1100 dava 1,65 por estar a ler o fundo à direita das
   letras, onde não passa texto nenhum.

   Os 151s são o genérico do fim do filme, que traz letras claras por baixo do
   nosso texto: 3,71 fica abaixo dos 4,5 da casa (passa o mínimo de 3 do WCAG
   para texto grande). NÃO É REGRESSÃO — já era 3,68 antes disto. Resolve-se
   cortando o filme aos ~148s com data-video-fim, não com mais escurecimento. */
.st-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(to right,
      rgba(var(--ink-rgb), 0.74) 0%,
      rgba(var(--ink-rgb), 0.66) 40%,
      rgba(var(--ink-rgb), 0.58) 52%,
      rgba(var(--ink-rgb), 0.12) 66%,
      rgba(var(--ink-rgb), 0.02) 100%),
    linear-gradient(to top,
      rgba(var(--ink-rgb), 0.40) 0%,
      rgba(var(--ink-rgb), 0) 42%);
}

/* O mesmo par, mas para a martin.html (.st-hero--foto). O nome ficou de
   quando ela só tinha fotografia; desde 10 de Agosto de 2026 tem o filme T75,
   e a fotografia é o que se vê enquanto ele carrega e abaixo dos 720px.

   PORQUE É QUE NÃO USA OS VALORES DA STRIEBIG, se agora as duas têm filme:
   por duas razões medidas, não por gosto.

   1. O T75 é mais claro por trás do texto. No pior fotograma (o dos 14s, com
      a oficina iluminada à esquerda) o degradé da Striebig, injectado aqui
      para ensaio, dava 3,93 no subtítulo — abaixo do mínimo de 4,5. Com estas
      paradas dá 5,31, e o título 7,80.
   2. O texto tem largura fixa (.st-hero__texto, 40rem), por isso quanto MAIS
      ESTREITO o cabeçalho, MAIOR a fracção que ele ocupa. A 1920 as letras do
      subtítulo acabam aos 49% da faixa; a 1100, onde a barra lateral ainda
      rouba 260px, acabam aos 53%. Daí o patamar aguentar até aos 56% e não
      aos 52%. A 1100, no mesmo fotograma dos 14s: subtítulo 5,45 e título
      7,26.

   Também foi aliviado a 10 de Agosto, a pedido do Diogo: era 0,93 na ponta
   esquerda e ainda 0,74 aos 66%, uma mancha que tapava a máquina toda. A
   queda passou a ser a pique logo a seguir ao texto — 0,16 aos 72%, onde
   antes só chegava aos 86%. */
.st-hero--foto::after {
  background:
    linear-gradient(to right,
      rgba(var(--ink-rgb), 0.82) 0%,
      rgba(var(--ink-rgb), 0.74) 42%,
      rgba(var(--ink-rgb), 0.66) 56%,
      rgba(var(--ink-rgb), 0.16) 72%,
      rgba(var(--ink-rgb), 0.03) 100%),
    linear-gradient(to top,
      rgba(var(--ink-rgb), 0.45) 0%,
      rgba(var(--ink-rgb), 0) 42%);
}

/* --- Faixa com a razão do próprio filme (.st-hero--inteiro) ---------------
   A leuco.html, a pedido do Diogo a 10 de Agosto de 2026: o filme aparecia
   "com zoom". Não havia transform nenhum — era o object-fit: cover das outras
   faixas, que estica o filme até encher e corta o resto. Medido no filme da
   Leuco (1920×1080): 24% da altura a 1920 e 26% da largura a 1100.

   Aqui a faixa toma a razão do filme, por isso não sobra nada para cortar E
   não aparecem tarjas: continua a sangrar de lado a lado. O cover fica como
   está — com as duas razões iguais ele não corta nada.

   O --hero-min é um CHÃO, não a medida. Abaixo de uma faixa com ~765px o 16:9
   dava menos de 430px de altura e o título, o subtítulo e o botão deixavam de
   caber; aí volta a haver um corte pequeno nos lados, que é o mal menor.

   SÓ ACIMA DOS 720px, os mesmos do initVideoHero() e da regra do
   .st-hero__cartaz: abaixo disso não se pede filme nenhum e quem lá está é a
   fotografia, que quer a faixa alta de sempre. Se um destes três números
   mudar, os outros dois têm de mudar com ele.

   O `width: 100%` NÃO É ENFEITE. A faixa é um bloco de largura automática, e
   com aspect-ratio o browser resolve a razão pelo lado que puder: quando o
   chão de 430px passa a mandar, ele ALARGA a caixa para manter o 16:9. Media
   a 765px de janela: a faixa saía a 764 dentro de um contentor de 760, e a
   página ganhava 5px de barra horizontal. Com a largura fixada, a razão só
   pode resolver-se pela altura — e nas larguras do chão a faixa fica um
   pouco mais alta que 16:9, com um corte pequeno nos lados, como se quer. */
@media (min-width: 720px) {
  .st-hero--inteiro {
    --hero-ar: 16 / 9;
    --hero-min: 430px;
    width: 100%;
  }
}

.st-hero__inner {
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
  color: #cddadd;
}
.st-hero__texto { max-width: 40rem; }

/* Duas linhas, no molde do homag.com: uma palavra grande e uma frase curta
   por baixo. Lá a primeira mede 66,7px numa janela de 1265; aqui é uma
   palavra só, e uma palavra só aguenta mais corpo — sobe até 5,8rem (92,8px)
   a 1920. */
.st-hero__titulo {
  margin: 0 0 0.5rem;
  font-size: clamp(2.9rem, 6.2vw, 5.8rem);
  line-height: 1;
  letter-spacing: -0.015em;
  text-transform: uppercase;
  color: #fff;
  max-width: none;
}
.st-hero__sub {
  margin: 0 0 clamp(1.6rem, 3vw, 2.4rem);
  font-family: var(--font-body);
  font-size: clamp(1.02rem, 1.5vw, 1.6rem);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: 0.01em;
  color: #dbe6e8;
}

/* O único sítio para clicar em cima do filme, por isso é maior e mais cheio
   do que os .btn do resto do site.

   A SETA APONTA PARA ONDE O BOTÃO LEVA, e o hover empurra-a nesse sentido.
   Aqui aponta para baixo, porque desce até à secção dos modelos da própria
   página. O .st-botao é o mesmo botão fora do cabeçalho — nos destaques das
   marcas e no bloco da empresa da página inicial — e como esses levam a
   OUTRA página, a seta aponta para a direita.

   O eixo vive em duas variáveis em vez de em duas regras de hover: assim há
   um só sítio a mexer no transform e nunca pode haver duas a competir. */
.st-hero__cta,
.st-botao {
  --seta-x: 0px;
  --seta-y: 4px;
  display: inline-flex;
  align-items: center;
  gap: 0.85rem;
  padding: 1.15rem 2.2rem;
  background: var(--teal-mid);
  color: var(--ink);
  border: 1px solid var(--teal-mid);
  /* Em cápsula, como o "Fale connosco" e o "Enviar". */
  border-radius: 9999px;
  font-family: var(--font-body);
  font-size: 0.92rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  transition: background-color 0.22s var(--ease), color 0.22s var(--ease),
    border-color 0.22s var(--ease);
}
.st-hero__cta:hover { background: #fff; border-color: #fff; color: var(--ink); }
.st-hero__cta svg,
.st-botao svg { transition: transform 0.25s var(--ease); }
.st-hero__cta:hover svg,
.st-botao:hover svg { transform: translate(var(--seta-x), var(--seta-y)); }

/* Seta para a direita, e o filete NÃO vai a branco no hover: sobre o filme
   escuro o branco do original destaca-se, mas sobre a página branca fazia o
   botão desaparecer. Mantendo o filete --teal-mid ele esvazia-se e continua a
   ser um objecto.

   O line-height está escrito e não herdado, ao contrário do original, porque
   este botão aparece em blocos com entrelinhas diferentes: no texto dos
   destaques herdava 1,55 e ficava com 62px de altura, no bloco da empresa
   herdava o 1,68 do body e ficava com 64. É o 1,68 do body — o mesmo que o
   "Ver os modelos" da Striebig herda —, para os cinco terem exactamente a
   altura do original em qualquer sítio onde se ponham. */
.st-botao {
  --seta-x: 4px;
  --seta-y: 0px;
  line-height: 1.68;
}
.st-botao:hover { background: #fff; }

/* Seta a apontar para a esquerda, para os destaques em que a fotografia está
   desse lado — os ímpares, porque a grelha inverte-se nos pares. A seta
   aponta para a máquina de que o botão fala, e o hover empurra-a para lá.

   Duas classes no selector, e não uma: assim ganha por peso e não por ordem,
   e nenhuma variante por largura lhe pode tapar o sentido. É a mesma razão
   por que o --de-x dos destaques vive numa variável.

   O row-reverse põe a seta à frente do rótulo sem mexer na ordem do HTML —
   uma seta para a esquerda atrás do texto lê-se como um engano. */
.st-botao.st-botao--esq {
  flex-direction: row-reverse;
  --seta-x: -4px;
}

/* Os 62px que aqui estavam eram a altura da navegação da página, que colava
   por baixo do cabeçalho. Essa barra foi apagada, e a reserva ficou a mais:
   os saltos passavam 62px do sítio. Agora é só o cabeçalho e uma folga, o
   mesmo que a folha já faz em html { scroll-padding-top }. */
.st-alvo { scroll-margin-top: calc(var(--head-h) + 16px); }

/* --- Faixa de factos ----------------------------------------------------
   Quatro colunas fixas em vez de auto-fit: com auto-fit, ao passar para duas
   colunas o terceiro item continuava a ser :first-child de nada e ficava com
   filete à esquerda no início da linha. Assim os cortes são explícitos. */
.st-factos { background: #fff; border-block: 1px solid var(--line); }
.st-factos__lista {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  margin: 0;
  padding: 0;
}
.st-facto {
  padding: clamp(1.1rem, 2.2vw, 1.6rem) clamp(1rem, 2vw, 1.75rem);
  border-left: 1px solid var(--line);
}
.st-facto:first-child { border-left: 0; padding-left: 0; }
.st-facto dt {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.st-facto dd {
  margin: 0.45rem 0 0;
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 700;
  line-height: 1.1;
  color: var(--ink);
}

/* --- Navegação da própria página ---------------------------------------
   Cola por baixo do cabeçalho, que tem --head-h de altura e z-index 70: esta
   fica em 60 para passar por baixo dele e não o tapar. */
.st-subnav {
  position: sticky;
  top: var(--head-h);
  z-index: 60;
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}
.st-subnav__lista {
  display: flex;
  gap: clamp(1rem, 2.5vw, 2.25rem);
  list-style: none;
  margin: 0;
  padding: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.st-subnav__lista::-webkit-scrollbar { display: none; }
.st-subnav a {
  display: block;
  padding: 0.9rem 0;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.st-subnav a:hover { color: var(--teal); border-bottom-color: var(--teal); }

/* --- Planta à escala ----------------------------------------------------
   O desenho do espaço ocupado é SVG à mão, à escala: 40 unidades = 1 m. O
   rectângulo de fora tem 310×310 (7,75 m de lado = 60,06 m²) e o de dentro
   256×150 (6,4 × 3,75 m = 24,00 m²), que são as áreas que a Striebig publica.
   Mexer numa medida obriga a refazer a outra. */
.st-planta {
  background: #fff;
  border: 1px solid var(--line);
  padding: clamp(1.25rem, 3vw, 2.25rem);
}
.st-planta svg { width: 100%; height: auto; display: block; }
.st-planta figcaption {
  margin-top: 1.1rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--line-soft);
  font-size: 0.82rem;
  color: var(--muted);
}

/* --- Duas colunas: cabeçalho à esquerda, lista à direita ----------------- */
.st-duas {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: clamp(1.75rem, 4vw, 4rem);
  align-items: start;
  /* As colunas com .st-lado entram meia largura para fora; sem isto a página
     ganhava deslocamento horizontal enquanto elas chegam. */
  overflow: hidden;
}

/* --- Pilares numerados --------------------------------------------------- */
.st-pilares { display: grid; margin: 0; padding: 0; list-style: none; }
.st-pilar {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(1.1rem, 2.5vw, 2rem);
  padding-block: clamp(1.4rem, 3vw, 2.1rem);
  border-top: 1px solid var(--line);
}
.st-pilar:last-child { border-bottom: 1px solid var(--line); }
/* O número era a --teal-mid. Medido na primeira vez que estes pilares foram
   usados a sério (servicos.html), dava 2,66 contra o branco — abaixo do 3
   mínimo para texto grande. A --teal dá 9,17 e é a mesma cor dos ícones dos
   cartões logo acima. A --teal-mid continua a servir onde é fundo, não
   texto. */
.st-pilar__num {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 700;
  line-height: 1;
  color: var(--teal);
  font-variant-numeric: tabular-nums;
}
.st-pilar h3 { margin-bottom: 0.4rem; font-size: var(--step-1); }
.st-pilar p { margin: 0; max-width: 58ch; color: var(--muted); font-size: 0.96rem; }

/* --- Destaques -----------------------------------------------------------
   Copiado da secção "Destaques" do homag.com, medida na página do CENTATEQ
   P-100 a 5 de Agosto de 2026, num contentor de 1265px:

     título        50,1px, peso máximo, 31px de margem em baixo
     grelha        12 colunas — fotografia em 7 (683px), texto em 5 (475px)
     intervalo     46px
     fotografia    16:9, object-fit: cover
     texto         17,3px / 26px de entrelinha (1,5), centrado na vertical
     entre linhas  48px
     realce        <strong> pelo meio da frase, mesma cor, só o peso muda

   O 7/5 fica em 7fr/5fr, que dá a mesma proporção em qualquer largura. */
/* Título das secções ao molde do homag.com: um h2 com o corpo de um h1, sem
   sobretítulo e sem introdução — só a palavra. Lá mede 50,1px num contentor
   de 1265; aqui sobe até 54,4px, que é a mesma presença num wrap de 1360.
   A margem larga (31px, como a deles) é a da secção dos destaques; quando o
   título leva uma linha por baixo, --justo encosta-a, tal como o mb-2xs que
   eles usam na comparação de produtos. */
.st-titulo {
  margin-bottom: clamp(1.5rem, 2.4vw, 1.95rem);
  font-size: clamp(2rem, 1.5rem + 1.9vw, 3.4rem);
}
.st-titulo--justo { margin-bottom: 0.5rem; }

/* A linha cinzenta por baixo do título, como o "Centros de usinagem CNC
   CENTATEQ" deles: diz do que trata a tabela sem repetir o título. */
.st-subtitulo {
  margin: 0 0 clamp(1.75rem, 3.2vw, 2.6rem);
  font-size: clamp(1.05rem, 0.98rem + 0.35vw, 1.28rem);
  color: var(--muted);
}

/* --- Entrada dos cartões e da tabela -------------------------------------
   A mesma curva e o mesmo meio segundo dos destaques, com a escala a
   desfazer-se à chegada. Só o valor da escala é que muda: 1,25 servia lá,
   onde cada peça ocupa a sua metade da linha, mas numa grelha de oito
   cartões punha-os a montar uns em cima dos outros durante a entrada — o
   cartão tem 296px e o intervalo 24, e 25% de crescimento são 37 de cada
   lado. 1,08 dá o mesmo gesto sem colisão.
   O escalonamento é o --delay que o initReveal() já põe nos irmãos. */
.js .st-surge[data-reveal] {
  opacity: 0;
  transform: scale(1.08);
  transition: opacity 0.5s cubic-bezier(0, 0, 0.2, 1),
    transform 0.5s cubic-bezier(0, 0, 0.2, 1);
  transition-delay: var(--delay, 0ms);
}
.js .st-surge[data-reveal].is-visible { opacity: 1; transform: none; }

/* A regra de cima tem quatro classes e mata o transform do .st-modelo:hover,
   que só tem duas — o cartão deixava de subir ao passar o rato. Esta repõe-o
   com peso que chegue. */
.js .st-modelo.st-surge[data-reveal].is-visible:hover { transform: translateY(-4px); }

/* --- Entrada lateral, fora dos destaques ---------------------------------
   Para blocos que também são um par de colunas — o desenho da planta e o
   texto ao lado dele. Mesmas contas dos destaques: meia largura da própria
   coluna, um quarto de escala a mais, meio segundo e a mesma curva. Aqui o
   lado é dito por classe (--esq/--dir) e não por :nth-child, porque é um par
   único e não uma lista que alterna. */
.js .st-lado[data-reveal] {
  opacity: 0;
  transition: opacity 0.5s cubic-bezier(0, 0, 0.2, 1),
    transform 0.5s cubic-bezier(0, 0, 0.2, 1);
}
.js .st-lado--esq[data-reveal] { transform: translateX(-50%) scale(1.25); }
.js .st-lado--dir[data-reveal] { transform: translateX(50%) scale(1.25); }
/* Uma classe a mais do que as duas de cima: ganha por peso, não por ordem —
   assim as variantes por media query nunca podem tapar o estado final. */
.js .st-lado[data-reveal].is-visible { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .js .st-surge[data-reveal],
  .js .st-lado[data-reveal] { opacity: 1; transform: none; }
}
.st-destaques {
  display: grid;
  gap: clamp(2rem, 3.8vw, 3rem);
  /* A animação atira as peças meia largura para fora da coluna. Sem isto, a
     página ganhava barra de deslocamento horizontal enquanto elas entram — o
     homag.com corta no contentor pela mesma razão. */
  overflow: hidden;
}
.st-destaque {
  display: grid;
  grid-template-columns: 7fr 5fr;
  gap: clamp(1.5rem, 3.6vw, 2.9rem);
  align-items: center;
  /* Lado de onde a fotografia entra; o texto entra sempre do lado oposto.
     Troca de sinal nas entradas pares, mais abaixo.
     50% da largura da própria coluna, que é o que o homag.com usa: a matriz
     deles dá 341px numa coluna de 683 e 237px numa de 475 — 0,4998 e 0,4997.
     (Cuidado a ler estas matrizes: com o translate antes do scale, o valor
     que lá aparece já é o deslocamento, não se divide pela escala. Dividir
     dava 40% e estaria errado.) */
  --de-x: -50%;
  --de-y: 0px;
  --de-s: 1.25;
}
/* Sem fundo. Era o --paper-soft, para a caixa se ler como um painel enquanto
   a fotografia não chegava; saiu a 10 de Agosto de 2026, a pedido do Diogo.
   Nas fotografias de cena (Striebig, Comeva, Leuco) nunca se via — o
   object-fit: cover tapa a caixa toda —, mas nos renders da Martin, que são
   máquinas recortadas sobre fundo liso, era ele que fazia os cinco
   rectângulos cinzentos.
   A outra metade disto está no fotos-martin.ps1: a cor também entrava nos
   JPEG. Mexer só aqui não chegava. */
.st-destaque__media {
  aspect-ratio: 16 / 9;
  overflow: hidden;
}
.st-destaque__media img { width: 100%; height: 100%; object-fit: cover; }
.st-destaque__texto {
  margin: 0;
  font-size: clamp(1.02rem, 0.96rem + 0.3vw, 1.12rem);
  line-height: 1.55;
  color: var(--ink);
}
/* Como no original: o realce não muda de cor, só de peso. */
.st-destaque__texto strong { font-weight: 700; color: inherit; }

/* --- Destaques que são marcas (página inicial) ---------------------------
   Na Striebig cada destaque é uma função da máquina e basta-lhe um parágrafo.
   Na página inicial cada um é uma MARCA, e uma marca tem de se apresentar
   pelo nome e levar a algum lado — daí o nome, a linha de origem e a seta,
   que o padrão dos destaques não tem. É tudo o que se acrescenta: a grelha
   7fr/5fr, a alternância de lado e a animação são exactamente as mesmas.

   Continuam a ser DOIS filhos na grelha, e não cinco. O que era um <p> passa
   a ser um <div> com o mesmo .st-destaque__texto e o resto lá dentro: assim
   as regras da animação, que apontam a .st-destaque__media e a
   .st-destaque__texto, continuam a apanhar a coluna inteira sem se lhes
   tocar. Meter o nome e a seta como irmãos partia a grelha.

   AS FOTOGRAFIAS. As das marcas vêm achatadas sobre branco, ao contrário das
   fotografias de cena da página da Striebig. Com object-fit: cover a Comeva,
   que está fotografada quase ao quadrado (1,166), perdia um terço da altura
   — a cabeça preta em cima e a base em baixo. Aqui é contain, e o multiply
   faz o branco desaparecer como já fazia nas vitrines.
   Efeito lateral bom: a caixa continua 16:9 e é ela que iguala a altura das
   quatro. Deixa de ser preciso o 65,8% que a vitrine da Comeva precisava. */
/* O `background: none` que aqui estava saiu com o fundo da caixa base: já não
   há cinzento nenhum para desligar. */
.st-destaque__media--produto img {
  object-fit: contain;
  mix-blend-mode: multiply;
}

.st-destaque__nome {
  margin: 0;
  font-size: clamp(1.4rem, 0.95rem + 1.2vw, 2.1rem);
  line-height: 1.1;
}
/* Mesma linha de origem das vitrines, para as marcas se lerem da mesma
   maneira em qualquer sítio do site. */
.st-destaque__origem {
  margin: 0.4rem 0 clamp(0.85rem, 1.8vw, 1rem);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.st-destaque__frase { margin: 0; }
.st-destaque--marca .st-botao { margin-top: clamp(1.1rem, 2.2vw, 1.5rem); }

/* Entradas pares: a fotografia passa para a direita e os dois lados trocam
   o sentido de entrada.

   As colunas TÊM de trocar com ela. O `order` muda só o lugar visual, não a
   largura da faixa: com as colunas fixas em 7fr 5fr, mandar a fotografia
   para segundo punha-a na faixa estreita e ela ficava mais pequena do que
   nas entradas ímpares (504 contra 706 a 1920). Invertendo também as faixas,
   a fotografia fica nos 7fr das duas maneiras. O homag.com não tropeça nisto
   porque põe o vão no próprio elemento (col-span-7), e aí ele viaja junto. */
.st-destaque:nth-child(even) {
  grid-template-columns: 5fr 7fr;
  --de-x: 50%;
}
.st-destaque:nth-child(even) .st-destaque__media { order: 2; }

/* Animação. Só existe com JavaScript — sem a classe .js nada disto pega e o
   conteúdo fica à vista, que é o que tem de acontecer se o guião falhar.
   Escondido: opacidade 0, deslocado 40% da largura da própria coluna e um
   quarto maior. Visível: assenta em nada. Meio segundo, com a mesma curva do
   original, cubic-bezier(0, 0, 0.2, 1). */
.js .st-destaque[data-reveal] {
  /* Anula o [data-reveal] geral da secção 19, que sobe 22px na vertical:
     aqui quem se move são os filhos, e na horizontal. */
  opacity: 1;
  transform: none;
  transition: none;
}
.js .st-destaque[data-reveal] .st-destaque__media,
.js .st-destaque[data-reveal] .st-destaque__texto {
  opacity: 0;
  transition: opacity 0.5s cubic-bezier(0, 0, 0.2, 1),
    transform 0.5s cubic-bezier(0, 0, 0.2, 1);
}
.js .st-destaque[data-reveal] .st-destaque__media {
  transform: translate(var(--de-x), var(--de-y)) scale(var(--de-s));
}
.js .st-destaque[data-reveal] .st-destaque__texto {
  transform: translate(calc(var(--de-x) * -1), var(--de-y)) scale(var(--de-s));
}
/* O sentido vive todo em --de-x, e não em selectores: assim estas duas
   regras ganham por especificidade (uma classe a mais) e não por virem
   depois. Foi de propósito — as variantes por media query mexem só na
   variável e nunca podem tapar o estado final. */
.js .st-destaque[data-reveal].is-visible .st-destaque__media,
.js .st-destaque[data-reveal].is-visible .st-destaque__texto {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .js .st-destaque[data-reveal] .st-destaque__media,
  .js .st-destaque[data-reveal] .st-destaque__texto {
    opacity: 1;
    transform: none;
  }
}

/* --- Cartões dos modelos ------------------------------------------------- */
.st-modelos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 258px), 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
  margin: 0;
  padding: 0;
  list-style: none;
}
.st-modelo {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease),
    border-color 0.3s var(--ease);
}
.st-modelo:hover { transform: translateY(-4px); box-shadow: var(--shadow); border-color: var(--teal-mid); }
/* Fotografia achatada sobre branco: o multiply apaga-lhe o fundo contra o
   branco do cartão, tal como nos .model-card. */
.st-modelo__media { padding: 1rem 1rem 0; }
.st-modelo__media img {
  width: 100%;
  height: auto;
  mix-blend-mode: multiply;
  transition: transform 0.5s var(--ease);
}
.st-modelo:hover .st-modelo__media img { transform: scale(1.04); }
.st-modelo__corpo {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: 0.7rem;
  padding: 0.85rem 1.25rem 1.3rem;
}
.st-modelo__nome { margin: 0; font-size: var(--step-1); }
/* O min-height vale duas linhas (2 × 1.5em = 3em) e é o que mantém os cartões
   todos da mesma altura.

   Sem ele a altura do cartão passa a depender do comprimento da frase, e não
   há frase que sirva: a grelha vai de 258px (o piso do minmax) até uns 390px,
   e nesse intervalo a mesma tagline quebra em duas linhas na largura pequena e
   assenta numa só na grande. Ficava sempre uma linha de cartões mais baixa do
   que as outras, conforme a largura da janela. Já aconteceu duas vezes, com
   frases diferentes.

   Só cresce, nunca corta: uma tagline de três linhas continua a ocupar três.
   Por isso o limite continua a ser caber em duas a 258px — o que se confere
   forçando essa largura e contando as linhas. */
.st-modelo__tagline {
  margin: 0;
  min-height: 3em;
  font-size: 0.87rem;
  line-height: 1.5;
  color: var(--muted);
}
.st-modelo__specs {
  display: grid;
  gap: 0.32rem;
  margin: 0;
  padding-top: 0.75rem;
  border-top: 1px solid var(--line-soft);
  font-size: 0.79rem;
}
.st-modelo__specs > div { display: flex; justify-content: space-between; gap: 0.75rem; }
.st-modelo__specs dt { color: var(--muted); }
.st-modelo__specs dd { margin: 0; font-weight: 600; text-align: right; }
.st-modelo .link-arrow { margin-top: auto; padding-top: 0.5rem; align-self: flex-start; }

/* Oitava célula, sem máquina. Não é enfeite: os modelos são sete, e sete é
   primo — a grelha dava sempre uma linha final com um cartão sozinho (3+3+1 a
   1280). Com oito células fica 4+4 a 1920 e 3+3+2 a 1280, e a pergunta cai
   exactamente onde alguém está a comparar. */
/* Miniatura do bloco de contacto do fim da página: mesma receita — retrato
   em 3:2 no topo, gradiente por baixo, texto centrado e botão em cápsula —
   reduzida ao tamanho do cartão. */
.st-modelo--ajuda {
  padding: 0;
  overflow: hidden;
  border-color: transparent;
  background: linear-gradient(to bottom, var(--teal), var(--ink));
  text-align: center;
}
.st-modelo--ajuda:hover { border-color: var(--teal-mid); }
.st-modelo__retrato { aspect-ratio: 3 / 2; overflow: hidden; }
.st-modelo__retrato img { width: 100%; height: 100%; object-fit: cover; }
.st-modelo__convite {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 1.15rem 1.1rem 1.4rem;
}
.st-modelo__pergunta {
  margin: 0;
  font-family: var(--font-body);
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.25;
  color: #fff;
}
.st-modelo__pergunta span { color: var(--realce-escuro); }
.st-modelo__botao {
  display: inline-block;
  padding: 0.58rem 1.35rem;
  background: var(--teal-mid);
  color: var(--ink);
  border-radius: 9999px;
  font-size: 0.85rem;
  font-weight: 700;
  transition: background-color 0.2s var(--ease);
}
.st-modelo__botao:hover { background: #fff; }

/* --- Tabela comparativa -------------------------------------------------
   A coluna do modelo cola à esquerda enquanto se arrasta a tabela na
   horizontal — é a única forma de sete colunas de números serem legíveis num
   ecrã estreito sem partir a tabela em cartões. */
.st-tabela-caixa {
  margin-top: clamp(1.75rem, 4vw, 2.75rem);
  overflow-x: auto;
  background: #fff;
  border: 1px solid var(--line);
}
.st-tabela { width: 100%; border-collapse: collapse; font-size: 0.84rem; }
.st-tabela caption {
  padding: 1rem 1.25rem;
  text-align: left;
  font-size: 0.8rem;
  color: var(--muted);
  border-bottom: 1px solid var(--line);
}
.st-tabela th,
.st-tabela td {
  padding: 0.75rem 1rem;
  text-align: left;
  vertical-align: top;
  white-space: nowrap;
  border-bottom: 1px solid var(--line-soft);
}
.st-tabela thead th {
  background: var(--paper);
  font-family: var(--font-body);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
}
.st-tabela td { color: var(--muted); font-variant-numeric: tabular-nums; }
.st-tabela tbody th[scope="row"] {
  position: sticky;
  left: 0;
  z-index: 1;
  background: #fff;
  border-right: 1px solid var(--line);
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 700;
}
.st-tabela tbody tr:last-child th,
.st-tabela tbody tr:last-child td { border-bottom: 0; }
/* Depois da regra da coluna colada, senão perdia por ter a mesma
   especificidade e o fundo branco tapava o realce da linha. */
.st-tabela tbody tr:hover th[scope="row"],
.st-tabela tbody tr:hover td { background: var(--paper-soft); }

/* --- Bloco de contacto ---------------------------------------------------
   Cópia do painel de contacto do homag.com, medido no próprio no estado
   aberto. Todos os números abaixo saíram de lá:

     cartão        branco, raio 6px, sombra rgba(0,0,0,.15) 0 0 6px 0
                   — igual dos quatro lados, é ela que dá o volume
     colunas       340px à esquerda e 680px à direita, ou seja 1 para 2
     esquerda      gradiente vertical (#0c5d93 → #053059), texto ao centro,
                   enchimento 32px em cima e nos lados, 95px em baixo
     fotografia    3:2, object-fit: cover
     pergunta      20,4px, entrelinha 25,5 (1,25), branca, com a parte
                   destacada num span da cor de realce
     painel dir.   enchimento 64px em cima, 48px nos lados e em baixo
     campos        fundo #f0f4f9, raio 4px, 9,8px por 24px, 14,7px de corpo,
                   sem filete nenhum
     grelha        2 colunas iguais, 16,56px na vertical e 24,31px na
                   horizontal
     botão         cápsula (raio 9999px), 7,74px por 20,69px, 16,56px de
                   corpo, peso normal, centrado
     nota          16,56px, por baixo do botão

   Só as cores é que são as nossas: o teal no lugar do azul deles.

   O botão levava --teal com texto branco, porque --teal-mid com texto branco
   não chega aos 4,5:1. A saída não era escurecer o fundo — era escurecer o
   TEXTO: --teal-mid com a tinta por cima dá 6,04, e é assim que o "Fale
   connosco" do cartão de ajuda sempre esteve. Os três botões cheios do fim da
   página usam agora essa mesma paleta. */
/* A cor do rodapé sobe por trás do cartão e começa exactamente a meio dele,
   para se perceber que a página está a acabar. Daí para baixo é tudo escuro
   até ao fim, sem costura: cartão, newsletter e rodapé real.

   O 50% é exacto e não precisa de saber a altura do cartão. O palco não tem
   enchimento nenhum na vertical e só contém o cartão, por isso mede
   exactamente o mesmo que ele — e metade do palco é metade do cartão. */
/* Ritmo entre grupos: todos com o mesmo enchimento e mais curto do que o
   .section do resto do site (que dá 96px a 1920). Assim o espaço entre dois
   grupos é sempre o mesmo — 2 × 44px — e a página fecha-se mais. */
.st-grupo { padding-block: clamp(1.75rem, 3vw, 2.75rem); }

.st-contacto {
  padding-top: clamp(1.75rem, 3vw, 2.75rem);
  padding-bottom: 0;
}
.st-contacto__palco { position: relative; isolation: isolate; }
.st-contacto__palco::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 50%;
  bottom: 0;
  /* Liso: quem faz o fade é só o rodapé. Ver os tokens na secção 2. */
  background: var(--rodape);
  z-index: -1;
}

/* --- Fecho: newsletter sobre o escuro ------------------------------------
   Medido no rodapé do homag.com:
     título      34,22px, negrito, entrelinha 51,33 (1,5), 16,56px abaixo
     texto       20,41px, entrelinha 30,61 (1,5), 32,07px abaixo, ~1040px
     botão       cápsula, 12,76px por 23,19px, 18,56px de corpo, peso normal
   Tudo centrado e branco sobre o escuro.

   A risca no fim tem a largura do conteúdo, não do ecrã, e usa o mesmo
   rgba(255,255,255,.12) do filete que o rodapé já tinha. */
.st-fecho { background: var(--rodape); color: #fff; text-align: center; }
.st-fecho__miolo {
  padding-block: clamp(2.5rem, 5vw, 4rem);
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
.st-fecho__titulo {
  margin: 0 0 16.56px;
  font-family: var(--font-body);
  font-size: clamp(1.5rem, 1.15rem + 1.35vw, 2.14rem);
  font-weight: 700;
  line-height: 1.5;
  color: #fff;
}
.st-fecho__texto {
  max-width: 65ch;
  margin: 0 auto 32.07px;
  font-size: clamp(1.02rem, 0.94rem + 0.36vw, 1.275rem);
  line-height: 1.5;
  color: #fff;
}
/* Cores do "Fale connosco" (cheio de --teal-mid, texto em tinta, branco no
   hover) na caixa do .st-botao. Contraste: 6,04 em repouso, 16,04 no hover.

   O CORPO SUBIU DE 13,6 PARA 14,72px e o enchimento de 12,76/23,19px para
   1,15/2,2rem. A 13,6 — que é o corpo exacto do "Fale connosco" — este ficava
   pequeno de mais, e com razão: lá é um botão dentro de um cartão de 296px,
   aqui é a última chamada da página, sozinha numa faixa à largura toda. O que
   se copia do outro é a paleta e o peso da letra; a caixa é a dos botões das
   marcas, para o mesmo papel ter o mesmo tamanho em toda a página.

   O line-height está escrito pela mesma razão que no .st-botao: herdado, a
   altura mudava conforme o bloco onde o botão estivesse. */
.st-fecho__botao {
  display: inline-block;
  padding: 1.15rem 2.2rem;
  background: var(--teal-mid);
  color: var(--ink);
  border-radius: 9999px;
  font-family: var(--font-body);
  font-size: 0.92rem;
  font-weight: 700;
  line-height: 1.68;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}
.st-fecho__botao:hover { background: #fff; }

.st-contacto__caixa {
  display: grid;
  grid-template-columns: 1fr 2fr;
  background: #fff;
  border-radius: 6px;
  overflow: hidden;
  box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.15);
}

.st-contacto__lado {
  display: flex;
  flex-direction: column;
  background: linear-gradient(to bottom, var(--teal), var(--ink));
  color: #fff;
  text-align: center;
}
/* 3:2 e a cortar, como lá. A fotografia entra por cima do gradiente sem
   caixa própria — nada de multiply aqui, que precisaria de fundo claro. */
.st-contacto__foto { aspect-ratio: 3 / 2; overflow: hidden; }
.st-contacto__foto img { width: 100%; height: 100%; object-fit: cover; }

/* A pergunta ocupa o corpo do painel e os contactos assentam na base, um em
   cada canto — telefone à esquerda, email à direita — como na captura. É o
   `margin-bottom: auto` da pergunta que os empurra para baixo. */
/* O `flex: 1` não é enfeite: sem ele o painel fica do tamanho do texto, não
   sobra espaço livre, e o `margin-bottom: auto` da pergunta não tem nada
   para consumir — os contactos ficavam colados a ela, a meio da coluna, em
   vez de assentarem na base. */
.st-contacto__convite {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 32px 32px 30px;
}

/* Fonte de texto a negrito, não a de títulos. */
.st-contacto__pergunta {
  margin: 0 0 auto;
  padding-bottom: 2rem;
  font-family: var(--font-body);
  font-size: clamp(1.45rem, 1.1rem + 1.15vw, 2.1rem);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: 0;
}
.st-contacto__pergunta span { color: var(--realce-escuro); }
.st-contacto__vias {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem 0.75rem;
  font-family: var(--font-body);
  /* Tecto em 0,9rem (14,4px). Medido a 1920: com o indicativo +351 os dois
     contactos somam 337px numa coluna que oferece 355 — cabem lado a lado
     numa linha só, com 18px de folga. A 15,2px somavam 353 e o flex encolhia
     o telefone, partindo-o em duas linhas. */
  font-size: clamp(0.8rem, 0.5rem + 0.5vw, 0.9rem);
  font-weight: 700;
  line-height: 1.5;
}
/* Sem encolher nem partir: em vez de espremer o número, prefere-se passar
   os dois para linhas separadas quando a coluna aperta. */
.st-contacto__vias li {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  flex: 0 0 auto;
  white-space: nowrap;
}
.st-contacto__vias svg { color: var(--teal-mid); flex-shrink: 0; }
.st-contacto__vias a { color: #fff; transition: color 0.2s var(--ease); }
.st-contacto__vias a:hover { color: var(--teal-mid); }

.st-contacto__painel { padding: clamp(1.5rem, 3.4vw, 4rem) clamp(1.5rem, 2.5vw, 3rem) clamp(1.5rem, 2.5vw, 3rem); }

.st-form__grelha {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16.56px 24.31px;
}
.st-campo { margin: 0; }
.st-campo--largo { grid-column: 1 / -1; }
.st-campo input,
.st-campo select,
.st-campo textarea {
  width: 100%;
  padding: 9.8px 24px;
  background: var(--paper-soft);
  border: 0;
  border-radius: 4px;
  font-family: var(--font-body);
  font-size: 0.92rem;
  color: var(--ink);
  transition: box-shadow 0.2s var(--ease);
}
.st-campo textarea { resize: vertical; min-height: 8rem; padding-block: 14px; }
.st-campo ::placeholder { color: var(--muted-2); opacity: 1; }
/* Filete só ao focar, e por sombra, para o campo não mudar de altura. */
.st-campo input:focus,
.st-campo select:focus,
.st-campo textarea:focus { outline: 0; box-shadow: inset 0 0 0 1px var(--teal-mid); }

.st-form__caixinha {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  margin: 1.1rem 0 0;
  font-size: 0.92rem;
  color: var(--ink);
}
.st-form__caixinha input { flex-shrink: 0; width: 1rem; height: 1rem; accent-color: var(--teal); }

/* Botão e nota centrados, um por cima do outro, como no original. */
.st-form__fim { margin-top: 1.75rem; text-align: center; }
/* As mesmas cores e a mesma letra dos outros dois: Inter 14,72px a 700, sem
   maiúsculas. Era 16,48px a 400.

   Fica um degrau abaixo do botão da newsletter — 52px de altura contra 62 —
   e é de propósito. Este vive dentro do cartão, ao lado de campos com 9,8px
   de enchimento; à altura do outro passava a ser a coisa mais pesada do
   formulário e roubava a atenção aos campos que é suposto preencherem-se
   primeiro. A letra é a mesma, que é o que os faz ler como família.

   O anel é um box-shadow para dentro e não um border, para não crescer 2px.
   Em repouso é da cor do preenchimento e não se vê; serve para o hover, que
   enche de branco — este botão está dentro do cartão branco, ao contrário
   dos outros dois, que estão sobre escuro, e sem o anel desaparecia. */
.st-form__botao {
  padding: 0.85rem 1.9rem;
  min-width: 8rem;
  background: var(--teal-mid);
  color: var(--ink);
  border: 0;
  border-radius: 9999px;
  box-shadow: inset 0 0 0 1px var(--teal-mid);
  font-family: var(--font-body);
  font-size: 0.92rem;
  font-weight: 700;
  line-height: 1.68;
  cursor: pointer;
  transition: background-color 0.2s var(--ease);
}
.st-form__botao:hover { background: #fff; }
.st-form__botao:disabled { opacity: 0.55; cursor: default; }
.st-form__nota { margin: 0.9rem 0 0; font-size: 0.84rem; color: var(--muted); }
.st-form__nota a { color: var(--teal); text-decoration: underline; text-underline-offset: 3px; }
.st-form__nota a:hover { color: var(--teal-mid); }

/* --- Ecrãs estreitos ----------------------------------------------------
   Sempre depois das regras base: com igual especificidade ganha a última. */
@media (max-width: 900px) {
  .st-duas { grid-template-columns: 1fr; }
  .st-contacto__caixa { grid-template-columns: 1fr; }
  /* Em coluna única não há lado nenhum de onde entrar: passa a subir, como o
     resto da página. */
  .js .st-lado--esq[data-reveal],
  .js .st-lado--dir[data-reveal] { transform: translateY(22px); }
  .st-factos__lista { grid-template-columns: repeat(2, 1fr); }
  .st-facto:nth-child(odd) { border-left: 0; padding-left: 0; }
  .st-facto:nth-child(n + 3) { border-top: 1px solid var(--line); }
}

/* 719px e não outro número qualquer: é o limite de baixo do LARGO = 720 do
   initVideoHero(). Os dois têm de andar juntos — se este subir sem o outro,
   há uma faixa de larguras em que o filme toca sem escurecimento nenhum por
   cima e o título branco fica ilegível sobre a oficina. */
@media (max-width: 719px) {
  /* Sem filme fica a cor de tinta, e o escurecimento da esquerda deixa de
     ter razão de ser: passa a parelho, para o cartaz não ganhar um degradé
     sem nada por baixo. */
  .st-hero { min-height: clamp(300px, 46vh, 420px); }
  .st-hero::after { background: none; }
  .st-hero__texto { max-width: none; }

  /* Excepção: o cabeçalho que tem FOTOGRAFIA em vez de filme (a martin.html,
     que não tem filme nenhum publicado pelo fabricante). Uma fotografia é um
     <img> normal — carrega em todas as larguras, ao contrário do filme, que o
     initVideoHero() trava nos 720px. Sem isto o título branco ficaria pousado
     em cima da oficina, que é exactamente a armadilha que o comentário aqui em
     cima descreve.

     Parelho e de baixo, e não da esquerda como no desktop: aqui o texto já
     ocupa a largura toda (.st-hero__texto perdeu o max-width três linhas
     acima), por isso um degradé lateral escureceria só metade do que precisa.

     Tem de ficar DEPOIS do .st-hero::after de cima: a especificidade é a
     mesma — uma classe e um pseudo-elemento — e nesse empate ganha a última.

     Os valores não são a olho. A 390px o object-fit:cover mostra a parte
     central da fotografia, que é onde estão as luminárias do tecto — o pixel
     mais claro por trás do subtítulo é quase branco. Medido pixel a pixel: com
     0,88/0,62/0,50 o subtítulo ficava em 3,75, abaixo do mínimo de 4,5. Assim
     dá 6,32, e o título 7,31. Baixar qualquer um destes três números obriga a
     medir outra vez. */
  .st-hero--foto::after {
    background: linear-gradient(to top,
      rgba(var(--ink-rgb), 0.92) 0%,
      rgba(var(--ink-rgb), 0.78) 55%,
      rgba(var(--ink-rgb), 0.72) 100%);
  }
}

@media (max-width: 820px) {
  /* As pares têm de vir nomeadas: a regra delas lá em cima tem uma classe a
     mais e ganharia a esta, mesmo estando dentro de uma media query. */
  .st-destaque,
  .st-destaque:nth-child(even) { grid-template-columns: 1fr; }
  .st-destaque:nth-child(even) .st-destaque__media { order: 0; }
  /* Em coluna única não há lado nenhum de onde entrar: passa a subir, como
     o resto da página. Mexe só nas variáveis — o estado final continua a ser
     decidido pela regra do .is-visible, que ganha por especificidade. */
  .st-destaque,
  .st-destaque:nth-child(even) { --de-x: 0%; --de-y: 22px; --de-s: 1; }
}

@media (max-width: 560px) {
  .st-form__grelha { grid-template-columns: 1fr; }
}

@media (max-width: 520px) {
  .st-factos__lista { grid-template-columns: 1fr; }
  .st-facto { border-left: 0; padding-left: 0; }
  .st-facto + .st-facto { border-top: 1px solid var(--line); }
  .st-pilar { grid-template-columns: 1fr; gap: 0.35rem; }
}

/* --------------------------------------------------------------------------
   22. Novidades e Feiras

   Duas coisas: o cartão de uma feira (.st-feira), que é o cartão de modelo da
   secção 21 crescido à largura toda, e a janela de fotografias (.st-galeria)
   que ele abre. Tudo com o prefixo .st-, como o resto do padrão, e num bloco
   só para se poder apagar de uma vez.

   Quem liga as duas pontas é o initGaleria() do main.js.
   -------------------------------------------------------------------------- */

/* --- Cabeçalho sem media -------------------------------------------------
   O .st-hero da secção 21 conta com um filme ou uma fotografia por baixo, e
   o ::after dele é um escurecimento pesado da esquerda que só existe para os
   tapar. Sem imagem nenhuma esse degradé pintava uma sombra sobre nada — o
   cabeçalho ficava sujo de um lado e chapado do outro.

   Aqui a faixa É o gradiente: do teal do logótipo para a tinta, na diagonal,
   com as linhas hexagonais por marca de água. O ::after passa a não pintar
   nada, senão tapava-as (é gerado depois de todos os filhos e, com o mesmo
   z-index, ganhava-lhes).

   Contraste medido contra o ponto mais claro do gradiente (--teal-deep):
   título branco 10,06 e subtítulo 10,06 — bem acima do mínimo. */
.st-hero--liso {
  background: linear-gradient(150deg, var(--teal-deep) 0%, var(--ink) 58%, #0f1a20 100%);
}
.st-hero--liso::after { background: none; }

/* --- Lista de feiras -----------------------------------------------------
   Uma coluna, sempre. Cada feira é uma faixa à largura toda, e não um cartão
   numa grelha: com uma feira só, uma grelha de mínimos deixava-a esticada e
   vazia; com duas, faixas seguidas continuam a ler-se de uma assentada, que é
   como se lê um calendário. */
.st-feiras {
  display: grid;
  gap: clamp(1rem, 2vw, 1.5rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* O cartão de modelo da secção 21, crescido: mesmo branco, mesmo filete,
   mesmo raio e o mesmo levantar de 4px ao passar o rato. O que muda é a
   escala — cartaz à esquerda em 5fr, informação à direita em 7fr — e o
   position: relative, que é onde o botão de cobrir se agarra. */
.st-feira {
  position: relative;
  display: grid;
  grid-template-columns: 5fr 7fr;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease),
    border-color 0.3s var(--ease);
}
.st-feira:hover { transform: translateY(-4px); box-shadow: var(--shadow); border-color: var(--teal-mid); }

/* Pelo mesmo motivo do .st-modelo: a regra do .st-surge tem quatro classes e
   mataria o transform do hover, que só tem duas. */
.js .st-feira.st-surge[data-reveal].is-visible:hover { transform: translateY(-4px); }

/* --- O cartaz ------------------------------------------------------------
   Três camadas, como o cabeçalho da Striebig: a arte da feira em baixo
   (z-index -2), um escurecimento por cima dela (-1) e o texto por último.
   O isolation cria o contexto de empilhamento onde os negativos ficam por
   trás do texto sem escaparem da caixa.

   O fundo continua a ser o gradiente da paleta e não é enfeite: é o que se vê
   se a fotografia faltar ou ainda não tiver chegado, e o cartaz lê-se na
   mesma. */
.st-feira__cartaz {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: clamp(230px, 24vw, 330px);
  padding: clamp(1.5rem, 3vw, 2.5rem);
  background: linear-gradient(150deg, var(--teal) 0%, var(--ink) 80%);
  color: #fff;
}
.st-feira__foto {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* O escurecimento. Anda casado com o alinhamento do texto, que vive à
   esquerda: pesado desse lado e a aliviar para a direita, onde não passa
   texto nenhum e a arte da feira se vê inteira.

   Os valores não são a olho. A arte tem uma zona creme quase branca no canto
   superior direito, e a caixa muda de forma — 523×455 a 1920, 375×567 a 1280,
   e uma faixa de 811×179 abaixo dos 900 —, por isso o object-fit: cover traz
   pixels diferentes para debaixo do texto em cada largura.

   Medido pixel a pixel sobre a arte, com estas duas camadas compostas por
   cima, e SÓ na caixa real dos glifos: um <p> ocupa a largura toda mesmo
   quando a palavra é curta, e medir a caixa do bloco dava valores de 2,05 que
   não existem em lado nenhum — o texto nunca lá chega.

     largura   pior par            onde acaba o texto
     1920      7,48  (travessão)   50% da largura
     1280      5,37  (a data)      66%  ← o pior de todos
     900       7,38  (travessão)   24%
     390       7,49  (travessão)   43%

   É a 1280 que aperta: a coluna do cartaz estreita para 375 mas a data
   mantém o corpo, por isso é a largura em que ela mais se estende para a
   direita, onde o escurecimento já aliviou. Baixar qualquer uma destas
   paradas obriga a medir outra vez.

   A segunda camada, de baixo para cima, assenta o cartaz: sem ela a arte
   encostava crua ao filete do cartão. */
.st-feira__cartaz::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(to right,
      rgba(var(--ink-rgb), 0.93) 0%,
      rgba(var(--ink-rgb), 0.88) 42%,
      rgba(var(--ink-rgb), 0.55) 74%,
      rgba(var(--ink-rgb), 0.26) 100%),
    linear-gradient(to top,
      rgba(var(--ink-rgb), 0.45) 0%,
      rgba(var(--ink-rgb), 0) 55%);
}
/* --realce-escuro e não --teal-mid: sobre o topo do gradiente o vivo dá 4,68
   e o outro não chega aos 4,5. É a mesma regra da secção 21b. */
.st-feira__etiqueta {
  margin: 0 0 0.7rem;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--realce-escuro);
}
.st-feira__dia {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 1.6rem + 3.4vw, 4.6rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: #fff;
}
/* O travessão mais pequeno e destacado: sem isto os dois números colavam-se
   e liam-se como um só de quatro algarismos. */
.st-feira__dia span {
  display: inline-block;
  margin-inline: 0.12em;
  font-size: 0.5em;
  vertical-align: middle;
  color: var(--realce-escuro);
}
.st-feira__mes {
  margin: 0.55rem 0 0;
  font-family: var(--font-body);
  font-size: clamp(0.95rem, 0.88rem + 0.3vw, 1.15rem);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #dbe6e8;
}

/* --- A informação --------------------------------------------------------
   Coluna flexível para o botão poder assentar na base com margin-top: auto,
   como o .link-arrow dos cartões de modelo. */
.st-feira__corpo {
  display: flex;
  flex-direction: column;
  padding: clamp(1.5rem, 3vw, 2.5rem);
}
.st-feira__local {
  margin: 0 0 0.5rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.st-feira__nome {
  margin: 0 0 0.9rem;
  font-size: clamp(1.6rem, 1.2rem + 1.35vw, 2.4rem);
  line-height: 1.1;
}
/* O mesmo corpo e a mesma entrelinha do texto dos destaques, para as duas
   páginas se lerem da mesma maneira. */
.st-feira__texto {
  margin: 0;
  max-width: 62ch;
  font-size: clamp(1.02rem, 0.96rem + 0.3vw, 1.12rem);
  line-height: 1.55;
  color: var(--ink);
}
.st-feira__texto strong { font-weight: 700; color: inherit; }

/* Os dados da feira, no molde do .st-modelo__specs mas com o rótulo por cima
   e o valor por baixo — aqui os valores são frases, não caberiam alinhados à
   direita.

   Flex com quebra, e não uma grelha de três colunas: as três frases medem
   449px e a coluna do texto tem 448 a 1280, ou seja ficavam a bater na
   parede. Com flex-wrap, a que não couber passa para a linha de baixo em
   qualquer largura, sem precisar de uma media query por medida. */
.st-feira__dados {
  display: flex;
  flex-wrap: wrap;
  /* As três medem 457px de texto: cabem lado a lado nos 652 da coluna a 1920
     e não cabem nos 448 a 1280, onde a terceira desce sozinha. É por isso que
     isto é flex com quebra e não uma grelha de três — a grelha empurrava-as
     umas contra as outras em vez de as deixar mudar de linha. */
  gap: 0.9rem clamp(1.25rem, 2vw, 2.5rem);
  margin: clamp(1.25rem, 2.5vw, 1.75rem) 0 0;
  padding-top: clamp(1rem, 2vw, 1.35rem);
  border-top: 1px solid var(--line-soft);
}
.st-feira__dados dt {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.st-feira__dados dd {
  margin: 0.3rem 0 0;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--ink);
}

/* Parece um botão mas é um <span>: quem recebe o clique é o .st-feira__abrir,
   que cobre o cartão inteiro. Por isso não tem :hover próprio — enche-se
   quando o rato está em qualquer sítio do cartão. */
.st-feira__cta {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  align-self: flex-start;
  margin-top: clamp(1.35rem, 2.5vw, 1.9rem);
  padding: 0.85rem 1.6rem;
  border: 1px solid var(--teal);
  border-radius: 9999px;
  color: var(--teal);
  font-family: var(--font-body);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  transition: background-color 0.22s var(--ease), color 0.22s var(--ease),
    border-color 0.22s var(--ease);
}
.st-feira:hover .st-feira__cta { background: var(--teal); color: #fff; }

/* Enquanto não houver fotografias, o botão diz "Fotografias em breve" e fica
   apagado — continua a abrir a janela, que explica porquê. A classe é posta
   pelo initGaleria() quando a fonte não tem <figure> nenhum, e cai sozinha
   assim que se acrescentar o primeiro. */
.st-feira--sem-fotos .st-feira__cta { border-color: var(--line); color: var(--muted); }
.st-feira--sem-fotos:hover .st-feira__cta { background: var(--muted); border-color: var(--muted); color: #fff; }

/* O botão que cobre tudo. Transparente e sem filete: o que se vê ao navegar
   com o teclado é o anel de foco, à volta do cartão inteiro. */
.st-feira__abrir {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  border-radius: inherit;
  cursor: pointer;
}
.st-feira__abrir:focus-visible { outline: 3px solid var(--teal-mid); outline-offset: 3px; }

/* A fonte das fotografias é só dados para o JavaScript. Fica escondida com o
   atributo hidden do HTML; esta regra existe para o caso de alguém lhe tirar
   o atributo por engano. */
.st-galeria-fonte { display: none; }

/* --- Janela das fotografias ----------------------------------------------
   z-index 200: acima da barra de atalhos (80) e do cabeçalho (70), abaixo do
   "saltar para o conteúdo" (300), que tem de continuar a ser o primeiro de
   todos.

   O [hidden] precisa de regra própria: o display: grid aqui em cima ganha ao
   display: none que o browser dá ao atributo, e sem isto a janela ficava
   sempre aberta. */
.st-galeria {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: clamp(0.75rem, 3vw, 2.5rem);
  /* A entrada é uma animação e não uma transição de propósito: a animação
     arranca sozinha quando o elemento deixa de estar hidden, sem depender de
     um segundo quadro nem de requestAnimationFrame. */
  animation: st-galeria-entra 0.22s var(--ease);
}
.st-galeria[hidden] { display: none; }
@keyframes st-galeria-entra {
  from { opacity: 0; }
  to { opacity: 1; }
}
.st-galeria__fundo {
  position: absolute;
  inset: 0;
  background: rgba(var(--ink-rgb), 0.86);
  backdrop-filter: blur(3px);
}
.st-galeria__caixa {
  position: relative;
  display: flex;
  flex-direction: column;
  width: min(1100px, 100%);
  max-height: 100%;
  background: #fff;
  border-radius: 6px;
  overflow: hidden;
  /* A mesma sombra sem direcção do cartão de contacto. */
  box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.15);
}

/* Tudo o que muda de feira para feira vive aqui dentro e é reescrito de cada
   vez que a janela abre; o cabeçalho fica. O min-height: 0 é o que permite ao
   palco encolher em vez de empurrar a caixa para fora do ecrã. */
.st-galeria__miolo {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

.st-galeria__topo {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  padding: clamp(1rem, 2.2vw, 1.5rem) clamp(1rem, 2.2vw, 1.75rem);
  border-bottom: 1px solid var(--line);
}
.st-galeria__titulo {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.2rem, 1rem + 0.7vw, 1.6rem);
  font-weight: 700;
  line-height: 1.15;
  color: var(--ink);
}
.st-galeria__sub { margin: 0.3rem 0 0; font-size: 0.85rem; color: var(--muted); }
.st-galeria__fechar {
  flex: none;
  margin-left: auto;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--line);
  border-radius: 9999px;
  background: #fff;
  color: var(--ink);
  cursor: pointer;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease),
    border-color 0.2s var(--ease);
}
.st-galeria__fechar:hover { background: var(--ink); border-color: var(--ink); color: #fff; }

/* O palco é escuro porque as fotografias são de feira — fundos claros e
   iluminação de pavilhão. Sobre branco as bordas desapareciam. */
.st-galeria__palco {
  position: relative;
  display: grid;
  place-items: center;
  /* min-height: 0 num filho de flex é o que o deixa encolher em vez de
     empurrar a caixa para fora do ecrã. */
  min-height: 0;
  flex: 1;
  padding: clamp(0.75rem, 2vw, 1.25rem);
  background: var(--ink);
}
.st-galeria__figura { margin: 0; text-align: center; }
.st-galeria__figura img {
  display: block;
  max-width: 100%;
  max-height: 60vh;
  margin: 0 auto;
  object-fit: contain;
}
.st-galeria__figura figcaption {
  margin-top: 0.75rem;
  font-size: 0.84rem;
  color: #bcd7d9;
}

.st-galeria__seta {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 9999px;
  background: var(--teal-mid);
  color: var(--ink);
  cursor: pointer;
  transition: background-color 0.2s var(--ease);
}
.st-galeria__seta:hover { background: #fff; }
.st-galeria__seta--esq { left: clamp(0.5rem, 1.5vw, 1rem); }
.st-galeria__seta--dir { right: clamp(0.5rem, 1.5vw, 1rem); }
/* A mesma armadilha do .st-galeria[hidden]: um display escrito na regra ganha
   ao display: none que o browser dá ao atributo hidden. Com uma fotografia só
   o JavaScript esconde as setas e a tira — sem isto continuavam à vista. */
.st-galeria__seta[hidden] { display: none; }

.st-galeria__rodape {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: clamp(0.6rem, 1.6vw, 1rem) clamp(1rem, 2.2vw, 1.75rem);
  border-top: 1px solid var(--line);
}
/* Tira de miniaturas: rola na horizontal em vez de partir em linhas, para a
   altura da janela não mudar com o número de fotografias. */
.st-galeria__tiras {
  display: flex;
  gap: 0.5rem;
  overflow-x: auto;
  scrollbar-width: thin;
}
.st-galeria__tiras[hidden] { display: none; }
.st-galeria__tira {
  flex: none;
  width: 84px;
  height: 56px;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 3px;
  background: var(--paper-soft);
  overflow: hidden;
  cursor: pointer;
  opacity: 0.6;
  transition: opacity 0.2s var(--ease), border-color 0.2s var(--ease);
}
.st-galeria__tira img { width: 100%; height: 100%; object-fit: cover; display: block; }
.st-galeria__tira:hover { opacity: 1; }
.st-galeria__tira[aria-current="true"] { opacity: 1; border-color: var(--teal-mid); }
.st-galeria__conta {
  flex: none;
  margin: 0;
  margin-left: auto;
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

/* Estado sem fotografias. Não é um erro: é o estado normal de uma feira que
   ainda não aconteceu. */
.st-galeria__vazio {
  padding: clamp(2rem, 5vw, 3.5rem) clamp(1.25rem, 3vw, 2.5rem);
  text-align: center;
}
.st-galeria__vazio svg { color: var(--muted-2); }
.st-galeria__vazio p {
  max-width: 46ch;
  margin: 1rem auto 0;
  font-size: 1rem;
  line-height: 1.55;
  color: var(--muted);
}
/* Cápsula --teal com texto branco (9,16 sobre o branco do painel). O
   --teal-mid do .st-modelo__botao não servia aqui: ele clareia para branco no
   hover, o que sobre um painel branco o faria desaparecer. */
.st-galeria__botao {
  display: inline-block;
  margin-top: 1.5rem;
  padding: 0.8rem 1.7rem;
  background: var(--teal);
  color: #fff;
  border-radius: 9999px;
  font-size: 0.9rem;
  font-weight: 700;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}
.st-galeria__botao:hover { background: var(--teal-mid); color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .st-galeria { animation: none; }
}

/* --- Ecrãs estreitos ---------------------------------------------------- */
/* 900 e não 820 como os destaques: aqui a coluna estreita é o cartaz, e a
   data ("21—24" a 56px) media 284px num cartaz de 284 — encostava à parede
   exactamente à largura em que o bloco de contacto já tinha desistido das
   duas colunas. Os dois passam agora a coluna única no mesmo ponto. */
@media (max-width: 900px) {
  /* O cartaz por cima e a informação por baixo. A altura mínima cai: em
     coluna única ele passa a ser uma faixa, não uma coluna. */
  .st-feira { grid-template-columns: 1fr; }
  .st-feira__cartaz { min-height: 0; padding-block: clamp(1.35rem, 4vw, 1.75rem); }
  .st-feira__cta { align-self: stretch; justify-content: center; }
}

@media (max-width: 560px) {
  /* Empilhadas de qualquer maneira, e a esta largura o rótulo por cima do
     valor gastava seis linhas para dizer três coisas: passa a lado a lado. */
  .st-feira__dados { flex-direction: column; gap: 0.7rem; }
  .st-feira__dados > div { display: flex; align-items: baseline; gap: 0.75rem; }
  .st-feira__dados dt { flex: none; min-width: 5.5rem; }
  .st-feira__dados dd { margin: 0; }
  /* Numa janela estreita a tira de miniaturas rouba mais do que dá. */
  .st-galeria__tiras { display: none; }
  .st-galeria__conta { margin-left: 0; }
  .st-galeria__figura img { max-height: 52vh; }
}

/* --------------------------------------------------------------------------
   23. Exemplos de instalações

   Duas coisas: o carrossel (.st-carrossel) e a publicação do Instagram que ele
   mostra (.st-obra). Tudo com o prefixo .st-, como o resto do padrão, e num
   bloco só para se poder apagar de uma vez.

   A .st-obra é prima da .st-feira da secção 22 — mesmo cartão branco, mesmo
   filete, mesmo raio, mesma divisão em duas colunas. As classes são próprias e
   não partilhadas de propósito: são duas páginas diferentes e nenhuma deve
   partir a outra ao ser mexida.

   Quem faz o carrossel andar é o initCarrossel() do main.js.
   -------------------------------------------------------------------------- */

/* O título desta página é uma palavra de onze letras. A 1920 o corpo do
   .st-hero__titulo chega aos 92,8px e "INSTALAÇÕES" não cabe nos 40rem do
   .st-hero__texto — uma palavra só não parte ao meio, e o overflow: hidden do
   cabeçalho cortava-lhe o fim sem se perceber porquê. 52rem dão-lhe folga em
   todas as larguras; o texto continua encostado à esquerda, como no padrão. */
.st-hero--largo .st-hero__texto { max-width: 52rem; }

/* --- Carrossel -----------------------------------------------------------
   A caixa é que corta e o carrossel é que anima — a mesma divisão de trabalho
   dos .st-destaques. O .st-surge cresce a peça 8% à entrada, e 8% de um wrap
   de 1360 são 54px de cada lado: sem alguém a cortar por fora, a página
   ganhava barra de deslocamento horizontal nas larguras em que o wrap já não
   tem folga (a partir de ~1464px de conteúdo). */
.st-carrossel-caixa { overflow: hidden; }
.st-carrossel { position: relative; }

/* A pista é um deslizador com paragem obrigatória em cada publicação. O CSS
   sozinho já dá o essencial: arrasta-se com o dedo e pára no sítio certo, sem
   JavaScript nenhum. O initCarrossel() só lhe junta o que falta a quem usa
   rato ou teclado — setas, pontos e a conta.

   A barra de deslocamento do sistema fica escondida: cortava a base do cartão
   e a altura mudava de browser para browser. Quem não tem rato arrasta; quem
   tem usa as setas. */
.st-carrossel__pista {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.st-carrossel__pista::-webkit-scrollbar { display: none; }
.st-carrossel__pista:focus-visible { outline: 3px solid var(--teal-mid); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  .st-carrossel__pista { scroll-behavior: auto; }
}

/* --- Uma publicação ------------------------------------------------------
   flex: 0 0 100% é o que faz cada publicação medir a pista toda — é daí que
   sai a conta do initCarrossel(), que anda de clientWidth em clientWidth.

   Sem levantar ao passar o rato, ao contrário da .st-feira e do .st-modelo:
   este cartão não é um botão gigante, é um painel com um filme lá dentro e um
   link no fim. E a sombra do levantamento seria cortada pelo overflow da
   .st-carrossel-caixa, que existe por outra razão e não se pode tirar. */
.st-obra {
  flex: 0 0 100%;
  scroll-snap-align: start;
  display: grid;
  grid-template-columns: 4fr 8fr;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

/* A coluna da esquerda estica-se ao cartão todo para o filete do meio correr
   de cima a baixo; quem lhe manda na altura é o quadro aqui em baixo. */
.st-obra__media {
  position: relative;
  background: var(--paper-soft);
  border-right: 1px solid var(--line);
}

/* O embed oficial do Instagram, num iframe. A altura não é a olho: foi medida
   na própria página do embed, a 980px de largura. Uma publicação mede

     54px  da barra do perfil, em cima
     + largura × 1,25  do filme (é 4:5)
     + 154px  da barra de gostos e comentários, em baixo

   O truque do enchimento em percentagem é o que deixa somar as duas coisas: um
   enchimento em percentagem conta a partir da LARGURA, e não da altura, por
   isso calc(125% + 54px) dá exactamente a barra do perfil mais o filme, em
   qualquer largura e sem JavaScript.

   ATENÇÃO: a largura de que ele conta é a do BLOCO QUE O CONTÉM, não a dele
   próprio. Um max-width no quadro não trava a altura — o quadro estreita e a
   altura fica na mesma, que foi o que aconteceu aos 900px (420 de largura e
   1068 de altura, quando devia ser 579). Quem tem de ser estreitado é o
   .st-obra__media, e é isso que a media query lá em baixo faz.

   O iframe por dentro é 154px mais alto do que o quadro, e é assim que a barra
   dos gostos fica de fora do recorte: não serve de nada num site e deixava o
   cartão a acabar num rodapé que não é nosso. A barra do perfil fica — é ela
   que assina a publicação e diz de quem é.

   Se o Instagram mudar o desenho do embed, são estes dois números que têm de
   ser medidos outra vez. O 125% só muda se a publicação não for 4:5. */
.st-obra__quadro {
  position: relative;
  height: 0;
  padding-bottom: calc(125% + 54px);
  overflow: hidden;
}
.st-obra__quadro iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: calc(100% + 154px);
  border: 0;
}

/* Botão de calar, no canto do filme. Fica por cima do iframe e não dentro
   dele — quem o constrói é o initSomEmbed() do main.js, que também explica
   porque é que ele recarrega em vez de silenciar.

   O canto de baixo à direita é o único que está livre: o do perfil está em
   cima à esquerda e o botão de reproduzir do Instagram fica ao centro.

   O fundo é quase opaco de propósito. Por trás dele passa um filme, e sobre um
   fotograma claro um fundo translúcido deixaria o texto branco ilegível. A
   0,85 o pior caso é um fotograma todo branco, e mesmo aí o composto dá 9,99
   com o branco por cima (13,32 sobre cinzento médio, 16,98 sobre preto) — bem
   acima do mínimo, seja qual for o fotograma. */
.st-obra__som {
  position: absolute;
  right: 10px;
  bottom: 10px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.5rem 0.9rem;
  border: 0;
  border-radius: 9999px;
  background: rgba(var(--ink-rgb), 0.85);
  color: #fff;
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.2s var(--ease);
}
.st-obra__som:hover { background: var(--teal); }
.st-obra__som:focus-visible { outline: 3px solid var(--teal-mid); outline-offset: 2px; }
.st-obra__som svg { flex: none; }

/* Centrado na vertical contra o filme, que é sempre mais alto do que o texto. */
.st-obra__corpo {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: clamp(1.5rem, 3vw, 2.5rem);
}
.st-obra__etiqueta {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.6rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.st-obra__etiqueta svg { flex: none; color: var(--teal); }

/* Maior do que o .st-feira__nome, ao contrário do resto da página. A razão é
   que aqui a coluna do texto tem de fazer frente a um filme de 575px de altura
   com só três coisas dentro — sobretítulo, título, parágrafo e botão. Ao corpo
   do padrão sobravam ~285px de ar no meio do cartão. */
.st-obra__nome {
  margin: 0 0 1.1rem;
  font-size: clamp(1.75rem, 1.3rem + 1.5vw, 2.75rem);
  line-height: 1.1;
}

/* Pelo mesmo motivo: 22,4px a 1920, contra os 17,9 do texto dos destaques.

   A medida de linha desceu de 62ch para 52 ao mesmo tempo. O ch é a largura do
   algarismo 0 e não a de uma letra média — 62ch dão 79 caracteres reais, que
   já era muito para um parágrafo, e com o corpo maior seria pior. 52ch ficam
   em ~66 caracteres, que é onde uma linha ainda se lê de um fôlego. */
.st-obra__texto {
  margin: 0;
  max-width: 52ch;
  font-size: clamp(1.08rem, 0.98rem + 0.5vw, 1.4rem);
  line-height: 1.5;
  color: var(--ink);
}
.st-obra__texto strong { font-weight: 700; color: inherit; }

/* Cápsula com o desenho do .st-feira__cta, mas com :hover próprio: aqui é um
   link a sério e não um <span> por baixo de um botão que cobre o cartão. */
.st-obra__cta {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  align-self: flex-start;
  margin-top: clamp(1.35rem, 2.5vw, 1.9rem);
  padding: 0.85rem 1.6rem;
  border: 1px solid var(--teal);
  border-radius: 9999px;
  color: var(--teal);
  font-family: var(--font-body);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  transition: background-color 0.22s var(--ease), color 0.22s var(--ease),
    border-color 0.22s var(--ease);
}
.st-obra__cta:hover { background: var(--teal); color: #fff; }

/* --- Controlos do carrossel ----------------------------------------------
   Debaixo da pista e não por cima dela: com publicações à largura toda, uma
   seta sobreposta cairia sempre em cima do filme ou do texto. */
.st-carrossel__controlos {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: clamp(1rem, 2vw, 1.5rem);
}
.st-carrossel__pontos { display: flex; gap: 0.15rem; }

/* O ponto tem 10px mas o botão tem 28: é o alvo do dedo que manda no tamanho,
   não a bolinha. O ponto da publicação em que se está estica a cápsula, para
   se ver onde se está mesmo sem distinguir bem as cores. */
.st-carrossel__ponto {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.st-carrossel__ponto::before {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: 9999px;
  background: var(--line);
  transition: background-color 0.22s var(--ease), width 0.22s var(--ease);
}
.st-carrossel__ponto:hover::before { background: var(--muted-2); }
.st-carrossel__ponto[aria-current="true"]::before { width: 26px; background: var(--teal); }
.st-carrossel__ponto:focus-visible { outline: 3px solid var(--teal-mid); outline-offset: 2px; border-radius: 9999px; }

.st-carrossel__conta {
  margin: 0;
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
.st-carrossel__setas { display: flex; gap: 0.5rem; margin-left: auto; }
.st-carrossel__seta {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 9999px;
  background: #fff;
  color: var(--ink);
  cursor: pointer;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease),
    border-color 0.2s var(--ease);
}
.st-carrossel__seta:hover { background: var(--teal); border-color: var(--teal); color: #fff; }

/* Link para o perfil, debaixo do carrossel. */
.st-social {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: clamp(1.25rem, 2.5vw, 1.75rem);
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--teal);
  transition: color 0.2s var(--ease);
}
.st-social:hover { color: var(--teal-mid); }
.st-social svg { flex: none; }

/* --- Ecrãs estreitos ----------------------------------------------------- */
@media (max-width: 900px) {
  /* O filme por cima e o texto por baixo, como a .st-feira faz aos 820. Aqui é
     aos 900 porque a coluna da esquerda leva 4fr e não 5: mais cedo do que lá,
     o filme fica estreito de mais para se ver o que está a acontecer. */
  .st-obra { grid-template-columns: 1fr; }
  /* O tecto é o que impede o filme de ficar com meio ecrã de altura numa
     tablet: a 900px de largura, sem isto, o quadro dava 1068px de altura.

     Está aqui e não no .st-obra__quadro porque o enchimento em percentagem
     dele conta a partir do bloco que o contém — ver o comentário lá em cima.
     Uma grelha de uma coluna resolve as duas coisas de uma vez: a coluna é o
     tecto, e o justify-content centra-a. O quadro passa a ter a coluna por
     bloco que o contém, e a percentagem passa a contar dos 420. */
  .st-obra__media {
    border-right: 0;
    border-bottom: 1px solid var(--line);
    display: grid;
    grid-template-columns: min(100%, 420px);
    justify-content: center;
  }
  .st-obra__cta { align-self: stretch; justify-content: center; }
}


/* --------------------------------------------------------------------------
   24. Página de Contactos

   Duas coisas só: o cartão de uma via de contacto (.st-via) e a moldura do
   mapa (.st-mapa). Tudo o resto da página já existia — o cabeçalho é o
   .st-hero--liso da secção 22, as duas colunas do "Onde estamos" são o
   .st-duas da secção 21, e o fim de página é o mesmo .st-contacto de todas
   as outras. Prefixo .st- e bloco próprio, para se poder apagar de uma vez.
   -------------------------------------------------------------------------- */

/* --- Cartões das vias de contacto ----------------------------------------
   O mesmo cartão dos modelos da secção 21 — branco, filete de --line, raio
   --radius e o levantar de 4px ao passar o rato — para as duas páginas não
   parecerem de sítios diferentes.

   A GRELHA É QUE NÃO PODE SER A DELES. O auto-fill de mínimos serve a oito
   cartões (dá 4+4 a 1920 e 3+3+2 a 1280, e em nenhum caso sobra um sozinho),
   mas aqui são QUATRO: medido a 1280, o auto-fill punha 3 numa linha e o
   quarto sozinho por baixo — exactamente o que o padrão proíbe.

   Por isso o número de colunas é fixo e só toma valores pares: 4 ou 2. Está
   numa variável e é só ela que muda por largura, que é a regra da casa —
   assim nenhuma regra de mais classes pode tapar o estado final.

   O corte dos 1560px não é redondo por acaso: abaixo dele a grelha deixa de
   ter os 1104px que quatro cartões de 258 e três intervalos de 24 precisam,
   e os cartões começariam a ficar mais estreitos do que o cartão de modelo. */
.st-vias {
  --colunas: 4;
  display: grid;
  grid-template-columns: repeat(var(--colunas), minmax(0, 1fr));
  /* Duas linhas de cartões medem cada uma o seu conteúdo, e a linha da morada
     ficava 16px mais alta do que a dos telefones. O 1fr iguala-as: os quatro
     cartões acabam sempre à mesma altura, em qualquer número de colunas. */
  grid-auto-rows: 1fr;
  gap: clamp(1rem, 2vw, 1.5rem);
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (max-width: 1560px) { .st-vias { --colunas: 2; } }
@media (max-width: 620px) { .st-vias { --colunas: 1; } }
.st-via {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: clamp(1.25rem, 2.2vw, 1.65rem);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease),
    border-color 0.3s var(--ease);
}
.st-via:hover { transform: translateY(-4px); box-shadow: var(--shadow); border-color: var(--teal-mid); }

/* Pelo mesmo motivo do .st-modelo e do .st-feira: a regra do .st-surge tem
   quatro classes e mataria o transform do hover, que só tem duas. */
.js .st-via.st-surge[data-reveal].is-visible:hover { transform: translateY(-4px); }

/* O ícone é o que distingue os quatro cartões antes de se ler nada. Cápsula
   de --paper-soft com o traço em --teal (9,16 sobre branco); ao passar o
   rato troca para o cheio, que é o mesmo gesto do .st-galeria__botao. */
.st-via__icone {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 42px;
  height: 42px;
  margin-bottom: 0.3rem;
  background: var(--paper-soft);
  border-radius: 9999px;
  color: var(--teal);
  transition: background-color 0.3s var(--ease), color 0.3s var(--ease);
}
.st-via:hover .st-via__icone { background: var(--teal); color: #fff; }

/* O rótulo é o do .contact-card__label da secção 15, que era o desenho
   antigo desta página: a única coisa que se aproveitou dele. */
.st-via__rotulo {
  margin: 0;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--teal);
}
.st-via__valor {
  display: block;
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.2;
  word-break: break-word;
}
a.st-via__valor:hover { color: var(--teal); }

/* O email do cartão "Geral" é o mesmo valor, num corpo mais pequeno: tem 22
   caracteres, que ao corpo de 1,5rem medem 288px. A caixa mais apertada é a
   dos 1600px de largura, onde a grelha ainda tem quatro colunas e o cartão dá
   251px úteis — partia em duas linhas. A 1,12rem, o corpo do .st-via__morada,
   mede 215px e sobram 36px. Medido, não a olho. */
.st-via__valor--email { font-size: 1.12rem; }

/* A morada é o valor do quarto cartão, mas em três linhas: o mesmo peso e a
   mesma família, num corpo que caiba na largura do cartão sem partir a rua
   ao meio. O font-style normal é para o <address>, que vem em itálico. */
.st-via__morada {
  margin: 0;
  font-style: normal;
  font-family: var(--font-display);
  font-size: 1.12rem;
  font-weight: 700;
  line-height: 1.35;
}
/* --muted e não --muted-2: o cinzento claro dá 2,3 sobre branco e não passa
   o mínimo de 4,5 da lista de conferência. Este dá 6,4. */
.st-via__nota { margin: 0; font-size: 0.78rem; color: var(--muted); }
.st-via__texto { margin: 0; font-size: 0.88rem; line-height: 1.5; color: var(--muted); }
/* Encosta à base, como o link dos catálogos no cartão de modelo: assim os
   quatro cartões acabam à mesma altura mesmo com textos de tamanhos
   diferentes. */
.st-via .link-arrow { margin-top: auto; padding-top: 0.6rem; align-self: flex-start; }

/* A morada do bloco "Onde estamos", ao lado do mapa: o mesmo desenho do
   .st-via__morada, mas no corpo de um nome de modelo — aqui ela abre a
   coluna, não é uma linha dentro de um cartão. */
.st-morada {
  margin: 0 0 1.15rem;
  font-style: normal;
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 700;
  line-height: 1.35;
}

/* A folga entre o texto e o par "Como chegar" / "Ligar". Estava num style=""
   no HTML, do tempo em que o botão era o .btn quadrado da secção 8; o botão
   passou ao .st-botao em cápsula do padrão e a folga veio para aqui. */
.st-morada__accoes { margin-top: 1.75rem; }

/* --- Moldura do mapa -----------------------------------------------------
   No molde da .st-planta da secção 21: fundo, filete de --line e sem raio.
   O 4:3 é o que faz o mapa ocupar a coluna estreita do .st-duas sem ficar
   uma tira baixa.

   SEM min-height, e não por esquecimento. Com `aspect-ratio` a altura mínima
   passa a mandar na LARGURA: a 390px a coluna tem 350, mas um mínimo de 320
   de altura dava 4/3 × 320 = 427 de largura, e o mapa saía 77px para fora da
   coluna — cortado pelo overflow: hidden do .st-duas, sem se perceber porquê.
   Medida a 390: 350 × 262, que é a proporção certa e cabe. */
.st-mapa {
  aspect-ratio: 4 / 3;
  background: var(--paper);
  border: 1px solid var(--line);
  overflow: hidden;
}
.st-mapa iframe { display: block; width: 100%; height: 100%; border: 0; }

/* --------------------------------------------------------------------------
   25. Pedir serviço técnico

   Uma coisa só: as duas vias directas para o departamento técnico
   (.st-vias-claras), que vivem no fim da coluna de texto da cobertura. Todo o
   resto da página já existia — o cabeçalho é o .st-hero--liso da secção 22, o
   mapa é a moldura .st-planta da secção 21, e o fim é o bloco de contacto de
   sempre.

   Prefixo .st-, como o resto do padrão, e num bloco só para se poder apagar
   de uma vez sem tocar no resto da folha.
   -------------------------------------------------------------------------- */

/* Os mesmos contactos que o painel escuro do fim da página tem, repetidos
   aqui em cima para quem chega com a máquina parada e não quer preencher
   formulário nenhum. Mesmo corpo (14,4px) e mesmo peso; o que muda é a cor,
   porque o fundo aqui é branco — a --realce-escuro não serve fora do escuro,
   e a --teal-mid não chega ao contraste mínimo sobre branco.

   Duas colunas enquanto couberem 220px, uma quando não couberem: são só duas
   linhas, não vale a pena media query. O 220 não é redondo por acaso — com
   240 a coluna de texto a 1280 media 489px e não chegava para duas (240+240
   mais 26 de intervalo dão 506), e as vias partiam-se em duas linhas só
   nessa largura. A linha mais larga é o email, que mede cerca de 200px com
   o ícone. */
.st-vias-claras {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
  gap: clamp(1rem, 2vw, 1.75rem);
  margin: clamp(1.5rem, 3vw, 2rem) 0 0;
  padding: clamp(1.25rem, 2.4vw, 1.6rem) 0 0;
  border-top: 1px solid var(--line);
  list-style: none;
}
/* O ícone ocupa as duas linhas: o número em cima, o que ele é por baixo. */
.st-vias-claras li {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 0.75rem;
  align-items: center;
}
.st-vias-claras svg { grid-row: 1 / span 2; color: var(--teal); }
.st-vias-claras a {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--ink);
  transition: color 0.2s var(--ease);
}
.st-vias-claras a:hover { color: var(--teal); }
.st-vias-claras span { font-size: 0.8rem; color: var(--muted); }

/* --------------------------------------------------------------------------
   20. Impressão
   -------------------------------------------------------------------------- */
@media print {
  .sidebar, .site-head, .quick-bar, .cta, .hero__bg, .hexlines { display: none !important; }
  .shell { display: block; }
  body { color: #000; background: #fff; }

  /* O cartaz da feira é texto branco sobre um gradiente, e os browsers não
     imprimem fundos: sem isto a data saía em branco sobre branco. O botão e a
     janela das fotografias não têm sentido nenhum em papel. */
  .st-galeria { display: none !important; }
  .st-feira__abrir, .st-feira__cta { display: none; }
  /* As imagens imprimem-se, os fundos não: sem isto a arte da feira saía a
     cores e o texto, que aqui passa a preto, ficava por cima dela ilegível.
     Some a fotografia e o escurecimento com ela — fica o texto em papel
     branco. */
  .st-feira__foto { display: none; }
  .st-feira__cartaz { background: none; }
  .st-feira__cartaz::before { display: none; }
  .st-feira__cartaz,
  .st-feira__etiqueta,
  .st-feira__dia,
  .st-feira__dia span,
  .st-feira__mes { color: #000; }

  /* O carrossel em papel: um iframe não imprime nada de útil e as setas e os
     pontos não têm onde carregar. A pista deixa de deslizar e passa a empilhar
     as publicações, para saírem as duas — em vez de meia primeira e mais nada.
     O link "Ver no Instagram" fica: numa folha é o endereço que interessa. */
  .st-obra__media, .st-carrossel__controlos, .st-obra__som { display: none !important; }
  .st-carrossel-caixa, .st-carrossel__pista { overflow: visible; }
  .st-carrossel__pista { display: block; }
  .st-obra { grid-template-columns: 1fr; break-inside: avoid; }
  .st-obra + .st-obra { margin-top: 1rem; }
}
