html, body, #form1 {
    height: 100%;
}

#wrapper {
    height: 100%;
}

/* Preloader: full-screen overlay shown until the view image has loaded */
#preloader {
    position: fixed;
    inset: 0;
    z-index: 1080; /* above content, above Bootstrap modal backdrop (1050) */
    display: flex;
    align-items: center;
    justify-content: center;
    background: #fff;
    transition: opacity 0.3s ease;
}

#preloader.is-hidden {
    opacity: 0;
    visibility: hidden; /* removes it from hit-testing once faded out */
}

#preloader .spinner-border {
    width: 3rem;
    height: 3rem;
}

/* Stage: positioning context for the image + hotspot overlay */
.visualizer-stage {
    position: relative;
    display: inline-block; /* shrink-wraps to the image so the overlay matches its box */
    max-width: 100%;
    line-height: 0; /* remove inline-image whitespace */
}

.visualizer-image {
    display: block;
    max-width: 100%;
    height: auto;
}

/* Overlay: sits exactly on top of the image, hosts the clickable items */
.visualizer-overlay {
    position: absolute;
    inset: 0;
    pointer-events: none; /* let only the hotspots receive clicks */
}

/* View switcher menu: fixed top-right, above the image/overlay */
#viewMenu {
    position: fixed;
    top: 1rem;
    right: 1rem;
    z-index: 1030; /* above content, below preloader (1080) and modal (1055) */
}

/* Hotspot marker, positioned by percentage (see visualizer.js item.x / item.y).
   The marker shows the hotspot icon image (Assets/Gfx/hotspot-icon-n.png). */
.visualizer-hotspot {
    position: absolute;
    transform: translate(-50%, -50%); /* x/y mark the centre of the hotspot */
    pointer-events: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    cursor: pointer;
    transition: transform 0.15s ease;
    animation: visualizer-pulse 2s infinite;
}

.visualizer-hotspot-icon {
    display: block;
    width: 32px;
    height: 32px;
    /* Matches the icon's red so no ring shows behind its circular edge. */
    border-radius: 50%;
    background: #e41e26;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
    position: relative;
    z-index: 1; /* keep the marker icon on top of the connected label */
}

.visualizer-hotspot:hover,
.visualizer-hotspot:focus {
    transform: translate(-50%, -50%) scale(1.15);
    outline: none;
}

/* Hover label: the item name shown to the right of the marker. Hidden by
   default; only revealed on hover on devices with a fine hover-capable
   pointer (i.e. desktop with a mouse), never on touch. */
.visualizer-hotspot-label {
    position: absolute;
    /* Start at the marker centre and tuck under it so the label reads as one
       piece with the hotspot; the marker icon sits on top of this left edge. */
    left: 50%;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    height: 32px; /* match the hotspot marker height */
    padding: 0 12px 0 24px; /* extra left padding clears the marker icon */
    white-space: nowrap;
    font-size: 14px;
    line-height: 1;
    color: #000;
    background: #fff;
    border-radius: 16px; /* pill: rounded ends match the circular marker */
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
    pointer-events: none; /* the label never intercepts clicks */
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.12s ease;
}

/* Flipped label: shown to the LEFT of the marker when a right-side label would
   overflow the viewport's right edge (see positionLabel() in visualizer.js).
   Mirror of the default: anchored on the right, clearance padding on the right. */
.visualizer-hotspot.label-left .visualizer-hotspot-label {
    left: auto;
    right: 50%;
    padding: 0 24px 0 12px;
    justify-content: flex-end;
}

@media (hover: hover) and (pointer: fine) {
    .visualizer-hotspot:hover .visualizer-hotspot-label,
    .visualizer-hotspot:focus-visible .visualizer-hotspot-label {
        opacity: 1;
        visibility: visible;
    }
}

/* Pulse ring around the marker to draw the eye. */
@keyframes visualizer-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(227, 11, 23, 0.5); }
    70%  { box-shadow: 0 0 0 12px rgba(227, 11, 23, 0); }
    100% { box-shadow: 0 0 0 0 rgba(227, 11, 23, 0); }
}

/* --- Hotspot modal ------------------------------------------------------- */
/* Widen the dialog to 90vw (overrides Bootstrap modal-xl's 1140px cap). */
#visualizerModal .modal-dialog {
    max-width: 90vw;
}

#visualizerModal .modal-content {
    position: relative;
    overflow: visible; /* let the close button sit outside the top-right corner */
}

/* Close button: a round white badge above the modal's top-right corner. The
   whole badge is the button, so clicking anywhere on it closes the modal. */
