/**
 * developments/css/mobile-v2.css — MOBILE V2 (2026-09-02), Round 1.
 *
 * The finger-first phone shell, flag-gated behind <html class="mobile-v2">
 * (?mobile=v2 → sticky via localStorage; ?mobile=v1 clears). Loaded LAST so
 * html.mobile-v2-scoped rules out-cascade devmap/panel-v5/user at equal
 * specificity. v1 is byte-identical without the class; rollback = remove
 * the class. Design: docs/developments/design/MOBILE-REDESIGN-BRIEF-2026-09.md.
 *
 * Round-1 principles (owner doctrine: mouse vs FINGER is the difference):
 *  - ONE surface owns the screen: sheets are OPAQUE (kills the D5 ghosting),
 *    the dossier is a pushed PAGE (tab bar + FAB step aside), the legend is
 *    a scrimmed modal.
 *  - Thumb-first: the dossier's tab strip moves to a fixed BOTTOM bar; its
 *    band pins as a fixed top bar (the un-sticking-✕ bug dies with it).
 *  - Touch mechanics: press states everywhere, touch-action, 44px floors on
 *    the audited offenders, overscroll containment on every sheet.
 */

/* ═══ Touch mechanics — FLIP GUARD (2026-09-03): v2 is the default, so the
   class is on desktop too; these stay scoped to the phone regimes so the
   mature desktop experience is byte-identical under the flipped default. ═══ */
@media (max-width: 540px), (max-height: 540px) and (pointer: coarse) and (max-width: 1023px) {
  html.mobile-v2 button,
  html.mobile-v2 [role="button"],
  html.mobile-v2 a {
    touch-action: manipulation;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  }
  html.mobile-v2 button:active,
  html.mobile-v2 [role="button"]:active,
  html.mobile-v2 .dev-rail-icon:active,
  html.mobile-v2 .dev-evt:active,
  html.mobile-v2 .dev-search-bar-result:active {
    filter: brightness(0.9);
  }
}

/* The scrim (mounted by surface-manager.js) */
html.mobile-v2 .sm-scrim {
  position: fixed; inset: 0;
  background: rgba(20, 16, 8, 0.38);
  z-index: 6; /* below the legend sheet (7), above map + chrome row + dossier */
  opacity: 1; transition: opacity 180ms ease-out;
}
html.mobile-v2 .sm-scrim[hidden] { display: none; }

