/* motion.css — the one motion language, shared by every page.
 *
 * index.html defines these tokens inline for the shell; this file carries the
 * same vocabulary to the standalone pages (chess, games, motoi, theater,
 * wallet, id, …) so nothing on the site moves in a different accent.
 *
 * The rules: arrivals decelerate with a soft overshoot, exits accelerate away
 * and are always faster than arrivals, nothing snaps, and a press has weight
 * under the finger. Load this AFTER palette.css and BEFORE the page's own
 * stylesheet so a page can still override any single line.
 */

:root {
  --ease:        cubic-bezier(.34, 1.25, .64, 1);
  --ease-emph:   cubic-bezier(.16, 1.05, .3, 1);
  --ease-spring: cubic-bezier(.34, 1.56, .64, 1);
  --ease-smooth: cubic-bezier(.22, .61, .36, 1);
  --ease-exit:   cubic-bezier(.4, 0, .8, .4);
  /* physical travel — a thing with mass decelerating into rest. No overshoot:
     a chess piece that lands past its square and corrects looks broken. */
  --ease-glide:  cubic-bezier(.22, .68, .24, 1);

  --dur:        480ms;
  --dur-fast:   330ms;
  --dur-slow:   570ms;
  --dur-exit:   260ms;
  --stagger:     45ms;
  --rise:        10px;
}

/* --- no text selection anywhere (Alfred, 2026-08-21) ---
   "All highlights off." A long-press on the graph selected the whole surface
   and raised iOS's Copy / Search bar over the app. The app is an instrument,
   not a document: nothing is selectable except fields you type into. */
html {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
input, textarea, [contenteditable="true"], [contenteditable=""] {
  -webkit-user-select: text;
  user-select: text;
}

/* --- pressable things: weight under the finger, spring on release --- */
button, .btn, [role="button"], summary, label.tap, a.btn,
button *, .btn *, [role="button"] *, summary *, a.btn * {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
/* .pane-node is excluded: the pane graph positions its node groups with an
   SVG translate, and a CSS transform here REPLACES it — the node flies to
   the origin mid-press. pane.css paints its own press feedback. */
button, .btn, [role="button"]:not(.pane-node), summary, label.tap, a.btn {
  -webkit-tap-highlight-color: transparent;
  transition:
    transform var(--dur-fast) var(--ease-spring),
    background-color var(--dur-fast) var(--ease-smooth),
    border-color var(--dur-fast) var(--ease-smooth),
    color var(--dur-fast) var(--ease-smooth),
    box-shadow var(--dur-fast) var(--ease-smooth),
    opacity var(--dur-fast) var(--ease-smooth);
}
button:active, .btn:active, [role="button"]:not(.pane-node):active, summary:active, a.btn:active {
  transform: translateY(1px) scale(.982);
  transition-duration: 90ms;
  transition-timing-function: var(--ease-exit);
}
button:disabled, .btn:disabled { transition-duration: var(--dur-fast); }

/* --- inputs settle rather than flick --- */
input, select, textarea {
  transition:
    border-color var(--dur-fast) var(--ease-smooth),
    background-color var(--dur-fast) var(--ease-smooth),
    box-shadow var(--dur-fast) var(--ease-smooth);
}

/* --- links --- */
a { transition: color var(--dur-fast) var(--ease-smooth), opacity var(--dur-fast) var(--ease-smooth); }

/* --- overlays: the backdrop fades, the panel rises with emphasis --- */
.veil, .overlay, .modal-backdrop, dialog::backdrop {
  transition: opacity var(--dur-fast) var(--ease-smooth);
}
.sheet, .panel, .card, .modal, .popover, .menu {
  transition:
    transform var(--dur) var(--ease-emph),
    opacity var(--dur-fast) var(--ease-smooth),
    box-shadow var(--dur) var(--ease-emph);
}

/* --- the two named arrivals. Add .rise-in / .fade-in to anything that
       appears; add .stagger to a parent to have its children arrive in
       sequence rather than as a chorus. --- */
@keyframes m-rise-in {
  from { opacity: 0; transform: translateY(var(--rise)); }
  to   { opacity: 1; transform: none; }
}
@keyframes m-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes m-pop-in {
  from { opacity: 0; transform: scale(.94); }
  to   { opacity: 1; transform: none; }
}
.rise-in { animation: m-rise-in var(--dur) var(--ease-emph) both; }
.fade-in { animation: m-fade-in var(--dur-fast) var(--ease-smooth) both; }
.pop-in  { animation: m-pop-in  var(--dur) var(--ease-spring) both; }

.stagger > * { animation: m-rise-in var(--dur) var(--ease-emph) both; }
.stagger > *:nth-child(1)  { animation-delay: calc(var(--stagger) * 0); }
.stagger > *:nth-child(2)  { animation-delay: calc(var(--stagger) * 1); }
.stagger > *:nth-child(3)  { animation-delay: calc(var(--stagger) * 2); }
.stagger > *:nth-child(4)  { animation-delay: calc(var(--stagger) * 3); }
.stagger > *:nth-child(5)  { animation-delay: calc(var(--stagger) * 4); }
.stagger > *:nth-child(6)  { animation-delay: calc(var(--stagger) * 5); }
.stagger > *:nth-child(7)  { animation-delay: calc(var(--stagger) * 6); }
.stagger > *:nth-child(8)  { animation-delay: calc(var(--stagger) * 7); }
.stagger > *:nth-child(9)  { animation-delay: calc(var(--stagger) * 8); }
.stagger > *:nth-child(n+10) { animation-delay: calc(var(--stagger) * 9); }

/* --- scrolling is momentum, not teleportation --- */
html { scroll-behavior: smooth; }

/* --- the one accessibility exit --- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}
