/* Motion (late Oct 2026, the user's: "animations and transitions for every screen, with something appropriate for each"): the Bureau's files slide
   into place, a cold light sweeps, a fight cuts in hard. Short (a screen 0.2–0.35 s, a fight 0.6 s), transform and opacity where it can be, and
   nothing ever covers a tap. What keeps it to real moves: every entrance here is a CSS animation on an element that is in index.html and is only
   shown or hidden (a screen's section, the battle's parts, a dialog, a popover, a tooltip), so it plays when the element goes from hidden to shown
   and never when what's inside is redrawn (renders replace contents; the clock ticks every second; the server sends updates). app.js adds what CSS
   can't (search "motion"): the cards of a screen just opened rising in turn (those there then: a redraw's cards just appear), a tab's contents and a
   fold opening, the tile a place opens out of (--mo-o), and body[data-from], the screen you came from. Reduced motion: a screen fades, nothing else. */
@media (prefers-reduced-motion: no-preference) {
  :root { --mo-ease: cubic-bezier(.2, .8, .2, 1); --mo-band: linear-gradient(100deg, transparent, #e2f4ef1f 35%, #e2f4ef59 48%, #a8e6b866 52%, #e2f4ef1f 65%, transparent); }

  /* screens: a file slid up into place (the menu's screens, the character list, the waiting room) */
  .screen, #no-battle { animation: mo-file .26s var(--mo-ease) backwards; }
  /* a place opened from the hub opens out of the tile you pressed (app.js sets --mo-o; from the menu, out of its top) */
  :is(#shop, #craft, #cook, #meditate, #lab, #arena, #resort, #workshop, #dojo, #bounties, #guildhouse, #casino, #harbour, #forge, #woods, #mine, #circuit, #mountain, #woodshop) { transform-origin: var(--mo-o, 50% 0); animation-name: mo-enter; animation-duration: .3s; }
  /* the hub: the case file's heading drops in, the places rise in turn (app.js), the cards beside them fade up */
  #hub { animation-name: mo-fade; animation-duration: .2s; }
  #hq { animation: mo-drop .32s var(--mo-ease) backwards; }
  #hub .cols > .stack:last-child > * { animation: mo-fade .3s .08s ease-out backwards; }
  /* back out of a fight: the world fades back up, slower (the hub, or your portal) */
  body[data-from="battle"] :is(#hub, #portal) { animation: mo-fade .4s ease-in backwards; }
  /* off a plane: a cold light runs across where you are now; taking off, across the flight */
  body[data-from="flight"] #hub .hq-here::after, #flight::before { content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none; opacity: 0; background: var(--mo-band) no-repeat 0 0 / 45% 100%; animation: mo-sweep .7s .08s ease-in-out; }
  #flight { animation-name: mo-fade; animation-duration: .3s; }
  #flight::before { position: fixed; z-index: 35; }
  /* the home: its doors open from the middle; the gallery: the lights come up; a portal: it irises open */
  #home { animation: mo-door .34s var(--mo-ease) backwards; }
  #gallery { animation: mo-lights .5s ease-out backwards; }
  #portal { animation: mo-iris .45s cubic-bezier(.6, 0, .2, 1) backwards; }
  /* the jail: bars drop over it and fade (not when you're only back from the yard's Meditation or the Guide) */
  #jail { animation-name: mo-fade; }
  #jail::before { content: ''; position: fixed; inset: 0; z-index: 35; pointer-events: none; opacity: 0; background: repeating-linear-gradient(90deg, #05070a 0 12px, transparent 12px 68px); animation: mo-bars .6s cubic-bezier(.6, 0, .3, 1); }
  body:is([data-from="meditate"], [data-from="guide"]) #jail::before { content: none; }

  /* into a fight: a hard cut, no fade. The floor snaps open from a line of cold light, the heading drops and your bar comes up (0.6 s in all); the
     same when a waiting room's fight starts. Only clip-path on the floor: battle-fx.js measures where the fighters are */
  #battle { animation: none; }
  #field { animation: mo-slit .38s .05s cubic-bezier(.7, 0, .2, 1) backwards; }
  .stage-wrap:has(> #field:not([hidden]))::after { content: ''; position: absolute; inset: 0; z-index: 5; pointer-events: none; opacity: 0; border-radius: 16px; background: radial-gradient(70% 55% at 50% 50%, #e2f4efd9, #a2d7cf40 55%, transparent 80%); animation: mo-flash .55s ease-out; }
  #battle-head { animation: mo-drop .3s .15s var(--mo-ease) backwards; }
  #actions { animation: mo-rise .3s .22s var(--mo-ease) backwards; }
  /* the fight's end: the verdict comes up and a cold light runs across it; its tiles rise in turn (app.js) */
  #result { position: relative; animation: mo-verdict .45s var(--mo-ease) backwards; }
  #result::before { content: ''; position: absolute; inset: 0; pointer-events: none; border-radius: inherit; opacity: 0; background: var(--mo-band) no-repeat 0 0 / 50% 100%; animation: mo-sweep .8s .15s ease-in-out; }

  /* the frame, entering the game (and the menu back after a fight or the tutorial): the bar drops, the menu slides in (on phones it comes up) */
  .topbar { animation: mo-drop .3s var(--mo-ease) backwards; }
  .sidenav { animation: mo-nav .3s var(--mo-ease) backwards; }
  /* the login: the wordmark, its line and the card rise in turn, the world beside them */
  #login { animation-name: mo-fade; }
  .login > *, .world-now { animation: mo-rise .4s var(--mo-ease) backwards; }
  .login > :nth-child(3) { animation-delay: .06s; } .login > :nth-child(4) { animation-delay: .12s; } .world-now { animation-delay: .18s; }
  /* the loading screen lifts like a shutter, a cold edge under it */
  .boot { transition: transform .5s cubic-bezier(.7, 0, .25, 1), visibility .5s; }
  .boot.done { opacity: 1; transform: translateY(-100%); box-shadow: 0 2px 0 var(--accent), 0 0 30px #a2d7cf55; }

  /* dialogs and popovers come up out of the page; the reward window's tiles in turn */
  dialog[open] { animation: mo-pop .2s var(--mo-ease); }
  dialog[open]::backdrop { animation: mo-fade .2s ease-out; }
  dialog.reward[open] .rw-row { animation: mo-tile .3s .08s var(--mo-ease) backwards; }
  dialog.reward[open] .rw-row:nth-child(2) { animation-delay: .14s; } dialog.reward[open] .rw-row:nth-child(3) { animation-delay: .2s; } dialog.reward[open] .rw-row:nth-child(n+4) { animation-delay: .26s; }
  .profile-pop:popover-open { animation: mo-pop .16s var(--mo-ease); }
  /* a tooltip fades in: opacity only, as the tips are placed by measuring them */
  .tip:not([hidden]) { animation: mo-fade .12s ease-out; }
  /* a notification slips in from the edge, a slip of paper (it rose before) */
  .toast { animation: mo-slip .24s var(--mo-ease); }
  @media (max-width: 719px) {
    .sidenav { animation-name: mo-tabbar; }
    .nav-foot:popover-open { transform-origin: 100% 100%; animation: mo-pop .16s var(--mo-ease); }
  }
}
@media (prefers-reduced-motion: reduce) { .screen { animation: mo-fade .15s ease-out backwards; } }

@keyframes mo-fade { from { opacity: 0; } }
@keyframes mo-file { from { opacity: 0; transform: translateY(14px); } }
@keyframes mo-enter { from { opacity: 0; transform: scale(.96); } }
@keyframes mo-drop { from { opacity: 0; transform: translateY(-10px); } }
@keyframes mo-rise { from { opacity: 0; transform: translateY(12px); } }
@keyframes mo-pop { from { opacity: 0; transform: translateY(8px) scale(.97); } }
@keyframes mo-slip { from { opacity: 0; transform: translateX(28px); } }
@keyframes mo-tile { from { opacity: 0; transform: translateY(8px) scale(.92); } }
@keyframes mo-nav { from { opacity: 0; transform: translateX(-14px); } }
@keyframes mo-tabbar { from { transform: translateY(100%); } }
@keyframes mo-verdict { from { opacity: 0; transform: translateY(16px) scale(.97); } }
@keyframes mo-slit { from { clip-path: inset(49.5% 0); } to { clip-path: inset(0); } }
@keyframes mo-flash { from { opacity: 1; transform: scaleY(.03); } 30% { opacity: .8; transform: none; } to { opacity: 0; } }
@keyframes mo-sweep { from { opacity: 1; background-position: -120% 0; } to { opacity: 1; background-position: 220% 0; } }
@keyframes mo-door { from { clip-path: inset(0 50%); } to { clip-path: inset(0); } }
@keyframes mo-lights { from { opacity: 0; filter: brightness(.2); } 40% { opacity: 1; } }
@keyframes mo-iris { from { clip-path: circle(0 at 50% 140px); } to { clip-path: circle(150% at 50% 140px); } }
@keyframes mo-bars { from { opacity: 1; transform: translateY(-100%); } 45%, 70% { opacity: 1; transform: none; } to { opacity: 0; transform: none; } }
