/**
 * @file
 * Styling for the interactive Leaflet map block.
 */

.cw-map-wrapper {
  width: 100%;
}

.cw-map {
  width: 100%;
  height: clamp(360px, 65vh, 700px);
  /* Ocean. The land GeoJSON layer is drawn on top of it in white. */
  background-color: #c9e2f0;
  /* Leaflet gives its panes z-index 400-800 and its controls 1000. The
     container is only position: relative, which is not a stacking context, so
     those values compete with the rest of the page and paint the map over
     overlays such as the Layout Builder dialog (jQuery UI sets its z-index
     inline, 100 by default). Making the container its own stacking context
     keeps Leaflet's layering inside the map, where it belongs. */
  position: relative;
  z-index: 0;
}

/* Source credit and projection caveat, directly under the map. */
.cw-map__note {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.4;
  color: #666;
  text-align: center;
}

/* The Commonwealth layer imitates the printed map, which has a white ocean.
   The ocean is the container's own background, so it changes with the layer. */
.cw-map.cw-map--filled,
.cw-map.cw-map--filled.leaflet-container {
  background-color: #ffffff;
}

.cw-map.leaflet-container {
  background-color: #c9e2f0;
  font: inherit;
}

/* ---- Markers ---------------------------------------------------------- */
.cw-map__marker {
  display: block;
  width: 12px;
  height: 12px;
  box-sizing: border-box;
  border: 2px solid #ffffff;
  border-radius: 50%;
  /* Halo keeps markers legible over the filled Commonwealth layer. */
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);
  transition: transform 0.1s ease-out;
}

/* One colour per map, so two maps on a page never read as one dataset. */
.cw-map__marker--countries {
  background: #e6007e;
}

/* Meridian markers carry no region colour, so they need their own. */
.cw-map__marker--meridian {
  background: #00839a;
}

/* One colour per Commonwealth region, matching the legend swatches. Keyed by a
   slug of the region term's label, so a renamed or new region falls back to the
   map's own colour above rather than disappearing. */
.cw-map__marker--region-africa {
  background: #e6007e;
}

.cw-map__marker--region-asia {
  background: #f39200;
}

.cw-map__marker--region-caribbean-and-americas {
  background: #00839a;
}

.cw-map__marker--region-europe {
  background: #6a3d9a;
}

.cw-map__marker--region-pacific {
  background: #69b42e;
}

/* A colour set on the facet's own term beats every fallback above: two classes,
   so it outranks the single-class region and per-map rules. The value arrives on
   the element as a custom property, which keeps what it paints in here. */
.cw-map__marker.cw-map__marker--has-colour {
  background: var(--cw-map-marker-colour);
}

/* A term can replace the default dot with a Font Awesome icon, which is the
   other visual axis a map can group by: region stays the colour, member status
   changes the glyph. The icon comes from the term's field_marker_icon, and
   without one every marker stays the disc above. Two classes, so undoing the
   disc outranks the single-class per-region and per-map fills, and it sits
   after the equally specific --has-colour rule so it undoes that fill too. */
