/* ============================================================
   Componente: banners animados Bauhaus (.motion)

   Vinte e uma composições de círculo, semicírculo e quadrado — três para
   os cards de destaque da Início (P1 · Recomendações, P2 · Fundamentos,
   P3 · Ferramentas) e dezoito de seção (01–12, uma por recomendação, e
   13–18, uma por página de Fundamentos e de Ferramentas). O markup mora
   em app/Views/partials/motion.php; o mapa slot → peça, em App\Core\Motions.

   Como isto escala
   ----------------
   As composições foram desenhadas em pixels sobre uma prancha fixa
   (588×256 nos banners largos, 378,66×236,66 nos de seção). Aqui cada
   medida vira um múltiplo de --u, a unidade de prancha, calculada por
   container query para COBRIR o espaço que o banner recebe (o mesmo efeito
   de object-fit: cover). Assim uma peça declara só o número do desenho
   (--x: 82) e o CSS resolve o resto.

   NÃO usar font-size como unidade de escala: o tamanho mínimo de fonte que
   o navegador ou o sistema operacional impõe (recurso de baixa visão, e
   portanto comum entre quem este site atende) esmagaria a composição.

   Acessibilidade
   --------------
   - Decorativo: quem insere o componente marca o contêiner com aria-hidden.
   - Sem flashes: nenhuma animação altera opacidade ou cor; só forma e posição.
   - Movimento reduzido (preferência do sistema OU painel do site) é atendido
     pelas regras globais de main.css, que encurtam a animação a 0,01ms e a
     rodam uma vez. Por isso o estado BASE de cada peça reproduz o quadro 0%
     da sua animação: parada, a composição é a que foi desenhada, não um
     resto de animação.
   - "Ocultar imagens" já apaga os contêineres (.hero__figura, .card__figura,
     .card-destaque__figura) em main.css — o banner some junto.
   ============================================================ */

/* ---------- Paleta ----------
   Duas famílias de token, e a distinção entre elas é o que sustenta os modos
   monocromáticos: --mo-campo-* pinta o fundo da peça, --mo-* pinta as figuras
   sobre ele. No tema normal as duas coincidem, mas separá-las permite recolorir
   campo e figura de modo independente onde a paleta encolhe.

   O desenho respeita uma regra que os modos monocromáticos dependem: figuras
   claras (branco, pálido, ciano) só aparecem sobre campo escuro ou médio, e
   figuras escuras (escuro, médio) só aparecem sobre campo ciano. Ao criar uma
   peça nova, manter essa separação — é ela que garante contraste quando a
   paleta cai para três tons.

   Quatro dos cinco tons são a paleta de marca de tokens.css. O quinto,
   --mo-ciano, é acento exclusivo destes banners (decisão de 29/08/2026): é o
   tom que separa as figuras claras entre si dentro de uma mesma peça, e não
   tem equivalente entre os tokens de marca. Não reutilizar fora daqui sem
   verificar contraste. */
.motion {
  --mo-campo-escuro: var(--rare-azul-escuro);
  --mo-campo-medio: var(--rare-azul-medio);
  --mo-campo-ciano: #57d7ff;

  --mo-escuro: var(--rare-azul-escuro);
  --mo-medio: var(--rare-azul-medio);
  --mo-ciano: #57d7ff;
  --mo-branco: var(--rare-branco);
  --mo-palido: var(--rare-azul-claro);
}

/* Tema escuro (automático do sistema ou escolhido no painel), decisão de
   30/08/2026. No escuro os TRÊS campos viram Azul Escuro: no tema claro o
   azul médio e o ciano funcionam como bloco de cor sobre superfície branca,
   mas no escuro eles brilham demais ao lado do texto e disputam com ele a
   atenção da página. O tom é aprofundado (55% preto) porque em Azul Escuro
   puro o campo seria a MESMA cor da superfície e o banner deixaria de se ler
   como um bloco.

   Com o campo escuro em toda peça, as figuras escuras — que pelo desenho só
   apareciam sobre campo ciano (§12) — perderiam o contraste. Por isso elas
   sobem para tons claros aqui: é o "adaptar os elementos de dentro". As duas
   continuam distinguíveis entre si, que é o que uma peça de campo ciano
   precisa (ela usa escuro e médio lado a lado). */
@media (prefers-color-scheme: dark) {
  :root:not([data-tema="claro"]) .motion {
    --mo-campo-escuro: color-mix(in srgb, var(--rare-azul-escuro) 55%, black);
    --mo-campo-medio: color-mix(in srgb, var(--rare-azul-escuro) 55%, black);
    --mo-campo-ciano: color-mix(in srgb, var(--rare-azul-escuro) 55%, black);

    --mo-escuro: var(--rare-azul-claro);
    --mo-medio: #57d7ff;
  }
}

