/* ===========================================================================
   LEAD48 - relay-map.css

   The animated world relay. Pairs with relay-map.js and the two build-time
   assets in /assets/relay/ (world-relay.json, relay-map-layout.css).

   No inline styles anywhere: the site CSP is style-src 'self' with no
   unsafe-inline, which blocks both <style> blocks and style attributes. The
   eight card positions come from the generated relay-map-layout.css; every
   other value lives here.
   =========================================================================== */

.relay-map {
  --relay-gold: #f0c04a;
  --relay-land: #173a5a;
  --relay-land-edge: #22527c;
  --relay-deep: #061424;

  position: relative;
  margin: 0;
  border: 1px solid rgba(240, 192, 74, 0.16);
  background:
    radial-gradient(circle at 50% 42%, rgba(35, 84, 128, 0.42) 0, transparent 62%),
    var(--relay-deep);
  overflow: hidden;
}

.relay-map-svg {
  display: block;
  width: 100%;
  height: auto;
}


/* --- The world ----------------------------------------------------------- */

.relay-land {
  fill: var(--relay-land);
  stroke: var(--relay-land-edge);
  stroke-width: 0.5;
  stroke-linejoin: round;
}


/* --- Route and trail ------------------------------------------------------
   Two copies of the same path. The base is the dim full route; the trail is
   the lit gold section the baton has already covered, revealed by animating
   stroke-dashoffset from script. */

.relay-route {
  fill: none;
  stroke: rgba(240, 192, 74, 0.2);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-dasharray: 5 7;
}

.relay-trail {
  fill: none;
  stroke: var(--relay-gold);
  stroke-width: 2.4;
  stroke-linecap: round;
  filter: drop-shadow(0 0 5px rgba(240, 192, 74, 0.65));
}


/* --- Region markers ------------------------------------------------------- */

.relay-marker-ring {
  fill: none;
  stroke: rgba(240, 192, 74, 0.4);
  stroke-width: 1.2;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
}

.relay-marker-dot {
  fill: #0d2c48;
  stroke: rgba(240, 192, 74, 0.5);
  stroke-width: 1.4;
}

.relay-marker.is-lit .relay-marker-dot {
  fill: var(--relay-gold);
  stroke: var(--relay-gold);
  filter: drop-shadow(0 0 6px rgba(240, 192, 74, 0.8));
}

.relay-marker.is-lit .relay-marker-ring {
  opacity: 1;
  animation: relay-ping 1.6s ease-out;
}

@keyframes relay-ping {
  from { transform: scale(0.5); opacity: 0.9; }
  to   { transform: scale(2.4); opacity: 0; }
}


/* --- The baton ------------------------------------------------------------ */

.relay-baton {
  fill: #fff6df;
  stroke: var(--relay-gold);
  stroke-width: 2;
  filter: drop-shadow(0 0 8px rgba(240, 192, 74, 0.95));
  opacity: 0;
}

.relay-map.is-running .relay-baton {
  opacity: 1;
}


/* --- Region cards ---------------------------------------------------------
   Positioned by assets/relay/relay-map-layout.css, which the build script
   generates from the projected coordinates.

   Cards are VISIBLE by default and only hidden once script takes over (the
   .is-animated class). If the JSON never loads or JS fails, the eight cards
   still render over the map rather than vanishing. */

.relay-stop {
  position: absolute;
  z-index: 2;
  display: grid;
  grid-template-columns: 26px 1fr;
  gap: 1px 9px;
  width: 168px;
  padding: 8px 11px;
  transform: translate(-50%, -50%);
  border: 1px solid rgba(240, 192, 74, 0.28);
  background: rgba(6, 20, 36, 0.9);
  color: #fff;
  text-align: left;
  cursor: pointer;
}

.relay-stop b {
  grid-row: 1 / 3;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: rgba(240, 192, 74, 0.16);
  color: var(--relay-gold);
  font: 800 0.72rem/1 ui-monospace, SFMono-Regular, Consolas, monospace;
}

.relay-stop span {
  font: 800 0.7rem/1.2 ui-monospace, SFMono-Regular, Consolas, monospace;
  letter-spacing: 0.04em;
}

