/* Hallmark · checked: 2026-11-02 · genre: playful (kept) · motion layer for style.css, read its stamp and tokens first
 * floor: transform, opacity and the individual translate, rotate, scale properties only · fixed iteration counts, no idle loops
 * built: the project · motion character: calm, a small spring on the sticker press and tilt only · v2.0.0 */
/* Liga Mabar: site-wide motion (track C, docs/alive-spec.md), now on the shared tokens of style.css.
 * Rules: transform/opacity only (plus the individual `translate`, `rotate`, `scale` properties, which compose with
 * the existing `transform: rotate(...)` tilts instead of replacing them), no big shadows on movers.
 * Loaded after style.css. Reduced motion: style.css zeroes animations and transitions; the page-transition
 * fade below is the only thing that still plays (150 ms, opacity only).
 * Pre-hidden entrances only exist when motion.js marked an element with [data-rv] AND the head script set html.mo-on,
 * so no-JS and reduced-motion visitors always see everything. */

/* ---------- cross-document view transitions (Chrome/Edge 126+, Safari 18.2+; others just navigate) ---------- */
@view-transition { navigation: auto; }

.top { view-transition-name: mo-top; }
.tabbar { view-transition-name: mo-tabbar; }
::view-transition-group(mo-top),
::view-transition-group(mo-tabbar) { animation: none; }
::view-transition-old(mo-top),
::view-transition-old(mo-tabbar) { display: none; }
::view-transition-new(mo-top),
::view-transition-new(mo-tabbar) { animation: none; }

::view-transition-old(root) { animation: mo-vt-out var(--dur-micro) var(--ease-in) both; }
::view-transition-new(root) { animation: mo-vt-in var(--dur-short) var(--ease-out) both; }
@keyframes mo-vt-out { to { opacity: 0; transform: translateX(-10px); } }
@keyframes mo-vt-in { from { opacity: 0; transform: translateX(16px); } }

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root) { animation: mo-vt-fade-out 150ms linear both; }
  ::view-transition-new(root) { animation: mo-vt-fade-in 150ms linear both; }
}
@keyframes mo-vt-fade-out { to { opacity: 0; } }
@keyframes mo-vt-fade-in { from { opacity: 0; } }

/* ---------- entrances: one small staggered settle, once per element ---------- */
.mo-on [data-rv]:not(.in) { opacity: 0; }
.mo-on [data-rv].in { animation: mo-in .6s var(--d, 0s) var(--ease-out) backwards; }
@keyframes mo-in {
  0% { opacity: 0; translate: 0 22px; scale: .96; }
  60% { opacity: 1; translate: 0 -3px; scale: 1.005; }
  100% { opacity: 1; translate: 0 0; scale: 1; }
}

/* ---------- press: stickers squish (the one place a spring is allowed, see the waiver in style.css) ---------- */
.btn { transition: transform var(--dur-micro) var(--ease-out), scale var(--dur-spring) var(--spring); }
.btn:active { scale: .96; }
.btn-ghost:active { scale: .98; }
.opt { transition: transform var(--dur-micro) var(--ease-out), scale var(--dur-spring) var(--spring); }
.stage, .kmc, .badge { transition: transform var(--dur-micro) var(--ease-out), scale var(--dur-spring) var(--spring); }
.opt:active, .kmc:active, .badge:active { scale: .96; }
.stage:active { scale: .94; }
.tab-ico { transition: scale var(--dur-spring) var(--spring); }
.tab:active .tab-ico { scale: .84; }
.main-btn { transition: transform var(--dur-micro) var(--ease-out), scale var(--dur-spring) var(--spring); }
.tab-main:active .main-btn { scale: .92; }
.hdr-pill { transition: scale var(--dur-spring) var(--spring); }
.hdr-pill:active { scale: .95; }

/* tabs wiggle once on arrival (view transitions keep the bar still, so the new active tab jiggles) and on tap */
.tab[aria-current="page"] .tab-ico { animation: mo-wiggle .6s .12s var(--ease-out) backwards; }
.tab.wig .tab-ico, .tab-main.wig .main-ico { animation: mo-wiggle .6s var(--ease-out); }
@keyframes mo-wiggle {
  0% { rotate: 0deg; scale: 1; }
  25% { rotate: -14deg; scale: 1.2; }
  50% { rotate: 9deg; scale: 1.1; }
  75% { rotate: -4deg; scale: 1.03; }
  100% { rotate: 0deg; scale: 1; }
}

/* Main button hops three times while the red "belum milih" dot is on, then rests */
.tab-main:has(.main-dot:not([hidden])) .main-btn { animation: mo-hop 2.6s var(--ease-out) 3; }
@keyframes mo-hop {
  0%, 52%, 100% { translate: 0 0; }
  12% { translate: 0 -11px; }
  24% { translate: 0 0; }
  34% { translate: 0 -5px; }
  44% { translate: 0 0; }
}

/* stickers tilt on hover (pointer devices) and on tap */
.sticker, .score, .game, .logo-mark, .step-no, .tl-t { transition: rotate var(--dur-spring) var(--spring), scale var(--dur-spring) var(--spring); }
.sticker:active, .score:active, .step-no:active, .tl-t:active { rotate: -6deg; scale: 1.06; }
.game:active { rotate: .8deg; scale: .985; }
.logo:active .logo-mark { rotate: 14deg; scale: 1.1; }
@media (hover: hover) {
  .sticker:hover, .step-no:hover, .tl-t:hover { rotate: -5deg; scale: 1.04; }
  .score:hover { rotate: 2deg; scale: 1.04; }
  .game:hover { rotate: -.6deg; scale: 1.01; }
  .logo:hover .logo-mark { rotate: 12deg; scale: 1.06; }
}

