/* ============================================================
   BOOKATOON — Personagens fora das molduras + Palco do elenco
   Etapa 4 da migração de @layer (docs/layer-proposal.md).

   PARTE 1 · Protagonistas: recortes transparentes saltando de
   pequenos palcos de papel (nenhuma caixa fechada).

   ── AJUSTES POR PERSONAGEM (tamanho/posição/rotação) ──
   .personagem--capy / --djn / --guardiao definem:
     --cutout-width   largura do recorte em relação ao palco
     --cutout-y       deslocamento vertical (positivo = desce)
     --cutout-rotate  inclinação de repouso
   Troca de render: substitua o arquivo em
   assets/img/personagens/*.png (mesma proporção 1200×1400)
   ou apenas o src do <img class="personagem__cutout">.
   ============================================================ */
@layer sections {

.personagem {
  position: relative;
  isolation: isolate;
  overflow: visible;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  display: grid;
  gap: 1rem;
  align-content: end;
}

/* Os protagonistas entram apenas no eixo vertical. O scale genérico do
   reveal (.motion-on [data-reveal] em base.css) altera a largura visual
   do card e cria um salto lateral visível ("jogado" pro lado) no
   primeiro scroll — já aconteceu e voltou uma vez, então documentando
   bem aqui: coberto por teste em tests/conditions.spec.js ("Reveal dos
   personagens sem salto lateral"), rode antes de mexer em qualquer
   coisa abaixo.

   ⚠️ FRÁGIL A REORDENAÇÃO DE CAMADA: este override só vence o de
   base.css porque a camada "sections" (aqui) é declarada DEPOIS de
   "base" em css/tokens.css — entre camadas diferentes, quem decide é
   a ORDEM DA CAMADA, nunca a especificidade do seletor (por isso
   ".personagem[data-reveal]" aqui, menos específico que
   "[data-reveal].is-in" de base.css, ainda assim vence). Duas formas
   de quebrar isso sem tocar nestas linhas: (1) reordenar a lista em
   tokens.css; (2) adicionar transform/translate em [data-reveal] ou
   .personagem num arquivo SEM @layer (hoje só css/refinement.css) —
   CSS fora de camada vence qualquer CSS em camada, sempre. */
.motion-on .personagem[data-reveal] {
  transform: translateY(var(--reveal-y));
}

.motion-on .personagem[data-reveal].is-in {
  transform: none;
}

/* Palco individual */
.personagem__stage {
  position: relative;
  isolation: isolate;
  overflow: visible;
  aspect-ratio: 4 / 3;
  min-height: 230px;
}

.personagem--guardiao .personagem__stage {
  aspect-ratio: 3 / 3.4; /* vertical: transmite escala */
}

/* Moldura-palco (única camada com recorte interno) */
.personagem__frame {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background: var(--pers-cor);
  border: var(--stroke) solid var(--ink);
  border-radius: var(--r-xl);
  box-shadow: 0.35rem 0.4rem 0 rgba(36, 21, 51, 0.16);
  transition: translate var(--dur-micro) var(--ease-energy);
}

/* Cenário decorativo dentro da moldura */
.personagem__backdrop {
  position: absolute;
  inset: 0;
}

.personagem--capy .personagem__backdrop {
  background:
    repeating-radial-gradient(circle at 50% 78%,
      transparent 0 34px,
      rgba(var(--branco-rgb), 0.35) 34px 38px);
}

.personagem--djn .personagem__backdrop {
  background:
    repeating-radial-gradient(circle at 50% 60%,
      transparent 0 26px,
      rgba(var(--roxo-profundo-rgb), 0.10) 26px 30px);
}

.personagem--guardiao .personagem__backdrop {
  /* stylelint-disable-next-line scale-unlimited/declaration-strict-value --
     falso positivo: o plugin não interpreta bem o valor de "background"
     multi-camada (vírgula); todas as cores aqui já são var(). */
  background:
    linear-gradient(180deg, rgba(var(--ambar-rgb), 0.25), transparent 55%),
    repeating-linear-gradient(90deg,
      transparent 0 44px,
      rgba(var(--ink-rgb), 0.05) 44px 48px);
}

/* Recorte transparente do personagem: pode saltar pra fora do palco
   em cima/nas laterais (efeito pop-up, de propósito), mas embaixo
   teria sombra/arte vazando reto sobre o fundo da página, sem a
   moldura arredondada do cartão pra "segurar" — por isso o clip só
   fecha embaixo (round nos dois cantos inferiores, mesmo raio do
   .personagem__frame), com folga enorme (-200%) nos outros 3 lados
   pra nunca cortar o personagem ali. */
.personagem__cutout-clip {
  position: absolute;
  inset: 0;
  z-index: 2;
  clip-path: inset(-200% -200% 0 -200% round 0 0 var(--r-xl) var(--r-xl));
  pointer-events: none;
}

.personagem__picture {
  display: contents;
}

.personagem__cutout {
  position: absolute;
  z-index: 2;
  left: 50%;
  bottom: -2px;
  width: var(--cutout-width, 86%);
  height: auto;
  max-height: 132%;
  object-fit: contain;
  object-position: center bottom;
  /* --mouse-rot/--mouse-y: js/main.js atualiza no pointermove sobre
     o .personagem__stage (mesma ideia do balanço do Chris) — a
     transition abaixo já suaviza, sem precisar de lerp em JS. */
  transform:
    translateX(calc(-50% + var(--cutout-x, 0px)))
    translateY(calc(var(--cutout-y, 0px) + var(--mouse-y, 0px)))
    rotate(calc(var(--cutout-rotate, 0deg) + var(--mouse-rot, 0deg)));
  filter: drop-shadow(0.5rem 0.75rem 0 rgba(36, 21, 51, 0.18));
  pointer-events: none;
  transition: transform 0.32s var(--ease-energy);
}

/* Borda frontal parcial: lábio do palco sobre a base do personagem */
.personagem__front-border {
  position: absolute;
  z-index: 3;
  left: 8%;
  right: 8%;
  bottom: -10px;
  height: 26px;
  background: var(--pers-cor);
  border: var(--stroke) solid var(--ink);
  border-radius: 14px;
  box-shadow: 0.2rem 0.25rem 0 rgba(36, 21, 51, 0.18);
  pointer-events: none;
}

/* Balão acima de tudo */
.personagem__stage .personagem__balao {
  z-index: 4;
}

/* Recorte: a nota PODE sair do cartão amarelo (fica bonito voando
   sobre o fundo da página) — só não pode invadir o cartão vizinho
   (Droid-guia) à direita. Por isso a folga é generosa em cima/embaixo/
   esquerda (nada ali pra esbarrar) e curta à direita.
   IMPORTANTE: a caixa deste elemento fica em inset:0 (do tamanho do
   cartão) — é ela que serve de referência pro left/top em % da nota
   lá dentro. Quem abre a área de corte pra fora é o clip-path (aceita
   valor negativo pra "crescer" o recorte), não o tamanho da caixa. */
.personagem__nota-clip {
  position: absolute;
  inset: 0;
  z-index: 5;
  clip-path: inset(-70% -6% -45% -70%);
  pointer-events: none;
}

/* Nota "BOO/KA/TOON": pop-up a cada troca de quadro do Capy Beat, saindo
   de um ponto diferente ao redor dela por vez (JS define left/top e
   reaplica a animação — ver main.js). Some sozinha; começa oculta pra
   não aparecer estática antes do primeiro ciclo. */
.personagem__nota {
  position: absolute;
  left: var(--nota-left, 0%);
  top: var(--nota-top, 10%);
  width: clamp(64px, 30%, 130px);
  pointer-events: none;
  opacity: 0;
}

.personagem__nota-img {
  display: block;
  width: 100%;
  height: auto;
  filter: drop-shadow(0.3rem 0.35rem 0 rgba(36, 21, 51, 0.18));
}

/* --nota-tx/--nota-ty/--nota-rot: destino da "viagem" da nota, definido
   por quadro em main.js — cada uma sai voando pra um canto diferente
   em vez de sempre nascer e sumir no mesmo pontinho. */
@keyframes nota-pop {
  0% {
    opacity: 0;
    transform: translate(0, 0) scale(0.4) rotate(-8deg);
  }
  35% {
    opacity: 1;
    transform:
      translate(calc(var(--nota-tx, 0px) * 0.35), calc(var(--nota-ty, -60px) * 0.35))
      scale(1.1)
      rotate(calc(var(--nota-rot, -4deg) * 0.5));
  }
  100% {
    opacity: 0;
    transform:
      translate(var(--nota-tx, 0), var(--nota-ty, -60px))
      scale(0.88)
      rotate(var(--nota-rot, -4deg));
  }
}

.motion-on .personagem__nota.is-pop {
  animation: nota-pop 0.9s var(--ease-energy);
}

/* Área de texto aberta (sem caixa) */
.personagem__info {
  position: relative;
  z-index: 3;
  display: grid;
  gap: 0.55rem;
  padding-inline: 0.4rem;
}

.personagem__info p:last-child {
  color: var(--text-muted);
  font-size: var(--fs-small);
}

/* ---------------- Variáveis individuais ---------------- */

.personagem--capy {
  /* Os quadros do Capy Beat (assets/img/personagens/capy-beat/) têm bem
     mais "respiro" transparente ao redor do personagem do que o antigo
     capy-home.png (a Capy ocupa ~67% do canvas, contra ~88% antes) —
     por isso o --cutout-width subiu bastante, só pra manter o mesmo
     tamanho visual de antes. --cutout-y também subiu um pouco pra
     compensar a sobra extra embaixo do novo recorte. */
  --cutout-width: 125%;
  --cutout-y: 24px;
  --cutout-rotate: -4deg;
}

/* Com os pés tão perto da base do palco (--cutout-y grande), o
   drop-shadow padrão (deslocado 0.75rem pra baixo) vazava pra fora do
   recorte, aparecendo como uma mancha solta abaixo do lábio do palco. */
.personagem--capy .personagem__cutout {
  filter: none;
}

.personagem--djn {
  --cutout-width: 78%;
  --cutout-y: 6px;
  --cutout-rotate: 1deg;
}

.personagem--guardiao {
  --cutout-width: 92%;
  --cutout-y: 8px;
  --cutout-rotate: 0deg;
}

/* ---------------- Motion: salto para fora da moldura ----------------
   Anima SÓ o cutout (o reveal já anima o artigo inteiro).
   fill backwards: após terminar, o transform natural assume e o
   hover pode transicionar sem disputa. */

@keyframes cutout-salto {
  0% {
    opacity: 0;
    transform:
      translateX(calc(-50% + var(--cutout-x, 0px)))
      translateY(calc(var(--cutout-y, 0px) + 24px))
      rotate(var(--cutout-rotate, 0deg));
  }
  70% {
    opacity: 1;
    transform:
      translateX(calc(-50% + var(--cutout-x, 0px)))
      translateY(calc(var(--cutout-y, 0px) - 8px))
      rotate(var(--cutout-rotate, 0deg));
  }
  100% {
    opacity: 1;
    transform:
      translateX(calc(-50% + var(--cutout-x, 0)))
      translateY(var(--cutout-y, 0))
      rotate(var(--cutout-rotate, 0deg));
  }
}

.motion-on .personagem[data-reveal].is-in .personagem__cutout {
  animation: cutout-salto 0.7s var(--ease-energy) backwards;
  animation-delay: calc(var(--reveal-delay, 0ms) + 140ms);
}

/* Hover/foco: personagem sobe, moldura recua, balão aparece
   (estados espelhados; sem loops) */
@media (hover: hover) {
  .motion-on .personagem:hover .personagem__cutout {
    transform:
      translateX(calc(-50% + var(--cutout-x, 0px)))
      translateY(calc(var(--cutout-y, 0px) + var(--mouse-y, 0px) - 13px))
      rotate(calc(var(--cutout-rotate, 0deg) + var(--mouse-rot, 0deg)))
      scale(1.03);
  }

  .motion-on .personagem:hover .personagem__frame {
    translate: 0 4px;
  }
}

.motion-on .personagem:focus-visible .personagem__cutout,
.motion-on .personagem:focus-within .personagem__cutout {
  transform:
    translateX(calc(-50% + var(--cutout-x, 0px)))
    translateY(calc(var(--cutout-y, 0px) + var(--mouse-y, 0px) - 13px))
    rotate(calc(var(--cutout-rotate, 0deg) + var(--mouse-rot, 0deg)))
    scale(1.03);
}

.motion-on .personagem:focus-visible .personagem__frame,
.motion-on .personagem:focus-within .personagem__frame {
  translate: 0 4px;
}

/* Touch: sem hover — balão sempre visível e pose final estável.
   translate precisa continuar -50% no eixo X (mesmo valor do estado
   :hover/:focus-within em popup.css): é o que centraliza o balão junto
   com "left: 50%" — um "translate: 0 0" aqui descentraliza e cola na
   borda direita do cartão. */
@media (hover: none) {
  .personagem__balao {
    opacity: 1;
    translate: -50% 0;
    scale: 1;
  }
}

/* ============================================================
   PARTE 2 · PALCO/CARROSSEL 3D DO ELENCO DE APOIO

   Dados (nomes, papéis, descrições, imagens): js/elenco.js.
   Troca de render: assets/img/elenco/*.png (1200×1400).
   Durações: --palco-troca abaixo (transição de personagem).
   ============================================================ */

.elenco-palco {
  --palco-troca: 0.3s; /* metade da troca (saída OU entrada) */
  margin-top: clamp(3.5rem, 7vw, 5.5rem);
}

.elenco-palco__layout {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
}

@media (min-width: 56rem) {
  .elenco-palco__layout {
    grid-template-columns: 55% 1fr; /* palco | texto */
  }
}

/* ---------------- Palco ---------------- */

/* Profundidade "de papel": planos escalonados 2D (sem transform 3D —
   perspective/preserve-3d + filter congelava o rasterizador do Chromium) */
.palco-3d {
  position: relative;
  isolation: isolate;
  min-height: clamp(300px, 42vw, 520px);
}

/* Fundo solto: a arte do palco (assets/img/Background-home-elenco.png)
   já traz fundo E chão prontos, com transparência real ao redor —
   nada de cartão/moldura aqui, só a ilustração flutuando sobre o
   fundo da página. (O .jpg original tinha fundo branco sólido; este
   .png foi recortado a partir dele removendo esse branco e depois
   aparado só na margem transparente — nenhum pixel de arte real foi
   cortado, o pódio só ficou maior por sobrar menos espaço vazio.) */
.palco-3d__fundo {
  position: absolute;
  inset: 0 2% 3%; /* menos sobra embaixo → contain escala a arte um pouco mais */
  z-index: 0;
  /* stylelint-disable-next-line scale-unlimited/declaration-strict-value --
     falso positivo: o plugin lê "center"/"/" do shorthand como se fossem cor. */
  background: url("../assets/img/Background-home-elenco.png") center / contain no-repeat;
}

/* Holofotes: dois triângulos de luz vindos do topo, um de cada lado,
   convergindo pro centro onde o personagem está. Tema por personagem.
   2026-07-27: substituído rgba(255,193,7,…) literal por rgba(var(--ambar-rgb),…)
   nestas 6 declarações + nas 3 do halo (var() puro, sem color-mix()).
   Verificado nesta sessão: o valor computado resolve exatamente igual ao
   literal anterior, sem erro de console, e a troca de tema (chris/banda/
   sakaguti) via elenco.js funciona normalmente. NÃO verificado: ausência
   de congelamento de rasterização em GPU — o ambiente de preview usado
   não compõe frames (mesma limitação de outras validações visuais desta
   sessão), então a checagem real do bug antigo continua pendente de
   confirmação visual humana. Se congelar em algum navegador, reverter
   estas 9 declarações para rgba(N,N,N,…) literal. */
.palco-3d__luzes {
  position: absolute;
  inset: 0 6% 18%;
  z-index: 1;
  border-radius: var(--r-xl);
  overflow: hidden;
  pointer-events: none;
}

.palco-3d__luzes::before,
.palco-3d__luzes::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0.6;
  mix-blend-mode: screen;
}

