/* =====================================================
   AXIS — motion system (2026-09-20)
   -----------------------------------------------------
   One vocabulary for how things move, layered on top of the existing
   animations rather than replacing them. Every rule here animates only
   transform, opacity or a colour; nothing touches layout. Loaded after
   components.css so its timings win, before responsive.css which stays
   last by project rule.

   Curves
     --ease-out   things ARRIVING (pages, cards, sheets): fast start, soft stop
     --ease-in    things LEAVING: soft start, gone quickly
     --ease-spring small elements that can afford a hint of overshoot (chips,
                  toggles) — never on pages or panels
   Durations
     --dur-fast 140ms  hover, press, focus
     --dur-base 220ms  cards, page enter, menus
     --dur-slow 320ms  modals, sheets, panels
   ===================================================== */
:root {
    --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
    --ease-in: cubic-bezier(0.4, 0, 1, 1);
    --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
    --ease-spring: cubic-bezier(0.34, 1.25, 0.64, 1);
    --dur-fast: 140ms;
    --dur-base: 220ms;
    --dur-slow: 320ms;
    /* The three legacy tokens (styles.css) used a plain `ease`; every rule
       that references them now decelerates properly. */
    --transition-fast: var(--dur-fast) var(--ease-out);
    --transition-normal: var(--dur-base) var(--ease-out);
    --transition-slow: var(--dur-slow) var(--ease-out);
}

/* ── Page enter ──────────────────────────────────────── */
@keyframes axisPageEnter {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}
.animate-fadeIn { animation: axisPageEnter var(--dur-base) var(--ease-out) both; }

/* ── Lists: a short stagger on the first rows only ───────
   Twelve steps of 22ms = the last card lands 264ms after the first; past
   that everything is already in place, so a 100-row page never waits. */
