/*
 * The dock of work in flight, bottom right.
 *
 * Plain CSS for the reason every bespoke stylesheet in this project is: the
 * panels have no Vite build and serve Filament's pre-compiled app.css, so
 * `class="flex gap-2"` written in a Blade view here is inert markup.
 *
 * Registered on **both** panels — an operator watching the admin panel has more
 * need of this than a customer — so it is added in each provider's Css::make
 * list separately rather than once globally.
 *
 *     Css::make('running-tasks', resource_path('css/running-tasks.css'))
 *
 * `php artisan filament:assets` copies it to public/css/app/running-tasks.css,
 * so editing this file needs that command re-run.
 *
 * ## It is built to look like a notification, on purpose
 *
 * Filament's toasts land in the same corner, and somebody who has learned that
 * things there are the panel talking to them should not have to learn a second
 * grammar. So: the same rounded card, the same shadow, the same title-plus-
 * detail stack. The differences are the ones that carry meaning — this one has a
 * spinner rather than a status icon, no close button because it leaves when the
 * work does, and a progress bar along the bottom.
 *
 * It follows the panel's theme rather than being dark in both, which is what it
 * was first written as. Measured on the running panel, a Filament surface is
 * `#fff` under a light theme and `oklch(0.21 …)` — gray-900 — under a dark one,
 * so a card that is dark in both is a black box on a white page. Every other
 * stylesheet in this project already encodes that pair; this one now does too.
 *
 * The namespace is `rt-`, apart from `wl-`, `oc-` and `sv-` for the reason
 * those three are apart from each other: all of them load on every page.
 */

/* Above the content and below Filament's own toasts, which sit at z-index 40 in
   a container anchored to the same corner. Stacking under them is deliberate: a
   toast is an event that just happened and should not be pushed off screen by a
   rebuild that has been running for ten minutes. */
.rt-dock {
    position: fixed;
    right: 1rem;
    bottom: 1rem;
    z-index: 30;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    width: min(22rem, calc(100vw - 2rem));
    pointer-events: none;
}

/* The cards take clicks; the container does not, so an empty dock is not an
   invisible sheet over the bottom-right corner of every page. */
.rt-dock > * {
    pointer-events: auto;
}

.rt-card {
    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
    gap: 0.625rem;
    padding: 0.75rem 0.875rem 0.875rem;
    overflow: hidden;
    border-radius: var(--radius-xl, 0.75rem);
    text-decoration: none;
    background-color: var(--color-white, #fff);
    box-shadow:
        0 0 0 1px var(--gray-200),
        0 10px 15px -3px rgb(0 0 0 / 10%),
        0 4px 6px -4px rgb(0 0 0 / 10%);
    transition:
        transform 120ms ease,
        box-shadow 120ms ease;
}

/* Lifted a pixel on hover rather than tinted: the card is a link, and the one
   thing it must not do is look like it has changed state. */
.rt-card:hover {
    transform: translateY(-1px);
    box-shadow:
        0 0 0 1px var(--gray-300),
        0 12px 20px -4px rgb(0 0 0 / 14%);
}

.rt-card:focus-visible {
    outline: 2px solid var(--primary-500);
    outline-offset: 2px;
}

.dark .rt-card {
    background-color: var(--gray-900);
    box-shadow:
        0 0 0 1px var(--gray-700),
        0 10px 15px -3px rgb(0 0 0 / 30%),
        0 4px 6px -4px rgb(0 0 0 / 30%);
}

.dark .rt-card:hover {
    box-shadow:
        0 0 0 1px var(--gray-600),
        0 12px 20px -4px rgb(0 0 0 / 38%);
}

.dark .rt-card:focus-visible {
    outline-color: var(--primary-400);
}

/* ------------------------------------------------------------------ *
 * The spinner — where a toast puts its status icon
 * ------------------------------------------------------------------ */

.rt-spinner {
    width: 1.125rem;
    height: 1.125rem;
    margin-top: 0.0625rem;
    border-radius: 50%;
    border: 2px solid color-mix(in oklab, var(--primary-500) 25%, transparent);
    border-top-color: var(--primary-500);
    animation: rt-spin 900ms linear infinite;
}

/* A queued task has not started, so a spinner would claim work nobody is doing
   yet. It pulses instead — present, waiting, not pretending. */
.rt-card--queued .rt-spinner {
    border-color: var(--gray-300);
    border-top-color: var(--gray-300);
    animation: rt-wait 1.6s ease-in-out infinite;
}

.dark .rt-spinner {
    border-color: color-mix(in oklab, var(--primary-400) 30%, transparent);
    border-top-color: var(--primary-400);
}

.dark .rt-card--queued .rt-spinner {
    border-color: var(--gray-600);
    border-top-color: var(--gray-600);
}

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

@keyframes rt-wait {
    0%,
    100% {
        opacity: 0.35;
    }

    50% {
        opacity: 1;
    }
}

/* Respect a reader who has asked for less movement. The card still says what is
   running and for how long, which is the information; the spin was never it. */
@media (prefers-reduced-motion: reduce) {
    .rt-spinner,
    .rt-card--queued .rt-spinner {
        animation: none;
    }

    .rt-bar-run {
        animation: none;
        width: 100%;
        opacity: 0.4;
    }
}

/* ------------------------------------------------------------------ *
 * The words
 * ------------------------------------------------------------------ */

.rt-body {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
}

.rt-title {
    font-size: var(--text-sm, 0.875rem);
    font-weight: 600;
    line-height: 1.25rem;
    color: var(--gray-950);
}

.rt-detail {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--text-xs, 0.75rem);
    line-height: 1.125rem;
    color: var(--gray-500);
}

.dark .rt-title {
    color: var(--gray-50);
}

.dark .rt-detail {
    color: var(--gray-400);
}

.rt-dot {
    margin: 0 0.3125rem;
    opacity: 0.6;
}

/* ------------------------------------------------------------------ *
 * The bar — indeterminate, because there is no honest percentage
 * ------------------------------------------------------------------ */

.rt-bar {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    height: 2px;
    overflow: hidden;
    background-color: var(--gray-100);
}

.dark .rt-bar {
    background-color: color-mix(in oklab, var(--gray-50) 10%, transparent);
}

/* A segment that travels rather than a fill that grows: a bar that advances
   predicts an end, and nothing here knows when a reboot finishes. */
.rt-bar-run {
    display: block;
    width: 35%;
    height: 100%;
    border-radius: 999px;
    background-color: var(--primary-500);
    animation: rt-travel 1.4s ease-in-out infinite;
}

.rt-card--queued .rt-bar-run {
    background-color: var(--gray-400);
}

.dark .rt-bar-run {
    background-color: var(--primary-400);
}

.dark .rt-card--queued .rt-bar-run {
    background-color: var(--gray-500);
}

@keyframes rt-travel {
    0% {
        transform: translateX(-100%);
    }

    100% {
        transform: translateX(300%);
    }
}

/* ------------------------------------------------------------------ *
 * The overflow line
 * ------------------------------------------------------------------ */

.rt-more {
    align-self: flex-end;
    padding: 0.25rem 0.625rem;
    border-radius: 999px;
    font-size: var(--text-xs, 0.75rem);
    color: var(--gray-500);
    background-color: var(--color-white, #fff);
    box-shadow: 0 0 0 1px var(--gray-200);
}

.dark .rt-more {
    color: var(--gray-400);
    background-color: var(--gray-900);
    box-shadow: 0 0 0 1px var(--gray-700);
}