.palco-3d__luzes::before {
  clip-path: polygon(6% 0%, 60% 100%, 0% 100%);
  transform-origin: 6% 0%; /* pico do triângulo: eixo do balanço */
}

.palco-3d__luzes::after {
  clip-path: polygon(94% 0%, 40% 100%, 100% 100%);
  transform-origin: 94% 0%; /* pico do triângulo: eixo do balanço */
}

[data-tema="chris"] .palco-3d__luzes::before {
  background: linear-gradient(180deg, rgba(var(--ambar-rgb), 0.85), rgba(var(--ambar-rgb), 0) 82%);
}

[data-tema="chris"] .palco-3d__luzes::after {
  background: linear-gradient(180deg, rgba(var(--ceu-rgb), 0.8), rgba(var(--ceu-rgb), 0) 82%);
}

[data-tema="banda"] .palco-3d__luzes::before {
  background: linear-gradient(180deg, rgba(var(--violeta-rgb), 0.85), rgba(var(--violeta-rgb), 0) 82%);
}

[data-tema="banda"] .palco-3d__luzes::after {
  background: linear-gradient(180deg, rgba(var(--coral-rgb), 0.8), rgba(var(--coral-rgb), 0) 82%);
}

[data-tema="sakaguti"] .palco-3d__luzes::before {
  background: linear-gradient(180deg, rgba(var(--coral-rgb), 0.85), rgba(var(--coral-rgb), 0) 82%);
}

