/**
 * QMT popup + lightbox styles.
 *
 * The overlay and surface box is shared by popups and lightboxes, so it lives
 * once here. Sizing arrives as custom properties set by the runtime, which is
 * what lets the responsive cascade override it per device without a second
 * stylesheet.
 */

/* ---- scroll lock ---------------------------------------------------- */
html.qmt-scroll-locked {
    overflow: hidden !important;
    /* Compensate for the disappearing scrollbar so the page does not jump. */
    padding-right: var(--qmt-scroll-lock-gap, 0px) !important;
}

/* ---- overlay -------------------------------------------------------- */
.qmt-overlay {
    position: fixed;
    inset: 0;
    z-index: 9990;
    background: rgba(15, 23, 42, .55);
    /* A fade only on the way in; the exit is the surface's own animation. */
    animation: qmtOverlayIn .18s ease-out both;
}

.qmt-overlay.is-blurred {
    backdrop-filter: blur(var(--qmt-overlay-blur, 0px));
    -webkit-backdrop-filter: blur(var(--qmt-overlay-blur, 0px));
}

@keyframes qmtOverlayIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* ---- shared surface box --------------------------------------------- */
.qmt-surface {
    position: fixed;
    z-index: 9991;
    background: #fff;
    color: inherit;
    width: var(--qmt-surface-width, auto);
    /* The min() is the guarantee that a popup can never overflow the viewport,
       at ANY width and regardless of what the breakpoints are set to. The
       runtime's per-device cascade decides the real value; this is the floor
       underneath it. A media query could not do this job, because the media
       query is a fixed number while the site is allowed to move its mobile
       breakpoint - the two would drift apart silently. */
    max-width: min(var(--qmt-surface-maxw, 92vw), calc(100vw - 24px));
    height: var(--qmt-surface-height, auto);
    max-height: min(var(--qmt-surface-maxh, 88vh), calc(100dvh - 32px));
    /* A long popup must scroll inside itself rather than growing past the
       viewport and pushing the page into an unusable state. */
    overflow: auto;
    overscroll-behavior: contain;
    box-shadow: 0 25px 60px rgba(2, 6, 23, .3);
    border-radius: 12px;
    --qmt-surface-dur: 280ms;
}

.qmt-surface--closing {
    /* The exit keyframes run at the same duration as the entrance. */
    animation-duration: var(--qmt-surface-dur);
}

/* ---- position: two independent axes ------------------------------------
   Horizontal and vertical are separate facts about the surface, so they are
   separate attributes and each can be overridden by the responsive cascade on
   its own - a popup can become a bottom bar on tablet while keeping its desktop
   horizontal centring.

   The transform property now means POSITION, and nothing else. The motion
   keyframes further down deliberately use the independent translate/scale
   properties instead, so an animation can never displace a surface from where
   it is anchored.
   ---------------------------------------------------------------------- */
.qmt-surface[data-qmt-px="left"]   { left: var(--qmt-surface-gutter, 24px); right: auto; }
.qmt-surface[data-qmt-px="center"] { left: 50%; right: auto; }
.qmt-surface[data-qmt-px="right"]  { right: var(--qmt-surface-gutter, 24px); left: auto; }

.qmt-surface[data-qmt-py="top"]    { top: var(--qmt-surface-gutter, 24px); bottom: auto; }
.qmt-surface[data-qmt-py="center"] { top: 50%; bottom: auto; }
.qmt-surface[data-qmt-py="bottom"] { bottom: var(--qmt-surface-gutter, 24px); top: auto; }

/* Centring needs a translate on whichever axis is centred, and transform takes
   one value, so each axis contributes its own half and centre/centre needs the
   pair. Spelled out rather than composed: composing them would mean reaching for
   the translate property, which is exactly what the keyframes use, and two
   things owning one property is how the previous version of this file ended up
   teleporting corner popups into the middle of the screen. */
.qmt-surface[data-qmt-px="center"] { transform: translateX(-50%); }
.qmt-surface[data-qmt-py="center"] { transform: translateY(-50%); }
.qmt-surface[data-qmt-px="center"][data-qmt-py="center"] { transform: translate(-50%, -50%); }

/* ---- full-screen mode ---------------------------------------------------
   `heightMode: screen`. The position axes are irrelevant here - the surface
   fills the viewport - and the close button is inset so it can never be clipped
   by the edge it is anchored to.
   ---------------------------------------------------------------------- */
/* Every declaration here is !important, and that is load-bearing rather than
   sloppy. The axis rules above are class+attribute (0-2-0) and the mobile block
   below is also !important, so a plain .qmt-surface--screen (0-1-0) would LOSE
   to them: the surface would keep a 24px edge inset while also being told to be
   100vw wide, which overflows the viewport by exactly that inset. Qualifying
   the same selector with the same attributes puts it on equal footing and lets
   source order decide, so the outcome no longer depends on the cascade. */
