/* Tabler's modal, offcanvas and toast styles applied to native <dialog> and popover elements, which the
   browser renders in its top layer. Opened and closed by js/top-layer.js. */

/* ---- Modal -------------------------------------------------------------------------------------- */

/* Tabler's .modal box - fixed, the whole viewport, scrolls itself, overscroll contained - on a dialog:
   undo the user-agent dialog box around it. */
dialog.modal {
    max-width: none;
    max-height: none;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--tblr-body-color);
}

dialog.modal[open] {
    display: block;
}

dialog.modal:focus-visible {
    outline: 0;
}

/* A press over the backdrop must not scroll the page underneath; ::backdrop only honours
   overscroll-behavior once it is a scroll container. */
dialog.modal::backdrop,
dialog.offcanvas::backdrop {
    overflow: hidden;
    overscroll-behavior: contain;
}

dialog.modal-no-backdrop::backdrop {
    background: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}

dialog.modal[open] .modal-dialog {
    transform: none;
    opacity: 1;
    transition: transform 0.3s ease-out, opacity 0.15s linear;
}

dialog.modal[open]::backdrop {
    opacity: 1;
    transition: opacity 0.15s linear;
}

@starting-style {
    dialog.modal[open] .modal-dialog {
        transform: translateY(-1rem);
        opacity: 0;
    }

    dialog.modal[open]::backdrop {
        opacity: 0;
    }
}

/* ---- Offcanvas ---------------------------------------------------------------------------------- */

/* Tabler's .offcanvas panel on a dialog. Its placement classes put the panel on its edge and off
   screen; open, it slides to transform: none. The side it slides from is kept in --rx-offcanvas-from so
   the entry (@starting-style) and the exit ([data-closing]) can both return to it. */
dialog.offcanvas {
    --rx-offcanvas-from: translateX(calc(var(--tblr-dir, 1) * 100%));
    max-width: 100%;
    max-height: 100%;
    margin: 0;
    padding: 0;
    border-block: 0;
    overscroll-behavior: contain;
}

dialog.offcanvas.offcanvas-start {
    --rx-offcanvas-from: translateX(calc(var(--tblr-dir, 1) * -100%));
    inset-inline-end: auto;
    height: 100%;
    border-inline-start: 0;
}

dialog.offcanvas.offcanvas-end {
    inset-inline-start: auto;
    height: 100%;
    border-inline-end: 0;
}

dialog.offcanvas.offcanvas-top {
    --rx-offcanvas-from: translateY(-100%);
    bottom: auto;
    width: 100%;
    border-inline: 0;
}

dialog.offcanvas.offcanvas-bottom {
    --rx-offcanvas-from: translateY(100%);
    top: auto;
    width: 100%;
    border-inline: 0;
}

dialog.offcanvas[open] {
    display: flex;
    visibility: visible;
    transform: none;
}

dialog.offcanvas[open]::backdrop {
    opacity: 1;
    transition: opacity 0.15s linear;
}

dialog.offcanvas[data-closing] {
    transform: var(--rx-offcanvas-from);
}

dialog.offcanvas[data-closing]::backdrop {
    opacity: 0;
}

@starting-style {
    dialog.offcanvas[open] {
        transform: var(--rx-offcanvas-from);
    }

    dialog.offcanvas[open]::backdrop {
        opacity: 0;
    }
}

/* "Floating" side panels from the theme settings (data-bs-offcanvas-style=floating): inset from the
   edges with a full border and rounded corners, as Tabler draws its own. The slide starts that much
   further out so the panel still enters from off screen. */
html[data-bs-offcanvas-style=floating] dialog.offcanvas {
    --rx-offcanvas-gap: var(--tblr-offcanvas-margin, 0.5rem);
    margin: var(--rx-offcanvas-gap);
    border: var(--tblr-offcanvas-border-width) solid var(--tblr-offcanvas-border-color);
    border-radius: var(--tblr-border-radius-lg);
}

/* Tabler's floating rule also nudges the panel by its margin until Bootstrap adds .show, which a dialog
   never gets; the slide here is done with transform alone. */
html[data-bs-offcanvas-style=floating] dialog.offcanvas:is(.offcanvas-start, .offcanvas-end, .offcanvas-top, .offcanvas-bottom) {
    translate: none;
}

html[data-bs-offcanvas-style=floating] dialog.offcanvas:is(.offcanvas-start, .offcanvas-end) {
    height: calc(100% - 2 * var(--rx-offcanvas-gap));
    max-width: calc(100% - 2 * var(--rx-offcanvas-gap));
}

html[data-bs-offcanvas-style=floating] dialog.offcanvas:is(.offcanvas-top, .offcanvas-bottom) {
    width: calc(100% - 2 * var(--rx-offcanvas-gap));
    max-height: calc(100% - 2 * var(--rx-offcanvas-gap));
}