[data-tema="sakaguti"] .palco-3d__luzes::after {
  background: linear-gradient(180deg, rgba(var(--ambar-rgb), 0.8), rgba(var(--ambar-rgb), 0) 82%);
}

.motion-on:not([data-decor-paused="true"]) .palco-3d__luzes::before {
  animation: holofote-varredura 6s ease-in-out infinite;
}

.motion-on:not([data-decor-paused="true"]) .palco-3d__luzes::after {
  animation: holofote-varredura 6.8s ease-in-out infinite 1.2s;
}

/* Balanço do holofote: gira em torno do próprio pico (transform-origin
   acima), como um facho de luz varrendo de um lado para o outro. */
@keyframes holofote-varredura {
  0%, 100% { rotate: -8deg; opacity: 0.45; }
  50%      { rotate: 8deg; opacity: 0.8; }
}

/* Halo atrás do personagem */
.palco-3d__halo {
  position: absolute;
  left: 50%;
  bottom: 17.5%;
  z-index: 1;
  width: 62%;
  aspect-ratio: 1;
  translate: -50% 0;
  pointer-events: none;
}

[data-tema="chris"] .palco-3d__halo {
  background: radial-gradient(circle, rgba(var(--ambar-rgb), 0.42), transparent 68%);
}

[data-tema="banda"] .palco-3d__halo {
  background: radial-gradient(circle, rgba(var(--violeta-rgb), 0.42), transparent 68%);
}

