/* Shared "▤ Map Layers" control (core/map-layers.js, TKF-257).
 *
 * One stylesheet for the planner and both activity maps. It supersedes the
 * `.rp-map-layers-*` block in route-planner.css and the `.tk-ml-*` block in
 * analysis.css, which were the same rules typed twice — the analysis copy even
 * carried "see .rp-map-layers-body" in its own comment, and named itself
 * `.tk-ml-*` rather than scoping to the track view precisely so the planner
 * could converge on it later. This is later.
 *
 * Where the CONTROL sits is NOT here: each host insets the Leaflet corner itself,
 * because the offsets are its own (the planner aligns to its sidebar chevrons,
 * the activity map to its drawer handle). Where the SCALE BAR sits is here, at
 * the foot of this file — it is not an inset but a relationship to the zoom bar
 * this module's hosts all put in the same corner, and it was the third copy of
 * the same layout that TKF-257 existed to stop (TKB-302). */

.tk-ml-ctl {
  position: relative;                /* anchor for the drop-down panel */
  width: max-content;                /* stay button-width so it can't shift */
  border: none !important;           /* override leaflet-bar chrome */
  box-shadow: none !important;
  background: transparent !important;
}

.tk-ml-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 36px;                      /* match the chevrons + fullscreen button */
  box-sizing: border-box;
  padding: 0 12px;
  background: var(--bg1);
  color: var(--txt);
  border: 2px solid rgba(0, 0, 0, 0.2);
  border-radius: 4px;
  font: inherit;
  font-size: var(--fs-sm);
  cursor: pointer;
  white-space: nowrap;
}
.tk-ml-toggle:hover {
  background: var(--bg2);
  color: var(--amber);
}
.tk-ml-ctl.open .tk-ml-toggle {
  background: var(--amber);
  color: var(--bg0);
}

/* An open panel wins the corner. Leaflet gives every `.leaflet-control` its
   own stacking context at z 800, so the panel's z-index below only ranks it
   WITHIN this control — a later control in the same corner (the 3D buttons,
   TKF-335) paints over the open panel no matter what the panel says. Lift the
   whole control while it is open; closed, order is irrelevant. */
.tk-ml-ctl.open { z-index: 801; }

/* Drops BELOW the button, out of flow, so opening never moves the button.
   Right-aligned to the (narrow) control. */
.tk-ml-body {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 1001;
  width: 270px;
  max-width: 78vw;
  /* Fallback only — the real cap is measured against the MAP when the panel
     opens (sizeBody in map-layers.js, TKB-268), because a vh cap knows nothing
     about the zoom buttons and scale bar parked in the map's bottom-right
     corner, which is exactly where a panel dropping from top-right grows. */
  max-height: 60vh;
  overflow-y: auto;
  /* Don't hand the leftover scroll to the page once the list bottoms out. */
  overscroll-behavior: contain;
  padding: 10px 12px;
  border-radius: 6px;
  border: 1px solid color-mix(in srgb, var(--dim) 35%, transparent);
  /* Frosted glass: blurred and still tinted by the map underneath, but opaque
     enough that the label COLOUR alone carries legibility over any tile. It sat
     at 50% and leaned on a hard black text-shadow instead; that shadow reads as
     a drop shadow on every label, which is what the panel was pulled up on.
     Don't take the alpha back below ~85% without restoring some other
     legibility mechanism. (TKB-243) */
  background: color-mix(in srgb, var(--bg1) 88%, transparent);
  -webkit-backdrop-filter: blur(16px) saturate(1.2);
  backdrop-filter: blur(16px) saturate(1.2);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.3);
  color: var(--txt-hi);
}
.tk-ml-body[hidden] { display: none; }

/* ── Collapsible section (Map options, and whatever the host appends) ────── */
.tk-ml-section + .tk-ml-section {
  border-top: 1px solid var(--bdr);
  padding-top: 8px;
  margin-top: 8px;
}
.tk-ml-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}
.tk-ml-section-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: 0;
  padding: 0;
  color: var(--txt-hi);
  font: inherit;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  cursor: pointer;
}
.tk-ml-caret {
  display: inline-block;
  transition: transform 0.15s ease;
  font-size: var(--fs-xs);
  color: var(--dim);
}
.tk-ml-section.collapsed .tk-ml-caret { transform: rotate(-90deg); }
.tk-ml-section.collapsed .tk-ml-section-body { display: none; }