.cw-map__marker.cw-map__marker--icon {
  display: flex;
  align-items: center;
  justify-content: center;
  /* The 16px of Leaflet's divIcon rather than the disc's 12px, so the glyph is
     centred on the coordinate it marks and has room to be read. */
  width: 16px;
  height: 16px;
  border: 0;
  border-radius: 0;
  background: none;
  /* The disc's halo followed its box; a glyph needs one that follows its own
     outline, which is what a drop-shadow filter does. White first, so the
     icon keeps the edge that holds it apart from a dark fill underneath. */
  box-shadow: none;
  filter:
    drop-shadow(0 0 1.5px #ffffff)
    drop-shadow(0 0 1px #ffffff)
    drop-shadow(0 0 1px rgba(0, 0, 0, 0.45));
  font-size: 14px;
  line-height: 1;
  /* Colour is the facet the term may not set; an icon still has to be visible,
     so it falls back to the map's own ink rather than to a region fill. */
  color: #1b2a4a;
}

.cw-map__marker.cw-map__marker--icon.cw-map__marker--has-colour {
  color: var(--cw-map-marker-colour);
}

.cw-map__marker--chogm {
  background: #1b2a4a;
}

/* Maps drawn from a CSV file colour each pin from its own row; this is the
   fill of a row that names no colour. */
.cw-map__marker--custom {
  background: #1b2a4a;
}

/* A Pro "light" or "thin" pin. The self-hosted free Font Awesome has neither
   weight, so the solid glyph is drawn as an outline instead: a white body
   ringed in the pin's colour, which keeps the light/solid distinction a CSV
   uses (completed vs active) without a font the site does not have. Fill and
   stroke are the -webkit- properties every current browser supports; colour
   stays in `color`, so the --has-colour rule above still decides it. */
.cw-map__marker--outline > i {
  -webkit-text-fill-color: #ffffff;
  -webkit-text-stroke: 1.25px currentColor;
}

.leaflet-marker-icon:hover .cw-map__marker,
.leaflet-marker-icon:focus .cw-map__marker {
  transform: scale(1.35);
}

/* ---- Clusters (blocks with "Group nearby pins") ------------------------ */

/* Fills the divIcon box, whose size the JavaScript sets by pin count. */
.cw-map__cluster {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  border: 2px solid #ffffff;
  border-radius: 50%;
  /* The map's ink, for a cluster whose pins do not share one colour. */
  background: #1b2a4a;
  color: #ffffff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25), 0 1px 4px rgba(0, 0, 0, 0.3);
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  transition: transform 0.1s ease-out;
}

.cw-map__cluster.cw-map__cluster--has-colour {
  background: var(--cw-map-marker-colour);
}

/* White on yellow or orange is unreadable; see isLightColour(). */
.cw-map__cluster.cw-map__cluster--light {
  color: #1b2a4a;
}

.leaflet-marker-icon:hover .cw-map__cluster,
.leaflet-marker-icon:focus .cw-map__cluster {
  transform: scale(1.1);
}

/* ---- Popup ------------------------------------------------------------ */
.cw-map__popup-head {
  display: flex;
  gap: 10px;
  align-items: flex-start;
}

.cw-map__flag {
  flex: 0 0 auto;
  width: 52px;
  height: auto;
  display: block;
  border: 1px solid #e2e2e2;
  border-radius: 2px;
}

.cw-map__popup-headings {
  min-width: 0;
}

.cw-map__popup-title {
  margin: 0;
  font-size: 16px;
  line-height: 1.2;
}

.cw-map__popup-title a {
  color: #1b2a4a;
  text-decoration: none;
}

.cw-map__popup-title a:hover {
  text-decoration: underline;
}

.cw-map__popup-meta {
  margin: 3px 0 0;
  font-size: 12px;
  color: #666;
}

.cw-map__popup-intro {
  margin: 8px 0 0;
  font-size: 13px;
  line-height: 1.4;
  color: #333;
}

/* Sits at the end of the truncated intro, so it must not be pulled onto a line
   of its own by a line break inside the link text. */
.cw-map__popup-more {
  white-space: nowrap;
  font-weight: 600;
  color: #1b2a4a;
}

/* ---- Popup: CSV map variant ------------------------------------------- */

/* HTML from the CSV's "Display info" column, already filtered server-side. */
.cw-map__popup-info {
  margin-top: 8px;
  font-size: 13px;
  line-height: 1.4;
  color: #333;
}

/* Two classes, to outrank Leaflet's `.leaflet-popup-content p` margin of
   1.3em, which would otherwise space the paragraphs of a short bio far apart. */
.cw-map__popup .cw-map__popup-info > * {
  margin: 6px 0 0;
}

.cw-map__popup .cw-map__popup-info > :first-child {
  margin-top: 0;
}

.cw-map__popup-info ul,
.cw-map__popup-info ol {
  padding-left: 18px;
}

/* The row's own button and the country page link, side by side when they fit.
   Two classes for the same reason as the info paragraphs above. */
.cw-map__popup .cw-map__popup-links {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin: 10px 0 0;
}

.cw-map__popup-links .cw-map__popup-link {
  margin-top: 0;
}

/* ---- Popup: related content mini slider -------------------------------- */
.cw-map__slider {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid #e2e2e2;
}

.cw-map__slider-loading {
  font-size: 12px;
  color: #777;
}

.cw-map__slider-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}

.cw-map__slider-label {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #888;
}

.cw-map__slider-nav {
  display: flex;
  align-items: center;
  gap: 4px;
}

.cw-map__slider-btn {
  width: 20px;
  height: 20px;
  padding: 0;
  border: 1px solid #d5d5d5;
  border-radius: 50%;
  background: #ffffff;
  color: #1b2a4a;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
}

.cw-map__slider-btn:disabled {
  opacity: 0.35;
  cursor: default;
}

.cw-map__slider-count {
  font-size: 11px;
  color: #777;
  font-variant-numeric: tabular-nums;
}

.cw-map__slider-viewport {
  overflow: hidden;
}

.cw-map__slider-track {
  display: flex;
  transition: transform 0.25s ease-out;
}

/* One slide per viewport width. A column, because the slide holds the item's
   own link and, under it, the way on to the listing of that item's kind. Track
   children stretch to the tallest slide, so a slide without a listing link does
   not make the popup resize as the reader swipes. */
.cw-map__popup .cw-map__slide {
  flex: 0 0 100%;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.cw-map__popup .cw-map__slide-link,
.cw-map__popup .cw-map__slide-link:hover {
  display: flex;
  gap: 8px;
  align-items: center;
  color: inherit;
  /* The site theme underlines links; the slide underlines its title only. */
  text-decoration: none;
  border-bottom: 0;
}

.cw-map__popup .cw-map__slide-more,
.cw-map__popup .cw-map__slide-more:hover {
  /* Indented to the title, past the thumbnail, so it reads as part of the card
     rather than as a caption under the image. */
  margin-left: 83px;
  font-size: 12px;
  font-weight: 600;
  color: #1b2a4a;
  border-bottom: 0;
}

.cw-map__slide-img {
  flex: 0 0 auto;
  /* 3:2, like the popup image. */
  width: 75px;
  height: 50px;
  object-fit: cover;
  border-radius: 3px;
  display: block;
}

.cw-map__slide-img--empty {
  background: #eef2f5;
}

.cw-map__slide-body {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* "Type | date" on a single inline line above the title. */
.cw-map__slide-meta {
  display: flex;
  align-items: baseline;
  font-size: 10px;
}

.cw-map__slide-type {
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #888;
}

.cw-map__slide-date {
  color: #777;
}

.cw-map__slide-date::before {
  content: "|";
  margin: 0 6px;
  color: #ccc;
}

.cw-map__popup .cw-map__slide-title {
  margin-top: 2px;
  text-decoration: none;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.25;
  color: #1b2a4a;
  /* Keep slide heights even when titles run long. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.cw-map__popup .cw-map__slide-link:hover .cw-map__slide-title {
  text-decoration: underline;
}

/* ---- Popup: CHOGM variant --------------------------------------------- */
.cw-map__popup-year {
  margin: 0;
  font-size: 20px;
  font-weight: 700;
  line-height: 1;
  color: #1b2a4a;
  font-variant-numeric: tabular-nums;
}

.cw-map__popup--chogm .cw-map__popup-title {
  margin-top: 2px;
  font-size: 14px;
  font-weight: 600;
  /* Not a link — the theme colours headings like one, so state it plainly. */
  color: #1b2a4a;
}

.cw-map__popup-image {
  display: block;
  width: 100%;
  margin-top: 8px;
  border-radius: 3px;
  /* 3:2 whatever the file's own shape, cropped to fill. A ratio rather than a
     height still reserves the space before the file arrives, so the CHOGM
     height animation measures the final layout; the popup's maxHeight is what
     keeps a tall popup inside the map. */
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

.cw-map__popup-image--empty {
  background: #eef2f5;
}

.cw-map__popup-link {
  display: inline-block;
  margin-top: 10px;
  font-size: 13px;
  font-weight: 600;
  color: #1b2a4a;
}

.cw-map__popup-link::after {
  content: " \2192";
}

/* ---- Popup: CHOGM year switcher --------------------------------------- */
.cw-map__popup-years {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.cw-map__popup-year-btn {
  padding: 2px 8px;
  border: 1px solid #d5d5d5;
  border-radius: 999px;
  background: #ffffff;
  color: #1b2a4a;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.4;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}

.cw-map__popup-year-btn.is-selected {
  border-color: #1b2a4a;
  background: #1b2a4a;
  color: #ffffff;
  cursor: default;
}

/* Empty until a flag loads, so it must not reserve space of its own. */
.cw-map__flag-slot:empty {
  display: none;
}

/* The year switcher eases between meeting heights; see switchChogmMeeting(). */
.cw-map__popup-meeting {
  overflow: hidden;
  transition: height 0.28s ease, opacity 0.22s ease;
}

@media (prefers-reduced-motion: reduce) {
  .cw-map__popup-meeting {
    transition: none;
  }
}

/* ---- Legend / category filter ----------------------------------------- */
.cw-map__legend {
  max-width: 240px;
  /* Two facets stack up; on a short map the legend scrolls rather than
     outgrowing the map it belongs to. */
  max-height: calc(100% - 24px);
  overflow-y: auto;
  padding: 8px 10px;
  border-radius: 4px;
  background: #ffffff;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.25);
  font-size: 13px;
  line-height: 1.3;
}

.cw-map__legend-section + .cw-map__legend-section {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid #e2e2e2;
}

.cw-map__legend-title {
  margin: 0 0 4px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #888;
}

.cw-map__legend-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 3px 2px;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.cw-map__legend-item .cw-map__marker {
  flex: 0 0 12px;
}

/* An icon swatch matches the marker's 16px box, so glyph and dot swatches line
   their labels up the same way. */
.cw-map__legend-item .cw-map__marker--icon {
  flex: 0 0 16px;
}

/* Colour belongs to the region facet. A status swatch that has no colour of its
   own shows only its glyph, so it stays neutral — otherwise it would read as
   "non-members are pink". */
.cw-map__legend-item .cw-map__legend-swatch--status:not(.cw-map__marker--has-colour) {
  background: #9aa4b2;
}

/* An icon swatch carries that same neutral as ink rather than as a fill: this
   selector outranks both the rule above and the icon marker's own background,
   so it has to restore the one and recolour the other. */
.cw-map__legend-item
  .cw-map__legend-swatch--status.cw-map__marker--icon:not(.cw-map__marker--has-colour) {
  background: none;
  color: #9aa4b2;
}

/* A CSV map colours its swatches only where every pin under one agrees — see
   ComsecMapDataController::legendStyle() — and the rest stay neutral, as
   status swatches do. */
.cw-map__legend-item .cw-map__marker--custom:not(.cw-map__marker--has-colour) {
  background: #9aa4b2;
}

.cw-map__legend-item
  .cw-map__marker--custom.cw-map__marker--icon:not(.cw-map__marker--has-colour) {
  background: none;
  color: #9aa4b2;
}

.cw-map__legend-label {
  flex: 1 1 auto;
}

.cw-map__legend-count {
  flex: 0 0 auto;
  color: #666;
  font-variant-numeric: tabular-nums;
}

/* Switched off: dimmed rather than hidden, so it still reads as a filter. */
.cw-map__legend-item.is-off {
  opacity: 0.4;
}

.cw-map__legend-item:hover .cw-map__legend-label {
  text-decoration: underline;
}
