/* ---------------------------------------------------------------------------
 * Geo Map tool.
 *
 * The page is the HISTORY MAP's layout (templates/apps/project/history/map.html):
 * one full-height card with the map in it. The map itself is a `BoreholeMap`,
 * so its chrome — control chips, the map-tools dock, the popup, the legend, the
 * coordinate readout — is already themed by custom/css/map/main.css and is NOT
 * restyled here. The drawing panel is a column beside it inside the same card.
 *
 * What is here is only what a drawing tool adds: the card's height, the panel
 * beside the map, its draw tools and its shape list. The panel reuses the
 * map-tools dock's own `.bm-dock-head` / `.bm-dock-section` / `.bm-dock-hint`
 * internals, so the two read as one system and cannot drift apart.
 *
 * The DRAW TOOLS are ours, not leaflet-draw's. Its `L.Control.Draw` toolbar —
 * a floating stack of unlabelled white squares — never renders; geo-map.js
 * drives the plugin's handlers from the buttons below, so the geometry is still
 * the plugin's and only the chrome is ours.
 *
 * Every colour comes from a `--bm-*` token, declared on `.leaflet-container`
 * and on `.bm-scope` (main.css) — the panel sits OUTSIDE the map container, so
 * it carries `.bm-scope` to inherit the same palette rather than a copy of it.
 * Nothing needs a `.dark-version` duplicate, because the tokens already flip:
 * an earlier version of this file carried a hand-written dark variant per rule
 * and they drifted from the map's own palette.
 *
 * Loaded by apps/tools/templates/page/geo_map/index.html with a ?v= stamp.
 * ------------------------------------------------------------------------- */

/* ── the page ────────────────────────────────────────────────────────────── */
/* The one hide switch this page uses. `d-none` is Bootstrap's and is fine for
   markup the theme also styles, but the panel is ours end to end and several of
   its parts (the project section, the coordinate entry, the editor scrim) ship
   hidden and are revealed by geo-map.js — an undefined class there means every
   one of them renders on load. */
.gm-hidden {
  display: none !important;
}



/* Full viewport, no page scroll: the map is the page.

   `--gm-chrome` is MEASURED by geo-map.js from the card's own offset — the
   navbar, breadcrumb and card margins are the theme's numbers, and a hard-coded
   `calc(100vh - 7rem)` copy of them drifts the moment the theme changes one. The
   fallback keeps the card sane in the instant before the script runs. */
html.gm-no-scroll,
html.gm-no-scroll body.gm-no-scroll {
  overflow: hidden;
}
.gm-card {
  height: calc(100vh - var(--gm-chrome, 8rem));
  min-height: 22rem;
  margin-bottom: 0 !important;
}

/* ── map + panel columns ─────────────────────────────────────────────────── */

/* The panel is a COLUMN beside the map, never an overlay on it. The overlay
   version pushed the map's Leaflet control stack aside with a margin while it
   was open, which teleported every control — the one just clicked included — on
   each toggle. Here the controls move only because the map's own edge moved. */
.gm-body {
  display: flex;
  align-items: stretch;
  height: 100%;
  gap: 0;
}

.gm-map {
  flex: 1 1 auto;
  min-width: 0; /* or a wide panel cannot shrink the map and the card overflows */
  height: 100%;
}

.gm-dock {
  flex: 0 0 21rem;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  background: var(--bm-panel);
  color: var(--bm-ink);
  border-left: 1px solid var(--bm-line);
}

.gm-collapsed .gm-dock {
  display: none;
}

/* The reopen rail.
 *
 * A COLUMN in the flex row, not a button floating on the map. Floated at the
 * map's top-right it landed on top of Leaflet's own control stack, which starts
 * at the same corner — the collision this whole layout exists to avoid. As a
 * column it is outside the map, so the map's right edge stops before it and the
 * two can never overlap however many controls the stack grows.
 *
 * It also means the panel's slot never fully disappears, so collapsing reads as
 * "folded away", not "gone". */
.gm-reopen {
  display: none;
}
.gm-collapsed .gm-reopen {
  display: flex;
  flex: 0 0 2.25rem;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  padding: 10px 0;
  font-family: inherit;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--bm-soft);
  background: var(--bm-panel);
  border: 0;
  border-left: 1px solid var(--bm-line);
  cursor: pointer;
  transition: color 0.12s, background-color 0.12s;
}
.gm-collapsed .gm-reopen:hover {
  color: var(--bm-accent);
  background: var(--bm-panel-2);
}
.gm-reopen .material-symbols-rounded {
  font-size: 19px;
  line-height: 1;
  color: var(--bm-accent);
}
/* Reading bottom-to-top keeps the label upright next to a right-hand edge. */
.gm-reopen span {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
}