@media (max-width: 540px) {

  /* ═══ Opaque sheets — a stack can never ghost (D5) ═══ */
  html.mobile-v2 #dev-nav {
    background: var(--bg-paper, #faf9f7);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
  /* Sheet grabber: the visible "this is a sheet, it goes down" affordance */
  html.mobile-v2 #dev-nav::before {
    content: "";
    display: block;
    width: 36px; height: 4px;
    margin: 8px auto 2px;
    border-radius: 2px;
    background: var(--line-strong, #d1d5db);
  }

  /* ═══ The dossier is a pushed PAGE ═══ */
  /* Full height — the global tab bar steps aside (it stopped lying). */
  html.mobile-v2 #dev-detail {
    bottom: 0;
    z-index: 12; /* above the nav sheet (8) and the bar (9): the page owns the screen */
    transition: transform 240ms cubic-bezier(0.2, 0, 0, 1);
    overscroll-behavior: contain;
  }
  html.mobile-v2 .dev-shell:has(.dev-main.detail-open) #dev-rail {
    transform: translateY(110%);
    transition: transform 240ms cubic-bezier(0.2, 0, 0, 1);
  }
  html.mobile-v2 .dev-shell:has(.dev-main.detail-open) .dev-legend-fab {
    opacity: 0; pointer-events: none; transition: opacity 150ms ease-out;
  }

  /* The band = a real fixed top bar (the sole ✕ can no longer scroll away —
     the ≤640 deck-scroll rules broke its sticky; fixed is immune). */
  html.mobile-v2 #dev-detail:has(.panel-v5) .pv5-card__band {
    position: fixed !important; /* out-rank panel-v5's !important accordion rules */
    top: 0; left: 0; right: 0;
    z-index: 14;
    padding-top: calc(env(safe-area-inset-top, 0px) + 6px);
    background: var(--bg-paper, #faf9f7);
    border-bottom: 1px solid var(--line, #e7e5e4);
  }
  /* Drag affordance on the band (surface-manager arms swipe-down there) —
     R2: seated clearly INSIDE the band's top edge. */
  html.mobile-v2 #dev-detail:has(.panel-v5) .pv5-card__band::before {
    content: "";
    position: absolute;
    top: calc(env(safe-area-inset-top, 0px) + 3px);
    left: 50%; transform: translateX(-50%);
    width: 40px; height: 4px; border-radius: 2px;
    background: var(--line-strong, #d1d5db);
    opacity: 0.9;
  }
  /* Content clears the fixed band */
  html.mobile-v2 #dev-detail:has(.panel-v5) .pv5-deck {
    padding-top: calc(env(safe-area-inset-top, 0px) + 58px);
  }
  /* R2: the meter chip ("2 free dossiers left") rendered UNDER the fixed
     band — join it to the fixed header stack instead (it is meter status;
     it should always be visible), and clear the deck further below it. */
  html.mobile-v2 #dev-detail:has(.panel-v5) .pv5-meter-chip {
    position: fixed;
    top: calc(env(safe-area-inset-top, 0px) + 50px);
    left: 0; right: 0;
    z-index: 14;
    margin: 0;
    border-radius: 0;
    text-align: center;
  }
  html.mobile-v2 #dev-detail:has(.pv5-meter-chip) .pv5-deck {
    padding-top: calc(env(safe-area-inset-top, 0px) + 92px);
  }

  /* ═══ The dossier tab strip moves to the THUMB ZONE ═══ */
  html.mobile-v2 #dev-detail:has(.panel-v5) .pv5-card__tabs {
    position: fixed !important;
    top: auto !important;
    bottom: 0; left: 0; right: 0;
    z-index: 14;
    background: var(--bg-paper, #faf9f7);
    border-top: 1px solid var(--line, #e7e5e4);
    border-bottom: none;
    padding: 4px 6px calc(4px + env(safe-area-inset-bottom, 0px));
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    /* R2: right-edge fade = "more tabs live this way" */
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
  }
  html.mobile-v2 #dev-detail:has(.panel-v5) .pv5-card__tab {
    padding: 12px 10px 13px;
    font-size: 12px;
  }
  /* Content clears the bottom tab strip */
  html.mobile-v2 #dev-detail:has(.panel-v5) .pv5-card {
    padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px));
  }

  /* Follow chip beside the ✕: honest touch height */
  html.mobile-v2 .pv5-card__band-actions .dev-follow-btn--panel {
    height: 36px;
  }

  /* ═══ The legend is a scrimmed MODAL sheet ═══ */
  html.mobile-v2 #dev-map .dev-legend.is-mobile-open {
    z-index: 13; /* above the dossier page (12) — it is a modal, scrim behind it */
    background: var(--bg-paper, #faf9f7);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    overscroll-behavior: contain;
    animation: sm-sheet-up 220ms cubic-bezier(0.2, 0, 0, 1);
    border-radius: 16px 16px 0 0;
    left: 0; right: 0; bottom: 0; /* true bottom sheet, full-bleed */
    padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px));
  }
  html.mobile-v2 #dev-map .dev-legend.is-mobile-open::before {
    content: "";
    display: block;
    width: 36px; height: 4px;
    margin: 0 auto 10px;
    border-radius: 2px;
    background: var(--line-strong, #d1d5db);
  }
  /* Right-edge clip fix: the desktop rows' negative margins pushed the
     UNITS column past the sheet padding ("16,67…"). */
  html.mobile-v2 #dev-map .dev-legend.is-mobile-open .dev-legend-row { margin: 0; }
  /* The scrim carries the modal — raise it under this sheet */
  html.mobile-v2 .sm-scrim { z-index: 12; }
  /* Target floors on the audited offenders */
  html.mobile-v2 .dev-legend.is-mobile-open .dev-legend-vis-toggle {
    font-size: 11px; padding: 8px 12px; min-height: 32px;
  }
  html.mobile-v2 .dev-legend.is-mobile-open .dev-legend-mu-chip {
    padding: 8px 12px; font-size: 11px;
  }
  html.mobile-v2 .dev-legend.is-mobile-open .dev-legend-collapse-btn {
    width: 40px; height: 40px;
  }

  @keyframes sm-sheet-up {
    from { transform: translateY(48px); opacity: 0.6; }
    to   { transform: translateY(0);    opacity: 1; }
  }

  /* Search results honor the real (keyboard-aware) viewport */
  html.mobile-v2 #dev-header .dev-search-bar-dropdown {
    max-height: calc(var(--app-height, 100svh) - 140px);
  }
}

