/* =============================================================
   THE RIVERLAND — componentes
   Depende de tokens.css e base.css.
   ============================================================= */

/* -------------------------------------------------------------
   Botões
   ------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  position: relative;
  overflow: hidden;                 /* segura o varrimento de brilho */
  isolation: isolate;
  /* 44px de altura mínima: alvo de toque confortável */
  min-height: 2.75rem;
  padding: var(--sp-3) var(--sp-6);
  border: 1px solid transparent;
  border-radius: var(--radius-btn);
  font-family: var(--font-util);
  font-size: var(--text-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .12em;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              color var(--dur) var(--ease);
}
.btn > * { position: relative; z-index: 1; }
.btn svg { transition: transform var(--dur) var(--ease-out); }

/* Varrimento de luz: uma faixa diagonal que atravessa o botão no hover.
   É o que faz o botão parecer metal apanhado pela luz em vez de um retângulo. */
.btn--primary::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(120deg, transparent 30%, rgba(255,255,255,.5), transparent 70%);
  transform: translateX(-120%);
  transition: transform .7s var(--ease-out);
}
.btn--primary:hover::before { transform: translateX(120%); }

.btn--primary {
  /* Quatro paragens, como na v1 — todas medidas contra o texto escuro,
     a mais escura ainda dá 5,53 (AA). */
  background: linear-gradient(135deg, #F2D48A 0%, var(--gold) 45%, var(--gold-deep) 78%, #A8842F 100%);
  color: var(--on-accent);
  border-color: transparent;
  box-shadow: 0 6px 26px color-mix(in srgb, var(--gold) 32%, transparent),
              inset 0 1px 0 rgba(255, 255, 255, .45);
}
.btn--primary:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 40px color-mix(in srgb, var(--gold) 48%, transparent),
              inset 0 1px 0 rgba(255, 255, 255, .45);
}
.btn--primary:hover svg { transform: translateX(4px); }

.btn--ghost {
  background: color-mix(in srgb, var(--ink) 4%, transparent);
  color: var(--ink);
  border: 1.5px solid color-mix(in srgb, var(--gold) 45%, transparent);
  backdrop-filter: blur(6px);
}
.btn--ghost:hover {
  transform: translateY(-3px);
  border-color: var(--gold);
  color: var(--gold);
  box-shadow: 0 8px 28px rgba(0, 0, 0, .45);
}
.btn--ghost:hover svg { transform: translateX(4px); }

.btn--lg { padding: var(--sp-4) var(--sp-7); font-size: var(--text-base); }

/* Quem pediu menos movimento não leva salto nem varrimento. */
@media (prefers-reduced-motion: reduce) {
  .btn:hover { transform: none; }
  .btn--primary::before { display: none; }
  .btn:hover svg { transform: none; }
}

.btn--quiet {
  background: transparent;
  color: var(--ink-dim);
  border-color: transparent;
  padding-inline: var(--sp-3);
}
.btn--quiet:hover { color: var(--ink); }

.btn[disabled], .btn[aria-disabled="true"] {
  opacity: .5;
  pointer-events: none;
}

/* -------------------------------------------------------------
   Cabeçalho do site
   ------------------------------------------------------------- */
/* A barra flutua por cima do hero e só ganha corpo ao descer.
   O estado sólido é o DEFAULT de propósito: sem JS, ou numa página sem hero,
   fica sempre legível. O `data-at-top` só é posto pelo site.js quando há mesmo
   um hero por baixo e o scroll está no topo. */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--ground) 88%, transparent);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid color-mix(in srgb, var(--gold) 18%, var(--edge));
  box-shadow: 0 10px 40px rgba(0, 0, 0, .45);
  transition: background-color var(--dur-slow) var(--ease),
              border-color var(--dur-slow) var(--ease),
              box-shadow var(--dur-slow) var(--ease),
              padding var(--dur-slow) var(--ease);
}
.site-header[data-at-top="true"] {
  background: transparent;
  backdrop-filter: none;
  border-bottom-color: transparent;
  box-shadow: none;
}
/* Com o menu aberto a barra volta a ser sólida, mesmo no topo — senão ficava
   uma faixa transparente por cima do painel. Tem de vir DEPOIS da regra do
   data-at-top: mesma especificidade, ganha a última. */
.site-header:has(.nav[data-open="true"]) {
  background: color-mix(in srgb, var(--ground) 96%, transparent);
  backdrop-filter: blur(14px);
  border-bottom-color: color-mix(in srgb, var(--gold) 18%, var(--edge));
}
.site-header__inner {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  min-height: var(--header-h);
  transition: min-height var(--dur-slow) var(--ease);
}
.site-header[data-at-top="true"] .site-header__inner { min-height: 5.5rem; }

/* A barra é fixa, por isso o conteúdo precisa de lhe dar espaço — exceto os
   heros, que sobem para debaixo dela e repõem o espaço por dentro. */
main { padding-top: var(--header-h); }
.hero { margin-top: calc(var(--header-h) * -1); padding-top: var(--header-h); }

.brand {
  display: flex; align-items: center; gap: var(--sp-3); margin-right: auto;
  color: inherit; text-decoration: none;
}
.brand img {
  width: 46px; height: auto; flex: none;
  filter: drop-shadow(0 2px 8px rgba(0, 0, 0, .6));
  transition: transform .5s var(--ease-out);
}
.brand:hover img { transform: rotate(-6deg) scale(1.06); }
@media (prefers-reduced-motion: reduce) { .brand:hover img { transform: none; } }
.brand__name {
  /* O nome é sempre a Crock, aqui como no hero. */
  font-family: var(--font-wordmark);
  font-size: var(--text-md);
  letter-spacing: .04em;
  line-height: 1;
  color: var(--ink);
  white-space: nowrap;
}

.nav { display: flex; align-items: center; gap: var(--sp-5); }
/* :not(.btn) é obrigatório — sem ele, `.nav a` (0,1,1) vence `.btn--primary`
   (0,1,0) e o botão da navegação fica com a cor de texto do menu por cima do
   ouro. Dava 1,82 de contraste. */
.nav { gap: var(--sp-1); }
.nav a:not(.btn) {
  position: relative;
  font-family: var(--font-util);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--ink-dim);
  padding: var(--sp-3) var(--sp-4);
  border-radius: 8px;
  transition: color var(--dur) var(--ease);
}
/* Sublinhado dourado que cresce da esquerda — é o detalhe da v1 que dá vida
   à barra sem lhe acrescentar peso. */
.nav a:not(.btn)::after {
  content: "";
  position: absolute;
  left: var(--sp-4); right: var(--sp-4); bottom: .35rem;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--gold-deep), var(--gold));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .35s var(--ease-out);
}
.nav a:not(.btn):hover { color: var(--ink); }
.nav a:not(.btn):hover::after { transform: scaleX(1); }
.nav a:not(.btn)[aria-current="page"] { color: var(--gold); }
.nav a:not(.btn)[aria-current="page"]::after { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
  .nav a:not(.btn)::after { transition: none; }
}

/* Abaixo dos 900px a navegação passa para o painel deslizante (nav-toggle). */
.nav-toggle { display: none; }
@media (max-width: 900px) {
  .nav-toggle {
    display: inline-flex;
    background: none;
    border: 1px solid var(--edge-strong);
    border-radius: var(--radius-sm);
    min-height: 2.75rem;
    min-width: 2.75rem;
    align-items: center;
    justify-content: center;
    color: var(--ink);
    cursor: pointer;
  }
  .nav {
    display: none;
    position: absolute;
    inset: 100% 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--surface);
    border-bottom: 1px solid var(--edge);
    padding: var(--sp-3) var(--gutter) var(--sp-5);
  }
  .nav[data-open="true"] { display: flex; }
  .nav a:not(.btn) {
    padding-block: var(--sp-4);
    border-bottom: 1px solid var(--edge);
  }
  .nav a:not(.btn)[aria-current="page"] { border-bottom-color: var(--gold); }
}

/* -------------------------------------------------------------
   Ecrã de carregamento

   QUEM O REMOVE É O CSS, não o JS. A animação tem `forwards` e um atraso de
   2,2s: mesmo que o JavaScript nunca corra, o ecrã sai. O site.js só antecipa
   esse fim quando a página acaba de carregar, o que é o caso normal. Era este
   o defeito da v1 — lá o overlay só saía por JS, e com o script partido a
   página ficava tapada para sempre.
   ------------------------------------------------------------- */
.loader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-6);
  background: radial-gradient(circle at 50% 42%,
              color-mix(in srgb, var(--gold) 7%, var(--ground)), var(--ground) 68%);
  animation: loaderOut var(--dur-slow) var(--ease-out) 2.2s forwards;
}
/* Sem atraso: o site.js põe isto assim que a página carrega. */
.loader[data-done="true"] { animation: loaderOut var(--dur-slow) var(--ease-out) forwards; }

