/*
 * Shared base for native <dialog>-based modals (replacement for Magnific Popup).
 * Apply the "gm-dialog" class alongside each dialog's own presentational
 * utility classes (background, rounded corners, layout, etc).
 */

/* Always reserve the scrollbar's gutter, whether or not the page currently
   overflows. Locking scroll below (html:has(.gm-dialog[open])) then removes
   the scrollbar itself, but since its space was already reserved beforehand,
   nothing shifts - the page doesn't get wider when the scrollbar disappears. */
html {
    scrollbar-gutter: stable;
}

/* Body-scroll lock while any gm-dialog is open. Pure CSS - no open/close JS
   needed, and it naturally holds the lock as long as ANY dialog is open even
   if others stack on top of each other. */
html:has(.gm-dialog[open]) {
    overflow: hidden;
}

.gm-dialog {
    /* The UA stylesheet only sets left/right + margin:auto, so a modal dialog
       centers horizontally but sits at its static position vertically.
       inset:0 gives margin:auto a box on both axes, centering it in the viewport. */
    position: fixed;
    inset: 0;
    margin: auto;
    border: none;
    padding: 0;
    /* Individual dialogs pinned to the bottom edge on mobile (OneClickBuy, product
       reviews, register-card, FTB locked sheet) override this per-side to flatten
       their bottom corners there - see each's own CSS. */
    border-radius: 24px;
    /* focus() lands on the dialog itself (see public.common.js) rather than an
       inner control, purely so opening never auto-selects/highlights something
       inside - the dialog isn't an interactive control, so it shouldn't show a
       focus ring for that. */
    outline: none;
    max-height: calc(100vh - 2rem);
    overflow-x: hidden;
    overflow-y: auto;
    box-shadow: 0 10px 40px rgba(0, 0, 0, .2);
    opacity: 0;
    transform: translateY(8px) scale(.98);
    /* close() removes the dialog from the modal top layer immediately, but our
       fade-out keeps display:block for .2s afterward so the animation can play.
       During that window it's a plain fixed, full-viewport element sitting in
       normal layout - without this, its buttons/content stay clickable even
       though it's fading toward invisible. */
    pointer-events: none;
    transition: opacity .2s ease, transform .2s ease, overlay .2s allow-discrete, display .2s allow-discrete;
}

.gm-dialog[open] {
    opacity: 1;
    transform: translateY(0) scale(1);
    pointer-events: auto;
}

.gm-dialog::backdrop {
    /* !important: a third-party cookie-consent stylesheet sets a global
       "dialog::backdrop { opacity: 0 }" rule. Without winning that property
       explicitly, the backdrop computes a correct background color but
       renders fully invisible. */
    background: rgba(0, 0, 0, 0) !important;
    backdrop-filter: blur(0px) !important;
    -webkit-backdrop-filter: blur(0px) !important;
    opacity: 1 !important;
    transition: background .2s ease, backdrop-filter .2s ease, overlay .2s allow-discrete, display .2s allow-discrete;
}

.gm-dialog[open]::backdrop {
    background: rgba(0, 0, 0, .6) !important;
    backdrop-filter: blur(2px) !important;
    -webkit-backdrop-filter: blur(2px) !important;
    opacity: 1 !important;
}

/* Enter-animation start frames. Kept LAST on purpose: @starting-style is a 2024
   at-rule some CSS minifiers don't parse, and a failed parse can drop whatever
   follows it. With nothing after it, every rule above always survives. */
@starting-style {
    .gm-dialog[open] {
        opacity: 0;
        transform: translateY(8px) scale(.98);
    }

    .gm-dialog[open]::backdrop {
        background: rgba(0, 0, 0, 0) !important;
        backdrop-filter: blur(0px) !important;
        -webkit-backdrop-filter: blur(0px) !important;
    }
}
