/* bracis-figma/speakers — keynote speakers (mock Figma 481:415)
 *
 * Geometria 1:1 do mock: frame de 1920x3240, faixas de 520px. O circuito de cada
 * faixa é um SVG com viewBox 1920x520 e preserveAspectRatio="none": o desenho
 * acompanha a largura da tela, e como o retrato é posicionado no MESMO percentual
 * do viewBox (278/1920), o traço sempre morre no centro dele. A espessura fica
 * fora dessa deformação via vector-effect: non-scaling-stroke.
 */

.bracis-speakers {
	/* tokens do tema (theme.json / DESIGN.md) */
	--navy: var(--wp--preset--color--navy);              /* #313267 */
	--gold: var(--wp--preset--color--gold);              /* #E2C576 */
	--slate: var(--wp--preset--color--slate);            /* #5c5d7a */
	--fog: var(--wp--preset--color--fog);                /* #F0F2F2 */
	--cloud: var(--wp--preset--color--cloud);            /* #ffffff */

	--band-h: 520px;          /* altura da faixa no mock */
	/* Em px, não mais em % da faixa: o nó e a descida penduram nesta âncora, e
	   um alvo que anda com a largura da tela obrigaria a diagonal a distorcer
	   para alcançá-lo. O clamp reproduz os 14,479% do mock até ~2070px e para
	   de crescer daí em diante. */
	--portrait-cx: clamp(150px, 14.5vw, 300px);
	--portrait-cy: 280px;
	--panel-x: 25.52%;        /* 490/1920 — início da coluna de texto */
	--portrait: clamp(150px, 15.5vw, 220px);
	--node: clamp(52px, 4.5vw, 86px);
	--trace-w: clamp(11px, 1.15vw, 22px);
	/* Lado do cotovelo que desvia a corrida horizontal para a pista vertical. */
	--elbow: clamp(120px, 11vw, 240px);

	/* ---- Árvore ----
	   Ancorada na base da seção, à direita. Ela é ALTA demais para caber depois
	   da última faixa, e reservar espaço para a arte inteira deixava mais de mil
	   pixels de branco no fim da página. Em vez disso ela sobe por trás das
	   faixas — é fundo, e pode passar por baixo do conteúdo — e --tree-zone
	   reserva só o pedaço de baixo, onde estão o tronco e as entradas das
	   trilhas. O resto emerge esmaecido por --tree-fade.
	   --tree-h: altura da arte inteira. É o botão principal de escala.
	   --tree-w: 141/227 do viewBox do SVG — não mexer sem refazer a conta.
	   --tree-cut: quanto da arte fica para fora pela base.
	   --tree-zone: espaço vazio reservado no fim. Tem de cobrir a entrada mais
	     alta (--rail-y da última faixa), senão uma bolinha cai atrás de uma
	     faixa. Já não vale --tree-h menos o corte: isso é a altura da ARTE, não
	     o espaço que ela precisa.
	   --tree-fade: onde o degradê do topo fecha, em fração de --tree-h. Precisa
	     terminar ANTES do começo da zona, senão a árvore chega desbotada na
	     parte que importa. */
	--tree-h: clamp(1400px, 174vw, 3200px);
	--tree-w: calc(var(--tree-h) * .6212);
	--tree-cut: calc(var(--tree-h) * .34);
	--tree-zone: calc(var(--tree-h) * .23);
	--tree-fade: 32%;
	/* Perto da borda: a árvore fica À DIREITA e a metade direita da copa sai da
	   tela de propósito — é a direção fixada, e o que sobra na tela é a copa se
	   abrindo para a esquerda a partir do tronco. Empurrar o tronco para o meio
	   (o que caberia a copa inteira) tira a árvore do canto e obriga as trilhas
	   a cruzarem a copa na diagonal para alcançá-la. */
	--trunk-x: clamp(80px, 9vw, 200px);
	/* A arte é feita de trilhas finas: abaixo daqui ela começa a sumir, e as
	   cinco linhas passam a convergir para um alvo que não se vê. */
	--tree-opacity: .25;

	/* ---- Silhueta do tronco ----
	   O tronco é um cone: na arte só existe abaixo de 38% da altura, e dali para
	   baixo a borda esquerda se afasta do eixo .0557px a cada px descido (medido
	   no SVG rasterizado, na faixa y=.37–.76, onde não há mais copa). As trilhas
	   entram por essa borda, e não pelo eixo: galho nasce da lateral do tronco.
	   --trunk-flare: a inclinação usada. Um pouco acima do valor real, porque 3°
	     exatos deixam as cinco entradas quase empilhadas na mesma vertical; .18
	     já era demais e jogava as bolinhas para fora do tronco, do lado errado.
	     .0557 devolve a borda exata.
	   --trunk-gap: folga entre a bolinha e a borda do tronco. Os ramos da própria
	     arte param a uma distância do tronco em vez de encostar nele; sem esta
	     folga as nossas bolinhas ficam grudadas e leem como emenda, não como
	     ramo. Não é o botão para separar as linhas umas das outras: isso se faz
	     na vertical, com --rail-step.
	   --trunk-vis: altura de tronco que sobra acima da base, onde as entradas
	     têm de caber. Sai da ARTE (o tronco começa a 38% do topo e a base perde
	     --tree-cut), não do tamanho da zona — são coisas independentes desde que
	     a árvore passou a subir por trás das faixas. */
	--trunk-flare: .07;
	--trunk-dx0: calc(var(--tree-w) * .0136);   /* meia-largura no alto do tronco */
	--trunk-gap: calc(var(--tree-w) * .04);
	--trunk-vis: calc(.62 * var(--tree-h) - var(--tree-cut));

	/* ---- Pistas ----
	   --rail-anchor: onde corre a pista mais interna (a da PRIMEIRA faixa, a mais
	     próxima do tronco). Todas as pistas correm à ESQUERDA do tronco e entram
	     nele virando para a direita, o que mantém os nós finais e o percurso do
	     lado de fora da copa em vez de atravessá-la. Tem de ser maior que o
	     maior --tap-x, senão o cotovelo de entrada aponta para o lado errado.
	   --rail-gap: distância entre uma pista e a seguinte. As cinco pistas somadas
	     empurram a mais externa contra a coluna de texto, então há teto aqui.
	   --rail-base / --rail-step: onde a primeira trilha entra no tronco e de
	     quanto em quanto as outras sobem — em fração do tronco visível, que é o
	     alvo real. */
	--rail-anchor: clamp(190px, 20vw, 400px);
	--rail-gap: clamp(28px, 2.4vw, 46px);
	/* --rail-step é o respiro VERTICAL entre uma linha e a seguinte: é ele que
	   impede as cinco diagonais de se lerem como um feixe único misturado às
	   trilhas do fundo. Custa altura: como é a entrada MAIS ALTA que fixa o
	   tamanho de --tree-zone, cada passo a mais empurra o rodapé para longe do
	   último palestrante. --rail-base foi encolhido para devolver parte disso,
	   baixando a primeira entrada em vez de subir a última. */
	--rail-base: calc(var(--trunk-vis) * .04);
	--rail-step: calc(var(--trunk-vis) * .17);

	margin: 0;
	color: var(--navy);
	background: var(--cloud);
}

