/* Copyright (c) 2026 Goldeneye Technologies LLC. All rights reserved. */
/**************************************************************************/
/********     Content classes: Map      ***********************************/
/**************************************************************************/
#map_container {float: left;}

/* Map-page flash overlay (map.html overrides the base `flash_messages` block).
   The map column is a fixed-height float, so an in-flow flash banner would push
   it down and break Leaflet's initial sizing. Float the flash over the map
   instead — anchored to #content_main (position: relative via .main_pinned /
   .main_unpinned), above Leaflet panes/controls.

   `top` used to clear the 90px-tall #leaderboard_ad band; the ad inventory was
   removed on 2026-07-25 (S6), so the banner now sits a plain gutter below the
   top of the map. The desktop search bar lives at the BOTTOM of the map, so
   nothing else competes for this space.
   <JAS 2026-06-13, re-anchored 2026-07-25> */
.flash-overlay {
  /* position:fixed (was absolute) — viewport-relative so it can't be distorted
     by an ambiguous positioned-ancestor containing block (the same issue that
     mis-sized the campaign banner, e.g. the admin-logout flash). The map page
     doesn't scroll on desktop, so fixed and absolute frame identically here;
     fixed just makes the placement robust. <JAS 2026-06-26> */
  position: fixed;
  top: var(--space-3);
  left: 50%;
  transform: translateX(-50%);
  z-index: 1100;
  width: 100%;
  max-width: min(560px, calc(100vw - 2 * var(--space-4)));
  pointer-events: none; /* let map interactions through the empty gutter */
}
.flash-overlay .flash-region {margin-top: 0;}
.flash-overlay .flash {
  pointer-events: auto; /* but the banner itself stays interactive */
  box-shadow: var(--shadow-md);
}
/* Persistent social-campaign banner (modules/notice.js::campaign_banner). A
   self-contained fixed bar (NOT routed through .flash-overlay) so its size is
   predictable on every viewport. Desktop: a compact pill centered at the top of
   the map (it used to sit below the leaderboard band, removed with the ad
   inventory on 2026-07-25); mobile: a full-width strip below the search bar
   (overrides at the breakpoint). <JAS 2026-06-26, re-anchored 2026-07-25> */
.campaign-banner {
  position: fixed;
  top: var(--space-3);
  left: 50%;
  transform: translateX(-50%);
  /* 1350, the transient-notice band it shares with `.flash-overlay`. It was
     1400 while #content_main trapped it at 0 — i.e. it read as 1400 but painted
     under the drawer. Dropping it to 1350 preserves exactly that behaviour now
     that the number is honest. <JAS 2026-08-21> */
  z-index: 1350;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  max-width: min(560px, calc(100vw - 2 * var(--space-4)));
  margin: 0;
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-3);
  background: var(--color-accent);          /* Tickerscape brand teal */
  color: var(--color-text-inverse);         /* white-on-accent = AA 6.2:1 */
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  font-size: var(--font-size-sm);
  line-height: 1.4;
}
.campaign-banner-text {flex: 1 1 auto;}
.campaign-banner-close {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border: none;
  background: transparent;
  color: inherit;
  font-size: var(--font-size-lg);
  line-height: 1;
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.campaign-banner-close:hover {background: rgba(255, 255, 255, 0.18);}

/* Transient flash toast: the runtime notices (modules/notice.js::flash_notice,
   e.g. the selection cap) and the re-homed server flash (flash.js, e.g. the
   logout message). Same self-contained fixed treatment as .campaign-banner so
   they're sized consistently; colour comes from the .flash--{info|error|success}
   modifier (global.css) — the bare category token would collide with the .info
   panel layout class and stretch this to full viewport height. <JAS 2026-06-26> */
.flash-toast {
  position: fixed;
  top: calc(90px + var(--space-3));
  left: 50%;
  transform: translateX(-50%);
  /* Above the modal overlays (chart / data table / shortcuts all sit at 2000).
     A toast is an answer to something the user just did, so it has to be visible
     from whatever surface fired it — at 1400 the data-table "added" confirmation
     rendered behind the table. <JAS 2026-07-25> */
  z-index: 2100;
  width: max-content;
  max-width: min(560px, calc(100vw - 2 * var(--space-4)));
  margin: 0;
  box-shadow: var(--shadow-md);
}

#tooltip {
  position: absolute;
  background-color: var(--color-text);
  color: var(--color-text-inverse);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-sm);
  box-shadow: var(--shadow-sm);
  display: none; /* Hidden by default */
  pointer-events: none; /* Prevent interference with mouse events */
  z-index: 1000;
}
.map {
    height: 100%;
    width: 75%;
    box-sizing: border-box;
    /* Containing block for the absolutely-positioned `.map-search` bar so its
       percentage geometry resolves against the map column (not the full content
       width) — keeps it centered over the map and tracking the width transition
       below when `info_collapsed_layout` grows .map 75% -> 90%. The Leaflet
       instance lives in the sibling #map div, unaffected. */
    position: relative;
    transition: width var(--transition-base);
}

