/* =========================================================
   Cajo Vertical Slider
   -----------------------------------------------------------
   A instância injecta os tokens (--cajo-vs-*) no atributo style
   do wrapper. Aqui ficam só os valores por omissão e a mecânica.

   Estrutura:
     .cajo-vs            wrapper, dono dos tokens
       .cajo-vs__pista   dá a altura de scroll (100vh + n * passo)
         .cajo-vs__ecra  sticky, ocupa o ecrã
           .cajo-vs__stack
             .cajo-vs__card × n
   ========================================================= */

.cajo-vs {
	--cajo-vs-total: 1;
	--cajo-vs-passo: 90vh;
	--cajo-vs-fechado: clamp(58px, 8vh, 96px);
	--cajo-vs-aberto: clamp(240px, 50vh, 600px);
	--cajo-vs-recuo: 34px;
	--cajo-vs-sobrepor: 6px;
	--cajo-vs-raio: 14px;
	--cajo-vs-largura-max: 1200px;
	--cajo-vs-padding-lateral: 5vw;
	--cajo-vs-texto: #fff;
	--cajo-vs-veu: 0.35;
	--cajo-vs-brilho-fechado: 0.55;
	--cajo-vs-tam-titulo: clamp(28px, 3.2vw, 52px);
	--cajo-vs-tam-titulo-card: clamp(18px, 1.9vw, 30px);
	--cajo-vs-tam-numero: clamp(24px, 3vw, 46px);
	--cajo-vs-tam-texto: 15px;
	--cajo-vs-topo: 0px;
	--cajo-vs-espaco-titulo: clamp(20px, 4vh, 56px);
	/* Ar que o card aberto ganha por cima do título, para o título não ficar
	   colado ao rebordo. Só se aplica ao card aberto — ver mais abaixo. */
	--cajo-vs-respiro-titulo: 30px;
	/* Tipo de letra do número. Fica separado do resto porque na República
	   os números são em serifa e os títulos não. */
	--cajo-vs-fonte-numero: "Maitree Regular", "Maitree", Georgia, serif;
	/* Quanto a imagem desliza dentro do card, em percentagem da própria
	   imagem. Subir isto obriga a subir também o scale lá em baixo, senão
	   aparece a aba vazia do lado para onde ela desliza. */
	--cajo-vs-parallax: 9%;
	/* Abertura (--a) a partir da qual o texto do painel começa a aparecer, e
	   abaixo da qual já desapareceu por completo.

	   Chegou a mandar também no ponto de não retorno do avanço automático, mas
	   já não: ficava longe de mais para um gesto de roda lá chegar em movimento
	   e o resultado era uma pausa antes de cada troca. Hoje o JS decide isso por
	   distância de scroll — ver medir() em cajo-vs.js. Aqui é só opacidade. */
	--cajo-vs-fim-texto: 0.45;
	--cajo-vs-tempo: 0.55s;
	--cajo-vs-curva: cubic-bezier(0.4, 0, 0.15, 1);
	/* Nunca deixar um card ficar mais estreito do que isto, mesmo com 10 slides. */
	--cajo-vs-largura-min: 42%;

	position: relative;
	color: var(--cajo-vs-texto);
}

.cajo-vs--tem-fundo {
	background: var(--cajo-vs-fundo);
}

/* Largura total do ecrã, a sair da coluna do WPBakery.
   Mesma técnica que o style.css do tema já usa na faixa verde do rodapé.
   Os 100vw contam com a barra de scroll, o que daria scroll horizontal — quem
   trata disso é o libertarSticky() do JS, que põe overflow-x:clip nos
   antepassados e no <body>. */
.cajo-vs--total {
	left: 50%;
	width: 100vw;
	max-width: 100vw;
	margin-left: -50vw;
	margin-right: -50vw;
}

/* ---------------------------------------------------------
   Pista e ecrã
   --------------------------------------------------------- */

.cajo-vs__pista {
	/* Um "passo" de scroll por card: o último fica com um passo inteiro
	   de leitura antes de a secção se soltar. */
	height: calc(100vh + var(--cajo-vs-total) * var(--cajo-vs-passo));
}

.cajo-vs__ecra {
	position: sticky;
	/* --cajo-vs-topo desconta o header fixo: sem isto o título da secção fica
	   por baixo dele enquanto a secção está presa. */
	top: var(--cajo-vs-topo, 0px);
	height: calc(100vh - var(--cajo-vs-topo, 0px));
	height: calc(100svh - var(--cajo-vs-topo, 0px));
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
}

