/* ============================================================================
 * PULSE — INTRO · assets/intro.css (v1.213)
 * ----------------------------------------------------------------------------
 * Estilo do bloco acf/pulse-intro. Carrega SÓ quando o bloco está na página
 * (pulse_intro_enqueue_assets), depois do sections.css — consome os TOKENS do
 * tema (--head/--ease), por isso cores globais e claro/escuro aplicam-se
 * sozinhos (o SVG pinta com currentColor ← var(--head)).
 *
 * ANIMAÇÃO: o port BYTE-FIEL da "11 · Travessia com batimento" do
 * preview-logo-anim.html — keyframes pl-top-travessia/pl-bot-travessia/
 * pl-fill-travessia/pl-beat-travessia renomeados pin-* (namespace próprio;
 * a Galeria já ocupa pgt-* com a nº 10) e as regras .pl--travessia/
 * .pl--travessia-bat re-scopadas a .pulse-intro. Os px dos keyframes são
 * unidades do viewBox 360×120 — o palco escala e os trajetos escalam juntos.
 * Motor 100% CSS: corre ao CARREGAR sem JS; 'loop' = infinite (base),
 * '--uma' troca para 1 iteração + forwards (a marca atravessa e sai — o
 * gesto de abertura) e '--uma-fica' (v1.219) troca os keyframes por
 * pin-*-fica: só o troço de entrada, a segurar no logótipo formado — a
 * abertura que termina com a marca presente. A duração vem do render em
 * --pin-dur (vazio = 5250 ms, o --pl-dur-longa original: 3 s × 1.75).
 *
 * TEXTO: a entrada (aparecer/subir/escala) são keyframes de load com from/to
 * — a base NUNCA fica opacity:0 (sem CSS-anim ou com movimento reduzido o
 * texto está sempre visível). O 'dividido' só anima DEPOIS de o intro.js
 * repartir a frase (.is-split): sem JS, texto normal — progressive
 * enhancement, o contrato da casa.
 *
 * NO EDITOR (.pulse-intro--editor): tudo congela na formação do logótipo
 * (animation none → transform 0 = a janela 21–29% dos keyframes), a mesma
 * regra da Galeria — as regras vêm DEPOIS das de animação de propósito
 * (mesma especificidade — ganham por ordem).
 * ========================================================================== */

.pulse-intro {
	display: flex;
	flex-direction: column;
	gap: clamp(1.2rem, .8rem + 1.6vw, 2.2rem);
}

/* ---- Palco --------------------------------------------------------------
   A pista 3:1 do viewBox, centrada e com largura travada por --pin-w — o
   "Tamanho da animação" do painel só troca a var (peq/gra). */
.pulse-intro__palco {
	width: min(100%, var(--pin-w, 36rem));
	margin-inline: auto;
}

.pulse-intro--tam-peq {
	--pin-w: 24rem;
}

.pulse-intro--tam-gra {
	--pin-w: 52rem;
}

/* ---- SVG (a estrutura base .pl do preview, scoped) -----------------------
   currentColor ← var(--head): branco no tema escuro, tinta no claro (o
   tema.css redefine --head em html.pulse-claro) — sem regras por tema aqui.
   A máscara nas pontas esbate a entrada/saída (o .pl--travessia original). */