/* When `#info_button` collapses the info panel, the map grows to fill the
   freed column. The info panel becomes `position: absolute` (see
   `content_infoPanel.css`) so its hover-expand overlays the map rather
   than pushing it back. */
#content_main.info_collapsed_layout .map {
    width: 90%;
}
.map_unpinned {
  position: relative;
  /* left: 2.5%; */
  width: 95%;
  height: 100%;
  z-index: 0;
  transition: 0.5s;
}

/* NOTE: This is not quite correct, but works for development.
   <JAS 2025-06-13>
*/
/* .map_pinned {left: 10%; width: 65%;} */
.map_pinned {width: 65%;}

/* Search bar wrapper (lifted from inline `style="..."` on #map_search
   in map.html per Q3). */
.map-search {
  position: absolute;
  width: 50%;
  height: 5%;
  /* `z-index: auto`, NOT a number, and that is load-bearing: the input and its
     suggestion dropdown need to sit on OPPOSITE sides of the info panel, which
     is impossible if this wrapper forms a stacking context that traps them
     together. Positioned + auto does not form one, so the two children below
     compete in the page's own context. <JAS 2026-08-21> */
  z-index: auto;
  bottom: 0;
  left: 25%;
}
.map-search #search_input {
  /* `position: relative` purely so the z-index applies (no offsets, so nothing
     moves). Below the info panel (1200) per the layer scale: on a landscape
     phone the panel's left edge cuts across this bar, and the panel should win
     there. <JAS 2026-08-21> */
  position: relative;
  z-index: 1150;
  width: 100%;
  height: 100%;
  padding: 0 var(--space-3);
  box-sizing: border-box;
  font: inherit;
  color: var(--color-text);
  background-color: var(--color-bg-elevated);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  transition: border-color var(--transition-base), box-shadow var(--transition-base);
}
.map-search #search_input:focus {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px var(--color-focus-ring);
}
.map-search #search_input:focus:not(:focus-visible) {
  outline: none;
}

/* Symbol hover tooltip (button_info active) — merged symbol + location info
   built by map/control_buttons.js::marker_tooltip_el. Overrides Leaflet's
   default single-line white tooltip: dark elevated surface, left-aligned,
   wraps multi-line addresses. <JAS 2026-05-27> */
.leaflet-tooltip.symbol_tooltip {
  white-space: normal;
  width: max-content;
  max-width: 240px;
  padding: var(--space-2) var(--space-3);
  background-color: var(--color-bg-elevated);
  color: var(--color-text);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  font-size: var(--font-size-xs);
  line-height: var(--line-height-base);
  text-align: left;
}
/* Recolor Leaflet's pointer triangle (drawn via ::before with border colors)
   to match the dark surface for the default 'top' direction. */
.leaflet-tooltip.symbol_tooltip.leaflet-tooltip-top::before {
  border-top-color: var(--color-border);
}
.symbol_tooltip_head {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}
.symbol_tooltip_ticker {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
}
.symbol_tooltip_exchange {color: var(--color-text-muted);}
.symbol_tooltip_company {
  color: var(--color-text-muted);
  margin-bottom: var(--space-1);
}
/* Sector line (A7): the marker's own non-colour decode channel, so it reads at
   full text colour rather than muted like the company line. */
.symbol_tooltip_sector {
  margin-bottom: var(--space-1);
}
.symbol_tooltip_quote {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}
.symbol_tooltip_price {
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-semibold);
}
.symbol_tooltip_status,
.symbol_tooltip_meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  color: var(--color-text-muted);
}
.symbol_tooltip_divider {
  border-top: 1px solid var(--color-border);
  margin: var(--space-1) 0;
}
.symbol_tooltip_title {font-weight: var(--font-weight-medium);}
.symbol_tooltip_address {color: var(--color-text-muted);}

/* For highlighting point */
/* NOTE: Maybe performance will improve with when removing list of points.*/
/* <JAS 2025-06-11> */
.highlight-point {
    animation: highlight 2s ease-out infinite;
    transform-origin: center;
    transform-box: content-box;
}

.no-highlight-point {opacity: 0}

