/* One restrained motion system for the web console, admin panel and updater. */
:root {
  --motion-ease: cubic-bezier(.2, .7, .2, 1);
  --motion-enter-ease: cubic-bezier(.16, 1, .3, 1);
  --motion-fast: 150ms;
  --motion-base: 220ms;
  --motion-enter: 300ms;
  --motion-exit: 160ms;
  --motion-spring: var(--motion-enter-ease);
  --motion-medium: var(--motion-enter);
}

html { scroll-behavior: smooth; }

button {
  transition: color var(--motion-fast) ease, background-color var(--motion-fast) ease,
    border-color var(--motion-fast) ease, box-shadow var(--motion-fast) ease,
    transform var(--motion-fast) var(--motion-ease);
}
button:active:not(:disabled) { transform: scale(.985); }
a, .nav-item {
  transition: color var(--motion-fast) ease, background-color var(--motion-fast) ease,
    border-color var(--motion-fast) ease, transform var(--motion-fast) var(--motion-ease);
}
input, select {
  transition: color var(--motion-fast) ease, background-color var(--motion-fast) ease,
    border-color var(--motion-fast) ease, box-shadow var(--motion-fast) ease;
}
input[type="search"], dialog input, input[type="checkbox"],
.settings input::after, .invite-form input, .invite-form select,
.role-select, .log-advanced-grid input, .log-advanced-grid select {
  transition-duration: var(--motion-fast);
  transition-timing-function: ease;
}
html.theme-transition body, html.theme-transition .sidebar, html.theme-transition main,
html.theme-transition .status-card, html.theme-transition .metric-card,
html.theme-transition .surface-card, html.theme-transition .admin-section,
html.theme-transition .bot-deck, html.theme-transition .summary article,
html.theme-transition .invite-card, html.theme-transition button,
html.theme-transition input, html.theme-transition select {
  transition-duration: 180ms;
  transition-timing-function: ease;
}

.status-card, .metric-card, .surface-card, .summary article, .bot-deck,
.admin-section, .invite-card, .diagnostic-item, .token-row, .backup-row,
.audit-group, .updates-grid article, .update-versions article {
  transition: transform var(--motion-base) var(--motion-ease),
    border-color var(--motion-base) ease, background-color var(--motion-base) ease,
    box-shadow var(--motion-base) ease;
}
.metric-card:hover { transform: translateY(-2px); }
.surface-card:hover { border-color: color-mix(in srgb, var(--mint) 24%, var(--line)); }
.diagnostic-item:hover, .token-row:hover, .backup-row:hover { transform: translateX(2px); }

/* Short, low-distance arrivals. Reveal targets are shown once, not on every refresh. */
.workspace-view:not([hidden]) { animation: motion-view-enter 280ms var(--motion-enter-ease) both; }
.shell > .sidebar { animation: motion-enter 300ms var(--motion-enter-ease) both; }
.shell > main { animation: motion-enter 320ms 35ms var(--motion-enter-ease) both; }
.view-intro { animation: motion-enter 260ms 20ms var(--motion-enter-ease) both; }
.admin-header, .update-header, .public-status-card { animation: motion-enter 300ms var(--motion-enter-ease) both; }
.update-hero { animation: motion-enter 320ms 35ms var(--motion-enter-ease) both; }
.public-status-card .status-card.is-ready { animation: motion-enter 220ms var(--motion-enter-ease) both; }
.motion-reveal-fallback .metric-card, .motion-reveal-fallback .surface-card,
.motion-reveal-fallback .admin-section, .motion-reveal-fallback .summary article,
.motion-reveal-fallback .bot-deck, .motion-reveal-fallback .update-versions,
.motion-reveal-fallback .update-timeline { animation: motion-enter 280ms var(--motion-enter-ease) both; }
.summary article:nth-child(2) { --reveal-delay: 35ms; }
.summary article:nth-child(3) { --reveal-delay: 70ms; }
.dashboard-grid .metric-card:nth-child(2) { --reveal-delay: 30ms; }
.dashboard-grid .metric-card:nth-child(3) { --reveal-delay: 60ms; }
.dashboard-grid .metric-card:nth-child(4) { --reveal-delay: 90ms; }
[data-reveal="waiting"] { opacity: 0; transform: translateY(8px); }
[data-reveal="shown"] {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 260ms var(--motion-ease) var(--reveal-delay, 0ms),
    transform 300ms var(--motion-enter-ease) var(--reveal-delay, 0ms),
    border-color var(--motion-base) ease, background-color var(--motion-base) ease,
    box-shadow var(--motion-base) ease;
}

.brand-mark::before, .brand-mark::after { animation: none; }
.status-card.online .dot, .bot-orbit span.online { animation: motion-status-breathe 3.2s ease-in-out infinite; }
.live-badge { animation: none; }
.live-badge i { animation: motion-signal-breathe 3s ease-in-out infinite; }
#stream-state i { animation: none; }
#stream-state.online i { animation: motion-signal-breathe 3s ease-in-out infinite; }
body::after { animation: none; }
.bot-deck::after { animation: none; }
.nav-item.active::before { animation: marker-enter 180ms var(--motion-enter-ease) both; }
.notice { animation: notice-enter 220ms var(--motion-enter-ease) both; }
.notice.is-leaving { animation: notice-exit 160ms ease-in both; pointer-events: none; }
.value-change { animation: value-change 180ms var(--motion-enter-ease); transform-origin: left center; }
.timeline-enter { animation: motion-enter 220ms var(--motion-enter-ease) both; }

dialog {
  opacity: 0;
  transform: translateY(6px) scale(.995);
  transition: opacity var(--motion-exit) ease, transform var(--motion-exit) var(--motion-ease);
}
dialog[open] { opacity: 1; transform: none; }
dialog[open] { animation: none; }
dialog[open]::backdrop { opacity: 1; transition: opacity var(--motion-exit) ease; }
dialog::backdrop { opacity: 0; transition: opacity var(--motion-exit) ease; }
@supports (transition-behavior: allow-discrete) {
  dialog { transition: opacity var(--motion-exit) ease, transform var(--motion-exit) var(--motion-ease), overlay var(--motion-exit) allow-discrete, display var(--motion-exit) allow-discrete; }
}
@supports not (transition-behavior: allow-discrete) {
  dialog[open] { animation: motion-enter var(--motion-enter) var(--motion-enter-ease) both; }
}
@starting-style {
  dialog[open] { opacity: 0; transform: translateY(6px) scale(.995); }
  dialog[open]::backdrop { opacity: 0; }
}

.log-advanced.is-closing .log-advanced-grid { opacity: 0; transform: translateY(-4px); }

@keyframes motion-enter { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes motion-view-enter { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }
@keyframes notice-enter { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: none; } }
@keyframes notice-exit { to { opacity: 0; transform: translateY(-4px); } }
@keyframes marker-enter { from { transform: scaleY(.55); opacity: .45; } to { transform: scaleY(1); opacity: 1; } }
@keyframes motion-signal-breathe { 50% { opacity: .68; } }
@keyframes motion-status-breathe { 50% { opacity: .82; } }
@keyframes value-change { 0% { transform: translateY(2px); opacity: .78; } 100% { transform: none; opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    scroll-behavior: auto !important;
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    transition-delay: 0ms !important;
  }
  [data-reveal="waiting"], [data-reveal="shown"] { opacity: 1; transform: none; transition: none !important; }
  dialog, dialog[open] { opacity: 1; transform: none; }
}