.pulse-intro__logo {
	display: block;
	width: 100%;
	height: auto;
	color: var(--head, #fff);
	overflow: hidden;
	-webkit-mask-image: linear-gradient(to right, transparent, #000 18%, #000 82%, transparent);
	mask-image: linear-gradient(to right, transparent, #000 18%, #000 82%, transparent);
}

.pulse-intro__logo path,
.pulse-intro__logo circle {
	fill: currentColor;
}

/* O filete anti-costura do preview: cada metade transborda para lá da sua
   geometria, as duas passam a SOBREPOR-SE ao longo da aresta partilhada e a
   linha de fundo entre elas desaparece. O stroke é non-scaling — mede-se em
   pixels de ECRÃ, não do viewBox — por isso vale igual na animação pequena e
   na "Cheia": o desenho escala, o filete não.
   v1.225 — a largura passou de 1 para 2. PORQUÊ: com 1 o transbordo era de
   MEIO pixel por lado, o mínimo possível, e como o preenchimento e o filete
   são duas passagens de pintura, um pixel de ecrã atravessado pela aresta
   nunca chegava a ficar 100% coberto por nenhuma das metades — sobrava uma
   risca a ~94% da cor da marca. Reta e longa, é precisamente o que o olho
   apanha: era o filete de fundo que se via no meio da marca (e só quando a
   aresta calha a meio de um pixel — daí aparecer nuns ecrãs e noutros não).
   Com 2, o transbordo é de UM pixel inteiro por lado: qualquer pixel que a
   aresta atravesse cai dentro do filete de uma das metades e fica opaco.
   Medido em headless na travessia inteira (palco de 576 px e "Cheia", DPR 1,
   1.5 e 2, os quatro encaixes de subpixel, nos dois temas): 0,75 sem filete →
   0,94 com 1 → 0,996 com 2 (1 = costura tapada). A marca continua o mesmo
   desenho: a caixa passa de 321×161 para 322×162 num palco de 576 px (meio
   pixel de ecrã por lado, o que o filete de 1 já fazia) e a área cresce menos
   de 1%. */
.pulse-intro__logo path {
	stroke: currentColor;
	stroke-width: 2;
	stroke-linejoin: round;
	vector-effect: non-scaling-stroke;
}

/* Origem das transformações = centro do viewBox = onde o círculo se forma. */
.pulse-intro__logo g {
	transform-box: view-box;
	transform-origin: 50% 50%;
}

/* O círculo cheio só existe na janela da fusão (tapa a costura das metades). */
.pulse-intro__logo .pl-fill {
	opacity: 0;
}

/* ---- Keyframes — os valores EXATOS da 11 --------------------------------
   fora de cena → logótipo (0) → círculo (±50, com o batimento) → marca
   espelhada (±100) → sai pelo lado oposto. */
@keyframes pin-top {

	0% {
		transform: translateX(-180px);
	}

	21%,
	29% {
		transform: translateX(0);
	}

	46%,
	54% {
		transform: translateX(50px);
	}

	71%,
	79% {
		transform: translateX(100px);
	}

	100% {
		transform: translateX(280px);
	}
}

@keyframes pin-bot {

	0% {
		transform: translateX(180px);
	}

	21%,
	29% {
		transform: translateX(0);
	}

	46%,
	54% {
		transform: translateX(-50px);
	}

	71%,
	79% {
		transform: translateX(-100px);
	}

	100% {
		transform: translateX(-280px);
	}
}

@keyframes pin-fill {

	0%,
	45% {
		opacity: 0;
	}

	46%,
	54% {
		opacity: 1;
	}

	55%,
	100% {
		opacity: 0;
	}
}

/* O batimento cabe INTEIRO na janela 46–54% (círculo fechado e parado) — não
   rouba tempo ao percurso nem amplia a marca aberta (a nota da 11). */
@keyframes pin-beat {

	0%,
	46% {
		transform: scale(1);
	}

	49% {
		transform: scale(1.12);
	}

	51.5% {
		transform: scale(.97);
	}

	54%,
	100% {
		transform: scale(1);
	}
}

/* ---- Animação ligada (loop = a base) ------------------------------------ */
.pulse-intro .pl-top {
	animation: pin-top var(--pin-dur, 5250ms) cubic-bezier(.65, .05, .36, 1) infinite;
}

.pulse-intro .pl-bot {
	animation: pin-bot var(--pin-dur, 5250ms) cubic-bezier(.65, .05, .36, 1) infinite;
}

.pulse-intro .pl-fill {
	animation: pin-fill var(--pin-dur, 5250ms) linear infinite;
}

.pulse-intro .pl-rot {
	animation: pin-beat var(--pin-dur, 5250ms) ease-in-out infinite;
}

/* 'Uma vez ao carregar': a MESMA volta, 1 iteração, e fica no estado final
   (forwards) — a marca fez a sua travessia e saiu de cena. */
.pulse-intro--uma .pl-top,
.pulse-intro--uma .pl-bot,
.pulse-intro--uma .pl-fill,
.pulse-intro--uma .pl-rot {
	animation-iteration-count: 1;
	animation-fill-mode: forwards;
}

/* ---- 'Uma vez (fica no logótipo)' (v1.219) -------------------------------
   A 3ª escolha do pintro_comp: keyframes PRÓPRIOS pin-*-fica que percorrem SÓ
   o troço de entrada da travessia — fora de cena (±180) → logótipo formado
   (translateX 0) — e SEGURAM lá (21%→100% parados, 1 iteração + forwards).
   Os números e o easing são os da entrada original (0→21% de pin-top/pin-bot,
   sobre a MESMA --pin-dur): a chegada é visualmente igual à do loop/'uma', só
   o destino muda. O círculo (.pl-fill) NUNCA acende — sem fusão, o que fica é
   a marca aberta, o logótipo reconhecível (acendê-lo mostraria o disco por
   trás das metades paradas). O batimento dá-se UMA vez, à chegada:
   pin-beat-fica é a curva exata do pin-beat deslocada -25%, a caber na
   paragem 21–29% — a marca instala-se e bate, o gesto de "cheguei". Regras
   DEPOIS das do loop/'uma' e ANTES das do editor/movimento reduzido — mesma
   especificidade, a ordem decide (o contrato deste ficheiro); as classes
   antigas não são tocadas. */
@keyframes pin-top-fica {

	0% {
		transform: translateX(-180px);
	}

	21%,
	100% {
		transform: translateX(0);
	}
}

@keyframes pin-bot-fica {

	0% {
		transform: translateX(180px);
	}

	21%,
	100% {
		transform: translateX(0);
	}
}

@keyframes pin-beat-fica {

	0%,
	21% {
		transform: scale(1);
	}

	24% {
		transform: scale(1.12);
	}

	26.5% {
		transform: scale(.97);
	}

	29%,
	100% {
		transform: scale(1);
	}
}

.pulse-intro--uma-fica .pl-top {
	animation: pin-top-fica var(--pin-dur, 5250ms) cubic-bezier(.65, .05, .36, 1) 1 forwards;
}

.pulse-intro--uma-fica .pl-bot {
	animation: pin-bot-fica var(--pin-dur, 5250ms) cubic-bezier(.65, .05, .36, 1) 1 forwards;
}

/* A fusão nunca acontece neste modo: o círculo fica no opacity 0 da base. */
.pulse-intro--uma-fica .pl-fill {
	animation: none;
}

.pulse-intro--uma-fica .pl-rot {
	animation: pin-beat-fica var(--pin-dur, 5250ms) ease-in-out 1 forwards;
}

/* ---- Texto ---------------------------------------------------------------
   O elemento é um .pulse-sec__heading (tipografia/cor/aparência da casa);
   aqui só se anula a margem própria dele — o respiro é o gap do flex — e se
   centra por omissão (é uma frase de abertura junto a um palco centrado). */
.pulse-intro .pulse-intro__texto {
	margin: 0 auto;
	text-align: center;
	text-wrap: balance;
}

@keyframes pin-txt-aparecer {

	from {
		opacity: 0;
	}

	to {
		opacity: 1;
	}
}

@keyframes pin-txt-subir {

	from {
		opacity: 0;
		transform: translateY(1.2rem);
	}

	to {
		opacity: 1;
		transform: none;
	}
}

@keyframes pin-txt-escala {

	from {
		opacity: 0;
		transform: scale(.92);
	}

	to {
		opacity: 1;
		transform: none;
	}
}

/* Entrada com um pequeno atraso (o olho apanha primeiro a marca a entrar);
   'both' segura o from durante o delay e o to no fim.
   v1.233: a duração multiplica por --pin-txt-vel (a "Velocidade da animação do
   texto") — sem a var, calc(.9s × 1) = os .9s de sempre, computado igual. O
   atraso de .25s fica FIXO de propósito: é o compasso "primeiro a marca,
   depois a frase", não faz parte do ritmo da própria animação. */
.pulse-intro--txt-aparecer .pulse-intro__texto {
	animation: pin-txt-aparecer calc(.9s * var(--pin-txt-vel, 1)) var(--ease, ease) .25s both;
}

.pulse-intro--txt-subir .pulse-intro__texto {
	animation: pin-txt-subir calc(.9s * var(--pin-txt-vel, 1)) cubic-bezier(.65, .05, .36, 1) .25s both;
}

.pulse-intro--txt-escala .pulse-intro__texto {
	animation: pin-txt-escala calc(.9s * var(--pin-txt-vel, 1)) cubic-bezier(.65, .05, .36, 1) .25s both;
}

/* ---- 'Pulsação' (v1.216) -------------------------------------------------
   Não é uma ENTRADA: o texto respira (escala + opacidade) em CONTÍNUO
   enquanto está visível — a companhia do batimento da marca, pensada para o
   ecrã de carregamento mas disponível também no bloco. A base fica opacity:1
   (0% e 100% do keyframe) — sem CSS-anim o texto está sempre visível, como
   as entradas. Fica ANTES das regras do editor e do movimento reduzido
   (mesma especificidade — elas ganham por ordem, o contrato deste ficheiro). */
@keyframes pin-txt-pulsar {

	0%,
	100% {
		opacity: 1;
		transform: scale(1);
	}

	50% {
		opacity: .8;
		transform: scale(1.045);
	}
}

.pulse-intro--txt-pulsar .pulse-intro__texto {
	/* v1.232: nº de pulsações via --pin-pulsos (o render põe-no inline no
	   .pulse-intro; herda para o __texto). Por definir → infinite (pulsa sempre);
	   um número faz N pulsações e pára na frase quieta (0%/100% do keyframe).
	   v1.233: a duração multiplica por --pin-txt-vel — a "Velocidade da animação
	   do texto" (lenta 1.5 / rápida .6, posta inline pelo render). Sem a var o
	   calc devolve os 2400 ms EXATOS de sempre (× 1): o 'pulsar' gravado não
	   muda um milissegundo. */
	animation: pin-txt-pulsar calc(var(--pin-pulso, 2400ms) * var(--pin-txt-vel, 1)) ease-in-out var(--pin-pulsos, infinite);
}

/* ---- 'Pulsação (bate)' (v1.233) ------------------------------------------
   O par a sério da 'Respiração' acima (o value antigo 'pulsar' fica INTACTO —
   só o rótulo mudou no painel): em vez do vaivém simétrico do respirar, um
   BATIMENTO cardíaco — golpe rápido (0→6%: a escala dispara a 1.16), recuo
   elástico abaixo do repouso (12%), segundo golpe mais curto (20%, o "dub" do
   lub-dub) e o resto do ciclo em REPOUSO (30→100%) — é a pausa longa que faz
   ler-se como pulso e não como tremor. A opacidade fica a 1 no repouso (o
   contrato das entradas: sem CSS-anim o texto está sempre visível); a força é
   toda da escala. Partilha as vars da 'Respiração': --pin-pulsos (nº de
   pulsações, v1.232) e --pin-txt-vel (velocidade) valem para as duas. Regras
   ANTES do editor e do movimento reduzido — mesma especificidade, elas ganham
   por ordem (o contrato deste ficheiro). */
@keyframes pin-txt-pulso {

	0%,
	30%,
	100% {
		opacity: 1;
		transform: scale(1);
	}

	6% {
		transform: scale(1.16);
	}

	12% {
		transform: scale(.985);
	}

	20% {
		transform: scale(1.09);
	}
}

.pulse-intro--txt-pulso .pulse-intro__texto {
	/* A curva arranca depressa e assenta suave (fast-out): cada troço do
	   keyframe é um golpe seco, não o embalo ease-in-out da Respiração. */
	animation: pin-txt-pulso calc(var(--pin-pulso, 2400ms) * var(--pin-txt-vel, 1)) cubic-bezier(.2, .7, .3, 1) var(--pin-pulsos, infinite);
}

/* ---- 'Dividido' (só com o intro.js montado: .is-split) -------------------
   As unidades (.pin-u — palavras, letras ou linhas, conforme o data-div)
   entram escalonadas: delay = passo × índice (--pin-i, posto pelo JS). As
   palavras são inline-block para nunca partirem a meio e para o transform
   valer. SEM .is-split não há regra nenhuma → o texto é texto normal. */
@keyframes pin-u-in {

	from {
		opacity: 0;
		transform: translateY(.55em);
	}

	to {
		opacity: 1;
		transform: none;
	}
}

.pulse-intro--txt-dividido.is-split .pin-w {
	display: inline-block;
}

.pulse-intro--txt-dividido.is-split .pin-u {
	/* v1.233: a velocidade também aqui — o ritmo do 'dividido' é o compasso do
	   stagger, por isso --pin-txt-vel multiplica a duração de cada unidade E o
	   passo entre elas (o compasso inteiro abranda/acelera junto). Os 120 ms de
	   arranque ficam fixos (o "primeiro a marca" das entradas). Sem a var,
	   × 1 = os valores de sempre. */
	opacity: 0;
	animation: pin-u-in calc(.7s * var(--pin-txt-vel, 1)) cubic-bezier(.65, .05, .36, 1) forwards;
	animation-delay: calc(var(--pin-passo, 90ms) * var(--pin-txt-vel, 1) * var(--pin-i, 0) + 120ms);
}

/* O passo do stagger por unidade: letras mais curto, linhas mais longo. */
.pulse-intro--div-letras {
	--pin-passo: 32ms;
}

.pulse-intro--div-linhas {
	--pin-passo: 160ms;
}

/* Texto de leitor de ecrã (o JS injeta a frase inteira antes do split — os
   spans repartidos ficam aria-hidden e leem-se de uma vez, não às letras). */
.pulse-intro .pin-sr {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* ---- Editor (.pulse-intro--editor) ---------------------------------------
   A máquina não corre: congela na formação do logótipo (transform 0 = a
   janela 21–29%) e o texto fica visível, quieto. Estas regras vêm DEPOIS
   das de animação de propósito — mesma especificidade, ganham por ordem. */
.pulse-intro--editor .pl-top,
.pulse-intro--editor .pl-bot,
.pulse-intro--editor .pl-fill,
.pulse-intro--editor .pl-rot {
	animation: none;
}

.pulse-intro--editor .pulse-intro__texto {
	animation: none;
}

/* ---- Movimento reduzido --------------------------------------------------
   Nada atravessa: fica o círculo cheio, estático (a mesma leitura da
   Galeria), e o texto aparece logo — as regras têm a mesma especificidade
   das de animação e vêm depois (ganham por ordem, sem !important). */
@media (prefers-reduced-motion: reduce) {

	.pulse-intro .pl-top,
	.pulse-intro .pl-bot {
		display: none;
		animation: none;
	}

	.pulse-intro .pl-fill {
		opacity: 1;
		animation: none;
	}

	.pulse-intro .pl-rot {
		animation: none;
	}

	/* v1.219: no 'fica no logótipo' o destino É a marca formada — é isso que
	   se mostra, estática: as metades visíveis no lugar (sem animação o
	   transform é none = a posição do logótipo) e o círculo apagado. Mesma
	   especificidade das regras gerais acima — ganham por vir depois. */
	.pulse-intro--uma-fica .pl-top,
	.pulse-intro--uma-fica .pl-bot {
		display: inline;
		animation: none;
	}

	.pulse-intro--uma-fica .pl-fill {
		opacity: 0;
	}

	.pulse-intro .pulse-intro__texto {
		animation: none;
	}

	.pulse-intro--txt-dividido.is-split .pin-u {
		opacity: 1;
		animation: none;
	}
}

/* ---- Ecrã de carregamento (v1.216) ---------------------------------------
   O overlay do ecra-carregamento.php. A EXISTÊNCIA dele (display/posição/
   fundo/tokens --head/--ease e a trava de scroll) vive no CSS CRÍTICO inline
   no <head> — tem de estar pintada antes de qualquer folha externa. Aqui fica
   só o resto: a medida do palco fora de .pulse-sec, a tipografia da frase (no
   overlay ela não é um .pulse-sec__heading — não herda o builder) e o fade de
   saída. O interior é um .pulse-intro normal: animação, entradas de texto,
   pulsação e 'dividido' são as regras acima, sem duplicar nada. */
/* A SAÍDA (v1.223) — um gesto só, não um apagar de luz.
   Quando o ecrã se dispensa, o ecra-carregamento.js pega na travessia onde ela
   estiver e leva o logótipo até ao fora-de-cena dos keyframes (±280) — e o
   overlay esvai-se ao MESMO tempo e na MESMA curva. Daí as duas vars:
     · --ecra-saida — a duração, posta pelo JS conforme o caminho que ainda
       falta à marca (perto da borda é curta, do meio do palco é mais demorada:
       o gesto tem sempre a mesma velocidade, seja onde for apanhado) e, desde
       a v1.224, já MULTIPLICADA pela "Velocidade da saída" das Definições do
       Tema — o CSS não muda nada por causa disso: continua a obedecer à var,
       e o valor de recurso (450ms/300ms) é o de sempre para o caso impossível
       de ela não chegar;
     · --ecra-curva — a curva, que mora AQUI e é o JS que a lê daqui para a
       copiar para as peças do SVG. Uma só curva = as duas coisas movem-se em
       trave: quando a marca vai a três quartos do caminho, o ecrã vai a três
       quartos do esbatimento.
   A curva escolhida arranca já em andamento (a tangente inicial não é zero — a
   marca pode ser apanhada a meio da travessia e não pode estacar), faz três
   quartos do percurso na primeira metade do tempo e assenta devagar: é essa
   cauda longa que faz o site APARECER em vez de acender de repente. */
.pulse-ecra {
	--ecra-curva: cubic-bezier(.4, .1, .3, 1);
	opacity: 1;
	transition: opacity var(--ecra-saida, 450ms) var(--ecra-curva);
}

/* A dispensa (ecra-carregamento.js): esbatimento e rato liberto no 1.º frame.
   O display REPETE-SE aqui de propósito — mal a saída começa, o <html> perde a
   classe pendente (tem de perder: é ela que segura o pano opaco por cima do
   site e a trava de scroll), e com ela ia-se embora o display:grid do CSS
   crítico; sem isto o overlay saltava para display:none e não havia
   esbatimento nenhum. A classe dobrada põe a regra acima do
   '.pulse-ecra{display:none}' crítico por ESPECIFICIDADE, não pela ordem das
   folhas — assim a saída resiste a quem reordene o <head>. */
.pulse-ecra.pulse-ecra--sair {
	display: grid;
	opacity: 0;
	pointer-events: none;
}

.pulse-ecra .pulse-intro {
	width: min(92vw, 44rem);
}

/* v1.315: a «Grande» do ecrã de carregamento chega aos 52rem do bloco Intro
   (achado do preview-ecra-carregamento.html: o teto de 44rem acima deixava-a em
   704px — o comentário da v1.222 já o notava). Mesma especificidade, depois. */
.pulse-ecra .pulse-intro--tam-gra {
	width: min(92vw, 52rem);
}

/* v1.222 — "Cheia": a animação ocupa a largura do ecrã.
   O que a segurava era o teto de 44rem da regra acima (por isso nem a
   "Grande", de 52rem, chegava a crescer aqui). Solta-se com máximos que
   garantem o resto do contrato:
     · 96% (do overlay, que é fixed inset:0) e NÃO 100vw — o vw conta a barra
       de deslocamento e criaria overflow horizontal; a percentagem não;
     · 120rem trava em monitores enormes (a pista deixaria de se ler);
     · 210vh porque a pista é 3:1 — a altura fica em ~70vh no máximo, sobrando
       sempre ecrã para a frase, mesmo numa janela baixa e larga.
   Continua centrada pelo place-items do overlay + o margin-inline do palco.
   Só o ecrã de carregamento tem esta escolha — o bloco Intro não a conhece. */
.pulse-ecra--cheio .pulse-intro {
	--pin-w: 120rem;
	width: min(96%, 120rem, 210vh);
}

/* v1.222: os dois multiplicadores da frase (Definições do Tema → Global →
   Ecrã de carregamento). As vars chegam no CSS crítico, no .pulse-ecra; sem
   elas o calc devolve a base EXATA (× 1) — o aspeto de sempre, sem regra
   condicional nenhuma. Cor/peso/espaço/maiúsculas/alinhamento vêm de lá
   também, mas como declarações próprias por #pulse-ecra (só quando escolhidas
   — daí o id: este ficheiro carrega depois do <style> crítico). */
.pulse-ecra .pulse-intro__texto {
	color: var(--head, #fff);
	font-size: calc(clamp(1.05rem, .9rem + .8vw, 1.5rem) * var(--ecra-tit-e, 1));
	line-height: calc(1.4 * var(--ecra-tit-lh, 1));
}

/* Movimento reduzido (v1.223): a saída continua SUAVE — mas é só isso. Um
   esbatimento não é movimento: aqui não há travessia nenhuma a acompanhar (as
   metades do logótipo estão display:none e o disco está quieto), por isso não
   se copia o gesto — fica um fade curto e linear, sem aceleração nenhuma. A
   duração chega na mesma do JS (--ecra-saida), que nunca espera por uma
   animação que não corre. */
@media (prefers-reduced-motion: reduce) {

	.pulse-ecra {
		transition: opacity var(--ecra-saida, 300ms) linear;
	}
}