@keyframes highlight {
    0% { transform: scale(1); }
    65% { transform: scale(3); opacity: 0; }
    100% { transform: scale(3); opacity: 0; }
}

.custom-menu {
  position: absolute;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-1) 0;
  box-shadow: var(--shadow-md);
  z-index: 1000;
  font-size: var(--font-size-sm);
}
.custom-menu li {
  list-style: none;
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  color: var(--color-text);
  transition: background-color var(--transition-base);
}
.custom-menu li:hover {
  background: var(--color-bg-hover);
}
/* Same overflow issue as the sort dropdown — inset the keyboard focus
   ring so it sits inside each entry instead of spilling past the menu's
   container border. */
.custom-menu li:focus-visible {
  outline-offset: -3px;
}

/* Leaflet toolbar icon buttons (mounted by static/js/map/control_buttons.js
   into Leaflet's standard .leaflet-control-zoom containers). Restyled
   for cohesion with the info-panel header icon buttons. */
.leaflet-control-zoom button {
  background-color: var(--color-bg-elevated);
  border: 0;
  width: 100%;
  height: 100%;
  padding: 4px;
  cursor: pointer;
  color: var(--color-text-muted);
  font: inherit;
  font-size: var(--font-size-sm);
  transition: background-color var(--transition-base), color var(--transition-base);
}
.leaflet-control-zoom button:hover {
  background-color: var(--color-bg-hover);
  color: var(--color-text);
}
.leaflet-control-zoom button.active {
  background-color: var(--color-bg-hover);
  color: var(--color-accent);
}
/* Hairline separators between stacked toolbar buttons, mirroring Leaflet's own
   zoom-control bar (which has them by default) — gives the icon buttons visual
   breathing room so the stack doesn't read as one cramped block. <JAS 2026-06-12> */
.leaflet-control-zoom > div + div {
  border-top: 1px solid var(--color-border);
}
/* Keyboard focus: inset the ring so it stays inside each button instead of
   being painted over by the (later-in-DOM) button stacked flush below it — the
   bottom of the default +2px-offset ring was clipped on every non-last toolbar
   button. Mirrors the .custom-menu / #infoPanel inset pattern. <JAS 2026-06-12> */
.leaflet-control-zoom button:focus-visible {
  outline-offset: -2px;
}

/* Desktop toolbar density (2026-07-16). The added viewport-select + cursor-mode
   buttons pushed the top-right stack (Leaflet zoom + four custom bars, ~26 cells)
   past the map height on shorter desktop viewports. Pin each custom cell to a
   compact 26px square (the JS sizes cells via a fragile width:100% ↔ aspect-ratio
   loop; pin the BAR width + cell HEIGHT the same way the mobile block does, so it
   resolves deterministically) and tighten the vertical gap between the stacked
   bars, so the whole column fits without scrolling. The mobile @media rules below
   (44px touch squares) have equal specificity but come later, so they still win
   at <=768px; the .map-toolbar-scroll fallback still catches very short desktop
   viewports. <JAS 2026-07-16> */
.leaflet-top.leaflet-right [data-toolbar-group] {
  width: 26px;
}
.leaflet-top.leaflet-right [data-toolbar-group] > div {
  height: 26px;
  aspect-ratio: auto;
}
.leaflet-top.leaflet-right [data-toolbar-group] > div > button {
  height: 26px;
}
.leaflet-top.leaflet-right .leaflet-control-zoom a {
  width: 26px;
  height: 26px;
  line-height: 26px;
}
/* Tighten the gap between the stacked controls (Leaflet's default is ~10px). */
.leaflet-top.leaflet-right .leaflet-control {
  margin-top: 4px;
}
/* Period buttons are the only TEXT toolbar buttons (1D … Max). The 3-character
   labels (YTD, Max) overflow the compact 26px cell at the default sm font-size,
   so drop them to xs and trim the side padding to give the text room. Icon-only
   buttons are unaffected. <JAS 2026-07-16> */
[data-toolbar-group="period"] button {
  font-size: var(--font-size-xs);
  padding-left: 1px;
  padding-right: 1px;
}

/* Short-height toolbar resilience (handoff Item 3, paired with the
   .map-toolbar-scroll wrapper built in map/control_buttons.js). The stacked
   top-right column (Leaflet zoom + four custom bars) can exceed the map height
   on a short viewport (e.g. 1060x750) and drop the lowest period buttons
   off-screen — a short-HEIGHT desktop bug that fires above Lane E's
   max-width:768px mobile breakpoint. Give the corner a definite height so the
   wrapper's percentage max-height resolves, then cap + scroll the wrapper. The
   corner keeps Leaflet's pointer-events:none (map stays draggable around the
   toolbar); the wrapper re-enables pointer events for its own scrolling.
   <JAS 2026-06-22> */