@keyframes loaderOut {
  to { opacity: 0; visibility: hidden; pointer-events: none; }
}

.loader__mark { position: relative; display: grid; place-items: center; }
.loader__mark img {
  width: clamp(88px, 11vw, 116px);
  height: auto;
  filter: drop-shadow(0 6px 24px rgba(0, 0, 0, .6))
          drop-shadow(0 0 30px color-mix(in srgb, var(--gold) 28%, transparent));
}
/* O anel gira à volta do logo, com folga para não lhe tocar. */
.loader__ring {
  position: absolute;
  width: 168%;
  height: 168%;
  color: var(--gold);
  animation: loaderSpin 1.2s linear infinite;
}
@keyframes loaderSpin { to { transform: rotate(360deg); } }

.loader__text {
  font-family: var(--font-util);
  text-transform: uppercase;
  letter-spacing: .22em;
  font-size: var(--text-sm);
  color: var(--ink-dim);
  margin: 0;
  animation: loaderPulse 1.7s ease-in-out infinite;
}
@keyframes loaderPulse { 0%, 100% { opacity: .45; } 50% { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  /* O bloco global reduz a *duração* das animações mas não o atraso — sem isto,
     quem pede menos movimento ficava 2,2s a olhar para um ecrã parado. */
  html:not([data-motion="on"]) .loader { animation-delay: 0s !important; }
  html:not([data-motion="on"]) .loader__ring,
  html:not([data-motion="on"]) .loader__text { animation: none; }
}
html[data-motion="off"] .loader { animation-delay: 0s !important; }
html[data-motion="off"] .loader__ring,
html[data-motion="off"] .loader__text { animation: none; }

/* -------------------------------------------------------------
   Voltar ao início
   ------------------------------------------------------------- */
.ao-topo {
  display: flex;
  justify-content: center;
  padding-block: var(--sp-8) var(--sp-6);
  border-top: 1px solid var(--edge);
  margin-top: var(--sp-8);
}
.ao-topo__link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 2.75rem;
  padding: var(--sp-2) var(--sp-5);
  border-radius: var(--radius-sm);
  color: var(--ink-dim);
  text-decoration: none;
  font-family: var(--font-util);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: var(--text-sm);
  transition: color var(--dur) var(--ease);
}
.ao-topo__link:hover { color: var(--gold); }
.ao-topo__link svg { transition: transform var(--dur) var(--ease-out); }
.ao-topo__link:hover svg { transform: translateY(-3px); }
@media (prefers-reduced-motion: reduce) {
  .ao-topo__link:hover svg { transform: none; }
}

/* O <main> tem tabindex="-1" para receber o foco no salto. Sem isto, o
   :focus-visible desenhava um contorno dourado à volta da página inteira, o
   que não diz nada a ninguém. O sinal de que o foco se moveu é a página ter
   rolado e o Tab seguinte ir para o primeiro controlo do topo. */
main:focus { outline: none; }

/* -------------------------------------------------------------
   Caixa de pesquisa

   Injetada pelo JS: sem JavaScript não aparece, e a página fica com tudo
   visível como está hoje. Um campo de pesquisa que não filtra nada seria pior
   do que não ter campo nenhum.
   ------------------------------------------------------------- */
/* Folga por baixo por omissão: na FAQ o contentor não é um `.stack` e a caixa
   ficava colada à lista. Dentro de um stack, o `gap` já trata disso e a margem
   sai — senão o espaço ficava a dobrar. */
.busca { margin-bottom: var(--sp-6); }
.stack > .busca { margin-bottom: 0; }

.busca {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--edge-strong);
  border-radius: var(--radius);
  background: var(--surface);
  transition: border-color var(--dur) var(--ease);
}
.busca:focus-within { border-color: var(--gold-deep); }
.busca__icone { color: var(--ink-mute); flex: none; }
.busca input {
  min-height: 2.5rem;
  border: 0;
  background: none;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--text-base);
  width: 100%;
}
.busca input:focus { outline: none; }
.busca input::placeholder { color: var(--ink-dim); }
/* O X nativo do type="search" é feio e inconsistente entre browsers. */
.busca input::-webkit-search-cancel-button { display: none; }
.busca__limpar {
  border: 0;
  background: none;
  color: var(--ink-dim);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 var(--sp-2);
}
.busca__limpar:hover { color: var(--gold); }
/* A contagem sai do fluxo da grelha e assenta por baixo da caixa. */
.busca__contagem {
  grid-column: 1 / -1;
  margin: 0;
  padding-bottom: var(--sp-2);
  font-family: var(--font-util);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--ink-dim);
}
.busca__contagem:empty { display: none; }

/* O realce dos resultados. Fundo dourado translúcido em vez do amarelo do
   browser, que sobre este chão gritava.
   MEDIDO na página: o fundo composto dá rgb(73, 67, 42), e o --ink por cima
   fica em 8,04 — bem acima do mínimo de 4,5. Se escureceres o chão ou subires
   a percentagem de ouro, volta a medir. */
mark {
  background: color-mix(in srgb, var(--gold) 26%, transparent);
  color: var(--ink);
  /* SEM padding e SEM contorno. O realce cai a meio de palavras — procurar
     «dele» marca as quatro primeiras letras de «Delegacias» — e qualquer
     espaçamento ou moldura parte a palavra em duas ao olho. A largura do texto
     tem de ficar exatamente igual com e sem realce. */
  padding: 0;
  border-radius: 2px;
}

/* Quando não há resultados, o vazio precisa de uma explicação. */
[data-pesquisavel][data-sem-resultados="true"]::after {
  content: "Nada corresponde a essa procura. Tenta outra palavra, ou pergunta no Discord.";
  display: block;
  padding: var(--sp-7) 0;
  text-align: center;
  color: var(--ink-dim);
}

/* -------------------------------------------------------------
   Índice das regras

   São 52 regras em 8 secções. Sem um índice no topo, chegar à secção das
   empresas obriga a percorrer tudo o resto.
   ------------------------------------------------------------- */
.rules-index {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
.rules-index a {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--edge);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink-dim);
  text-decoration: none;
  font-family: var(--font-util);
  font-size: var(--text-sm);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.rules-index a:hover { color: var(--ink); border-color: var(--gold-deep); }
.rules-index a span {
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}
/* A barra é fixa: sem isto, saltar para uma secção deixava o título por baixo
   dela. */
.rules-section__title { scroll-margin-top: calc(var(--header-h) + var(--sp-5)); }

/* -------------------------------------------------------------
   Sobre — duas colunas assimétricas

   A forma é o ponto: 7fr para o texto, 5fr para os pilares. Uma grelha
   desigual quebra o ritmo das grelhas de cartões que vêm a seguir, que é onde
   a página estava a ficar monótona. Herdado da v1, que fazia o mesmo.
   ------------------------------------------------------------- */
.about { display: grid; gap: var(--sp-7); align-items: start; }
@media (min-width: 62rem) {
  .about { grid-template-columns: 7fr 5fr; gap: var(--sp-9); }
}
.about__lead { font-size: var(--text-md); color: var(--ink); }
.about p { max-width: var(--measure); }
.about p + p, .about__lead { margin-top: var(--sp-4); }
.about .section-head__title { margin-top: var(--sp-2); }
.about em { font-style: italic; color: var(--gold); }

/* O selo: uma linha discreta a fechar o texto, com um fio dourado por cima. */
.about__seal {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--edge);
  font-family: var(--font-util);
  text-transform: uppercase;
  letter-spacing: .14em;
  font-size: var(--text-xs);
  color: var(--ink-dim);
}
.about__seal svg { color: var(--gold); flex: none; }

/* Pilares: não são cartões. Sem fundo nem moldura — só um fio à esquerda,
   dourado, que os liga em coluna. Outra forma, de propósito. */
.pillars { display: grid; gap: var(--sp-5); }
.pillar {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--sp-4);
  padding-left: var(--sp-5);
  border-left: 2px solid var(--edge-strong);
  transition: border-color var(--dur) var(--ease);
}
.pillar:hover { border-left-color: var(--gold); }
.pillar__icon {
  display: grid;
  place-items: center;
  width: 2.5rem; height: 2.5rem;
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--gold) 12%, transparent);
  color: var(--gold);
}
.pillar h3 { font-size: var(--text-md); margin-bottom: var(--sp-1); }
.pillar p { color: var(--ink-dim); font-size: var(--text-sm); margin: 0; }

/* -------------------------------------------------------------
   Faixa de números

   Estavam escondidos dentro da primeira secção, como um aparte. Numa banda
   própria passam a ser a pontuação entre duas grelhas de cartões.
   ------------------------------------------------------------- */