.cajo-vs__interior {
	width: 100%;
	max-width: var(--cajo-vs-largura-max);
	margin: 0 auto;
	padding: 0 var(--cajo-vs-padding-lateral);
	box-sizing: border-box;
}

/* O selector leva três classes de propósito.

   O Salient tem ".row .col h3, .row .col h4 { margin-bottom: 8px }", que é
   (0,2,1). Um simples ".cajo-vs__titulo" (0,1,0) perdia, e o espaço entre o
   título e o baralho ficava sempre nos 8px do tema por muito que se mexesse na
   opção — parecia que a opção não funcionava. Três classes dão (0,3,0), que
   ganha por número de classes sem ser preciso !important nem prender-se ao id
   da instância. */
.cajo-vs .cajo-vs__interior .cajo-vs__titulo {
	margin: 0 0 var(--cajo-vs-espaco-titulo);
	text-align: center;
	color: inherit;
	font-size: var(--cajo-vs-tam-titulo);
	line-height: 1.15;
}

/* ---------------------------------------------------------
   Baralho
   --------------------------------------------------------- */

.cajo-vs__stack {
	display: flex;
	flex-direction: column;
	align-items: center;
}

.cajo-vs__card {
	--d: 0;
	/* Quanto este card está aberto, de 0 a 1. Em modo fluido é o JS que o
	   escreve ao frame; fora dele fica em 0 e manda a classe .is-active. */
	--a: 0;
	/* O mesmo que o --d mas com sinal: negativo se o card já passou, positivo
	   se ainda está para vir. É só isto que dá a direcção ao parallax. */
	--sd: 0;

	/* Coluna flex para o painel poder ser encostado ao fundo com margin-top:auto
	   (ver .cajo-vs--texto-baixo). A media e o véu são absolutos, ficam fora do
	   fluxo e não entram na conta. */
	display: flex;
	flex-direction: column;
	position: relative;
	z-index: calc(var(--i) + 1);
	box-sizing: border-box;
	/* O leque: quanto mais longe do card aberto, mais estreito. */
	width: max(
		var(--cajo-vs-largura-min),
		calc(100% - 2 * var(--d) * var(--cajo-vs-recuo))
	);
	height: var(--cajo-vs-fechado);
	border-radius: var(--cajo-vs-raio);
	overflow: hidden;
	isolation: isolate;
	transition:
		width var(--cajo-vs-tempo) var(--cajo-vs-curva),
		height var(--cajo-vs-tempo) var(--cajo-vs-curva);
}

.cajo-vs__card + .cajo-vs__card {
	margin-top: calc(-1 * var(--cajo-vs-sobrepor));
}

.cajo-vs__card.is-active {
	z-index: calc(var(--cajo-vs-total) + 2);
	height: var(--cajo-vs-aberto);
	box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
}

/* ---------------------------------------------------------
   Modo fluido — a abertura segue o scroll

   Antes: o JS trocava a classe .is-active e o CSS fazia a transição de uma
   vez, sempre com a mesma duração, independentemente de se estar a rolar
   depressa ou devagar. O movimento não tinha nada a ver com o dedo.

   Agora: o JS escreve em cada card o quanto está aberto (--a) e a que
   distância está do foco (--d, --sd), e é o CSS que interpola. Rolar devagar
   abre devagar; parar a meio deixa o card a meio.

   A altura total do baralho não muda ao longo do percurso: a curva usada no
   JS faz com que dois cards a meio somem o mesmo que um card sozinho no
   máximo. Sem isso, animar altura ao frame punha a página a tremer.

   Tudo o que não é altura ou largura é transform e filter, que o browser
   resolve sem voltar a fazer o layout.
   --------------------------------------------------------- */

.cajo-vs--fluido .cajo-vs__card,
.cajo-vs--fluido .cajo-vs__card.is-active {
	height: calc(
		var(--cajo-vs-fechado) +
		(var(--cajo-vs-aberto) - var(--cajo-vs-fechado)) * var(--a)
	);
	/* O leque também deixa de ser aos degraus. */
	width: max(
		var(--cajo-vs-largura-min),
		calc(100% - 2 * var(--d) * var(--cajo-vs-recuo))
	);
	/* A sombra só aparece quando o card já está quase aberto. */
	box-shadow: 0 24px 60px rgba(0, 0, 0, calc(0.35 * var(--a)));
	/* Quem manda é o scroll. Uma transição por cima disto só atrasava o
	   desenho e dava a sensação de o card ir atrás do rato. */
	transition: none;
}

