/* Lagebild three-column layout — left rail (320px) / center map (1fr) / right rail (340px).
   Side rails contain stacked panels; the center column hosts the map and its HUD overlays. */

.ms-lagebild {
    flex: 1;
    display: grid;
    grid-template-columns: 320px 1fr 340px;
    min-height: 0;
    gap: 0;
    background: var(--ms-bg);
}

.ms-lagebild-col {
    display: flex;
    flex-direction: column;
    min-height: 0;
    min-width: 0;
}
.ms-lagebild-col.left,
.ms-lagebild-col.right { gap: 0; }
.ms-lagebild-col.center {
    position: relative;
    overflow: hidden;
}

/* The map container fills the center column. ms-mapview is the canonical
   wrapper — pages use it for any tactical-map embedding. */
.ms-mapview {
    position: absolute;
    inset: 0;
    background: var(--ms-water);
    border-inline-start: 1px solid var(--ms-panel-border);
    border-inline-end: 1px solid var(--ms-panel-border);
}

/* ---- Hover tooltip (Phase #106-A) ---- */
.ms-map-tooltip {
    position: absolute;
    transform: translate(-50%, calc(-100% - 14px));
    background: var(--ms-panel);
    color: var(--ms-text);
    border: 1px solid var(--ms-panel-border);
    padding: 6px 10px;
    min-width: 140px;
    max-width: 240px;
    font-family: var(--ms-font-ui);
    font-size: 11px;
    line-height: 1.35;
    pointer-events: none;
    z-index: 4;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
    opacity: 0;
    visibility: hidden;
    transition: opacity 90ms ease-out;
}
.ms-map-tooltip.visible { opacity: 1; visibility: visible; }
.ms-map-tooltip-name {
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ms-map-tooltip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    margin-top: 4px;
}
.ms-map-tooltip-mono {
    font-family: var(--ms-font-mono);
    font-size: 10px;
    color: var(--ms-text-dim);
}
.ms-map-tooltip-age { color: var(--ms-text-mute); }
.ms-map-tooltip-chip {
    display: inline-block;
    padding: 1px 6px;
    font-family: var(--ms-font-mono);
    font-size: 9px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    border: 1px solid currentColor;
    border-radius: 2px;
}
.ms-map-tooltip-chip.ok      { color: var(--ms-ok); }
.ms-map-tooltip-chip.unknown { color: var(--ms-unknown); }
.ms-map-tooltip-chip.alert   { color: var(--ms-alert); }
html[dir="rtl"] .ms-map-tooltip { text-align: start; }

/* ---- Weather chip (Open-Meteo overlay) ----
   Originally lived at top: 12px but that crowded the corner with the
   LayerFilterPanel. Moved to bottom-inline-end (above the OpenSeaMap
   attribution which sits bottom-center) so the operator-facing top
   corners stay clean. */
.ms-weather-chip {
    position: absolute;
    bottom: 28px;
    inset-inline-end: 12px;
    z-index: 5;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    background: var(--ms-panel);
    border: 1px solid var(--ms-panel-border);
    color: var(--ms-text);
    font-family: var(--ms-font-mono);
    font-size: 11px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
    pointer-events: auto;
}
.ms-weather-arrow {
    display: inline-block;
    width: 14px;
    text-align: center;
    color: var(--ms-accent);
    font-size: 14px;
    line-height: 1;
}
.ms-weather-wind { color: var(--ms-text); font-weight: 600; }
.ms-weather-wave { color: var(--ms-friend); }
.ms-weather-temp { color: var(--ms-text-dim); }
.ms-weather-unit { color: var(--ms-text-mute); font-size: 9px; }

/* ---- AIS layer filter (multi-source overlay) ----
   Sits on the OPPOSITE side from .ms-layer-filter so the two top-of-map
   panels never collide. LayerFilter is anchored at inset-inline-end
   (visual right in LTR, visual left in RTL); AisFilter must be at the
   inline-start side. We had inset-inline-start: 12px here originally but
   it resolved to the same physical edge as inset-inline-end on Chromium
   in RTL (browser quirk in this nested-flex layout), causing the AIS
   panel to overlap LayerFilter. Direction-explicit left/right is
   bulletproof. */