.figures {
  display: grid;
  gap: var(--sp-7);
  text-align: center;
  grid-template-columns: 1fr;
}
@media (min-width: 40rem) { .figures { grid-template-columns: repeat(3, 1fr); } }
.figure__value {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 7vw, 4.4rem);
  line-height: 1;
  color: var(--gold);
  text-shadow: 0 4px 30px color-mix(in srgb, var(--gold) 30%, transparent);
}
.figure__label {
  font-family: var(--font-util);
  text-transform: uppercase;
  letter-spacing: .16em;
  font-size: var(--text-sm);
  color: var(--ink-dim);
  margin-top: var(--sp-2);
}
/* Divisórias entre os números, só quando estão lado a lado. */
@media (min-width: 40rem) {
  .figure + .figure { border-left: 1px solid var(--edge); }
}

/* -------------------------------------------------------------
   Mosaico

   Imagens de tamanhos diferentes, sem molduras, sem títulos, sem texto. É a
   forma mais distante de um cartão que a página tem — e é isso que faz.
   ------------------------------------------------------------- */
.mosaic {
  display: grid;
  gap: var(--sp-3);
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows: 9rem;
}
@media (min-width: 48rem) {
  .mosaic { grid-template-columns: repeat(4, 1fr); grid-auto-rows: 11rem; }
  /* Sete imagens fecham a grelha sem buracos:
       linha 1  [1][1][2][3]
       linha 2  [1][1][4][4]
       linha 3  [5][6][7][7]
     Com seis, sobrava um vazio no canto inferior direito. */
  .mosaic > :nth-child(1) { grid-column: span 2; grid-row: span 2; }
  .mosaic > :nth-child(4) { grid-column: span 2; }
  .mosaic > :nth-child(7) { grid-column: span 2; }
}
.mosaic > * {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--surface);
}
.mosaic picture, .mosaic img {
  display: block; width: 100%; height: 100%; object-fit: cover;
}
.mosaic img { transition: transform 700ms var(--ease-out); }
.mosaic > *:hover img { transform: scale(1.05); }
@media (prefers-reduced-motion: reduce) {
  .mosaic > *:hover img { transform: none; }
}

/* -------------------------------------------------------------
   Notícias — lista, não grelha

   Em grelha de três colunas, uma notícia sozinha ficava um cartão órfão com
   dois buracos ao lado. Em lista funciona com uma ou com cinco, e é mais uma
   forma diferente entre as grelhas.
   ------------------------------------------------------------- */
.news-list { display: flex; flex-direction: column; }
.news-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-5) 0;
  border-top: 1px solid var(--edge);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--dur) var(--ease);
}
.news-row:last-child { border-bottom: 1px solid var(--edge); }
.news-row:hover { border-top-color: var(--gold-deep); }
.news-row__date {
  font-family: var(--font-util);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: var(--text-xs);
  color: var(--river);
}
.news-row__title {
  font-size: var(--text-md);
  margin: var(--sp-1) 0 var(--sp-2);
  transition: color var(--dur) var(--ease);
}
.news-row:hover .news-row__title { color: var(--gold); }
.news-row__text { color: var(--ink-dim); font-size: var(--text-sm); margin: 0; max-width: var(--measure); }
.news-row__arrow {
  color: var(--ink-mute);
  transition: transform var(--dur) var(--ease-out), color var(--dur) var(--ease);
}
.news-row:hover .news-row__arrow { transform: translateX(5px); color: var(--gold); }
@media (prefers-reduced-motion: reduce) {
  .news-row:hover .news-row__arrow { transform: none; }
}

/* -------------------------------------------------------------
   Passos — como entrar

   Deliberadamente NÃO são cartões. Vêm logo a seguir à grelha dos destaques,
   e com molduras e fundo seriam mais uma grelha encostada a outra — que é
   exatamente o que se anda a corrigir. Aqui são algarismos grandes numa linha
   contínua, como uma marcação de percurso.
   ------------------------------------------------------------- */
.steps {
  display: grid;
  gap: var(--sp-6);
  grid-template-columns: 1fr;
  counter-reset: passo;
}
@media (min-width: 52rem) { .steps { grid-template-columns: repeat(4, 1fr); gap: var(--sp-5); } }

.step { position: relative; padding-top: var(--sp-6); }
.step__num {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  line-height: 1;
  color: var(--gold);
  display: block;
  margin-bottom: var(--sp-3);
}
.step h3 { font-size: var(--text-md); margin-bottom: var(--sp-2); }
.step p { color: var(--ink-dim); font-size: var(--text-sm); margin: 0; }

/* O fio que liga os passos, com um ponto em cada um. Em coluna (ecrã estreito)
   o fio passa a vertical, à esquerda. */
.step::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: var(--edge-strong);
}
.step::after {
  content: "";
  position: absolute;
  top: -3px; left: 0;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 12px color-mix(in srgb, var(--gold) 60%, transparent);
}
/* O fio atravessa os intervalos da grelha, senão lê-se como quatro traços
   soltos em vez de um percurso. O último pára onde acaba. */
@media (min-width: 52rem) {
  .step::before { right: calc(var(--sp-5) * -1); }
  .step:last-child::before { right: 0; }
}

/* -------------------------------------------------------------
   Fecho — a última coisa da página

   Sem fotografia: um clarão dourado ao centro e mais nada. Depois de uma
   página inteira de imagens, o vazio é que dá peso à frase.
   ------------------------------------------------------------- */
.finale {
  position: relative;
  text-align: center;
  padding-block: var(--sp-10);
}
/* O clarão TEM de acabar de esbater antes de tocar em qualquer aresta.
   Estava em `60% 70% at 50% 42%` com o transparente a 70%: centrado acima do
   meio e com raio vertical grande, a mancha ainda tinha cor quando batia no
   topo da secção — e o overflow cortava-a a direito, deixando uma linha a
   atravessar a página inteira.

   Centrado a 50% e com raios abaixo de 50%, o esbatimento fecha dentro da
   caixa. Se mexeres nestes números, a regra é essa: centro + raio nunca pode
   chegar à borda. */
.finale::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  background: radial-gradient(46% 42% at 50% 50%,
              color-mix(in srgb, var(--gold) 14%, transparent) 0%,
              transparent 100%);
  pointer-events: none;
}
.finale__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-5);
}
.finale__badge {
  width: clamp(96px, 11vw, 128px);
  height: auto;
  filter: drop-shadow(0 8px 30px rgba(0, 0, 0, .6))
          drop-shadow(0 0 36px color-mix(in srgb, var(--gold) 34%, transparent));
}
.finale__title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 5.5vw, 3.6rem);
  line-height: 1.1;
  max-width: 18ch;
  /* O mesmo preenchimento em gradiente do hero: apanha a luz do clarão. */
  color: var(--ink);
  background: linear-gradient(180deg, var(--ink) 34%, var(--gold) 128%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
.finale__sub { color: var(--ink-dim); max-width: 46ch; }

/* -------------------------------------------------------------
   Banda fotográfica
   Uma secção com fotografia de fundo, para a página não ser só chão escuro
   depois do hero. Usada com parcimónia — duas na home. Em todas, o ritmo
   perde-se e a página fica pesada de descarregar.
   ------------------------------------------------------------- */
/* Sem `isolation`, sem `filter`, sem `z-index`: qualquer um deles cria contexto
   de empilhamento, prende a fotografia cá dentro e o fluido deixa de lhe passar
   por cima. `overflow: hidden` não cria contexto, por isso pode ficar. */
/* As bandas precisam de altura própria: o `.section + .section { padding-top: 0 }`
   do base.css esmagava-as contra o topo, e com 167px os dois esbatimentos do véu
   sobrepunham-se e apagavam a fotografia toda. */
.band { position: relative; overflow: hidden; }
/* `.section.band` e não `.band`: o `.section + .section { padding-top: 0 }` do
   base.css tem duas classes, logo mais especificidade, e ganhava. Com 167px de
   altura os dois esbatimentos do véu sobrepunham-se e a fotografia desaparecia. */
.section.band { padding-block: var(--sp-9); }
.band__media { position: absolute; inset: 0; z-index: -2; }
.band__media picture { display: block; width: 100%; height: 100%; }
.band__media img { width: 100%; height: 100%; object-fit: cover; }

/* 90% de chão por cima da fotografia. O número é medido, não escolhido: a 88%
   o texto secundário caía para 4,70 sobre as zonas claras das fotografias, à
   tangente do mínimo. A 90% fica em 5,00. */
.band__scrim {
  position: absolute;
  inset: 0;
  z-index: -2;
  background: color-mix(in srgb, var(--ground) 90%, transparent);
}
/* Esbatimento em cima e em baixo: a banda derrete na página em vez de acabar
   numa aresta a direito, que denunciaria logo o retângulo. */
.band__scrim::before,
.band__scrim::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  height: 5rem;
  pointer-events: none;
}
.band__scrim::before { top: 0; background: linear-gradient(to bottom, var(--ground), transparent); }
.band__scrim::after { bottom: 0; background: linear-gradient(to top, var(--ground), transparent); }