:root[data-tema="escuro"] .motion {
  --mo-campo-escuro: color-mix(in srgb, var(--rare-azul-escuro) 55%, black);
  --mo-campo-medio: color-mix(in srgb, var(--rare-azul-escuro) 55%, black);
  --mo-campo-ciano: color-mix(in srgb, var(--rare-azul-escuro) 55%, black);

  --mo-escuro: var(--rare-azul-claro);
  --mo-medio: #57d7ff;
}

/* Modos de cor do painel de preferências (revistos em 30/08/2026). Eles não
   têm cinco tons distinguíveis para oferecer — nem devem ter: existem
   justamente para reduzir a paleta. Aqui ela cai para DOIS tons, não três: o
   meio-tom cinza/oliva que sobrava era o problema, porque cinza sobre preto é
   exatamente o par que quem tem baixa visão perde primeiro. Some o meio-tom;
   fica campo × figura, no contraste máximo que o modo permite.

   A regra que decide qual dos dois tons pinta o campo é uma só: o campo é
   SEMPRE o oposto da superfície da página, senão o banner some dentro dela —
   era o que acontecia com o campo preto no modo amarelo sobre preto e com o
   campo amarelo no modo preto sobre amarelo.

   Consequência aceita: dentro de uma peça, figuras de cores diferentes que se
   tocam viram uma massa só. O desenho perde a divisão interna e mantém a
   silhueta e o movimento — que é o que sobra de informação num banner
   decorativo. */

/* Superfície branca → campo preto, figuras brancas. */
:root[data-modo-cor="alto-contraste"] .motion {
  --mo-campo-escuro: #000000;
  --mo-campo-medio: #000000;
  --mo-campo-ciano: #000000;

  --mo-escuro: #ffffff;
  --mo-medio: #ffffff;
  --mo-ciano: #ffffff;
  --mo-branco: #ffffff;
  --mo-palido: #ffffff;
}

/* Superfície preta → campo amarelo, figuras pretas. */
:root[data-modo-cor="amarelo-preto"] .motion {
  --mo-campo-escuro: #ffe94e;
  --mo-campo-medio: #ffe94e;
  --mo-campo-ciano: #ffe94e;

  --mo-escuro: #000000;
  --mo-medio: #000000;
  --mo-ciano: #000000;
  --mo-branco: #000000;
  --mo-palido: #000000;
}

/* Superfície amarela → campo preto, figuras amarelas. */
:root[data-modo-cor="preto-amarelo"] .motion {
  --mo-campo-escuro: #000000;
  --mo-campo-medio: #000000;
  --mo-campo-ciano: #000000;

  --mo-escuro: #ffe94e;
  --mo-medio: #ffe94e;
  --mo-ciano: #ffe94e;
  --mo-branco: #ffe94e;
  --mo-palido: #ffe94e;
}

/* ---------- Prancha ---------- */

/* O banner preenche o espaço de imagem que o recebe. Ele é absoluto para que
   a altura seja sempre definida pelo contêiner (que já tem proporção ou
   altura mínima), e não pelo conteúdo — condição do container query abaixo. */
.hero__figura:has(> .motion),
.card__figura:has(> .motion),
.card-destaque__figura:has(> .motion) {
  position: relative;
}