/* O respiro por cima do título também tem de ser contínuo.

   A regra lá em baixo dá esse respiro ao card com .is-active, e o .is-active
   muda de card de um frame para o outro, a meio do percurso. Resultado: no
   ponto médio de cada transição o título do card que entra caía 30px de uma vez
   e o do que sai subia outros 30 — dois safanões no meio de um movimento que é
   suposto ser contínuo. Estava a acontecer em todas as trocas.

   Aqui o respiro cresce com a abertura, por isso nas pontas dá exactamente o
   mesmo que dava antes e pelo meio não há degrau nenhum. Os quatro níveis de
   classe são para ganhar à regra do .is-active, que tem três. */
.cajo-vs--fluido .cajo-vs__card .cajo-vs__cabecalho,
.cajo-vs--fluido .cajo-vs__card.is-active .cajo-vs__cabecalho {
	height: calc(
		var(--cajo-vs-fechado) +
		var(--cajo-vs-respiro-titulo) * var(--a)
	);
	transition: none;
}

/* Brilho contínuo, do valor dos fechados até 1 no aberto. */
.cajo-vs--fluido .cajo-vs__media {
	filter: brightness(
		calc(
			var(--cajo-vs-brilho-fechado) +
			(1 - var(--cajo-vs-brilho-fechado)) * var(--a)
		)
	);
	transition: none;
}

/* O parallax propriamente dito: a imagem desliza ao contrário do card, por
   isso parece estar mais longe.

   O deslocamento é em percentagem da própria imagem e não em pixéis, para
   ser proporcional ao tamanho do card — num card fechado de 60px, 40px de
   deslocamento seria a imagem inteira a saltar.

   O scale existe para haver imagem de sobra a entrar no enquadramento. Tem de
   ser maior do que o dobro do deslocamento, senão aparece a aba vazia. */
.cajo-vs--fluido .cajo-vs__img,
.cajo-vs--fluido .cajo-vs__media > img {
	transform: translate3d(0, calc(var(--sd) * var(--cajo-vs-parallax)), 0) scale(1.22);
	will-change: transform;
}

/* O texto acompanha a abertura em vez de ligar e desligar de golpe.

   Duas coisas o faziam aparecer e desaparecer em bloco, e eram precisas as
   duas para o resolver:

   1. A regra ".cajo-vs__card.is-active .cajo-vs__painel" tem três classes e
      ganhava a uma regra minha com duas. O opacity:1 dela passava à frente do
      cálculo, por isso o texto só conhecia dois estados. É por isso que este
      selector repete o .is-active — para ficar acima e não abaixo.

   2. A visibilidade estava presa ao .is-active, que muda de card de um frame
      para o outro. Mesmo com a opacidade certa, o texto do card anterior
      desaparecia de repente. Em modo fluido a visibilidade é sempre visible e
      quem manda é só a opacidade.

   A rampa começa no --cajo-vs-fim-texto (0,45): na troca entre dois cards ambos os
   textos ficam a 10%, o suficiente para não haver dois parágrafos legíveis ao
   mesmo tempo. Medido ao longo da pista: 100, 96, 75, 44, 10, 10, 44, 75, 96,
   100. Antes era 100 e logo a seguir 0.

   O pointer-events evita que o texto quase transparente de um card fechado
   apanhe cliques que eram para o card de cima. */
.cajo-vs--fluido .cajo-vs__card .cajo-vs__painel,
.cajo-vs--fluido .cajo-vs__card.is-active .cajo-vs__painel {
	visibility: visible;
	opacity: clamp(0, calc((var(--a) - var(--cajo-vs-fim-texto)) * 1.9), 1);
	transform: translateY(calc((1 - var(--a)) * 12px));
	transition: none;
	transition-delay: 0s;
	pointer-events: none;
}

.cajo-vs--fluido .cajo-vs__card.is-active .cajo-vs__painel {
	pointer-events: auto;
}

/* Media ---------------------------------------------------- */

.cajo-vs__media,
.cajo-vs__veu {
	position: absolute;
	inset: 0;
	z-index: -1;
}

.cajo-vs__media {
	filter: brightness(var(--cajo-vs-brilho-fechado));
	transition: filter var(--cajo-vs-tempo) var(--cajo-vs-curva);
}

.cajo-vs__card.is-active .cajo-vs__media {
	filter: brightness(1);
}