/* -------------------------------------------------------------
   Hero
   ------------------------------------------------------------- */
/* Sem `isolation: isolate`: se o hero criasse contexto próprio, a sua
   fotografia ficava presa lá dentro e o fluido (fixo, z-index -1 na raiz) nunca
   lhe passaria por cima. As camadas de fundo do hero vão todas a -2 para
   ficarem por baixo do fluido. */
.hero { position: relative; }
.hero__media { position: absolute; inset: 0; z-index: -2; overflow: hidden; }
/* <picture> é inline por omissão: sem isto o height da imagem não tem contra o
   que resolver, a imagem fica com a altura intrínseca e transborda para fora do
   hero, aparecendo por trás da secção seguinte.

   A fotografia é 18% mais alta do que o hero e está encostada em BAIXO: a folga
   fica toda em cima, que é exatamente para onde ela foge quando desliza (ver
   --drift). Sem a folga, abria-se uma faixa de fundo no topo ao primeiro pixel
   de scroll. O deslize vai até 15%, e os 3% que sobram são a margem de erro. */
.hero__media picture {
  display: block;
  position: absolute;
  inset: auto 0 0 0;
  width: 100%;
  height: 118%;
}
.hero__media img { width: 100%; height: 100%; object-fit: cover; }

/* O DESLIZE é movimento a sério: só com `js-motion`, ou seja, só quando não há
   prefers-reduced-motion. Sem ela a fotografia fica parada. */
.js-motion .hero__media picture {
  transform: translate3d(0, var(--drift, 0px), 0);
  will-change: transform;
}

/* O ENCADEADO fica de fora desse gate, de propósito: é só opacidade, nada se
   desloca. Quem pede movimento reduzido continua a ver as fotografias mudar —
   é o deslizar e o fluido que lhe fazem mal, não um cross-fade lento.
   Sem JS não há atributo nenhum e não acontece nada, por isso não precisa de
   `js-motion` para se proteger. */
.hero__media picture { transition: opacity 1.4s linear; }
.hero__media picture[data-slide-hidden] { opacity: 0; }

/* O véu garante que o texto assenta sempre sobre fundo suficiente.
   Em ecrã largo é lateral; em estreito passa a chapado, senão o texto
   cai fora do gradiente e fica ilegível. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -2;
  background: linear-gradient(
    90deg,
    var(--ground) 2%,
    color-mix(in srgb, var(--ground) 80%, transparent) 42%,
    color-mix(in srgb, var(--ground) 30%, transparent) 78%
  );
}
@media (max-width: 720px) {
  .hero__scrim { background: color-mix(in srgb, var(--ground) 82%, transparent); }
}

/* Vinheta por cima do véu: fecha os cantos e faz a imagem morrer no fundo da
   página, em vez de acabar a direito numa aresta. */
.hero__scrim::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--vignette);
}
.hero::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 8rem;
  z-index: -2;
  background: linear-gradient(to bottom, transparent, var(--ground));
  pointer-events: none;
}

/* --- fluido que segue o rato, na página toda ---
   AS TRÊS CAMADAS DA PÁGINA, e a ordem entre elas não é negociável:

     z-index -1   fotografias de fundo (hero, bandas)
     z-index  0   este fluido, fixo ao ecrã
     z-index  1   cabeçalho, conteúdo, rodapé — todo o texto

   Porquê exatamente aí: por cima das fotografias, senão não se via nada nas
   zonas que interessam; por baixo do texto, porque medido dá 2,65:1 de
   contraste no texto secundário com o rasto por cima — falha AA. Por baixo,
   não toca em texto nenhum e pode ser tão forte quanto se queira.

   `position: fixed` de propósito: o rasto acompanha o rato, não o documento.
   Ao fazer scroll ele fica onde está, como uma luz na sala.

   `pointer-events: none` não é um detalhe — sem isto a tela cobria a página
   inteira e nada se conseguia carregar. Quem ouve o ponteiro é o documento.

   `screen` faz o preto da tela desaparecer e só deixa passar a luz do rasto,
   por isso não é preciso alfa — o que evita bordas sujas nos cantos. */
.fluid-layer {
  position: fixed;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  pointer-events: none;
  mix-blend-mode: screen;
  /* Só aparece depois de o WebGL confirmar que arrancou. Se a máquina não der,
     fica invisível em vez de deixar um retângulo preto sobre a página. */
  opacity: 0;
  transition: opacity 600ms var(--ease-out);
}
.fluid-layer[data-ready="true"] { opacity: 1; }

/* O conteúdo fica em z-index automático, ou seja, acima de qualquer negativo.
   Não precisa de regra nenhuma — mas precisa que NINGUÉM pelo caminho crie um
   contexto de empilhamento, senão prende lá dentro as fotografias de fundo e o
   fluido deixa de as alcançar. Foi por isso que o `isolation: isolate` saiu do
   .hero. Se algum dia puseres `isolation`, `filter`, `transform` ou um
   `z-index` no <main> ou numa .section com fotografia, o fluido desaparece
   dessa zona — e o motivo não será óbvio. */

/* --- interruptor de movimento (rodapé) ---
   Escondido no HTML e revelado pelo JS: sem JS não teria como funcionar, e um
   botão morto é pior do que botão nenhum. */
.motion-toggle {
  font-family: var(--font-util);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--ink-dim);
  background: none;
  border: 1px solid var(--edge-strong);
  border-radius: var(--radius-sm);
  padding: .35rem .7rem;
  margin-right: var(--sp-3);
  cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.motion-toggle:hover { color: var(--ink); border-color: var(--ink-mute); }
.motion-toggle[aria-pressed="true"] { color: var(--gold); border-color: var(--gold-deep); }

html[data-motion="off"] .hero__fluid { display: none; }
@media (prefers-reduced-motion: reduce) {
  html:not([data-motion="on"]) .hero__fluid { display: none; }
}

.hero__body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding-block: var(--sp-9);
  max-width: var(--measure-narrow);
}
.hero__title {
  font-family: var(--font-display);
  font-size: var(--text-hero);
  line-height: var(--leading-tight);
  /* Preenchimento em gradiente: o texto apanha a luz do poente das imagens.
     `color` fica definido como fallback para quem não suporta background-clip. */
  color: var(--ink);
  background: linear-gradient(180deg, var(--ink) 30%, var(--gold) 130%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  text-shadow: 0 2px 30px rgba(0, 0, 0, .5);
}

/* --- wordmark: o nome partido em dois, como na v1 --- */
.wordmark { display: block; line-height: .92; }
.wordmark__the {
  display: block;
  font-family: var(--font-wordmark);
  font-weight: 600;
  font-size: clamp(1.1rem, 3vw, 2rem);
  letter-spacing: .55em;      /* o espaçamento largo é metade do efeito */
  text-indent: .55em;         /* compensa o espaço extra à direita */
  text-transform: uppercase;
  color: var(--ink);
  text-shadow: 0 3px 18px rgba(0, 0, 0, .7);
}
.wordmark__name {
  display: block;
  font-family: var(--font-wordmark);
  font-weight: 900;
  font-size: clamp(3.2rem, 12vw, 9rem);
  letter-spacing: .01em;
  /* Quatro paragens: luz no topo, ouro no meio, a morrer em bronze em baixo. */
  background: linear-gradient(180deg, #FFF6DE 0%, var(--gold) 45%, var(--gold-deep) 80%, #8A6B28 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* Dois drop-shadow: um brilho quente que separa da fotografia, e uma sombra
     dura por baixo que lhe dá peso. É isto que a v1 faz e faltava aqui. */
  filter: drop-shadow(0 6px 30px color-mix(in srgb, var(--gold) 42%, transparent))
          drop-shadow(0 2px 4px rgba(0, 0, 0, .55));
}
.hero__sub { font-size: var(--text-md); color: var(--ink-dim); }

/* --- home: hero de ecrã inteiro --- */
.hero--tall { display: flex; align-items: center; min-height: min(88svh, 46rem); }
.hero--tall .hero__body {
  align-items: center;
  text-align: center;
  max-width: 42rem;
  margin-inline: auto;
}
/* Texto sobre fotografia: o corpo sobe para a cor de texto principal e o véu
   fecha no meio, que é onde ele assenta. Com --ink-dim e véu a 45% a frase
   ficava a competir com os telhados por baixo. */
.hero--tall .hero__sub {
  max-width: 34rem;
  color: var(--ink);
  text-shadow: 0 1px 12px rgba(0, 0, 0, .8);
}
.hero--tall .hero__scrim {
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--ground) 72%, transparent) 0%,
    color-mix(in srgb, var(--ground) 66%, transparent) 45%,
    color-mix(in srgb, var(--ground) 88%, transparent) 100%);
}
.hero__badge {
  width: clamp(130px, 15vw, 168px); height: auto;
  /* Duas sombras: uma escura que assenta o logo na fotografia, e um halo
     dourado que o descola dela. É o halo que faltava. */
  filter: drop-shadow(0 8px 28px rgba(0, 0, 0, .6))
          drop-shadow(0 0 34px color-mix(in srgb, var(--gold) 30%, transparent));
  animation: badgeFloat 5s ease-in-out infinite;
}
@keyframes badgeFloat {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-9px) rotate(1.2deg); }
}
@media (prefers-reduced-motion: reduce) {
  .hero__badge { animation: none; }
  .scroll-cue svg { animation: none; }
  .live__dot::after { animation: none; }
}