[data-tema="sakaguti"] .palco-3d__halo {
  background: radial-gradient(circle, rgba(var(--coral-rgb), 0.42), transparent 68%);
}


[data-tema="lore"] .palco-3d__halo {
  background: radial-gradient(circle, rgba(var(--coral-rgb), 0.42), transparent 68%);
}

/* Piso: já vem pintado dentro do .palco-3d__fundo (assets/img/Background-home-elenco.png),
   então esta elipse amarela antiga fica desligada — evita duplicar o chão. */
.palco-3d__base {
  display: none;
}

/* Personagem em primeiro plano.
   O posicionamento (-50%) vive no wrapper estático .palco-3d__ator;
   as trocas animam o <img> com px puros via ANIMATION (o padrão
   transition:none + reflow forçado congelava o renderer). */
.palco-3d__ator {
  position: absolute;
  left: 50%; /* centro geométrico do palco — poses do elenco já vêm centralizadas
                no próprio canvas (conferido por pixel), sem precisar de offset */
  bottom: 22%; /* pé um pouco mais para trás na superfície dourada do pódio pintado */
  z-index: 2;
  width: min(58%, 320px);
  translate: -50% 0;
  pointer-events: none;
}

.palco-3d__personagem {
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
  object-position: center bottom;
  /* escala por pose (js/elenco.js define img.style.scale): compensa
     recortes com "envergadura" diferente (braços abertos/agachado)
     medindo pela cabeça, não pela caixa inteira da imagem — sem
     isso, poses com braços mais abertos pareceriam menores e a
     agachada pareceria maior, dando sensação de personagem
     crescendo/encolhendo entre as trocas. */
  scale: 1;
  transform-origin: 50% 100%; /* base fixa: escala nunca "levanta" os pés do chão */
}