/* O !important aqui não é preguiça.
   O Salient tem regras de imagem com muita especificidade (".row .col img",
   "#ajax-content-wrap … img", height:auto) que ganhavam a um simples
   ".cajo-vs__img{height:100%}". Resultado: a <img> ficava com a altura do seu
   rácio (256px) dentro de um card de 371px e sobrava fundo por baixo — parecia
   espaço a mais entre o card aberto e o seguinte, mas era buraco lá dentro.
   O position:absolute + inset:0 é o cinto; o height:100% é os suspensórios. */
.cajo-vs__img,
.cajo-vs .cajo-vs__img,
.cajo-vs__media > img {
	position: absolute !important;
	inset: 0 !important;
	width: 100% !important;
	height: 100% !important;
	max-width: none !important;
	max-height: none !important;
	min-width: 0 !important;
	min-height: 0 !important;
	margin: 0 !important;
	padding: 0 !important;
	object-fit: cover !important;
	object-position: center !important;
	display: block !important;
	border-radius: 0 !important;
}

.cajo-vs__veu {
	background: rgba(0, 0, 0, var(--cajo-vs-veu));
	pointer-events: none;
}

/* Cabeçalho ------------------------------------------------ */

.cajo-vs__cabecalho {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	flex: 0 0 auto;
	width: 100%;
	height: var(--cajo-vs-fechado);
	padding: 0 clamp(18px, 3%, 44px);
	box-sizing: border-box;
	margin: 0;
	background: none;
	border: 0;
	border-radius: 0;
	color: inherit;
	font: inherit;
	text-align: left;
	cursor: pointer;
	-webkit-appearance: none;
	appearance: none;
}

.cajo-vs__cabecalho:hover,
.cajo-vs__cabecalho:focus {
	background: none;
	color: inherit;
}

.cajo-vs__cabecalho:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: -4px;
}

.cajo-vs__card-titulo {
	font-size: var(--cajo-vs-tam-titulo-card);
	line-height: 1.2;
	font-weight: 400;
}

.cajo-vs__num {
	flex: 0 0 auto;
	font-family: var(--cajo-vs-fonte-numero);
	font-size: var(--cajo-vs-tam-numero);
	line-height: 1;
	/* 400 e não 300: a Maitree só tem Regular carregada no site, e um peso
	   que não existe obriga o browser a inventar um falso-light. */
	font-weight: 400;
	opacity: 0.9;
	font-variant-numeric: tabular-nums;
}

/* O card aberto respira mais por cima.

   O cabeçalho tem a altura do card fechado e o conteúdo ao centro, o que
   chega enquanto o card está fechado. Aberto, esses mesmos pixéis passam a
   ser a faixa de cima de um card muito maior e o título ficava encostado ao
   rebordo.

   A altura cresce em vez de se acrescentar padding porque o conteúdo está
   centrado: assim o título e o número descem juntos e continuam com o mesmo
   centro óptico. Com padding-top, e sendo o número mais alto do que o
   título, deixavam de estar alinhados um com o outro. */
.cajo-vs__card.is-active .cajo-vs__cabecalho {
	height: calc(var(--cajo-vs-fechado) + var(--cajo-vs-respiro-titulo));
}

/* Painel --------------------------------------------------- */

.cajo-vs__painel {
	/* O último valor é a folga por baixo do texto. Estava em 3vh e o texto
	   ficava a 25px do rebordo do card — encostado. 5.5vh dá cerca de 49px
	   num ecrã de portátil, que é o mesmo ar que o texto tem de lado. */
	padding: 0 clamp(18px, 3%, 44px) clamp(28px, 5.5vh, 64px);
	flex: 0 0 auto;
	max-width: 46ch;
	opacity: 0;
	visibility: hidden;
	transform: translateY(12px);
	transition:
		opacity var(--cajo-vs-tempo) var(--cajo-vs-curva),
		transform var(--cajo-vs-tempo) var(--cajo-vs-curva),
		visibility 0s linear var(--cajo-vs-tempo);
}

.cajo-vs__card.is-active .cajo-vs__painel {
	opacity: 1;
	visibility: visible;
	transform: none;
	transition-delay: 0.12s, 0.12s, 0s;
}

/* Texto encostado ao fundo do card em vez de logo a seguir ao título.
   Em mobile o card tem altura automática, não sobra espaço nenhum e o
   margin-top:auto não faz nada — que é o que se quer num acordeão. */
.cajo-vs--texto-baixo .cajo-vs__painel {
	margin-top: auto;
}

