/* B28 v1: purely decorative motion for existing /w/ UI. No state mutation. */
:root {
  --afm-fast: 140ms;
  --afm-medium: 220ms;
  --afm-slow: 300ms;
  --afm-ease: cubic-bezier(.2,.8,.2,1);
}
/* 1. Navigation active pill: existing aria-selected remains authoritative. */
#app .tabs[data-afm-nav] { isolation: isolate; }
/* position:relative с нулевой специфичностью: не перебивает position:fixed нижней панели на телефоне (widget.css) */
:where(#app .tabs[data-afm-nav]) { position: relative; }
#app .tabs[data-afm-nav] > button { z-index: 1; }
#app .tabs[data-afm-nav] > .afm-indicator {
  position: absolute; pointer-events: none; z-index: 0;
  top: 0; left: 0; width: var(--afm-w, 0px); height: var(--afm-h, 0px);
  border-radius: 12px; background: var(--soft);
  opacity: var(--afm-opacity, 0);
  transform: translate3d(var(--afm-x, 0px), var(--afm-y, 0px), 0);
  transition: transform var(--afm-medium) var(--afm-ease),
              width var(--afm-medium) var(--afm-ease),
              height var(--afm-medium) var(--afm-ease), opacity var(--afm-fast) ease;
}
/* 2. Card lift (pointer-capable devices only; does not move focused elements). */
@media (hover:hover) and (pointer:fine) {
  #app .nx, #app .day, #app .card {
    transition: translate var(--afm-medium) var(--afm-ease),
                box-shadow var(--afm-medium) var(--afm-ease),
                border-color var(--afm-medium) var(--afm-ease);
  }
  #app .nx:hover, #app .card:hover { translate: 0 -2px; }
  #app .day:hover { translate: 0 -1px; }
}
/* 3. Badge enters once when the *actual* DOM content changes. */
#app .afm-badge-pop { animation: afm-badge var(--afm-slow) var(--afm-ease) both; }
@keyframes afm-badge { from { transform: scale(.72); opacity:.55; } 70% { transform:scale(1.08) } to {transform:scale(1);opacity:1} }
/* 4. Native modal: animation never affects dialog visibility or keyboard escape. */
#sheet[open] { animation: afm-sheet var(--afm-medium) var(--afm-ease); }
@keyframes afm-sheet { from { opacity:.65; translate:0 8px; scale:.985; } to {opacity:1; translate:0 0; scale:1;} }
/* 5. Real controls, pressed state only. */
#app button:active:not(:disabled), #sheet button:active:not(:disabled) { scale: .985; }
/* 6. Error shake is opt-in after a real error result, not inferred from a request. */
#app [data-afm-error="true"], #sheet [data-afm-error="true"] { animation: afm-shake var(--afm-medium) ease-out; }
@keyframes afm-shake { 0%,100% {translate:0} 25% {translate:-3px} 75% {translate:3px} }
/* 7. Skeleton shimmer only for explicit loading elements; never invent data. */
#app [data-afm-loading="true"] { background-image: linear-gradient(100deg,transparent 20%,var(--soft) 50%,transparent 80%); background-size:220% 100%; animation:afm-shimmer 1.6s linear infinite; }
@keyframes afm-shimmer { to { background-position-x:-220%; } }
/* 8. Success badge requires a confirmed booking event from the real server path. */
.afm-success { position:fixed; right:max(18px, env(safe-area-inset-right)); bottom:calc(20px + var(--tabbar,0px));
  z-index:110; display:flex; gap:10px; align-items:center; max-width:calc(100vw - 36px);
  border-radius:14px; padding:12px 16px; border:1px solid var(--line2);
  background:var(--panel); color:var(--text); box-shadow:var(--shadow-pop);
  animation:afm-toast var(--afm-slow) var(--afm-ease); }
.afm-success svg {flex:none; width:24px;height:24px; fill:none;stroke:var(--ok);stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round}
@keyframes afm-toast { from {opacity:0;transform:translateY(12px)} to {opacity:1;transform:none} }
@media (prefers-reduced-motion: reduce) {
  :root { --afm-fast:0ms; --afm-medium:0ms; --afm-slow:0ms; }
  #app .tabs[data-afm-nav] > .afm-indicator, #app .nx, #app .day, #app .card,
  #app .afm-badge-pop, #sheet[open], #app [data-afm-error="true"],
  #sheet [data-afm-error="true"], #app [data-afm-loading="true"], .afm-success {
    animation:none !important; transition:none !important; translate:none !important;
  }
  #app button:active:not(:disabled), #sheet button:active:not(:disabled) {scale:1}
}