/* Cada traço é desenhado por DUAS tecnologias: <div> nas retas longas, <svg> nos
   cotovelos. Em posição fracionária as duas não concordam — a borda da div
   encaixa no pixel, o stroke do SVG fica com meio pixel de antialias de cada
   lado — e a emenda vira um fio claro ao longo do rabo do cotovelo, que lê como
   uma segunda linha, mais grossa e mais curta, atrás da pista. Medido em
   Chromium e WebKit: o rabo pintava 1512,4–1534,4 e a pista 1513–1535.
   Arredondar as medidas que definem esse eixo põe as duas peças no mesmo pixel.
   --trace-w em passo de 2px porque o stroke é centrado, e metade dele tem de ser
   inteira; --elbow em 4px porque os rabos valem .25 dele. Não adianta corrigir
   pela vertical: nessa direção run e cotovelo já coincidem (medido).
   Atrás de @supports porque round() sem suporte invalidaria as variáveis, e uma
   variável vazia aqui não degrada — apaga o circuito inteiro. */
@supports (width: round(1px, 1px)) {
	.bracis-speakers {
		--trace-w: round(clamp(11px, 1.15vw, 22px), 2px);
		--elbow: round(clamp(120px, 11vw, 240px), 4px);
		--rail-anchor: round(clamp(190px, 20vw, 400px), 1px);
		--rail-gap: round(clamp(28px, 2.4vw, 46px), 1px);
	}
}