.ms-ais-filter {
    position: absolute;
    top: 12px;
    left: 12px;
    z-index: 5;
    background: var(--ms-panel);
    border: 1px solid var(--ms-panel-border);
    color: var(--ms-text);
    font-size: 11px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
html[dir="rtl"] .ms-ais-filter {
    left: auto;
    right: 12px;
}
.ms-ais-filter-toggle {
    border: none;
    width: 100%;
    text-align: start;
}
.ms-ais-filter-body {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 6px 8px 8px;
    border-top: 1px solid var(--ms-panel-border);
    min-width: 240px;
}
.ms-ais-filter-row {
    display: grid;
    grid-template-columns: 16px 12px 1fr auto auto;
    gap: 6px;
    align-items: center;
    cursor: var(--ms-cursor-pointer);
    padding: 2px 0;
}
.ms-ais-filter-dot {
    width: 10px; height: 10px;
    border-radius: 50%;
    border: 1px solid var(--ms-panel-border);
}
.ms-ais-src-1 { background: var(--ms-friend); }
.ms-ais-src-2 { background: var(--ms-link); }
.ms-ais-src-3 { background: var(--ms-ok); }
.ms-ais-src-4 { background: var(--ms-accent2); }

/* Vessel-type category dots — kept 1:1 in sync with aisPointColorExpr()
   in maplibre-interop.js so the panel doubles as a legend. The N index
   is (int)AisShipCategory; if a new category is added on either side
   the other has to follow. */
.ms-ais-cat-0 { background: var(--ms-text-mute);   } /* unknown */
.ms-ais-cat-1 { background: var(--ms-warn-strong); } /* fishing */
.ms-ais-cat-2 { background: var(--ms-ok);          } /* passenger */
.ms-ais-cat-3 { background: var(--ms-friend);      } /* cargo */
.ms-ais-cat-4 { background: var(--ms-alert);       } /* tanker */
.ms-ais-cat-5 { background: var(--ms-accent2);     } /* high-speed */
.ms-ais-cat-6 { background: var(--ms-link);        } /* tug / service */
.ms-ais-cat-7 { background: var(--ms-warn);        } /* military */
.ms-ais-cat-8 { background: var(--ms-ok-bright);   } /* SAR */
.ms-ais-cat-9 { background: var(--ms-text-dim);    } /* other */

/* Section heading inside the AIS filter body that separates the
   provider rows from the category rows. Visual cue only — keeps the
   12-row stack scannable without breaking up the grid layout of the
   existing filter rows. */
.ms-ais-filter-section {
    font-family: var(--ms-font-mono);
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ms-text-mute);
    padding: 6px 0 2px 0;
    margin-block-start: 4px;
    border-block-start: 1px solid var(--ms-panel-border);
}

/* Collapsible sub-group header (AIS sources / vessel types). Looks like the
   old .ms-ais-filter-section label but is a full-width clickable toggle with
   a leading ▸/▾ disclosure arrow. */
.ms-ais-filter-group-head {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    background: none;
    border: none;
    border-block-start: 1px solid var(--ms-panel-border);
    cursor: pointer;
    font-family: var(--ms-font-mono);
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--ms-text-mute);
    padding: 6px 0 4px 0;
    margin-block-start: 4px;
    text-align: start;
}
.ms-ais-filter-group-head:hover { color: var(--ms-text); }
.ms-ais-filter-group-arrow {
    display: inline-block;
    width: 0.8em;
    font-size: 10px;
    line-height: 1;
}

.ms-ais-filter-name { font-family: var(--ms-font-ui); }
.ms-ais-filter-state {
    font-family: var(--ms-font-mono);
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 1px 4px;
    border: 1px solid currentColor;
    border-radius: 2px;
}
.ms-ais-filter-state.ok    { color: var(--ms-ok); }
.ms-ais-filter-state.warn  { color: var(--ms-warn); }
.ms-ais-filter-state.alert { color: var(--ms-alert); }
.ms-ais-filter-state.mute  { color: var(--ms-text-mute); }
.ms-ais-filter-count {
    font-family: var(--ms-font-mono);
    font-size: 10px;
    color: var(--ms-text-dim);
    min-width: 28px;
    text-align: end;
}
.ms-ais-filter-refresh {
    margin-top: 4px;
    font-size: 9px;
}