/* Reuse the map dock's internals so the panel and the map-tools dock stay one
   system: heading bar, section rhythm, hint text, the lot. */
.gm-dock .bm-dock-head {
  flex: 0 0 auto;
}
.gm-dock .bm-dock-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
}

/* ── the draw tools ──────────────────────────────────────────────────────── */

/* Three big labelled targets, one row, exactly one active — a tool picker, not
   a strip of unlabelled squares. This is what replaces `L.Control.Draw`'s own
   toolbar; the plugin's handlers still do the geometry. */
.gm-tools {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}

.gm-tool {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 10px 4px;
  font-family: inherit;
  font-size: 0.66rem;
  font-weight: 600;
  color: var(--bm-ink);
  background: var(--bm-panel-2);
  border: 1px solid var(--bm-line);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color 0.12s, background-color 0.12s, color 0.12s;
}
.gm-tool .material-symbols-rounded {
  font-size: 21px;
  line-height: 1;
  color: var(--bm-accent);
}
.gm-tool:hover {
  border-color: var(--bm-accent);
}
/* Active state has to be unmistakable: it is the difference between "a click
   places a point" and "a click pans the map". */
.gm-tool.active {
  background: var(--bm-accent);
  border-color: var(--bm-accent);
  color: #fff;
}
.gm-tool.active .material-symbols-rounded {
  color: #fff;
}

/* Revealed under the Point tool: typing a coordinate IS placing a point, so it
   belongs to that tool rather than to a section of its own. */
.gm-subpanel {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed var(--bm-line);
}

/* A section heading with an action on its right (Drawn shapes / Clear all).
   Without this the action sits against the count and reads as part of it. */
.gm-sec-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

/* ── controls inside the panel ──────────────────────────────────────────── */

/* One input style for text boxes and selects. Bootstrap's `.form-control` is
   sized for a page form and is far too tall for a drawer this dense; these
   match the dock's own button metrics instead. */
.gm-input {
  display: block;
  width: 100%;
  margin-bottom: 6px;
  padding: 6px 9px;
  font-family: inherit;
  font-size: 0.76rem;
  line-height: 1.3;
  color: var(--bm-ink);
  background: var(--bm-panel-2);
  border: 1px solid var(--bm-line);
  border-radius: 6px;
  transition: border-color 0.12s;
}
.gm-input:focus {
  outline: none;
  border-color: var(--bm-accent);
}
.gm-input::placeholder {
  color: var(--bm-soft);
}
/* A native select paints its own arrow in the OS colour, which is invisible on
   the dark panel; the caret is drawn here so it follows --bm-soft. */
select.gm-input {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 26px;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 14px) 12px, calc(100% - 9px) 12px;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  color: var(--bm-ink);
}
select.gm-input option {
  /* Windows/Chrome paints the open list from the element, not the page. */
  background: var(--bm-panel);
  color: var(--bm-ink);
}

.gm-grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}

.gm-field-check {
  cursor: pointer;
}
.gm-field-check input[type="checkbox"] {
  accent-color: var(--bm-accent);
  width: 15px;
  height: 15px;
  cursor: pointer;
}

/* Buttons: the dock's `.bm-dock-btn` metrics, declared standalone because these
   are real <button>s outside a `.leaflet-bar` and must not depend on the
   control-chip overrides that class carries. */
.gm-btn {
  flex: 1 1 0;
  min-width: 0;
  margin-top: 6px;
  padding: 7px 9px;
  font-family: inherit;
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.2;
  color: var(--bm-ink);
  background: var(--bm-panel-2);
  border: 1px solid var(--bm-line);
  border-radius: 6px;
  cursor: pointer;
  transition: border-color 0.12s, color 0.12s, background-color 0.12s;
}
.gm-btn:hover {
  border-color: var(--bm-accent);
  color: var(--bm-accent);
}
.gm-btn-primary {
  background: var(--bm-accent);
  border-color: var(--bm-accent);
  color: #fff;
}
.gm-btn-primary:hover {
  background: var(--bm-accent);
  color: #fff;
  filter: brightness(1.08);
}
.gm-btn-danger:hover {
  border-color: #f5365c;
  color: #f5365c;
}
.gm-dock .bm-dock-row {
  align-items: stretch;
}