/* ---------- Hero ---------- */
.bracis-speakers__hero {
	background: var(--wp--preset--gradient--navy-depth);
	border-bottom: 6px solid var(--gold);
	padding: 4.5rem 0 4rem;
}
.bracis-speakers__hero-inner {
	max-width: 1584px;
	margin: 0 auto;
	padding: 0 clamp(1.25rem, 8.75vw, 168px);
}
.bracis-speakers__eyebrow-rule {
	display: block;
	width: 32px;
	height: 3px;
	border-radius: 999px;
	background: var(--gold);
	margin-bottom: 1.6rem;
}
.bracis-speakers__title {
	/* Bebas Neue vem de theme.json (elements.heading) */
	margin: 0;
	color: var(--cloud);
	font-size: var(--wp--preset--font-size--display);
	line-height: .9;
	letter-spacing: .02em;
	text-transform: uppercase;
}
/* ---------- Faixas + árvore ---------- */
/* Grid, e não empilhamento simples, porque é o que dá às pistas um começo e um
   fim: `grid-row: i / -1` faz a trilha nascer no topo da SUA faixa e morrer na
   base da árvore, sem ninguém precisar saber a altura das bios. O template de
   linhas vem inline do render.php (ver o porquê lá). */
.bracis-speakers__bands {
	position: relative;
	display: grid;
	grid-template-columns: 1fr;
	/* recorta a copa e as pistas que passam da borda; `clip` em vez de `hidden`
	   para não criar um scrollport à toa */
	overflow: clip;
	background: var(--cloud);
}

/* A árvore-circuito. O SVG de origem é todo branco, então ele entra como
   máscara e a cor vem do background — pintar por filtro não funcionaria sobre
   fundo claro.
   Fica ancorada na base da seção, com a linha de centro do tronco caindo
   exatamente em --trunk-x (por isso o deslocamento de .485 da largura: é a
   distância do tronco à borda DIREITA da arte). */
.bracis-speakers__tree {
	position: absolute;
	right: calc(var(--trunk-x) - .485 * var(--tree-w));
	bottom: calc(-1 * var(--tree-cut));
	width: var(--tree-w);
	height: var(--tree-h);
	/* Acima do fundo das faixas que atravessa, abaixo do conteúdo delas (que
	   sobe para z-index 2). É o que deixa a árvore emergir por trás das últimas
	   faixas em vez de precisar de espaço vazio só seu. */
	z-index: 1;
	background-color: var(--navy);
	-webkit-mask: url(../../images/arvore-colorida.svg) no-repeat center / 100% 100%;
	mask: url(../../images/arvore-colorida.svg) no-repeat center / 100% 100%;
	opacity: var(--tree-opacity);
	pointer-events: none;
}
/* Sobrepõe à silhueta um degradê que apaga a árvore em direção ao topo, senão o
   trecho que invade as faixas termina num corte reto na borda da faixa, que lê
   como erro de recorte. Atrás do @supports porque as duas camadas dependem de
   `intersect`: sem ele o padrão é somar, e a máscara vira um retângulo — pior
   que não ter degradê nenhum. */
