/* ==========================================================================
   L.U.M.E.N. — 11 MAP
   Shadow canvas, vector overlay, reticle, and the MapLibre overrides.
   ========================================================================== */

/* --------------------------------------------------------------------------
   OVERLAY STACK
   Three layers over the map canvas, all transparent to the pointer so panning
   and pin-dropping still reach the map underneath.

     1. shadow canvas   the projected silhouettes
     2. vector svg      sun, moon and boundary bearings, plus the reticle
     3. controls        real buttons, which DO take pointer events
   -------------------------------------------------------------------------- */

.lumen-shadow-canvas,
.lumen-vector-layer {
  position: absolute;
  inset: 0;
  /* ------------------------------------------------------------------------
     THESE TWO DECLARATIONS ARE LOAD-BEARING. DO NOT REMOVE THEM.

     `position: absolute; inset: 0` stretches a normal element to fill its
     containing block. It does NOT do that to a REPLACED element — a canvas,
     an img, an svg with intrinsic dimensions. For those, CSS resolves the
     used width from the element's own intrinsic size and then treats the
     over-constrained `left`/`right` pair by ignoring one of them.

     A canvas's intrinsic size is its BACKING STORE, i.e. its width and
     height attributes. This layer sets those to `container size x devicePixelRatio`,
     which is the standard way to get a crisp canvas on a high-density
     display. So on a 2x screen the canvas was laid out at twice the
     container's dimensions, anchored to the top-left, with the remainder
     overflowing and clipped away.

     The visible result was a wash covering exactly the top-left quarter —
     read as "only the top half" or "only the left half" depending on where
     the buildings happened to be — and correct on a 1x display, which is
     what made it look intermittent and random. Browser zoom changes the
     device pixel ratio, so it changed with zoom too.

     The vector layer never showed the fault only because it happened to
     carry `width: 100%`. That asymmetry is now removed: both overlays are
     sized explicitly, and neither relies on `inset` alone.
     ------------------------------------------------------------------------ */
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.lumen-shadow-canvas {
  z-index: 2;
  /* A canvas is inline by default, which leaves a descender gap beneath it. */
  display: block;
}

.lumen-vector-layer { z-index: 3; }

/* --------------------------------------------------------------------------
   CELESTIAL VECTORS
   Colour carries meaning here and is not interchangeable:

     cyan     the live solar reading
     ivory    the moon, a second and colder light
     orange   the operational limits of the day, sunrise and sunset bearings
     muted    the shadow direction, which is structure rather than a reading
   -------------------------------------------------------------------------- */

.lumen-vec {
  fill: none;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.lumen-vec--sun {
  stroke: var(--nova-cyan-bright);
  stroke-width: 2.5;
}

/* A sun below the horizon still has a bearing worth knowing, but it is not
   an operational light source and must not look like one. */
.lumen-vec--sun.is-below {
  stroke: var(--nova-text-diagnostic);
  stroke-width: 1.5;
  stroke-dasharray: 3 5;
}

.lumen-vec--moon {
  stroke: var(--nova-ivory);
  stroke-width: 1.8;
  opacity: 0.9;
}

.lumen-vec--moon.is-below {
  stroke: var(--nova-text-diagnostic);
  stroke-width: 1.2;
  stroke-dasharray: 2 6;
  opacity: 0.6;
}

.lumen-vec--boundary {
  stroke: var(--nova-orange);
  stroke-width: 1.4;
  stroke-dasharray: 6 5;
  opacity: 0.75;
}

.lumen-vec--shadow {
  stroke: var(--nova-text-muted);
  stroke-width: 1.4;
  stroke-dasharray: 1 4;
  opacity: 0.7;
}

/* --------------------------------------------------------------------------
   TELEMETRY RETICLE
   A targeting reticle, not a teardrop pin. This instrument reports a
   position; it does not label a place of interest.
   -------------------------------------------------------------------------- */

.lumen-reticle__ring {
  fill: none;
  stroke: var(--nova-cyan-bright);
  stroke-width: 1.6;
}

.lumen-reticle__core {
  fill: var(--nova-cyan-bright);
}

.lumen-reticle__tick {
  stroke: var(--nova-cyan-bright);
  stroke-width: 1.6;
}

/* --------------------------------------------------------------------------
   MAPLIBRE OVERRIDES
   The library ships a light-mode widget aesthetic. All of it is either
   suppressed or restyled; none of it is allowed through as-is.
   -------------------------------------------------------------------------- */

.maplibregl-map {
  font-family: var(--font-mono);
  background: var(--nova-space);
}

.maplibregl-canvas { outline: none; }

/* Stock controls are rebuilt as .nova-btn in the markup. */
.maplibregl-ctrl-top-right,
.maplibregl-ctrl-top-left,
.maplibregl-ctrl-bottom-right,
.maplibregl-ctrl-bottom-left {
  display: none !important;
}

/* Popups and tooltips, should any ever appear, follow the chassis. */
.maplibregl-popup-content {
  background: var(--nova-panel);
  border: var(--border-structural) solid var(--nova-border);
  border-radius: 0;
  box-shadow: none;
  color: var(--nova-text-secondary);
  font-family: var(--font-mono);
  font-size: var(--fs-tiny);
}

.maplibregl-popup-tip { display: none; }

/* MapLibre's missing-image and error text */
.maplibregl-canvas-container.maplibregl-interactive { cursor: crosshair; }
.maplibregl-canvas-container.maplibregl-interactive:active { cursor: crosshair; }