@keyframes axisItemEnter {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
}
.property-card, .order-card, .prop-card, .kanban-card,
.dashboard-widget, .quick-stat-card, .stat-card, .kpi-card,
.contacts-table tbody .contact-row, .contact-card,
.training-course-card, .lb-row, .ranking-row, .changelog-entry {
    animation: axisItemEnter var(--dur-base) var(--ease-out) both;
}
.property-card:nth-child(2),  .order-card:nth-child(2),  .prop-card:nth-child(2),  .kanban-card:nth-child(2),  .dashboard-widget:nth-child(2),  .quick-stat-card:nth-child(2),  .stat-card:nth-child(2),  .kpi-card:nth-child(2),  .contact-row:nth-child(2),  .contact-card:nth-child(2),  .training-course-card:nth-child(2),  .lb-row:nth-child(2),  .ranking-row:nth-child(2),  .changelog-entry:nth-child(2)  { animation-delay: 22ms; }
.property-card:nth-child(3),  .order-card:nth-child(3),  .prop-card:nth-child(3),  .kanban-card:nth-child(3),  .dashboard-widget:nth-child(3),  .quick-stat-card:nth-child(3),  .stat-card:nth-child(3),  .kpi-card:nth-child(3),  .contact-row:nth-child(3),  .contact-card:nth-child(3),  .training-course-card:nth-child(3),  .lb-row:nth-child(3),  .ranking-row:nth-child(3),  .changelog-entry:nth-child(3)  { animation-delay: 44ms; }
.property-card:nth-child(4),  .order-card:nth-child(4),  .prop-card:nth-child(4),  .kanban-card:nth-child(4),  .dashboard-widget:nth-child(4),  .quick-stat-card:nth-child(4),  .stat-card:nth-child(4),  .kpi-card:nth-child(4),  .contact-row:nth-child(4),  .contact-card:nth-child(4),  .training-course-card:nth-child(4),  .lb-row:nth-child(4),  .ranking-row:nth-child(4),  .changelog-entry:nth-child(4)  { animation-delay: 66ms; }
.property-card:nth-child(5),  .order-card:nth-child(5),  .prop-card:nth-child(5),  .kanban-card:nth-child(5),  .dashboard-widget:nth-child(5),  .quick-stat-card:nth-child(5),  .stat-card:nth-child(5),  .kpi-card:nth-child(5),  .contact-row:nth-child(5),  .contact-card:nth-child(5),  .training-course-card:nth-child(5),  .lb-row:nth-child(5),  .ranking-row:nth-child(5),  .changelog-entry:nth-child(5)  { animation-delay: 88ms; }
.property-card:nth-child(6),  .order-card:nth-child(6),  .prop-card:nth-child(6),  .kanban-card:nth-child(6),  .dashboard-widget:nth-child(6),  .quick-stat-card:nth-child(6),  .stat-card:nth-child(6),  .kpi-card:nth-child(6),  .contact-row:nth-child(6),  .contact-card:nth-child(6),  .training-course-card:nth-child(6),  .lb-row:nth-child(6),  .ranking-row:nth-child(6),  .changelog-entry:nth-child(6)  { animation-delay: 110ms; }
.property-card:nth-child(7),  .order-card:nth-child(7),  .prop-card:nth-child(7),  .kanban-card:nth-child(7),  .dashboard-widget:nth-child(7),  .quick-stat-card:nth-child(7),  .stat-card:nth-child(7),  .kpi-card:nth-child(7),  .contact-row:nth-child(7),  .contact-card:nth-child(7),  .training-course-card:nth-child(7),  .lb-row:nth-child(7),  .ranking-row:nth-child(7),  .changelog-entry:nth-child(7)  { animation-delay: 132ms; }
.property-card:nth-child(8),  .order-card:nth-child(8),  .prop-card:nth-child(8),  .kanban-card:nth-child(8),  .dashboard-widget:nth-child(8),  .quick-stat-card:nth-child(8),  .stat-card:nth-child(8),  .kpi-card:nth-child(8),  .contact-row:nth-child(8),  .contact-card:nth-child(8),  .training-course-card:nth-child(8),  .lb-row:nth-child(8),  .ranking-row:nth-child(8),  .changelog-entry:nth-child(8)  { animation-delay: 154ms; }
.property-card:nth-child(9),  .order-card:nth-child(9),  .prop-card:nth-child(9),  .kanban-card:nth-child(9),  .dashboard-widget:nth-child(9),  .quick-stat-card:nth-child(9),  .stat-card:nth-child(9),  .kpi-card:nth-child(9),  .contact-row:nth-child(9),  .contact-card:nth-child(9),  .training-course-card:nth-child(9),  .lb-row:nth-child(9),  .ranking-row:nth-child(9),  .changelog-entry:nth-child(9)  { animation-delay: 176ms; }
.property-card:nth-child(10), .order-card:nth-child(10), .prop-card:nth-child(10), .kanban-card:nth-child(10), .dashboard-widget:nth-child(10), .quick-stat-card:nth-child(10), .stat-card:nth-child(10), .kpi-card:nth-child(10), .contact-row:nth-child(10), .contact-card:nth-child(10), .training-course-card:nth-child(10), .lb-row:nth-child(10), .ranking-row:nth-child(10), .changelog-entry:nth-child(10) { animation-delay: 198ms; }
.property-card:nth-child(11), .order-card:nth-child(11), .prop-card:nth-child(11), .kanban-card:nth-child(11), .dashboard-widget:nth-child(11), .quick-stat-card:nth-child(11), .stat-card:nth-child(11), .kpi-card:nth-child(11), .contact-row:nth-child(11), .contact-card:nth-child(11), .training-course-card:nth-child(11), .lb-row:nth-child(11), .ranking-row:nth-child(11), .changelog-entry:nth-child(11) { animation-delay: 220ms; }
.property-card:nth-child(12), .order-card:nth-child(12), .prop-card:nth-child(12), .kanban-card:nth-child(12), .dashboard-widget:nth-child(12), .quick-stat-card:nth-child(12), .stat-card:nth-child(12), .kpi-card:nth-child(12), .contact-row:nth-child(12), .contact-card:nth-child(12), .training-course-card:nth-child(12), .lb-row:nth-child(12), .ranking-row:nth-child(12), .changelog-entry:nth-child(12) { animation-delay: 242ms; }
/* Rows further down are in place from the start. */
.property-card:nth-child(n+13), .order-card:nth-child(n+13), .prop-card:nth-child(n+13), .kanban-card:nth-child(n+13), .dashboard-widget:nth-child(n+13), .contact-row:nth-child(n+13), .contact-card:nth-child(n+13), .lb-row:nth-child(n+13), .ranking-row:nth-child(n+13), .changelog-entry:nth-child(n+13) { animation: none; }

