/* Small spinner shown on top of the still-visible map while a selection (layer
   toggle, year, depth scenario, ...) is being recomputed -- see #map's comment
   in app.py. Dash tags #map with data-dash-is-loading="true" for as long as
   update_map (its "figure" callback) is running; this rule just reacts to that
   attribute with a sibling-selector, no callback or JS of its own needed.
   Deliberately NOT a full-screen dimmer/backdrop -- just the circle itself, so
   the map underneath stays visible instead of blanking out.
   Defaults to black because the very first time it shows -- the initial page
   load -- the map hasn't rendered yet, so the spinner sits on the plain white
   page background where a white spinner is invisible. assets/loading_spinner.js
   adds "app-loaded" to <body> the first time that initial load finishes, which
   flips it back to white for every load after that (map tiles behind it by then). */
.map-spinner {
    display: none;
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    margin: -22px 0 0 -22px;
    border-radius: 50%;
    border: 4px solid rgba(0, 0, 0, 0.35);
    border-top-color: #000;
    z-index: 2000;
    pointer-events: none;
    animation: map-spinner-rotate 0.8s linear infinite;
}

body.app-loaded .map-spinner {
    border-color: rgba(255, 255, 255, 0.35);
    border-top-color: #fff;
}

#map[data-dash-is-loading="true"] ~ .map-spinner {
    display: block;
}

@keyframes map-spinner-rotate {
    to { transform: rotate(360deg); }
}

/* Riverbed Surveys layer-toggle option has multi-line label content (title,
   subtitle, risk swatches), so the default vertical-centered checkbox floats
   next to the middle of the whole block instead of the "Riverbed Surveys"
   title. Pin it to the top of that option only -- the other layer-toggle
   options are single-line and stay centered via the inline labelStyle. */
#layer-toggle-full .dash-options-list-option-wrapper:first-child .dash-options-list-option,
#layer-toggle-full > label:first-child {
    align-items: flex-start !important;
}

#layer-toggle-full .dash-options-list-option-wrapper:first-child .dash-options-list-option-checkbox,
#layer-toggle-full > label:first-child input[type="checkbox"] {
    margin-top: 3px;
}

/* "?" info badge next to each layer-toggle label -- pure CSS hover tooltip, no
   click handling needed (and none wanted, since these labels sit inside the
   checkbox's <label> and a click would toggle the layer). */
.layer-info-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    margin-left: 6px;
    border-radius: 50%;
    border: 1px solid #888;
    color: #888;
    font-size: 10px;
    line-height: 1;
    cursor: help;
    position: relative;
    flex-shrink: 0;
    vertical-align: middle;
}

.layer-info-icon .layer-info-tooltip {
    visibility: hidden;
    opacity: 0;
    position: absolute;
    z-index: 1000;
    left: 20px;
    top: 50%;
    transform: translateY(-50%);
    width: 200px;
    background: #1b3a5c;
    color: #fff;
    font-family: 'DM Sans', sans-serif;
    font-size: 12px;
    line-height: 1.4;
    text-align: left;
    padding: 8px 10px;
    border-radius: 6px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.25);
    transition: opacity 0.15s ease;
    pointer-events: none;
}

.layer-info-icon:hover .layer-info-tooltip {
    visibility: visible;
    opacity: 1;
}

/* Riverbed Surveys tooltip has a longer explanation plus a 3-line risk
   breakdown, so it needs more width than the default 200px box to stay
   readable instead of turning into a tall, narrow column. */
.layer-info-icon .layer-info-tooltip-wide {
    width: 300px;
}

/* River Depth tooltip needs enough width that "River Depth = Riverbed
   Elevation - River Surface Elevation." fits on a single line. */
.layer-info-icon .layer-info-tooltip-xwide {
    width: 400px;
}

/* River Depth Scenarios' two RadioItems (depth-scenario-radio-today,
   depth-scenario-radio-years) -- dash's own default per-option padding
   (--Dash-Spacing, 4px top+bottom) stacks with the margins already set on
   these two in app.py, reading as a much bigger gap than the rest of this
   compact legend box uses. Tighten it down just for this box. */
#depth-scenario-content .dash-options-list-option {
    padding: 1px 0;
}

/* Constraining Points callout -- a speech bubble popping out of the legend's
   "Constraining Points" row, pointing an arrow back at it, so it still reads as
   explaining that specific row rather than a random dialog. Shown once, right after the
   welcome modal closes (see close_welcome/close_constrain_callout in app.py). The
   anchor just needs position:relative so the popout's left:100% is relative to this
   row rather than the whole legend card.

   Two bugs this needs to keep dodging:
   - Width: popping out at a fixed 270px past left:100% can run past the right edge of
     the screen on an in-between width (e.g. a ~800px iPad). min()'d against the actual
     viewport width lets it shrink instead of overflow.
   - Stacking: this box's own z-index only wins against *siblings inside the legend* --
     it's still a descendant of map-controls-stack (zIndex 10), so on Current Conditions
     (where the price-plots panel, zIndex 15, auto-opens on load, right as this callout
     would be shown) the plots panel painted over this box and its own ✕, with no way to
     reach it. Fixed not here but in app.py: close_welcome/close_constrain_callout
     toggle a "legend-elevated" className on map-controls-stack that lifts the whole
     legend's zIndex above every other floating panel while this is open. */
