/*
 * Toast notifications, shared by index.html and single.html (see js/toast.js).
 *
 * Replaces the inline alert banner each page used to carry at the top of its body. That banner was
 * part of the flow, so showing it pushed the whole layout down; it lived at the top of a page whose
 * log panel is at the bottom, so it was routinely missed; and it took itself away after a few
 * seconds whether or not anyone had read it.
 *
 * The colours come from css/tokens.css, which all three pages load before this file; the
 * fallbacks keep it usable on its own. They used to come from whichever page happened to declare
 * them, which is how --neutral -- declared only by index.html -- left every toast on the Single
 * page falling back to the grey below.
 *
 * Sizes are in em, not px: the stack inherits the page's body size, so it stays in proportion
 * with whatever it sits on. The Single page used to scale its whole interface up
 * (html { font-size: 20px }) and the stack scaled with it; both pages now share one root, so the
 * same toast is the same size on each.
 */

.toast-region {
    position: fixed;
    right: 16px;
    bottom: 16px;
    z-index: 2000;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 8px;
    /*
     * The stack is anchored to the bottom of the window and grows upwards, so without a bound it
     * grows off the top of the screen: three failure toasts at the maximum height .toast-message
     * allows came to about 580px, and a failure toast has no dismiss timer, so the oldest of them
     * left for good. Bounded by the window it is anchored to, and scrollable inside that bound --
     * pointer-events below keeps the region itself click-through, but a wheel over a toast still
     * scrolls this, its nearest scrollable ancestor.
     */
    max-height: calc(100vh - 32px);
    overflow-y: auto;
    /* The stack overlaps the log panel: only the toasts themselves may take a click. */
    pointer-events: none;
}

.toast-group {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 8px;
}

.toast {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: 0.6em;
    width: 24em;
    /* 100% as well as the viewport bound: once the region above is scrolling, its scrollbar takes
       its width out of the content box, and a card that insisted on 24em inside it would earn a
       horizontal scrollbar too. */
    max-width: min(100%, calc(100vw - 32px));
    padding: 0.6em 0.75em;
    border: 1px solid var(--border, #d6dbe2);
    border-left: 3px solid var(--neutral, #4b5563);
    border-radius: 6px;
    background: var(--surface-0, #ffffff);
    color: var(--text-1, #111827);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
    line-height: var(--lh-ui, 1.4);
    animation: toast-in 120ms ease-out;
}

.toast-success { border-left-color: var(--success, #047857); }
.toast-error { border-left-color: var(--danger, #dc2626); }
.toast-info { border-left-color: var(--brand-800, #1e3c72); }

.toast-message {
    flex: 1;
    /* A server message can be one long unbroken token: a file path, a URL, a class name. */
    overflow-wrap: anywhere;
    /*
     * And it is not always one line. A failed request hands the toast whatever the response body
     * contained, which during a redeploy is a proxy's whole HTML error page, and for an unmapped
     * server failure is Spring's whitelabel one. The stack is anchored to the bottom of the
     * viewport and grows upwards, so an unbounded card runs off the top of the screen with no way
     * to scroll it back - and a failure toast has no auto-dismiss timer, so a reload would be the
     * only way out. Six lines or so, then scroll.
     *
     * The bound belongs here and not on .toast: capping the card would take the close button with
     * it, which is the half of the problem that actually traps the user.
     */
    max-height: 8.4em;
    overflow-y: auto;
}

.toast-close {
    flex: none;
    padding: 0 0.15em;
    border: 0;
    background: none;
    font: inherit;
    line-height: 1;
    color: var(--text-2, #4b5563);
    cursor: pointer;
}

.toast-close:hover {
    color: var(--text-1, #111827);
}

.toast-close:focus-visible {
    outline: 2px solid var(--brand-800, #1e3c72);
    outline-offset: 2px;
}

.toast-leaving {
    animation: toast-out 120ms ease-in forwards;
}

@keyframes toast-in {
    from { opacity: 0; transform: translateY(6px); }
}

@keyframes toast-out {
    to { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .toast,
    .toast-leaving {
        animation: none;
    }
}