/* (Older RTL override that pinned the AIS filter to inset-inline-end
   was removed — it forced it onto the same side as the LayerFilter,
   producing an overlap. The direction-explicit left/right rule next to
   the .ms-ais-filter base block above already handles RTL correctly.) */

/* Panels in the side rails fill available vertical space proportionally. */
.ms-lagebild-col > .ms-panel { flex: 1 1 0; min-height: 0; }

/* Lightning strikes fade from full opacity to zero across their TTL window
   (LightningOptions.StrikeTtl = 15 min). Operators can read freshness at a
   glance — bright = just hit, dim = nearly evicted by the prune loop.
   `forwards` keeps the final state pinned in case a marker survives slightly
   past TTL between janitor ticks. */
@keyframes ms-fade-strike {
    from { opacity: 1; }
    to   { opacity: 0; }
}
.ms-lightning-marker {
    animation: ms-fade-strike 900s linear forwards;
}

/* Stack at narrower widths — tablet portrait or smaller windows.
   Below this, the map gets full width and panels collapse to a single column above/below. */
@media (max-width: 1280px) {
    .ms-lagebild {
        grid-template-columns: 1fr;
        grid-auto-rows: minmax(140px, auto);
    }
    .ms-lagebild-col.center {
        position: relative;
        height: 50vh;
    }
}

/* ---- Floating action buttons (FABs) ----
   Round, theme-coloured buttons that float over the map. The panels FAB is
   tablet-only (revealed in ms-draggable-panels.css); the fullscreen-exit FAB
   only renders while fullscreen is active. */
.ms-map-fab {
    position: absolute;
    z-index: 50;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--ms-panel);
    color: var(--ms-accent);
    border: 1px solid var(--ms-panel-border);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
    cursor: var(--ms-cursor-pointer);
    font-size: 18px;
    line-height: 1;
    padding: 0;
}
.ms-map-fab:hover { filter: brightness(1.15); border-color: var(--ms-accent); }
.ms-map-fab-panels {
    inset-block-end: 16px;
    inset-inline-end: 16px;
}
.ms-map-fab-fullscreen {
    inset-block-start: 16px;
    inset-inline-end: 16px;
}

/* ---- Fullscreen map (F shortcut) ----
   The shell stretches to cover the viewport and the floating HUD groups +
   tablet drawer chrome are hidden, leaving just the map (and the
   fullscreen-exit FAB). The map container already fills the shell via
   inset:0, so the only work here is hiding the overlays. */
.ms-lagebild.ms-map-fullscreen {
    position: fixed;
    inset: 0;
    z-index: 1000;
}
.ms-map-fullscreen .ms-hud-groups,
.ms-map-fullscreen .ms-panels-backdrop,
.ms-map-fullscreen .ms-map-fab-panels {
    display: none !important;
}

/* AIS popup vessel photo — Wikidata-backed, fetched after popup mount.
   Displayed only when the contact carries an IMO and Wikidata returned
   a Wikimedia Commons image; otherwise the slot is removed entirely so
   no empty box leaks into the popup. */
