/* ═════════════════════════════════════════════════════════════════════════
   MOBILE-FIRST POPUPS
   Loaded LAST (after style.css, auth_popup.css and measure.css) so it wins
   on source order without needing !important on geometry. Everything in
   here is one of three promises:

     1. NOTHING THE SIDEBAR CAN BLOCK
        Every popup, panel, bar, sheet, dropdown, modal scrim and toast
        starts at --popup_left_margin (48px, the width of #left_nav_sidebar).
        Three families were still landing under the column before this file:
        the measurement panel and feature profile (measure.css forces
        left:0/width:100vw at its own "no 48px squeeze on mobile" rule), the
        four modal scrims (left:0/right:0), and the toast strip (centred on
        the whole viewport). They are all pulled onto the same rail here.

     2. THE MAP IS ALWAYS VISIBLE
        Base rules - which is to say the PHONE rules, this file being
        mobile-first - cap every docked popup at --popup_max_height (45svh)
        and anchor it to the top bar. Whatever the panel cannot show, its
        own content area scrolls; the bottom half of the screen stays map.
        Desktop opts back into full-height panels at the bottom of the file,
        so nothing changes on a large screen.

     3. EVERY POPUP COLLAPSES
        popup_mobile.js puts a chevron in each popup's top-right chrome cell
        (next to the close button) that toggles .state_popup_collapsed. A
        collapsed popup is exactly one 48px cell - its header row - so a
        panel can be pushed out of the way to read the map under it without
        losing its state, and re-opened from the same cell.

   The two numbers this file measures from are style.css's own rails:
   --top_bar_height and --left_sidebar_width, both 48px.
   ═════════════════════════════════════════════════════════════════════════ */

:root {
  /* The clear column down the left. Same 48px as the sidebar it clears,
     but named separately: a popup's left margin is a statement about the
     popup, and reading --left_sidebar_width in a popup rule would silently
     glue the two together if the column were ever resized to something a
     popup should not inherit. */
  --popup_left_margin: 48px;

  /* the right rail (fullscreen toggle / mini map / altitude scale) - popups
     stop short of it at every viewport width, so those controls are never
     covered and never have to be dug out from under a panel */
  --popup_right_margin: 48px;

  /* one cell: the height of a popup header, and of a collapsed popup */
  --popup_header_cell: 48px;

  /* Mobile default. 45% of the small viewport height leaves the bottom
     ~55% of a phone screen as map, INCLUDING the browser chrome's worst
     case (svh = the viewport with the URL bar showing, so a panel sized
     against it never grows past the fold when the bar retracts). */
  --popup_max_height: 45vh;

  /* the popup column: the full width between the two rails, never wider
     than the 610px the rest of the chrome is built on */
  --popup_column_width: min(
    610px,
    calc(100vw - var(--popup_left_margin) - var(--popup_right_margin))
  );
}
@supports (height: 1svh) {
  :root {
    --popup_max_height: 45svh;
  }
}


/* ── 1. The 48px left margin, on everything that floats ───────────────────
   One list, one rail. Anything that can appear over the map and is not
   drawn ON the map (markers, their rings, the crosshair) is in it. */
.side-panel,
.sliding_menu,
.control_panel,
.view_controls_panel,
.overlay_panel,
.filemanager_panel,
.search_popup,
.cs_feature_profile_popup,
.cs_panel_container_expandable,
.cs_input_bar,
.bottom_popup_container,
.footer_nav_bar,
.marker_direction_nav_bar,
.marker_travel_panel,
.cs_toolbar_controls_container {
  left: var(--popup_left_margin);
  right: auto;
  width: var(--popup_column_width);
  min-width: 0;
  max-width: var(--popup_column_width);
  /* measure.css centres its two panels with `margin-left:auto` inside a
     left:0/right:0 box; with a real left edge that would push them back off
     the rail */
  margin-left: 0;
  margin-right: 0;
}

/* the two that were centred with a transform rather than with offsets - the
   transform has to go or they would sit 50% of their own width to the left
   of the rail. The sliding menus are deliberately NOT in here: their
   transform is how they open and close. */
