/* ==========================================================================
   DO BIT AO CAMPO — o campo e a rede CAN
   Mesma geometria e mesma entrada animada da abertura das aulas
   (curso/04_producao/tools/animar.py: _campo_geometria, campo_escuro_svg,
   fundo_campo, capa_html e __intro, marcas para 4 s):
     sol e céu 0–1 s · morro 0,15 s · crista 0,1–1,3 s · sulcos a partir de 0,3 s
     (0,08 s entre eles) · fazenda 0,9 s · fio reto · linhas CAN · pulso que
     percorre a rede em 1 s e acende cada nó quando passa por ele.
   Depois da entrada: o sol respira, um reflexo corre devagar por três sulcos
   e o pulso volta a percorrer a rede a cada 10 s.
   Os traços usam pathLength="1": stroke-dasharray 1 2 e stroke-dashoffset de
   1 (escondido) a 0 (desenhado), sempre a partir da borda direita, do sol.
   ========================================================================== */

.campo { display: block; overflow: visible; }

/* --------------------------------------------------------------------------
   Entrada: os traços se desenham a partir do sol
   -------------------------------------------------------------------------- */
.campo .sulco path {
  stroke-dasharray: 1 2;
  animation: desenha 1.1s var(--curva) calc(0.22s + var(--i) * 0.08s) both;
}
.campo .crista path { animation-duration: 1.2s; animation-delay: 0.1s; }

.campo .morro { animation: surge 0.9s var(--curva) 0.15s both; }
.campo .fazenda { animation: fazenda 0.6s var(--curva) 0.9s both; }

.campo--escuro .ceu { animation: surge 1s var(--curva) both; }
.campo--escuro .sol {
  animation: surge 1s var(--curva) both,
             respira 7s ease-in-out 1.2s infinite alternate;
}

/* Reflexo do sol que desce pela crista e por dois sulcos, um de cada vez */
.campo .reflexo {
  stroke-dasharray: 0.12 1.88;
  stroke-dashoffset: 0.12;
  stroke-linecap: round;
  opacity: 0;
  animation: reflexo 12s linear calc(3.6s + var(--r) * 4s) infinite;
}

.leque path {
  stroke-dasharray: 1 2;
  animation: desenha 0.9s var(--curva) calc(0.3s + var(--i) * 0.0167s) both;
}

@keyframes desenha {
  from { stroke-dashoffset: 1; }
  to   { stroke-dashoffset: 0; }
}

@keyframes surge {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes fazenda {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

@keyframes respira {
  from { opacity: 1; }
  to   { opacity: 0.78; }
}

@keyframes reflexo {
  0%   { stroke-dashoffset: 0.12; opacity: 0; }
  3%   { opacity: 0.85; }
  26%  { opacity: 0.7; }
  32%  { stroke-dashoffset: -1; opacity: 0; }
  100% { stroke-dashoffset: -1; opacity: 0; }
}

/* --------------------------------------------------------------------------
   Rede CAN da abertura (capa_html): linhas, nós alternados e o pulso
   O pulso começa a 2,2 s; cada nó tem --t = (x + 20) / 1960 s, o instante em
   que o pulso chega a ele.
   -------------------------------------------------------------------------- */
.barramento path,
.barramento rect {
  fill: none;
  stroke: var(--azul-cinza);
  stroke-width: 2;
}
.barramento circle { fill: var(--cinza-claro); }
.barramento text {
  fill: var(--cinza-claro);
  font: 500 22px var(--fonte-mono);
  letter-spacing: 0.02em;
  text-anchor: middle;
}

.barramento .fio {
  stroke-dasharray: 1 2;
  animation: desenha 0.55s var(--curva) 1.8s both;
}

.barramento .no {
  animation: surge 0.25s var(--curva) calc(2.15s + var(--t)) both;
}

.barramento .no rect {
  animation: acende 0.7s linear calc(1.97s + var(--t)) 1,
             acende-ronda 10s linear calc(11.97s + var(--t)) infinite;
}

.barramento .pulso {
  opacity: 0;
  animation: pulso 1s linear 2.2s 1 both,
             pulso-ronda 10s linear 12.2s infinite;
}
.barramento .halo { fill: #7FB8F0; }
.barramento .nucleo { fill: #E6F3FF; }

@keyframes pulso {
  0%   { transform: translateX(-20px); opacity: 1; }
  88%  { opacity: 1; }
  100% { transform: translateX(1940px); opacity: 0; }
}

@keyframes pulso-ronda {
  0%   { transform: translateX(-20px); opacity: 0; }
  1%   { opacity: 1; }
  9%   { opacity: 1; }
  10%  { transform: translateX(1940px); opacity: 0; }
  100% { transform: translateX(1940px); opacity: 0; }
}

@keyframes acende {
  0%, 100% { stroke: var(--azul-cinza); fill: rgba(79, 127, 174, 0); }
  50%      { stroke: var(--azul-luz);   fill: rgba(79, 127, 174, 0.35); }
}

@keyframes acende-ronda {
  0%, 7%, 100% { stroke: var(--azul-cinza); fill: rgba(79, 127, 174, 0); }
  3.5%         { stroke: var(--azul-luz);   fill: rgba(79, 127, 174, 0.3); }
}

/* --------------------------------------------------------------------------
   Cenas: as claras só começam quando entram na tela; todas param fora dela
   -------------------------------------------------------------------------- */
.js-ativo .cena:not(.em-cena) .campo *,
.js-ativo .cena:not(.em-cena) .campo,
[data-fora="true"] .campo *,
[data-fora="true"] .barramento *,
[data-fora="true"] .leque * {
  animation-play-state: paused !important;
}

@media (prefers-reduced-motion: reduce) {
  .campo *, .barramento *, .leque * { animation: none !important; }
  .barramento .pulso, .campo .reflexo { opacity: 0; }
}
