/*
 * Async status: toast + blocking cover for work that continues after the user
 * stops looking at it.
 *
 * Built for invoice payment settlement -- a card is captured in seconds but the
 * invoice is not written until a cron drains the webhook -- and deliberately
 * kept generic so QBO sync, CSV import and campaign sends can reuse it rather
 * than each inventing another inline-styled banner.
 *
 * Depends only on design-system/tokens.css. No Bootstrap classes, no !important
 * except where it must beat a legacy status colour that ships its own.
 */

:root {
    --tt-async-toast-inset: var(--ds-space-6);
    --tt-async-toast-width: 380px;

    /* Decorative only -- a rule and a spinner arc, never a text background. */
    --tt-async-accent: var(--ds-color-teal-600);

    /* Text sits on this one, so it is a step darker: white on teal-600 measures
       3.74:1 and fails WCAG AA for body-size text, teal-700 measures 5.47:1. */
    --tt-async-accent-on-text: var(--ds-color-teal-700);
}

/* ---------------------------------------------------------------- toast --- */

.tt-async-toast {
    position: fixed;
    inset-block-end: var(--tt-async-toast-inset);
    inset-inline-end: var(--tt-async-toast-inset);
    z-index: var(--tt-z-modal-popover);

    display: flex;
    align-items: flex-start;
    gap: var(--ds-space-3);

    box-sizing: border-box;
    inline-size: max-content;
    max-inline-size: min(var(--tt-async-toast-width), calc(100vw - (var(--ds-space-4) * 2)));
    padding: var(--ds-space-3) var(--ds-space-4);

    background: var(--ds-surface-raised);
    color: var(--ds-text-primary);
    border: 1px solid var(--ds-border-subtle);
    border-inline-start: 4px solid var(--tt-async-accent);
    border-radius: var(--ds-radius-lg);
    box-shadow: var(--ds-shadow-popover);

    animation: tt-async-toast-in 220ms ease-out;
}

.tt-async-toast__title {
    font-size: var(--ds-font-size-md);
    line-height: 1.4;
}

.tt-async-toast__detail {
    margin-block-start: var(--ds-space-1);
    font-size: var(--ds-font-size-xs);
    line-height: 1.45;
    color: var(--ds-text-secondary);
}

.tt-async-toast__detail:empty {
    display: none;
}

/* --------------------------------------------------------------- spinner --- */

.tt-async-spinner {
    flex: 0 0 auto;
    inline-size: 20px;
    block-size: 20px;
    margin-block-start: 2px;
    border: 2px solid var(--ds-border-default);
    border-block-start-color: var(--tt-async-accent);
    border-radius: var(--ds-radius-pill);
    animation: tt-async-spin 900ms linear infinite;
}

.tt-async-spinner--lg {
    inline-size: 34px;
    block-size: 34px;
    border-width: 3px;
    margin-block-end: var(--ds-space-3);
    margin-inline: auto;
}

/* ----------------------------------------------------------------- cover --- */

/* Covers a container while an irreversible action is in flight, so nothing
   underneath reads as still cancellable. */
.tt-async-cover {
    position: absolute;
    inset: 0;
    z-index: var(--tt-z-modal-popover);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--ds-space-6);
    text-align: center;
    background: color-mix(in srgb, var(--ds-surface-raised) 97%, transparent);
    border-radius: inherit;
}

.tt-async-cover__label {
    font-size: var(--ds-font-size-md);
    color: var(--ds-text-primary);
}

/* Hides dismiss controls that live in their own stacking context and would
   otherwise stay clickable beneath the cover. */
.tt-async-hidden {
    display: none !important;
}

/* For actions that must not fire while irreversible work is in flight but
   should stay visible, so the page does not appear to lose functionality. */
.tt-async-disabled {
    pointer-events: none;
    opacity: 0.45;
    cursor: not-allowed;
}

/* -------------------------------------------------- legacy status badge --- */

/* The invoice status pill still ships legacy .bgm-* colours declared with
   !important, so this state has to match that weight to win. */
.tt-status-processing {
    background-color: var(--tt-async-accent-on-text) !important;
    color: #ffffff !important;
}

/* -------------------------------------------------------------- motion --- */

@keyframes tt-async-toast-in {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes tt-async-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .tt-async-toast { animation: none; }
    .tt-async-spinner { animation-duration: 2.4s; }
}
