/*
 * Virgo CMS - Hotspot Image module styles.
 *
 * Clickable points over a single image. The stage holds one main image and N
 * percentage-positioned pins; each pin dispatches an action on click (popup /
 * menu_link / url / image / video). The image is shown at its ORIGINAL aspect
 * ratio (uncropped): the stage pins the image height (--hi-height) and derives
 * its width from the image's own ratio (--hi-aspect), so the stage is exactly
 * as wide as the image — no letterbox gap. Pins (positioned by percentage on
 * the stage) therefore always land on the image, and stay correct when the
 * height changes. Pin positions are applied at runtime by the engine
 * (element.style.left/top) from data-x / data-y.
 *
 * Runtime values come from CSS custom properties set inline by the renderer
 * (the only sanctioned inline-style use): --hi-pin-size, --hi-height,
 * --hi-aspect, --hi-radius, --hi-popup-max.
 *
 * Colors/radii/shadows draw from the design-system tokens defined in
 * template.css :root (--primary-color, --text-color, --text-ink, --bg-color,
 * --border-color, --shadow-*). No literal brand colors are authored here.
 *
 * This stylesheet also covers the ADMIN editor (admin/modules.php edit page)
 * because the editor reuses the same .hotspot-pin / stage vocabulary on the
 * .hotspot-editor canvas. Admin-only rules are scoped under .hotspot-editor.
 */

/* ============================================
   FRONTEND ROOT + STAGE
   ============================================ */

