/* Page-scoped styling for the public /explorer map. Loaded only on
 * /explorer (via page_layout's extra_head), never globally — the map IS
 * the page: it fills the entire viewport and every piece of chrome (nav,
 * hero, legend, cursor, attribution, popup) floats over it as an absolute
 * overlay. The page is rendered full_bleed (no .container gutter, no
 * footer), so the positioning context can run edge-to-edge. */

/* Full-viewport positioning context. The map root fills it; all chrome
 * (incl. the nav) is absolutely positioned against it. 100dvh tracks the
 * mobile dynamic viewport (browser UI collapse) and falls back to 100vh on
 * engines without dvh support. */
/* Pico's global stylesheet pads every <main> landmark with vertical block
 * spacing (~1rem top + bottom). The full-bleed explorer renders the map
 * inside that <main>, so its 100dvh .explorer-page is pushed down by the top
 * inset AND overflows the viewport bottom by the same amount — clipping the
 * bottom map edge, the MapLibre attribution, and the mobile bottom-sheet's
 * lower content, and leaving the whole document scrollable behind the fixed
 * map (worst on phones, where vertical space is scarce). Zero the host main's
 * padding so the page truly owns the viewport edge-to-edge. Page-scoped: this
 * sheet only loads on /explorer, so the rule never touches a normal page's
 * <main>. */
main:has(> .explorer-page) {
    padding: 0;
}

.explorer-page {
    position: relative;
    width: 100%;
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
    /* Expose the device safe-area insets (notch / rounded corners / home
     * indicator) as tokens the overlays add to their edge offsets, so the
     * nav links + corner chrome clear the unsafe zone on iOS et al. The
     * env() fallback is 0, so non-mobile/desktop layout is unchanged. */
    --ds-safe-top: env(safe-area-inset-top, 0px);
    --ds-safe-right: env(safe-area-inset-right, 0px);
    --ds-safe-bottom: env(safe-area-inset-bottom, 0px);
    --ds-safe-left: env(safe-area-inset-left, 0px);
}

/* The nav floats over the top edge of the map — a sibling of #map_root,
 * not a normal-flow bar above it (which would push the map down). Instead
 * of a hard chrome bar it lays down a top-down gradient scrim: the map
 * shows through below the links for a tasteful full-bleed look while the
 * scrim keeps the white nav text legible over bright bathymetry. The
 * content row is inset by the device safe area so the brand + login link
 * clear the notch / rounded corners. */
.explorer-nav {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 6;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--ds-space-2);
    padding:
        calc(var(--ds-space-1) + var(--ds-safe-top))
        calc(var(--ds-space-2) + var(--ds-safe-right))
        var(--ds-space-3)
        calc(var(--ds-space-2) + var(--ds-safe-left));
    background: var(--ds-map-scrim-top);
    color: #fff;
    /* Dark halo keeps the white brand/login text legible even where the
     * scrim has faded thinnest over bright shelf bathymetry (WCAG AA without
     * relying on the gradient's unmeasured thinnest point). */
    text-shadow: var(--ds-map-text-halo);
    /* Scrim is decorative chrome; never intercept map drags outside the
     * actual links (the links + brand re-enable pointer events). */
    pointer-events: none;
}
/* Users who need maximal contrast get a hard opaque bar instead of the soft
 * gradient — the scrim's transparent tail is replaced by a solid panel. */
@media (prefers-contrast: more) {
    .explorer-nav {
        background: var(--ds-map-scrim-top-solid);
    }
}
.explorer-nav > * {
    pointer-events: auto;
}
.explorer-nav-login {
    align-self: center;
    color: #fff;
}
/* The global nav hides .nav-title under 768px (the authed nav is crowded
 * with links + admin dropdown). The public explorer nav holds only the
 * brand + a Log in link, so the title fits even on phones and anchors the
 * page identity — keep it visible, truncating instead of wrapping if a
 * very narrow viewport ever runs short. */
.explorer-nav .nav-title {
    display: inline;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
/* Focus ring legible over both the scrim and bright bathymetry: a white
 * halo with a dark gap so it reads against either backdrop. */
.explorer-nav a:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
    border-radius: var(--ds-radius-sm);
}
/* Hover affordance on the otherwise chrome-flat login link. */
.explorer-nav-login:hover {
    text-decoration: underline;
}

