/* map.css: the Map tab. A full-bleed canvas under floating glass.
 *
 * The map owns the whole space between the top bar and the tab bar
 * (.view-fill, base.css). Everything on top of it floats: the metric and
 * filter controls, the zoom buttons, the legend, the callout, and the
 * drawer that slides up from the bottom (on a wide screen it docks to the
 * right instead). Their positions come from CSS variables views/heatmap.js
 * sets from measured heights: --map-top, --peek-h, --legend-h, --drawer-w.
 *
 * What it refuses to do: put anything under a finger that scrolls the page
 * while it should move the map. The canvas and the drawer's handle are
 * touch-action: none; the drawer's body scrolls on its own and never
 * drags the page behind it.
 *
 * ⚠ iOS: a long-press on the map must plan an access point, not select text
 * or raise the "copy / look up" callout. user-select and -webkit-touch-callout
 * are off on the whole stage for that reason.
 */

/* ── The view and the stage ───────────────────────────────────────────── */
.map-view {
  --map-top: 104px; --peek-h: 96px; --legend-h: 72px; --drawer-w: 0px;
  --map-glass: rgba(5, 11, 31, .66);
  --map-glass-hi: rgba(10, 22, 58, .82);
  background: var(--bg);
  isolation: isolate;
  -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none;
}
.map-stage { position: absolute; inset: 0; overflow: hidden; touch-action: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.mapview-canvas { position: absolute; left: 0; top: 0; display: block; touch-action: none; outline: none; cursor: grab; -webkit-tap-highlight-color: transparent; }
.mapview-canvas:active { cursor: grabbing; }
.mapview-canvas.editing { cursor: crosshair; }
.mapview-canvas:focus-visible { box-shadow: inset 0 0 0 2px var(--blue-hi); }
.map-view.dragging-ap .mapview-canvas { cursor: grabbing; }

/* The computing shimmer: a thin bright line sweeping under the controls. */
.map-shimmer {
  position: absolute; z-index: 6; left: 0; right: 0; top: 0; height: 2px; pointer-events: none;
  opacity: 0; transition: opacity 260ms var(--ease);
  background: linear-gradient(90deg, transparent, rgba(41, 169, 242, .95), #a5f3fc, rgba(41, 169, 242, .95), transparent) no-repeat;
  background-size: 38% 100%;
}
.map-view.computing .map-shimmer { opacity: 1; animation: mapScan 1.15s cubic-bezier(.4, 0, .2, 1) infinite; }
@keyframes mapScan { from { background-position: -40% 0; } to { background-position: 140% 0; } }

/* ── Glass ────────────────────────────────────────────────────────────── */
.map-pill, .map-round, .map-legend, .map-metrics .seg, .map-notice-card {
  background: var(--map-glass);
  -webkit-backdrop-filter: saturate(160%) blur(16px); backdrop-filter: saturate(160%) blur(16px);
  border: 1px solid var(--line-2);
  box-shadow: 0 10px 28px -14px rgba(0, 0, 0, .85), inset 0 1px 0 rgba(255, 255, 255, .06);
}

/* ── Top controls ─────────────────────────────────────────────────────── */
.map-top {
  position: absolute; z-index: 5; top: 10px;
  left: calc(var(--safe-l) + 12px); right: calc(var(--safe-r) + 12px);
  display: flex; flex-direction: column; gap: 8px;
  pointer-events: none;
}
.map-top > * { pointer-events: auto; }
.map-metrics .seg { border-radius: 16px; padding: 4px; }
.map-metrics .seg-thumb { border-radius: 12px; background: linear-gradient(180deg, rgba(41, 169, 242, .5), rgba(1, 142, 220, .32)); box-shadow: inset 0 0 0 1px rgba(125, 211, 252, .45), 0 6px 16px -8px rgba(1, 142, 220, .9); }
.map-metrics .seg-opt { min-height: 36px; font-size: 13px; color: var(--ink-2); }
.map-metrics .seg-opt[aria-checked="true"] { color: #fff; }
.map-metrics .seg-opt.no-data { color: rgba(125, 142, 171, .5); }
.map-metrics .seg-opt.no-data span { text-decoration: line-through; text-decoration-color: rgba(125, 142, 171, .35); }

.map-top-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.map-chips { flex: 1; min-width: 0; padding: 2px 2px 4px; margin: -2px -2px -4px; }
/* ⚠ NO EDGE FADE HERE (.scroll-x, base.css): a mask on the row makes it the
   backdrop root, and the glass pills in it would stop blurring the map. */
.map-chips { -webkit-mask-image: none; mask-image: none; animation: none; }
.map-pill {
  display: inline-flex; align-items: center; gap: 7px; height: 40px; padding: 0 12px 0 11px; border-radius: 999px;
  font: 600 13px/1 var(--head); color: var(--ink); white-space: nowrap; max-width: 220px;
  transition: transform 120ms var(--ease), background 200ms;
}
.map-pill .ico-sm { color: var(--blue-hi); }
.map-pill .ico-xs { color: var(--ink-3); }
.map-pill:active { transform: scale(.95); background: var(--map-glass-hi); }
.map-pill:disabled { opacity: .55; pointer-events: none; }
.map-chip-text, .map-floor-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.map-floor { color: #e0f2fe; }
.map-round {
  flex: none; width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; color: var(--ink);
  transition: transform 120ms var(--ease), background 200ms;
}
.map-round:active { transform: scale(.9); background: var(--map-glass-hi); }
.map-round .ico { width: 20px; height: 20px; }

/* ── Zoom ─────────────────────────────────────────────────────────────── */
.map-zoom {
  position: absolute; z-index: 4;
  right: calc(var(--safe-r) + 12px + var(--drawer-w));
  bottom: calc(var(--peek-h) + var(--legend-h) + 10px);
  display: flex; flex-direction: column; gap: 8px;
  transition: bottom 260ms var(--ease);
}
/* Fingers pinch; on a phone only "show the whole floor" earns its space. */
@media (pointer: coarse) and (max-width: 899px) {
  .map-zoom .map-round:not(:last-child) { display: none; }
}

/* ── Legend ───────────────────────────────────────────────────────────── */
.map-legend {
  position: absolute; z-index: 4; display: block; text-align: left; color: var(--ink);
  left: calc(var(--safe-l) + 12px);
  bottom: calc(var(--peek-h) + 10px);
  width: min(360px, calc(100% - 84px - var(--safe-l) - var(--safe-r) - var(--drawer-w)));
  padding: 10px 13px 8px; border-radius: 16px;
  transition: transform 140ms var(--ease), bottom 260ms var(--ease);
  animation: rise 320ms var(--ease) both;
}
.map-legend:active { transform: scale(.98); }
.legend-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; min-width: 0; }
.legend-title { font: 700 12px/1.2 var(--head); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.legend-mode { font: 600 10.5px/1.2 var(--body); color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.legend-track { position: relative; display: block; height: 10px; margin-top: 20px; }
.legend-bar { display: block; height: 10px; border-radius: 5px; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18), 0 0 18px -6px rgba(41, 169, 242, .6); }
.legend-marker {
  position: absolute; top: -5px; bottom: -5px; width: 2px; margin-left: -1px; border-radius: 1px;
  background: #fff; box-shadow: 0 0 0 1px rgba(5, 11, 31, .75), 0 0 10px rgba(255, 255, 255, .7);
  transition: left 300ms var(--ease);
}
.legend-marker-text {
  position: absolute; bottom: calc(100% + 3px); left: 50%; transform: translateX(-50%);
  font: 700 10px/1.3 var(--mono); color: #050b1f; background: #fff; padding: 1px 6px; border-radius: 6px; white-space: nowrap;
}
.legend-ticks { position: relative; display: block; height: 15px; margin-top: 5px; font: 600 11px/1.3 var(--mono); color: var(--ink-2); }
/* On the card the target's label rides above the bar: clear of the title row wherever the target is. */
.map-legend .legend-track { margin-top: 26px; }
.legend-tick { position: absolute; top: 0; transform: translateX(-50%); white-space: nowrap; }
.legend-tick.start { transform: none; }
.legend-tick.end { transform: translateX(-100%); }
/* One line of plain words under the scale (what a speed map measures). The HUD stays fixed in px. */
.legend-note { display: block; margin-top: 6px; font: 500 10.5px/1.35 var(--body); color: var(--ink-2); white-space: normal; }
/* The legend entry for the faded heat: where nobody walked, the map is the model's guess (mapview.heatRaster). */
.legend-pred { display: flex; align-items: center; gap: 7px; margin-top: 6px; font: 600 10.5px/1.3 var(--body); color: var(--ink-2); white-space: nowrap; }
.swatch-predicted { flex: none; display: inline-block; width: 24px; height: 8px; border-radius: 4px; opacity: .45; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .25); }
.peek-pred { margin: 2px 2px 0; }
.map-view.computing .legend-bar { animation: legendGlow 1.3s ease-in-out infinite; }
@keyframes legendGlow { 50% { filter: brightness(1.25) saturate(1.25); } }

/* ── Notices over the map ─────────────────────────────────────────────── */
.map-notice {
  position: absolute; z-index: 5; top: calc(var(--map-top) + 10px);
  left: calc(var(--safe-l) + 12px); right: calc(var(--safe-r) + 12px + var(--drawer-w));
  display: flex; justify-content: center; pointer-events: none;
}
.map-notice-card {
  pointer-events: auto; width: 100%; max-width: 460px; display: flex; gap: 12px; align-items: flex-start;
  padding: 14px 14px 13px; border-radius: 18px; background: var(--map-glass-hi);
  animation: rise 300ms var(--ease) both;
}
.map-notice-card > .ico { color: var(--blue-hi); margin-top: 1px; }
.notice-title { font: 700 15px/1.25 var(--head); margin: 0 0 4px; }
.notice-body { font-size: 13.5px; line-height: 1.45; color: var(--ink-2); margin: 0; }
.notice-actions { margin-top: 11px; flex-wrap: wrap; }
.map-notice.slim .map-notice-card { padding: 11px 12px; }
.map-notice.slim .notice-body { font-size: 12.5px; }

/* ── Callout ──────────────────────────────────────────────────────────── */
.map-callout { position: absolute; inset: 0; z-index: 6; pointer-events: none; }
.map-callout.offscreen { visibility: hidden; }
.callout-card {
  position: absolute; left: 0; top: 0; width: max-content; min-width: 190px; max-width: min(300px, calc(100vw - 32px));
  pointer-events: auto; padding: 12px 12px 12px 14px; border-radius: 16px;
  background: linear-gradient(180deg, rgba(17, 32, 76, .95), rgba(8, 19, 52, .95));
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border: 1px solid var(--line-2);
  box-shadow: 0 20px 44px -16px rgba(0, 0, 0, .85), inset 0 1px 0 rgba(255, 255, 255, .07);
  transform-origin: 50% 100%;
  -webkit-user-select: text; user-select: text;
}
.map-callout.below .callout-card { transform-origin: 50% 0; }
.map-callout.pop .callout-card { animation: calloutPop 240ms var(--spring) both; }
@keyframes calloutPop { from { opacity: 0; scale: .9; } }
.callout-arrow {
  position: absolute; left: 0; top: 0; width: 12px; height: 12px; margin-left: -6px; pointer-events: none;
  background: rgba(9, 20, 54, .97); border-right: 1px solid var(--line-2); border-bottom: 1px solid var(--line-2);
}
.map-callout.below .callout-arrow { border: 0; border-left: 1px solid var(--line-2); border-top: 1px solid var(--line-2); background: rgba(17, 32, 76, .97); }
.callout-head { display: flex; gap: 6px; align-items: flex-start; }
.callout-eyebrow { font: 700 10px/1.2 var(--head); letter-spacing: .12em; text-transform: uppercase; color: var(--blue-hi); margin: 0 0 4px; }
.callout-title { font: 800 18px/1.2 var(--head); margin: 0; display: flex; align-items: center; gap: 8px; letter-spacing: -.01em; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.callout-dot { width: 10px; height: 10px; border-radius: 50%; flex: none; box-shadow: 0 0 0 2px rgba(255, 255, 255, .15); }
.callout-sub { margin: 6px 0 0; font-size: 13px; line-height: 1.42; color: var(--ink-2); }
.callout-note { margin: 4px 0 0; font-size: 11.5px; line-height: 1.35; color: var(--ink-3); }
.callout-close { flex: none; width: 40px; height: 40px; margin: -10px -8px -8px 0; border-radius: 12px; display: grid; place-items: center; color: var(--ink-3); }
.callout-close:active { background: var(--glass-2); }
.callout-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.callout-actions .btn { -webkit-user-select: none; user-select: none; }

/* ── Drawer ───────────────────────────────────────────────────────────── */
.map-drawer {
  position: absolute; z-index: 7; left: 0; right: 0; bottom: 0;
  display: flex; flex-direction: column;
  padding: 0 var(--safe-r) 0 var(--safe-l);
  border-radius: 26px 26px 0 0; border: 1px solid var(--line-2); border-bottom: 0;
  background: linear-gradient(180deg, rgba(14, 31, 80, .95) 0%, rgba(8, 20, 54, .97) 40%, rgba(7, 18, 51, .98) 100%);
  -webkit-backdrop-filter: saturate(160%) blur(18px); backdrop-filter: saturate(160%) blur(18px);
  box-shadow: 0 -20px 50px -14px rgba(0, 0, 0, .7), inset 0 1px 0 rgba(255, 255, 255, .08);
  will-change: transform;
  /* At its peek until the view measures it (then an inline transform takes
     over), so a first frame never shows the whole drawer open. */
  transform: translateY(calc(100% - var(--peek-h)));
}
.map-drawer.settle { transition: transform 320ms var(--ease); }
.drawer-handle { flex: none; padding: 8px 14px 10px; touch-action: none; cursor: grab; }
/* On a phone the tab bar's Survey button rises into the drawer's bottom edge: the peek keeps clear of it. */
.map-view:not(.wide) .drawer-handle { padding-bottom: 40px; }
/* The legend strip in the peek is a button too (it opens the coverage target). */
.peek-legend-btn { display: block; width: 100%; padding: 0 6px 8px; text-align: left; }
.drawer-grab { display: block; width: 40px; height: 5px; border-radius: 3px; background: rgba(255, 255, 255, .26); margin: 0 auto 8px; }
.drawer-peek { display: flex; align-items: center; gap: 13px; width: 100%; min-height: 60px; padding: 0 2px; text-align: left; border-radius: 14px; }
.drawer-peek .ring { flex: none; }
.drawer-peek .ring-label { font-size: 13.5px; }
.peek-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; transition: opacity 200ms; }
.peek-title { font: 700 15.5px/1.25 var(--head); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.peek-sub { font-size: 12.5px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.peek-chev { flex: none; color: var(--ink-3); display: grid; place-items: center; width: 32px; height: 32px; transform: rotate(180deg); transition: transform 280ms var(--ease); }
.map-drawer.open .peek-chev { transform: none; }
.drawer-body {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
  padding: 2px 16px calc(28px + var(--safe-b)); display: flex; flex-direction: column; gap: 14px;
  -webkit-user-select: text; user-select: text;
}
.map-view.computing .drawer-stats, .map-view.computing .peek-text { opacity: .62; }
.drawer-stats { transition: opacity 200ms; }
.drawer-stats .stat { padding: 11px 10px 10px; }
.drawer-stats .stat-value { font-size: 21px; }
.drawer-note { font-size: 13px; }
.drawer-predicted { display: flex; align-items: flex-start; gap: 8px; margin: -4px 2px 0; line-height: 1.45; }
.drawer-predicted .swatch-predicted { margin-top: 5px; }
.drawer-link-note { margin: -4px 2px 0; line-height: 1.45; }
.drawer-sec { display: flex; flex-direction: column; }
.drawer-sec-title { font: 700 11.5px/1 var(--head); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3); margin: 8px 2px 8px; display: flex; align-items: center; gap: 8px; }
.drawer-sec-title .ico { color: var(--blue-hi); }
.drawer-sec-sub { margin: -2px 2px 6px; }
.drawer-li { padding: 0; gap: 8px; min-height: 60px; }
.li-hit { display: flex; align-items: center; gap: 12px; min-height: 58px; padding: 8px 2px; text-align: left; min-width: 0; border-radius: 12px; }
.li-hit:active { background: var(--glass); }
.drawer-li .btn-sm { flex: none; }
.drawer-li .icon-btn { flex: none; color: var(--ink-3); }
.li-icon.tone-bad { background: rgba(248, 113, 113, .14); color: #fca5a5; }
.li-icon.tone-warn { background: rgba(251, 191, 36, .13); color: #fcd34d; }
.li-icon.tone-ok { background: rgba(52, 211, 153, .14); color: #6ee7b7; }
.li-icon.tone-threat { background: rgba(255, 77, 109, .18); color: #ff8fa6; box-shadow: inset 0 0 0 1px rgba(255, 77, 109, .4); }
.li-icon.tone-own { background: rgba(1, 142, 220, .18); color: #7dd3fc; }
.li-icon.tone-neighbor { background: rgba(165, 180, 252, .14); color: #c7d2fe; }
.li-icon.tone-plan { background: rgba(41, 169, 242, .1); color: #7dd3fc; box-shadow: inset 0 0 0 1.5px rgba(41, 169, 242, .5); }
.finding { background: var(--glass); border: 1px solid var(--line); border-radius: 15px; padding: 12px 13px; }
.finding.sev-high { border-color: rgba(248, 113, 113, .32); background: linear-gradient(180deg, rgba(248, 113, 113, .07), var(--glass)); }
.finding-head { align-items: flex-start; }
.finding-title { font: 700 14px/1.3 var(--head); }
.finding-detail { margin: 6px 0 0; font-size: 13px; line-height: 1.45; color: var(--ink-2); }
.finding-action { margin: 6px 0 0; font-size: 13px; line-height: 1.45; color: #cfe9fb; display: flex; gap: 4px; align-items: flex-start; }
.finding-action .ico { margin-top: 3px; color: var(--blue-hi); }
.finding .link-btn { margin-top: 2px; font-size: 13.5px; min-height: 40px; }
.drawer-foot { margin: 2px 2px 0; }

/* ── Sheets this view opens ───────────────────────────────────────────── */
/* One check, on the chosen row only: the coverage presets draw one on every
   row and leave it to this to show the right one, which scales in. */
.target-li .li-trail .ico { color: var(--blue-hi); transition: opacity 160ms var(--ease), transform 160ms var(--spring); }
.target-li:not(.current) .li-trail .ico { opacity: 0; transform: scale(.5); }
.target-li.current .li-icon { background: rgba(1, 142, 220, .22); color: #fff; box-shadow: inset 0 0 0 1px rgba(41, 169, 242, .55); }
.thr-swatch { font: 700 12px/1 var(--mono); color: var(--ink); width: 46px; }
.thr-custom { background: var(--glass); border: 1px solid var(--line); border-radius: 15px; padding: 12px 14px 10px; }
.thr-value { font: 800 20px/1 var(--head); color: var(--ink); }
.thr-ends { color: var(--ink-3); margin-top: 2px; }
input[type="range"].reverse { direction: rtl; }
.layer-card { padding: 2px 14px; }
.layer-card .toggle { min-height: 50px; border-bottom: 1px solid var(--line); }
.layer-card .toggle:last-child { border-bottom: 0; }
/* The walks sheet: a switch per walk, and its delete button beside it. */
.walk-row { display: flex; align-items: center; gap: 4px; border-bottom: 1px solid var(--line); }
.walk-row:last-child { border-bottom: 0; }
.walk-list .walk-row .toggle { flex: 1; min-width: 0; border-bottom: 0; }
.walk-del { flex: none; color: var(--ink-3); }

/* ── Home's floor card ────────────────────────────────────────────────── */
/* The open floor nearing the 12 MB the cloud takes: under the heat map card (views/home.js floorSizeNote). */
.home-size-warn { margin-top: 12px; }

/* ── No floor at all ──────────────────────────────────────────────────── */
.map-empty { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 24px calc(var(--safe-r) + 20px) 24px calc(var(--safe-l) + 20px); overflow: hidden; }
.map-empty-art { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.map-empty-art .blob { position: absolute; border-radius: 50%; filter: blur(40px); opacity: .5; animation: drift 14s ease-in-out infinite alternate; }
.map-empty-art .b1 { width: 70%; height: 46%; left: -6%; top: 6%; background: radial-gradient(circle, rgba(30, 155, 240, .8), transparent 70%); }
.map-empty-art .b2 { width: 60%; height: 40%; right: -10%; top: 34%; background: radial-gradient(circle, rgba(20, 199, 192, .55), transparent 70%); animation-delay: -5s; }
.map-empty-art .b3 { width: 46%; height: 32%; left: 20%; bottom: 4%; background: radial-gradient(circle, rgba(255, 154, 46, .35), transparent 70%); animation-delay: -9s; }
.map-empty-art .grid-lines { position: absolute; inset: 0; background-image: linear-gradient(rgba(255, 255, 255, .04) 1px, transparent 1px), linear-gradient(90deg, rgba(255, 255, 255, .04) 1px, transparent 1px); background-size: 28px 28px; }
.map-empty .empty {
  position: relative; z-index: 1; max-width: 420px; border-radius: var(--radius);
  background: linear-gradient(180deg, rgba(255, 255, 255, .07), rgba(255, 255, 255, .03));
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border: 1px solid var(--line-2);
  animation: rise 360ms var(--ease) both;
}
.map-empty-more { position: relative; z-index: 1; justify-content: center; margin-top: 14px; }

/* ── Wide screens: the drawer docks to the right ──────────────────────── */
@media (min-width: 900px) {
  .map-view.wide .map-drawer {
    left: auto; top: 12px; right: calc(var(--safe-r) + 12px); bottom: 12px; width: 384px;
    padding: 0; border-radius: 24px; border-bottom: 1px solid var(--line-2);
    transform: none !important; height: auto !important;
    box-shadow: 0 24px 60px -18px rgba(0, 0, 0, .75), inset 0 1px 0 rgba(255, 255, 255, .08);
    animation: rise 320ms var(--ease) both;
  }
  .map-view.wide .drawer-grab, .map-view.wide .peek-chev { display: none; }
  .map-view.wide .drawer-handle { cursor: default; touch-action: auto; padding-top: 14px; }
  .map-view.wide .drawer-peek { cursor: default; }
  .map-view.wide .drawer-body { padding-bottom: 20px; }
  .map-view.wide .map-top { right: calc(var(--safe-r) + 384px + 28px); max-width: 640px; }
  .map-view.wide .map-legend { bottom: 16px; }
  .map-view.wide .map-zoom { bottom: calc(var(--legend-h) + 12px); }
}

@media (max-width: 360px) {
  .map-metrics .seg-opt { font-size: 12px; padding: 0 3px; }
  .map-pill { padding: 0 10px; font-size: 12.5px; }
  .drawer-stats .stat-value { font-size: 18px; }
}

@media (prefers-reduced-motion: reduce) {
  .map-view.computing .map-shimmer { animation: none; background-size: 100% 100%; opacity: .6; }
  .map-empty-art .blob { animation: none !important; }
}
