/* =====================================================================
   MOTION

   Everything here obeys three rules, and they are what keep it from
   turning into a slideshow you have to sit through every morning:

   1. TRANSFORM AND OPACITY ONLY. Those two are the properties a browser
      can animate on the compositor without laying the page out again.
      Nothing here animates width, height, top or margin — a single
      animated layout property on a list of forty tasks costs more than
      every animation on this page put together.

   2. UNDER 300ms, AND ONCE. Entrances play when a page loads or when a
      thing is created. Nothing loops except the machine's own "still
      thinking" light, which is the one case where a loop MEANS
      something.

   3. IT EXPLAINS A CHANGE, OR IT IS NOT HERE. A card settles in because
      it just arrived; a stage fades because you switched to it; the
      drawer slides from the right because that is where it lives.
      Decoration that says nothing gets cut.

   Reduced motion switches all of it off at the bottom of the file —
   not by shortening it, by removing it.
   ===================================================================== */

/* --- the vocabulary ------------------------------------------------- */
@keyframes m-rise    { from { opacity: 0; transform: translateY(8px);  } to { opacity: 1; transform: none; } }
@keyframes m-settle  { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
@keyframes m-in      { from { opacity: 0; } to { opacity: 1; } }
@keyframes m-slide   { from { opacity: 0; transform: translateX(10px); } to { opacity: 1; transform: none; } }
@keyframes m-pop     { 0% { transform: scale(.94); opacity: 0; } 60% { transform: scale(1.01); opacity: 1; } 100% { transform: scale(1); } }

/* =====================================================================
   PAGE ARRIVAL

   The page settles onto the desk rather than being thrown at you: the
   panels rise a few pixels, in the order they are read, and the whole
   thing is over in a third of a second. Six steps, because a stagger
   that keeps counting past that is a page that feels slow to load.
   ===================================================================== */
.panel,
.set-card,
.admin-card,
.admin-tiles,
.tb-stack,
.tb-copy,
.rev-item,
.imp-step {
  animation: m-rise 260ms cubic-bezier(.2, .7, .3, 1) both;
}
.panel:nth-of-type(2), .set-card:nth-of-type(2), .admin-card:nth-of-type(2) { animation-delay: 40ms; }
.panel:nth-of-type(3), .set-card:nth-of-type(3), .admin-card:nth-of-type(3) { animation-delay: 80ms; }
.panel:nth-of-type(4), .set-card:nth-of-type(4), .admin-card:nth-of-type(4) { animation-delay: 120ms; }
.panel:nth-of-type(5), .set-card:nth-of-type(5), .admin-card:nth-of-type(5) { animation-delay: 150ms; }
.panel:nth-of-type(n+6), .set-card:nth-of-type(n+6), .admin-card:nth-of-type(n+6) { animation-delay: 175ms; }

/* The page title arrives first, because it is what you read first. */
.rev-title, .in-title, .arc-title, .imp-title, .admin-h1 {
  animation: m-settle 240ms cubic-bezier(.2, .7, .3, 1) both;
}

/* =====================================================================
   THE BOARD
   ===================================================================== */

/* Switching stage: the new column fades up rather than snapping in, so
   the eye follows the change instead of re-reading the whole list. */
.tb-card .board-col:not([hidden]) {
  animation: m-rise 180ms cubic-bezier(.2, .7, .3, 1) both;
}

/* A task that has just been typed in. The app already adds .is-adding
   for one frame; this gives it something worth watching. */
.task.is-adding { animation: m-pop 200ms cubic-bezier(.2, .9, .3, 1.15) both; }

/* And one that is leaving — deleted, or moved to another stage. */
.task.is-removing {
  animation: m-in 140ms ease-in reverse both;
  pointer-events: none;
}

/* The counters on the tabs tick rather than blink. */
.tb-tab-count { transition: color 140ms ease-out, background-color 140ms ease-out; }

/* =====================================================================
   THINGS THAT APPEAR BECAUSE YOU ASKED
   ===================================================================== */
.toast        { animation: m-slide 200ms cubic-bezier(.2, .7, .3, 1) both; }
.modal-card   { animation: m-pop 180ms cubic-bezier(.2, .9, .3, 1.1) both; }
.td-dock      { animation: m-rise 180ms cubic-bezier(.2, .7, .3, 1) both; }
.brand-pop,
.user-pop,
.cp-panel     { animation: m-rise 140ms cubic-bezier(.2, .7, .3, 1) both; }

/* The machine's answer arrives as a block of text somebody now has to
   read, so it fades rather than sliding — nothing to track, just
   something that is now there. */
.mtg-ai-log > *, #cResult, .kt-doc, .td-ai { animation: m-in 220ms ease-out both; }

/* =====================================================================
   THE HOVER LIFT

   A card you can act on rises a hair under the pointer. One pixel and
   a slightly deeper shadow — enough to feel, not enough to notice.
   ===================================================================== */
.rev-item,
.pl-card,
.mtg-item,
.imp-drop {
  transition: transform 120ms ease-out, box-shadow 120ms ease-out, border-color 120ms ease-out;
}
.rev-item:hover,
.pl-card:hover,
.mtg-item:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); }

/* =====================================================================
   RESPECT THE SETTING

   Removed, not shortened. Somebody who has switched motion off is
   telling the machine that movement makes them unwell, and a 40ms
   version of the same slide is still a slide.
   ===================================================================== */
@media (prefers-reduced-motion: reduce) {
  .panel, .set-card, .admin-card, .admin-tiles, .tb-stack, .tb-copy,
  .rev-item, .imp-step, .rev-title, .in-title, .arc-title, .imp-title,
  .admin-h1, .tb-card .board-col:not([hidden]), .task.is-adding,
  .task.is-removing, .toast, .modal-card, .td-dock, .brand-pop,
  .user-pop, .cp-panel, .mtg-ai-log > *, #cResult, .kt-doc, .td-ai {
    animation: none !important;
  }
  .rev-item, .pl-card, .mtg-item, .imp-drop { transition: none; }
  .rev-item:hover, .pl-card:hover, .mtg-item:hover { transform: none; }
}

/* Print gets none of it, and none of the states it leaves behind. */
@media print {
  * { animation: none !important; transition: none !important; }
}
