:root {
  --motion-out: cubic-bezier(0.23, 1, 0.32, 1);
  --motion-soft: cubic-bezier(0.32, 0.72, 0, 1);
}

/* Short, interruptible feedback; moving targets never change their hit area. */
.btn, .icon-btn, .message-action, .suggestions button,
.language-option, .photo-controls button, .budget-stops button {
  transition: transform 180ms var(--motion-out), opacity 150ms var(--motion-out),
    background-color 180ms var(--motion-out), color 180ms var(--motion-out),
    border-color 180ms var(--motion-out), box-shadow 180ms var(--motion-out);
}
.btn:active:not(:disabled), .icon-btn:active:not(:disabled),
.message-action:active, .suggestions button:active,
.language-option:active, .photo-controls button:active, .budget-stops button:active {
  transform: scale(0.97);
  transition-duration: 110ms;
}
.btn:disabled, .icon-btn:disabled { transform: none; }
.btn .icon, .source-link .icon, .sidebar-qr .icon:last-child {
  transition: transform 180ms var(--motion-out);
}
.chip>span {
  transition: background-color 200ms var(--motion-out), border-color 200ms var(--motion-out),
    box-shadow 200ms var(--motion-out), transform 180ms var(--motion-out);
}
.chip input:active+span { transform: scale(0.985); transition-duration: 110ms; }
.choice-check {
  transition: background-color 170ms var(--motion-out), border-color 170ms var(--motion-out);
}
.choice-check .icon {
  transition: transform 200ms var(--motion-out), opacity 130ms var(--motion-out);
}
.guide-tab, .side-link, .mobile-views a, .new-trip, .source-link, .sidebar-qr {
  transition: background-color 160ms var(--motion-out), border-color 160ms var(--motion-out),
    color 160ms var(--motion-out), opacity 160ms var(--motion-out), box-shadow 160ms var(--motion-out);
}
.wizard-progress li { transition: color 200ms var(--motion-out); }
.wizard-progress li span {
  transition: background-color 200ms var(--motion-out), border-color 200ms var(--motion-out), color 200ms var(--motion-out);
}
.wizard-progress li.current span { box-shadow: 0 0 0 3px #365d5b12; }
.js .step.active { animation: none; }
.language-popover, .sos-panel { transform-origin: top right; }
.language-menu summary>.icon:last-child { transition: transform 200ms var(--motion-soft); }
.language-menu summary, .sos summary {
  transition: transform 160ms var(--motion-out), color 160ms var(--motion-out), background-color 160ms var(--motion-out), border-color 160ms var(--motion-out);
}
.language-menu summary:active, .sos summary:active { transform: scale(0.98); transition-duration: 110ms; }
.composer form { transition: border-color 180ms var(--motion-out), box-shadow 180ms var(--motion-out); }
.completion-toast { animation-duration: 260ms; }
.message-action.copied .icon { transform: scale(1.06); }
.message-action .icon { transition: transform 180ms var(--motion-out); }

.typing-indicator { display: inline-flex; align-items: center; gap: 6px; min-height: 26px; padding: 4px 2px; vertical-align: middle; direction: ltr; }
.typing-dot { display: block; width: 7px; height: 7px; flex: 0 0 7px; border-radius: 50%; background: var(--accent); opacity: .3; transform: scale(.72); animation: typing-glance 1200ms cubic-bezier(.45, 0, .55, 1) infinite; }
.typing-dot:nth-child(2) { animation-delay: 160ms; }
.typing-dot:nth-child(3) { animation-delay: 320ms; }
@keyframes typing-glance {
  0%, 65%, 100% { opacity: .3; transform: scale(.72); }
  30% { opacity: 1; transform: scale(1.18); }
}

@media (hover: hover) and (pointer: fine) {
  .btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 4px 11px #233d3d15; }
  .btn.ghost:hover { box-shadow: none; }
  .btn:hover .icon { transform: translateX(2px); }
  .btn.ghost:hover .icon { transform: translateX(-2px); }
  .btn:active:not(:disabled) { transform: scale(0.97); box-shadow: none; }
  .icon-btn:hover:not(:disabled), .message-action:hover { transform: translateY(-1px); }
  .icon-btn:active:not(:disabled), .message-action:active { transform: scale(0.97); }
  .source-link:hover .icon, .sidebar-qr:hover .icon:last-child { transform: translate(1px,-1px); }
}

/* Keyboard operations stay immediate and never depend on animation completion. */
.motion-keyboard .btn, .motion-keyboard .btn .icon, .motion-keyboard .icon-btn,
.motion-keyboard .message-action, .motion-keyboard .message-action .icon,
.motion-keyboard .suggestions button, .motion-keyboard .language-option,
.motion-keyboard .photo-controls button, .motion-keyboard .budget-stops button,
.motion-keyboard .chip>span, .motion-keyboard .choice-check .icon,
.motion-keyboard .language-menu summary, .motion-keyboard .sos summary {
  transition: none !important;
  transform: none !important;
}
.motion-keyboard .chip input:not(:checked)+span .choice-check .icon { opacity: 0; }
.motion-keyboard .language-menu summary>.icon:last-child { transition: none; }

@media (prefers-reduced-motion: reduce) {
  .typing-dot { animation: none; transform: none; opacity: .65; }
  .btn, .btn .icon, .icon-btn, .message-action, .message-action .icon,
  .suggestions button, .language-option, .photo-controls button, .budget-stops button,
  .chip>span, .choice-check .icon, .language-menu summary>.icon:last-child,
  .source-link .icon, .sidebar-qr .icon:last-child {
    transition: none !important;
  }
  .btn:hover:not(:disabled), .btn:active:not(:disabled), .btn:hover .icon,
  .icon-btn:hover:not(:disabled), .icon-btn:active:not(:disabled),
  .message-action:hover, .message-action:active, .message-action.copied .icon,
  .suggestions button:active, .language-option:active, .photo-controls button:active,
  .budget-stops button:active, .chip input:active+span,
  .language-menu summary:active, .sos summary:active,
  .source-link:hover .icon, .sidebar-qr:hover .icon:last-child { transform: none; }
}
