/* ===================================================================
   MAP LAYERS  -  shared map overlay control
   ===================================================================
   Zoning, cadastral lots, land use, population and basemap, as one
   panel that can be dropped onto any Mapbox map on the site.

   Extracted verbatim from draw.php, where it was built and proven. The
   ONLY changes made in the move:
     - every var() gained a fallback, because host pages are not
       required to define draw.php's :root block;
     - the two absolutely-positioned roots take their offsets from
       --ov-btn-* / --ov-panel-* so a host can place the control
       without editing this file;
     - the .ov-compact block at the end is new - a bottom-sheet layout
       for the short embedded maps this now has to fit inside.

   Pairs with mapLayers.js. Neither file is useful without the other.
   =================================================================== */

/* Reuses the .tt-panel geometry and chrome from draw.php on purpose, so a
   map that carries both has one panel language rather than two. */
.ov-toggle-btn {
    position: absolute;
    /* Top-left, at Mapbox's own 10px control inset, so on a map with no
       other left-hand chrome it lines up with the navigation control on the
       right. draw.php is the exception, not the default: it has a 36px
       fullscreen toggle above this one, so it sets
       --ov-btn-top: calc(1rem + 36px + 0.4rem) and --ov-btn-left: 1rem to
       keep its stack. Carrying that offset as the DEFAULT left every other
       host with a 36px gap above the button and nothing in it. */
    top: var(--ov-btn-top, 10px);
    left: var(--ov-btn-left, 10px);
    z-index: 10;
    width: 36px;
    height: 36px;
    background: #fff;
    border: 1px solid var(--map-panel-border, rgba(0, 95, 110, 0.2));
    border-radius: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
    color: var(--text-color, #1A171B);
    transition: all 0.2s ease;
    padding: 0;
    font-size: 0.95rem;
}
.ov-toggle-btn:hover {
    background: rgba(0, 95, 110, 0.1);
    border-color: var(--primary-color, #005F6E);
    color: var(--primary-color, #005F6E);
}
.ov-toggle-btn.active {
    background: var(--primary-color, #005F6E);
    border-color: var(--primary-color, #005F6E);
    color: #fff;
}
.ov-toggle-btn[data-tooltip]:hover::after {
    content: attr(data-tooltip);
    position: absolute;
    left: 44px;
    background: var(--dark-color, #1A171B);
    color: #fff;
    padding: 0.4rem 0.6rem;
    border-radius: 4px;
    font-size: 0.7rem;
    white-space: nowrap;
    pointer-events: none;
    z-index: 20;
}

.ov-panel {
    position: absolute;
    /* Clear of the toggle above: 10px inset + 36px button + 8px gap. */
    top: var(--ov-panel-top, 10px);
    left: var(--ov-panel-left, 54px);
    width: var(--ov-panel-width, 320px);
    max-height: var(--ov-panel-max-h, calc(100% - 2rem));
    display: flex;
    flex-direction: column;
    background: var(--map-panel-bg, rgba(255, 255, 255, 0.97));
    border: 1px solid var(--map-panel-border, rgba(0, 95, 110, 0.2));
    border-radius: 10px;
    z-index: 12;
    backdrop-filter: blur(10px);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
    overflow: hidden;
    animation: ovSlideIn 0.25s ease-out;
    font-family: 'DM Sans', sans-serif;
}

.ov-panel-head {
    background: var(--dark-color, #1A171B);
    padding: 0.75rem 1rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex: 0 0 auto;
}

.ov-panel-head h4 {
    margin: 0;
    color: #fff;
    font-size: 0.9rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.ov-panel-head h4::before {
    content: '';
    display: inline-block;
    width: 3px;
    height: 14px;
    background: var(--accent-color, #ED8B00);
    margin-right: 8px;
    vertical-align: middle;
}

.ov-panel-close {
    background: none;
    border: none;
    color: rgba(255, 255, 255, 0.6);
    cursor: pointer;
    font-size: 0.85rem;
    padding: 4px;
    transition: color 0.15s;
}

.ov-panel-close:hover { color: #fff; }

.ov-panel-body {
    padding: 0.85rem 1rem 1rem;
    overflow-y: auto;
    flex: 1 1 auto;
}

/* --- one row per overlay ------------------------------------------- */
.ov-row + .ov-row {
    margin-top: 0.6rem;
    padding-top: 0.6rem;
    border-top: 1px solid var(--map-panel-border, rgba(0, 95, 110, 0.2));
}

.ov-row-head {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.ov-row-title {
    flex: 1;
    min-width: 0;
}

.ov-row-title b {
    display: block;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--dark-color, #1A171B);
    line-height: 1.2;
}

.ov-row-title span {
    display: block;
    font-size: 0.68rem;
    color: #6b7280;
    line-height: 1.3;
    margin-top: 1px;
}

/* Switch. Built from a checkbox so it stays keyboard-operable. */
.ov-switch { position: relative; width: 38px; height: 21px; flex: 0 0 auto; }
.ov-switch input {
    position: absolute; inset: 0; opacity: 0; margin: 0;
    width: 100%; height: 100%; cursor: pointer; z-index: 2;
}
.ov-switch i {
    position: absolute; inset: 0; border-radius: 21px;
    background: #cbd5e1; transition: background 0.2s;
}
.ov-switch i::after {
    content: ''; position: absolute; top: 2px; left: 2px;
    width: 17px; height: 17px; border-radius: 50%;
    background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.3);
    transition: transform 0.2s;
}
.ov-switch input:checked + i { background: var(--primary-color, #005F6E); }
.ov-switch input:checked + i::after { transform: translateX(17px); }
.ov-switch input:focus-visible + i {
    outline: 2px solid var(--accent-color, #ED8B00); outline-offset: 2px;
}
.ov-switch input:disabled { cursor: not-allowed; }
.ov-switch input:disabled + i { background: #e5e7eb; }

/* Per-overlay detail, revealed only when that overlay is on */
.ov-detail { margin-top: 0.55rem; display: none; }
.ov-row.on .ov-detail { display: block; }

.ov-opacity {
    display: flex; align-items: center; gap: 0.5rem;
    font-size: 0.68rem; color: #6b7280;
}
.ov-opacity input[type=range] {
    flex: 1; height: 4px; -webkit-appearance: none; appearance: none;
    background: #e2e8f0; border-radius: 2px; outline: none; cursor: pointer;
}
.ov-opacity input[type=range]::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 14px; height: 14px; border-radius: 50%;
    background: var(--primary-color, #005F6E); cursor: pointer;
}
.ov-opacity input[type=range]::-moz-range-thumb {
    width: 14px; height: 14px; border: none; border-radius: 50%;
    background: var(--primary-color, #005F6E); cursor: pointer;
}

/* --- legend, which doubles as the class filter ----------------------- */
.ov-legend { margin-top: 0.5rem; }

.ov-legend-hint {
    font-size: 0.64rem; color: #9ca3af; margin-bottom: 0.35rem;
}

.ov-swatches { display: flex; flex-wrap: wrap; gap: 3px; }

.ov-sw {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 2px 7px 2px 4px;
    border: 1px solid var(--map-panel-border, rgba(0, 95, 110, 0.2));
    border-radius: 20px; background: #fff;
    font-size: 0.63rem; color: var(--dark-color, #1A171B);
    cursor: pointer; user-select: none;
    transition: opacity 0.15s, border-color 0.15s;
}
.ov-sw i {
    width: 10px; height: 10px; border-radius: 3px;
    border: 1px solid rgba(0,0,0,0.15); flex: 0 0 auto;
}
.ov-sw:hover { border-color: var(--primary-color, #005F6E); }
/* Muted rather than hidden: a filtered-out class must still be findable. */
.ov-sw.off { opacity: 0.32; }

.ov-legend-actions {
    display: flex; gap: 0.4rem; margin-top: 0.45rem;
}
.ov-mini {
    flex: 1; padding: 3px 0; font-size: 0.64rem;
    border: 1px solid var(--map-panel-border, rgba(0, 95, 110, 0.2)); border-radius: 5px;
    background: #fff; color: #6b7280; cursor: pointer;
    transition: all 0.15s;
}
.ov-mini:hover {
    border-color: var(--primary-color, #005F6E); color: var(--primary-color, #005F6E);
}

.ov-note {
    margin-top: 0.5rem; font-size: 0.63rem; line-height: 1.4;
    color: #9ca3af;
}
.ov-note b { color: #6b7280; font-weight: 600; }

/* Shown when the current view has no data for an overlay */
.ov-warn {
    margin-top: 0.45rem; padding: 0.4rem 0.55rem;
    background: rgba(237, 139, 0, 0.1);
    border-left: 2px solid var(--accent-color, #ED8B00);
    border-radius: 3px; font-size: 0.65rem; color: #92400e;
    line-height: 1.35;
}

/* --- click popup ------------------------------------------------------ */
.ov-pop .mapboxgl-popup-content {
    padding: 0; border-radius: 8px; overflow: hidden;
    box-shadow: 0 6px 24px rgba(0,0,0,0.18);
    font-family: 'DM Sans', sans-serif;
    min-width: 210px;
}
.ov-pop .mapboxgl-popup-close-button {
    color: rgba(255,255,255,0.75); font-size: 1.1rem;
    padding: 2px 7px; right: 2px; top: 1px;
}
.ov-pop .mapboxgl-popup-close-button:hover {
    background: none; color: #fff;
}
.ov-pop-head {
    background: var(--dark-color, #1A171B); color: #fff;
    padding: 0.5rem 1.6rem 0.5rem 0.75rem;
}
.ov-pop-code {
    font-size: 0.95rem; font-weight: 700; letter-spacing: -0.01em;
    line-height: 1.1;
}
.ov-pop-name {
    font-size: 0.7rem; opacity: 0.82; margin-top: 1px; line-height: 1.25;
}
.ov-pop-body { padding: 0.55rem 0.75rem 0.65rem; }
.ov-pop-cls {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: 0.68rem; color: var(--dark-color, #1A171B); font-weight: 600;
}
.ov-pop-cls i {
    width: 10px; height: 10px; border-radius: 3px;
    border: 1px solid rgba(0,0,0,0.15);
}
.ov-pop-meta {
    margin-top: 0.4rem; font-size: 0.65rem; color: #6b7280;
    line-height: 1.4;
}
.ov-pop-meta b { color: var(--dark-color, #1A171B); font-weight: 600; }

@media (max-width: 768px) {
    .ov-panel {
        right: 0.5rem; left: 0.5rem; width: auto;
        top: auto; bottom: 0.5rem; max-height: 58%;
    }
}

/* The overlay panel now opens from the LEFT, so it slides in from the
   left rather than reusing the travel-time panel's rightward motion. */
@keyframes ovSlideIn {
    from { opacity: 0; transform: translateX(-20px); }
    to   { opacity: 1; transform: translateX(0); }
}

/* --- development controls: a segmented picker, one at a time ---------- */
.ov-seg { display: flex; gap: 3px; margin-top: 0.5rem; }
.ov-seg button {
    flex: 1; padding: 5px 2px; font-size: 0.66rem; line-height: 1.15;
    border: 1px solid var(--map-panel-border, rgba(0, 95, 110, 0.2)); border-radius: 6px;
    background: #fff; color: #6b7280; cursor: pointer;
    transition: all 0.15s;
}
.ov-seg button b { display: block; font-weight: 600; color: var(--dark-color, #1A171B); }
.ov-seg button:hover { border-color: var(--primary-color, #005F6E); }
.ov-seg button.on {
    background: var(--primary-color, #005F6E); border-color: var(--primary-color, #005F6E);
    color: rgba(255,255,255,0.85);
}
.ov-seg button.on b { color: #fff; }

/* graduated legend for the numeric controls */
.ov-ramp { margin-top: 0.5rem; }
.ov-ramp-bar {
    height: 9px; border-radius: 3px;
    border: 1px solid rgba(0,0,0,0.12);
}
.ov-ramp-ticks {
    display: flex; justify-content: space-between;
    font-size: 0.6rem; color: #6b7280; margin-top: 3px;
}

.ov-state-tag {
    font-size: 0.58rem; font-weight: 600; letter-spacing: 0.03em;
    color: var(--primary-color, #005F6E); background: rgba(0,95,110,0.09);
    border-radius: 3px; padding: 1px 5px; margin-left: 5px;
    vertical-align: middle;
}

/* --- richer popup: a table of controls ------------------------------- */
.ov-pop-rows { margin-top: 0.5rem; border-top: 1px solid #e5e7eb; }
.ov-pop-row {
    display: flex; justify-content: space-between; gap: 0.75rem;
    padding: 3px 0; font-size: 0.68rem; border-bottom: 1px solid #f1f3f5;
}
.ov-pop-row:last-child { border-bottom: none; }
.ov-pop-row span { color: #6b7280; }
.ov-pop-row b { color: var(--dark-color, #1A171B); font-weight: 600; text-align: right; }
.ov-pop-none { color: #b0b7bf; font-weight: 500; }
.ov-pop-lot {
    margin-top: 0.5rem; padding-top: 0.45rem;
    border-top: 1px solid #e5e7eb;
    font-size: 0.68rem; color: var(--dark-color, #1A171B);
}
.ov-pop-lot b { font-weight: 700; }
.ov-pop-lot .ov-pop-wait { color: #9ca3af; font-weight: 400; }
/* The street address is the line a person actually recognises, so it leads
   the lot block and the lot/plan sits under it as the reference. */
.ov-pop-addr {
    font-size: 0.74rem; font-weight: 700; line-height: 1.3;
    color: var(--dark-color, #1A171B); margin-bottom: 0.1rem;
}
.ov-pop-units {
    font-weight: 500; font-size: 0.62rem; color: #7b8794;
    white-space: nowrap;
}
/* Named buildings within one strata scheme. */
.ov-pop-bldg {
    font-size: 0.65rem; font-weight: 600; color: #4a90b8;
    line-height: 1.3; margin-bottom: 0.12rem;
}
/* The one ACTION in the popup, so it reads as a button rather than another
   line of data: full width under the facts, with a clear affordance. Uses
   the same accent as the rest of the panel rather than a new colour. */
.ov-pop-sales {
    display: flex; align-items: center; justify-content: center; gap: 0.3rem;
    width: 100%; margin-top: 0.4rem; padding: 0.32rem 0.5rem;
    border: 1px solid var(--primary-color, #005F6E); border-radius: 3px;
    background: transparent; color: var(--primary-color, #005F6E);
    font-family: inherit; font-size: 0.66rem; font-weight: 600;
    line-height: 1.2; cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease;
}
.ov-pop-sales:hover,
.ov-pop-sales:focus-visible {
    background: var(--primary-color, #005F6E); color: #fff; outline: none;
}
.ov-pop-sales[disabled] { opacity: 0.55; cursor: progress; }
.ov-pop-sales i { font-size: 0.62rem; }

/* The mesh block is the join key into everything else we hold, so it is
   shown as a value to be read and copied, not as prose. */
.ov-pop-mb {
    margin-top: 0.18rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.63rem; color: #6b7280; letter-spacing: 0.01em;
}
/* Panel-level version of the popup's note: says which rows are missing and
   why, so a state with less data reads as a known limit rather than a bug. */
.ov-state-note {
    margin: 0 0 0.5rem; padding: 0.45rem 0.6rem;
    background: #f3f6f9; border-left: 3px solid #9fb3c4; border-radius: 3px;
    font-size: 0.66rem; line-height: 1.45; color: #55636f;
}
.ov-state-note b { color: var(--dark-color, #1A171B); }
/* Full CC BY wording. The map credit is deliberately terse so it fits on
   one line; this is where the licence is actually stated. */
.ov-sources {
    margin-top: 0.6rem; padding-top: 0.5rem;
    border-top: 1px solid #e5e7eb;
    font-size: 0.6rem; line-height: 1.5; color: #7b8794;
}
.ov-sources b { display: block; color: #55636f; margin-bottom: 0.12rem; }
.ov-sources a { color: #4a90b8; text-decoration: underline; }
/* A row whose data does not exist here: legible, obviously inactive. */
.ov-row-off { opacity: 0.5; }
.ov-row-off .ov-switch { pointer-events: none; }

/* --- group titles ------------------------------------------------------
   The panel now carries four kinds of thing (basemap, national data,
   state planning, boundaries). Without banding it reads as one long list
   of unrelated switches; the rule above each title is what makes it scan
   as four groups rather than eleven rows. */
.ov-group-title {
    margin: 0.85rem 0 0.45rem; padding-top: 0.65rem;
    border-top: 1px solid var(--map-panel-border, rgba(0, 95, 110, 0.2));
    font-size: 0.6rem; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; color: #9ca3af;
}
.ov-group-title:first-child { margin-top: 0; padding-top: 0; border-top: none; }
/* the title already draws the separator, so the row under it must not */
.ov-group-title + .ov-row { border-top: none; padding-top: 0; margin-top: 0; }

/* --- basemap chips: an exclusive choice that stays compact ----------- */
.ov-choices { display: flex; flex-wrap: wrap; gap: 4px; }
.ov-choice { position: relative; flex: 1 1 auto; }
.ov-choice input {
    position: absolute; inset: 0; opacity: 0; margin: 0;
    width: 100%; height: 100%; cursor: pointer; z-index: 2;
}
.ov-choice span {
    display: block; text-align: center; padding: 4px 9px;
    border: 1px solid var(--map-panel-border, rgba(0, 95, 110, 0.2)); border-radius: 6px;
    background: #fff; font-size: 0.66rem; color: #6b7280;
    user-select: none; transition: all 0.15s;
}
.ov-choice:hover span { border-color: var(--primary-color, #005F6E); color: var(--primary-color, #005F6E); }
.ov-choice input:checked + span {
    background: var(--primary-color, #005F6E); border-color: var(--primary-color, #005F6E);
    color: #fff; font-weight: 600;
}
.ov-choice input:focus-visible + span {
    outline: 2px solid var(--accent-color, #ED8B00); outline-offset: 1px;
}

/* --- stacked radios (population underlay) ---------------------------- */
.ov-radios { margin-top: 0.5rem; display: flex; flex-direction: column; gap: 2px; }
.ov-radio {
    position: relative; display: flex; align-items: flex-start;
    gap: 0.5rem; padding: 4px 6px; border-radius: 6px; cursor: pointer;
}
.ov-radio:hover { background: rgba(0, 95, 110, 0.05); }
.ov-radio input {
    position: absolute; inset: 0; opacity: 0; margin: 0;
    width: 100%; height: 100%; cursor: pointer; z-index: 2;
}
.ov-radio-dot {
    flex: 0 0 auto; width: 14px; height: 14px; margin-top: 2px;
    border-radius: 50%; border: 2px solid #cbd5e1; background: #fff;
    transition: border 0.15s;
}
.ov-radio input:checked + .ov-radio-dot { border: 4px solid var(--primary-color, #005F6E); }
.ov-radio input:focus-visible + .ov-radio-dot {
    outline: 2px solid var(--accent-color, #ED8B00); outline-offset: 2px;
}
.ov-radio-text b {
    display: block; font-size: 0.72rem; font-weight: 600;
    color: var(--dark-color, #1A171B); line-height: 1.25;
}
.ov-radio-text span { display: block; font-size: 0.62rem; color: #9ca3af; line-height: 1.3; }

/* Sign-in gated option: legible, obviously locked, not clickable. */
.ov-radio.ov-lock { opacity: 0.55; }
.ov-radio.ov-lock input { cursor: not-allowed; }
.ov-lock-ic { display: none; font-size: 0.55rem; color: #9ca3af; margin-left: 4px; }
.ov-radio.ov-lock .ov-lock-ic { display: inline; }

/* Shown instead of the controls table where a state does not map them.
   "not published" is a different answer from "no control". */
.ov-pop-note {
    margin-top: 0.5rem; padding: 0.4rem 0.55rem;
    background: #f3f4f6; border-radius: 4px;
    font-size: 0.64rem; color: #6b7280; line-height: 1.4;
}
.ov-pop-her {
    margin-top: 0.45rem; padding: 0.35rem 0.5rem;
    background: rgba(200, 60, 60, 0.08);
    border-left: 2px solid #c83c3c; border-radius: 3px;
    font-size: 0.65rem; color: #7f1d1d; line-height: 1.35;
}


/* ===================================================================
   THE INJECTED ROOT  -  and the layout query it answers
   ===================================================================
   mapLayers.js injects one .ov-root covering the map, and puts the
   button and the panel inside it.

   ⚠️ pointer-events is load-bearing. The root covers the ENTIRE map,
   so without `none` here and `auto` on the children it would swallow
   every drag, click and scroll the map needs, and the map would look
   frozen with nothing in the console to say why.

   `container-type: size` makes the root the query container below.
   The panel's real constraint is that the MAP is short, not that the
   SCREEN is narrow: draw.php's map is the full viewport and has a
   fullscreen toggle, so one map is both tall and short within a
   session, and a flag decided at init would be stale the moment
   fullscreen flipped. The query re-answers it on every resize.

   Making the root a size container also makes it the containing
   block for the absolutely-positioned children, which is what we
   want - they position against the map area, not the page.
   =================================================================== */
.ov-root {
    position: absolute;
    inset: 0;
    pointer-events: none;
    container-type: size;
    container-name: asmap;
}
.ov-root > * { pointer-events: auto; }

/* ===================================================================
   SHORT MAPS  -  the panel becomes a bottom sheet
   ===================================================================
   draw.php's map is the viewport; an embedded panel map is often
   340px tall, where a 320px side panel with max-height:calc(100% -
   2rem) leaves ~300px of panel over a 340px map and fights the
   navigation control for the same corner. Spanning the width and
   sitting on the bottom edge is the same answer the 768px phone
   breakpoint already reached, reused here for SHORT rather than
   NARROW - the constraint is identical.
   =================================================================== */
@container asmap (max-height: 460px) {
    .ov-panel {
        top: auto;
        left: 0.5rem;
        right: 0.5rem;
        bottom: 0.5rem;
        width: auto;
        /* 68%, not the full height. At `calc(100% - 1rem)` the sheet covered
           the entire map, so you were choosing layers with no view of what
           they did to the thing you were choosing them for - which is the
           whole point of a layer control. Two thirds of the map is enough to
           see a zoning pattern change under the panel; the panel body already
           scrolls, so nothing is lost but the scrolling. */
        max-height: 68%;
        animation: ovSlideUp 0.22s ease-out;
    }
    /* Three rows of chrome on a panel that may only be 300px tall, so
       the head tightens rather than eating the content. */
    .ov-panel-head { padding: 0.55rem 0.8rem; }
    .ov-panel-head h4 { font-size: 0.82rem; }
    .ov-panel-body { padding: 0.7rem 0.8rem 0.8rem; }

    /* The sheet is wide and short, the opposite shape to the side
       panel, so one column would waste the width it has and spend the
       height it does not. */
    .ov-radios { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 0.6rem; }
}
/* Short AND narrow: back to one column, there is no width to split. */
@container asmap (max-height: 460px) and (max-width: 560px) {
    .ov-radios { grid-template-columns: 1fr; }
}

@keyframes ovSlideUp {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: translateY(0); }
}
