/* ==========================================================================
   hotspots.css — in-panorama markers.  Component: js/hotspots.js

   A hotspot is a "pill": a white circle (with the gradient type-icon) that,
   on hover, smoothly expands to the right to reveal the location name.
   The circle stays anchored to the panorama point; only the pill grows.

   Colours are driven by the variables below so re-theming is a one-line change.
   The icon is the type SVG (assets/icons/{type}.svg) applied as a mask, so its
   colour comes from --hotspot-fg (a gradient), not from the file.
   ========================================================================== */

:root {
  --hotspot-size: 32px;                             /* circle diameter */
  --hotspot-pill-h: 32px;                           /* pill body height (= circle) */
  --hotspot-bg: #ffffff;                            /* circle fill (white) */
  --hotspot-bg-hover: #ffffff;                      /* circle fill on hover */
  /* Arrow icon fill: brand gradient */
  --hotspot-fg: linear-gradient(135deg, var(--color-green) 0%, var(--color-mint) 50%, var(--color-blue) 100%);
  /* Pill body: same brand gradient */
  --hotspot-pill-bg: linear-gradient(135deg, var(--color-green) 0%, var(--color-mint) 50%, var(--color-blue) 100%);
  /* Smooth ease-out for the expand (no overshoot, gentle settle) */
  --hotspot-ease: cubic-bezier(0.33, 0.9, 0.28, 1);
  --hotspot-expand-dur: 0.55s;                      /* pill + label expand duration */

  /* Featured hotspots (the plant manager's message, sustainability,
     certifications) are visually IDENTICAL to every other hotspot — same
     brand gradient, same size, same hover label. The pulsing ring below is
     the only thing that sets them apart, and it stops for good once the
     visitor opens the hotspot (see hotspots.js). White, so it reads against
     both the sky and the greenery in the drone shot. */
  --pulse-ring-rgb: 255 255 255;
}

/* Outer element is owned/positioned by Marzipano — keep it layout-neutral. */
.hotspot.link-hotspot {
  cursor: pointer;
  user-select: none;
  /* Default z-index for all hotspots */
  z-index: 1;
  position: relative;
}

/* A hotspot showing the "Start here" callout sits above every IDLE hotspot,
   but still below whichever one the visitor is actively hovering — the thing
   under the cursor should always win, otherwise its expanded label reads as
   sliding underneath the callout.

   The three z-index tiers this juggles:
     1     — idle hotspots (the rule above)
     50    — this one, while the callout is showing
     101+  — the hovered/expanded hotspot (hotspots.js sets this inline via
             zIndexCounter, which starts at 100 and only ever increments, so
             it always clears 50)
   !important is needed because hotspots.js also *resets* the inline z-index
   back to 1 after a hover ends — without it, this hotspot would silently drop
   to the idle tier the first time it's hovered and left. Excluding the
   hovered/expanded state means its own inline 101+ still applies when it is
   the one being hovered, so it can rise above everything as normal. */
.link-hotspot:has(.hotspot-starthere):not(:hover):not(.is-expanded) {
  z-index: 50 !important;
}

/* The pill: circle + label on one row, sharing a rounded gradient body.
   Shifted left by half a circle so the CIRCLE (not the whole pill) sits on
   the panorama point; the pill then expands to the right on hover. */
.link-hotspot__pill {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translate(calc(var(--hotspot-size) / -2), -50%);
  display: inline-flex;
  align-items: center;
  height: var(--hotspot-pill-h);
  border-radius: 999px;
  background: var(--hotspot-pill-bg);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.35);
  /* Collapsed: only wide enough for the circle. Expands on hover.
     No overflow:hidden here — that would clip the circle when it scales on
     hover. The label clips itself instead (see .link-hotspot__label). */
  max-width: var(--hotspot-size);
  transition: max-width var(--hotspot-expand-dur) var(--hotspot-ease);
  will-change: max-width;
}

.link-hotspot:hover .link-hotspot__pill,
.link-hotspot.is-expanded .link-hotspot__pill {
  /* Exact content width, measured on first hover (see hotspots.js). The 640px
     fallback only applies on the very first frame before measurement, so the
     animated range is fully visible and expand matches collapse.
     .is-expanded is the touch-device equivalent, toggled by tap (see
     hotspots.js) since touch devices have no persistent hover state. */
  max-width: var(--pill-expanded, 640px);
}

/* Dark circle behind every hotspot marker */
.link-hotspot__marker::before {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.2);
  z-index: -1;
  pointer-events: none;
}