.motion {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.motion--fundo-escuro { background: var(--mo-campo-escuro); }
.motion--fundo-medio { background: var(--mo-campo-medio); }
.motion--fundo-ciano { background: var(--mo-campo-ciano); }

.motion__palco {
  position: absolute;
  inset-inline-start: 50%;
  inset-block-start: 50%;
  translate: -50% -50%;

  /* Sem container queries a prancha fica no tamanho de desenho e é
     recortada/centralizada pelo overflow do contêiner. */
  --u: 1px;
}

.motion--largo .motion__palco {
  inline-size: calc(588 * var(--u));
  block-size: calc(256 * var(--u));
}

.motion--secao .motion__palco {
  inline-size: calc(378.66 * var(--u));
  block-size: calc(236.66 * var(--u));
}

@supports (container-type: size) {
  .motion {
    container-type: size;
  }

  /* max() dos dois eixos = cobrir: a prancha nunca deixa faixa vazia. */
  .motion--largo .motion__palco {
    --u: max(calc(100cqw / 588), calc(100cqh / 256));
  }

  .motion--secao .motion__palco {
    --u: max(calc(100cqw / 378.66), calc(100cqh / 236.66));
  }
}

/* Perspectiva (14 · Metodologia): as peças giram no eixo Y. */
.motion--perspectiva .motion__palco {
  perspective: calc(800 * var(--u));
}

/* ---------- Peças ----------
   .motion__peca posiciona pelo desenho (--x, --y, --w, --h);
   .motion__cel só dimensiona (a posição vem da grade ou da faixa). */

.motion__peca,
.motion__cel {
  inline-size: calc(var(--w) * var(--u));
  block-size: calc(var(--h) * var(--u));
  flex: none;
}

.motion__peca {
  position: absolute;
  inset-inline-start: calc(var(--x) * var(--u));
  inset-block-start: calc(var(--y) * var(--u));
}

.motion__cel--centro {
  align-self: center;
}

/* ---------- Formas ----------
   Só três primitivas, como pede o desenho: círculo, semicírculo e quadrado
   (o quadrado é o estado sem classe). O raio é o menor lado da peça, que é o
   que produz meia-circunferência exata em qualquer proporção. */
.motion__peca,
.motion__cel {
  --mo-raio: calc(min(var(--w), var(--h)) * var(--u));
}

.mo-circulo { border-radius: 50%; }

.mo-semi--cima { border-radius: var(--mo-raio) var(--mo-raio) 0 0; }
.mo-semi--baixo { border-radius: 0 0 var(--mo-raio) var(--mo-raio); }
.mo-semi--esq { border-radius: var(--mo-raio) 0 0 var(--mo-raio); }
.mo-semi--dir { border-radius: 0 var(--mo-raio) var(--mo-raio) 0; }

/* Quarto de círculo, pelo canto arredondado (noroeste, nordeste, …). */
.mo-quarto--no { border-radius: var(--mo-raio) 0 0 0; }
.mo-quarto--ne { border-radius: 0 var(--mo-raio) 0 0; }
.mo-quarto--se { border-radius: 0 0 var(--mo-raio) 0; }
.mo-quarto--so { border-radius: 0 0 0 var(--mo-raio); }

/* ---------- Cores das peças ---------- */
.mo-cor--escuro { background: var(--mo-escuro); }
.mo-cor--medio { background: var(--mo-medio); }
.mo-cor--ciano { background: var(--mo-ciano); }
.mo-cor--branco { background: var(--mo-branco); }
.mo-cor--palido { background: var(--mo-palido); }

/* ---------- Grade (06, 11, 13, 18) ---------- */
.motion__grade {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(var(--colunas), calc(var(--cw) * var(--u)));
  grid-template-rows: repeat(var(--linhas), calc(var(--ch) * var(--u)));
  gap: calc(var(--gap) * var(--u));
  align-content: center;
  justify-content: center;
}

/* ---------- Faixa contínua (P2, 07, 15) ----------
   A caixa recorta; o trilho desliza. O trilho traz DUAS cópias da sequência,
   e a animação o desloca em -50%: no fim do ciclo a segunda cópia está
   exatamente onde a primeira começou, então o laço não tem emenda visível. */
.motion__caixa {
  position: absolute;
  inset-inline-start: calc(var(--x) * var(--u));
  inset-block-start: calc(var(--y) * var(--u));
  inline-size: calc(var(--w) * var(--u));
  block-size: calc(var(--h) * var(--u));
  overflow: hidden;
}

.motion__trilho {
  display: flex;
  align-items: center;
  inline-size: max-content;
}

.motion__trilho > * {
  margin-inline-end: calc(var(--esp) * var(--u));
}

.motion__trilho--v {
  flex-direction: column;
  inline-size: auto;
  block-size: max-content;
}

.motion__trilho--v > * {
  margin-inline-end: 0;
  margin-block-end: calc(var(--esp) * var(--u));
}

/* ============================================================
   Movimento

   Duração em --d e atraso em --a, ambos em segundos e sem unidade (o
   atraso é negativo para escalonar as peças já dentro do ciclo, sem
   nenhuma esperar para começar). Curva padrão cubic-bezier(.7,0,.2,1):
   sai e chega devagar, sem solavanco.
   ============================================================ */
.mo-anim {
  animation-duration: calc(var(--d, 5) * 1s);
  animation-delay: calc(var(--a, 0) * 1s);
  animation-iteration-count: infinite;
  animation-timing-function: cubic-bezier(0.7, 0, 0.2, 1);
}

/* Rotação */
.mo-gira { animation-name: moGira; }
.mo-gira-inv { animation-name: moGiraInv; }
.mo-vira { animation-name: moVira; }
.mo-vira-y { animation-name: moViraY; }

@keyframes moGira {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

@keyframes moGiraInv {
  from { transform: rotate(0deg); }
  to { transform: rotate(-360deg); }
}

@keyframes moVira {
  0%, 14% { transform: rotate(0deg); }
  42%, 64% { transform: rotate(180deg); }
  92%, 100% { transform: rotate(360deg); }
}

@keyframes moViraY {
  0%, 14% { transform: rotateY(0deg); }
  46%, 64% { transform: rotateY(180deg); }
  96%, 100% { transform: rotateY(360deg); }
}

/* Respiração e flutuação — curva simétrica, movimento de vaivém */
.mo-flutua {
  animation-name: moFlutua;
  animation-timing-function: cubic-bezier(0.45, 0, 0.55, 1);
}

.mo-respira {
  animation-name: moRespira;
  animation-timing-function: cubic-bezier(0.5, 0, 0.5, 1);
}

@keyframes moFlutua {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(calc(-18 * var(--u))); }
}

@keyframes moRespira {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.18); }
}