/* Sombra de contato */
.palco-3d__sombra {
  position: absolute;
  left: 50%;
  bottom: 20%; /* logo abaixo dos pés, já em cima do palco pintado */
  z-index: 1;
  width: 42%;
  height: 26px;
  translate: -50% 0;
  background: radial-gradient(ellipse, rgba(36, 21, 51, 0.35), transparent 70%);
  pointer-events: none;
}

/* Troca de personagem (JS controla as classes) */
@keyframes palco-sai-esq {
  to { opacity: 0; transform: translateX(-48px) scale(0.96); }
}

@keyframes palco-sai-dir {
  to { opacity: 0; transform: translateX(48px) scale(0.96); }
}

@keyframes palco-entra-dir {
  from { opacity: 0; transform: translateX(48px) scale(0.96); }
  to   { opacity: 1; transform: none; }
}

@keyframes palco-entra-esq {
  from { opacity: 0; transform: translateX(-48px) scale(0.96); }
  to   { opacity: 1; transform: none; }
}

.palco-3d__personagem.is-saindo-esq {
  animation: palco-sai-esq var(--palco-troca) var(--ease-suave) forwards;
}

.palco-3d__personagem.is-saindo-dir {
  animation: palco-sai-dir var(--palco-troca) var(--ease-suave) forwards;
}

