/*
 * GivePower Hotspot Map — frontend styles.
 * Consumes the High Noon theme's design tokens with hard-coded fallbacks so
 * the component still renders correctly if the theme changes.
 */

.gp-hotspot-map {
    font-family: var(--font-content, "Lato", sans-serif);
}

/* The section is a container-fitting component: it takes the width of its
   parent (Beaver Builder row/column), which owns background and padding. */
.gp-hotspot-map {
    width: 100%;
}

/* Some theme modules (e.g. the flex "box" component) shrink-wrap their
   children instead of stretching them, leaving the hosting module narrower
   than its column. Any Beaver Builder wrapper carrying a hotspot map must
   span the full width it was given. */
.fl-module:has(.gp-hotspot-map),
.fl-module-content:has(.gp-hotspot-map),
.fl-html:has(.gp-hotspot-map) {
    width: 100% !important;
    max-width: 100% !important;
    flex: 1 1 100%;
    align-self: stretch;
}

/* Defined locally (scoped) so the component never depends on the theme for
   it — e.g. inside the admin live-preview iframe. */
.gp-hotspot-map .screen-reader-text {
    position: absolute !important;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.gp-hotspot-map__inner {
    /* No padding of its own — the hosting row controls spacing. The header's
       bottom margin provides the heading-to-photo rhythm. */
    padding: 0;
}

/* The section is transparent by default — the hosting Beaver Builder row
   owns the background. A per-placement `background` shortcode attribute can
   paint it when a page needs the section self-contained. */


/* ---------- Header: title + legend ---------- */

.gp-hotspot-map__header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px 32px;
    flex-wrap: wrap;
    /* Figma: 42px between the heading block and the photo. */
    margin-bottom: clamp(24px, 3vw, 42px);
}

.gp-hotspot-map__eyebrow {
    margin: 0 0 4px;
    font-family: var(--font-headline, "futura-pt", sans-serif);
    font-size: 16px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ocean, #1A3242);
}