.hotspot-image {
    --hi-pin-size: 32px;
    --hi-height: 500px;
    --hi-aspect: 1 / 1;
    --hi-radius: var(--radius-md, 8px);
    --hi-popup-max: 360px;
    /* Pin opacity (admin "Nokta Opaklığı", 30–100% → 0.3–1.0). Scales every pin's
       own opacity; the pulse halo and tooltip keep their own opacity behavior. */
    --hi-pin-opacity: 1;
    /* Pin + pulse-halo share one color source. Default is the primary token; the
       engine overrides --hi-pin-glow per pin when an admin pin_color is set, so
       the halo always matches the pin fill. */
    --hi-pin-glow: var(--primary-color, var(--bs-primary, #0d6efd));
    /* Glyph (foreground) color for the pin's numeral / icon. Default is the page
       surface token so the glyph reads against the pin fill; the engine overrides
       --hi-pin-glyph per pin when an admin icon_color / number_color is set. */
    --hi-pin-glyph: var(--bg-color, #ffffff);

    box-sizing: border-box;
    width: 100%;
}

.hotspot-image *,
.hotspot-image *::before,
.hotspot-image *::after {
    box-sizing: border-box;
}

/* The stage keeps the image's original aspect ratio (uncropped) at every
   viewport. The image height is treated as a MAXIMUM (--hi-height): on wide
   containers the stage grows up to that height and derives its width from the
   ratio; on narrow containers (mobile) max-width:100% caps the stage width and
   the height scales down proportionally to keep the ratio, never cropping and
   never forcing the desktop height. The result: pins positioned by percentage
   always land on the image, never on a gap, and stay put as the stage shrinks. */
.hotspot-image__stage {
    position: relative;
    height: auto;
    max-height: var(--hi-height);
    width: auto;
    max-width: 100%;
    aspect-ratio: var(--hi-aspect);
    overflow: visible;
    border-radius: var(--hi-radius);
    background: var(--bg-color, #ffffff);
}

/* Inner frame: keeps corners clean. Pins live OUTSIDE this frame (positioned on
   the stage), so a pin placed at an edge is never clipped. */
.hotspot-image__stage-frame {
    position: absolute;
    inset: 0;
    overflow: hidden;
    border-radius: inherit;
}

/* The image fills the stage exactly (the stage already matches its ratio, so
   no cropping occurs). */
.hotspot-image__img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    -webkit-user-select: none;
    user-select: none;
    -webkit-user-drag: none;
}

/* ============================================
   PINS
   ============================================ */

.hotspot-image__pin {
    position: absolute;
    transform: translate(-50%, -50%);
    width: var(--hi-pin-size);
    height: var(--hi-pin-size);
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--primary-color, var(--bs-primary, #0d6efd));
    color: var(--hi-pin-glyph, var(--bg-color, #ffffff));
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: calc(var(--hi-pin-size) * 0.5);
    font-weight: 700;
    line-height: 1;
    box-shadow: var(--shadow, 0 4px 8px rgba(26, 36, 33, 0.35));
    transition: box-shadow 0.18s ease, opacity 0.18s ease;
    opacity: var(--hi-pin-opacity, 1);
    z-index: 2;
}

/* Hover and focus do NOT scale the pin. A hover-scale transform was the
   flicker source: the pin enlarges, the cursor (still at the same screen
   point) slips off the now-shifted hit-box edge, hover drops, the pin snaps
   back, the cursor is over the pin again, hover re-enters — repeat. The
   non-scaling transform stays identical on hover, so the hit-box never moves
   relative to the cursor; hover state is stable. The only hover feedback is
   a stronger shadow + full opacity (so a dimmed pin still reads clearly when
   the user is about to click it). */
.hotspot-image__pin:hover,
.hotspot-image__pin:focus-visible {
    box-shadow: var(--shadow-lg, 0 12px 32px rgba(26, 36, 33, 0.45));
    opacity: 1;
    outline: none;
}

.hotspot-image__pin:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
}

/* Icon variant: a slightly larger glyph so common icons read clearly. Scales
   with the pin box (--hi-pin-size) so the icon grows/shrinks with the pin. */
.hotspot-image__pin--icon {
    font-size: calc(var(--hi-pin-size) * 0.55) !important;
}

/* The numeral span (number variant). pointer-events:none so the digit never
   steals the click from the button. font-size is pinned to --hi-pin-size directly
   (mirroring the icon variant) instead of relying on inheritance, so the digit
   scales with the pin box when the pin size setting changes. */
.hotspot-image__pin-num {
    pointer-events: none;
    font-size: calc(var(--hi-pin-size) * 0.5) !important;
}

/* Pulse halo (enabled via .hotspot-image--pulse on the root). The halo expands
   via box-shadow spread, NOT transform: scale. A transform on ::before combined
   with the pin's hover-scale transition forces continuous compositing/repaint
   (visible flicker), and a scaled ::before also makes the perceived pin much
   larger than its hit box (off-center clicks miss the button). box-shadow keeps
   the halo purely visual — the clickable area stays the pin's own box — and adds
   no transform layer, so there is no flicker. The halo color tracks the pin
   color via --hi-pin-glow (set by the engine when a per-pin color is present),
   falling back to the primary token. */
/* z-index is 0 (NOT -1). The pin carries a transform (the centering
   translate), which establishes a new stacking context on the button itself.
   With z-index:-1 the ::before would be painted BEHIND the pin's own opaque
   background — and since the pin's box exactly covers the ::before, the halo
   box-shadow spread (the only part that extends past the pin) renders behind
   the stage too, so the pulse visually vanishes. z-index:0 keeps the halo
   below the pin content (the number/icon) but above the pin's own background
   layer, so the expanding spread stays visible while pulsing. */
.hotspot-image--pulse .hotspot-image__pin::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    box-shadow: 0 0 0 0 var(--hi-pin-glow);
    animation: hotspot-pulse 2s ease-out infinite;
    pointer-events: none;
    z-index: 0;
}

@keyframes hotspot-pulse {
    0% {
        box-shadow: 0 0 0 0 var(--hi-pin-glow);
        opacity: 1;
    }
    70% {
        box-shadow: 0 0 0 calc(var(--hi-pin-size) * 0.6) var(--hi-pin-glow);
        opacity: 0;
    }
    100% {
        box-shadow: 0 0 0 calc(var(--hi-pin-size) * 0.6) var(--hi-pin-glow);
        opacity: 0;
    }
}

/* ============================================
   TOOLTIP (pin hover label)
   ============================================ */

/* Tooltip surface = the page surface token (--bg-color) and label = the ink
   token (--text-ink). These two tokens are theme-aware opposites in
   template.css :root (light: white bg / dark ink; dark: dark bg / light ink),
   so the tooltip reads correctly in BOTH themes. The previous mapping swapped
   them (--text-ink on background), which inverted the colors. */
.hotspot-image__tooltip {
    position: absolute;
    left: 50%;
    background: var(--bg-color, rgba(0, 0, 0, 0.85));
    color: var(--text-ink, #ffffff);
    padding: var(--radius-xs, 4px) var(--radius-xs, 8px);
    border-radius: var(--radius-xs, 4px);
    font-size: 12px;
    font-weight: 500;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s ease;
    z-index: 3;
}

.hotspot-image--tooltip-top .hotspot-image__tooltip    { bottom: calc(100% + 8px);  transform: translateX(-50%); }
.hotspot-image--tooltip-bottom .hotspot-image__tooltip { top: calc(100% + 8px);     transform: translateX(-50%); }
.hotspot-image--tooltip-left .hotspot-image__tooltip   { right: calc(100% + 8px);   top: 50%; transform: translateY(-50%); }
.hotspot-image--tooltip-right .hotspot-image__tooltip  { left: calc(100% + 8px);    top: 50%; transform: translateY(-50%); }

.hotspot-image:not(.hotspot-image--tooltip) .hotspot-image__tooltip {
    display: none;
}

.hotspot-image__pin:hover .hotspot-image__tooltip,
.hotspot-image__pin:focus-visible .hotspot-image__tooltip {
    opacity: 1;
}

/* ============================================
   POPUP MODAL (SweetAlert2 — Google Maps InfoWindow clone)
   ============================================ */

/* The popup uses this module's OWN .hotspot-image-info-* vocabulary and does
   NOT depend on google-maps.css (module CSS/JS independence rule). The popup
   markup mirrors the Google Maps InfoWindow so both modules render the same
   popup, but the styles live here under self-named classes.
   SweetAlert2 injects its own padding on .swal2-popup; reset it so the padding
   lives on the inner .hotspot-image-info-window box (matching the maps InfoWindow
   layout where the close button anchors to the padded box's corner). The card
   chrome (border-radius + box-shadow) mirrors the maps InfoWindow / Leaflet
   popup card so both popups look identical.
   Margin is zeroed here as a static default so the engine's runtime top/left
   (inline-CSS exception 1) anchor the popup to the clicked pin without fighting
   SweetAlert2's flex-centering margins; top/left/transform are applied by JS at
   open time because they depend on the live pin coordinates. */
.hotspot-image-modal__popup {
    padding: 0 !important;
    margin: 0;
    text-align: initial;
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg);
}

/* SweetAlert2 centers its content (.swal2-popup text-align:center + grid) and
   wraps the inner HTML in .swal2-html-container which carries its own padding
   (--swal2-html-container-padding: 1em 1.6em 0.3em). The maps InfoWindow has no
   such wrapper — content padding comes only from .hotspot-image-info-window
   (12px 14px). Zero out the SweetAlert2 wrapper's padding+margin so the single
   padded box matches the maps layout exactly, and force start alignment so
   title, image+desc row and the standalone link sit flush to the inline-start
   edge like the maps popup. */
.hotspot-image-modal .swal2-html-container {
    text-align: start;
    margin: 0;
    padding: 0;
}

/* ============================================
   POPUP INFO WINDOW CONTENT (self-contained, no google-maps.css dependency)
   ============================================ */

/* Popup content mirrors the Google Maps InfoWindow exactly (min/max width +
   padding), so the rendered box is the same size as the maps popup.
   position: relative anchors the custom close button (.hotspot-image-info-close-btn). */
.hotspot-image-info-window {
    position: relative;
    font-family: inherit !important;
    min-width: 180px;
    max-width: 300px;
    padding: 12px 14px;
    font-size: 0.875rem !important;
    text-align: start;
}

/* Popup content row: image + description side by side */
.hotspot-image-info-content-row {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    gap: 8px;
    margin-top: 6px;
}

/* RTL: image left, text right */
[dir="rtl"] .hotspot-image-info-content-row {
    flex-direction: row-reverse;
}

.hotspot-image-info-image {
    width: 100px;
    border-radius: var(--radius-xs);
    flex-shrink: 0;
}

.hotspot-image-info-text {
    min-width: 0;
    flex: 1;
}

.hotspot-image-info-title {
    font-weight: 700;
    font-size: 1rem !important;
    margin-bottom: 4px;
    color: var(--text-ink);
    line-height: 1.3;
}

.hotspot-image-info-desc {
    font-size: 0.8125rem !important;
    color: var(--text-color);
    margin-bottom: 6px;
    line-height: 1.4;
}

.hotspot-image-info-link {
    font-size: 1rem !important;
    font-weight: 600;
    color: var(--primary-color);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    outline: none;
    justify-content: flex-start;
}

.hotspot-image-info-link:hover {
    text-decoration: underline;
    color: var(--primary-deep);
}

.hotspot-image-info-link:focus-visible {
    outline: 2px solid var(--primary-color);
    outline-offset: 2px;
    border-radius: var(--radius-xs);
}

.hotspot-image-info-link:hover sup {
    opacity: 1;
}

/* ============================================
   POPUP CLOSE BUTTON (module-consistent, no google-maps.css dependency)
   ============================================ */

/* A single close button rendered inside the popup content. Sized and positioned
   identically to the maps InfoWindow / Leaflet popup close control so all three
   modules show the exact same control in the exact same place. Anchored to the
   inline-end (right in LTR) top corner of the padded .hotspot-image-info-window
   box. */
.hotspot-image-info-close-btn {
    position: absolute;
    top: 5px;
    inset-inline-end: 5px;
    width: 11px;
    height: 11px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    border-radius: var(--radius-xs);
    background-color: transparent;
    color: var(--text-muted);
    cursor: pointer;
    line-height: 1;
    z-index: 5;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.hotspot-image-info-close-btn:hover,
.hotspot-image-info-close-btn:focus-visible {
    color: var(--text-ink);
    outline: none;
}

.hotspot-image-info-close-btn i {
    font-size: 0.5rem;
}

/* ============================================
   POPUP RESPONSIVE (small viewports)
   ============================================ */

/* Stack image + description vertically on narrow screens (matches the maps
   InfoWindow / Leaflet popup responsive behavior). */
@media (max-width: 767.98px) {
    /* The engine opens the popup at a fixed SweetAlert2 width (200px on mobile).
       That value is applied as a fixed .swal2-popup width, which would overflow
       a sub-320px viewport and fight the engine's horizontal clamp. Cap the
       popup at the live viewport width (minus the MARGIN kept by the clamp) so
       it shrinks to fit narrow screens instead of bleeding past the edge. */
    .hotspot-image-modal__popup {
        max-width: calc(100vw - 16px) !important;
    }

    .hotspot-image-info-content-row {
        flex-direction: column !important;
    }

    .hotspot-image-info-image {
        width: auto;
        max-width: 150px !important;
        max-height: 50px !important;
    }

    .hotspot-image-info-desc {
        font-size: 0.8rem !important;
    }

    .hotspot-image-info-title.hotspot-image-info-link {
        display: inline;
        background: none;
    }
}

/* ============================================
   POPUP DARK MODE
   ============================================ */

/* Dark mode — match the maps InfoWindow dark card (google-maps.css) and the
   Leaflet popup card (openstreet-maps.css): same #242830 background and deeper
   shadow. Overrides template.css's generic dark .swal2-popup for this popup. */
html[data-bs-theme="dark"] .hotspot-image-modal__popup {
    background-color: #242830 !important;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
}

html[data-bs-theme="dark"] .hotspot-image-info-title {
    color: #e2e2f0;
}

html[data-bs-theme="dark"] .hotspot-image-info-desc {
    color: #a0a0b8;
}

html[data-bs-theme="dark"] .hotspot-image-info-link {
    color: #2d8676;
}

html[data-bs-theme="dark"] .hotspot-image-info-link:hover {
    color: var(--primary-color);
}

html[data-bs-theme="dark"] .hotspot-image-info-close-btn {
    color: #a0a0b8;
}

html[data-bs-theme="dark"] .hotspot-image-info-close-btn:hover {
    background-color: rgba(255, 255, 255, 0.08);
    color: #e2e2f0;
}

/* ============================================
   ACCESSIBILITY — reduced motion
   ============================================ */

@media (prefers-reduced-motion: reduce) {
    .hotspot-image__pin,
    .hotspot-image__pin::before,
    .hotspot-image__tooltip {
        transition: none;
        animation: none;
    }

    .hotspot-image--pulse .hotspot-image__pin::before {
        animation: none;
        opacity: 0;
    }
}