/* ── Hover on pointer devices only ───────────────────────
   A touch screen has no hover; a lifted card that never settles reads as
   stuck. `@media (hover: hover)` keeps this to mice and trackpads. */
@media (hover: hover) {
    .property-card, .prop-card, .contact-card, .training-course-card, .dashboard-widget, .kanban-card {
        transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
    }
    .property-card:hover, .prop-card:hover, .contact-card:hover, .training-course-card:hover, .kanban-card:hover {
        transform: translateY(-2px);
        box-shadow: 0 10px 24px -12px rgba(15, 23, 42, 0.18), 0 2px 6px -2px rgba(15, 23, 42, 0.08);
    }
    .btn-primary:hover, .btn-secondary:hover, .btn-outline:hover { transform: translateY(-1px); }
}

/* ── Press feedback: every button, chip and nav item ───── */
.btn, .filter-chip, .mobile-nav-item, .nav-item, .tab, .tasks-pill, .period-btn,
.lb-period button, .lb-board-toggle button, .filters-toggle, .btn-icon, .modal-close {
    transition-property: color, background-color, border-color, box-shadow, transform, opacity, filter, outline-color;
    transition-duration: var(--dur-fast);
    transition-timing-function: var(--ease-out);
}
.btn:active, .filter-chip:active, .filters-toggle:active, .btn-icon:active, .modal-close:active,
.lb-period button:active, .lb-board-toggle button:active, .mobile-nav-item:active {
    transform: scale(0.97);
    transition-duration: 60ms;
}
.filter-chip.active, .filter-chip.is-active { transition-timing-function: var(--ease-spring); }

/* ── Modals: overlay fades, panel rises and settles ───────
   The panel's own `scaleIn` (styles.css) is kept as the fallback; this
   sequence replaces it for the shared modal + the record detail modal. */
@keyframes axisOverlayIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes axisPanelIn {
    from { opacity: 0; transform: translateY(10px) scale(0.985); }
    to   { opacity: 1; transform: none; }
}
.modal.open .modal-overlay { animation: axisOverlayIn var(--dur-base) var(--ease-out) both; }
.modal.open .modal-container { animation: axisPanelIn var(--dur-slow) var(--ease-out) both; }

/* Phone: modals are bottom sheets; they slide from below. */
@keyframes axisSheetIn {
    from { opacity: 0; transform: translateY(24px); }
    to   { opacity: 1; transform: none; }
}
@media (max-width: 768px) {
    .modal.open .modal-container { animation: axisSheetIn var(--dur-slow) var(--ease-out) both; }
}

/* The record detail panel (#property-slideout) */
#property-slideout { transition: transform var(--dur-slow) var(--ease-out), opacity var(--dur-slow) var(--ease-out); }

/* Notifications panel + the More sheet + dropdown menus */
@keyframes axisPopIn {
    from { opacity: 0; transform: translateY(-6px) scale(0.98); }
    to   { opacity: 1; transform: none; }
}
#notifications-panel:not(.hidden), .dropdown.open .dropdown-menu, .slideout-dropdown, .user-picker-menu, .ap-usel-menu {
    animation: axisPopIn var(--dur-base) var(--ease-out) both;
}
.mobile-nav-group.open .mobile-nav-group-menu .mobile-nav-group-item {
    animation: axisItemEnter var(--dur-base) var(--ease-out) both;
}
.mobile-nav-group.open .mobile-nav-group-menu .mobile-nav-group-item:nth-child(2) { animation-delay: 30ms; }
.mobile-nav-group.open .mobile-nav-group-menu .mobile-nav-group-item:nth-child(3) { animation-delay: 60ms; }
.mobile-nav-group.open .mobile-nav-group-menu .mobile-nav-group-item:nth-child(4) { animation-delay: 90ms; }
.mobile-nav-group.open .mobile-nav-group-menu .mobile-nav-group-item:nth-child(5) { animation-delay: 120ms; }