.qmt-surface--screen,
.qmt-surface--screen[data-qmt-px],
.qmt-surface--screen[data-qmt-py] {
    inset: 0 !important;
    width: 100vw !important;
    max-width: 100vw !important;
    height: 100dvh !important;
    max-height: 100dvh !important;
    transform: none !important;
    border-radius: 0;
    margin: 0 !important;
}
/* 100dvh is the modern viewport unit; vh is the fallback for engines without
   it. Without this line a full-screen popup is 100% of the LARGEST viewport on
   iOS, which is taller than the visible area and hides the bottom of the
   content behind the browser chrome. */
@supports not (height: 100dvh) {
    .qmt-surface--screen,
    .qmt-surface--screen[data-qmt-px],
    .qmt-surface--screen[data-qmt-py] { height: 100vh !important; max-height: 100vh !important; }
}
.qmt-surface--screen .qmt-popup-content { height: 100%; overflow: auto; }
.qmt-surface--screen .qmt-popup-close { top: 16px; right: 16px; }

/* Offsets are additive to the position, applied as a nudge so the base
   transform above is preserved. */
.qmt-surface {
    margin-left: var(--qmt-surface-offx, 0px);
    margin-top: var(--qmt-surface-offy, 0px);
}

/* ---- popup surface --------------------------------------------------- */
.qmt-popup-surface .qmt-popup-content {
    padding: 28px;
}

.qmt-popup-close {
    position: absolute;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    padding: 0;
    background: rgba(255, 255, 255, .9);
    border: 1px solid rgba(15, 23, 42, .1);
    border-radius: 999px;
    cursor: pointer;
    line-height: 0;
}