.constrain-callout-anchor {
    position: relative;
}

.constrain-callout-popout {
    position: absolute;
    left: 100%;
    top: -10px;
    margin-left: 16px;
    width: min(270px, calc(100vw - 100px));
    z-index: 50;
    background: white;
    color: #333;
    font-family: Arial, sans-serif;
    font-size: 14px;
    line-height: 1.5;
    padding: 14px 18px;
    border-radius: 8px;
    border: 2px solid #d62728;
    box-shadow: 0 2px 10px rgba(0,0,0,0.4);
}

.constrain-callout-popout::before {
    content: "";
    position: absolute;
    left: -8px;
    top: 16px;
    width: 0;
    height: 0;
    border-top: 8px solid transparent;
    border-bottom: 8px solid transparent;
    border-right: 8px solid #d62728;
}

/* map-controls-stack's own zIndex (10, set inline in app.py) is too low to keep the
   Constraining Points callout above the plots panel/tab stack while it's shown -- see
   the callout's own comment above. Toggled by close_welcome/close_constrain_callout. */
#map-controls-stack.legend-elevated {
    z-index: 48 !important;
}

/* ==========================================================================
   Mobile layout (phones / narrow tablets)
   The desktop layout is built from fixed-px floating panels over a full-height
   map, which is fine on a laptop screen but overflows or clips on a phone.
   Everything below only kicks in under 768px; desktop is untouched. Most of
   these panels get their base look from inline `style={}` dicts set in
   app.py's Python layout (and swapped between hidden/visible dicts by
   callbacks), so overriding them here requires `!important`.
   ========================================================================== */
@media (max-width: 768px) {

    /* Header: title + nav no longer fit in one row, so stack them instead of
       letting the row overflow sideways */
    #app-header {
        flex-direction: column !important;
        align-items: flex-start !important;
        height: auto !important;
        padding: 10px 14px !important;
        gap: 8px;
    }
    #app-title {
        margin: 0 !important;
        font-size: 18px !important;
        letter-spacing: 0.5px !important;
    }
    #nav-links {
        width: 100%;
        flex-wrap: wrap;
        gap: 4px 14px;
    }
    #nav-links button {
        margin-left: 0 !important;
        font-size: 12px !important;
        padding: 4px 2px !important;
    }

    /* Map fills whatever's left under the now-taller (wrapped) header */
    #map-container {
        height: 85vh !important;
    }

    /* Year/layers control box: the desktop version (year dropdown + 5-layer
       checklist, one of which has a full risk-tier breakdown) is tall enough
       to cover most of a phone screen. Cap it to a fraction of the viewport
       in both directions and let it scroll internally instead. */
    #map-controls {
        max-width: 58vw !important;
        max-height: 42vh !important;
        overflow-y: auto;
    }
    #historic-year-note {
        max-width: 58vw !important;
    }
    #year-select-wrapper, #layer-toggle-wrapper {
        width: 100% !important;
    }

    #historic-purpose-heading {
        font-size: 15px !important;
        max-width: 78vw !important;
        white-space: normal !important;
    }

    /* Constraining Points callout: desktop pops it out to the right of the legend row
       (left:100%), but there's no room for that on a phone. Popping it below the row
       in-flow (position:static) used to be the fallback, but the row sits inside
       #map-controls' own scrollable 42vh box above, so the callout became part of that
       scroll -- it read as stuck inside the legend rather than an overlay explaining it,
       and its own ✕ could end up needing a scroll to reach. Pinning it just below the
       legend's own capped height (42vh + the 15px it's offset from the top) instead
       keeps it a real overlay -- out of that scroll -- while still reading as attached to
       the legend right above it. left+right (no width) clamps it to the viewport so it
       can never run off either edge; max-height/overflow-y guard the rare case where the
       callout's own text is taller than what's left of a short landscape viewport. */
    .constrain-callout-popout {
        position: fixed !important;
        top: calc(15px + 42vh + 8px) !important;
        left: 15px !important;
        right: 12px !important;
        width: auto !important;
        max-width: none !important;
        margin: 0 !important;
        max-height: calc(100vh - 15px - 42vh - 24px);
        overflow-y: auto;
    }
    .constrain-callout-popout::before {
        display: none;
    }

    /* Floating detail panels (notice/gage click-throughs) are sized in px for
       a desktop map; cap them so they can't run off a phone screen */
    #notice-detail-box,
    #gage-detail-box {
        max-width: 78vw !important;
        width: auto !important;
    }

    /* River Depth Scenarios box is a fixed 300px on desktop -- cap it to the
       same width as the legend above it so it can't push past the screen edge */
    #depth-scenario-wrapper {
        width: 58vw !important;
        max-width: 58vw !important;
    }

    /* Price-plots slide-out panel: its desktop width (400px, see
       PLOTS_PANEL_WIDTH) is as wide as most phone screens, so opening it hid
       the map completely. An earlier fix capped it to 80vw, but the panel
       also carries 20px of its own left+right padding (40px total, see
       PLOTS_PANEL_OPEN in app.py) on top of that CSS width -- the actual
       on-screen box came out closer to 90% of the viewport, leaving only a
       sliver of map too thin to read. In practice you could see the plots or
       the map but not both the way desktop lets you. calc(60vw - 40px)
       targets the padding-inclusive on-screen width directly, landing the
       panel at an actual 60% of the viewport and leaving a genuinely usable
       ~40% strip of map alongside it, at the cost of tighter charts. Matches
       PLOTS_PANEL_WIDTH's actual "400px" (the old rule here checked for
       "420px", which never matched, so this never actually applied). Only
       matters when open -- the closed state is width:0. The toggle tab
       itself (#plots-toggle, in #right-tabs-stack) is a separate
       position:absolute element pinned to the map's right edge above the
       panel (zIndex 20 vs. the panel's 15), so it's never covered by the
       panel regardless of width -- closing it back out is always reachable. */
    #plots-panel[style*="400px"] {
        width: calc(60vw - 40px) !important;
    }
    #plots-toggle {
        font-size: 11px !important;
        padding: 8px 5px !important;
    }

    /* Full-page sections: desktop padding is generous, phones need it tight */
    #demand-page, #about-page {
        padding: 16px 14px !important;
    }

    /* Demand-page explanation boxes and chart columns are flex items with a
       400px min-width for the desktop side-by-side layout -- on a phone that
       min-width is wider than the screen itself, forcing horizontal scroll.
       Let them shrink to full-width single-column instead. */
    .demand-explanation-box, .crop-chart-col {
        min-width: 0 !important;
        width: 100% !important;
    }

    /* Compare-years modal holds fixed-width (596px) Plotly figures that won't
       resize themselves -- cap the modal to the viewport and let the figures
       scroll horizontally inside it rather than blowing out the page */
    #compare-years-box {
        width: 92vw !important;
        max-width: 92vw !important;
        padding: 30px 10px 16px 10px !important;
        overflow-x: auto;
    }
    #compare-years-toggle {
        font-size: 14px !important;
        padding: 10px 16px !important;
        width: 100%;
        box-sizing: border-box;
    }
}

