/* Small conceptual demonstrations, not live MeshLink traffic or delivery data.
   All effects stay inside existing illustrations; captions remain readable. */

#possibilities .demo-phone { isolation: isolate; }
#panel-conversations:not([hidden]) .phone-compose > span {
  animation: ml-compose-send 8.8s ease-in-out infinite;
}
#panel-conversations:not([hidden]) .demo-phone::after {
  content: '';
  position: absolute;
  z-index: 4;
  width: 5px;
  height: 5px;
  right: 26px;
  bottom: 27px;
  border-radius: 50%;
  opacity: 0;
  background: #315b46;
  box-shadow: 0 0 0 3px #79bc9024, 0 0 12px #5c9e7240;
  pointer-events: none;
  animation: ml-message-journey 8.8s cubic-bezier(.35, .1, .3, 1) infinite;
}
#panel-conversations:not([hidden]) .chat-bubble.sent {
  animation: ml-message-send 8.8s ease-in-out infinite;
}
#panel-conversations:not([hidden]) .chat-bubble.sent > span {
  display: inline-block;
  animation: ml-receipt 8.8s ease-in-out infinite;
}
#panel-conversations:not([hidden]) .phone-header small i {
  animation: ml-room-presence 4.4s ease-in-out infinite;
}
#panel-conversations:not([hidden]) .phone-map svg path {
  animation: ml-phone-route 8.8s linear infinite;
}
#panel-conversations:not([hidden]) .phone-map svg circle {
  transform-box: fill-box;
  transform-origin: center;
  animation: ml-map-arrival 8.8s ease-in-out infinite;
}
#panel-conversations:not([hidden]) .phone-map svg circle:last-child {
  animation-delay: -.7s;
}
#panel-conversations:not([hidden]) .location-message > span {
  transform-origin: 50% 75%;
  animation: ml-location-share 8.8s ease-in-out infinite;
}