/* White circle (slightly taller than the pill so it "pops"). Always visible. */
.link-hotspot__marker {
  position: relative;
  flex: 0 0 var(--hotspot-size);
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--hotspot-size);
  height: var(--hotspot-size);
  border-radius: 50%;
  background: var(--hotspot-bg);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
  transition: background 0.2s ease;
}

.link-hotspot:hover .link-hotspot__marker,
.link-hotspot.is-expanded .link-hotspot__marker {
  background: var(--hotspot-bg-hover);
}

/* Icon: the type SVG used as a mask, filled with --hotspot-fg (a gradient) */
.link-hotspot__icon {
  width: 55%;
  height: 55%;
  background: var(--hotspot-fg);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

/* Label revealed inside the pill on hover */
.link-hotspot__label {
  white-space: nowrap;
  overflow: hidden;
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1;
  /* Collapsed: clipped and transparent; expands with the pill. */
  max-width: 0;
  padding-right: 0;
  padding-left: 0;
  opacity: 0;
  transition: max-width var(--hotspot-expand-dur) var(--hotspot-ease),
              padding var(--hotspot-expand-dur) var(--hotspot-ease),
              opacity 0.25s ease-out 0.1s;
}

.link-hotspot:hover .link-hotspot__label,
.link-hotspot.is-expanded .link-hotspot__label {
  max-width: 600px;
  padding-left: 10px;
  padding-right: 16px;
  opacity: 1;
}

/* ── Info, Video & QR hotspot variants ───────────────────────────────── */
.link-hotspot--info .link-hotspot__marker,
.link-hotspot--video .link-hotspot__marker,
.link-hotspot--qr .link-hotspot__marker {
  background: var(--hotspot-pill-bg);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}

.link-hotspot--info .link-hotspot__icon,
.link-hotspot--video .link-hotspot__icon,
.link-hotspot--qr .link-hotspot__icon {
  background: #fff;
}

/* The play triangle fills its 8x8 viewBox, so its bounding box is centred but
   its centroid (visual weight) sits at x≈2.67 of 8 — noticeably left of centre.
   Nudge it right optically. Done with a transform rather than by reshaping the
   polygon so the triangle's proportions stay intact. */
.link-hotspot--video .link-hotspot__icon {
  width: 40%;
  height: 40%;
  transform: translateX(8%);
}

.link-hotspot--qr .link-hotspot__icon {
  width: 50%;
  height: 50%;
}

.link-hotspot--info:hover .link-hotspot__marker,
.link-hotspot--video:hover .link-hotspot__marker,
.link-hotspot--qr:hover .link-hotspot__marker,
.link-hotspot--info.is-expanded .link-hotspot__marker,
.link-hotspot--video.is-expanded .link-hotspot__marker,
.link-hotspot--qr.is-expanded .link-hotspot__marker {
  background: var(--hotspot-pill-bg);
}

/* ── Landmark hotspots ───────────────────────────────────────────────────
   Geographic orientation on the drone overview — the canal, the solar field,
   the rail spur, the motorway link. They answer "what am I looking at?",
   where every other dot answers "what happens here?" or "where can I go?",
   so they get their own pin glyph rather than reusing the info circle.

   Deliberately SUBORDINATE to the other markers: smaller, a white pin on a
   neutral dark chip instead of the brand gradient. The overview already
   carries 26 hotspots; landmarks rendered at equal weight would bury the
   places a visitor can actually enter. These are map annotation, so they
   should read as a caption layer, not as more destinations.

   Achieved by overriding the same tokens the rest of the file reads, so the
   pill, marker, icon and label all follow from this one block. */
.link-hotspot--landmark {
  --hotspot-size: 24px;
  --hotspot-pill-h: 24px;
  /* The label chip stays dark so white text on it reads over any terrain.
     It is hidden until hover though — see the rule below. */
  --hotspot-pill-bg: rgba(20, 28, 34, 0.72);
}

/* The pill is the label chip, and when collapsed it sits exactly behind the
   marker at the same diameter. With an opaque marker that never shows, but a
   TRANSLUCENT one lets the chip through — so a 0.72 pill under a 0.28 marker
   composited to ~0.80 and the dot looked almost solid however far the marker
   alpha was lowered. Landmarks therefore carry no chip at rest; it fades in
   with the label on hover, where it is actually needed. */
.link-hotspot--landmark .link-hotspot__pill {
  background: transparent;
  box-shadow: none;
  transition: max-width var(--hotspot-expand-dur) var(--hotspot-ease),
              background 0.2s ease;
}
.link-hotspot--landmark:hover .link-hotspot__pill,
.link-hotspot--landmark.is-expanded .link-hotspot__pill {
  background: var(--hotspot-pill-bg);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.35);
}
/* Dark disc with a white pin. With the chip behind it now removed at rest,
   this alpha is finally the ONLY thing setting the dot's weight — it is the
   dial, and what you see is what it says. The drop shadow is light to match;
   a heavier one would read as a smudge under a disc this faint. Hover jumps
   a long way up so the marker still clearly answers the cursor. */