.relay-stop small {
  color: #a8c0d6;
  font: 700 0.6rem/1.3 ui-monospace, SFMono-Regular, Consolas, monospace;
}

.relay-stop:hover,
.relay-stop:focus-visible {
  border-color: var(--relay-gold);
  outline: 2px solid var(--relay-gold);
  outline-offset: 2px;
}

.relay-stop[aria-pressed="true"] {
  border-color: var(--relay-gold);
  background: rgba(18, 61, 98, 0.95);
  box-shadow: inset 3px 0 var(--relay-gold);
}

/* Script has taken over: cards start hidden and are revealed as the baton
   arrives. Each reveal STAYS until the whole loop restarts. */
.relay-map.is-animated .relay-stop {
  opacity: 0;
  transform: translate(-50%, calc(-50% + 12px));
  transition: opacity 0.5s ease, transform 0.5s ease;
}

.relay-map.is-animated .relay-stop.is-revealed {
  opacity: 1;
  transform: translate(-50%, -50%);
}

/* End of a loop: everything fades together before the next pass. */
.relay-map.is-clearing .relay-stop.is-revealed {
  opacity: 0;
}


/* --- Legend --------------------------------------------------------------- */

.relay-map-legend {
  position: absolute;
  z-index: 2;
  left: 14px;
  bottom: 12px;
  margin: 0;
  color: #93aec6;
  font: 700 0.6rem/1.4 ui-monospace, SFMono-Regular, Consolas, monospace;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}


/* --- Narrow widths --------------------------------------------------------
   The eight cards cannot sit on a phone-width map without covering each other.
   Below 860px the map keeps its markers, trail and baton, and the numbered
   .region-stop-list underneath carries the names and hours - it is already in
   the markup and lists all eight. */

@media (max-width: 860px) {
  .relay-stop {
    width: auto;
    padding: 5px 7px;
    grid-template-columns: 22px;
    gap: 0;
  }

  .relay-stop span,
  .relay-stop small {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .relay-stop b {
    width: 22px;
    height: 22px;
    font-size: 0.66rem;
  }

  .relay-map-legend {
    left: 10px;
    bottom: 8px;
    font-size: 0.54rem;
  }
}

/* audience.css only reveals .region-stop-list at <=720px, but the cards above
   drop their labels at <=860px. Without this, 721-860px shows neither the
   names nor the list - just numbered dots. Scoped to that band exactly so the
   existing <=720px rules keep full control below it. */

@media (min-width: 721px) and (max-width: 860px) {
  .region-stop-list {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    margin-top: 10px;
    border-top: 1px solid rgba(255, 255, 255, 0.12);
    border-left: 1px solid rgba(255, 255, 255, 0.12);
  }
}


/* --- Reduced motion -------------------------------------------------------
   No baton, no sweep, no loop: the final state, fully revealed, straight away.
   relay-map.js checks the same query and never starts its timer. */

@media (prefers-reduced-motion: reduce) {
  .relay-map.is-animated .relay-stop,
  .relay-map.is-clearing .relay-stop.is-revealed {
    opacity: 1;
    transform: translate(-50%, -50%);
    transition: none;
  }

  .relay-marker.is-lit .relay-marker-ring {
    animation: none;
    opacity: 0;
  }

  .relay-map.is-running .relay-baton {
    opacity: 0;
  }
}


/* If the JSON never loads, relay-map.js leaves the host untouched. Collapse it
   rather than showing an empty bordered box - the numbered .region-stop-list
   underneath already carries all eight regions with their names and hours. */
.relay-map:empty {
  display: none;
}

/* Contrast: inside a dark panel the accent takes its lighter variant.
   A dark panel is a rule that sets both a dark background and light text;
   anything less is a card or a border, and its accent stays as it is. */
/* --- Region cards ---------------------------------------------------------
   Positioned by assets/relay/relay-map-layout.css,
which the build script
   generates from the projected coordinates.

   Cards are VISIBLE by default and only hidden once script takes over (the
   .is-animated class). If the JSON never loads or JS fails,
the eight cards
   still render over the map rather than vanishing. */

.relay-stop{--accent-text:var(--copper-on-dark,#d4834a)}