.cajo-vs__texto {
	font-size: var(--cajo-vs-tam-texto);
	line-height: 1.55;
}

.cajo-vs__texto p {
	margin: 0 0 0.7em;
	color: inherit;
	font-size: inherit;
	line-height: inherit;
}

.cajo-vs__texto p:last-child {
	margin-bottom: 0;
}

.cajo-vs__link {
	display: inline-block;
	margin-top: 1em;
	color: inherit;
	font-size: var(--cajo-vs-tam-texto);
	text-decoration: underline;
	text-underline-offset: 0.25em;
}

.cajo-vs__link:hover {
	color: inherit;
	opacity: 0.75;
}

/* ---------------------------------------------------------
   Editor: sem scroll de página não há efeito nenhum, por isso
   mostramos o baralho todo aberto para se ver o conteúdo.
   --------------------------------------------------------- */

.cajo-vs--edicao .cajo-vs__pista {
	height: auto;
}

.cajo-vs--edicao .cajo-vs__ecra {
	position: static;
	height: auto;
	overflow: visible;
	padding: 40px 0;
}

/* Sem isto os cards ficavam todos fechados e o auto-ajuste do JS, ao ver que
   o ecrã já não tinha 100vh, encolhia-os até ao mínimo. Dava uma pilha de
   barras de 34px e a sensação de que o elemento estava avariado. */
.cajo-vs--edicao .cajo-vs__card {
	width: 100%;
	height: auto;
	min-height: var(--cajo-vs-fechado);
}

.cajo-vs--edicao .cajo-vs__card + .cajo-vs__card {
	margin-top: 10px;
}

.cajo-vs--edicao .cajo-vs__painel {
	opacity: 1;
	visibility: visible;
	transform: none;
	max-width: none;
}

.cajo-vs--edicao .cajo-vs__media {
	filter: brightness(1);
}

.cajo-vs__aviso {
	padding: 24px;
	border: 1px dashed currentColor;
	border-radius: 8px;
	text-align: center;
	opacity: 0.7;
}

/* ---------------------------------------------------------
   Mobile
   -----------------------------------------------------------
   O JS põe .cajo-vs--mobile quando a largura está abaixo do
   ponto definido. Não usamos media query fixa porque o ponto
   é configurável no elemento.
   --------------------------------------------------------- */

.cajo-vs--mobile .cajo-vs__pista {
	height: auto;
}

.cajo-vs--mobile .cajo-vs__ecra {
	position: static;
	height: auto;
	overflow: visible;
	padding: clamp(32px, 8vw, 72px) 0;
}

.cajo-vs--mobile .cajo-vs__interior {
	padding: 0 var(--cajo-vs-padding-lateral-mobile, 6vw);
}

.cajo-vs--mobile .cajo-vs__card {
	/* Sem leque em mobile: não há largura para isso. */
	width: 100%;
	height: auto;
	min-height: var(--cajo-vs-fechado);
}

.cajo-vs--mobile .cajo-vs__card + .cajo-vs__card {
	margin-top: 10px;
}

.cajo-vs--mobile .cajo-vs__card.is-active {
	box-shadow: none;
}

.cajo-vs--mobile .cajo-vs__painel {
	display: none;
	max-width: none;
}

.cajo-vs--mobile .cajo-vs__card.is-active .cajo-vs__painel {
	display: block;
}

/* Modo "todos abertos": sem interacção nenhuma. */
.cajo-vs--mobile.cajo-vs--m-todos .cajo-vs__cabecalho {
	cursor: default;
}

.cajo-vs--mobile.cajo-vs--m-todos .cajo-vs__painel {
	display: block;
}

.cajo-vs--mobile.cajo-vs--m-todos .cajo-vs__media {
	filter: brightness(1);
}

/* ---------------------------------------------------------
   Acessibilidade
   --------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {

	.cajo-vs__card,
	.cajo-vs__media,
	.cajo-vs__painel {
		transition-duration: 0.001s !important;
		transition-delay: 0s !important;
	}
}

/* O fallback para quem não tem JS vive num <noscript> impresso pelo render —
   ver cajo_vs_noscript() em includes/render.php.

   Antes era uma classe posta no <html> por um script inline. Não servia: o
   Salient reescreve o className do <html> ("js js_active vc_desktop
   vc_transform page-trans-loaded") e apagava-a. O fallback ficava ligado para
   toda a gente, a pista perdia a altura, o sticky nunca acontecia e o scroll
   não fazia nada. Um <noscript> não depende de JS nenhum para estar certo. */
