/* Vessel maps (vessel-map.js) on the portal, the staff dashboard and the public tracker. */

.vessel-map {
  position: relative;
  /* Leaflet stacks its panes up to z-index 1000; keep that inside the map so drawers,
     menus and modals still cover it. */
  isolation: isolate;
  width: 100%;
  height: 260px;
  background: #d9dcdf;
  border: 1px solid var(--line, #deddd9);
  overflow: hidden;
  font: 11px var(--body, sans-serif);
}

/* Muted tiles so the red ships carry the eye, with just enough blue to tell sea from
   land. Filtered per tile: a filter on the whole tile pane leaves hairline seams. */
.vessel-map .leaflet-tile { filter: saturate(.3) contrast(.95) brightness(1.03); }
.dark .vessel-map { background: #1d1e20; border-color: #3a3a3b; }
.dark .vessel-map .leaflet-tile { filter: invert(1) hue-rotate(180deg) saturate(.35) brightness(.82) contrast(.9); }

.vessel-map .leaflet-control-attribution {
  font: 9px var(--mono, monospace);
  background: rgba(255, 255, 255, .78);
  color: #555;
}
.dark .vessel-map .leaflet-control-attribution { background: rgba(20, 20, 22, .78); color: #aaa; }
.dark .vessel-map .leaflet-control-attribution a { color: #ddd; }

.vessel-map .leaflet-bar a {
  width: 30px;
  height: 30px;
  line-height: 30px;
  border-radius: 0;
  color: #141416;
}
.dark .vessel-map .leaflet-bar a { background: #202021; color: #f4f3f1; border-color: #3a3a3b; }

/* Ships */
.ship-marker { position: relative; background: none; border: 0; }
.ship-marker svg {
  position: absolute;
  inset: 3px;
  width: 22px;
  height: 22px;
  fill: #e30613;
  stroke: #fff;
  stroke-width: 1.6;
  stroke-linejoin: round;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .35));
}
.ship-marker.stale svg { fill: #8a8a88; }
.ship-marker.selected svg { inset: 0; width: 28px; height: 28px; }

.ship-ping {
  position: absolute;
  inset: 4px;
  border-radius: 50%;
  background: rgba(227, 6, 19, .35);
  animation: ship-ping 2.2s ease-out infinite;
}
.ship-marker.stale .ship-ping { display: none; }

@keyframes ship-ping {
  0% { transform: scale(.6); opacity: .9; }
  100% { transform: scale(2.4); opacity: 0; }
}

/* The route travelled, from the stored trail of AIS fixes. */
.vessel-trail { stroke: #e30613; stroke-width: 2; stroke-dasharray: 4 6; fill: none; opacity: .85; }
/* The planned sea route from the shipping line: quieter than the ship's own trail. */
.vessel-route { stroke: #4f5b66; stroke-width: 2; fill: none; opacity: .6; }
.dark .vessel-route,
.network-vessel-map .vessel-route { stroke: #d4dbe1; opacity: .5; }

.route-port { background: none; border: 0; }
.route-port span {
  position: absolute;
  inset: 2px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid #4f5b66;
}
.route-port.destination span { border-color: #e30613; }
.route-port.transshipment span { inset: 3px; border-width: 1.5px; }
.route-port b {
  position: absolute;
  left: 16px;
  top: -2px;
  white-space: nowrap;
  font: 500 9px var(--mono, monospace);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: #141416;
  text-shadow: 0 0 3px rgba(255, 255, 255, .9);
  pointer-events: none;
}
.dark .route-port span { background: #1d1e20; border-color: #d4dbe1; }
.dark .route-port.destination span { border-color: #ff4a55; }
.dark .route-port b { color: #f4f3f1; text-shadow: 0 0 3px rgba(0, 0, 0, .9); }

.vessel-tooltip {
  border: 0;
  border-radius: 0;
  background: #141416;
  color: #fff;
  font: 11px/1.45 var(--body, sans-serif);
  box-shadow: 0 8px 22px rgba(0, 0, 0, .25);
}
.vessel-tooltip::before { border-top-color: #141416; }
.vessel-tooltip small { font: 9px var(--mono, monospace); letter-spacing: .04em; color: #bbb; }

/* Where each page places its map. */
.track-vessel-map { height: 220px; margin-top: 4px; }

/* Homepage network map: fills the dark panel, with the live label above it. */
.network-vessel-map { position: absolute; inset: 0; z-index: 1; height: 100%; border: 0; background: #0e0f10; }
.network-vessel-map .leaflet-tile { filter: invert(1) hue-rotate(180deg) saturate(.35) brightness(.72) contrast(.9); }
.network-vessel-map .leaflet-control-attribution { background: rgba(14, 15, 16, .8); color: #999; }
.network-vessel-map .leaflet-control-attribution a { color: #ccc; }
.map-panel .map-ui { justify-content: flex-end; pointer-events: none; }

/* "14.2 kn · heading 112° · seen 6 min ago" under a map. */
.updates-line { margin: 10px 0 0; font: 8px/1.6 var(--mono, monospace); letter-spacing: .06em; text-transform: uppercase; color: #777; }
.updates-line::before { content: "● "; color: #259954; }
.timeline + .updates-line { margin: -14px 0 20px; }
.vessel-line.route-line { margin-top: 2px; }
.dark .updates-line { color: #aaa; }
.vessel-line { margin: 8px 0 0; font: 9px var(--mono, monospace); letter-spacing: .05em; color: #777; }
.vessel-line b { color: #e30613; font-weight: 500; }
.vessel-line.stale b { color: #8a8a88; }
.dark .vessel-line { color: #aaa; }

/* Ports */
/* Twenty ports share this map, so the ordinary ones are quiet: a small dot and
   a dimmed label that reads as context rather than as twenty announcements.
   Port Louis is the exception -- see .port-home below. */
.port-marker { background: none; border: 0; }
.port-marker span {
  position: absolute;
  inset: 2.5px;
  border-radius: 50%;
  background: #e8e8e6;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, .22);
}
.port-marker b {
  position: absolute;
  left: 13px;
  top: -2px;
  white-space: nowrap;
  font: 500 8px var(--mono, monospace);
  letter-spacing: .09em;
  text-transform: uppercase;
  color: #141416;
  opacity: .72;
  text-shadow: 0 0 3px rgba(255, 255, 255, .9);
}

/* Where the company is. The only red on the map that is not a ship. */
.port-marker.port-home span {
  inset: 1px;
  background: #fff;
  box-shadow: 0 0 0 3px rgba(227, 6, 19, .55);
}
.port-marker.port-home b {
  left: 16px;
  top: -3px;
  font-size: 9px;
  opacity: 1;
}

.dark .port-marker b,
.network-vessel-map .port-marker b { color: #f4f3f1; text-shadow: 0 0 3px rgba(0, 0, 0, .9); }

/* Live map / Live tracking screens: the map beside the list of ocean shipments. */
.tracking-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(280px, 1fr);
  gap: 18px;
  align-items: start;
}
.tracking-layout .panel { margin-bottom: 0; }
.tracking-layout + .view-hint { margin-top: 14px; }
.tracking-map-panel { padding: 0; overflow: hidden; }
.tracking-map { height: 560px; border: 0; }

.tracking-list { list-style: none; margin: 0; padding: 0; max-height: 500px; overflow-y: auto; }
.tracking-list > .empty-note { padding: 22px 21px; }
.tracking-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
  padding: 13px 21px;
  border-bottom: 1px solid #e8e7e4;
  cursor: pointer;
  transition: background .15s ease;
}
.tracking-row:last-child { border-bottom: 0; }
.tracking-row:hover,
.tracking-row.active { background: #f6f5f2; }
.tracking-row.active { box-shadow: inset 3px 0 0 var(--red, #e30613); }
.tracking-row b { display: block; font: 500 11px var(--mono, monospace); }
.tracking-row span { display: block; margin-top: 3px; font: 600 12px var(--body, sans-serif); overflow-wrap: anywhere; }
.tracking-row small { display: block; margin-top: 3px; font: 9px var(--mono, monospace); color: #888; }
.tracking-side { display: grid; justify-items: end; gap: 6px; }

.track-state { font: normal 8px var(--mono, monospace); letter-spacing: .07em; white-space: nowrap; }
.track-state.live { color: #e30613; }
.track-state.stale { color: #8a8a88; }
.track-state.waiting { color: #b67300; }
.track-state.missing { color: #3975cb; }

.feed-status { margin: -6px 0 16px; font: 9px/1.6 var(--mono, monospace); letter-spacing: .04em; color: #777; }
.feed-status::before { content: "● "; }
.feed-status.on::before { color: #259954; }
.feed-status.idle::before { color: #b67300; }
.feed-status.off::before,
.feed-status.error::before { color: #e30613; }

.dark .tracking-row { border-color: #3a3a3b; }
.dark .tracking-row:hover,
.dark .tracking-row.active { background: #29292a; }
.dark .tracking-row small,
.dark .feed-status { color: #aaa; }

@media (max-width: 1030px) {
  .tracking-layout { grid-template-columns: 1fr; }
  .tracking-map { height: 420px; }
  .tracking-list { max-height: none; }
}

@media (max-width: 720px) {
  .tracking-map { height: 340px; }
  .tracking-row { padding: 13px 16px; }
  .track-state { font-size: 9px; }
}

@media (prefers-reduced-motion: reduce) {
  .ship-ping { animation: none; display: none; }
}

/* --- How tall the network map stands ----------------------------------------
   It keeps the section's own gutters: edge to edge was too wide, and a map that
   runs under the browser chrome stops reading as part of the page. What it
   gains is height, so the world fits without the letterbox crop of the old
   540px.

   Declared after styles.css sets that 540px, and its breakpoints are repeated
   here -- otherwise one unconditional rule would also flatten the shorter
   heights that file sets for phones. */

.map-panel { height: min(58vh, 560px); }

@media (max-width: 800px) {
  .map-panel { height: min(64vh, 520px); }
}

@media (max-width: 460px) {
  .map-panel { height: min(58vh, 430px); }
}

/* A port name with no room for it. The dot stays -- that is the port -- and the
   name comes back as soon as zooming in gives the cluster space. Kept in the
   layout rather than display:none so measuring it next time costs nothing. */
/* Set by spaceLabels() in vessel-map.js once the names have been measured on
   screen: which side of its dot each name sits on, and which name had nowhere
   to go. The offsets here have to match labelBox() in that file. */
.port-marker b.label-left { left: auto; right: 13px; top: -2px; }
.port-marker b.label-above { left: 5px; right: auto; top: -4px; transform: translate(-50%, -100%); }
.port-marker b.label-below { left: 5px; right: auto; top: 14px; transform: translateX(-50%); }
.port-marker b.label-ne { left: 11px; right: auto; top: -4px; transform: translateY(-100%); }
.port-marker b.label-se { left: 11px; right: auto; top: 12px; }
.port-marker b.label-nw { left: auto; right: 11px; top: -4px; transform: translateY(-100%); }
.port-marker b.label-sw { left: auto; right: 11px; top: 12px; }
.port-marker b.label-crowded { visibility: hidden; }