.palco-3d__personagem.is-entrando-dir {
  animation: palco-entra-dir var(--palco-troca) var(--ease-suave) backwards;
}

.palco-3d__personagem.is-entrando-esq {
  animation: palco-entra-esq var(--palco-troca) var(--ease-suave) backwards;
}

/* Fallback deliberado quando a imagem faltar */
.palco-3d__fallback {
  position: absolute;
  left: 50%;
  bottom: 22%;
  z-index: 2;
  translate: -50% 0;
  display: none;
  text-align: center;
  color: var(--papel-sobre-escuro);
  font-family: var(--font-display);
  font-weight: 600;
}

.palco-3d__fallback svg {
  width: 72px;
  margin-inline: auto;
}

.palco-3d.sem-imagem .palco-3d__personagem { display: none; }
.palco-3d.sem-imagem .palco-3d__fallback { display: grid; gap: 0.5rem; }

/* ---------------- Conteúdo textual ---------------- */

.elenco-palco__conteudo {
  display: grid;
  gap: 1rem;
  align-content: center;
}

.elenco-palco__meta {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.elenco-palco__contador {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--text-muted);
}

.elenco-palco__texto {
  min-height: 11rem; /* evita layout shift entre textos */
  transition: opacity var(--palco-troca) linear;
}

.elenco-palco__texto.is-trocando {
  opacity: 0;
}

.elenco-palco__papel {
  font-size: 0.85rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--roxo-profundo);
}

.elenco-palco__texto h3 {
  font-size: clamp(1.8rem, 3vw, 2.4rem);
  margin-block: 0.2rem 0.5rem;
}

.elenco-palco__frase {
  margin-top: 0.6rem;
  font-family: var(--font-display);
  font-weight: 500;
  color: var(--roxo-profundo);
}

/* Controles */
.elenco-palco__controles {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  flex-wrap: wrap;
}

.elenco-palco__anterior,
.elenco-palco__proximo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap-min);
  height: var(--tap-min);
  padding: 0;
  background: var(--branco);
  border: var(--stroke) solid var(--ink);
  border-radius: var(--r-pill);
  box-shadow: 0.18rem 0.22rem 0 rgba(36, 21, 51, 0.2);
  cursor: var(--cursor-hand);
  transition: translate var(--dur-fast) var(--ease-energy);
}

.elenco-palco__anterior svg,
.elenco-palco__proximo svg {
  width: 15px;
  height: 15px;
  fill: var(--ink);
}