@supports (mask-composite: intersect) {
	.bracis-speakers__tree {
		-webkit-mask-image: url(../../images/arvore-colorida.svg), linear-gradient(to bottom, transparent, #000 var(--tree-fade));
		mask-image: url(../../images/arvore-colorida.svg), linear-gradient(to bottom, transparent, #000 var(--tree-fade));
		-webkit-mask-size: 100% 100%, 100% 100%;
		mask-size: 100% 100%, 100% 100%;
		-webkit-mask-repeat: no-repeat, no-repeat;
		mask-repeat: no-repeat, no-repeat;
		mask-composite: intersect;
	}
}

.bracis-speaker {
	position: relative;
	grid-column: 1;
	min-height: var(--band-h);
	background: var(--cloud);
}
.bracis-speaker:nth-child(odd) {  /* :nth-child conta a árvore, então ímpar = faixa par */
	background: var(--fog);
}
/* O conteúdo da faixa sobe acima da árvore; só o fundo dela fica por baixo.
   Sem isto a árvore, que agora pinta depois das faixas, passaria por cima do
   texto e dos retratos. */
.bracis-speaker__run,
.bracis-speaker__elbow,
.bracis-speaker__lead,
.bracis-speaker__node,
.bracis-speaker__portrait,
.bracis-speaker__panel {
	z-index: 2;
}

/* ---------- Pistas até a árvore ---------- */
/* As progressões que ligam faixa e tronco, a partir do --i (1-based) que vem
   inline. Juntas, elas são o que faz NENHUMA linha cruzar outra — e há dois
   cruzamentos possíveis, cada um resolvido por uma delas:
   1. A corrida horizontal de uma faixa, vindo da esquerda, atravessando pistas
      alheias. Resolvido por --rail-x CRESCENTE com --i: a faixa 1 pega a pista
      mais próxima do tronco e cada faixa seguinte uma mais para fora, então a
      corrida sempre para na primeira pista que encontra. As pistas que ficam
      por dentro pertencem a faixas de cima e já terminaram; as de fora
      pertencem a faixas de baixo e ainda nem começaram naquela altura.
   2. O cotovelo de entrada atravessando pistas alheias para alcançar o tronco.
      Resolvido por --rail-y DECRESCENTE com --i: cada faixa entra mais embaixo
      que a anterior, então o cotovelo passa sempre por baixo do ponto onde as
      pistas que cruza já terminaram.
   Inverter uma das duas sozinha reintroduz o cruzamento que ela resolve.
   --tap-x é o ponto de entrada: segue a borda esquerda do tronco, que se abre
   conforme desce, então cada faixa entra num x um pouco diferente. O termo
   entre parênteses é a distância da entrada até o alto do tronco. */
.bracis-speaker,
.bracis-speakers__rail {
	/* --node-y e --lead-dx vêm inline por faixa (são do mock); --ny e --ldx são
	   a versão que as peças leem, para que o empilhado possa substituí-las sem
	   disputar com o inline, que sempre venceria. */
	--ny: var(--node-y);
	--ldx: var(--lead-dx);
	--rail-x: calc(var(--rail-anchor) + var(--rail-gap) * (var(--i) - 1));
	--rail-y: calc(var(--rail-base) + var(--rail-step) * (var(--n) - var(--i)));
	--tap-x: calc(
		var(--trunk-x) + var(--trunk-dx0) + var(--trunk-gap)
		+ var(--trunk-flare) * (var(--trunk-vis) - var(--rail-y))
	);
	--tap: calc(var(--rail-x) - var(--tap-x));   /* 45°, logo dx = dy */
}

.bracis-speakers__rail {
	position: relative;
	z-index: 3;                /* acima das faixas que atravessa e da árvore */
	grid-column: 1;
	pointer-events: none;
}
/* A descida vertical: do pé do cotovelo da sua faixa até o alto do cotovelo de
   entrada no tronco. O translateX põe o CENTRO do traço em --rail-x, que é onde
   os rabos das duas diagonais a esperam — daí o 1.25 nas duas pontas: ela
   emenda vertical com vertical, e não com o corte enviesado da diagonal. */
.bracis-speakers__rail::before {
	content: "";
	position: absolute;
	right: var(--rail-x);
	top: calc(var(--ny) + var(--elbow) * 1.25 - 1px);
	bottom: calc(var(--rail-y) + var(--tap) * 1.25 - 1px);
	width: var(--trace-w);
	transform: translateX(50%);
	background: var(--event);
}
/* Vira para a DIREITA ao entrar: a pista corre à esquerda do tronco, então a
   caixa encosta a borda direita no ponto de entrada e o traço a atravessa do
   canto de cima à esquerda (onde a pista termina) até ali. */
.bracis-speakers__tap {
	position: absolute;
	right: var(--tap-x);
	bottom: var(--rail-y);
	width: var(--tap);
	height: var(--tap);
	overflow: visible;
	fill: none;
	stroke: var(--event);
	stroke-width: var(--trace-w);
	stroke-linejoin: miter;
}
.bracis-speakers__tap path {
	vector-effect: non-scaling-stroke;
}
/* Solda no ponto em que a trilha encontra o tronco. Na arte da árvore toda
   trilha termina numa bolinha; sem ela a nossa morre num corte enviesado e o
   traço parece apontar para a árvore em vez de nascer dela. Faz par com o nó
   grande do keynote, na outra ponta do percurso. */
.bracis-speakers__rail::after {
	content: "";
	position: absolute;
	right: var(--tap-x);
	bottom: var(--rail-y);
	width: calc(var(--trace-w) * 1.9);
	height: calc(var(--trace-w) * 1.9);
	transform: translate(50%, 50%);
	border-radius: 50%;
	background: var(--event);
}

/* ---------- Circuito dentro da faixa ---------- */
/* Três peças (ver o contrato em render.php): corrida elástica, cotovelo rígido
   que desvia para a pista e descida rígida até o retrato. Ancorado em --rail-x
   à direita e em --portrait-cx à esquerda; entre os dois, só a corrida cede. */
.bracis-speaker__elbow,
.bracis-speaker__lead {
	position: absolute;
	overflow: visible;   /* o traço é grosso e transborda a caixa do path */
	fill: none;
	stroke: var(--event);
	stroke-width: var(--trace-w);
	stroke-linejoin: miter;
	pointer-events: none;
}
/* No <path> e não no <svg>: `stroke` e `stroke-width` são herdadas, mas
   `vector-effect` NÃO é. Declarada só no <svg>, ela não chegava ao path, e o
   cotovelo — cujo viewBox 100x100 é ampliado para ~190px — engordava o traço
   na mesma proporção (~1,9x a corrida horizontal). A descida escapava por ter
   viewBox 1:1 com o tamanho em px. */
.bracis-speaker__elbow path,
.bracis-speaker__lead path {
	vector-effect: non-scaling-stroke;
}

/* Desvia a corrida horizontal para a pista vertical. Quadrado, logo sempre 45°. */
.bracis-speaker__elbow {
	right: var(--rail-x);
	top: var(--ny);
	width: var(--elbow);
	height: var(--elbow);
}
.bracis-speaker__run {
	position: absolute;
	top: var(--ny);
	/* 1.25 e não 1: encontra a ponta do rabo horizontal do cotovelo, não o
	   início da diagonal. O 1px a menos é sobreposição: encostadas, duas peças
	   da mesma cor ainda deixam uma costura de antialiasing. */
	right: calc(var(--rail-x) + var(--elbow) * 1.25 - 1px);
	left: calc(var(--portrait-cx) - var(--ldx));
	height: var(--trace-w);
	transform: translateY(-50%);
	background: var(--event);
	pointer-events: none;
}
/* Do nó até o centro do retrato. O viewBox é 1:1 com o tamanho em px, então
   nada escala e a diagonal fecha exatamente em (--portrait-cx, 280px). */
.bracis-speaker__lead {
	left: calc(var(--portrait-cx) - var(--ldx));
	top: var(--ny);
}
.bracis-speaker__node {
	position: absolute;
	left: calc(var(--portrait-cx) - var(--ldx));
	top: var(--ny);
	transform: translate(-50%, -50%);
	width: var(--node);
	height: var(--node);
	border-radius: 50%;
	background: var(--event);
	pointer-events: none;
}

/* ---------- Retrato ---------- */
.bracis-speaker__portrait {
	position: absolute;
	left: var(--portrait-cx);
	top: var(--portrait-cy);
	transform: translate(-50%, -50%);
	margin: 0;
	width: var(--portrait);
	height: var(--portrait);
	border-radius: 50%;
	border: 8px solid var(--event);
	background: var(--fog);
	background: color-mix(in srgb, var(--slate) 12%, var(--cloud));
	overflow: hidden;
	display: grid;
	place-items: center;
}
.bracis-speaker__portrait img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
.bracis-speaker__silhouette {
	width: 100%;
	height: 100%;
	fill: var(--slate);
	fill: color-mix(in srgb, var(--slate) 45%, var(--cloud));
}

/* ---------- Painel de texto ---------- */
/* acima do circuito: nas faixas 4 e 5 a diagonal desce cruzando a coluna de
   texto, e o traço não pode passar por cima da leitura */
.bracis-speaker__panel {
	position: relative;
	margin-left: var(--panel-x);
	max-width: min(700px, 40%);
	padding: 88px 0 48px;
}
/* Título da palestra: abre a faixa. Quem chega aqui está escolhendo sessão, e
   é a palestra que responde a isso — o nome vem logo em seguida. Fica em Noto
   Sans (o <h2> herdaria Bebas do tema): duas linhas de Bebas caixa alta
   empilhadas viram um bloco só, e o nome perderia o contorno. */
.bracis-speaker__talk {
	margin: 0;
	font-family: var(--wp--preset--font-family--noto-sans);
	font-size: clamp(1.55rem, 2.5vw, 1.95rem);
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -.005em;
	color: var(--navy);
}
/* O nome desceu um degrau ao perder a abertura, mas continua em Bebas caixa
   alta, como manda o contrato. Declara a família porque virou <p>: a hierarquia
   do documento mudou, a voz tipográfica não. */
.bracis-speaker__name {
	margin: .85rem 0 0;
	font-family: var(--wp--preset--font-family--bebas-neue);
	font-size: clamp(1.7rem, 2.8vw, 2rem);
	line-height: 1.05;
	letter-spacing: .01em;
	text-transform: uppercase;
	color: var(--navy);
}
/* Herdou o lugar que era da linha do evento, logo abaixo do nome, e por isso
   o degrau subiu: é ela que situa a pessoa agora. */
.bracis-speaker__affil {
	margin: .25rem 0 0;
	color: var(--event-ink);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--lg);
	line-height: 1.35;
}
/* Quando a palestra acontece. Fica em slate e não na cor do evento: a filiação
   logo acima já usa esse acento, e dois acentos seguidos empatam a leitura. */
.bracis-speaker__when {
	margin: .75rem 0 0;
	color: var(--slate);
	font-size: var(--wp--preset--font-size--md);
	font-weight: 600;
	letter-spacing: .01em;
	line-height: 1.35;
}
.bracis-speaker__when a {
	color: inherit;
	text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
	text-underline-offset: .22em;
}
.bracis-speaker__when a:hover,
.bracis-speaker__when a:focus-visible {
	color: var(--event-ink);
	text-decoration-color: currentColor;
}
.bracis-speaker__label {
	/* navy, não o gold do tema: sobre faixa clara o gold dá 1,49:1 */
	margin: 1.6rem 0 .5rem;
	color: var(--navy);
	font-family: var(--wp--preset--font-family--noto-sans);
	font-weight: 700;
	font-size: var(--wp--preset--font-size--lg);
	letter-spacing: .02em;
	text-transform: uppercase;
}
.bracis-speaker__body {
	margin: 0;
	color: var(--slate);
	font-size: var(--wp--preset--font-size--lg);
	line-height: 1.35;
}
.bracis-speaker__body + .bracis-speaker__body {
	margin-top: .7em;
}
/* Estado vazio desenhado: a organização ainda não confirmou o material, e não
   se inventa texto atribuído a pessoa real. */
.bracis-speaker__body.is-pending {
	color: var(--slate);
	color: color-mix(in srgb, var(--slate) 70%, var(--cloud));
	font-style: italic;
}

/* Entre ~1024 e 1365px o circuito completo ainda cabe, mas a coluna de texto
   fica estreita demais se ficar presa ao lado do retrato: sobra uma faixa
   vazia sob ele e o corpo desce em tiras. Aqui o painel passa a ocupar toda a
   largura útil e abre um vão flutuante no canto superior esquerdo, do tamanho
   do retrato — nome, filiação e título correm ao lado dele, e o corpo desce
   por baixo aproveitando a largura inteira. O vão é um float vazio e não uma
   margem porque a margem valeria para o bloco todo, inclusive abaixo da foto.
   O retrato continua absoluto: mexer nele desalinharia o nó e o traço que o
   liga ao circuito. */
@media (min-width: 1024px) and (max-width: 1365px) {
	.bracis-speakers {
		/* recuo do texto que corre por baixo do retrato; sem ele o corpo cola na
		   borda da faixa, já que aqui o painel perdeu a margem esquerda */
		--panel-pad: clamp(1.5rem, 3vw, 3rem);
	}
	.bracis-speaker__panel {
		margin-left: 0;
		max-width: none;
		padding-left: var(--panel-pad);
		/* corredor das pistas na direita */
		padding-right: calc(var(--rail-anchor) + var(--rail-gap) * (var(--n) - 1) + 3.5rem);
	}
	/* Sem isto o rótulo cai na altura do vão e a primeira linha do corpo sai
	   recuada, sozinha, enquanto o resto do parágrafo ocupa a largura toda. */
	.bracis-speaker__label {
		clear: left;
	}
	.bracis-speaker__panel::before {
		content: "";
		float: left;
		/* medido a partir do retrato, não de --panel-x: aquele é uma
		   porcentagem, e dentro do painel ela passa a valer sobre a largura
		   dele — bem menor que a do artigo — e o texto invade a foto.
		   Desconta --panel-pad porque o float nasce depois do padding. */
		width: calc(var(--portrait-cx) + var(--portrait) / 2 + 2rem - var(--panel-pad));
		/* do topo do painel até a base do retrato, mais um respiro */
		height: calc(var(--portrait-cy) + var(--portrait) / 2 - 88px + 1.5rem);
	}
}

/* ---------- Empilhado ---------- */
/* 1023px e não 1199px: até aí o percurso completo ainda cabe, e perdê-lo cedo
   demais tirava as linhas de telas onde elas ainda funcionavam. */
@media (max-width: 1023px) {
	/* O circuito NÃO some aqui: o percurso é o mesmo do desktop, só reescalado
	   e reancorado. O que muda é de onde ele parte — com o retrato empilhado, o
	   nó sobe para o topo da faixa, e é lá que a corrida horizontal começa.
	   --portrait-cx deixa de ser o centro do retrato absoluto e passa a ser o
	   centro do retrato empilhado; --lead-dx zera porque não há mais recuo
	   entre nó e retrato. Redefinir as duas aqui evita reescrever as peças. */
	.bracis-speakers {
		--portrait: 132px;
		/* + a borda: o retrato não é border-box, então a caixa dele mede
		   --portrait mais os 6px de cada lado, e é o centro DESSA caixa que o nó
		   e o traço precisam encontrar */
		--portrait-cx: calc(clamp(1.25rem, 5vw, 3rem) + (var(--portrait) + 12px) / 2);
		--trace-w: clamp(6px, 1.6vw, 9px);
		--node: clamp(20px, 5.4vw, 30px);
		--elbow: clamp(30px, 8vw, 52px);
		--rail-anchor: clamp(40px, 11vw, 62px);
		--rail-gap: clamp(11px, 3vw, 17px);
		--trunk-x: clamp(10px, 3vw, 20px);
		--trunk-gap: calc(var(--tree-w) * .03);
		/* generosa apesar da tela pequena: --rail-step sai de --trunk-vis, que sai
		   daqui, então uma árvore curta espreme as cinco entradas umas nas outras */
		--tree-h: clamp(600px, 175vw, 1000px);
		--tree-opacity: .3;
	}
	/* o empilhado redefine as quatro medidas do eixo, então o arredondamento do
	   topo do arquivo não o alcança — ver o porquê lá */
	@supports (width: round(1px, 1px)) {
		.bracis-speakers {
			--trace-w: round(clamp(6px, 1.6vw, 9px), 2px);
			--elbow: round(clamp(30px, 8vw, 52px), 4px);
			--rail-anchor: round(clamp(40px, 11vw, 62px), 1px);
			--rail-gap: round(clamp(11px, 3vw, 17px), 1px);
		}
	}
	/* o nó sobe para junto do topo da faixa, alinhado ao centro do retrato
	   empilhado — daí --ldx zerar: não há mais recuo entre nó e retrato */
	.bracis-speaker,
	.bracis-speakers__rail {
		--ny: clamp(14px, 4vw, 22px);
		--ldx: 0px;
	}
	.bracis-speaker {
		min-height: 0;
		padding: 3rem clamp(1.25rem, 5vw, 3rem) 3.5rem;
	}
	/* a descida diagonal até o retrato não cabe; o traço vertical abaixo faz o
	   papel dela */
	.bracis-speaker__lead {
		display: none;
	}
	/* liga o nó ao topo do retrato empilhado */
	.bracis-speaker::before {
		content: "";
		position: absolute;
		z-index: 2;
		top: var(--ny);
		left: calc(var(--portrait-cx) - var(--trace-w) / 2);
		width: var(--trace-w);
		height: calc(3rem - var(--ny));
		background: var(--event);
	}
	.bracis-speaker__portrait {
		position: static;
		transform: none;
		border-width: 6px;
		margin: 0 0 1.75rem;
	}
	.bracis-speaker__panel {
		margin-left: 0;
		max-width: none;
		/* corredor das pistas: sem ele o texto corre por baixo delas */
		padding: 0 calc(var(--rail-anchor) + var(--rail-gap) * (var(--n) - 1) + 1rem) 0 0;
	}
	/* o retrato também não pode invadir o corredor */
	.bracis-speaker__portrait {
		max-width: calc(100% - var(--rail-anchor));
	}
}

@media (prefers-reduced-motion: no-preference) {
	.bracis-speaker__portrait img {
		transition: transform .4s ease;
	}
}