/* Figma: Desktop H2 — Futura Medium 500, 62/62, uppercase, Ocean. */
.gp-hotspot-map__title {
    margin: 0;
    font-family: var(--font-headline, "futura-pt", sans-serif);
    font-size: clamp(36px, 4.6vw, 62px);
    font-weight: 500;
    line-height: 1;
    text-transform: uppercase;
    letter-spacing: 0;
    color: var(--ocean, #1A3242);
}

/* Figma: P Regular Desktop — Lato 400, 18/30, Ocean. */
.gp-hotspot-map__legend {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0 0 8px;
    font-size: 18px;
    font-weight: 400;
    line-height: 30px;
    letter-spacing: 0;
    color: var(--ocean, #1A3242);
}

/* Same dot as on the photo: plain gradient circle, no ring, soft halo
   (a scaled-down version of the active dot's #FFC300 glow). */
.gp-hotspot-map__legend-dot {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    border: 0;
    border-radius: 50%;
    background: linear-gradient(0deg, #FFC300 0%, #FFD753 100%);
    box-shadow: 0 0 12px 4px rgba(255, 195, 0, 0.7);
}

/* ---------- Stage ---------- */

.gp-hotspot-map__stage {
    position: relative;
}

.gp-hotspot-map__frame {
    display: block;
    width: 100%;
    overflow: hidden;
    border-radius: var(--border-radius-img, 24px);
}

/* <picture> is inline by default, which can add line-box gaps and lets it
   shrink-wrap — force the full chain to fill the container. */
.gp-hotspot-map__frame picture {
    display: block;
    width: 100%;
}

/* !important: theme/builder CSS on this site has overridden plugin rules
   before (module img sizing, skin resets). The map photo must always span
   its container with its natural aspect ratio. */
.gp-hotspot-map__image {
    display: block;
    width: 100% !important;
    max-width: 100% !important;
    height: auto !important;
}

/* ---------- Hotspot dots ---------- */

/* IMPORTANT: the dot button itself carries NO animation, ever. Some Safari
   builds corrupt the layout of an absolutely-positioned element when a
   running transform animation on it is cancelled (the dot would render at
   its static position — the bottom of the stage). The pulse therefore lives
   entirely on the ::before halo. */
.gp-hotspot-map__dot {
    position: absolute;
    z-index: 2;
    /* Desktop position comes from the inline left/top (plain values for
       maximum browser compatibility); the mobile breakpoint overrides with
       the --gp-mx/--gp-my custom properties. */
    left: 50%;
    top: 50%;
    /* Figma dot SVG: 23px plain gradient circle — no ring, no hairline. */
    width: 23px;
    height: 23px;
    padding: 0;
    margin: 0;
    border: 0;
    border-radius: 50%;
    background: linear-gradient(0deg, #FFC300 0%, #FFD753 100%);
    box-shadow: none;
    cursor: pointer;
    transform: translate(-50%, -50%);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
    -webkit-tap-highlight-color: transparent;
}

/* The BB Theme skin ships `button:active, button:focus { position: relative;
   background: #ffd73a; border: 1px solid #fcc900 }` (plus a grey hover
   repaint) site-wide at specificity 0,1,1 — enough to knock an absolutely-
   positioned button into static flow mid-press, sending clicks to the photo
   instead of the dot. Class+pseudo (0,2,0) pins every interactive state. */
.gp-hotspot-map__dot:hover,
.gp-hotspot-map__dot:focus,
.gp-hotspot-map__dot:active {
    position: absolute;
    background: linear-gradient(0deg, #FFC300 0%, #FFD753 100%);
    border: 0;
    color: var(--ocean, #1A3242);
}

/* The breathing pulse: a radar-style halo expanding out of the dot. */
.gp-hotspot-map__dot::before {
    content: "";
    position: absolute;
    inset: -3px;
    z-index: -1;
    border-radius: 50%;
    background: rgba(255, 195, 0, 0.5);
    pointer-events: none;
    animation: gp-hotspot-pulse 2.8s ease-out infinite;
}

/* Halos breathe out of phase so the field feels alive, not mechanical. */
.gp-hotspot-map__dot:nth-of-type(3n+2)::before {
    animation-delay: 0.9s;
}

.gp-hotspot-map__dot:nth-of-type(3n+3)::before {
    animation-delay: 1.8s;
}

.gp-hotspot-map__dot:hover {
    transform: translate(-50%, -50%) scale(1.18);
}

.gp-hotspot-map__dot:hover::before {
    animation-play-state: paused;
    opacity: 0;
}

.gp-hotspot-map__dot:focus-visible {
    outline: 2px solid var(--white, #fff);
    outline-offset: 2px;
    box-shadow: 0 0 0 6px rgba(26, 50, 66, 0.9);
}

.gp-hotspot-map__dot:focus-visible::before {
    display: none;
}

/* Figma active dot SVG: 39px circle (23 x 1.7) with a soft pure-#FFC300
   halo — feMorphology dilate 11px + gaussian blur stdDeviation 17
   ≈ box-shadow spread 11px / blur 34px. */
.gp-hotspot-map__dot.is-active {
    z-index: 3;
    transform: translate(-50%, -50%) scale(1.7);
    box-shadow: 0 0 34px 11px #FFC300;
}

.gp-hotspot-map__dot.is-active::before {
    display: none;
}

/* Rest the ambient pulse while a card is open so motion doesn't compete
   with reading. Only the halo pseudo-element is affected — the positioned
   button itself never gains or loses an animation. */
.gp-hotspot-map--card-open .gp-hotspot-map__dot::before {
    display: none;
}

/* Larger touch target without growing the visual dot. */
.gp-hotspot-map__dot::after {
    content: "";
    position: absolute;
    inset: -9px;
    border-radius: 50%;
}

/* Runs on the ::before halo only — never on the positioned button. */
@keyframes gp-hotspot-pulse {
    0% {
        transform: scale(1);
        opacity: 0.7;
    }

    70% {
        transform: scale(2.1);
        opacity: 0;
    }

    100% {
        transform: scale(2.1);
        opacity: 0;
    }
}

/* ---------- Info card (desktop: overlay on the image) ---------- */

.gp-hotspot-map__card {
    position: absolute;
    z-index: 4;
    top: 50%;
    right: clamp(16px, 3vw, 40px);
    /* Figma: 384px card. */
    width: min(384px, calc(100% - 32px));
    max-height: calc(100% - 32px);
    overflow-y: auto;
    background: var(--cream, #F6F2EF);
    border-radius: 24px;
    /* Layered: a tight contact shadow plus a deep soft key shadow, so the
       card reads as floating above the photo rather than printed on it. */
    box-shadow:
        0 2px 6px rgba(12, 12, 13, 0.08),
        0 24px 48px -12px rgba(26, 50, 66, 0.35);
    opacity: 0;
    transform: translateY(calc(-50% + 12px));
    transition:
        opacity 0.3s cubic-bezier(0.22, 1, 0.36, 1),
        transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
    overscroll-behavior: contain;
}

.gp-hotspot-map__card.is-open {
    opacity: 1;
    transform: translateY(-50%);
}

/* The same guard the scrim carries: a dismissed card stays in the DOM for
   CLOSE_DELAY (400ms) while it fades, and would otherwise keep absorbing taps
   aimed at the dots underneath it. Critical on phones, where the card is
   centred and covers every dot. `:not([hidden])` is load-bearing — the no-JS
   fallback reveals the cards with the hidden attribute still set, and their
   bodies may contain links that must stay clickable. */
.gp-hotspot-map__card:not(.is-open):not([hidden]) {
    pointer-events: none;
}

.gp-hotspot-map__card--left {
    right: auto;
    left: clamp(16px, 3vw, 40px);
}

/* The card is a reading container: it receives programmatic focus for
   screen-reader context, but must never draw a ring (Safari applies
   :focus-visible to script focus, which put a blue outline around the
   card for mouse users). Keyboard focus indication lives on the card's
   interactive children (the close button). */
.gp-hotspot-map__card:focus,
.gp-hotspot-map__card:focus-visible {
    outline: none !important;
}

.gp-hotspot-map__card-close {
    /* Sticky (not absolute): the card is its own scroll container, and the
       close control must stay visible however far the content scrolls. */
    position: sticky;
    top: 12px;
    float: right;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    /* Figma: 42px close circle, ~17px in from the card's top-right corner. */
    width: 42px;
    height: 42px;
    /* Negative bottom margin collapses the float's footprint to zero height
       so the (block-level replaced) thumbnail below is not pushed down —
       the button overlays the image corner as in the design. */
    margin: 18px 17px -60px 0;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--charcoal, #2B2B2B);
    color: var(--white, #fff);
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    transition: background-color 0.15s ease, transform 0.15s ease;
}

/* Same guard for the close button (it is a <button> too — the theme skin
   would repaint it yellow and unstick it while pressed). */
.gp-hotspot-map__card-close:hover,
.gp-hotspot-map__card-close:focus,
.gp-hotspot-map__card-close:active {
    position: sticky;
    border: 0;
    background: var(--charcoal, #2B2B2B);
    color: var(--white, #fff);
}

.gp-hotspot-map__card-close:hover {
    background: var(--ocean, #1A3242);
    transform: scale(1.08);
}

.gp-hotspot-map__card-close:focus-visible {
    outline: 3px solid var(--ocean, #1A3242);
    outline-offset: 2px;
}

/* The floated close button overlaps the media block (floats overlap block
   boxes), so the button sits over the thumbnail's top-right corner as in
   the design without extra offsets. */
.gp-hotspot-map__card-media {
    /* Figma: thumbnail inset 10px top, 11px sides. */
    padding: 10px 11px 0;
}

.gp-hotspot-map__card-thumb {
    display: block;
    width: 100%;
    height: auto;
    /* Figma: 362x217. */
    aspect-ratio: 362 / 217;
    object-fit: cover;
    border-radius: 16px;
}

.gp-hotspot-map__card-content {
    /* Figma: 21px below the thumbnail, 27px sides, 20px bottom. */
    padding: 21px 27px 20px;
}

/* Figma: P Large Bold — Lato Heavy 800, 24/36, Ocean. (The site loads Lato
   400/700/900; 800 resolves to the loaded 900.) */
.gp-hotspot-map__card-title {
    margin: 0 0 16px;
    font-family: var(--font-content, "Lato", sans-serif);
    font-size: 24px;
    font-weight: 800;
    line-height: 36px;
    letter-spacing: 0;
    color: var(--ocean, #1A3242);
}

/* Figma: P Regular — Lato 400, 18/30, Ocean. */
.gp-hotspot-map__card-body {
    font-size: 18px;
    line-height: 30px;
    color: var(--ocean, #1A3242);
}

.gp-hotspot-map__card-body p {
    margin: 0 0 12px;
}

.gp-hotspot-map__card-body p:last-child {
    margin-bottom: 0;
}

.gp-hotspot-map__card-steps-title {
    margin: 20px 0 4px;
    font-family: var(--font-content, "Lato", sans-serif);
    font-size: 18px;
    font-weight: 800;
    line-height: 30px;
    color: var(--ocean, #1A3242);
}

.gp-hotspot-map__card-steps {
    margin: 0;
    /* Figma: markers indent ~1.5em of the marker size, text tight after. */
    padding-left: 24px;
    font-size: 18px;
    line-height: 30px;
    color: var(--ocean, #1A3242);
}

.gp-hotspot-map__card-steps li {
    margin-bottom: 2px;
    padding-left: 4px;
}

.gp-hotspot-map__card-steps li:last-child {
    margin-bottom: 0;
}

/* ---------- Scrim (mobile) ---------- */

.gp-hotspot-map__scrim {
    position: fixed;
    inset: 0;
    z-index: 99998;
    background: rgba(26, 50, 66, 0.55);
    opacity: 0;
    /* No pointer events while fading out, so a tap right after closing
       reaches the page instead of the dying scrim. */
    pointer-events: none;
    transition: opacity 0.28s ease;
}

.gp-hotspot-map__scrim.is-open {
    opacity: 1;
    pointer-events: auto;
}

/* ---------- Mobile: centred modal ---------- */

@media (max-width: 767px) {
    .gp-hotspot-map__header {
        align-items: flex-start;
        flex-direction: column;
    }

    .gp-hotspot-map__frame {
        border-radius: var(--border-radius-img-mobile, 16px);
    }

    .gp-hotspot-map__dot {
        /* !important: must beat the inline desktop left/top. Every dot
           always carries --gp-mx/--gp-my (mirroring desktop when no mobile
           position was set), so these always resolve. */
        left: var(--gp-mx, 50%) !important;
        top: var(--gp-my, 50%) !important;
        width: 20px;
        height: 20px;
    }

    /* Comfortable reading sizes on phones. */
    .gp-hotspot-map__legend {
        font-size: 16px;
        line-height: 26px;
    }

    .gp-hotspot-map__card-title {
        font-size: 20px;
        line-height: 28px;
    }

    .gp-hotspot-map__card-body,
    .gp-hotspot-map__card-steps,
    .gp-hotspot-map__card-steps-title {
        font-size: 16px;
        line-height: 26px;
    }

    /* The card floats in the middle of the screen rather than docking to the
       bottom edge. It is portaled to <body> before opening, so the fixed
       containing block is the viewport and the 90% is 90% of screen width.
       The cap never engages on a phone in portrait (90% of the widest phone
       is ~387px) — it only stops the card sprawling to a 100-character
       measure in landscape. */
    .gp-hotspot-map__card,
    .gp-hotspot-map__card--left {
        position: fixed;
        z-index: 99999;
        top: 50%;
        right: auto;
        bottom: auto;
        left: 50%;
        width: min(90%, 480px);
        max-height: 80vh;
        max-height: 80dvh;
        border-radius: var(--border-radius-img-mobile, 16px);
        /* A 16px rise layered on top of the centring offset. (The desktop card
           rises 12px — these are different objects and share no magic number.) */
        transform: translate(-50%, calc(-50% + 16px));
        box-shadow:
            0 2px 8px rgba(12, 12, 13, 0.1),
            0 24px 60px -12px rgba(26, 50, 66, 0.45);
        transition:
            opacity 0.34s cubic-bezier(0.22, 1, 0.36, 1),
            transform 0.34s cubic-bezier(0.22, 1, 0.36, 1);
    }

    .gp-hotspot-map__card.is-open {
        transform: translate(-50%, -50%);
    }

    /* Half the padding ring around the glyph. The × is unchanged (still 22px
       Lato, a 12.8px ink box); the visible gap from glyph to circle edge was
       (42 − 12.8) / 2 = 14.6px, so halving it gives 12.8 + 14.6 = 27.4 ≈ 28px.
       The negative bottom margin re-collapses the float's footprint to zero at
       the new height (18 top + 28 height − 46 = 0), so the thumbnail below is
       still not pushed down. */
    .gp-hotspot-map__card-close {
        width: 28px;
        height: 28px;
        margin-bottom: -46px;
    }

    /* The visible circle shrinks but the touch target must not: this keeps a
       44px tappable area around the smaller button. */
    .gp-hotspot-map__card-close::after {
        content: "";
        position: absolute;
        inset: -8px;
        border-radius: 50%;
    }
}

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
    .gp-hotspot-map__dot {
        transition: none;
    }

    .gp-hotspot-map__dot::before {
        display: none;
    }

    .gp-hotspot-map__card,
    .gp-hotspot-map__scrim,
    .gp-hotspot-map__card-close {
        transition: none;
    }
}

/* ---------- Editor-only inline notice ---------- */

.gp-hotspot-map__editor-notice {
    margin: 16px 0;
    padding: 12px 16px;
    border-left: 4px solid var(--yellow, #FFC300);
    background: var(--cream, #F6F2EF);
    color: var(--charcoal, #2B2B2B);
    font-size: 14px;
}

/* The no-JS fallback is emitted as a <noscript><style> block by the renderer
   so cards never flash open while the footer script is still loading. */
