/* The app's motion (js/core/motion.js). Only transform / opacity (+ stroke-dashoffset for the line draw and the
   design's own bar sizes). <html data-motion="reduce"> (the OS setting or the account switch «تقليل الحركة») turns
   movement off. One-shot animations fill "backwards" (not "both"): a finished enter animation must not keep a
   stacking context, or a menu inside an entered block (the period / month menus in a page head) is painted under the
   blocks after it; motion.js also drops the class when the animation ends. */

@keyframes m-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes m-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes m-spin { to { transform: rotate(360deg); } }
@keyframes m-pulse { 0% { transform: scale(.3); opacity: .5; } 100% { transform: scale(1.4); opacity: 0; } }
@keyframes m-pop { from { opacity: 0; transform: translateY(6px) scale(.96); } to { opacity: 1; transform: none; } }
@keyframes m-ping { 0% { transform: scale(1); } 35% { transform: scale(1.22); } 70% { transform: scale(.96); } 100% { transform: scale(1); } }
@keyframes m-ring { from { opacity: .5; transform: scale(1); } to { opacity: 0; transform: scale(2); } }
@keyframes m-shimmer { from { transform: translateX(calc(100% * var(--flip))); } to { transform: translateX(calc(-100% * var(--flip))); } }
@keyframes m-typing { 0%, 70%, 100% { opacity: .3; transform: translateY(0) scale(.8); } 35% { opacity: 1; transform: translateY(-3px) scale(1); } }
@keyframes m-menu { from { opacity: 0; transform: translateY(-4px) scale(.98); } to { opacity: 1; transform: none; } }

/* Page enter: the blocks on screen fade + rise 8px, 40ms apart (motion.enter; the home feed 70ms apart) */
.m-enter { animation: m-rise var(--t-enter) var(--ease) backwards; animation-delay: var(--m-delay, 0ms); }
.m-fade { animation: m-fade 200ms var(--ease) backwards; }
.m-spin { animation: m-spin .8s linear infinite; }

/* Chat bubbles appear from the speaker's side (motion.pop): the owner's question on the right (RTL start),
   the answer on the left; English (dir=ltr) mirrors it, as the ask page's logical CSS does */
.m-pop { animation: m-pop 280ms var(--ease) backwards; transform-origin: 50% 100%; }
.ask-row.me.m-pop { transform-origin: 100% 100%; }
.ask-row.ai.m-pop, .ask-ai.m-pop { transform-origin: 0 100%; }
:root[dir="ltr"] .ask-row.me.m-pop { transform-origin: 0 100%; }
:root[dir="ltr"] .ask-row.ai.m-pop, :root[dir="ltr"] .ask-ai.m-pop { transform-origin: 100% 100%; }

/* The calm typing pulse while an answer is written: three accent dots, one after another */
.m-typing { display: inline-flex; align-items: center; gap: 4px; height: 12px; flex: none; }
.m-typing i { width: 6px; height: 6px; border-radius: 50%; background: var(--ac); opacity: .3; animation: m-typing 1s ease-in-out infinite; }
.m-typing i:nth-child(2) { animation-delay: .15s; }
.m-typing i:nth-child(3) { animation-delay: .3s; }

/* The urgent badge (and the bell dot) pulse once when they appear or their number grows (motion.ping) */
.m-ping { animation: m-ping 600ms var(--ease) 1; }
.nav-badge.m-ping { position: relative; }
.m-ping::after {
  content: ''; position: absolute; inset: 0; z-index: -1; border-radius: inherit; background: inherit;
  pointer-events: none; animation: m-ring 600ms var(--ease) 1 forwards;
}

/* Skeleton shimmer: a soft light sweeps across with the reading direction (Arabic right to left) and stops after 5 s */
.sk { position: relative; overflow: hidden; }
.sk::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; transform: translateX(calc(100% * var(--flip)));
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .05) 50%, transparent);
  animation: m-shimmer 1s var(--ease) 5;
}

/* Old content dims while the new period loads (motion.busy and the pages' own busy classes); the numbers then roll */
.m-busy, .dash-view.dash-busy, .rv-list.rv-busy, .tp-main.tp-busy { opacity: .55; }
.m-busy, .dash-view, .rv-list, .tp-main, .home-aside, .rv-tiles { transition: opacity 200ms var(--ease); }

/* Floating menus (period, sort) open with a short fade + drop */
.period-menu:not([hidden]), [role="menu"]:not([hidden]) { animation: m-menu 160ms var(--ease); transform-origin: 50% 0; }

/* Press feedback on phone tiles (design: scale .96 on press) */
@media (hover: none) {
  button.tile:active, a.tile:active, button.kpi:active, a.kpi:active { transform: scale(.96); }
  button.tile, a.tile, button.kpi, a.kpi { transition: transform var(--t-fast) var(--ease); }
}

/* Reduced motion: final states at once, short fades only */
html[data-motion="reduce"] *, html[data-motion="reduce"] *::before, html[data-motion="reduce"] *::after {
  animation-duration: 1ms !important;
  animation-iteration-count: 1 !important;
  animation-delay: 0ms !important;
  transition-duration: 1ms !important;
  scroll-behavior: auto !important;
}
html[data-motion="reduce"] .m-enter, html[data-motion="reduce"] .m-fade, html[data-motion="reduce"] .m-pop {
  animation: m-fade 150ms linear backwards !important;
}
html[data-motion="reduce"] .m-spin, html[data-motion="reduce"] .m-ping, html[data-motion="reduce"] .m-ping::after,
html[data-motion="reduce"] .m-typing i, html[data-motion="reduce"] [role="menu"] { animation: none !important; }
html[data-motion="reduce"] .sk::after { display: none; }
html[data-motion="reduce"] .m-typing i { opacity: .7; }

/* The loading sign (js/core/busy.js): a thin accent bar along the very top that runs back and forth, and the page
   area faded a little. Opacity only, so nothing moves. A page that dims itself (.m-busy, .dash-busy, .rv-busy,
   .tp-busy) is not faded twice. Reduced motion (OS or «تقليل الحركة»): the bar is still and full. */
.busy-bar {
  position: fixed; top: 0; inset-inline: 0; height: 3px; z-index: 2100; overflow: hidden;
  pointer-events: none; opacity: 0; transition: opacity 120ms linear;
}
.busy-bar.on { opacity: 1; }
.busy-bar::before {
  content: ''; position: absolute; inset-block: 0; inset-inline-start: 0; width: 35%; border-radius: 2px; background: var(--ac);
  animation: busy-run 1.2s ease-in-out infinite;
}
@keyframes busy-run {
  from { transform: translateX(calc(100% * var(--flip))); }
  to { transform: translateX(calc(-290% * var(--flip))); }
}
#page { transition: opacity 150ms var(--ease); }
#page.is-loading:not(:has(.m-busy, .dash-busy, .rv-busy, .tp-busy)) { opacity: .6; }
html[data-motion="reduce"] .busy-bar::before { animation: none !important; width: 100%; }
@media (prefers-reduced-motion: reduce) { .busy-bar::before { animation: none !important; width: 100%; } }
