/* ---- motion: one vocabulary for the whole site. Things arrive by rising a little and fading in; a ruled row draws its line in
   from the left before its content lands; a group staggers its children; nothing waits on a page change. Built the way Framer
   Motion feels, costing almost nothing: transform and opacity only (compositor work, no layout), CSS transitions not scripts,
   one IntersectionObserver that fires once per element (motion.js). Off under reduced motion. ---- */
:root {
  --m-dur: 0.6s;
  --m-fast: 0.25s;
  --m-ease: cubic-bezier(0.22, 0.61, 0.14, 1);   /* a long, soft settle: fast off the line, slow into place */
  --m-rise: 12px;
  --m-stagger: 45ms;
}

/* the entrance */
[data-m] { opacity: 0; transform: translateY(var(--m-rise)); transition: opacity var(--m-dur) var(--m-ease), transform var(--m-dur) var(--m-ease); transition-delay: calc(var(--i, 0) * var(--m-stagger)); will-change: auto; }
[data-m="fade"] { transform: none; }
[data-m].is-in { opacity: 1; transform: none; }
[data-m].is-in.is-dim { opacity: 0.18; }   /* the work shelf's dimming still wins once a tile is in */

/* the rule: the element's top line draws in from the left, then the content rises with it */
[data-m-rule] { position: relative; }
[data-m-rule]::before { content: ''; position: absolute; left: 0; right: 0; top: -1px; height: 1px; background: var(--line-2, var(--line)); transform: scaleX(0); transform-origin: left; transition: transform var(--m-dur) var(--m-ease); transition-delay: calc(var(--i, 0) * var(--m-stagger)); pointer-events: none; }
[data-m-rule].is-in::before { transform: scaleX(1); }
[data-m-rule][data-m-rule-hide] { border-top-color: transparent !important; }   /* the real border steps aside while the line draws */


@media (prefers-reduced-motion: reduce) {
  [data-m], [data-m].is-in { opacity: 1; transform: none; transition: none; }
  [data-m-rule]::before { transform: none; transition: none; }
  [data-m-rule][data-m-rule-hide] { border-top-color: var(--line) !important; }
}