/* ── Toasts: rise in, fall away ───────────────────────── */
@keyframes axisToastIn {
    from { opacity: 0; transform: translateY(8px) scale(0.98); }
    to   { opacity: 1; transform: none; }
}
@keyframes axisToastOut {
    from { opacity: 1; transform: none; }
    to   { opacity: 0; transform: translateY(6px); }
}
.toast { animation: axisToastIn var(--dur-base) var(--ease-out) both; }
.toast.toast-leaving { animation: axisToastOut var(--dur-base) var(--ease-in) both; }

/* ── Empty states: the icon settles, the copy follows ───── */
.empty-state .empty-state-icon, .empty-state > .material-icons-outlined:first-child {
    animation: axisPanelIn var(--dur-slow) var(--ease-out) both;
}
.empty-state .empty-state-title, .empty-state .empty-state-description {
    animation: axisItemEnter var(--dur-base) var(--ease-out) both;
    animation-delay: 60ms;
}

/* ── Skeleton: an opacity pulse, never a light sweep ───── */
@keyframes axisSkeleton { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }
.skeleton {
    display: block;
    background: var(--bg-tertiary);
    border-radius: var(--radius-sm);
    animation: axisSkeleton 1.4s var(--ease-in-out) infinite;
    min-height: 12px;
}
.skeleton-line { height: 12px; margin: 6px 0; }
.skeleton-line.w-60 { width: 60%; }
.skeleton-line.w-40 { width: 40%; }
.skeleton-line.w-80 { width: 80%; }
.skeleton-circle { width: 32px; height: 32px; border-radius: 50%; }
.skeleton-block { height: 72px; border-radius: var(--radius-md); }

/* ── Route change: the header title cross-fades ─────────── */
#header-page-title { transition: opacity var(--dur-fast) var(--ease-out); }

/* ── Reduced motion: still instant, still complete ────────
   The global rule in responsive.css shrinks every duration to 0.01ms; the
   stagger delays must go too or rows would appear one by one anyway. */
@media (prefers-reduced-motion: reduce) {
    .property-card, .order-card, .prop-card, .kanban-card, .dashboard-widget, .quick-stat-card, .stat-card, .kpi-card,
    .contact-row, .contact-card, .training-course-card, .lb-row, .ranking-row, .changelog-entry,
    .mobile-nav-group-item, .empty-state .empty-state-title, .empty-state .empty-state-description {
        animation-delay: 0ms !important;
    }
    .skeleton { animation: none; opacity: 0.7; }
}

/* ── Touch reach for the inline links inside detail panels ──
   The phone/email rows in the contact panel measured 21px tall. */
@media (max-width: 768px) {
    .slideout-body .detail-link, .slideout-body .contact-link { min-height: 36px; display: inline-flex; align-items: center; }
}

/* =====================================================
   Live layer (2026-09-21) — the app should feel like it is
   responding, never like it is decorating. Same rules as above:
   transform / opacity / colour only, every entrance settles
   within ~300ms, nothing loops except the skeleton pulse and a
   busy button.
   ===================================================== */

/* ── Route change: only the page region transitions ────────
   The View Transitions API (Router.renderPage) cross-fades the OLD page
   out while the NEW one rises 6px. The shell (sidebar, header, nav) is
   not part of the snapshot because #page-content carries its own
   view-transition-name, so nothing outside the page moves. Browsers
   without the API keep the .animate-fadeIn entrance. */
#page-content { view-transition-name: axis-page; }
::view-transition-old(axis-page) { animation: axisPageOut var(--dur-fast) var(--ease-in) both; }
::view-transition-new(axis-page) { animation: axisPageEnter var(--dur-base) var(--ease-out) both; }
@keyframes axisPageOut { from { opacity: 1; } to { opacity: 0; } }
/* The View Transition already animates the page; the class-based
   entrance would double it. Router sets html.vt-active for the duration. */
html.vt-active #page-content.animate-fadeIn { animation: none; }