.leaflet-top.leaflet-right {
  height: 100%;
}
.map-toolbar-scroll {
  pointer-events: auto;
  /* Leave a little breathing room above the bottom map edge / search bar. */
  max-height: calc(100% - var(--space-3));
  overflow-y: auto;
  overflow-x: hidden;
}
/* Thin, unobtrusive scrollbar so the (rare, short-viewport-only) overflow bar
   doesn't read as a chunky OS scrollbar painted over the map — mirrors the
   light-surface treatment used elsewhere. */
.map-toolbar-scroll::-webkit-scrollbar {
  width: 6px;
}
.map-toolbar-scroll::-webkit-scrollbar-thumb {
  background: rgba(60, 60, 60, 0.4);
  border-radius: var(--radius-sm);
}
.map-toolbar-scroll::-webkit-scrollbar-thumb:hover {
  background: rgba(60, 60, 60, 0.6);
}

/* Mobile "more tools" toggle (Lane E / Prompt 3, built in
   map/control_buttons.js). Hidden off mobile; the @media block below reveals it.
   Lives top-right, above the (pushed-down) Leaflet control stack. 44x44 meets
   the WCAG 2.5.5 touch-target minimum. <JAS 2026-06-22> */
.map-more-tools {
  display: none;
  position: fixed;
  top: 8px;
  right: 8px;
  width: 44px;
  height: 44px;
  z-index: 1100;
  align-items: center;
  justify-content: center;
  background: var(--color-bg-elevated);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: background-color var(--transition-base), color var(--transition-base);
}
.map-more-tools:hover {
  background: var(--color-bg-hover);
  color: var(--color-text);
}
.map-more-tools svg {
  display: block;
  width: 22px;
  height: 22px;
}

/* Erase tool (map/draw_tool.js): while the erase mode is engaged, drawn shapes
   carry .shape_erasable so the cursor signals they are clickable to delete. */
.leaflet-interactive.shape_erasable {
  cursor: pointer;
}

/* While a map tool is engaged, the default Leaflet grab/hand cursor is
   misleading — the map isn't there to be panned, it's there to be clicked. Two
   affordances, toggled on the map container by the map/*_tool.js files:
   - crosshair for point-placement tools (box/lasso selection, draw, marker) —
     a centered hotspot that doesn't obscure the exact click point;
   - pointer for erase (draw_tool.js) — you click a whole shape, not a point,
     matching the .shape_erasable pointer above.
   Specificity clears .leaflet-grab (idle) and .leaflet-dragging .leaflet-grab
   (grabbing during a pan). <JAS 2026-07-01> */
.leaflet-container.map-tool-crosshair,
.leaflet-dragging .leaflet-container.map-tool-crosshair.leaflet-grab {
  cursor: crosshair;
}
.leaflet-container.map-tool-cursor,
.leaflet-dragging .leaflet-container.map-tool-cursor.leaflet-grab {
  cursor: pointer;
}

/* Keyboard cursor mode (map/cursor_mode.js): the visible virtual crosshair a
   keyboard user drives with the arrow keys. Fixed-positioned by JS to the
   crosshair's client coords (the map page doesn't scroll), centered on that
   point via translate(-50%,-50%). Brand-teal cross with a white halo so it
   stays legible over any basemap tile. pointer-events:none so it never eats a
   click. Sits above the map/markers but below the modals (z 2000). Desktop-only
   — the button that toggles it is hidden on mobile (see the @media block).
   <JAS 2026-07-16> */
.map-cursor-crosshair {
  position: fixed;
  z-index: 1100;
  width: 30px;
  height: 30px;
  pointer-events: none;
  transform: translate(-50%, -50%);
}
.map-cursor-crosshair::before,
.map-cursor-crosshair::after {
  content: "";
  position: absolute;
  background: var(--color-accent);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.9);
}
.map-cursor-crosshair::before {   /* horizontal arm */
  top: 50%;
  left: 0;
  right: 0;
  height: 2px;
  transform: translateY(-50%);
}
.map-cursor-crosshair::after {    /* vertical arm */
  left: 50%;
  top: 0;
  bottom: 0;
  width: 2px;
  transform: translateX(-50%);
}

/* Reference marker (map/marker_tool.js): a divIcon whose pin glyph strokes in
   currentColor — tint it to the brand teal so dropped markers match the draw +
   selection tools (replacing Leaflet's default blue teardrop). The custom
   className suppresses the default .leaflet-div-icon white box. */