.marker_travel_panel,
.toast-container {
  transform: none;
}
.toast-container {
  /* was left:50% of the whole viewport, so on a phone the toast reached back
     over the sidebar. Now it spans the map area and centres its single toast
     inside that, which is where the user is already looking. */
  left: var(--popup_left_margin);
  right: 0;
  width: auto;
  max-width: none;
  justify-content: center;
}

/* Closed sliding menus hide outright rather than only sitting off-screen.
   A menu hides by translating up by its own height plus the bar, which lands
   its bottom edge exactly on y:0 - and with the height cap above that height
   is now fractional (45svh of an 844px screen is 379.797px), which leaves the
   compositor a sub-pixel row of the last menu item painted over the top bar.
   Visibility removes it without touching the transform the open/close
   animation rides on; the delay on the way out lets that animation play out
   before the panel disappears. */
.sliding_menu {
  visibility: hidden;
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease,
    visibility 0s linear 0.3s;
}
.sliding_menu.open {
  visibility: visible;
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease,
    visibility 0s linear 0s;
}

/* Modal scrims. Dimming the sidebar as well as the map made the column look
   disabled while a modal was up (it is not - the modal is dismissible and
   the tools underneath still work the moment it closes), and put the dialog
   itself, which is centred in the scrim, 24px left of where the map's centre
   actually is. Both fixed by starting the scrim at the same rail. */
.filemanager_modal_overlay,
.overlay_export_modal,
.cs_qr_share_modal,
.auth_modal_overlay,
.menu_overlay {
  left: var(--popup_left_margin);
  right: 0;
  top: var(--top_bar_height);
  bottom: 0;
}

/* the dialogs inside those scrims: never wider than the map area, and never
   taller than it either - the body scrolls instead of the dialog running off
   the bottom of a short phone screen */
.filemanager_modal,
.cs_qr_share_modal_content,
.auth_modal {
  max-width: calc(
    100vw - var(--popup_left_margin) - var(--popup_right_margin)
  ) !important;
  max-height: calc(100svh - var(--top_bar_height) - var(--popup_header_cell));
  overflow-y: auto;
}

/* the account dropdown is placed from JS (positionUserDropdown in
   auth_system.js, which floors its left at this same rail); this is the
   resting value it carries before that runs, and the width cap that keeps it
   inside the map area on a narrow screen */
.user_dropdown {
  left: var(--popup_left_margin);
  max-width: calc(
    100vw - var(--popup_left_margin) - var(--popup_right_margin)
  );
}

/* maplibre's own feature popups are anchored to a map coordinate, so no
   left rule can hold them off the column - popup_mobile.js nudges the map
   when one opens near it. This is the size half of the same job: a popup
   that cannot be wider than the map area cannot reach the rail from the
   other side either. */
.maplibregl-popup {
  max-width: calc(
    100vw - var(--popup_left_margin) - var(--popup_right_margin)
  ) !important;
}
.maplibregl-popup .maplibregl-popup-content {
  max-width: 100%;
  /* vh first as the fallback, svh for browsers that have it - a popup with a
     long feature list scrolls inside itself rather than covering the map */
  max-height: 45vh;
  max-height: 45svh;
  overflow-y: auto;
}


/* ── 2. Vertical budget: the map stays on screen ──────────────────────────
   Top-anchored under the bar, height driven by content, capped at 45svh.
   The EDGE PASS block at the end of style.css had run these from the navbar
   all the way down to the bottom rails (`bottom: var(--content_bottom_inset)`
   with `max-height: none`), which on a phone is the entire screen: opening
   Map Layers or Files left no map visible at all.

   Nothing here needs a scroll container of its own - every one of these
   panels is already a flex column whose content child carries
   `flex:1; overflow-y:auto`, so capping the container is all it takes for
   the content to become scrollable inside it. */
.side-panel,
.sliding_menu,
.control_panel,
.view_controls_panel,
.overlay_panel,
.filemanager_panel,
.search_popup,
.cs_feature_profile_popup,
.cs_panel_container_expandable,
.marker_travel_panel {
  top: var(--top_bar_height);
  bottom: auto;
  height: auto;
  max-height: var(--popup_max_height);
  overflow: hidden;
}