.gm-linkbtn {
  padding: 0;
  font-family: inherit;
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--bm-soft);
  background: none;
  border: 0;
  cursor: pointer;
}
.gm-linkbtn:hover {
  color: var(--bm-accent);
}
.gm-link-danger:hover {
  color: #f5365c;
}

/* ── the shape list ──────────────────────────────────────────────────────── */

.gm-count {
  display: inline-block;
  min-width: 1.15rem;
  padding: 0 5px;
  margin-left: 3px;
  font-size: 0.6rem;
  line-height: 1.15rem;
  text-align: center;
  color: #fff;
  background: var(--bm-accent);
  border-radius: 999px;
}

.gm-feature-list {
  /* Tall enough to work in, short enough to leave the tools and the export
     buttons reachable without scrolling the panel. */
  max-height: 40vh;
  padding: 0;
  margin: 0 0 6px;
  overflow-y: auto;
  list-style: none;
}
/* An empty <ul> still occupies its margin, which reads as a gap between the
   heading and the empty state that is explaining the gap. */
.gm-feature-list:empty {
  display: none;
}

.gm-feature {
  border-bottom: 1px dashed var(--bm-line);
}
.gm-feature:last-child {
  border-bottom: 0;
}

/* The whole row is the affordance: it opens the shape's settings. One target
   beats a row of small icon buttons at this width, and the settings popup is
   where zoom and delete now live. */
.gm-feature-open {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 7px 4px;
  font-family: inherit;
  text-align: left;
  background: none;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
}
.gm-feature-open:hover {
  background: var(--bm-panel-2);
}
.gm-feature.active .gm-feature-open {
  background: var(--bm-accent-soft);
}

/* Tinted with the shape's own colour, so the list doubles as the legend. */
.gm-feature-icon {
  flex: 0 0 auto;
  font-size: 18px;
}

.gm-feature-main {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  flex-direction: column;
}
.gm-feature-name {
  overflow: hidden;
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--bm-ink);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gm-feature-meta {
  font-size: 0.66rem;
  color: var(--bm-soft);
  font-variant-numeric: tabular-nums;
}
.gm-feature-chevron {
  flex: 0 0 auto;
  font-size: 17px;
  color: var(--bm-soft);
}

.gm-totals {
  font-size: 0.68rem;
  color: var(--bm-soft);
  font-variant-numeric: tabular-nums;
}
.gm-totals strong {
  color: var(--bm-ink);
}

/* ── status lines ────────────────────────────────────────────────────────── */

/* `note()` writes these. Empty by default, so the reserved space must collapse
   — a permanently blank line under every section reads as a layout bug. */
.gm-note:empty {
  display: none;
}
.gm-err {
  color: #f5365c;
}
.gm-ok {
  color: #2dce89;
}

/* ── narrow screens ──────────────────────────────────────────────────────── */

@media (max-width: 767.98px) {
  .gm-card {
    height: 78vh;
  }
  /* A column and a map cannot both be usable at phone width, so the panel takes
     the card and the map goes behind it. `PANEL_AUTO_OPEN_PX` in geo-map.js
     means the page still OPENS on the map; this is the state once the tab is
     tapped. */
  .gm-body {
    position: relative;
  }
  .gm-dock {
    position: absolute;
    inset: 0 0 0 auto;
    width: min(21rem, 100%);
    z-index: 600;
    box-shadow: var(--bm-shadow);
  }
}


/* ── the shape editor popup ──────────────────────────────────────────────── */

/* A floating, MOVEABLE dialog over the map — not a modal.
 *
 * There is no dark scrim and no click-outside-to-close: the whole point of a
 * dialog you can drag is that you keep working on the map while it is open, and
 * a scrim would make the map underneath both dimmed and unclickable. It closes
 * on its × or Escape. The layer below is only a positioning surface, so it lets
 * every click through and the popup takes them back. */
.gm-scrim {
  position: fixed;
  inset: 0;
  z-index: 1080; /* over Leaflet's controls (1000) and its own panes */
  pointer-events: none;
}
.gm-scrim.gm-hidden {
  display: none;
}