.reference-marker-icon {
  color: var(--color-accent);
  background: none;
  border: none;
}
.reference-marker-icon svg {
  display: block;
}

/* Search bar — Google-style suggestion cards stacked above the input. */
#search_suggestions {
  /* ABOVE the info panel (1200), unlike the input that opens it. A dropdown
     that is clipped by the panel is unusable — at the full snap in portrait the
     list would have ~40px of visible height — so the panel yields to it for as
     long as it is open. Still below the nav backdrop (1399), so opening the
     drawer dims it like everything else. <JAS 2026-08-21> */
  z-index: 1250;
  display: none;
  position: absolute;
  bottom: 100%;
  left: 0;
  right: 0;
  margin-bottom: var(--space-1);
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  max-height: 240px;
  overflow-y: auto;
}
.search-suggestion {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--color-border);
  font: inherit;
  font-size: var(--font-size-sm);
  text-align: left;
  color: var(--color-text);
  cursor: pointer;
  transition: background-color var(--transition-base);
}
.search-suggestion:last-child {border-bottom: 0;}
.search-suggestion:hover,
.search-suggestion[data-active="true"] {background: var(--color-bg-hover);}
.search-suggestion[data-active="true"] {color: var(--color-accent);}
.search-suggestion-label {
  flex: 1 1 auto;
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  overflow: hidden;
  white-space: nowrap;
}
.search-suggestion-symbol {
  flex: 0 0 auto;
  font-weight: var(--font-weight-semibold);
}
.search-suggestion-name {
  flex: 0 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--color-text-muted);
}
.search-suggestion[data-active="true"] .search-suggestion-name {
  color: inherit;
}
.search-suggestion-badge {
  flex: 0 0 auto;
  font-size: 10px;
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.5px;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  color: var(--color-text-inverse);
}
.search-suggestion-badge-ticker {background: var(--color-accent);}
.search-suggestion-badge-name {background: var(--color-text-muted);}

/* ----------------------------------------- */
/* Mobile viewport (≤ 768 CSS px wide). The map fills the viewport behind the
   bottom-sheet info panel (content_infoPanel.css). The four-bar custom toolbar
   collapses behind the "more tools" toggle (Prompt 3); the side-nav becomes a
   hamburger drawer (content_sideNav.css). <JAS 2026-06-22> */