/* the inner scrollers that carry their own vh caps stop competing with the
   panel's cap - the panel is the one thing that decides how tall it is, and
   these just fill it */
#basemap-scrollable-container,
#layers-scrollable-container,
#features-scrollable-container,
.panel-content,
.overlay_panel_content,
.filemanager_panel_content,
.view_controls_content.active,
.sliding_menu_content,
.cs_panel_content_scrollable {
  max-height: none;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* the bottom strip keeps its 3 cells but never more, however many cards are
   in it - it sits on the footer bar, at the end of the thumb's reach, and is
   the one popup a phone user is most likely to have open alongside another */
.bottom_popup_container {
  max-height: var(--bottom_popup_strip_open_height, 144px);
}


/* ── 3. Collapsible: every popup shrinks to one cell ──────────────────────
   .state_popup_collapsed is set by the chevron popup_mobile.js adds, and by
   the header-click handler in script.js (setupPopupHeaderCollapse). The rule
   is deliberately structural rather than a list of panel-specific selectors:
   every popup in this app is built header-first, so "keep the first child,
   drop the rest" collapses all of them, including the ones built at runtime.

   The two chrome buttons are excluded from the hiding: in a popup with no
   header to put them in they are appended to the popup itself and floated
   into its top-right cell, so without the exclusion collapsing that popup
   would hide the very control that un-collapses it. Where they DO sit in a
   header they are inside the first child already, and the exclusion is
   simply redundant rather than wrong. */
.state_popup_collapsed {
  max-height: var(--popup_header_cell) !important;
  min-height: 0 !important;
  overflow: hidden !important;
}
.state_popup_collapsed
  > *:not(:first-child):not(.cs_popup_close_btn):not(.cs_popup_collapse_btn) {
  display: none !important;
}
.state_popup_collapsed > *:first-child {
  max-height: var(--popup_header_cell);
}

/* measure.js's own collapsed state gets the same one-cell treatment, so a
   collapsed measurement panel and a collapsed Map Layers are the same
   height and read as one row of stacked headers */
.cs_panel_container_expandable.state_collapsed,
.cs_feature_profile_popup.state_collapsed {
  max-height: var(--popup_header_cell) !important;
}

/* The chevron itself. Same 48px cell, same fill and same hover as
   .cs_popup_close_btn in style.css, because it is the other half of the same
   two-cell chrome group in the popup's top-right corner. */
.cs_popup_collapse_btn {
  width: var(--popup_header_cell);
  height: var(--popup_header_cell);
  min-width: var(--popup_header_cell);
  max-width: var(--popup_header_cell);
  min-height: var(--popup_header_cell);
  max-height: var(--popup_header_cell);
  flex: 0 0 var(--popup_header_cell);
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(6, 6, 6, 0.88);
  color: var(--text-color, #fff);
  border: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}
.cs_popup_collapse_btn i {
  font-size: 16px;
  line-height: 1;
  margin: 0;
  transition: transform 0.15s ease;
}
.cs_popup_collapse_btn:hover {
  background-color: rgba(255, 255, 255, 0.15);
}
/* collapsed: the chevron points the other way, so the control says what the
   next tap does rather than what state the panel is in */
.state_popup_collapsed .cs_popup_collapse_btn i {
  transform: rotate(180deg);
}

/* A header that hosts a chrome cell is exactly one cell tall and runs to the
   panel's own right edge. Two things had to give for that: the overlay and
   file-manager headers carried 12px of vertical padding (a 48px button inside
   them made the row 72px), and .panel-header carried 48px of right padding
   left over from when a floating close button had to be kept off its title -
   which now shows as a gap between the chevron and the close control rather
   than as clearance. */
.panel-header,
.view_controls_header,
.overlay_panel_header,
.filemanager_panel_header,
.sliding_menu_header {
  height: var(--popup_header_cell);
  min-height: var(--popup_header_cell);
  max-height: var(--popup_header_cell);
  padding-top: 0;
  padding-bottom: 0;
  padding-right: 0;
  box-sizing: border-box;
}
/* the chrome group sits in the corner: the auto margin takes all the free
   space in the header, so the chevron and whatever follows it are flush
   right whether the header distributes its children with space-between
   (the side panels) or packs them left (the sliding menus) */
.cs_popup_collapse_btn {
  margin-left: auto;
}
.cs_popup_collapse_btn_floating {
  margin-left: 0;
}
/* the cell to the left of a close control that is pinned to the header's
   right edge rather than sitting in its flow */
.cs_popup_collapse_btn_clear_of_close {
  margin-right: var(--popup_header_cell);
}

/* Popups with no header row to sit in get it floated into the same corner
   the close button uses; when both are there the chevron takes the cell one
   to the left, so they never stack on top of each other. */
.cs_popup_collapse_btn_floating {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 6;
}
.cs_popup_collapse_btn_floating.cs_popup_collapse_btn_beside_close,
/* the same fact stated structurally, so the two cells never land on top of
   each other in the window between this file adding its chevron and
   script.js's observer adding the close button next to it */
.js_popup_has_floating_chrome:has(> .cs_popup_close_btn)
  > .cs_popup_collapse_btn_floating {
  right: var(--popup_header_cell);
}
/* a header now ends where the chrome cells begin, so a long title runs into
   an ellipsis instead of under the buttons */
.js_popup_has_floating_chrome > *:first-child {
  padding-right: calc(var(--popup_header_cell) * 2);
  box-sizing: border-box;
}


/* ── 4. Phone density ─────────────────────────────────────────────────────
   Everything above is geometry; this is the content inside it. The touch
   targets stay 48px - a phone is exactly where they should not shrink - so
   what gets removed is stacking, not size: rows that were laid out one per
   line become one row where they can be. */
@media (max-width: 768px) {
  /* View Controls was the worst of these: each of Zoom / Tilt / Rotation
     stacked label, input row, Set and Reset as four full-width 48px rows
     (196px per control, 588px for the three - taller than the phone screen
     they were on). Set and Reset are a pair and belong on one row, which
     takes the block to 144px and fits all three controls in the panel. */
  .vc_control_block {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }
  .vc_block_label,
  .vc_input_row {
    grid-column: 1 / -1;
  }

  /* the movement/tilt pads are square grids of arrows; their title row does
     not need the same 48px cell a dismissible panel header needs */
  .control_panel_title {
    height: var(--popup_header_cell);
    min-height: 0;
    display: flex;
    align-items: center;
    padding: 0 12px;
    box-sizing: border-box;
  }
}

@media (max-width: 480px) {
  /* Basemap cards: thumbnail + name is enough to pick one on a phone. The
     two-line description under each was adding ~34px to every card in a
     three-column grid, which is a full extra row of cards' worth of height
     per two rows shown. */
  .basemap-description {
    display: none;
  }
  /* the tab strips keep their 48px height but drop the labels' second line
     rather than wrapping to 96px */
  .panel-tab span,
  .view_controls_tab span,
  .filemanager_panel_tab span {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* Landscape phones: the screen is short, so the same 45% is far less useful
   than it is in portrait, and there is map either side of the 610px column
   anyway. A bit more height, still never the whole screen. */
@media (max-height: 500px) {
  :root {
    --popup_max_height: 62vh;
  }
  @supports (height: 1svh) {
    :root {
      --popup_max_height: 62svh;
    }
  }
}


/* ── 5. Desktop opts back into full-height panels ─────────────────────────
   Last block in the file, and the only one keyed to a large screen: on a
   real display there is room for the panel to run from the navbar down to
   the bottom rails the way it did before, and the 45svh cap would just make
   the panel scroll for no reason. Everything else above - the left margin,
   the collapse chevron, the modal geometry - applies at every width. */
@media (min-width: 768px) and (min-height: 640px) {
  :root {
    --popup_max_height: calc(
      100vh - var(--top_bar_height) - var(--content_bottom_inset, 48px)
    );
  }
}