.ms-ais-photo {
    margin-bottom: 6px;
    line-height: 0; /* kill the gap below the inline-block <img> */
}
.ms-ais-photo a,
.ms-ais-photo img {
    display: block;
    width: 100%;
    max-width: 280px;
    max-height: 180px;
    object-fit: cover;
    border-radius: 4px;
    background: var(--ms-bg-mute, #e5e7eb);
}

/* Loading shimmer for the AIS popup vessel photo. Reserves the layout
   slot the photo will fill so the popup doesn't reflow when Wikidata
   responds, and gives a perceptible "fetching" cue during the multi-
   second cold-cache SPARQL latency. Removed by paintVesselPhoto on
   200; .ms-ais-photo itself is removed on 404 / error. */
.ms-ais-photo-loading {
    position: relative;
    height: 120px;
    border-radius: 4px;
    background: linear-gradient(
        90deg,
        var(--ms-bg-mute, #e5e7eb) 0%,
        var(--ms-bg, #f3f4f6) 50%,
        var(--ms-bg-mute, #e5e7eb) 100%);
    background-size: 200% 100%;
    animation: ms-ais-photo-shimmer 1.4s linear infinite;
}
@keyframes ms-ais-photo-shimmer {
    0%   { background-position: 100% 0; }
    100% { background-position: -100% 0; }
}
@media (prefers-reduced-motion: reduce) {
    .ms-ais-photo-loading { animation: none; }
}

/* ---- Mission dispatch UX (#dispatch-ux) ---------------------------------- */

/* Draggable own-unit marker. The glyph + colour are set inline in JS
   (makeUnitEl) so the marker survives a stylesheet-less first paint; this
   block adds the interaction affordances. */
.ms-unit-marker {
    box-shadow: 0 1px 3px rgba(3, 9, 17, 0.5);
    transition: transform 0.08s ease-out, box-shadow 0.08s ease-out;
    user-select: none;
}
.ms-unit-marker:hover {
    transform: scale(1.15);
    box-shadow: 0 0 8px var(--ms-friend, #a5b4fc);
}

/* One-shot "tasking sent" ping dropped at the target track on mission start.
   An expanding, fading accent ring; the JS removes the marker after the run. */
.ms-dispatch-ping {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    border: 2px solid var(--ms-accent, #22d3ee);
    background: transparent;
    pointer-events: none;
    animation: ms-dispatch-ping 1.2s ease-out forwards;
}
@keyframes ms-dispatch-ping {
    0%   { transform: scale(0.4); opacity: 0.9; }
    70%  { opacity: 0.5; }
    100% { transform: scale(3.2); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
    .ms-dispatch-ping { animation-duration: 0.01s; }
}

/* Track / unit popups opened by click-to-navigate from the side panels.
   Rendered inside MapLibre's default (light) popup, so dark text. */
.ms-map-popup { min-width: 120px; font-size: 12px; color: #0b1220; }
.ms-map-popup-title { font-weight: 700; margin-bottom: 4px; }
.ms-map-popup-row {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
    color: #334155;
}
.ms-map-popup-row + .ms-map-popup-row { margin-top: 2px; }

/* Click-to-navigate highlight (focusOnMap): a longer-lived accent ring that
   pulses for 3 s so the operator's eye lands on the target they just clicked
   in the TracksPanel ("أهداف الرادار") or AssetsPanel ("الوحدات"). */
.ms-focus-pulse {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 3px solid var(--ms-accent, #22d3ee);
    background: transparent;
    pointer-events: none;
    box-shadow: 0 0 12px var(--ms-accent, #22d3ee);
    animation: ms-focus-pulse 1s ease-out 3;
}
@keyframes ms-focus-pulse {
    0%   { transform: scale(0.5); opacity: 0.95; }
    100% { transform: scale(2.6); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
    .ms-focus-pulse { animation: none; opacity: 0.9; }
}

/* Right-click track → dispatch context menu (#dispatch-ux). The scrim is a
   full-viewport transparent catch so the next click anywhere dismisses; the
   menu sits above it, anchored at the cursor in viewport coordinates. */
.ms-map-ctxmenu-scrim {
    position: fixed;
    inset: 0;
    z-index: 1400;
    background: transparent;
}
.ms-map-ctxmenu {
    position: fixed;
    z-index: 1401;
    min-width: 168px;
    padding: 4px;
    background: var(--ms-panel, #0f1b2d);
    border: 1px solid var(--ms-panel-border, #1e2d44);
    border-radius: 6px;
    box-shadow: 0 6px 20px rgba(3, 9, 17, 0.55);
}
.ms-map-ctxmenu-item {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 8px 10px;
    background: transparent;
    border: none;
    border-radius: 4px;
    color: var(--ms-text, #e2e8f0);
    font: inherit;
    font-size: 13px;
    text-align: start;
    cursor: pointer;
}
.ms-map-ctxmenu-item:hover {
    background: var(--ms-accent-soft, rgba(34, 211, 238, 0.15));
    color: var(--ms-accent, #22d3ee);
}