/* ----------------------------------------- */
@media (max-width: 768px),
       (orientation: landscape) and (max-height: 500px) and (pointer: coarse) {
    .map {
        /* Override the desktop 75% float split: the map is the full viewport,
           the info panel floats over it as a fixed bottom sheet. */
        width: 100vw !important;
        height: 100vh !important;
        height: 100dvh !important;   /* visible viewport on iOS — keeps the legend
                                        + bottom controls above Safari's chrome */
        float: none;
        /* `position: absolute` (anchored to the relatively-positioned, full-
           viewport #content_main), NOT `position: fixed`. `position: fixed`
           ALWAYS forms a stacking context, which trapped the search bar
           (#map_search, a child of this element) below the bottom sheet: bumping
           `.map-search` to z-index 1300 did nothing because that z-index resolved
           inside the .map context, which itself sits at z-index 0 under the sheet
           (z-index 1200). Round-1's z-index bump therefore "didn't land". With
           `position: absolute` + `z-index: auto`, .map no longer forms a context,
           so #map_search's z-index 1300 escapes to the #content_main context and
           wins over the sheet. The map page does not scroll (body overflow:hidden),
           so absolute-vs-fixed is visually identical here. <JAS 2026-06-22> */
        position: absolute;
        top: 0;
        left: 0;
    }

    /* Toolbar consolidation (Q6). Reveal the "more tools" toggle and default-hide
       the three custom bars; the toggle's data-toolbar-show attribute on the map
       container reveals one bar at a time. The upper bar (home / info /
       fullscreen / table / help) and Leaflet's own zoom control stay visible. */
    .map-more-tools {
        display: flex;
        /* Size parity with the toolbar column (P20). Each `[data-toolbar-group]`
           bar is a `.leaflet-bar`, and Leaflet 1.9.4 puts
           `border: 2px solid rgba(0,0,0,0.2)` on `.leaflet-touch .leaflet-bar`
           (leaflet.css) — a class the map container always carries on a modern
           browser (Leaflet's `Browser.touch` is `touchNative || !!window.
           PointerEvent`, so it is NOT phone-only). With the content-box
           `width: 44px` pinned on those bars further down, a bar RENDERS 48px
           wide, while this button measured 46px (44 + its own 1px border on
           each side) — that 2px is the "slightly smaller" mismatch. It is a
           child of #map_container, NOT of the Leaflet container
           (map/control_buttons.js::_init_more_tools_toggle), so it cannot pick
           that border up from `.leaflet-touch`; match the bar's OUTER box
           instead. `border-box` makes its own 1px border eat INTO the 48px
           rather than add to it, so the 44px WCAG 2.5.5 touch square survives
           inside. <JAS 2026-08-15> */
        box-sizing: border-box;
        width: calc(44px + 2 * 2px);   /* 44px touch square + Leaflet bar border */
        height: calc(44px + 2 * 2px);
    }
    [data-toolbar-group="selection"],
    [data-toolbar-group="markup"],
    [data-toolbar-group="period"] {
        display: none !important;
    }

    /* Keyboard cursor mode is desktop-only (a touch device has direct point-
       picking), so drop its button from the always-visible upper bar on mobile.
       The button sits in a 1:1 wrapper div, so collapse the WRAPPER (via :has)
       to reclaim the slot, not just the <button>. Belt-and-suspenders with the
       runtime _touch_primary() gate in cursor_mode.js. <JAS 2026-07-16> */
    .leaflet-bar > div:has(> #button_cursor_mode) {
        display: none !important;
    }
    #map_container[data-toolbar-show="selection"] [data-toolbar-group="selection"],
    #map_container[data-toolbar-show="markup"] [data-toolbar-group="markup"],
    #map_container[data-toolbar-show="period"] [data-toolbar-group="period"] {
        display: block !important;
    }

    /* Push Leaflet's top-right control stack (zoom + upper bar, inside the
       .map-toolbar-scroll wrapper) down so the fixed more-tools toggle
       (top:8px right:8px, 48px tall since P20) doesn't overlap it.
       64px = 8px top inset + 48px toggle + 8px gap. It was 60px while the
       toggle rendered 44px tall; leaving it there would cut the gap to 4px.
       The handoff-Item-3 scroll wrapper stays intact and layers on top: cap its
       height for the 64px offset so a revealed period bar (10 buttons) still
       scrolls rather than running off the bottom edge. <JAS 2026-08-15> */
    .leaflet-top.leaflet-right {
        top: 64px;
    }
    .map-toolbar-scroll {
        /* Reserve the 56px bottom-sheet PEEK strip (content_infoPanel.css) at the
           bottom too, not just the 64px top offset. Without it, a tall revealed
           group (the 10-button period bar) scrolls to a bottom edge that sits
           behind the peek strip, leaving the last buttons (eraser / Max)
           untappable on short viewports (round-2 feedback). 56 = peek height; the
           wrapper still scrolls internally so every button stays reachable above
           the strip. Also reserve the map-page footer bar (--map-footer-h,
           measured by bottom_sheet.js) so the lowest buttons clear it too
           (round-3 follow-up). <JAS 2026-06-22> */
        max-height: calc(100dvh - 64px - 56px - var(--map-footer-h, 0px) - var(--space-3));
        /* Anchor the wrapper width to its content so the shrink-to-fit corner
           doesn't collapse to zero / blow up to the viewport. */
        width: max-content;
    }

    /* Lift the bottom-left Leaflet corner (the color-scale legend + its palette
       toggle) above the 56px bottom-sheet peek strip so it's not occluded when
       the sheet is collapsed to peek (round-2 feedback). At the mid/full snaps
       the sheet covers far more than 56px, so the legend is intentionally behind
       it there — the user is working the panel, not the map, at those snaps.
       64 = 56 peek + an 8px gap. Keeps Leaflet's bottom-RIGHT attribution corner
       in place. Add the map-page footer height (--map-footer-h, measured by
       bottom_sheet.js) so the legend also clears the slim fixed footer bar
       (round-3 follow-up). <JAS 2026-06-22> */
    .leaflet-bottom.leaflet-left {
        bottom: calc(64px + var(--map-footer-h, 0px));
    }
    /* Lift Leaflet's bottom-right attribution above the footer bar too, so the
       OSM/Carto credit isn't hidden behind it. <JAS 2026-06-22> */
    .leaflet-bottom.leaflet-right {
        bottom: var(--map-footer-h, 0px);
    }

    /* NOTE: the map-page mobile footer used to be a slim FIXED strip pinned over
       the bottom of the map here (round-3 follow-up, 2026-06-22). It was removed
       in S7 (2026-07-25): the footer is now MOVED into the nav drawer on mobile
       by nav/toggle.js::init_footer_in_drawer, so the map reaches the bottom of
       the viewport and there is no bar to reserve space for. The --map-footer-h
       consumers above are deliberately KEPT (bottom_sheet.js::_measure_footer
       now publishes 0px whenever the footer isn't a fixed bar), so re-introducing
       a bottom bar is a one-rule change. <JAS 2026-07-25> */

    /* Transient flash notice (e.g. the >50-marker selection cap). The desktop
       rule pins it near the top of the map at z-index 1100 — but 1100 sits
       UNDER the bottom sheet (1200),
       footer (1250) and search bar (1300), so the notice was created (the JS
       path is the same on touch) but painted behind the mobile chrome — and
       add_location snaps the sheet up over it. Tuck it just below the top search
       bar and lift it above the sheet so it's actually seen; it auto-dismisses
       in ~4s. <JAS 2026-06-24>

       position:fixed + side gutters (was the desktop absolute/left:50% centering)
       so the bar is reliably anchored below the search bar and respects the
       screen edges on mobile — the absolute/centered context mis-sized it the
       same way it did the campaign banner (e.g. the admin-logout flash).
       <JAS 2026-06-26> */
    .flash-overlay {
        position: fixed;
        top: 64px;
        left: var(--space-3);
        right: var(--space-3);
        width: auto;
        max-width: none;
        transform: none;
        z-index: 1350;
    }
    /* Campaign banner: full-width strip below the search bar (mirrors the
       transient .flash-overlay mobile offset) instead of the desktop centered
       pill, with a 44x44 close tap target. */
    .campaign-banner {
        top: 64px;
        left: var(--space-3);
        right: var(--space-3);
        transform: none;
        max-width: none;
    }
    .campaign-banner-close {
        width: 44px;
        height: 44px;
    }
    /* Flash toast: full-width strip below the search bar, mirroring the campaign
       banner's mobile treatment. */
    .flash-toast {
        top: 64px;
        left: var(--space-3);
        right: var(--space-3);
        transform: none;
        width: auto;
        max-width: none;
    }

    /* Hide the full-screen + help toolbar cells (round-2 feedback): the
       Fullscreen API is a no-op on iOS Safari, and the help button only documents
       keyboard shortcuts a touch device can't use. `:has(> #id)` drops the whole
       44px cell (not just the button) so no empty square is left behind; the upper
       bar collapses to home / info / table. <JAS 2026-06-22> */
    [data-toolbar-group="upper"] > div:has(> #button_fullscreen),
    [data-toolbar-group="upper"] > div:has(> #button_help) {
        display: none !important;
    }
    /* Pin the custom toolbar cells to a definite 44px touch square. Their cells
       rely on aspect-ratio:1/1 sized off width (map/control_buttons.js); on the
       full-viewport mobile map that resolves unpredictably via the shrink-to-fit
       ↔ width:100% loop and stretches each button (e.g. home) into a full-height
       sliver. Pin BOTH dimensions explicitly (not just width) so the square does
       not depend on aspect-ratio resolving in the shrink-to-fit corner; also
       meets WCAG 2.5.5. The real Leaflet zoom control (no data-toolbar-group)
       keeps its own sizing. <JAS 2026-06-22> */
    .leaflet-top.leaflet-right [data-toolbar-group] {
        width: 44px;
    }
    .leaflet-top.leaflet-right [data-toolbar-group] > div {
        width: 44px;
        height: 44px;
        aspect-ratio: auto;
    }
    .leaflet-top.leaflet-right [data-toolbar-group] > div > button {
        width: 44px;
        height: 44px;
    }
    /* Match the native Leaflet zoom buttons (the +/- anchors, no
       data-toolbar-group) to the 44px custom squares so the stack reads as one
       consistent, touch-friendly column. line-height = height keeps the +/-
       glyph vertically centered. <JAS 2026-06-22> */
    .leaflet-top.leaflet-right .leaflet-control-zoom a {
        width: 44px;
        height: 44px;
        line-height: 44px;
    }

    /* Move the search bar off the bottom of the viewport — at `bottom: 0` it
       sits under the bottom-sheet peek strip (z-index 1200) and is unreachable.
       Re-home it to the top, clear of BOTH the sidenav hamburger and the
       more-tools toggle. Both are 8px-inset 48px squares, so both edges land at
       56px and both offsets are 56 + an 8px gap = 64px. They were 60px when
       those two buttons measured 44-46px outer; the hamburger in fact rendered
       64px wide (content-box + padding, fixed in content_sideNav.css), so its
       right 12px sat UNDER this input. <JAS 2026-08-21> */
    .map-search {
        bottom: auto;
        top: 8px;
        left: 64px;
        right: 64px;
        width: auto;
        height: 36px;
        /* NO z-index override here any more. This used to be 1300 — above the
           sheet (1200) so the suggestion dropdown wasn't occluded by the panel
           at the full snap. That solved the dropdown by lifting the whole bar,
           which also put the INPUT above the panel; on a landscape phone the
           panel's left edge cuts across this bar, and there the panel should
           win. The two are now separated at the base rules: the wrapper is
           `z-index: auto` (no stacking context), `#search_input` is 1150 (below
           the panel) and `#search_suggestions` is 1250 (above it). Re-adding a
           z-index here would re-form the context and undo both.
           <JAS 2026-06-22, split 2026-08-21> */
    }
    /* Suppress iOS Safari's focus auto-zoom: it zooms the page in on any control
       whose font is < 16px when focused. The input inherits --font-size-base
       (15px) off `font: inherit`, which tripped the zoom (round-3 feedback) —
       same fix already applied to the feedback-form fields (global.css). 16px
       reads near-identically at this size. <JAS 2026-06-22> */
    .map-search #search_input {
        font-size: 16px;
    }
    /* Suggestions drop DOWN from the input on mobile (it now sits at the top),
       not up (the desktop default, where the input is at the map bottom). */
    #search_suggestions {
        bottom: auto;
        top: 100%;
        margin-top: var(--space-1);
        margin-bottom: 0;
    }
}


