:root {
  --app-motion-instant: 70ms;
  --app-motion-fast: 110ms;
  --app-motion-base: 170ms;
  --app-motion-slow: 230ms;
  --app-motion-ease: cubic-bezier(0.2, 0, 0, 1);
  --app-motion-ease-emphasized: cubic-bezier(0.22, 1, 0.36, 1);
}

@view-transition {
  navigation: auto;
}

html {
  scroll-behavior: smooth;
}

/* Keep the desktop shell visually stable while only the working area changes. */
html.app-shell .layout-menu {
  view-transition-name: app-shell-menu;
}

html.app-shell #layout-navbar {
  view-transition-name: app-shell-navbar;
}

html.app-shell .app-system-alerts {
  view-transition-name: app-system-alerts;
}

html.app-shell .app-content-viewport {
  view-transition-name: app-page-content;
}

::view-transition-group(root),
::view-transition-group(app-page-content),
::view-transition-group(app-system-alerts) {
  animation-duration: var(--app-motion-slow);
  animation-timing-function: var(--app-motion-ease-emphasized);
}

::view-transition-old(root) {
  animation: app-motion-view-old var(--app-motion-fast) ease-in both;
}

::view-transition-new(root) {
  animation: app-motion-view-new var(--app-motion-slow) var(--app-motion-ease-emphasized) both;
  mix-blend-mode: normal;
}

::view-transition-old(app-page-content) {
  animation: app-motion-content-old var(--app-motion-fast) ease-in both;
  mix-blend-mode: normal;
}

::view-transition-new(app-page-content) {
  animation: app-motion-content-new var(--app-motion-slow) var(--app-motion-ease-emphasized) both;
  mix-blend-mode: normal;
}

::view-transition-old(app-shell-menu),
::view-transition-new(app-shell-menu),
::view-transition-old(app-shell-navbar),
::view-transition-new(app-shell-navbar) {
  animation-duration: var(--app-motion-fast);
  animation-timing-function: ease-out;
  mix-blend-mode: normal;
}

.app-motion-surface {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--app-motion-fast) ease-out,
    transform var(--app-motion-base) var(--app-motion-ease);
}

html.app-motion-fallback.app-motion-entering .app-motion-surface {
  animation: app-motion-page-enter var(--app-motion-slow) var(--app-motion-ease-emphasized) both;
}

html.app-motion-fallback.app-motion-leaving .app-motion-surface {
  opacity: 0.94;
  pointer-events: none;
  transform: translateY(-2px);
  transition-duration: var(--app-motion-instant);
  transition-timing-function: ease-in;
}

.app-navigation-progress {
  position: fixed;
  inset: 0 0 auto;
  z-index: 20000;
  width: 100%;
  height: 2px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--app-motion-fast) ease-out;
}

.app-navigation-progress::before {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--bs-primary, #07894f);
  box-shadow: 0 0 8px rgba(var(--bs-primary-rgb, 7, 137, 79), 0.34);
  content: "";
  transform: scaleX(0);
  transform-origin: left center;
}

html.app-motion-busy {
  cursor: progress;
}

html.app-motion-busy .app-navigation-progress {
  opacity: 1;
  transition-delay: 110ms;
}

html.app-motion-busy .app-navigation-progress::before {
  animation: app-motion-progress 1.5s var(--app-motion-ease-emphasized) 110ms forwards;
}

.btn,
.menu-link,
.nav-link,
.dropdown-item,
.page-link,
.form-control,
.form-select,
.form-check-input,
.select2-selection,
.app-detail-action-bar a,
.app-detail-action-bar button {
  transition-duration: var(--app-motion-base);
  transition-timing-function: var(--app-motion-ease);
}

.btn {
  transition-property: color, background-color, border-color, box-shadow, opacity, transform;
}

@media (hover: hover) and (pointer: fine) {
  .btn:not(:disabled):not(.disabled):not(.is-submitting):hover {
    transform: translateY(-1px);
  }

  .menu-item:not(.active) > .menu-link:not(.menu-toggle):hover {
    transform: translateX(2px);
  }
}

.btn:not(:disabled):not(.disabled):not(.is-submitting):active {
  transform: translateY(0) scale(0.985);
  transition-duration: var(--app-motion-instant);
}

.menu-link {
  transition-property: color, background-color, box-shadow, opacity, transform;
}