.elenco-palco__anterior:hover,
.elenco-palco__proximo:hover {
  translate: 0 -2px;
}

.elenco-palco__anterior:active,
.elenco-palco__proximo:active {
  translate: 0 1px;
}

.elenco-palco__paginacao {
  display: flex;
  gap: 0.4rem;
}

/* Indicadores: nome acessível + estado não só por cor */
.elenco-palco__dot {
  display: grid;
  place-items: center;
  width: var(--tap-min);
  height: var(--tap-min);
  padding: 0;
  background: none;
  border: 0;
  cursor: var(--cursor-hand);
}

.elenco-palco__dot::after {
  content: "";
  width: 13px;
  height: 13px;
  background: var(--branco);
  border: 3px solid var(--ink);
  border-radius: 50%;
  transition: scale var(--dur-fast) var(--ease-energy), background-color var(--dur-fast) linear;
}

.elenco-palco__dot[aria-current="true"]::after {
  background: var(--ink);
  scale: 1.45;
}

/* ---------------- Responsivo ---------------- */

@media (max-width: 55.99rem) {
  .palco-3d {
    min-height: clamp(280px, 78vw, 360px);
  }

  .elenco-palco__texto {
    min-height: 0;
  }

  /* Toque vira o controle principal aqui (arrastar o dedo sobre o
     palco — ver js/elenco.js), então as setas somem; os
     indicadores em bolinha continuam como alternativa alcançável
     (cada um já tem aria-label com o nome do personagem) e as setas
     de teclado seguem funcionando com o foco dentro do componente. */
  .elenco-palco__anterior,
  .elenco-palco__proximo {
    display: none;
  }

  .elenco-palco__paginacao {
    margin-inline: auto;
  }
}

/* ---------------- Grid dos protagonistas ---------------- */

.personagens__grid {
  /* Só o respiro pro recorte "saltar" pra fora do palco — o espaço
     depois do parágrafo em si já vem do margin-bottom do .section-head
     (reduzido logo abaixo só nesta seção), que cresce/encolhe sozinho
     com o texto. */
  padding-top: 0.25rem;
}

/* Essa seção especificamente não precisa do respiro padrão de
   .section-head (clamp(2.5rem,5vw,4rem) em components.css) — os
   personagens já têm presença visual forte, sobrava vão vazio antes
   deles. Só aqui, não mexe no resto do site. */
.personagens .section-head {
  margin-bottom: clamp(0.75rem, 1.5vw, 1.25rem);
}

@media (min-width: 40rem) and (max-width: 55.99rem) {
  /* tablet: dois na primeira linha, Guardião centralizado abaixo */
  .personagens__grid {
    grid-template-columns: 1fr 1fr;
  }

  .personagem--guardiao {
    grid-column: 1 / -1;
    max-width: 26rem;
    margin-inline: auto;
    width: 100%;
  }
}

@media (min-width: 56rem) {
  /* Subgrid: sem isso, cada .personagem é bloco rígido (palco+info)
     alinhado pela base — como o palco do Guardião é mais alto (aspect-
     ratio vertical, de propósito, "transmite escala"), o bloco dele
     empurrava o título mais pra baixo que o dos outros dois. Com
     subgrid, palco e info viram FAIXAS compartilhadas entre os três:
     a base de todos os palcos alinha (align-self:end na faixa 1) e
     todos os títulos começam juntos (align-self:start na faixa 2) —
     só o texto de descrição, que não precisa alinhar, cresce livre.
     O align-items:end de antes virou no-op (o item passa a esticar
     exatamente pelas faixas que ocupa), mantido só por segurança. */
  .personagens__grid {
    align-items: end;
    grid-template-rows: auto auto;
    gap: clamp(2rem, 3vw, 2.75rem);
  }

  .personagem {
    grid-row: span 2;
    grid-template-rows: subgrid;
  }

  .personagem__stage {
    align-self: end;
  }

  .personagem__info {
    align-self: start;
  }
}

@media (max-width: 39.99rem) {
  .personagem__stage {
    max-width: 24rem;
    width: 100%;
    margin-inline: auto;
  }

  .personagens__grid {
    row-gap: 4.5rem;
  }
}

} /* fim de @layer sections */