/* ----------------------------------------- */
/* LANDSCAPE PHONE map chrome (P21, 2026-08-21). The companion of the
   right-side-sheet block in content_infoPanel.css: with the sheet moved from
   the bottom edge to the right edge, every offset the mobile block reserves for
   it has to move with it.

   The mobile block above reserves the 56px PEEK strip along the BOTTOM (it
   lifts the legend by 64px and trims `.map-toolbar-scroll`'s max-height by 56).
   In landscape that strip is a vertical band on the RIGHT instead, so those two
   bottom reservations are RELEASED - the map regains that height, which is the
   entire point of P21 - and the reservation is re-taken along the right edge.

   One arithmetic, same as P20's: the peek strip is 56px wide, so anything that
   must clear it sits at 56px from the right edge, plus the usual 8px gap where
   a gap is wanted.

   DELIBERATE NON-GOAL: at the mid (40vw) and full (70vw) snaps the sheet covers
   the top-right toolbar column, exactly as the portrait sheet covers the legend
   at those snaps. That is the same contract stated in the mobile block above -
   at mid/full the user is working the panel, not the map - and it is preferred
   over relocating the toolbar to the left edge in landscape, which would put a
   ~310px-tall scrolling column on top of the bottom-left legend on a 390px-tall
   viewport. Drag the sheet to peek to work the map. <JAS 2026-08-21> */