/* ═══ R5: the search TAKEOVER (phone regimes; class set by surface-manager) ═══ */
@media (max-width: 540px), (max-height: 540px) and (pointer: coarse) and (max-width: 1023px) {
  html.mobile-v2.sm-search-open #dev-header {
    top: 0; bottom: 0;
    background: var(--bg-paper, #faf9f7);
    pointer-events: auto;
    z-index: 20; /* search owns the screen — above the dossier page too */
  }
  html.mobile-v2.sm-search-open #dev-header .dev-brand,
  html.mobile-v2.sm-search-open #dev-header .dev-user-slot { display: none; }
  html.mobile-v2.sm-search-open #dev-header .dev-topbar { align-items: flex-start; }
  html.mobile-v2.sm-search-open #dev-header .dev-topbar-center {
    flex-direction: row; flex-wrap: wrap; align-items: center; gap: 10px;
  }
  html.mobile-v2.sm-search-open #dev-header .dev-search-bar { flex: 1 1 auto; }
  html.mobile-v2 .sm-search-cancel { display: none; }
  html.mobile-v2.sm-search-open .sm-search-cancel {
    display: inline-block;
    background: none; border: none; cursor: pointer;
    font: 600 15px/1 Inter, var(--font-body, sans-serif);
    color: var(--gold-600, #b8923f);
    padding: 12px 4px;
    flex: 0 0 auto;
  }
  /* Results fill the keyboard-aware viewport as a static list */
  html.mobile-v2.sm-search-open #dev-header .dev-search-bar-dropdown {
    position: fixed;
    left: 0; right: 0;
    top: calc(env(safe-area-inset-top, 0px) + 62px);
    bottom: 0;
    max-height: none;
    height: auto;
    border-radius: 0; border-left: none; border-right: none; border-bottom: none;
    box-shadow: none;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
  /* Search owns the screen: the bar, FAB and preview card step aside */
  html.mobile-v2.sm-search-open #dev-rail { transform: translateY(110%); }
  html.mobile-v2.sm-search-open .dev-legend-fab,
  html.mobile-v2.sm-search-open .sm-preview { display: none; }
}

