/* ======================================================================
   MOTION AND SEQUENCE STATES
   Timing values that control the narrative live in scripts/config.js.
   ====================================================================== */
.agent-route { animation: routeDrift 7s linear infinite; }
.answer-route { animation: routeDrift 6.3s linear infinite; }
.writeback-route { animation: reverseRouteDrift 8.4s linear infinite; }
.registrar-writeback-route { animation: routeDrift 7.6s linear infinite; }
.typed-copy::after { animation: cursorBlink .82s steps(1) infinite; }

.canvas.query-ready .click-ring { animation: clickRipple .7s var(--ease) both; }
.canvas.query-ready .query-box-frame {
  animation: queryBoxConfirm var(--box-pulse-duration, .52s) ease-out both;
}
.canvas.query-ready .query-box-pulse {
  animation: queryBoxPulse var(--box-pulse-duration, .52s) ease-out both;
}
.canvas.query-ready .query-box-merge {
  animation: queryBoxMerge var(--box-pulse-duration, .52s) ease-out both;
}
.canvas.handoff-active .query-box-merge {
  animation: queryBoxRelease .16s ease-out both;
}
.canvas.handoff-active .query-resolver-link { opacity: .30; }
.canvas.handoff-active .query-resolver-trail {
  animation: queryTrailTravel var(--handoff-duration, .72s) ease-out both;
}
.canvas.handoff-active .query-handoff-signal {
  animation: querySignalTravel var(--handoff-duration, .72s) ease-out both;
}
.canvas.system-active .active-route {
  opacity: var(--active-route-opacity);
  stroke-width: var(--active-route-width);
}

.canvas.system-active .memory-node.selected {
  opacity: var(--active-opacity, .90) !important;
}

.canvas.system-active .workset-node {
  animation: worksetBreathe 5.2s var(--pulse-delay, 0s) ease-in-out infinite;
}

.canvas.system-active .workset-node-halo {
  animation: worksetHaloBreathe 5.2s var(--pulse-delay, 0s) ease-in-out infinite;
}

.canvas.system-active .processor-core {
  animation: processorBreathe 4.6s var(--agent-delay, 0s) ease-in-out infinite;
}

.arrival-glow.is-arriving { animation: arrivalPulse .46s ease-out both; }

.memory-interaction-ring.signal-impact.is-interacting {
  animation: memorySignalImpactOnce .40s ease-out both;
}

.memory-interaction-ring.signal-emergence.is-interacting {
  animation: memorySignalEmergenceOnce .42s ease-out both;
}

.canvas.system-active .answer-route { opacity: .48; }

.canvas.answer-generating .answer-line,
.canvas.answer-generating .answer-accent {
  animation: lineReveal .66s var(--line-delay, 0s) var(--ease) forwards;
}

.canvas.answer-generating .citation-dot {
  animation:
    citationReveal .55s var(--cite-delay, 0s) var(--ease) forwards,
    citationBreathe 3.8s calc(var(--cite-delay, 0s) + .8s) ease-in-out infinite;
}

.canvas.answer-generating .registrar-writeback-route { opacity: .42; }

@keyframes cursorBlink {
  0%, 48% { opacity: 1; }
  49%, 100% { opacity: 0; }
}

@keyframes clickRipple {
  0% { opacity: 0; transform: scale(.35); }
  18% { opacity: .85; transform: scale(.55); }
  100% { opacity: 0; transform: scale(2.25); }
}

@keyframes queryBoxConfirm {
  0% { stroke: rgba(247,251,255,.24); }
  42% { stroke: rgba(247,251,255,.56); }
  100% { stroke: rgba(247,251,255,.30); }
}

@keyframes queryBoxPulse {
  0% { opacity: 0; stroke-dashoffset: 0; }
  12% { opacity: 1; }
  90% { opacity: .96; }
  100% { opacity: 0; stroke-dashoffset: -81; }
}

@keyframes queryBoxMerge {
  0%, 68% { opacity: 0; transform: scale(.45); }
  86% { opacity: .78; transform: scale(.82); }
  100% { opacity: 1; transform: scale(1); }
}

@keyframes queryBoxRelease {
  0% { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(.72); }
}

@keyframes queryTrailTravel {
  0% { opacity: 0; stroke-dashoffset: 100; }
  16% { opacity: .96; }
  82% { opacity: .82; }
  100% { opacity: 0; stroke-dashoffset: -28; }
}

@keyframes querySignalTravel {
  0%, 82% { opacity: 1; }
  100% { opacity: 0; }
}

@keyframes routeDrift { to { stroke-dashoffset: -92; } }
@keyframes reverseRouteDrift { to { stroke-dashoffset: 102; } }

@keyframes worksetBreathe {
  0%, 100% { opacity: var(--node-low-opacity, .58); }
  50% { opacity: var(--node-high-opacity, .94); }
}

@keyframes worksetHaloBreathe {
  0%, 100% { opacity: var(--halo-low-opacity, .5); transform: scale(.94); }
  50% { opacity: var(--halo-opacity, .7); transform: scale(1.05); }
}

@keyframes processorBreathe {
  0%, 100% { opacity: .62; transform: scale(.94); }
  50% { opacity: 1; transform: scale(1.10); }
}

@keyframes arrivalPulse {
  0%, 74% { opacity: 0; transform: scale(.5); }
  84% { opacity: .24; transform: scale(1); }
  100% { opacity: 0; transform: scale(2.5); }
}

@keyframes memorySignalImpactOnce {
  0% { opacity: .28; }
  16% { opacity: .88; }
  64% { opacity: .60; }
  100% { opacity: 0; }
}

@keyframes memorySignalEmergenceOnce {
  0% { opacity: .84; }
  58% { opacity: .52; }
  100% { opacity: 0; }
}

@keyframes lineReveal {
  0% { opacity: 0; transform: scaleX(0); }
  100% { opacity: 1; transform: scaleX(1); }
}

@keyframes citationReveal {
  0% { opacity: 0; transform: scale(.45); }
  100% { opacity: .85; transform: scale(1); }
}

@keyframes citationBreathe {
  0%, 100% { opacity: .52; transform: scale(.86); }
  50% { opacity: .95; transform: scale(1.12); }
}

@media (prefers-reduced-motion: reduce) {
  .signal-particle { display: none; }
  .physics-node { transition: none; }
  .agent-route,
  .answer-route,
  .writeback-route,
  .typed-copy::after { animation: none; }

  .canvas.system-active .workset-node,
  .canvas.system-active .workset-node-halo,
  .canvas.system-active .processor-core,
  .canvas.system-active .arrival-glow,
  .canvas.answer-generating .citation-dot { animation: none; }

  .query-resolver-trail,
  .query-handoff-signal,
  .query-box-pulse,
  .query-box-merge,
  .memory-interaction-ring { display: none; }
}