/* ── Numbers count up on arrival (Motion.countUp) ───────── */
.is-counting { font-variant-numeric: tabular-nums; }

/* ── Progress and meters grow from the left ─────────────── */
@keyframes axisGrowX { from { transform: scaleX(0); } to { transform: none; } }
.training-progress-fill, .training-card-progress-fill, .training-lesson-progress-fill,
.training-tracking-mini-fill, .analytics-product-bar-fill, .analytics-geo-bar-fill,
.mt-bar-fill, .progress-fill, .progress-bar-fill, .bonus-progress-fill, .tier-progress-fill,
.onboarding-progress-fill, .points-progress-fill, .lb-bar-fill {
    transform-origin: left center;
    animation: axisGrowX 600ms var(--ease-out) both;
    animation-delay: 80ms;
}

/* ── Tables: rows settle in, hover answers instantly ─────── */
#page-content table tbody tr { transition: background-color var(--dur-fast) var(--ease-out); }
#page-content table tbody tr:nth-child(-n+12) { animation: axisItemEnter var(--dur-base) var(--ease-out) both; }
#page-content table tbody tr:nth-child(2)  { animation-delay: 18ms; }
#page-content table tbody tr:nth-child(3)  { animation-delay: 36ms; }
#page-content table tbody tr:nth-child(4)  { animation-delay: 54ms; }
#page-content table tbody tr:nth-child(5)  { animation-delay: 72ms; }
#page-content table tbody tr:nth-child(6)  { animation-delay: 90ms; }
#page-content table tbody tr:nth-child(7)  { animation-delay: 108ms; }
#page-content table tbody tr:nth-child(8)  { animation-delay: 126ms; }
#page-content table tbody tr:nth-child(9)  { animation-delay: 144ms; }
#page-content table tbody tr:nth-child(10) { animation-delay: 162ms; }
#page-content table tbody tr:nth-child(11) { animation-delay: 180ms; }
#page-content table tbody tr:nth-child(12) { animation-delay: 198ms; }

/* ── Detail panel: the cards inside arrive after the panel ── */
#property-slideout.open .slideout-body > .card,
#property-slideout.open .slideout-body .detail-grid > .card,
#property-slideout.open .slideout-body .contact-details-section {
    animation: axisItemEnter var(--dur-base) var(--ease-out) both;
    animation-delay: 120ms;
}
#property-slideout.open .slideout-body > .card:nth-child(2),
#property-slideout.open .slideout-body .detail-grid > .card:nth-child(2) { animation-delay: 150ms; }
#property-slideout.open .slideout-body > .card:nth-child(3),
#property-slideout.open .slideout-body .detail-grid > .card:nth-child(3) { animation-delay: 180ms; }
#property-slideout.open .slideout-body > .card:nth-child(4),
#property-slideout.open .slideout-body .detail-grid > .card:nth-child(4) { animation-delay: 210ms; }
#property-slideout.open .slideout-body > .card:nth-child(n+5),
#property-slideout.open .slideout-body .detail-grid > .card:nth-child(n+5) { animation-delay: 240ms; }

/* ── Tabs and segmented controls: colour glides, a press settles ── */
.builder-tab, .user-detail-tab, .settings-tab, .view-tab, .training-cat-tab, .tab-btn,
.recruitment-tab, .lb-tab, .chat-emoji-tab, .srb-tab, .profile-tab, .commission-tab,
.appinfo-nav-item, .catalog-view-btn, .prop-status-filter, .tasks-pill, .changelog-chip {
    transition: color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out),
                transform var(--dur-fast) var(--ease-out);
}
.builder-tab:active, .user-detail-tab:active, .settings-tab:active, .view-tab:active,
.training-cat-tab:active, .tab-btn:active, .recruitment-tab:active, .lb-tab:active,
.appinfo-nav-item:active, .tasks-pill:active, .changelog-chip:active { transform: scale(0.97); transition-duration: 60ms; }

