/* anim.effects.css — animations ON/OFF controlled by html.anim-off */

/*
  FIX (Requested):
  - Remove the "dust / powder" overlay layer.
  - Animate the REAL background itself (4 colors moving).
  - Keep existing tree/link/node animations below.
*/

html:not(.anim-off):not(.no-anim){ position: relative; }

/* Animated background directly on <body> (no pseudo overlays) */
html:not(.anim-off) body{
  background: linear-gradient(120deg, var(--bg1), var(--bg2), var(--bg3), var(--bg4));
  background-size: 320% 320%;
  animation-name: var(--bgAnim, bgShift4);
  animation-duration: var(--bgDur, 14s);
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}

@keyframes bgShift4{
  0%   { background-position: 0% 20%; }
  50%  { background-position: 100% 80%; }
  100% { background-position: 0% 20%; }
}

/* Optional darker veil so UI always reads well */
html:not(.anim-off) body::before{
  content:"";
  position: fixed;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(1200px 800px at 50% 40%, rgba(0,0,0,.10), rgba(0,0,0,.42));
  z-index: 0;
}

/* Keep app above veil */
html:not(.anim-off) body > *{ position: relative; z-index: 1; }

/* Respect reduced motion */
@media (prefers-reduced-motion: reduce){
  html:not(.anim-off) body{ animation: none; }
}

/* ON: smooth transitions across UI */
html:not(.anim-off) .btn,
html:not(.anim-off) button,
html:not(.anim-off) a,
html:not(.anim-off) .card,
html:not(.anim-off) .panel,
html:not(.anim-off) .modal,
html:not(.anim-off) input,
html:not(.anim-off) select,
html:not(.anim-off) textarea{
  transition: transform .14s ease, box-shadow .14s ease, opacity .14s ease,
              background-color .20s ease, color .20s ease, border-color .20s ease;
}

/* ON: micro hover */
html:not(.anim-off) .btn:hover,
html:not(.anim-off) button:hover{
  transform: translateY(-1px);
  box-shadow: 0 10px 22px rgba(0,0,0,.28);
}

/* ON: gentle lift on cards/panels when hovered */
html:not(.anim-off) .card:hover,
html:not(.anim-off) .panel:hover,
html:not(.anim-off) .modal-card:hover{
  transform: translateY(-1px);
}

/* ON: gentle “pop” for toast if exists */
html:not(.anim-off) .toast,
html:not(.anim-off) .bubble,
html:not(.anim-off) #toast{
  animation: toastIn .18s ease-out;
}

@keyframes toastIn{
  from{ transform: translateY(8px); opacity: 0; }
  to  { transform: translateY(0); opacity: 1; }
}

/* OFF: hard stop */
html.anim-off *,
html.anim-off *::before,
html.anim-off *::after{
  animation: none !important;
  transition: none !important;
  scroll-behavior: auto !important;
}

/* ===== Tree branch-by-branch LOOP animation =====
   Draw -> hold -> reset (repeats). Stagger controlled via inline animation-delay from JS.
*/
@keyframes linkFlow {
  /* extra-slow + clear "___ ___ ___" rhythm */
  0%   { stroke-dashoffset: var(--dash, 999); opacity: 0.08; }
  14%  { opacity: 1; }
  58%  { stroke-dashoffset: 0; opacity: 1; }   /* draw */
  86%  { stroke-dashoffset: 0; opacity: 1; }   /* hold */
  100% { stroke-dashoffset: var(--dash, 999); opacity: 0.08; } /* reset */
}

/* dotted “droplets” traveling along the branch while it draws */
@keyframes linkDots {
  0%   { opacity: 0; stroke-dashoffset: 0; }
  14%  { opacity: .95; }
  62%  { opacity: .95; stroke-dashoffset: -160; }
  86%  { opacity: 0; }
  100% { opacity: 0; stroke-dashoffset: -220; }
}

@keyframes nodeBloom {
  /* Bloom without "jumping" (keep in place) */
  0%   { transform: scale(.92); opacity: .35; filter: drop-shadow(0 0 0 rgba(0,0,0,0)); }
  52%  { transform: scale(.92); opacity: .35; }
  68%  { transform: scale(1.06); opacity: 1;  filter: drop-shadow(0 0 12px rgba(255,255,255,.22)) drop-shadow(0 0 18px rgba(34,211,238,.28)); }
  84%  { transform: scale(1.00); opacity: 1;  filter: drop-shadow(0 0 16px rgba(34,211,238,.34)); }
  100% { transform: scale(.94); opacity: .45; filter: drop-shadow(0 0 0 rgba(0,0,0,0)); }
}

.link.link-anim{
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 2px 6px rgba(0,0,0,.22));
  animation: linkFlow 18s ease-in-out infinite;
}

/* overlay dotted path (created by JS as a clone) */
.link.link-dots{
  fill: none;
  pointer-events: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1 14;
  filter: drop-shadow(0 2px 10px rgba(34,211,238,.20));
  animation: linkDots 18s linear infinite;
}

.nodes .node circle.node-anim{
  /* IMPORTANT: stop circles from "running away" in SVG */
  transform-box: fill-box;
  transform-origin: center;
  animation: nodeBloom 18s ease-in-out infinite;
}

/* Hover glow on node edges (the "light ring") */
.nodes .node circle{
  transition: stroke .15s ease, stroke-width .15s ease, filter .18s ease, opacity .18s ease;
}
.nodes .node:hover circle{
  stroke: rgba(255,255,255,.85) !important;
  stroke-width: 2.2 !important;
  filter: drop-shadow(0 0 10px rgba(255,255,255,.18)) drop-shadow(0 0 18px rgba(34,211,238,.30));
  opacity: 1;
}

@media (prefers-reduced-motion: reduce){
  .link.link-anim{ animation: none !important; stroke-dashoffset: 0 !important; opacity: 1 !important; }
  .nodes .node circle.node-anim{ animation: none !important; opacity: 1 !important; }
}

/* ===== Lines animation OFF: force clean white branches =====
   Users expect that disabling animations returns all branches to a neutral white.
   JS may set colored stroke inline, so we override with !important.
*/
html.anim-off .links .link{
  stroke: rgba(255,255,255,.62) !important;
  filter: none !important;
  opacity: 1 !important;
  animation: none !important;
  stroke-dasharray: none !important;
  stroke-dashoffset: 0 !important;
}
html.anim-off .links .link.link-dots{ display:none !important; }



/* Compatibility: older builds used html.no-anim */
html.no-anim{ }