html[data-bs-offcanvas-style=floating] dialog.offcanvas.offcanvas-end {
    --rx-offcanvas-from: translateX(calc(var(--tblr-dir, 1) * (100% + 2 * var(--rx-offcanvas-gap))));
}

html[data-bs-offcanvas-style=floating] dialog.offcanvas.offcanvas-start {
    --rx-offcanvas-from: translateX(calc(var(--tblr-dir, 1) * -1 * (100% + 2 * var(--rx-offcanvas-gap))));
}

html[data-bs-offcanvas-style=floating] dialog.offcanvas.offcanvas-top {
    --rx-offcanvas-from: translateY(calc(-100% - 2 * var(--rx-offcanvas-gap)));
}

html[data-bs-offcanvas-style=floating] dialog.offcanvas.offcanvas-bottom {
    --rx-offcanvas-from: translateY(calc(100% + 2 * var(--rx-offcanvas-gap)));
}

/* OffCanvasOption.Scroll = false: the page behind stays put while the panel is open, as Bootstrap's
   offcanvas did by locking <body>. */
:root:has(dialog.offcanvas.rx-lock-scroll[open]) {
    overflow: hidden;
}

/* A dialog component shown as a plain panel (ShowOffCanvasAsync) loses its footer buttons; shown as a
   dialog (ShowOffCanvasDialogAsync) it keeps them. */
dialog.offcanvas:not(.offcanvas-dialog) div.modal-footer {
    display: none;
}

/* ---- Toasts ------------------------------------------------------------------------------------- */

/* A manual popover in the top layer, so a dialog does not cover it. Undo the user-agent popover box. */
.toast-container[popover] {
    /* Bootstrap makes .toast-container absolute, which in the top layer is the top of the document. */
    position: fixed;
    inset: 0 0 auto auto;
    margin: 0.25rem 0 0;
    padding: 0;
    border: 0;
    background: transparent;
    overflow: visible;
}

/* ---- Dropdown menus ----------------------------------------------------------------------------- */

/* An open TabBlazor menu promoted to the top layer (top-layer.js anchorMenu), placed against its toggle
   the way Bootstrap's classes would place it inline, flipping when it would leave the screen. */
.dropdown-menu[popover] {
    position: fixed;
    inset: auto;
    margin: var(--tblr-dropdown-spacer, 0.125rem) 0 0;
    /* Tabler draws the menu's edge with its shadow and sets no border, so the popover's own shows. */
    border: 0;
    position-area: block-end span-inline-end;
    position-try-fallbacks: flip-block, flip-inline;
    /* A long list goes to whichever side has more room and scrolls inside it, instead of running off
       the screen. 100% is the space position-area gives it; a MaxListHeight set inline still wins. */
    position-try-order: most-block-size;
    max-height: 100%;
    overflow-y: auto;
}

.dropdown-menu[popover][data-placement=dropend] {
    margin: 0 0 0 var(--tblr-dropdown-spacer, 0.125rem);
    position-area: inline-end span-block-end;
}

.dropdown-menu[popover][data-placement=dropstart] {
    margin: 0 var(--tblr-dropdown-spacer, 0.125rem) 0 0;
    position-area: inline-start span-block-end;
}

.dropdown-menu[popover][data-placement=dropup] {
    margin: 0 0 var(--tblr-dropdown-spacer, 0.125rem);
    position-area: block-start span-inline-end;
}

/* ---- Popover ---------------------------------------------------------------------------------- */

/* The Popover component's trigger when it is given no class of its own: just its content. */
.rx-popover-trigger {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    cursor: pointer;
}

/* Bootstrap's .popover look on a native popover. Bootstrap positions .popover absolutely from JS; this
   one is fixed in the top layer. */
.popover.rx-popover {
    position: fixed;
    margin: 0;
    /* .popover-body carries the padding; the user-agent popover would add its own. */
    padding: 0;
    max-width: min(22rem, calc(100vw - 2rem));
}

.popover.rx-popover:not(:popover-open) {
    display: none;
}

/* Below the button that opened it (its implicit anchor), flipped above it near the bottom of the
   screen. Without anchor positioning the popover keeps the browser's default: centred on the screen. */
@supports (anchor-name: --rx-popover) {
    .popover.rx-popover {
        inset: auto;
        margin-block: 0.375rem;
        position-area: block-end span-inline-end;
        position-try-fallbacks: flip-block, flip-inline;
    }
}

@supports not (anchor-name: --rx-popover) {
    .popover.rx-popover {
        inset: 0;
        margin: auto;
    }
}

/* ---- Motion ------------------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    dialog.modal[open] .modal-dialog,
    dialog.modal[open]::backdrop,
    dialog.offcanvas,
    dialog.offcanvas[open]::backdrop {
        transition-duration: 0.01s;
    }

    @starting-style {
        dialog.modal[open] .modal-dialog {
            transform: none;
        }
    }
}