.visualizer-modal-close {
    position: absolute;
    top: -18px;
    right: -18px;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
    cursor: pointer;
    transition: background-color 0.15s ease;
}

.visualizer-modal-close:hover,
.visualizer-modal-close:focus-visible {
    background: #e41e26;
}

/* Invert the × to white so it stays visible on the red hover background. */
.visualizer-modal-close:hover .btn-close,
.visualizer-modal-close:focus-visible .btn-close {
    filter: invert(1) grayscale(100%) brightness(200%);
}

.visualizer-modal-close .btn-close {
    display: block;
    padding: 0;
    margin: 0;
    width: 14px;
    height: 14px;
    background-size: 14px;
    pointer-events: none; /* clicks belong to the badge button */
}

/* The two item images stack vertically in the left column. */
.visualizer-modal-images {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.visualizer-modal-img {
    display: block;
    width: 100%;
    height: auto; /* natural size by default (mobile: columns stack, page scrolls) */
    object-fit: contain;
    object-position: top;
}

/* Each modal image sits in a figure so its "enlarge" button can float over its
   top-right corner. Clicking anywhere on the figure enlarges the image. */
.visualizer-modal-figure {
    position: relative;
}

.visualizer-img-zoomable {
    cursor: zoom-in;
}

/* Round enlarge/shrink button (a magnifier). Enlarge floats on the image's
   corner; shrink floats on the zoomed layer's corner. */
.visualizer-img-zoom {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.9);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
    color: #212529;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.visualizer-img-zoom:hover,
.visualizer-img-zoom:focus-visible,
/* Hovering anywhere on the image figure highlights its enlarge button too. */
.visualizer-modal-figure:hover .visualizer-img-zoom {
    background: #e41e26;
    color: #fff;
}

/* Full-modal image overlay shown while an image is enlarged. Sits over the
   body content but below the close/back badges so the modal can still close. */
.visualizer-zoom-layer {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: #fff;
    border-radius: inherit;
}

.visualizer-zoom-img {
    width: 100%;
    height: auto;
    max-height: 100%;
}

/* Carousel prev/next arrows: round badges vertically centred at each edge of
   the zoom layer (shown only when an accessory has more than one image). */
.visualizer-zoom-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.9);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
    color: #212529;
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.visualizer-zoom-nav-prev { left: 12px; }
.visualizer-zoom-nav-next { right: 12px; }

.visualizer-zoom-nav:hover,
.visualizer-zoom-nav:focus-visible {
    background: #e41e26;
    color: #fff;
}

/* Dots indicator: centred at the bottom of the zoom layer. */
.visualizer-zoom-dots {
    position: absolute;
    bottom: 14px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 2;
    display: flex;
    gap: 8px;
}

.visualizer-zoom-dot {
    width: 10px;
    height: 10px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.25);
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.6);
    cursor: pointer;
    transition: background-color 0.15s ease;
}

.visualizer-zoom-dot.is-active {
    background: #e41e26;
}

/* The shrink pill reuses the back-pill look/position (top-left corner). It sits
   above the zoom layer, and its icon needs to line up with the name text. */
.visualizer-img-shrink {
    z-index: 3;
}

.visualizer-img-shrink .visualizer-modal-back-arrow {
    display: inline-flex;
    align-items: center;
}

/* While zoomed, hide the normal body content behind the overlay, and hide the
   panel back pill (the shrink pill takes its place). The shrink pill also
   carries .visualizer-modal-back for styling, so exclude it from the hide. */
.visualizer-zoomed .modal-body {
    visibility: hidden;
}

.visualizer-zoomed .visualizer-modal-back:not(.visualizer-img-shrink) {
    display: none;
}

/* A panel modal shows the panel image (with its own hotspots) in the left
   column. Make the reused .visualizer-stage span the column width. */
.visualizer-panel-stage {
    display: block;
    width: 100%;
    max-width: 100%;
    /* Clip anything that sits past the image box - a hotspot marker placed near
       an edge is centred on its x/y, so half of it overhangs the stage and would
       otherwise widen the column and add a horizontal scrollbar. */
    overflow: hidden;
}

/* Fill the stage width so the panel image can't overflow the column; height
   follows the aspect ratio. */
.visualizer-panel-stage .visualizer-image {
    width: 100%;
    max-width: 100%;
}

/* "Back" button shown in an item modal that was opened from a panel; returns
   to that panel's modal. A pill (arrow + panel name) at the top-left corner,
   matching the height/look of the round close badge. */