/* ═══ R3: the map tap-preview card ═══ */
html.mobile-v2 .sm-preview {
  position: fixed;
  left: 10px; right: 10px;
  bottom: calc(var(--hdm-bar-h, 56px) + 10px + env(safe-area-inset-bottom, 0px));
  z-index: 10; /* above the tab bar (9); below the dossier page (12) */
  display: block;
  text-align: left;
  background: var(--bg-paper, #faf9f7);
  border: 1px solid var(--line, #e7e5e4);
  border-radius: 14px;
  box-shadow: 0 10px 32px rgba(20, 16, 8, 0.22);
  padding: 12px 14px;
  cursor: pointer;
  font-family: var(--font-body, Inter, sans-serif);
  animation: sm-sheet-up 200ms cubic-bezier(0.2, 0, 0, 1);
}
html.mobile-v2 .sm-preview:active { filter: brightness(0.95); }
/* QA 2026-09-08 (D6) — while the card is up, the map's own controls sit above
   it instead of under it. --sm-preview-h is the card's measured height
   (surface-manager.js), so the one-row and two-row cards both clear exactly. */
html.mobile-v2.sm-preview-open .mapboxgl-ctrl-bottom-right,
html.mobile-v2.sm-preview-open .mapboxgl-ctrl-bottom-left {
  bottom: calc(var(--hdm-bar-h, 56px) + 10px + env(safe-area-inset-bottom, 0px)
               + var(--sm-preview-h, 96px) + 8px);
  transition: bottom 180ms cubic-bezier(0.2, 0, 0, 1);
}
/* QA 2026-09-08 (PH-07/MAP-08) - the lift above reaches only Mapbox's own
   control containers. The legend key is Helio's own button, mounted straight
   into #dev-map (ui.js) at z-index 5, so the full-width card (z-index 10) sat
   on top of it and swallowed the tap: measured on a 390x844 phone, the FAB
   spans y 680-724 and the card starts at y 693, so the button's own centre
   hit-tested to the card. max() so the FAB is only ever raised, never dropped
   below its 64px scale-control clearance. (The FAB is display:none >640px, so
   the landscape regime - where the card is right-inset - is unaffected.) */
html.mobile-v2.sm-preview-open #dev-map .dev-legend-fab {
  bottom: max(calc(var(--hdm-bar-h, 0px) + 64px),
              calc(var(--hdm-bar-h, 56px) + 10px + env(safe-area-inset-bottom, 0px)
                   + var(--sm-preview-h, 96px) + 8px));
  transition: bottom 180ms cubic-bezier(0.2, 0, 0, 1);
}
html.mobile-v2 .sm-preview__eyebrow {
  display: block;
  font-size: 10px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--ink-3, #6b7280);
}
html.mobile-v2 .sm-preview__name {
  display: block;
  font: 700 16px/1.25 var(--font-display, Outfit, sans-serif);
  color: var(--ink-1, #111);
  margin: 2px 0 6px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
html.mobile-v2 .sm-preview__row { display: flex; align-items: center; gap: 8px; }
html.mobile-v2 .sm-preview__chip {
  font-size: 10.5px; font-weight: 700;
  padding: 3px 9px; border-radius: 999px;
  background: var(--ink-3, #6b7280); color: #fff;
}
html.mobile-v2 .sm-preview__chip[data-stage="construction"] { background: var(--gold, #d4a84b); color: #111; }
html.mobile-v2 .sm-preview__chip[data-stage="approved"] { background: #4a6fa5; }
html.mobile-v2 .sm-preview__chip[data-stage="proposed"] { background: #7c6cae; }
html.mobile-v2 .sm-preview__chip[data-stage="completed"] { background: #6b8e4e; }
html.mobile-v2 .sm-preview__facts {
  font: 500 12px/1 var(--font-mono, monospace);
  color: var(--ink-2, #374151);
}
html.mobile-v2 .sm-preview__cue {
  position: absolute; right: 14px; top: 50%;
  transform: translateY(-50%);
  font-size: 12px; font-weight: 600;
  color: var(--gold-600, #b8923f);
}

/* ═══ R3: the LANDSCAPE-PHONE regime (coarse pointer, low height) ═══
   Landscape phones used to get raw tablet chrome. They now get the v2 page
   grammar: the dossier owns the screen with the same fixed band + bottom
   tab strip; the legend is the same scrimmed modal. The tablet band's side
   rail is kept (thumbs live at the screen's sides in landscape). */
@media (min-width: 541px) and (max-width: 1023px) and (max-height: 540px) and (pointer: coarse) {
  /* .dev-main in the selector out-ranks the (1,2,0) desktop positioning
     rules (.dev-main.detail-open #dev-detail) that kept a 56px header strip. */
  html.mobile-v2 .dev-main #dev-detail {
    top: 0; left: 0; right: 0; bottom: 0;
    width: 100%; max-width: none;
    z-index: 12;
    border: none; border-radius: 0;
  }
  html.mobile-v2 #dev-detail:has(.panel-v5) .pv5-card__band {
    position: fixed !important;
    top: 0; left: 0; right: 0;
    z-index: 14;
    padding-top: 4px;
    background: var(--bg-paper, #faf9f7);
    border-bottom: 1px solid var(--line, #e7e5e4);
  }
  html.mobile-v2 #dev-detail:has(.panel-v5) .pv5-deck { padding-top: 56px; }
  html.mobile-v2 #dev-detail:has(.panel-v5) .pv5-card__tabs {
    position: fixed !important;
    top: auto !important;
    bottom: 0; left: 0; right: 0;
    z-index: 14;
    background: var(--bg-paper, #faf9f7);
    border-top: 1px solid var(--line, #e7e5e4);
    border-bottom: none;
    padding: 4px 6px;
    overflow-x: auto;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
  }
  html.mobile-v2 #dev-detail:has(.panel-v5) .pv5-card { padding-bottom: 60px; }
  html.mobile-v2 #dev-map .dev-legend.is-mobile-open {
    display: block;
    position: fixed; left: 0; right: 0; top: auto; bottom: 0;
    max-height: 78vh; overflow-y: auto;
    z-index: 13;
    background: var(--bg-paper, #faf9f7);
    border-radius: 16px 16px 0 0;
    padding: 14px 16px;
    overscroll-behavior: contain;
  }
  html.mobile-v2 #dev-map .dev-legend.is-mobile-open .dev-legend-row { margin: 0; }
  html.mobile-v2 .sm-preview { bottom: 10px; right: 84px; /* clear the side rail */ }
  /* Landscape: the card is right-inset past the control column, so the
     controls keep their own bottom — lifting them here would push them off
     a 390px-tall viewport. */
  html.mobile-v2.sm-preview-open .mapboxgl-ctrl-bottom-right,
  html.mobile-v2.sm-preview-open .mapboxgl-ctrl-bottom-left {
    bottom: calc(var(--hdm-bar-h, 56px) + 4px);
  }
  html.mobile-v2 #dev-nav {
    background: var(--bg-paper, #faf9f7);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* Reduced motion: the global kill switch in dev.css already nukes
   transitions/animations; nothing here depends on transitionend. */