/* --- estado do servidor ao vivo --- */
.live {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--edge-strong);
  border-radius: 999px;
  background: color-mix(in srgb, var(--surface) 80%, transparent);
  backdrop-filter: blur(6px);
  font-family: var(--font-util);
  font-size: var(--text-sm);
  letter-spacing: .06em;
  color: var(--ink-dim);
}
.live__count { color: var(--gold); font-weight: 600; font-variant-numeric: tabular-nums; }
.live__dot {
  position: relative;
  width: .5rem; height: .5rem; border-radius: 50%;
  background: var(--good);
  flex: none;
}
.live__dot::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: 50%;
  background: var(--good);
  animation: pulse 2.4s var(--ease-out) infinite;
}
.live[data-state="offline"] .live__dot { background: var(--bad); }
.live[data-state="offline"] .live__dot::after { animation: none; }

@keyframes pulse {
  0%   { transform: scale(1);   opacity: .7; }
  70%  { transform: scale(3);   opacity: 0; }
  100% { transform: scale(3);   opacity: 0; }
}

/* --- sinal de scroll --- */
.scroll-cue {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
  margin-top: var(--sp-6);
  font-family: var(--font-util);
  text-transform: uppercase;
  letter-spacing: .18em;
  font-size: var(--text-xs);
  color: var(--ink-dim);
  text-decoration: none;
}
.scroll-cue svg { animation: nudge 2.6s var(--ease-out) infinite; }
@keyframes nudge {
  0%, 100% { transform: translateY(0); opacity: .55; }
  50%      { transform: translateY(5px); opacity: 1; }
}

/* Página de uma funcionalidade: texto e ficha lado a lado em ecrã largo,
   empilhados em estreito. A ficha acompanha a leitura sem a interromper. */
.feature-layout { display: grid; gap: var(--sp-7); align-items: start; }
@media (min-width: 60rem) {
  .feature-layout { grid-template-columns: minmax(0, 1fr) 20rem; }
  .feature-layout aside { position: sticky; top: 6rem; }
}

/* -------------------------------------------------------------
   Cabeçalho das páginas sem imagem (guias, regras, FAQ, notícias)
   Sem isto começavam a seco por baixo do header e pareciam por acabar,
   ao lado das páginas que abrem com hero.
   ------------------------------------------------------------- */
.page-head {
  border-bottom: 1px solid var(--edge);
  padding-block: var(--sp-8) var(--sp-6);
  background:
    radial-gradient(120% 100% at 0% 0%,
      color-mix(in srgb, var(--gold) 7%, transparent) 0%,
      transparent 60%);
}
.page-head__inner { display: flex; flex-direction: column; gap: var(--sp-3); }
.page-head h1 { font-size: clamp(2.2rem, 5vw, 3.2rem); line-height: var(--leading-tight); }
.page-head .lede { margin-top: var(--sp-1); }

/* -------------------------------------------------------------
   Acordeão (FAQ)
   ------------------------------------------------------------- */
.accordion { border: 1px solid var(--edge); border-radius: var(--radius); background: var(--surface); }
.accordion + .accordion { margin-top: var(--sp-3); }
/* NÃO é flex, e isso é deliberado. Enquanto era, o `gap` metia-se entre os
   itens flex — e a pesquisa, ao partir o título em <mark> + resto, criava dois
   itens e ganhava um intervalo de 12px a meio da palavra: «Dele gacias».
   Como bloco normal, o texto flui inline e pode ser partido à vontade.
   O chevron passa a estar preso por posição, com espaço reservado no padding. */
.accordion__q {
  position: relative;
  display: block;
  padding: var(--sp-4) var(--sp-5) var(--sp-4)
           calc(var(--sp-5) + .5rem + var(--sp-3));
  font-weight: 600;
  font-size: var(--text-md);
  cursor: pointer;
  list-style: none;                 /* tira o triângulo por omissão */
  transition: color var(--dur) var(--ease);
}
.accordion__q::-webkit-details-marker { display: none; }
.accordion__q:hover { color: var(--gold); }
/* Marcador próprio: um sinal que roda ao abrir. */
.accordion__q::before {
  content: "";
  position: absolute;
  left: var(--sp-5);
  top: 50%;
  width: .5rem; height: .5rem;
  border-right: 2px solid var(--gold);
  border-bottom: 2px solid var(--gold);
  transform: translateY(-50%) rotate(-45deg);
  transition: transform var(--dur) var(--ease);
}
.accordion[open] .accordion__q::before { transform: translateY(-50%) rotate(45deg); }
.accordion__a {
  padding: 0 var(--sp-5) var(--sp-5) calc(var(--sp-5) + var(--sp-3) + .5rem);
  color: var(--ink-dim);
  /* O acordeão alargou para 900px, mas o TEXTO lá dentro não pode acompanhar:
     a essa largura dava ~90 caracteres por linha, e o olho perde-se a voltar
     ao início da linha seguinte. A caixa é larga, a linha é curta. */
  max-width: var(--measure);
}
.accordion__a > * + * { margin-top: var(--sp-3); }

/* -------------------------------------------------------------
   Cartões
   ------------------------------------------------------------- */
.card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  /* relative por causa do brilho (::after), que tem de sair do fluxo — como
     filho de um flex container, sem position ele viraria um item de layout. */
  position: relative;
  /* Sem isto, os cantos quadrados da fotografia (que sangra até à borda com
     margens negativas) espetavam para fora do cartão arredondado. */
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  padding: var(--sp-5);
  box-shadow: var(--edge-light);
  transition: border-color var(--dur) var(--ease),
              background-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              transform var(--dur) var(--ease-out);
}
a.plain:hover .card, .card--link:hover {
  border-color: color-mix(in srgb, var(--gold) 35%, var(--edge-strong));
  background: var(--surface-2);
  box-shadow: var(--shadow-lift), var(--edge-light);
  transform: translateY(-2px);
}
.card__media {
  position: relative;  /* âncora do brilho */
  margin: calc(var(--sp-5) * -1) calc(var(--sp-5) * -1) 0;
  overflow: hidden;   /* segura o zoom da imagem no hover */
}
.card__media img {
  width: 100%; aspect-ratio: 16 / 10; object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}
a.plain:hover .card__media img { transform: scale(1.04); }

/* --- inclinação e brilho, a seguir ao rato ---
   Um ÚNICO ouvinte delegado no <main> trata dos 82 cartões da home: descobre o
   que está sob o cursor com closest() e só calcula para esse. Se cada cartão
   tivesse o seu ouvinte — que é como o componente do 21st.dev faz — seriam 82 a
   disputar a mesma thread com a simulação de fluido, que corre no mesmo evento.

   A inclinação é de 5,5°, de propósito. O registo da marca é madeira gasta e
   chapa, não vidro: a 15° com camadas a flutuar parecia um cartão de SaaS.

   O `transform` base é composto, não substituído — o hover já trazia um
   translateY(-2px) e perdê-lo tirava a elevação. */
@media (hover: hover) and (pointer: fine) {
  .js-motion .card {
    transform: perspective(900px)
               rotateX(var(--tilt-x, 0deg))
               rotateY(var(--tilt-y, 0deg));
  }
  .js-motion a.plain:hover .card,
  .js-motion .card--link:hover {
    transform: perspective(900px)
               translateY(-2px)
               rotateX(var(--tilt-x, 0deg))
               rotateY(var(--tilt-y, 0deg));
  }
  /* Só o cartão sob o cursor é promovido a camada. Nos 82 permanentemente,
     seriam 82 camadas na GPU — aí sim ficava pesado. */
  .js-motion .card[data-tilting] { will-change: transform; }
}

/* O brilho: uma mancha de luz dourada onde o rato está. É o mesmo gesto do
   varrimento dos botões — luz a correr sobre chapa, não reflexo de vidro.

   VIVE NA FOTOGRAFIA, NÃO NO CARTÃO INTEIRO, e isso é medido: por cima do
   cartão todo, o pior pixel atrás do `.card__text` dava 4,30 de contraste, que
   falha AA. Baixar a intensidade não servia — pelas contas teria de descer de
   10% para ~4%, e a essa força já não se vê nada. Confinado à imagem, não toca
   em texto nenhum e pode ficar com a força que precisa.

   Consequência aceite: cartões sem fotografia levam inclinação mas não levam
   brilho. */
