/* Navigation is immediate; only newly arriving content gets a short fade. */
.app-page #mainContent,
.app-page #friendsPanel,
.app-page .settings-section { animation: none; }
.app-page .view-enter,
.app-page #friendsPanel.view-enter,
.app-page .messages.chan-switch,
.app-page #settingsModalRoot .settings-panel,
.app-page #serverSettingsRoot .settings-panel {
  animation: motion-c-fade 120ms var(--ease-out);
}
.app-page .skeleton-msg { animation: motion-c-fade 120ms var(--ease-out); }
/* align-content:start keeps the header row from stretching while 1fr→0fr leaves free space. */
.app-page .cat-wrap { transition: grid-template-rows 180ms var(--ease-out); align-content: start; }
.app-page .cat-list { transition: opacity 180ms var(--ease-out); }
.app-page .cat-caret { transition: transform 180ms var(--ease-out); }

/* Old skeletons fade over the final content without affecting its layout. */
.app-page .messages { position: relative; }
.app-page .messages.skeleton-swap.chan-switch { animation: none; }
.app-page .messages > .content-arrive { animation: motion-c-fade 120ms var(--ease-out); }
.app-page .messages > .skeleton-exit { animation: none; pointer-events: none; }
.app-page .mobile-nav-enter-tab { animation: motion-c-fade 120ms var(--ease-out); }
.app-page .discover-fullscreen:not(.anim-out):not(.closing) { animation: motion-c-fade 120ms var(--ease-out); }
.app-page .discover-fullscreen:is(.anim-out, .closing) { animation: motion-c-fade-out var(--dur-pop-out) var(--ease-exit) forwards; }
.app-page .discover-fullscreen:is(.anim-out, .closing) .discover-shell { animation: none; }

/* Classes belong to actual inserts, never every render of the containing list. */
.app-page .body.msg-enter { animation: motion-c-message 140ms var(--ease-out); }
.app-page .attach-preview,
.app-page .attach-preview > *,
.app-page .typing-dots i { animation: none; }
.app-page .attach-preview > .preview-enter {
  animation: motion-c-arrive var(--dur-pop-in) var(--ease-out);
}
.app-page .reaction-chip.just-added {
  animation: motion-c-chip var(--dur-pop-in) var(--ease-out);
}
.app-page #mainContent .reaction-chip,
.app-page .reaction-chip {
  transition: background-color var(--dur-hover) var(--ease-standard), border-color var(--dur-hover) var(--ease-standard),
    scale var(--control-press-duration, var(--dur-press-out)) var(--control-press-ease, var(--ease-out));
}
.app-page .reaction-chip:hover { transform: none; }
.app-page .msg .motion-exit,
.app-page .attach-preview > .motion-exit {
  animation: motion-c-leave var(--dur-pop-out) var(--ease-exit) forwards;
  pointer-events: none;
}

/* Keep the normal-flow jump control painted until its display transition ends. */
.app-page #mainContent .jump-bottom {
  --jump-duration: 160ms;
  --jump-ease: var(--ease-exit);
  transition: opacity var(--jump-duration) var(--jump-ease), transform var(--jump-duration) var(--jump-ease),
    visibility var(--jump-duration) allow-discrete, display var(--jump-duration) allow-discrete,
    scale var(--control-press-duration, var(--dur-press-out)) var(--control-press-ease, var(--ease-out)),
    background-color var(--dur-hover) var(--ease-standard);
}
.app-page #mainContent .jump-bottom.is-visible {
  animation: none;
  --jump-duration: 220ms;
  --jump-ease: var(--ease-out);
}
@starting-style {
  .app-page #mainContent .jump-bottom.is-visible { opacity: 0; transform: translateY(8px); }
}

@media (max-width: 800px) {
  .app-page .messages.chan-switch { animation: none; }
}
@media (min-width: 801px) {
  .app-page .app.with-right .right { animation: motion-c-panel var(--dur-panel) var(--ease-out); }
}
.app-page .thread-panel-bg:not(.anim-out) .thread-panel {
  animation: motion-c-panel var(--dur-panel) var(--ease-out);
}
.app-page .thread-panel-bg.anim-out { animation: motion-c-fade-out var(--dur-sheet-out) var(--ease-exit) forwards; }
.app-page .thread-panel-bg.anim-out .thread-panel {
  animation: motion-c-panel-out var(--dur-sheet-out) var(--ease-exit) forwards;
}
@keyframes motion-c-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes motion-c-fade-out { to { opacity: 0; } }
@keyframes motion-c-message { from { transform: translateY(4px); } to { transform: none; } }
@keyframes motion-c-arrive { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@keyframes motion-c-leave { to { opacity: 0; transform: translateY(-4px); } }
@keyframes motion-c-chip { from { opacity: 0; transform: scale(.96); } to { opacity: 1; transform: none; } }
@keyframes motion-c-panel { from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: none; } }
@keyframes motion-c-panel-out { to { opacity: 0; transform: translateX(14px); } }

/* Existing global reduced-motion rules also cover descendants and skeletons. */
body.app-page.reduce-motion :is(.msg-enter, .preview-enter, .motion-exit, .jump-bottom, .thread-panel, .right, .pins-panel) {
  animation: none !important;
  transition: none !important;
}
@media (prefers-reduced-motion: reduce) {
  .app-page :is(.msg-enter, .preview-enter, .motion-exit, .jump-bottom, .thread-panel, .right, .pins-panel) {
    animation: none !important;
    transition: none !important;
  }
}