.link-hotspot--landmark .link-hotspot__marker {
  background: rgba(20, 28, 34, 0.35);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
}
.link-hotspot--landmark:hover .link-hotspot__marker,
.link-hotspot--landmark.is-expanded .link-hotspot__marker {
  background: rgba(20, 28, 34, 0.75);
}
.link-hotspot--landmark .link-hotspot__icon {
  width: 58%;
  height: 58%;
  background: #fff;
}
/* Smaller marker needs a smaller label to stay in proportion. */
.link-hotspot--landmark .link-hotspot__label {
  font-size: 11px;
  letter-spacing: 0.03em;
}
/* The shared dark backing ring is tuned to sit behind the white 32px circle;
   behind a translucent dark 24px disc it just muddies the edge. */
.link-hotspot--landmark .link-hotspot__marker::before {
  display: none;
}
/* Set by hotspots.js on a landmark with no infoText: hovering still reveals
   the name, but clicking does nothing, so it shouldn't offer a pointer. */
.link-hotspot.is-static {
  cursor: default;
}

/* ── Featured hotspots ────────────────────────────────────────────────
   Opt-in via `"featured": true` on any hotspot in tour.json (see app.js,
   which adds .is-featured). Identical to every other marker of its type —
   same brand gradient, same size, same behaviour; the pulsing ring below is
   the ONLY thing that makes it stand out, for the handful of things that
   matter most to a first-time visitor (corporate video, certifications,
   etc). */

/* Pulsing ring — a second element so the scale animation doesn't fight with
   the hover-expand transform on the marker itself. Fades away on hover/expand
   so it doesn't compete with the label for attention once noticed.

   Split across TWO elements on purpose:
     .link-hotspot__pulse          — positioning + the hover fade (transition)
     .link-hotspot__pulse::before  — the ring itself + the pulse (animation)
   A CSS transition cannot reliably interpolate a property that a keyframe
   animation is also driving — the animation keeps supplying its own value for
   opacity every frame, so the hover fade just snapped instantly no matter the
   duration. Keeping the animation's opacity on the inner element and the
   hover fade's opacity on the outer one means the two never touch the same
   property on the same element, and both work as written. */
.link-hotspot.is-featured .link-hotspot__pulse {
  /* Centred on the marker circle — which sits flush-left in the pill,
     exactly --hotspot-size wide, at a FIXED offset from the pill's left
     edge. `left: 50%` looked right at rest (the collapsed pill is exactly
     --hotspot-size wide too, so 50% of the pill happened to coincide with
     the marker's centre) but is actually relative to the PILL's box, which
     grows via `max-width` on hover/expand — so the ring's anchor slid along
     with the growing pill instead of staying put on the marker, stretching
     the whole animated ring across the revealed label. Anchoring at the
     marker's fixed offset keeps it centred on the marker regardless of the
     pill's width. */
  position: absolute;
  top: 50%;
  left: calc(var(--hotspot-size) / 2);
  width: var(--hotspot-size);
  height: var(--hotspot-size);
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: -1;
  /* Same duration + easing as the pill's own expand (see .link-hotspot__pill)
     so the ring finishes fading exactly as the pill finishes opening, and
     fades back in as it collapses. */
  opacity: 1;
  transition: opacity var(--hotspot-expand-dur) var(--hotspot-ease);
}

/* ── The expanding ring ──────────────────────────────────────────────────
   OPT-IN, and only one hotspot has it: `"pulse": true` in tour.json adds
   .has-pulse (see hotspots.js). Every other featured hotspot gets the static
   halo below and nothing else — motion on several dots at once reads as
   nagging rather than helpful.

   Runs as a short BURST, not forever: three iterations, replayed each time
   the visitor enters the scene (TourController adds .is-pulsing to the
   incoming hotspot container — hotspot elements are built once at startup,
   so without that hook it would play on page load and never again). 3 x 1.6s
   = 4.8s also stays under the five seconds past which WCAG 2.2.2 would
   require a pause control.

   `:not(.is-opened)` stops it for good once the visitor has opened the
   hotspot (persisted, so it also applies on a return visit). Expressed in
   the selector rather than as a later `animation: none` override, which
   would be the same specificity and could lose if the blocks were reordered. */