/* ---------- live feel ---------- */
/* new ticker items drop in from the top */
.tk-new { animation: mo-tk-in var(--dur-long) var(--ease-out) backwards; }
@keyframes mo-tk-in {
  0% { opacity: 0; translate: 0 -16px; scale: .96; }
  100% { opacity: 1; translate: 0 0; scale: 1; }
}

/* a number that just ticked */
.mo-bump { animation: mo-bump var(--dur-long) var(--ease-out); }
.mo-bump-i { display: inline-block; }   /* `scale` needs a non-inline box; motion.js adds this only to inline targets */
@keyframes mo-bump { 0% { scale: 1; } 35% { scale: 1.1; } 100% { scale: 1; } }
.trend-n { display: inline-block; font-variant-numeric: tabular-nums; }

/* ---------- landing hero ---------- */
.js .ht-1 { animation: mo-drop .3s var(--ease-out) backwards; }
.js .ht-2 { animation: mo-stamp .4s .08s var(--spring) backwards; }
.js [data-wobble].wob { animation: mo-wob .6s var(--ease-out); }
@keyframes mo-drop { 0% { opacity: 0; translate: -26px -16px; rotate: -8deg; } 100% { opacity: 1; translate: 0 0; rotate: 0deg; } }
@keyframes mo-stamp {
  0% { opacity: 0; scale: 1.7; rotate: 12deg; }
  50% { opacity: 1; scale: .94; rotate: -4deg; }
  75% { scale: 1.04; rotate: 2deg; }
  100% { scale: 1; rotate: 0deg; }
}
@keyframes mo-wob {
  0%, 100% { rotate: 0deg; scale: 1; }
  25% { rotate: -6deg; scale: 1.06; }
  55% { rotate: 4deg; scale: 1.03; }
  80% { rotate: -2deg; scale: 1.01; }
}

/* ---------- trend line: stacked sticker avatars + one real sentence ---------- */
.trend-wrap { padding-top: var(--s-4); }
.trend {
  display: flex; align-items: center; gap: var(--s-3); padding: var(--s-2) var(--s-4); min-height: var(--s-14);
  background: var(--paper); border: var(--bw) solid var(--ink); border-radius: var(--r-4); box-shadow: var(--sh-s);
}
[data-live-page] > .trend { margin-bottom: var(--s-4); }
.trend-avs { flex: none; display: flex; align-items: center; min-width: 34px; }
.av {
  position: relative; display: grid; place-items: center; width: 36px; height: 36px; margin-left: -12px;
  font-family: var(--font-d); font-weight: var(--w-display); font-style: normal; font-size: var(--t-base); line-height: 1; text-transform: uppercase;
  border: 3px solid var(--ink); border-radius: 50%; box-shadow: var(--sh-s);
  z-index: calc(10 - var(--i, 0)); rotate: calc((var(--i, 0) - 1) * 7deg);
}
.av:first-child { margin-left: 0; }
.av-t0 { background: var(--chili-d); color: var(--on-color); }
.av-t1 { background: var(--leaf-d); color: var(--on-color); }
.av-t2 { background: var(--turmeric); color: var(--ink); }
.av-t3 { background: var(--sky-d); color: var(--on-color); }
.trend-text { margin: 0; min-width: 0; flex: 1; font-weight: var(--w-label); font-size: var(--t-sm); line-height: 1.4; overflow-wrap: anywhere; }
.trend-text b { font-family: var(--font-d); font-weight: var(--w-display); color: var(--chili-d); }
/* avatars pop in one by one once the row is on screen; a brand-new joiner flies in from the left */
.trend.in .av:not(.av-new):not(.av-done) { animation: mo-av-pop .5s calc(.15s + var(--i, 0) * .1s) var(--spring) backwards; }
.av-new { animation: mo-av-new .6s var(--spring) backwards; }
.av-out { animation: mo-av-out var(--dur-short) var(--ease-in) forwards; }
@keyframes mo-av-pop { 0% { scale: 0; translate: -10px 0; } 100% { scale: 1; translate: 0 0; } }
@keyframes mo-av-new { 0% { scale: .2; translate: -46px -8px; rotate: -40deg; opacity: 0; } 100% { scale: 1; translate: 0 0; opacity: 1; } }
@keyframes mo-av-out { to { scale: 0; opacity: 0; translate: 16px 0; } }
.av { transition: rotate var(--dur-long) var(--spring); }
.av.av-shift { transition: translate var(--dur-long) var(--ease-out), rotate var(--dur-long) var(--spring); }
.trend-text.swap { animation: mo-swap var(--dur-long) var(--ease-out); }
@keyframes mo-swap { 0% { opacity: .2; translate: 0 8px; } 100% { opacity: 1; translate: 0 0; } }

@media (max-width: 380px) {
  .av { width: 32px; height: 32px; margin-left: -12px; font-size: var(--t-sm); }
  .trend { gap: var(--s-2); padding-right: var(--s-3); }
  .trend-text { font-size: var(--t-sm); }
}