/* ==========================================================================
   Phone layout (narrower than the 768px tablet breakpoint above)
   The legend ("Layers" box) is built from a couple dozen individually-set
   px font-sizes and icon heights, tuned to look right on a laptop. Capped to
   58vw it's still legible on an iPad -- there's enough actual screen there --
   but the exact same px values on a ~390px-wide phone read as oversized for
   how little screen the phone actually has. Rather than hand-shrinking each
   of those many explicit sizes individually, every row's text content is
   marked with the shared .cc-legend-row-text class (see _cc_legend_row,
   FULL_LAYER_OPTIONS, and CC_LAYER_OPTIONS in app.py) so one rule can
   collapse all of them to a single smaller size at once -- row-to-row
   hierarchy still reads through font-weight (bold headers vs. plain notes),
   which this doesn't touch. Deliberately does NOT touch the Constraining
   Points callout (.constrain-callout-popout) even though it's nested inside
   this same legend -- that box isn't tagged with .cc-legend-row-text, so
   it keeps its own (already-legible) sizing.
   ========================================================================== */
@media (max-width: 480px) {
    /* Welcome modal: smaller padding and a visible margin on each side, so it
       reads as a pop-up over the map instead of filling the screen. Pinned to
       the screen (not the map, which runs past the bottom of a phone screen) so
       the max-height keeps the whole box on screen; the rest scrolls inside it. */
    #welcome-box {
        position: fixed !important;
        max-width: calc(100% - 40px) !important;
        max-height: calc(100dvh - 48px) !important;
        padding: 20px 20px 18px 20px !important;
    }
    #welcome-backdrop {
        position: fixed !important;
    }
    #map-controls {
        max-width: 52vw !important;
        padding: 8px 10px !important;
    }
    .cc-legend-row-text,
    .cc-legend-row-text * {
        font-size: 11px !important;
    }
    #layer-toggle-wrapper img {
        height: 14px !important;
        width: auto !important;
    }
    .layer-info-icon {
        width: 11px !important;
        height: 11px !important;
        font-size: 8px !important;
    }
}

/* ==========================================================================
   Phones (same 600px cutoff as detect_phone_screen in app.py): the plots
   panel doesn't auto-open here, so when someone taps it open they want the
   charts -- give it the map's full width instead of the 60% split above
   (which squeezed each chart to ~190px). Extra right padding keeps the ✕ tab
   (pinned over the panel's right edge) from covering the charts. Solid
   background (the desktop one is 97% opaque) so the Layers box underneath
   doesn't ghost through -- #f7f7f7 is what that 97% white looks like over
   the dark map anyway.
   ========================================================================== */
@media (max-width: 600px) {
    #plots-panel[style*="400px"] {
        background: #f7f7f7 !important;
        width: 100% !important;
        box-sizing: border-box !important;
        padding: 16px 34px 16px 12px !important;
    }
}