.link-hotspot.has-pulse .link-hotspot__pulse::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 3px solid rgb(var(--pulse-ring-rgb));
  opacity: 0;
}
.is-pulsing .link-hotspot.has-pulse:not(.is-opened) .link-hotspot__pulse::before {
  animation: hotspot-pulse 1.6s ease-out 3;
}
@keyframes hotspot-pulse {
  0%   { transform: scale(0.1); opacity: 0; }
  50%  { opacity: 1; }
  100% { transform: scale(1.6); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  /* No burst; the static halo alone carries the emphasis. */
  .is-pulsing .link-hotspot.has-pulse:not(.is-opened) .link-hotspot__pulse::before {
    animation: none;
  }
}

/* Permanent static halo — on EVERY featured hotspot, with or without the
   burst above. It never moves and never goes away, so the key hotspots stay
   distinguishable for the rest of the visit. Sits just outside the marker's
   own dark backing ring (.link-hotspot__marker::before, inset -3px). */
.link-hotspot.is-featured .link-hotspot__pulse::after {
  content: '';
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  border: 2px solid rgb(var(--pulse-ring-rgb) / 0.45);
  box-shadow: 0 0 10px 2px rgb(var(--pulse-ring-rgb) / 0.18);
}

/* Fades while the pill is hovered or expanded so it doesn't crowd the label,
   and fades back in on leave. */
.link-hotspot.is-featured:hover .link-hotspot__pulse,
.link-hotspot.is-featured.is-expanded .link-hotspot__pulse {
  opacity: 0;
}

/* ── "Start here" callout ────────────────────────────────────────────
   A small badge anchored above a featured hotspot, pointing new visitors to
   it before they've had a chance to explore. Dismissed permanently once the
   hotspot is opened once (see hotspots.js, localStorage flag) — there is no
   separate close control. Independent of hover/expand state — visible even while the
   pill is collapsed, since its whole job is to be noticed before the first
   interaction. */
.hotspot-starthere {
  position: absolute;
  /* The wrapper itself has zero height (every child is absolutely
     positioned, so nothing contributes to normal flow) — its own "100%" is
     therefore always 0, not the marker's height. Anchoring off `100%` like
     the scene-dot tooltip does (see .scene-dot__tip in scene-nav.css) would
     put this only 14px above the wrapper's anchor POINT, which is the
     marker's vertical CENTRE — 2px inside the circle, not above it. Adding
     half the marker's diameter first gets us to the marker's actual top
     edge; the +14px on top of that is the same gap scene-dot__tip uses. */
  bottom: calc(var(--hotspot-size) / 2 + 14px);
  /* Centred on the wrapper's own anchor point (x = 0, the exact pano point
     Marzipano positions this hotspot at — same point the marker circle is
     centred on). `left: 0` puts the badge's LEFT EDGE there; `translateX(-50%)`
     then shifts it left by half of *its own* rendered width, landing its
     centre — and so the arrow below, which is centred on the badge — exactly
     over the marker regardless of how wide the label happens to render.
     (The previous `translateX(-half of --hotspot-size)`
     only centred correctly if the badge were exactly as wide as the marker,
     which it never is — hence the arrow pointing at empty space.) */
  left: 0;
  transform: translate(-50%, 0);
  /* Padding, radius and type all match .scene-dot__tip (scene-nav.css) — the
     bottom-nav's own hover tooltip — so this callout reads as the same
     "label" style used elsewhere in the app, not a one-off. The radius in
     particular is a soft 7px rect, NOT a 999px pill: the two sit on screen
     at the same time and any difference in corner rounding reads as two
     unrelated components. Keep these in sync with .scene-dot__tip. */
  padding: 6px 11px;
  border-radius: 7px;
  background: var(--hotspot-pill-bg);
  color: #fff;
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.01em;
  white-space: nowrap;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
  z-index: 2;
}
.hotspot-starthere::after {
  /* Little arrow pointing down at the hotspot. A CSS border can't take a
     gradient, so this is the flat colour at the 100% stop of the badge's
     own --hotspot-pill-bg (the brand gradient) — keep the two in step or the
     arrow stops looking like part of the badge. */
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-top-color: var(--color-blue);
}
/* Fade out the whole callout once dismissed, rather than snapping away. */
.hotspot-starthere.is-dismissing {
  transition: opacity 0.25s ease, transform 0.25s ease;
  opacity: 0;
  transform: translate(-50%, -8px);
}

/* Optional media-count badge, pinned to the circle */
.link-hotspot__badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 700;
  color: #fff;
  background: var(--hotspot-pill-bg);
  border-radius: 8px;
}
