/* Town motion is a different material from travel motion: one arrival settle,
   then long, low-amplitude loops that make a stop feel inhabited. */
.twMode .twLife{position:absolute;inset:0;z-index:2;overflow:hidden;pointer-events:none}

/* A person takes almost a minute to cross the road plane. The six-frame walk
   carries scale; the long translation keeps it subordinate to the choices. */
.twMode .twWalker{position:absolute;left:0;bottom:138px;width:36px;height:72px;
  background:url('assets/fx/walk-v2.webp') 0 0/600% 100% no-repeat;
  filter:brightness(.72) saturate(.72) drop-shadow(0 3px 4px rgba(0,0,0,.45));
  animation:twWalk 1.28s steps(5) infinite,twCross 38s linear infinite}
@keyframes twWalk{to{background-position:100% 0}}
@keyframes twCross{from{transform:translate3d(628px,0,0)}to{transform:translate3d(1030px,0,0)}}

/* The tailpipe is the one continuous machine cue while parked. Three puffs
   share a long cycle and spend most of it invisible. */
.twMode .twExhaust{position:absolute;left:288px;top:248px;width:54px;height:38px}
.twMode .twExhaust u{position:absolute;left:9px;bottom:3px;width:8px;height:8px;
  border-radius:50%;background:rgba(202,210,211,.42);filter:blur(.7px);
  animation:twSmoke 6.6s cubic-bezier(.2,.65,.3,1) infinite}
.twMode .twExhaust u:nth-child(2){animation-delay:-4.4s}
.twMode .twExhaust u:nth-child(3){animation-delay:-2.2s}
@keyframes twSmoke{0%,68%,100%{opacity:0;transform:translate3d(0,0,0) scale(.55)}
  7%{opacity:.54}30%{opacity:.20;transform:translate3d(-25px,-15px,0) scale(1.35)}
  42%{opacity:0;transform:translate3d(-37px,-23px,0) scale(1.7)}}

/* Arrival is a single 680ms suspension settle. Dust is bounded to the wheels
   and disappears; routine town re-renders do not replay it. */
.twMode.twArrive>.truck{animation:twTruckSettle .68s cubic-bezier(.16,1,.3,1) both}
.twMode.twArrive>.s2-crew{animation:twCrewSettle .68s cubic-bezier(.16,1,.3,1) both}
@keyframes twTruckSettle{from{transform:translate3d(15px,-4px,0) rotate(.5deg)}
  68%{transform:translate3d(-1px,1px,0) rotate(-.08deg)}to{transform:translate3d(0,0,0) rotate(0)}}
@keyframes twCrewSettle{from{transform:translate3d(15px,-4px,0) rotate(.5deg)}
  68%{transform:translate3d(-1px,1px,0) rotate(-.08deg)}to{transform:translate3d(0,0,0) rotate(0)}}
.twMode .twDust{position:absolute;left:295px;top:244px;width:318px;height:48px;opacity:0}
.twMode.twArrive .twDust{animation:twDustCloud .76s ease-out both}
.twMode .twDust u{position:absolute;bottom:0;width:62px;height:28px;border-radius:50%;
  background:rgba(190,163,116,.38);filter:blur(5px)}
.twMode .twDust u:nth-child(1){left:7px}.twMode .twDust u:nth-child(2){left:112px;width:82px}
.twMode .twDust u:nth-child(3){right:5px;width:72px}
@keyframes twDustCloud{0%{opacity:.72;transform:translate3d(12px,0,0) scale(.7)}
  38%{opacity:.48}100%{opacity:0;transform:translate3d(-18px,-8px,0) scale(1.3)}}

/* Grande Prairie's main-street plate has a much lower foreground plane than
   the highway plates. Seat the actors on that plane; otherwise both the truck
   and the pedestrian hover a full wheel-height above the storefront road. */
html[data-scene="grandeprairie"] .twMode>.truck{top:178px}
html[data-scene="grandeprairie"] .twMode>.s2-crew.parked{top:217px}
html[data-scene="grandeprairie"] .twMode .twWalker{bottom:96px}
html[data-scene="grandeprairie"] .twMode .twExhaust{top:290px}
html[data-scene="grandeprairie"] .twMode .twDust{top:286px}

/* Alberta wind touches the roadside object, not every panel on the screen. */
.twMode .sign{transform-origin:50% 118%;animation:twSignWind 8.2s ease-in-out infinite alternate}
@keyframes twSignWind{from{transform:rotate(-.12deg)}to{transform:rotate(.18deg)}}

.twMode.twLifePause .twLife *,.twMode.twLifePause .sign{animation-play-state:paused}

@media (prefers-reduced-motion:reduce){
  .twMode .twWalker,.twMode .twExhaust u,.twMode .twDust,.twMode .sign,
  .twMode.twArrive>.truck,.twMode.twArrive>.s2-crew{animation:none!important}
  .twMode .twWalker,.twMode .twExhaust,.twMode .twDust{display:none}
}