/* ----------------------------------------- */
@media (orientation: landscape) and (max-height: 500px) and (pointer: coarse) {
    /* Clear the peek strip: the more-tools toggle is an 8px-inset 48px square
       (P20), so 8 + 56 puts its right edge where it was relative to the map. */
    .map-more-tools {
        right: calc(8px + 56px);
    }
    /* The search bar spans between the hamburger (left) and the more-tools
       toggle (right); its right offset takes the same 56px as that toggle did,
       on top of the 64px it already clears. */
    .map-search {
        right: calc(64px + 56px);
    }
    /* Leaflet's top-right corner (zoom + the upper bar, inside
       `.map-toolbar-scroll`) keeps its 64px top offset - the more-tools toggle
       is still above it - and gains the 56px right inset. */
    .leaflet-top.leaflet-right {
        right: 56px;
    }
    /* RELEASE the bottom reservations. The peek strip is no longer along the
       bottom edge, so the legend drops back to the map's bottom-left corner and
       the toolbar column reclaims the 56px the strip used to cost it. Both keep
       their `--map-footer-h` term: bottom_sheet.js::_measure_footer publishes 0
       today (S7 moved the footer into the drawer) but the plumbing is
       deliberately kept, so do not hardcode these to 0. */
    .leaflet-bottom.leaflet-left {
        bottom: var(--map-footer-h, 0px);
    }
    .map-toolbar-scroll {
        max-height: calc(100dvh - 64px - var(--map-footer-h, 0px) - var(--space-3));
    }
    /* Leaflet's bottom-right attribution would sit behind the peek strip. */
    .leaflet-bottom.leaflet-right {
        right: 56px;
        bottom: var(--map-footer-h, 0px);
    }
}