.card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
  background: radial-gradient(
    300px circle at var(--mx, 50%) var(--my, 50%),
    color-mix(in srgb, var(--gold) 22%, transparent),
    transparent 60%
  );
}
.card[data-tilting] .card__media::after { opacity: 1; }

/* Quem pediu menos movimento não leva zoom nem deslocamento. */
@media (prefers-reduced-motion: reduce) {
  a.plain:hover .card { transform: none; }
  a.plain:hover .card__media img { transform: none; }
  .card__media::after { display: none; }
}
.card__title { font-size: var(--text-lg); }
.card__text { color: var(--ink-dim); font-size: var(--text-sm); }
.card__foot { margin-top: auto; padding-top: var(--sp-3); }

/* -------------------------------------------------------------
   Cartão que vira — só nas atividades e nos ofícios
   -------------------------------------------------------------
   Frente: a fotografia ocupa o cartão todo e por cima está só o nome.
   Verso: o resumo, o que dá, o que precisa, a dificuldade e onde é.

   As duas caras estão sobrepostas e `backface-visibility: hidden` esconde a
   que está de costas. Sendo ambas absolutas, nenhuma dá altura ao cartão — daí
   o aspect-ratio, que é o que o impede de colapsar a zero.

   O quadrado é medido, não é gosto. O verso mais cheio ocupa 338px e o mais
   vazio 313px; a três colunas o cartão tem 361px de largura. Em 4:5 dava 452px
   de altura e sobrava um buraco de 114 a 139px a meio de todos os versos. Em
   1:1 o conteúdo quase preenche a cara e o pé assenta onde deve.

   O quadrado é também o formato mais fácil de gerar para as fotografias novas.

   NÃO usa a classe .card de propósito. O `cardTilt` procura `.card` e escreve
   `transform` no elemento; aqui o `transform` é da rotação e os dois pisavam-se
   um ao outro. Ao ficar de fora, o tilt ignora-o sozinho.                    */
.flip {
  display: block;
  perspective: 1400px;
}
.flip__inner {
  position: relative;
  aspect-ratio: 1 / 1;
  transform-style: preserve-3d;
  transition: transform .7s var(--ease);
}
/* :focus-visible no <a> de fora, que é quem recebe o foco: quem anda de teclado
   vê o mesmo que quem anda de rato. */
.flip:hover .flip__inner,
.flip:focus-visible .flip__inner { transform: rotateY(180deg); }
.flip:hover .flip__inner { will-change: transform; }

.flip__face {
  position: absolute;
  inset: 0;
  /* `overflow` aqui pode: o que não pode é no .flip__inner, que perderia o
     preserve-3d e achataria as duas caras uma sobre a outra. */
  overflow: hidden;
  border: 1px solid var(--edge);
  border-radius: var(--radius-lg);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.flip__face--verso { transform: rotateY(180deg); }
.flip:hover .flip__face,
.flip:focus-visible .flip__face {
  border-color: color-mix(in srgb, var(--gold) 35%, var(--edge-strong));
}

/* --- frente --- */
.flip__face--frente {
  /* Fundo para os ofícios que ainda não têm fotografia própria: sem isto a
     frente ficava um retângulo preto e parecia partida. */
  background:
    radial-gradient(120% 80% at 50% 0%, var(--surface-2), var(--surface));
}
.flip__face--frente picture { position: absolute; inset: 0; display: block; }
.flip__face--frente img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}
/* O véu escurece o terço de baixo para o nome ter contraste venha a fotografia
   que vier — e vão vir muitas que eu não vejo.

   Os valores são calculados para o PIOR caso: uma fotografia toda branca por
   baixo do topo de um nome de três linhas, que é o que sobe mais e por isso
   apanha o véu mais fraco. Com 55%/92% dava 4,06, que passa em AA só por o
   nome contar como texto grande (27,6px). Com 62%/94% dá 4,83 e passa o limiar
   de texto normal, 4,5, sem depender dessa isenção.

   Medido nas fotografias que lá estão hoje: o pior é 5,76 («Companhia dos
   caminhos de ferro»), o melhor passa dos 11. */
.flip__veu {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    transparent 32%,
    color-mix(in srgb, var(--ground) 62%, transparent) 64%,
    color-mix(in srgb, var(--ground) 94%, transparent) 100%
  );
}
.flip__nome {
  position: absolute;
  inset: auto var(--sp-5) var(--sp-5) var(--sp-5);
  font-family: var(--font-display);
  font-size: var(--text-xl);
  line-height: var(--leading-tight);
  color: var(--ink);
  text-shadow: 0 2px 14px rgba(0, 0, 0, .85);
}
/* A seta circular é a única pista de que o cartão vira. Discreta: quem não
   reparar continua a poder clicar e chegar à mesma informação. */
.flip__pista {
  position: absolute;
  top: var(--sp-4);
  right: var(--sp-4);
  display: grid;
  place-items: center;
  width: 30px; height: 30px;
  border: 1px solid color-mix(in srgb, var(--ink) 30%, transparent);
  border-radius: 50%;
  color: var(--ink);
  background: color-mix(in srgb, var(--ground) 45%, transparent);
  backdrop-filter: blur(3px);
  opacity: .75;
}

/* --- verso --- */
.flip__face--verso {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-5);
  background: var(--surface);
  box-shadow: var(--edge-light);
}
.flip__eco {
  font-family: var(--font-util);
  text-transform: uppercase;
  letter-spacing: .08em;
  font-size: var(--text-sm);
  color: var(--gold);
}
.flip__resumo { color: var(--ink); font-size: var(--text-sm); }
.flip__bloco { display: flex; flex-direction: column; gap: var(--sp-2); }
.flip__badges { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.flip__pe {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  margin-top: auto;
  padding-top: var(--sp-3);
  border-top: 1px solid var(--edge);
}
.flip__cta {
  margin-left: auto;
  font-family: var(--font-util);
  text-transform: uppercase;
  letter-spacing: .08em;
  font-size: var(--text-sm);
  color: var(--gold);
}
.flip__cta::after { content: " →"; }

/* Num ecrã de toque não há hover, e virar ao toque roubava o toque ao link.
   Fica a frente, e quem quiser saber mais abre a página — que tem tudo isto e
   mais. O verso sai do documento para nem chegar a pintar. */
@media (hover: none) {
  .flip__inner { transform: none !important; }
  .flip__face--verso { display: none; }
  .flip__pista { display: none; }
}

/* Com movimento reduzido a regra global do base.css já corta a duração da
   transição, e a troca passa a ser instantânea em vez de uma rotação. É o que
   se quer: o estado continua a mudar, o movimento é que desaparece. */
@media (prefers-reduced-motion: reduce) {
  .flip__face--frente img { transition: none; }
}

/* -------------------------------------------------------------
   Quadro — anúncios e cartazes
   -------------------------------------------------------------
   Na home fica logo a seguir ao hero. Os anúncios são o que traz de volta quem
   já conhece o servidor, e estavam a meio da página, abaixo de três grelhas. */
.quadro__topo {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: space-between;
  gap: var(--sp-4);
}
/* Os cartazes ocupam colunas iguais e os avisos ficam com a última. Sem
   cartazes, a lista de avisos toma a largura toda em vez de deixar buracos. */
.quadro__grelha {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: 1fr;
}
@media (min-width: 48rem) {
  .quadro__grelha { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
  .quadro__avisos { grid-column: span 2; }
}
@media (min-width: 64rem) {
  .quadro__avisos { grid-column: auto; }
}

/* Um aviso é uma linha, não um cartão: ao lado de um cartaz, um cartão com
   fotografia disputava-lhe a atenção. */
.aviso {
  display: block;
  padding: var(--sp-4);
  border: 1px solid var(--edge);
  border-left: 2px solid var(--gold-deep);
  border-radius: var(--radius-sm);
  background: var(--surface);
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.aviso:hover { background: var(--surface-2); border-color: var(--edge-strong); border-left-color: var(--gold); }
.aviso__data {
  display: block;
  font-family: var(--font-util);
  text-transform: uppercase;
  letter-spacing: .08em;
  font-size: var(--text-xs);
  color: var(--ink-mute);
}
.aviso__titulo { display: block; margin-top: var(--sp-1); color: var(--ink); }
.aviso__marca { margin-top: var(--sp-2); }

/* --- cartazes --- */
.cartazes {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
}
.cartaz {
  display: block;
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease-out);
}
.cartaz:hover { border-color: color-mix(in srgb, var(--gold) 35%, var(--edge-strong)); transform: translateY(-2px); }
@media (prefers-reduced-motion: reduce) { .cartaz:hover { transform: none; } }
.cartaz__imagem { position: relative; background: var(--ground); }
/* 2:3, que é o formato em que os cartazes são feitos (1024×1536). O número não
   é escolhido: com 3:4 o corte comia 11% da altura, e nestes cartazes o topo e o
   rodapé são texto — «FESTA DO» em cima, «VENHAM COM FOME» em baixo. Na medida
   certa não se corta nada e a grelha continua alinhada.

   Se algum dia vier um cartaz de outra proporção, é ele que se ajusta: mudar
   isto volta a cortar todos os outros. */
.cartaz__imagem img { display: block; width: 100%; aspect-ratio: 2 / 3; object-fit: cover; }
.cartaz__selo {
  position: absolute;
  inset: auto var(--sp-3) var(--sp-3) auto;
  padding: var(--sp-1) var(--sp-3);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--ground) 88%, transparent);
  font-family: var(--font-util);
  text-transform: uppercase;
  letter-spacing: .08em;
  font-size: var(--text-xs);
  color: var(--ink-dim);
}
/* Um evento passado não se esconde — serve de prova de que o servidor tem
   vida — mas também não compete com o que ainda vai acontecer. */