#map_root {
    /* The map fills the whole positioning context — it is the page. */
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    background: var(--ds-map-void); /* dark ocean void while tiles load */
}

/* --- Chrome overlays. z-index (low→high): canvas < legend < hero <
 * cursor readout < popup/bottom-sheet (.map-popup is z 5). --- */
.map-hero,
.map-legend,
.map-cursor {
    position: absolute;
    background: var(--ds-map-chrome-bg);
    color: #fff;
    border-radius: var(--ds-radius-sm);
    padding: var(--ds-space-1) var(--ds-space-2);
}

/* The nav now owns the top edge, so the top-anchored overlays (hero,
 * cursor readout) clear its bar. --ds-explorer-nav-clear is the nav's
 * bar height (its content row + vertical padding) plus a gap, so a tweak
 * to the nav padding only needs touching here. */
:root { --ds-explorer-nav-clear: 3.5rem; }

.map-hero {
    top: calc(var(--ds-explorer-nav-clear) + var(--ds-safe-top));
    left: calc(var(--ds-space-2) + var(--ds-safe-left));
    z-index: 3;
    max-width: min(20rem, 70%);
}
.map-hero-title { display: block; }
.map-hero-counts {
    margin: var(--ds-space-0) 0 0;
    font-size: var(--ds-font-sm);
}

.map-legend {
    bottom: calc(var(--ds-space-2) + var(--ds-safe-bottom));
    left: calc(var(--ds-space-2) + var(--ds-safe-left));
    z-index: 2;
    font-size: var(--ds-font-sm);
    /* The legend carries role="group", which Pico styles as a full-width
       flex row — that stretched the chrome bar across the whole bottom edge
       (overlapping the centered attribution). Pin it back to a content-sized
       box with its two rows stacked. */
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    width: fit-content;
    right: auto;
}
.map-legend-row {
    display: flex;
    align-items: center;
    gap: var(--ds-space-1);
}
/* The swatch must depict a footprint AS RENDERED, not a saturated solid
 * block: on the map each fill sits at a low opacity over the dark ocean
 * void inside its line-colour outline. Reproduce that faithfully so the
 * key teaches the colour the visitor actually sees — void base, the fill
 * at its real fill-opacity (via the ::before overlay, since `background`
 * can't carry a separate alpha from a hex token), and the line outline. */
.legend-swatch {
    position: relative;
    width: 0.9rem;
    height: 0.9rem;
    border-radius: 2px;
    flex: 0 0 auto;
    background: var(--ds-map-void);
}
.legend-swatch::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
}
.legend-swatch-vivid {
    border: 1px solid var(--ds-map-vivid-line);
}
.legend-swatch-vivid::before {
    background: var(--ds-map-vivid-fill);
    opacity: var(--ds-map-vivid-fill-opacity);
}
.legend-swatch-muted {
    border: 1px solid var(--ds-map-muted-line);
}
.legend-swatch-muted::before {
    background: var(--ds-map-muted-fill);
    opacity: var(--ds-map-muted-fill-opacity);
}

.map-cursor {
    /* Top-right, clear of the nav bar: the bottom-right corner is occupied
       by MapLibre's own attribution control, which the readout used to
       overlap. */
    top: calc(var(--ds-explorer-nav-clear) + var(--ds-safe-top));
    right: calc(var(--ds-space-2) + var(--ds-safe-right));
    z-index: 4;
    font-family: var(--pico-font-family-monospace, ui-monospace, monospace);
    font-variant-numeric: tabular-nums;
    font-size: var(--ds-font-xs);
    min-height: 1.4em; /* reserve space so the layout doesn't jump on first move */
}

/* Mobile: the popup docks as a bottom sheet over the bottom-left legend;
 * drop the legend below the cursor readout's corner and let the sheet
 * (z 5) sit on top. A clean popup-open data-show hide is deferred — the
 * z-order already prevents the sheet being obscured. */
@media (max-width: 640px) {
    .map-legend { display: none; }
}

/* Clickability affordance. MapLibre toggles `.maplibregl-interactive` on
 * the canvas container for hit-tested layers and sets an inline cursor on
 * the bare <canvas> during drag/grab — so the rule targets the container
 * class (a stylesheet rule there wins on the non-dragging base state),
 * NOT `#map_root canvas` which the inline drag cursor would override. */
#map_root .maplibregl-canvas-container.maplibregl-interactive {
    cursor: pointer;
}
