/* css/02-shell.css — app frame: full-bleed stage.
   Split from the index.html <style> block (REFACTOR-PLAN Phase 2). Load order = cascade order; do not reorder. */
/* ---------- app frame: full-bleed stage under everything ---------- */
#app{position:fixed;inset:0;background:var(--bg);opacity:1;transform:translateY(0);
  transition:opacity .2s var(--ease),transform .2s var(--ease)}
#app.hide{opacity:0;transform:translateY(8px);visibility:hidden}
#stage{position:absolute;inset:0;z-index:0;background:#0A0F11}
#stage canvas{position:absolute;inset:0;width:100%;height:100%}
.mapgl{position:absolute;inset:0}
/* vignette: keeps glass legible over any tile, and darkens the frame so the lit
   centre of the city reads as the subject */
#vignette{position:absolute;inset:0;pointer-events:none;z-index:2;
  background:
    radial-gradient(126% 96% at 50% 46%, rgba(7,10,11,0) 32%, rgba(7,10,11,.44) 70%, rgba(7,10,11,.86) 100%),
    linear-gradient(180deg, rgba(7,10,11,.78) 0, rgba(7,10,11,0) 15%),
    linear-gradient(0deg, rgba(7,10,11,.70) 0, rgba(7,10,11,0) 20%)}
/* pass 23 (client, verbatim): "in the re-rectify cameras module or any other
   module, we do not need to have the map in the background — this is just for
   the inspection." The map is therefore painted on Drive ONLY.
   It is NOT unmounted: re-creating a MapLibre instance costs a style fetch, a
   fresh GL context and every source/layer the trail and the detections live in,
   and Drive has to come back instantly with its camera exactly where it was.
   `visibility` keeps the element laid out at full size — `display:none` would
   collapse the canvas to 0x0 and MapLibre would come back mis-sized — and
   setView('drive') still calls resizeMap() on the way in for the case where the
   window was resized while Drive was off screen.
   Off Drive #stage itself becomes the opaque surface every non-map module sits
   on: the token background, not a dimmed basemap, which is what the scrim used
   to approximate. With nothing to dim, the scrim stays off. */
#scrim{position:absolute;inset:0;z-index:3;pointer-events:none;opacity:0;
  background:rgba(7,10,11,.66);transition:opacity .2s var(--ease)}
body:not([data-view="drive"]) #map,
body:not([data-view="drive"]) #vignette{visibility:hidden}
body:not([data-view="drive"]) #stage{background:var(--bg)}
/* Home re-hosts the #start screen (its own full-bleed sector preview) BEHIND
   the app shell, so the stage must not paint over it at all there. */
body[data-view="home"] #stage{visibility:hidden}
/* verify-wave15 POINTER ROUTING: main is pointer-events:none so the shared
   map stage stays grabbable on Drive. Off Drive that made every drag, tap and
   wheel that missed an opted-in element fall THROUGH the screen onto #map,
   which panned/tilted the basemap under the UI (and swallowed list scrolls).
   Off Drive the stage takes no pointer input at all — MapLibre's own handlers
   are also disabled in setView(), so a gesture cannot start there either. */
body:not([data-view="drive"]) #map,
body:not([data-view="drive"]) #map .maplibregl-canvas-container,
body:not([data-view="drive"]) #map canvas{pointer-events:none!important;touch-action:none}