/* Separar e reunir (P3) */
.mo-parte-esq { animation-name: moParteEsq; }
.mo-parte-dir { animation-name: moParteDir; }

@keyframes moParteEsq {
  0%, 8% { transform: translateX(0); }
  46%, 58% { transform: translateX(calc(-34 * var(--u))); }
  96%, 100% { transform: translateX(0); }
}

@keyframes moParteDir {
  0%, 8% { transform: translateX(0); }
  46%, 58% { transform: translateX(calc(34 * var(--u))); }
  96%, 100% { transform: translateX(0); }
}

/* Faixa contínua */
.mo-faixa-x {
  animation-name: moFaixaX;
  animation-timing-function: linear;
}

.mo-faixa-y {
  animation-name: moFaixaY;
  animation-timing-function: linear;
}

.mo-faixa--inversa { animation-direction: reverse; }

@keyframes moFaixaX {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@keyframes moFaixaY {
  from { transform: translateY(0); }
  to { transform: translateY(-50%); }
}

/* Metamorfoses de forma. O estado base repete o quadro 0% para que a
   composição parada (movimento reduzido) seja a desenhada. */
.mo-morfa {
  animation-name: moMorfa;
  border-radius: 50%;
}

.mo-canto {
  animation-name: moCanto;
  border-radius: 100% 0 0 0;
}

.mo-flexivel {
  animation-name: moFlexivel;
  border-radius: 0;
}

@keyframes moMorfa {
  0%, 10% { border-radius: 50%; }
  46%, 60% { border-radius: 0%; }
  96%, 100% { border-radius: 50%; }
}

@keyframes moCanto {
  0%, 16% { border-radius: 100% 0 0 0; }
  25%, 41% { border-radius: 0 100% 0 0; }
  50%, 66% { border-radius: 0 0 100% 0; }
  75%, 91% { border-radius: 0 0 0 100%; }
  100% { border-radius: 100% 0 0 0; }
}

@keyframes moFlexivel {
  0%, 10% { border-radius: 0%; }
  28%, 38% { border-radius: 50%; }
  56%, 66% { border-radius: 100% 100% 0 0; }
  84%, 100% { border-radius: 0%; }
}

/* Deslocamentos */
.mo-diagonal { animation-name: moDiagonal; }
.mo-pupila { animation-name: moPupila; }
.mo-converge { animation-name: moConverge; }
.mo-sobe { animation-name: moSobe; }

@keyframes moDiagonal {
  0%, 8% { transform: translate(0, 0); }
  46%, 58% { transform: translate(calc(48 * var(--u)), calc(36 * var(--u))); }
  96%, 100% { transform: translate(0, 0); }
}

@keyframes moPupila {
  0%, 6% { transform: translateX(calc(-26 * var(--u))); }
  46%, 56% { transform: translateX(calc(26 * var(--u))); }
  96%, 100% { transform: translateX(calc(-26 * var(--u))); }
}

/* --dx e --dy são números do desenho, declarados na própria peça. */
@keyframes moConverge {
  0%, 10% { transform: translate(0, 0); }
  46%, 62% { transform: translate(calc(var(--dx) * var(--u)), calc(var(--dy) * var(--u))); }
  96%, 100% { transform: translate(0, 0); }
}

@keyframes moSobe {
  0%, 12% { transform: translateY(0) scale(1); }
  46%, 64% { transform: translateY(calc(-46 * var(--u))) scale(1.34); }
  94%, 100% { transform: translateY(0) scale(1); }
}

/* Escala e leque */
.mo-cresce { animation-name: moCresce; }
.mo-leque { animation-name: moLeque; }

@keyframes moCresce {
  0%, 30% { transform: scale(1); }
  46%, 56% { transform: scale(0); }
  72%, 100% { transform: scale(1); }
}

/* --rot é o ângulo de abertura da peça, declarado nela. */
@keyframes moLeque {
  0%, 14% { transform: rotate(0deg); }
  46%, 62% { transform: rotate(var(--rot, 0deg)); }
  94%, 100% { transform: rotate(0deg); }
}

/* ---------- Eixos de rotação ---------- */
.mo-eixo--base { transform-origin: bottom center; }
.mo-eixo--topo { transform-origin: top center; }
.mo-eixo--esq { transform-origin: left center; }