a.is-navigating,
.menu-link.is-navigating {
  opacity: 0.72;
  pointer-events: none;
}

.nav-link,
.dropdown-item,
.page-link {
  transition-property: color, background-color, border-color, box-shadow, opacity, transform;
}

.dropdown-item:active,
.page-link:active {
  transform: scale(0.985);
  transition-duration: var(--app-motion-instant);
}

.form-control,
.form-select,
.form-check-input,
.select2-selection {
  transition-property: color, background-color, border-color, box-shadow, opacity;
}

.table-hover > tbody > tr,
.table tbody tr {
  transition: background-color var(--app-motion-fast) ease-out;
}

.dropdown-menu.show {
  animation: app-motion-dropdown-enter var(--app-motion-base) var(--app-motion-ease-emphasized) both;
}

.select2-dropdown,
.toast.show,
.popover.show,
.tooltip.show {
  animation: app-motion-overlay-enter var(--app-motion-base) var(--app-motion-ease-emphasized) both;
}

.alert {
  transition:
    opacity var(--app-motion-base) ease-out,
    transform var(--app-motion-base) var(--app-motion-ease);
}

.alert.fade:not(.show) {
  opacity: 0;
  transform: translateY(-4px);
}

.field-validation-error,
.validation-summary-errors {
  animation: app-motion-message-enter var(--app-motion-base) var(--app-motion-ease-emphasized) both;
}

.modal.fade .modal-dialog {
  transform: translateY(8px) scale(0.988);
  transition: transform var(--app-motion-base) var(--app-motion-ease-emphasized);
}

.modal.show .modal-dialog {
  transform: translateY(0) scale(1);
}

.modal-backdrop.fade {
  transition: opacity var(--app-motion-base) ease-out;
}

.collapse,
.collapsing,
.offcanvas,
.offcanvas-backdrop {
  transition-timing-function: var(--app-motion-ease);
}

.btn.is-submitting {
  position: relative;
  color: transparent !important;
  pointer-events: none;
  text-shadow: none !important;
}

.btn.is-submitting > * {
  opacity: 0;
}

.btn.is-submitting::after {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1rem;
  height: 1rem;
  margin: -0.5rem 0 0 -0.5rem;
  border: 2px solid rgba(var(--bs-primary-rgb, 7, 137, 79), 0.28);
  border-color: color-mix(in srgb, currentColor 32%, transparent);
  border-top-color: currentColor;
  border-radius: 50%;
  color: var(--bs-btn-color, var(--bs-primary, #07894f));
  content: "";
  animation: app-motion-spin 650ms linear infinite;
}

@keyframes app-motion-view-old {
  to {
    opacity: 0.94;
  }
}

@keyframes app-motion-view-new {
  from {
    opacity: 0.96;
  }
  to {
    opacity: 1;
  }
}

@keyframes app-motion-content-old {
  to {
    opacity: 0.82;
    transform: translateY(-2px);
  }
}

@keyframes app-motion-content-new {
  from {
    opacity: 0.78;
    transform: translateY(5px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes app-motion-page-enter {
  from {
    opacity: 0.92;
    transform: translateY(4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes app-motion-progress {
  0% {
    transform: scaleX(0);
  }
  35% {
    transform: scaleX(0.46);
  }
  70% {
    transform: scaleX(0.76);
  }
  100% {
    transform: scaleX(0.92);
  }
}

@keyframes app-motion-overlay-enter {
  from {
    opacity: 0;
    transform: translateY(3px) scale(0.995);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes app-motion-dropdown-enter {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes app-motion-message-enter {
  from {
    opacity: 0;
    transform: translateY(-2px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes app-motion-spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  * ,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-delay: 0ms !important;
    transition-duration: 0.01ms !important;
  }

  ::view-transition-old(root),
  ::view-transition-new(root),
  ::view-transition-old(app-page-content),
  ::view-transition-new(app-page-content),
  .app-motion-surface,
  html.app-motion-fallback.app-motion-entering .app-motion-surface,
  html.app-motion-fallback.app-motion-leaving .app-motion-surface,
  .btn,
  .menu-link,
  .dropdown-item,
  .page-link,
  .modal.fade .modal-dialog,
  .modal.show .modal-dialog {
    opacity: 1 !important;
    transform: none !important;
  }
}