.gm-popup {
  position: absolute;
  /* Seeded by geo-map.js from the map's top-left corner, then owned by the drag.
     The fallback matters only for the first frame. */
  top: 1rem;
  left: 1rem;
  width: min(23rem, calc(100vw - 2rem));
  max-height: min(34rem, calc(100vh - 5rem));
  overflow: auto;
  pointer-events: auto;
  background: var(--bm-panel);
  color: var(--bm-ink);
  border: 1px solid var(--bm-line);
  border-radius: var(--bm-radius, 0.5rem);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.4);
}

/* The header is the drag handle. `cursor: move` on the bar but not on the name
   field or the close button — a text field you cannot click into because its
   parent is a drag handle is a genuinely maddening control. */
.gm-editor-head {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  background: var(--bm-panel);
  border-bottom: 1px solid var(--bm-line);
  cursor: move;
  user-select: none;
}
.gm-editor-head input,
.gm-editor-head button {
  cursor: auto;
  user-select: text;
}
.gm-editor-head button {
  cursor: pointer;
}
/* While dragging, stop the pointer picking up text or map tiles under it. */
.gm-dragging,
.gm-dragging * {
  user-select: none !important;
}
.gm-editor-icon {
  flex: 0 0 auto;
  font-size: 20px;
  color: var(--bm-accent);
}
/* The name is the dialog's title AND its first field — the thing you opened it
   to set, so it is focused on open rather than hidden behind a label. */
.gm-editor-name {
  flex: 1 1 auto;
  min-width: 0;
  padding: 4px 6px;
  font-family: inherit;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--bm-ink);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 5px;
}
.gm-editor-name:hover {
  border-color: var(--bm-line);
}
.gm-editor-name:focus {
  outline: none;
  background: var(--bm-panel-2);
  border-color: var(--bm-accent);
}
.gm-popup-close {
  flex: 0 0 auto;
  display: flex;
  padding: 2px;
  color: var(--bm-soft);
  background: none;
  border: 0;
  border-radius: 5px;
  cursor: pointer;
}
.gm-popup-close:hover {
  color: var(--bm-accent);
  background: var(--bm-accent-soft);
}

.gm-textarea {
  min-height: 4.5rem;
  resize: vertical;
}
/* An inline field's control should not take the whole row — the label is beside
   it, not above it. */
.gm-input-inline {
  width: auto;
  min-width: 7rem;
  margin-bottom: 0;
}

/* ── colour swatches ─────────────────────────────────────────────────────── */

/* A fixed palette, not a free colour picker: a drawing is read against
   satellite imagery and these are the hues that survive it. The list matches
   STYLE_COLOURS in apps/tools/domain/geo_map.py, which normalises an IMPORTED
   colour against the same set — offer one here that is missing there and it is
   silently rewritten on the round trip. */
.gm-swatches {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 5px;
  margin-bottom: 10px;
}
.gm-swatch {
  aspect-ratio: 1;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 50%;
  cursor: pointer;
  /* The ring makes white and near-white swatches visible on a light panel. */
  box-shadow: inset 0 0 0 1px var(--bm-line);
  transition: transform 0.1s, border-color 0.1s;
}
.gm-swatch:hover {
  transform: scale(1.12);
}
.gm-swatch.active {
  border-color: var(--bm-ink);
}

/* ── on-map shape labels ─────────────────────────────────────────────────── */

/* Same treatment as the borehole labels in css/map/main.css (`.label-icon`):
   white text with a black halo and no bubble. A default Leaflet tooltip is a
   white box with an arrow — over satellite imagery that is a second object
   competing with the shape it names, and next to a circle marker it read as a
   popup that would not close. */
.leaflet-tooltip.gm-label {
  padding: 0;
  margin: 0;
  color: #fff;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
  background: none;
  border: 0;
  box-shadow: none;
  text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000,
    -1.5px 0 0 #000, 1.5px 0 0 #000, 0 -1.5px 0 #000, 0 1.5px 0 #000;
}
/* Leaflet draws the bubble's arrow as a pseudo-element on the tooltip. */
.leaflet-tooltip.gm-label::before,
.leaflet-tooltip.gm-label::after {
  display: none !important;
}

/* The divIcon wrapper must not paint anything of its own around the SVG. */
.gm-dot {
  background: none;
  border: 0;
}

/* ── the page background behind the map ─────────────────────────────────── */

/* The card no longer scrolls with the page, so its own body must not either:
   the panel scrolls, the map does not. */
.gm-card > .card-body {
  overflow: hidden;
}
