/* ==========================================================================
   Toast Component
   Reusable notification toasts with auto-dismiss and countdown bar.
   Pairs with static/js/toast.js
   ========================================================================== */

/* Container — stacks toasts at top or bottom of viewport */
.toast-container {
    position: fixed;
    z-index: 10000;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    pointer-events: none;
    padding: 1rem;
    max-width: min(480px, calc(100vw - 2rem));
    width: 100%;
    left: 50%;
    transform: translateX(-50%);
}

.toast-container--top {
    top: 0;
}

.toast-container--bottom {
    bottom: 0;
    flex-direction: column-reverse;
}

/* Individual toast */
.toast {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.875rem 1rem;
    border-radius: var(--border-radius);
    box-shadow: var(--shadow-lg);
    pointer-events: auto;
    overflow: hidden;
    border: 1px solid transparent;
    opacity: 0;
    transform: translateY(-1rem);
    transition: opacity 0.3s ease, transform 0.3s ease;
}

.toast--entering {
    opacity: 1;
    transform: translateY(0);
}

.toast--exiting {
    opacity: 0;
    transform: translateY(-1rem);
    transition: opacity 0.2s ease, transform 0.2s ease;
}

/* Toast variants — theme tokens, no fallbacks.

   ⚠️ ALL TWELVE OF THESE WERE WRITTEN AS `var(--x, #hex)`, and the hexes were
   Bootstrap's, not Pensio's: `#dcfce7`, `#721c24`, `#ffeeba`. Checked
   2026-08-25 — every one of the twelve tokens IS defined in both
   `themes/default.css` and `themes/dark.css`, so nothing was actually
   rendering a light hex on a dark theme. The fallbacks were dead, not
   dangerous.

   ⛔ THEY STILL HAD TO GO. `tests/test_css_tokens_exist.py` deliberately
   exempts a `var()` that carries a fallback — correctly, since such a
   declaration is not dropped — so a fallback is precisely the shape in which a
   hardcoded light-mode colour hides from the one guard that would find it.
   That is not theory: it is how focus mode painted `#F5F3EF` over the entire
   viewport in dark mode until Batch 2. A fallback that never fires still costs
   the next reader a check. */
.toast--success {
    background: var(--success-bg);
    color: var(--success-text);
    border-color: var(--success-border);
}

.toast--error {
    background: var(--error-bg);
    color: var(--error-text);
    border-color: var(--error-border);
}

.toast--warning {
    background: var(--warning-bg);
    color: var(--warning-text);
    border-color: var(--warning-border);
}

.toast--info {
    background: var(--info-bg);
    color: var(--info-text);
    border-color: var(--info-border);
}

/* Toast icon */
.toast__icon {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    margin-top: 0.125rem;
}

/* Toast content */
.toast__content {
    flex: 1;
    min-width: 0;
}

.toast__message {
    font-size: 0.9rem;
    line-height: 1.5;
    word-break: break-word;
}

/* Close button */
.toast__close {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    cursor: pointer;
    padding: 0.25rem;
    color: inherit;
    opacity: 0.6;
    border-radius: var(--border-radius-sm);
    min-width: 28px;
    min-height: 28px;
    transition: opacity var(--transition-fast);
}

.toast__close:hover,
.toast__close:focus-visible {
    opacity: 1;
}

.toast__close:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
}

/* Countdown bar */
.toast__countdown {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: rgba(0, 0, 0, 0.08);
    overflow: hidden;
}

.toast__countdown-bar {
    height: 100%;
    width: 100%;
    background: currentColor;
    opacity: 0.3;
    transform-origin: left;
    animation: toast-countdown linear forwards;
}

@keyframes toast-countdown {
    from {
        transform: scaleX(1);
    }

    to {
        transform: scaleX(0);
    }
}

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 600px) {
    .toast-container {
        padding: 0.5rem;
        max-width: 100vw;
    }

    .toast {
        padding: 0.75rem;
        gap: 0.5rem;
        border-radius: var(--border-radius-sm);
    }

    .toast__message {
        font-size: 0.85rem;
    }
}

/* Mobile: position toasts above the bottom nav bar (Material Snackbar pattern).
   Avoids status bar / notch / Dynamic Island overlap on both Android and iOS. */
@media (max-width: 1023px) {
    .toast-container--top {
        top: auto;
        bottom: calc(72px + env(safe-area-inset-bottom, 0px));
        flex-direction: column-reverse;
    }

    .toast {
        transform: translateY(1rem);
    }

    .toast--entering {
        transform: translateY(0);
    }

    .toast--exiting {
        transform: translateY(1rem);
    }
}

/* ⛔ **ON DESKTOP THE TOAST LANDED ON THE PAGE TITLE.** `--top` pins it to
   `top: 0`, so a success message sat over the top ~22px of the `<h1>` for its
   full 7s life. Measured 2026-08-22 at 1280x900 on /questions/: h1 36->78,
   toast 0->56.

   ⚠️ **MOBILE WAS FIXED IN APRIL AND DESKTOP WAS NEVER TOUCHED** — the
   `max-width: 1023px` block above bottom-anchors it clear of the nav, which is
   why this survived: the surface most people test on already looked right.

   ⛔ **THE FIRST FIX HERE WAS A `top` OFFSET, AND IT DID NOT WORK.** Measured:
   at `top: 1.5rem` the toast occupies 20->76 and the h1 36->78, so it still
   collides. It cannot not collide — the h1 begins 36px down, and no positive
   `top` clears a 56px box above it.

   ⚠️ **AND THE REASON GIVEN FOR PREFERRING `top` WAS WRONG.** It said
   bottom-anchoring would put the toast "under the fold on a tall page". The
   container is `position: fixed`, so `bottom` is the VIEWPORT bottom — always
   in view, regardless of page height or scroll. That is precisely why the
   mobile rule does it, citing the Material Snackbar pattern.

   ⭐ So desktop matches mobile: bottom-anchored, clear of everything, with no
   bottom nav to avoid so a plain offset suffices. */
@media (min-width: 1024px) {
    .toast-container--top {
        top: auto;
        bottom: var(--space-lg);
        flex-direction: column-reverse;
    }
}