@keyframes ml-compose-send {
  0%, 8%, 29%, 100% { transform: none; box-shadow: 0 0 0 0 #31534200; }
  16% { transform: translateY(-2px); box-shadow: 0 0 0 6px #31534212; }
  22% { transform: none; box-shadow: 0 0 0 10px #31534200; }
}
@keyframes ml-message-journey {
  0%, 13% { right: 26px; bottom: 27px; opacity: 0; transform: scale(.6); }
  19% { right: 26px; bottom: 34px; opacity: .9; transform: scale(1); }
  37% { right: 17px; bottom: 36%; opacity: .9; }
  51% { right: 20px; bottom: 62%; opacity: .8; }
  65% { right: 29%; bottom: 71%; opacity: .7; transform: scale(1); }
  71%, 100% { right: 29%; bottom: 71%; opacity: 0; transform: scale(1.8); }
}
@keyframes ml-message-send {
  0%, 12%, 100% { opacity: .88; transform: none; }
  19% { opacity: .8; transform: translateY(4px); }
  29%, 85% { opacity: 1; transform: none; }
}
@keyframes ml-receipt {
  0%, 53%, 100% { opacity: .5; color: #b1c5ac; transform: none; }
  64% { opacity: 1; color: #c3f1c8; transform: scale(1.18); }
  73%, 88% { opacity: 1; color: #c3f1c8; transform: none; }
}
@keyframes ml-room-presence {
  0%, 100% { box-shadow: 0 0 0 0 #46785600; }
  45% { box-shadow: 0 0 0 3px #46785616; }
  75% { box-shadow: 0 0 0 5px #46785600; }
}
@keyframes ml-phone-route { to { stroke-dashoffset: -56; } }
@keyframes ml-map-arrival {
  0%, 49%, 83%, 100% { transform: scale(1); }
  64% { transform: scale(1.22); }
}
@keyframes ml-location-share {
  0%, 63%, 86%, 100% { transform: none; }
  71% { transform: translateY(-3px) rotate(-6deg); }
  78% { transform: none; }
}

/* A traced route and an observer-centred sweep make the difference between
   travelling a line and looking over an area legible without extra labels. */
#panel-terrain .terrain-illustration { isolation: isolate; }
#panel-terrain .topography { z-index: 0; }
#panel-terrain .terrain-illustration svg { z-index: 2; }
#panel-terrain .map-label { z-index: 4; }
#panel-terrain .terrain-illustration::before {
  content: '';
  position: absolute;
  left: 17%;
  top: 15%;
  width: 57%;
  height: 70%;
  z-index: 1;
  border-radius: 50%;
  opacity: .4;
  background: conic-gradient(from 0deg, transparent 0deg 284deg, #d6f3bb05 294deg, #d6f3bb33 346deg, #d6f3bb6b 359deg, transparent 360deg);
  -webkit-mask-image: radial-gradient(closest-side, #000 6%, #0009 65%, transparent 100%);
  mask-image: radial-gradient(closest-side, #000 6%, #0009 65%, transparent 100%);
  pointer-events: none;
}
#panel-terrain:not([hidden]) .terrain-illustration::before {
  animation: ml-viewshed-sweep 10s linear infinite;
}
#panel-terrain:not([hidden]) .terrain-illustration svg > circle:first-of-type {
  transform-box: fill-box;
  transform-origin: center;
  animation: ml-coverage-breathe 10s ease-in-out infinite;
}
#panel-terrain:not([hidden]) .terrain-illustration svg > path:first-of-type {
  animation: ml-terrain-route 10s linear infinite;
}
#panel-terrain:not([hidden]) .terrain-illustration svg > path:nth-of-type(2) {
  stroke-dasharray: 230;
  animation: ml-sight-line 10s ease-in-out infinite;
}
#panel-terrain:not([hidden]) .terrain-illustration svg > circle:last-child {
  transform-box: fill-box;
  transform-origin: center;
  animation: ml-observer 5s ease-in-out infinite;
}
@keyframes ml-viewshed-sweep { to { transform: rotate(360deg); } }
@keyframes ml-terrain-route { to { stroke-dashoffset: -110; } }
@keyframes ml-coverage-breathe {
  0%, 100% { opacity: .65; transform: scale(.94); }
  50% { opacity: 1; transform: scale(1.025); }
}
@keyframes ml-sight-line {
  0%, 9%, 100% { stroke-dashoffset: 230; opacity: .35; }
  30%, 76% { stroke-dashoffset: 0; opacity: 1; }
  89% { stroke-dashoffset: 0; opacity: .35; }
}
@keyframes ml-observer {
  0%, 100% { transform: scale(1); opacity: .85; }
  45% { transform: scale(1.18); opacity: 1; }
}

/* Quiet orbiting points surround a stable, always visible privacy core. */
#panel-control .privacy-illustration { perspective: 650px; }
#panel-control .privacy-orbit::after {
  content: '';
  position: absolute;
  top: -3px;
  left: calc(50% - 3px);
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #d2ecc1;
  box-shadow: 0 0 13px #c8ecad80;
  pointer-events: none;
}
#panel-control .orbit-two::after { background: #f0be8d; box-shadow: 0 0 13px #efb37c60; }
#panel-control .orbit-three::after { width: 4px; height: 4px; top: -2px; opacity: .65; }
#panel-control:not([hidden]) .orbit-one { animation: ml-privacy-orbit-one 17s linear infinite; }
#panel-control:not([hidden]) .orbit-two { animation: ml-privacy-orbit-two 23s linear infinite; }
#panel-control:not([hidden]) .orbit-three { animation: ml-privacy-orbit-three 29s linear infinite; }
#panel-control:not([hidden]) .privacy-core { animation: ml-privacy-core 7s ease-in-out infinite; }
#panel-control:not([hidden]) .privacy-core svg path:nth-child(2) {
  stroke-dasharray: 38;
  animation: ml-private-check 7s ease-in-out infinite;
}
@keyframes ml-privacy-orbit-one {
  from { transform: rotateX(54deg) rotateY(20deg) rotateZ(0); }
  to { transform: rotateX(54deg) rotateY(20deg) rotateZ(360deg); }
}
@keyframes ml-privacy-orbit-two {
  from { transform: rotateX(20deg) rotateY(62deg) rotateZ(360deg); }
  to { transform: rotateX(20deg) rotateY(62deg) rotateZ(0); }
}
@keyframes ml-privacy-orbit-three { to { transform: rotate(360deg); } }
@keyframes ml-privacy-core {
  0%, 100% { box-shadow: 0 0 45px #b4d2ac0c; border-color: #bcdab336; }
  50% { box-shadow: 0 0 75px #b4d2ac27; border-color: #c6e0b96b; }
}
@keyframes ml-private-check {
  0%, 8%, 100% { stroke-dashoffset: 0; opacity: .7; }
  20% { stroke-dashoffset: 38; opacity: .4; }
  39%, 80% { stroke-dashoffset: 0; opacity: 1; }
}

/* Only occupied seats glow: this does not imply that every place is taken. */
#rooms .seat.occupied::before { animation: ml-room-join 8s ease-in-out infinite; }
#rooms .seat.occupied:nth-child(5n + 1)::before { animation-delay: -.2s; }
#rooms .seat.occupied:nth-child(5n + 2)::before { animation-delay: -.8s; }
#rooms .seat.occupied:nth-child(5n + 3)::before { animation-delay: -1.4s; }
#rooms .seat.occupied:nth-child(5n + 4)::before { animation-delay: -2s; }
#rooms .seat.occupied:nth-child(5n)::before { animation-delay: -2.6s; }
@keyframes ml-room-join {
  0%, 42%, 100% { opacity: .75; box-shadow: 0 0 5px #d2e9bd55; transform: scale(1); }
  20% { opacity: 1; box-shadow: 0 0 10px #d2e9bd, 0 0 0 4px #d2e9bd16; transform: scale(1.18); }
}

/* Hidden tabs do no animation work. The global pause freezes the conceptual
   diagrams at their current frame, just like the 3D world. */
#possibilities .feature-panel[hidden] *,
#possibilities .feature-panel[hidden] *::before,
#possibilities .feature-panel[hidden] *::after { animation: none !important; }
#possibilities .feature-stage:not(.visible) *,
#possibilities .feature-stage:not(.visible) *::before,
#possibilities .feature-stage:not(.visible) *::after,
#rooms .rooms-inner:not(.visible) *,
#rooms .rooms-inner:not(.visible) *::before,
#rooms .rooms-inner:not(.visible) *::after,
html[data-motion='paused'] #possibilities *,
html[data-motion='paused'] #possibilities *::before,
html[data-motion='paused'] #possibilities *::after,
html[data-motion='paused'] #rooms .seat::before { animation-play-state: paused !important; }

@media (prefers-reduced-motion: reduce) {
  #possibilities .feature-panel *,
  #possibilities .feature-panel *::before,
  #possibilities .feature-panel *::after,
  #rooms .seat::before { animation: none !important; }
  #panel-conversations .demo-phone::after,
  #panel-terrain .terrain-illustration::before { display: none; }
}
