/* Things that float over everything (0.18): toasts and modals. Each toast
   wears a cut-out sticker for its kind (a pin, a stamped tick, a bolt;
   generic art, so a toast on the stage brands nothing) and arrives in one of
   four flavours, a modal in one of three; admin/fx.js picks by hash so two
   in a row differ. Distances times --fx-amp; all removable. */

.toast::before {
  width: 26px; height: 26px; border-radius: 0; background: url(../img/admin/pin-info.webp) center / contain no-repeat;
  filter: drop-shadow(1px 1px 0 #000); margin: -6px 0 -6px -4px;
}
.toast.ok::before { background: url(../img/admin/stamp-tick.webp) center / contain no-repeat; }
.toast.error::before { background: url(../img/admin/bolt-warning.webp) center / contain no-repeat; }

.toast[data-fx] { animation-duration: var(--t-4); animation-fill-mode: both; }
.toast[data-fx="0"] { animation-name: fx-toast-up; animation-timing-function: var(--e-over); }
.toast[data-fx="1"] { animation-name: fx-toast-slam; animation-timing-function: var(--e-hitstop); }
.toast[data-fx="2"] { animation-name: fx-toast-drop; animation-timing-function: var(--e-bounce); animation-duration: var(--t-5); }
.toast[data-fx="3"] { animation-name: fx-toast-side; animation-timing-function: var(--e-out); }
@keyframes fx-toast-up { from { opacity: 0; translate: 0 calc(18px * var(--fx-amp)); } }
@keyframes fx-toast-slam { from { opacity: 0; scale: calc(1 + .35 * var(--fx-amp)); } }
@keyframes fx-toast-drop { from { opacity: 0; translate: 0 calc(-26px * var(--fx-amp)); } 20% { opacity: 1; } }
@keyframes fx-toast-side { from { opacity: 0; translate: calc(-36px * var(--fx-amp)) 0; } }
/* The sticker lands a beat after its toast. */
.toast[data-fx]::before { animation: fx-toast-sticker var(--t-4) var(--e-over) 120ms both; }
@keyframes fx-toast-sticker { from { scale: calc(1 - .8 * var(--fx-amp)); rotate: calc(-20deg * var(--fx-amp)); } }

.modal[data-fx] { animation-duration: var(--t-4); animation-fill-mode: both; }
.modal[data-fx="0"] { animation-name: fx-modal-slam; animation-timing-function: var(--e-over); }
.modal[data-fx="1"] { animation-name: fx-modal-rise; animation-timing-function: var(--e-anticipate); }
.modal[data-fx="2"] { animation-name: fx-modal-drop; animation-timing-function: var(--e-bounce); animation-duration: var(--t-5); }
@keyframes fx-modal-slam { from { opacity: 0; scale: calc(1 + .08 * var(--fx-amp)); } }
@keyframes fx-modal-rise { from { opacity: 0; translate: 0 calc(24px * var(--fx-amp)); } 30% { opacity: 1; } }
@keyframes fx-modal-drop { from { opacity: 0; translate: 0 calc(-30px * var(--fx-amp)); } 20% { opacity: 1; } }

/* The burst (admin/fx.js pow): a blank comic shape from tools/art with one
   word set over it in the bundled display face, popping over the toast that
   says the same thing in plain words. Two shapes, one per kind, so a save
   and a print do not look alike. It leaves by itself after 1.4 s, so with
   every animation off it simply appears and goes. */
.pow {
  order: -1; position: relative; display: grid; place-items: center;
  width: 190px; height: 140px; margin: 0 auto -10px; pointer-events: none;
  animation: fx-pow 1.4s var(--e-over) both;
}
.pow img { grid-area: 1 / 1; width: 100%; height: 100%; object-fit: contain; filter: drop-shadow(3px 3px 0 #000); }
/* The picture carries a filter, so it paints as its own stacking context,
   above plain inline text: the word has to be lifted over it by hand. */
.pow span {
  grid-area: 1 / 1; position: relative; z-index: 1; font-family: var(--display); font-weight: 400; font-size: 40px; line-height: 1;
  letter-spacing: .03em; padding-top: .08em; color: #FFF6D8;
  -webkit-text-stroke: 5px #14162B; paint-order: stroke fill; text-shadow: 2px 2px 0 #14162B;
}
.pow[data-pow="print"] span { color: #FFE14D; }
@keyframes fx-pow {
  0% { opacity: 0; scale: calc(1 - .55 * var(--fx-amp)); }
  22% { opacity: 1; scale: 1; }
  76% { opacity: 1; scale: 1; }
  100% { opacity: 0; scale: calc(1 + .12 * var(--fx-amp)); }
}