.qmt-popup-close:hover { background: #fff; }
.qmt-popup-close:focus-visible { outline: 2px solid #ff800b; outline-offset: 2px; }

.qmt-popup-close--top-right     { top: 10px; right: 10px; }
.qmt-popup-close--top-left      { top: 10px; left: 10px; }
.qmt-popup-close--bottom-right  { bottom: 10px; right: 10px; }
.qmt-popup-close--bottom-left   { bottom: 10px; left: 10px; }

/* ---- lightbox -------------------------------------------------------- */
.qmt-lightbox-surface {
    background: #0b1220;
    color: #e2e8f0;
    padding: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.qmt-lightbox-bar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 10px;
    flex: 0 0 auto;
}

.qmt-lightbox-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    background: rgba(255, 255, 255, .1);
    color: #fff;
    border: 0;
    border-radius: 8px;
    cursor: pointer;
    line-height: 0;
}

.qmt-lightbox-close:focus-visible { outline: 2px solid #ff800b; outline-offset: 2px; }

.qmt-lightbox-caption {
    font-size: 13px;
    color: #cbd5e1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.qmt-lightbox-body {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 12px;
    min-height: 0;
    overflow: auto;
}

.qmt-lightbox-image {
    max-width: 100%;
    max-height: 78vh;
    width: auto;
    height: auto;
    object-fit: contain;
    border-radius: 4px;
}

.qmt-lightbox-video {
    width: min(1100px, 92vw);
    aspect-ratio: 16 / 9;
    height: auto;
    border: 0;
    border-radius: 6px;
    background: #000;
}

.qmt-lightbox-error {
    color: #fca5a5;
    font-size: 14px;
    text-align: center;
    padding: 24px;
    max-width: 420px;
}

/* ---- runtime visibility state ---------------------------------------- */
/* Show/Hide is a runtime class, never a saved style change. */
.qmt-hidden-runtime {
    display: none !important;
}

/* ---- motion ---------------------------------------------------------- */
/* Motion tokens mirror the existing entrance-animation vocabulary so a popup
   looks like the rest of the site rather than a foreign system. */
.qmt-surface.qmt-anim-fade-in  { animation: qmtLbFadeIn  var(--qmt-surface-dur) ease-out both; }
.qmt-surface.qmt-anim-fade-up  { animation: qmtLbFadeUp  var(--qmt-surface-dur) ease-out both; }
.qmt-surface.qmt-anim-fade-down{ animation: qmtLbFadeDown var(--qmt-surface-dur) ease-out both; }
.qmt-surface.qmt-anim-zoom-in  { animation: qmtLbZoomIn  var(--qmt-surface-dur) ease-out both; }
.qmt-surface.qmt-anim-zoom-out { animation: qmtLbZoomOut var(--qmt-surface-dur) ease-in both; }
.qmt-surface.qmt-anim-slide-up { animation: qmtLbSlideUp var(--qmt-surface-dur) ease-out both; }
.qmt-surface.qmt-anim-slide-down{ animation: qmtLbSlideDown var(--qmt-surface-dur) ease-out both; }

@keyframes qmtLbFadeIn   { from { opacity: 0; } to { opacity: 1; } }
@keyframes qmtLbFadeUp   { from { opacity: 0; translate: 0 14px; } to { opacity: 1; translate: 0 0; } }
@keyframes qmtLbFadeDown { from { opacity: 0; translate: 0 -14px; } to { opacity: 1; translate: 0 0; } }
@keyframes qmtLbZoomIn   { from { opacity: 0; scale: .94; } to { opacity: 1; scale: 1; } }
@keyframes qmtLbZoomOut  { from { opacity: 1; scale: 1; } to { opacity: 0; scale: .96; } }
@keyframes qmtLbSlideUp  { from { opacity: 0; translate: 0 26px; } to { opacity: 1; translate: 0 0; } }
@keyframes qmtLbSlideDown{ from { opacity: 0; translate: 0 -26px; } to { opacity: 1; translate: 0 0; } }

/* These keyframes deliberately use the INDEPENDENT `translate` and `scale`
   properties and never `transform`.

   `transform` now belongs to POSITION: the axis rules above set
   `transform: translate(-50%, -50%)` to centre a surface, and a keyframe that
   also set `transform` would REPLACE that centring for the duration of the
   animation - teleporting a corner popup into the middle of the screen and
   then back. The previous keyframes hard-coded `translate(-50%, -50%)` and
   needed a hand-written exception block for each of the eight non-centred
   positions, which is the same bug waiting to happen the next time a position
   is added.

   The individual transform properties compose with `transform` in a fixed order
   (translate, rotate, scale, then transform), so an animation offset and the
   position centring coexist correctly with no special cases at all. */
@supports not (translate: 0 0) {
    /* No independent translate: fall back to opacity-only motion rather than
       shipping a keyframe that would fight the position transform. */
    .qmt-surface.qmt-anim-fade-up,
    .qmt-surface.qmt-anim-fade-down,
    .qmt-surface.qmt-anim-slide-up,
    .qmt-surface.qmt-anim-slide-down { animation-name: qmtLbFadeIn; }
}

/* ---- responsive ------------------------------------------------------ */
/* The runtime already resolves a per-device max width from the SAME builder
   breakpoints that generate the site CSS; these are the safety nets that make an
   overflowing popup impossible even if a value is mistyped. */
@media (max-width: 991px) {
    /* No width override here on purpose. The base rule's min() already
       guarantees the surface fits, and the runtime resolves the real per-device
       width from the site's configured breakpoints. Hard-coding a second
       number here is how the two would drift apart. */
    .qmt-popup-surface .qmt-popup-content { padding: 22px; }
}

@media (max-width: 640px) {
    /* Full-bleed on a phone, with a gutter, so nothing is ever cut off. */
    .qmt-surface {
        width: calc(100vw - 24px) !important;
        max-width: calc(100vw - 24px) !important;
        max-height: calc(100dvh - 32px);
        border-radius: 10px;
    }
    /* On a phone every position becomes "inset with a gutter", because a popup
       that honours `right: 24px` on a 360px screen is a popup the visitor can
       only read half of. The two axes are collapsed together deliberately. */
    .qmt-surface[data-qmt-px],
    .qmt-surface[data-qmt-py] {
        left: 12px !important;
        right: 12px !important;
        top: 16px !important;
        bottom: auto !important;
        transform: none !important;
    }
    /* A full-screen popup on mobile is full screen, not "full screen minus a
       gutter" - the setting asked for the whole viewport. The selector is
       qualified with the same attributes as the axis rules above so that it
       wins on equal footing rather than on specificity. */
    .qmt-surface--screen,
    .qmt-surface--screen[data-qmt-px],
    .qmt-surface--screen[data-qmt-py] {
        inset: 0 !important;
        width: 100vw !important;
        max-width: 100vw !important;
        height: 100dvh !important;
        max-height: 100dvh !important;
        transform: none !important;
    }
    .qmt-popup-surface .qmt-popup-content { padding: 18px; }
    .qmt-lightbox-image { max-height: 70vh; }
}

/* ---- reduced motion -------------------------------------------------- */
/* Motion is decoration. Everything must still open, close and be reachable
   when it is turned off. */
@media (prefers-reduced-motion: reduce) {
    .qmt-overlay,
    .qmt-surface,
    .qmt-surface.qmt-anim-fade-in,
    .qmt-surface.qmt-anim-fade-up,
    .qmt-surface.qmt-anim-fade-down,
    .qmt-surface.qmt-anim-zoom-in,
    .qmt-surface.qmt-anim-zoom-out,
    .qmt-surface.qmt-anim-slide-up,
    .qmt-surface.qmt-anim-slide-down {
        animation: none !important;
        transition: none !important;
    }
}