/* ── Sidebar: the active pill slides its accent in ────────── */
@keyframes axisAccentIn { from { transform: translateY(-50%) scaleY(0); } to { transform: translateY(-50%) scaleY(1); } }
.nav-item.active::before { animation: axisAccentIn var(--dur-base) var(--ease-out) both; }
.nav-item .material-icons-outlined { transition: transform var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out); }
@media (hover: hover) {
    .nav-item:hover .material-icons-outlined { transform: translateX(1px); }
}

/* ── Badges: a count that changed pops once (Motion.badges) ── */
@keyframes axisBadgePop {
    0%   { transform: scale(1); }
    40%  { transform: scale(1.28); }
    100% { transform: scale(1); }
}
.nav-badge, .notification-badge { transform-origin: center; }
.badge-pop { animation: axisBadgePop 360ms var(--ease-spring) both; }

/* ── Chat: the newest messages arrive, older history is in place ── */
.chat-message:nth-last-child(-n+6) { animation: axisItemEnter var(--dur-base) var(--ease-out) both; }
.chat-message:nth-last-child(2) { animation-delay: 20ms; }
.chat-message:nth-last-child(1) { animation-delay: 40ms; }
.chat-nav-item, .chat-message-reaction { transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out); }
.chat-message-reaction:active { transform: scale(0.94); }

/* ── Phone filter bars unfold: rows step in ──────────────── */
.orders-filters:not(.filters-collapsed) .filter-row,
.properties-filters:not(.filters-collapsed) .filter-row,
.filters-bar:not(.filters-collapsed) .filter-row {
    animation: axisItemEnter var(--dur-base) var(--ease-out) both;
}
.orders-filters:not(.filters-collapsed) .filter-row:nth-child(2),
.properties-filters:not(.filters-collapsed) .filter-row:nth-child(2),
.filters-bar:not(.filters-collapsed) .filter-row:nth-child(2) { animation-delay: 40ms; }

/* ── Saving: a busy button breathes, it does not freeze ────── */
@keyframes axisBusy { 0%, 100% { opacity: 1; } 50% { opacity: 0.66; } }
.btn[aria-busy="true"], form[data-submitting] .btn[type="submit"] { animation: axisBusy 1.1s var(--ease-in-out) infinite; }

/* ── Scroll reveal for content below the fold (Motion.reveal) ──
   Elements are marked only when they start below the viewport; when
   scrolled into view they rise into place. Motion reveals everything
   after 1.5s regardless, so nothing can stay hidden. */
.reveal-pending { opacity: 0; transform: translateY(10px); }
.reveal-in { animation: axisItemEnter var(--dur-slow) var(--ease-out) both; }

/* ── Focus rings ease in; stat cards and icon buttons answer hover ── */
:is(button, a, input, select, textarea, [tabindex]):focus-visible { transition: box-shadow var(--dur-fast) var(--ease-out), outline-color var(--dur-fast) var(--ease-out); }
@media (hover: hover) {
    .btn-icon, .header-btn, #header-profile-btn, .stat-card, .quick-stat-card, .kpi-card, .commission-stat-card {
        transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
    }
    .btn-icon:hover, .header-btn:hover { transform: translateY(-1px); }
    .stat-card:hover, .quick-stat-card:hover, .kpi-card:hover, .commission-stat-card:hover { transform: translateY(-1px); box-shadow: 0 8px 18px -12px rgba(15, 23, 42, 0.18); }
}

/* ── Reduced motion: the live layer goes still too ────────── */
@media (prefers-reduced-motion: reduce) {
    ::view-transition-old(axis-page), ::view-transition-new(axis-page) { animation: none; }
    .training-progress-fill, .training-card-progress-fill, .training-lesson-progress-fill, .training-tracking-mini-fill,
    .analytics-product-bar-fill, .analytics-geo-bar-fill, .mt-bar-fill, .progress-fill, .progress-bar-fill,
    .bonus-progress-fill, .tier-progress-fill, .onboarding-progress-fill, .points-progress-fill, .lb-bar-fill,
    #page-content table tbody tr, #property-slideout.open .slideout-body .card, .chat-message, .filter-row,
    .nav-item.active::before, .badge-pop, .reveal-in, .btn[aria-busy="true"] { animation: none !important; animation-delay: 0ms !important; }
    .reveal-pending { opacity: 1; transform: none; }
}