.visualizer-modal-back {
    position: absolute;
    top: -18px;
    left: -18px;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    height: 36px;
    padding: 0 1rem;
    border: 0;
    border-radius: 18px; /* half the height -> pill */
    background: #fff;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
    color: #212529;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.visualizer-modal-back-arrow {
    font-size: 18px;
    line-height: 1;
}

.visualizer-modal-back:hover,
.visualizer-modal-back:focus-visible {
    background: #e41e26;
    color: #fff;
}

/* Two-column layout (Bootstrap md and up): the modal sizes to its content but
   is capped at 90vh, after which each column scrolls on its own. On smaller
   screens the columns stack and the modal flows/scrolls naturally instead —
   otherwise the images get squeezed into a fraction of the height. */
@media (min-width: 768px) {
    #visualizerModal .modal-content {
        max-height: 90vh; /* size to content, but never taller than 90vh */
    }

    #visualizerModal .modal-body {
        overflow: hidden; /* the right column scrolls, not the body as a whole */
        display: flex;
        flex: 1 1 auto;
        min-height: 0;
    }

    #visualizerModal .modal-body > .row {
        flex: 1 1 auto;
        min-height: 0;
        width: 100%;
    }

    .visualizer-modal-images {
        min-height: 0;
        max-height: 100%;
        overflow-y: auto; /* images keep their natural size; the column scrolls */
    }

    .visualizer-modal-content {
        max-height: 100%;
        overflow-y: auto;
    }
}

/* On small screens the modal spans almost the full viewport width, so badges
   offset outside the corners (top/left/right: -18px) get clipped by the screen
   edge. Tuck them just inside the modal corners instead. */
@media (max-width: 767.98px) {
    .visualizer-modal-close {
        top: 8px;
        right: 8px;
    }

    .visualizer-modal-back {
        top: 8px;
        left: 8px;
    }

    /* Leave room at the top of the body so the now-inside badges don't overlap
       the content (image / title). */
    #visualizerModal .modal-body {
        padding-top: 3.25rem;
    }
}

/* Item title heading (the modal's h5). */
.visualizer-modal-title {
    font-size: 1.8rem;
    margin-bottom: 1rem;
}

/* Divider between the links and the accessories. */
.visualizer-divider {
    color: #dee2e6;
    opacity: 1; /* Bootstrap dims hr via opacity; keep the colour solid */
}

/* Links list: horizontal, wraps to the next line. Each link is a pill. */
.visualizer-links {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.visualizer-link {
    display: inline-flex;
    align-items: center;
    padding: 0.25rem 0.75rem;
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: 999px;
    background: var(--bs-secondary-bg, #f8f9fa);
    color: inherit;
    text-decoration: none;
    font-size: 14px;
    white-space: nowrap;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.visualizer-link:hover,
.visualizer-link:focus {
    background: #e41e26;
    border-color: #e41e26;
    color: #fff;
}

/* Accessory: name on top, its 1-3 images in a row beneath. */
.visualizer-accessory {
    margin-top: 0.5rem;
    margin-bottom: 0.5rem;
    border-top: 1px solid var(--bs-border-color, #dee2e6);
}

.visualizer-accessory:first-child {
    margin-top: 0;
    border-top: 0;
}

.visualizer-accessory-name {
    margin-bottom: 0.5rem;
}

/* Each image occupies a third of the column, so one or two images leave
   space on the right rather than stretching. */
.visualizer-accessory-images {
    display: flex;
    gap: 0.5rem;
}

/* Each accessory image sits in a figure (a third of the row width) so its zoom
   badge can float over the bottom-right corner. */
.visualizer-accessory-figure {
    position: relative;
    width: calc((100% - 1rem) / 3); /* 3 thirds minus the two 0.5rem gaps */
    flex: 0 0 auto;
    line-height: 0; /* remove inline-image whitespace under the img */
}

.visualizer-accessory-img {
    width: 100%;
    height: auto;
    object-fit: contain;
}

/* Accessory images enlarge on click (same zoom overlay as the item images). */
.visualizer-accessory-img-zoomable {
    cursor: zoom-in;
}

/* Zoom badge in the bottom-right corner of an accessory image. */
.visualizer-accessory-zoom {
    position: absolute;
    right: 6px;
    bottom: 6px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.9);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
    color: #212529;
    pointer-events: none; /* the figure handles the click */
    transition: background-color 0.15s ease, color 0.15s ease;
}

.visualizer-accessory-figure:hover .visualizer-accessory-zoom {
    background: #e41e26;
    color: #fff;
}