.cartaz--passado .cartaz__imagem img { filter: grayscale(.7) brightness(.75); }
/* Cartaz dentro de um cartão de anúncio. Ao contrário das fotografias, que são
   fundo e por isso vão a 16:10 cortadas, este é a mensagem: mostra-se inteiro.

   O seletor tem de incluir `.card__media` para bater a regra de cima, que é
   `.card__media img` e ganhava por especificidade — o cartaz da Delegacia
   aparecia cortado a meio, sem o título nem o «PROCURAMOS DELEGADOS». */
.card__media img.card__cartaz,
img.card__cartaz {
  width: 100%;
  height: auto;
  aspect-ratio: auto;
  max-height: 26rem;
  object-fit: contain;
  /* Transparente e não `--ground`: um cartaz ao alto dentro de uma caixa mais
     larga sobra dos dois lados, e com fundo próprio essas sobras apareciam como
     duas barras escuras. Assim é o cartão que se vê por trás. */
  background: transparent;
}

.cartaz__corpo { display: flex; flex-direction: column; gap: var(--sp-2); padding: var(--sp-4); }
.cartaz__titulo { font-size: var(--text-lg); }
.cartaz__onde { color: var(--ink-dim); font-size: var(--text-sm); }
.cartaz__resumo { color: var(--ink-dim); font-size: var(--text-sm); }

/* --- página de um evento --- */
.evento { display: grid; gap: var(--sp-6); align-items: start; }
@media (min-width: 60rem) {
  .evento { grid-template-columns: minmax(0, 5fr) minmax(0, 4fr); gap: var(--sp-7); }
}
/* Aqui o cartaz vê-se INTEIRO: é o que foi feito para ser visto. O tecto de
   altura é para um cartaz muito ao alto não empurrar o texto para fora do ecrã. */
.evento__cartaz img {
  display: block;
  width: 100%;
  max-height: 80vh;
  object-fit: contain;
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  background: var(--ground);
}
.evento__titulo { font-family: var(--font-display); font-size: var(--text-2xl); line-height: var(--leading-tight); }
.evento__quando {
  padding: var(--sp-4);
  border: 1px solid var(--edge);
  border-radius: var(--radius-sm);
  background: var(--surface);
}

/* -------------------------------------------------------------
   Carrossel em arco — destaques da home
   -------------------------------------------------------------
   Por baixo é um scroller horizontal com scroll-snap nativo. Isso é o que o
   faz funcionar com o dedo, com a roda, com o teclado e SEM JavaScript: sem o
   site.js fica um carrossel liso, que é uma versão inteiramente utilizável.

   O JS só escreve --giro, --profundidade, --escala e --opacidade a partir da
   distância de cada cartão ao centro da pista. Se ele não correr, os valores
   por omissão deixam tudo direito.

   O `perspective` vive na PISTA e não em cada cartão: com perspetiva própria
   cada cartão teria o seu ponto de fuga e a curva deixava de ser uma curva.  */
.arco { position: relative; }

.arco__pista {
  display: flex;
  gap: var(--sp-5);
  margin: 0;
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  /* SEM scroll-snap, de propósito. O carrossel roda de contínuo, e o encosto
     obrigatório puxava-o de volta ao cartão mais próximo a cada frame — ou
     tremia, ou parava. Isto é uma passadeira, não um diaporama: quem dá o
     ponto de leitura é a curva, que já põe o cartão do meio direito e à
     frente. */
  perspective: 1100px;
  /* Espaço em cima e em baixo para os cartões que rodam não serem cortados
     pelo próprio scroller — `overflow-x: auto` também recorta em Y. */
  padding-block: var(--sp-6);
  /* Zero, e não `calc(50% - w/2)`: a centrar o primeiro cartão, metade esquerda
     da pista ficava vazia ao chegar à página — 430px de nada antes do primeiro
     destaque. Assim começa cheia e vê-se logo a curva, que é o ponto.

     Zero e não `var(--gutter)`: a pista já vive dentro de um `.wrap`, que traz
     a margem da secção. Somar outra punha os cartões 24px à direita do título
     da secção. */
  padding-inline: 0;
  scrollbar-width: none;
  --arco-w: 320px;
}
.arco__pista::-webkit-scrollbar { display: none; }

.arco__item {
  flex: 0 0 var(--arco-w);
  transform:
    rotateY(var(--giro, 0deg))
    translateZ(var(--profundidade, 0px))
    scale(var(--escala, 1));
  opacity: var(--opacidade, 1);
}

.arco__cartao {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  border: 1px solid var(--edge);
  border-radius: var(--radius-lg);
  background: radial-gradient(120% 80% at 50% 0%, var(--surface-2), var(--surface));
  box-shadow: var(--shadow-lift);
}
.arco__cartao picture { position: absolute; inset: 0; display: block; }
.arco__cartao img { width: 100%; height: 100%; object-fit: cover; }
.arco__cartao:hover { border-color: color-mix(in srgb, var(--gold) 35%, var(--edge-strong)); }

/* Os mesmos 62%/94% do cartão que vira, e pela mesma razão medida. */
.arco__veu {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    transparent 32%,
    color-mix(in srgb, var(--ground) 62%, transparent) 64%,
    color-mix(in srgb, var(--ground) 94%, transparent) 100%
  );
}
.arco__nome {
  position: absolute;
  inset: auto var(--sp-5) var(--sp-5) var(--sp-5);
  font-family: var(--font-display);
  font-size: var(--text-lg);
  line-height: var(--leading-tight);
  color: var(--ink);
  text-shadow: 0 2px 14px rgba(0, 0, 0, .85);
}

.arco__seta {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 44px; height: 44px;   /* 44px é o alvo mínimo de toque */
  border: 1px solid var(--edge-strong);
  border-radius: 50%;
  background: color-mix(in srgb, var(--ground) 82%, transparent);
  backdrop-filter: blur(6px);
  color: var(--ink);
  cursor: pointer;
}
.arco__seta:hover {
  border-color: var(--gold);
  color: var(--gold);
}
.arco__seta[disabled] { opacity: .3; cursor: default; }
.arco__seta[disabled]:hover { border-color: var(--edge-strong); color: var(--ink); }
.arco__seta--tras { left: calc(var(--gutter) * -1); }
.arco__seta--frente { right: calc(var(--gutter) * -1); }
/* Em ecrã estreito não há espaço fora da pista, e há dedo para arrastar. */
@media (max-width: 60rem) {
  .arco__seta { display: none; }
  .arco__pista { --arco-w: min(76vw, 320px); }
}

/* -------------------------------------------------------------
   Estatísticas
   ------------------------------------------------------------- */
.stat__value {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  line-height: 1;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}
.stat__label {
  font-family: var(--font-util);
  text-transform: uppercase;
  letter-spacing: .1em;
  font-size: var(--text-xs);
  color: var(--ink-dim);
  margin-top: var(--sp-1);
}

/* -------------------------------------------------------------
   Distintivos e estado
   ------------------------------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-util);
  text-transform: uppercase;
  letter-spacing: .1em;
  font-size: var(--text-xs);
  font-weight: 600;
  padding: var(--sp-1) var(--sp-3);
  border: 1px solid var(--edge-strong);
  border-radius: var(--radius-sm);
  color: var(--ink-dim);
}
.badge--good { color: var(--good); border-color: color-mix(in srgb, var(--good) 40%, transparent); }
.badge--warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.badge--bad  { color: var(--bad);  border-color: color-mix(in srgb, var(--bad) 40%, transparent); }

/* O ponto tem de acompanhar a cor — nunca só a cor a dar a informação:
   o texto do badge diz sempre o estado por extenso. */
.badge__dot { width: .5rem; height: .5rem; border-radius: 50%; background: currentColor; flex: none; }

/* -------------------------------------------------------------
   Cabeçalho de secção
   ------------------------------------------------------------- */
.section-head { display: flex; flex-direction: column; gap: var(--sp-2); margin-bottom: var(--sp-6); }
.section-head__title { font-size: var(--text-2xl); }