.tk-ml-section-body {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* ── Rows ────────────────────────────────────────────────────────────────── */
/* Label and control both have to be allowed to SHRINK. Flex items default to
   min-width:auto, so a <select> sized to its widest option refuses to narrow —
   and once the label grows with translation ("Basemap" → "Kartengrundlage") the
   row overflows the 270px panel to the right. min-width:0 is what permits the
   shrink; the rest just makes the result read well. */
.tk-ml-field {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-size: var(--fs-sm);
  color: var(--txt-hi);
}
.tk-ml-field > span {
  min-width: 0;
  overflow-wrap: anywhere;
}
.tk-ml-field select {
  background: var(--bg2);
  color: var(--txt);
  border: 1px solid var(--bdr);
  border-radius: 4px;
  padding: 4px 6px;
  font: inherit;
  font-size: var(--fs-sm);
  min-width: 0;
  max-width: 62%;
  text-overflow: ellipsis;
  cursor: pointer;
}

.tk-ml-check {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: var(--fs-sm);
  color: var(--txt-hi);
  cursor: pointer;
}
/* accent-color, not a custom control: the box is a real checkbox so it keeps
   its native focus ring and keyboard behaviour. Amber ink on the tick — see
   TKB-250 for why this is set explicitly rather than inherited. */
.tk-ml-check input { accent-color: var(--amber); margin: 0; flex-shrink: 0; }
.tk-ml-check input:disabled + span { color: var(--dim2); }

@media (max-width: 640px) {
  .tk-ml-body { width: 240px; max-height: 60vh; }
}

/* ── The map's bottom-right corner: scale bar beside the zoom ─────────────── */
/* Leaflet drops the scale bar, the zoom bar and the attribution into one
   bottom-right corner and stacks them in DOM order, and it PREPENDS in a bottom
   corner — so the scale, added last, lands on top of the zoom buttons rather
   than beside them. The planner used to be the only surface that corrected
   this, with `position:absolute; right:50px; bottom:32px` in route-planner.css;
   the two activity maps got the raw stack. That rule is gone with this one
   (TKB-302).

   Laid out rather than measured, because both hand-set offsets were fragile in
   a different direction and neither could survive being shared:

     • an offset from the zoom's TOP has to encode the zoom's height, and
       Leaflet sizes that from `.leaflet-touch` — 30px buttons + a 2px border
       against 26px + 1px, ~10px apart — so it is wrong on half the devices;
     • an offset from the corner's BOTTOM has to encode the attribution's
       height, which is one line until the map is narrow enough to wrap it, and
       then the zoom rides up while a pinned scale bar does not.

   A two-column grid derives both. Row 1 is scale | zoom, `align-items: end`
   putting their margin boxes on one bottom line; the attribution spans and
   takes row 2. Whatever the zoom's height, and however the attribution wraps,
   the scale bar's bottom edge is the zoom bar's bottom edge.

   With the scale bar switched off the corner is just zoom + attribution: the
   zoom takes column 1, the attribution still spans, and both stay hard right —
   measured identical to before this rule existed, 10px in and 26px up. */
.tk-ml-map .leaflet-bottom.leaflet-right {
  display: grid;
  /* `1fr auto`, not `auto auto`: the attribution spans both columns and is far
     the widest thing in the corner, and equal `auto` tracks split that extra
     width BETWEEN them — which pushes the scale bar a couple of hundred pixels
     off the zoom it is supposed to sit beside. Let column 1 take the slack and
     size column 2 to the zoom bar. */
  grid-template-columns: 1fr auto;
  align-items: end;
  /* Shrink-wrap each control instead of stretching it across its cell. The
     corner is as wide as the attribution line — much wider than scale + zoom —
     so stretched controls sit at the FAR left of that width, drawing their
     content yards from the right-hand edge they are supposed to hug. */
  justify-items: end;
}
.tk-ml-map .leaflet-bottom.leaflet-right .leaflet-control-attribution {
  grid-column: 1 / -1;
}
/* Leaflet gives the scale bar `margin-bottom: 5px` and every other bottom
   control 10px. `align-items: end` aligns MARGIN boxes, so the 5px would leave
   the scale bar sitting 5px lower than the zoom it is meant to line up with. */
.tk-ml-map .leaflet-bottom.leaflet-right .leaflet-control-scale {
  margin-bottom: 10px;
}

/* ── 3D view (core/map3d.js, TKF-335) ────────────────────────────────────── */
/* Two controls in the Map Layers corner, one row, corner-outward: Map Layers,
   the `3D` toggle to its left, and — only while 3D is up — ↺ N ↻ to the
   toggle's left (TKF-376). Both wear the `.tk-ml-toggle` skin, `.leaflet-bar`
   chrome stripped the way `.tk-ml-ctl` strips it.

   Leaflet gives every control `float` and `clear: both`, so controls in a
   corner can only stack. The corner floats right and Leaflet appends in add
   order, so Map Layers (added at mount) is the earliest sibling and takes the
   corner; lifting `clear` on the two 3D controls lets them float up beside it,
   each to the left of the one before. `.leaflet-control` is what carries the
   `clear`, so the compound selector outranks it whichever order the sheets
   load. The top inset that places them is copied from Map Layers at mount
   (map-layers.js), because the corner inset is each host's own; the right
   margin is the 6px gap to the neighbour, set there too. On a map too narrow
   for the row, a control that does not fit drops to the line below, still
   against the right edge. */
.tk-ml-3d-toggle,
.tk-ml-3d-row {
  width: max-content;
  border: none !important;
  box-shadow: none !important;
  background: transparent !important;
}
.leaflet-control.tk-ml-3d-toggle,
.leaflet-control.tk-ml-3d-row {
  clear: none;                       /* up beside the earlier sibling */
}
.tk-ml-3d-btn {
  min-width: 46px;
  font-weight: 600;
  letter-spacing: 0.5px;
}
.tk-ml-3d-toggle.active .tk-ml-3d-btn {
  background: var(--amber);
  color: var(--bg0);
}
.tk-ml-3d-row {
  display: flex;
  gap: 4px;
}
.tk-ml-3d-row[hidden] { display: none; }
.tk-ml-3d-north {
  min-width: 46px;
  gap: 3px;
  font-weight: 600;
}
.tk-ml-3d-rot {
  min-width: 36px;
  padding: 0 8px;
  font-size: var(--fs-base);
}
/* The needle turns with the map (map3d 'rotate' → rotate(-bearing)), so the
   button always shows where north IS; clicking it puts north back at the top. */
.tk-ml-3d-needle {
  display: inline-block;
  color: #ef4444;
  font-size: 0.8em;
  transition: transform 0.15s ease;
}

/* The GL map's home: fills the Leaflet container. Its z-index is NOT here —
   map3d.js sets it inline to the map pane's own value and slots the node right
   after the pane, so it paints over the map and under the control corners
   whatever a host has clamped them to (the planner clamps both to 10, Leaflet's
   defaults are 400 / 1000). A fixed number here got the planner a 3D view with
   its `2D` and Map Layers buttons buried. The background is the sky's fog
   colour, so the instant before the first frame is not the 2D map showing
   through. */
.tk-3d-wrap {
  /* !important on purpose: MapLibre adds `.maplibregl-map { position: relative }`
     to this same node, from a stylesheet appended to <head> AFTER this one, so
     at equal specificity it would win and the map would collapse to a 0-height
     block in the container's flow. */
  position: absolute !important;
  inset: 0;
  width: 100%;
  height: 100%;
  background: #dfe6ee;
}
.tk-3d-wrap[hidden] { display: none; }
/* The planner's Crosshair cursor rule (`.rp-map.rp-crosshair *`, !important)
   reaches into the GL canvas too, and a draw cursor over a view that cannot
   be drawn on is a promise the view cannot keep. Grab, like any 3D map. */
.leaflet-container .tk-3d-wrap .maplibregl-canvas-container.maplibregl-interactive,
.leaflet-container .tk-3d-wrap .maplibregl-canvas-container.maplibregl-interactive canvas {
  cursor: grab !important;
}
.leaflet-container .tk-3d-wrap .maplibregl-canvas-container.maplibregl-interactive:active,
.leaflet-container .tk-3d-wrap .maplibregl-canvas-container.maplibregl-interactive:active canvas {
  cursor: grabbing !important;
}