/* -------------------------------------------------------------
   Tabelas
   ------------------------------------------------------------- */
.table { width: 100%; border-collapse: collapse; }
.table th, .table td {
  text-align: left;
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--edge);
  vertical-align: top;
}
.table th {
  font-family: var(--font-util);
  text-transform: uppercase;
  letter-spacing: .12em;
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--gold);
}
.table td { font-size: var(--text-sm); }
.table tr:last-child td { border-bottom: 0; }

/* -------------------------------------------------------------
   Rodapé
   ------------------------------------------------------------- */
.site-footer {
  border-top: 1px solid var(--edge);
  padding-block: var(--sp-7);
  margin-top: var(--sp-9);
  color: var(--ink-dim);
  font-size: var(--text-sm);
}
/* Nas colunas de navegação o sublinhado sobrecarrega a lista; guarda-se para
   o hover. Nas ligações dentro de frases (Discord, endereço) mantém-se. */
.site-footer a { color: var(--ink-dim); text-decoration: none; }
.site-footer a:hover { color: var(--river-bright); text-decoration: underline; }
.site-footer .cluster a { text-decoration: underline; }

/* -------------------------------------------------------------
   Cursor de revólver

   Só em desktop: num ecrã de toque não há ponteiro nenhum para substituir.

   É CSS puro e sem JavaScript, de propósito. A palavra-chave a seguir à imagem
   (`, auto` / `, pointer`) é a reserva: se o PNG falhar, o browser cai no
   cursor semântico certo em vez de deixar a pessoa sem cursor. Nunca uses
   `cursor: none` aqui — com o JS partido ficava-se sem ponteiro nenhum.

   As duas variantes partilham o ponto ativo `9 11`, medido na boca do cano.
   Se gerares os PNG outra vez, o script confirma que os dois coincidem — se
   divergirem, o cursor salta ao passar por cima de um link.

   Caminhos relativos ao ficheiro CSS: é assim que o manifesto do WhiteNoise os
   consegue reescrever com hash em produção.

   ESTE BLOCO FICA NO FIM DO FICHEIRO. Regras de classe com `cursor: pointer`
   (.btn, .nav-toggle, .motion-toggle, .accordion__q) vencem seletores de
   elemento por especificidade, por isso estão nomeadas abaixo — e ficar no
   fim garante que empates de especificidade também caem para este lado.
   ------------------------------------------------------------- */
@media (hover: hover) and (pointer: fine) {
  html {
    cursor: url("../img/cursor/revolver.02ae51756e42.png?v=2") 2 6, auto;
    cursor: image-set(url("../img/cursor/revolver.02ae51756e42.png?v=2") 1x,
                      url("../img/cursor/revolver@2x.ec14889fcef0.png?v=2") 2x) 2 6, auto;
  }

  /* Com o revólver em todo o lado perde-se a mão do sistema, que era o que
     dizia «isto é clicável». O anel na boca do cano é o que a substitui. */
  a, button, summary, label[for], select,
  [role="button"], [role="link"], .card,
  .btn, .nav-toggle, .motion-toggle, .accordion__q {
    cursor: url("../img/cursor/revolver-hover.5a097d47d551.png?v=2") 2 6, pointer;
    cursor: image-set(url("../img/cursor/revolver-hover.5a097d47d551.png?v=2") 1x,
                      url("../img/cursor/revolver-hover@2x.46556fc2d3e1.png?v=2") 2x) 2 6, pointer;
  }

  /* Onde se escreve e onde se lê muito seguido, manda o sistema. Um revólver
     por cima de uma caixa de texto ou de um artigo longo não é ambiente — é
     uma coisa avariada. */
  input, textarea, [contenteditable] { cursor: text; }
  .prose, .prose * { cursor: auto; }
  .prose a { cursor: pointer; }

  [disabled], [aria-disabled="true"] { cursor: not-allowed; }
}

/* -------------------------------------------------------------
   Acordeão em duas colunas

   As 52 regras numa só coluna deixavam metade da largura vazia. A duas
   colunas o espaço é usado e cada coluna fica com ~500px de texto — melhor
   medida de leitura do que os 900px de coluna única que isto foi antes.

   GRELHA e não `columns` do CSS: com multi-coluna, abrir um item reflui todo
   o conteúdo entre as colunas e as regras saltam de sítio debaixo do cursor.
   Com grelha, abrir um item cresce só a sua linha.

   `align-items: start` é obrigatório: sem ele os itens esticam-se à altura da
   linha, e um item aberto ao lado de um fechado deixava o fechado com uma
   caixa alta e vazia.
   ------------------------------------------------------------- */
.accordion-grid { display: grid; gap: var(--sp-3); }
@media (min-width: 60rem) {
  .accordion-grid {
    grid-template-columns: repeat(2, 1fr);
    column-gap: var(--sp-5);
    align-items: start;
  }
}

/* Dentro da grelha o espaçamento vem do `gap`. A margem da lista empilhada
   continuava a aplicar-se e empurrava para baixo todos os itens menos o
   primeiro — na prática, a coluna da direita ficava 12px desalinhada. */
.accordion-grid .accordion + .accordion { margin-top: 0; }

/* -------------------------------------------------------------
   Cabeçalho de página com fotografia

   Mesmo tratamento das bandas: imagem e véu em z-index -2, para o fluido
   (fixo, z-index -1) lhes passar por cima. Se algum dia isto ganhar
   `isolation`, `filter` ou `z-index` próprio, a fotografia fica presa cá
   dentro e o fluido desaparece desta zona.
   ------------------------------------------------------------- */
.page-head--photo {
  position: relative;
  overflow: hidden;
  padding-block: var(--sp-9) var(--sp-8);
  border-bottom: 0;
}
.page-head__media { position: absolute; inset: 0; z-index: -2; }
.page-head__media picture { display: block; width: 100%; height: 100%; }
.page-head__media img { width: 100%; height: 100%; object-fit: cover; }

/* Véu em GRADIENTE, não chapado. A 90% em toda a largura o texto passava mas a
   fotografia desaparecia — ficava textura, não imagem. Aqui é escuro onde o
   texto assenta (à esquerda) e alivia para a direita, onde não há nada a ler.
   É o mesmo truque do hero.

   Em ecrã estreito volta a ser chapado: o texto ocupa a largura toda e sairia
   fora da parte escura do gradiente. */
.page-head__scrim {
  position: absolute;
  inset: 0;
  z-index: -2;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--ground) 95%, transparent) 0%,
    color-mix(in srgb, var(--ground) 90%, transparent) 46%,
    color-mix(in srgb, var(--ground) 55%, transparent) 100%
  );
}
@media (max-width: 60rem) {
  .page-head__scrim { background: color-mix(in srgb, var(--ground) 90%, transparent); }
}
/* Só esbate em baixo: em cima encosta ao cabeçalho fixo do site, e um
   esbatimento aí deixava uma faixa estranha por baixo da barra. */
.page-head__scrim::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 6rem;
  background: linear-gradient(to bottom, transparent, var(--ground));
  pointer-events: none;
}

/* Sobre fotografia, o texto secundário sobe para o tom principal. É a mesma
   decisão do hero, e pelo mesmo motivo: com --ink-dim e véu suficientemente
   leve para a imagem se ver, o lede caía para 3,9 de contraste. Ou se escurece
   a fotografia até a apagar, ou se clareia o texto — clareia-se o texto. */
.page-head--photo .lede {
  color: var(--ink);
  text-shadow: 0 1px 10px rgba(0, 0, 0, .55);
}

/* -------------------------------------------------------------
   Manifesto — é uma declaração, não um artigo de referência.
   ------------------------------------------------------------- */
.manifesto-hero { display: flex; align-items: center; min-height: min(58svh, 30rem); }
.manifesto-hero .hero__body { align-items: center; text-align: center; margin-inline: auto; max-width: 40rem; }
.manifesto-hero .hero__sub { color: var(--ink); text-shadow: 0 1px 12px rgba(0,0,0,.8); }

/* Texto maior e mais arejado do que num guia: lê-se de uma vez, não se
   consulta.

   Fica CENTRADO, mas isso obriga a linhas curtas — texto centrado com 80
   caracteres por linha é penoso, porque o olho não sabe onde começa a linha
   seguinte. Daí os 34rem em vez dos 680px da prosa normal. Se alargares a
   coluna, tira o centrado. */
.manifesto__texto {
  font-size: var(--text-md);
  max-width: 34rem;
  margin-inline: auto;
}
.manifesto__texto p { text-wrap: balance; }
.manifesto__texto h2 {
  font-size: var(--text-lg);
  color: var(--gold);
  margin-top: var(--sp-8);
}
.manifesto__texto strong { color: var(--ink); }
.manifesto__texto hr { border-top-color: var(--edge-strong); }
.manifesto__texto > p:last-child { color: var(--gold); font-style: italic; }
