/* ==========================================================================
   Quercia viva — map view (Leaflet, hybrid aerial basemap)
   Shared skin for full-panel maps: the Pianificazione map today, any other
   "places on a map" panel later.
   ========================================================================== */

/* ---- Map panel ---------------------------------------------------------- */
.qc-map__caption { color: var(--qc-text-secondary); font-size: var(--qc-fs-sm); }

/* Three pin colours mean nothing without a key, so one sits under the title.
   Colour is never the only cue: every swatch carries its label. */
.qc-map__legend { display: flex; flex-wrap: wrap; gap: 0 .7rem; margin-top: .1rem; }
.qc-map__legend-item {
    display: inline-flex; align-items: center; gap: .3rem;
    font: 600 var(--qc-fs-xs)/1.7 var(--qc-font-body); color: var(--qc-text-secondary);
}
.qc-map__legend-item::before {
    content: ''; flex: none;
    width: .55rem; height: .55rem; border-radius: 50%;
    background: var(--qc-legend-dot, var(--qc-state-done));
}
/* A state that has a glyph on the map wears it in the key too: the dot gives
   way to the pin's own head — the colour, the ink edge, the mark. */
.qc-map__legend-item--mark::before { content: none; }
.qc-map__legend-mark {
    flex: none; display: grid; place-items: center;
    width: 1.05rem; height: 1.05rem; border-radius: 50%;
    background: var(--qc-legend-dot, var(--qc-state-done));
    border: 1.2px solid var(--qc-pin-ink);
    --qc-pin-glyph: var(--qc-pin-ink);
}
.qc-map__legend-mark svg { display: block; width: .8rem; height: .8rem; }
.qc-map__legend-item--picked .qc-map__legend-mark { --qc-pin-glyph: var(--qc-on-primary); }
.qc-map__legend-item--priority { --qc-legend-dot: var(--qc-status-purple); }
.qc-map__legend-item--priority::before { border: 1.2px solid var(--qc-pin-ink); box-sizing: content-box; }

.qc-map { position: relative; overflow: hidden; }

/* Inside a modal the map fills the body, keeping the dialog's bottom corners. */
.qc-map__host { position: absolute; inset: 0; z-index: 1; }
.qc-map__host .leaflet-container {
    width: 100%; height: 100%;
    background: var(--qc-surface);
    font-family: var(--qc-font-body);
}

/* Leaflet chrome re-skinned onto brand tokens */
/* The day round and the irrigation components carry a map outside `.qc-map`:
   their zoom buttons and attribution stayed Leaflet's white in the dark theme. */
:is(.qc-map, .qc-route__map, .qc-compmap) .leaflet-control-zoom a {
    background: var(--qc-surface-raised); color: var(--qc-text-primary); border-color: var(--qc-border);
}
:is(.qc-map, .qc-route__map, .qc-compmap) .leaflet-control-zoom a:hover { background: var(--qc-layer-hover); color: var(--qc-primary); }
:is(.qc-map, .qc-route__map, .qc-compmap) .leaflet-control-attribution {
    background: color-mix(in srgb, var(--qc-surface-raised) 82%, transparent);
    /* Ten pixels, before. Attribution is not decoration — it is the condition
       the tiles are used under, and it has to be legible like anything else. */
    color: var(--qc-text-tertiary); font-size: var(--qc-fs-xs);
}
:is(.qc-map, .qc-route__map, .qc-compmap) .leaflet-control-attribution a { color: var(--qc-primary); }

/* ---- Basemap ------------------------------------------------------------- */
/* The aerial imagery is blended over the drawn map (its opacity and the zoom it
   starts at are set on the layer, in the controller) and toned down here so it
   reads as ground texture under the data instead of competing with the pins.
   Dark theme also dims it, or a sunlit field would glow against the dark chrome
   around it.

   It is no longer desaturated on the way: what the photograph is for is the
   colour of the ground — a lawn, a hedge, a bare yard — and taking that out
   left it a grey haze over a map that had just been given its own. */
.qc-map__host .qc-map__imagery { filter: contrast(.94); }
[data-bs-theme="dark"] .qc-map__host .qc-map__imagery {
    filter: saturate(.6) brightness(.72) contrast(.95);
}

/* The drawn map has one edition, and it is a daylight one: a sheet that colours
   woods green has no night version to fetch. On a dark page it is settled in
   rather than swapped out — dimmed and warmed a little, so it sits inside the
   chrome instead of glaring out of it, and never so far that the green stops
   being green. That is the whole point of the sheet.

   The pane, not the tiles: filtering each <img> leaves hairlines where they
   meet, because a filter is resolved per element. */
[data-bs-theme="dark"] .qc-map__host .leaflet-tile-pane {
    filter: brightness(.82) saturate(.9) contrast(1.02);
}

/* A map read for its pins (`.qc-map--quiet`, the Pianificazione): the sheet
   keeps its shapes and gives up most of its colour, because the colours it
   spends on roads and fields are the ones the pins say a state with. The round
   and the job sheet are read for the ground itself and keep the full sheet. */
.qc-map--quiet .qc-map__host .leaflet-tile-pane {
    filter: saturate(.4) contrast(.88) brightness(1.06);
}
[data-bs-theme="dark"] .qc-map--quiet .qc-map__host .leaflet-tile-pane {
    filter: brightness(.62) saturate(.35) contrast(.92);
}

/* ---- The neutral state -------------------------------------------------- */
/* What a dot or a pin falls back to when no state names it: a neutral, never a
   hue. Declared on :root because Leaflet appends popups outside .qc-map. */
:root {
    --qc-state-done: var(--qc-text-tertiary);
}

/* ---- Customer pins ------------------------------------------------------- */
/* Teardrop pins (`pinIcon()` in assets/qc_map_pins.js): the fill is the state,
   set as a class so every colour stays a token — the theme switch re-colours them
   with no redraw.

   The edge is ink over a pale halo, and it is the same ink on both themes: the
   sheet under the pins is a daylight one whichever theme the page wears, and
   the state colours are that sheet's own — a yellow road, an orange one, a
   beige field. Edged in the card colour, a yellow pin on a field was 1.4:1 and
   had no outline at all. Declared on :root because the legend and the popups
   sit outside .qc-map. */
:root {
    --qc-pin-ink: var(--qc-text-primary);
    --qc-pin-halo: var(--qc-surface);
}
[data-bs-theme="dark"] {
    --qc-pin-ink: var(--qc-on-primary);
    --qc-pin-halo: var(--qc-text-primary);
}

.qc-pin { background: none; border: 0; }
.qc-pin__shape {
    position: relative;
    display: block; width: 100%; height: 100%;
    filter: drop-shadow(0 2px 2.5px var(--qc-shadow-color));
    transform-origin: 50% 100%;
    transition: transform var(--qc-dur-fast) var(--qc-ease-fast);
    --qc-pin-glyph: var(--qc-pin-ink);
}
.qc-pin__shape svg { display: block; width: 100%; height: 100%; overflow: visible; }
.qc-pin__halo {
    fill: none;
    stroke: var(--qc-pin-halo); stroke-width: 4.8; stroke-linejoin: round;
}
.qc-pin__body {
    fill: var(--qc-pin, var(--qc-primary));
    stroke: var(--qc-pin-ink);
    stroke-width: 1.7;
}
/* The state said a second time, as a shape: colour is never the only sign. */
.qc-pin__glyph {
    fill: none; stroke: var(--qc-pin-glyph);
    stroke-linecap: round; stroke-linejoin: round;
}
.qc-pin__priority {
    fill: var(--qc-status-purple);
    stroke: var(--qc-pin-ink); stroke-width: 1.3;
}

/* How many rows share this spot, in the head where the glyph would be. */
.qc-pin__count {
    position: absolute; inset: 0 0 auto 0; height: 30.5px;
    display: flex; align-items: center; justify-content: center;
    font: 800 var(--qc-fs-xs)/1 var(--qc-font-body); letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    color: var(--qc-pin-glyph);
    pointer-events: none;
}

.qc-pin:hover .qc-pin__shape,
.qc-pin:focus-visible .qc-pin__shape { transform: scale(1.14); }
.qc-pin:focus-visible { outline: none; }
.qc-pin:focus-visible .qc-pin__halo { stroke: var(--qc-primary); stroke-width: 6.4; }

/* ---- The pin as a label --------------------------------------------------- */
/* From a town's zoom (`labelIcon()`): who the place is and how the work stands,
   readable without opening the card. The icon is a box of nothing at the spot;
   the capsule hangs centred above it, as wide as its name. */
.qc-pinlab { background: none; border: 0; overflow: visible; }
.qc-pinlab__box {
    position: absolute; left: 0; bottom: 7px;
    display: inline-flex; align-items: center; gap: .35rem;
    padding: 2px .6rem 2px 2px;
    transform: translateX(-50%);
    transform-origin: 50% calc(100% + 7px);
    background: var(--qc-pin-halo); color: var(--qc-pin-ink);
    border: 1.5px solid var(--qc-pin-ink); border-radius: var(--qc-radius-pill);
    box-shadow: 0 2px 4px var(--qc-shadow-color);
    font: 700 var(--qc-fs-xs)/1 var(--qc-font-body);
    white-space: nowrap;
    transition: transform var(--qc-dur-fast) var(--qc-ease-fast);
    --qc-pin-glyph: var(--qc-pin-ink);
}
/* The stem: the capsule's own corner, turned, so it wears the same edge. */
.qc-pinlab__box::after {
    content: ''; position: absolute; left: 50%; bottom: -5.5px;
    width: 8px; height: 8px;
    background: inherit;
    border: solid var(--qc-pin-ink); border-width: 0 1.5px 1.5px 0;
    transform: translateX(-50%) rotate(45deg);
}
.qc-pinlab__cap {
    flex: none; display: grid; place-items: center;
    width: 20px; height: 20px; border-radius: 50%;
    background: var(--qc-pin, var(--qc-primary));
    border: 1.2px solid var(--qc-pin-ink);
}
.qc-pinlab__cap svg { display: block; width: 15px; height: 15px; }
.qc-pinlab__name { max-width: 14ch; overflow: hidden; text-overflow: ellipsis; }
.qc-pinlab__verdict {
    padding-left: .4rem;
    border-left: 1px solid color-mix(in srgb, currentColor 35%, transparent);
    font-weight: 600; font-variant-numeric: tabular-nums;
}
.qc-pinlab__count { font-weight: 800; font-variant-numeric: tabular-nums; }
.qc-pinlab__priority {
    flex: none; width: 9px; height: 9px; border-radius: 50%;
    background: var(--qc-status-purple); border: 1.2px solid var(--qc-pin-ink);
}
.qc-pinlab:hover .qc-pinlab__box,
.qc-pinlab:focus-visible .qc-pinlab__box { transform: translateX(-50%) scale(1.08); }
.qc-pinlab:focus-visible { outline: none; }
.qc-pinlab:focus-visible .qc-pinlab__box { outline: 2px solid var(--qc-primary); outline-offset: 2px; }

/* ---- Several places as one mark ------------------------------------------ */
/* Below a town's zoom (`clusterIcon()`): the count of jobs, ringed by the share
   of them that are late. */
.qc-pincluster { background: none; border: 0; }
.qc-pincluster__ring {
    display: grid; place-items: center;
    width: 100%; height: 100%; border-radius: 50%;
    background: conic-gradient(
        var(--qc-state-late) 0 var(--qc-cluster-late, 0%),
        var(--qc-state-due) var(--qc-cluster-late, 0%) 100%);
    border: 1.6px solid var(--qc-pin-ink);
    box-shadow: 0 0 0 2.5px var(--qc-pin-halo), 0 3px 6px var(--qc-shadow-color);
    transition: transform var(--qc-dur-fast) var(--qc-ease-fast);
}
.qc-pincluster__ring--picked { box-shadow: 0 0 0 3.5px var(--qc-state-picked), 0 3px 6px var(--qc-shadow-color); }
.qc-pincluster__count {
    display: grid; place-items: center;
    width: 30px; height: 30px; border-radius: 50%;
    background: var(--qc-pin-halo); color: var(--qc-pin-ink);
    border: 1.2px solid var(--qc-pin-ink);
    font: 800 var(--qc-fs-sm)/1 var(--qc-font-body); font-variant-numeric: tabular-nums;
}
.qc-pincluster:hover .qc-pincluster__ring,
.qc-pincluster:focus-visible .qc-pincluster__ring { transform: scale(1.1); }
.qc-pincluster:focus-visible { outline: none; }
.qc-pincluster:focus-visible .qc-pincluster__ring { outline: 2px solid var(--qc-primary); outline-offset: 4px; }

@media (prefers-reduced-motion: reduce) {
    .qc-pin__shape, .qc-pinlab__box, .qc-pincluster__ring { transition: none; }
}

/* ---- Customer popup ------------------------------------------------------ */
.qc-mapop .leaflet-popup-content-wrapper {
    background: var(--qc-surface-overlay); color: var(--qc-text-primary);
    border: 1px solid var(--qc-border); border-radius: var(--qc-radius-card);
    box-shadow: var(--qc-shadow-md);
}
.qc-mapop .leaflet-popup-tip { background: var(--qc-surface-overlay); border: 1px solid var(--qc-border); }
.qc-mapop .leaflet-popup-content { margin: .8rem .9rem; line-height: 1.4; }
.qc-mapop .leaflet-popup-close-button { color: var(--qc-text-tertiary); }
.qc-mapop .leaflet-popup-close-button:hover { color: var(--qc-primary); }

.qc-mapop__title {
    display: flex; align-items: center; gap: .4rem; flex-wrap: wrap;
    margin: 0 1.1rem .35rem 0;
    font-family: var(--qc-font-display); font-weight: 800; font-size: var(--qc-fs-xl);
    letter-spacing: -.01em; color: var(--qc-text-primary);
}
.qc-mapop__flag {
    padding: .05rem .4rem; border-radius: var(--qc-radius-pill);
    font: 700 var(--qc-fs-xs)/1.5 var(--qc-font-body); text-transform: uppercase; letter-spacing: .04em;
    color: var(--qc-error-text); background: color-mix(in srgb, var(--qc-error) 14%, transparent);
}
/* Leaflet gives every paragraph in a popup 1.3em above and below
   (`.leaflet-popup-content p`, a class and a tag), which beat every margin set
   here by one class: the card had a blank line between each of its parts.
   Taken out once; the parts space themselves. */
.qc-mapop .leaflet-popup-content p { margin: 0; }

/* The verdict, as the list's own outlined pill (qc_state_pill.js). */
.qc-mapop__verdict { display: flex; margin: 0 0 .4rem; }

.qc-mapop .qc-mapop__addr { margin: 0 0 .4rem; font-size: var(--qc-fs-sm); line-height: 1.35; color: var(--qc-text-secondary); }

.qc-mapop__facts {
    display: grid; grid-template-columns: auto 1fr; gap: .2rem .6rem;
    align-items: baseline;
    margin: 0; font-size: var(--qc-fs-sm);
}
.qc-mapop__facts dt { color: var(--qc-text-tertiary); font-weight: 600; }
.qc-mapop__facts dd { margin: 0; color: var(--qc-text-primary); font-variant-numeric: tabular-nums; }

/* ---- Picking between jobs at one address --------------------------------- */
/* Each row carries the same coloured dot as its pin, so the list reads as the
   pin taken apart rather than as a new piece of vocabulary. The card of the
   row that was pressed sits above the list — see `_chooser` for why above, and
   why a press rather than a hover. The chosen row wears the primary edge and a
   filled mark, the way a chosen option does anywhere else. */
.qc-mapop__preview:not(:empty) {
    margin-bottom: .55rem; padding-bottom: .55rem;
    border-bottom: 1px solid var(--qc-divider);
}
.qc-mapop__pick { list-style: none; margin: 0; padding: 0; display: grid; gap: .25rem; }
.qc-mapop__pick-item {
    display: flex; align-items: center; gap: .5rem;
    width: 100%; min-height: 2.75rem; padding: .35rem .55rem;
    border: 1px solid var(--qc-border); border-radius: var(--qc-radius-input);
    background: none; text-align: left; cursor: pointer;
    color: var(--qc-text-primary);
    transition: background var(--qc-dur-fast) var(--qc-ease-fast),
                border-color var(--qc-dur-fast) var(--qc-ease-fast);
}
.qc-mapop__pick-item::before {
    content: ''; flex: none;
    width: .6rem; height: .6rem; border-radius: 50%;
    background: var(--qc-state-dot, var(--qc-state-done));
}
.qc-mapop__pick-item:hover { background: var(--qc-layer-hover); }
.qc-mapop__pick-item:focus-visible { outline: 2px solid var(--qc-primary); outline-offset: 1px; }
.qc-mapop__pick-item.is-current {
    background: var(--qc-layer-hover);
    border-color: var(--qc-primary);
    box-shadow: inset 0 0 0 1px var(--qc-primary);
}
.qc-mapop__pick-words { display: grid; flex: 1 1 auto; min-width: 0; gap: .05rem; }
.qc-mapop__pick-name { font-weight: 700; font-size: var(--qc-fs-sm); line-height: 1.25; }
.qc-mapop__pick-state { font-size: var(--qc-fs-xs); line-height: 1.3; color: var(--qc-text-secondary); }
.qc-mapop__pick-item .tpill { flex: none; }

@media (prefers-reduced-motion: reduce) {
    .qc-mapop__pick-item { transition: none; }
}

/* Phones: the dialog goes full screen, so the map takes what the header leaves. */
@media (max-width: 575.98px) {
    .modal-fullscreen-sm-down .modal-body { display: flex; }
    .modal-fullscreen-sm-down .modal-body > .qc-map { flex: 1 1 auto; }
}

/* On a page of its own, rather than inside a modal.

   The map used to exist only as a modal, which meant it could not be resized,
   printed, linked to, or left open beside the list it is about. As a panel it
   keeps its own card border — there is no dialog around it any more — and takes
   a fixed share of the viewport so the list underneath it stays reachable
   without the page becoming a map with a footnote. */
.qc-map--page {
    height: min(58vh, 640px);
    min-height: 22rem;
    border: 1px solid var(--qc-border);
    border-radius: var(--qc-radius-card);
}

/* ---- Pianificazione ------------------------------------------------------
   Two states of a place (planning_map_controller.js): late and waiting.
   Lateness is orange as the list's pill is — never red, which is the archived
   badge. A place nothing is asked of is not drawn at all. */
:root {
    --qc-state-late: var(--qc-status-orange);
    --qc-state-due: var(--qc-status-yellow);
}
.qc-pin__shape--late { --qc-pin: var(--qc-state-late); }
.qc-pin__shape--due { --qc-pin: var(--qc-state-due); }
.qc-map__legend-item--late { --qc-legend-dot: var(--qc-state-late); }
.qc-map__legend-item--due { --qc-legend-dot: var(--qc-state-due); }
.qc-mapop__state--late { --qc-state-dot: var(--qc-state-late); }
.qc-mapop__state--due { --qc-state-dot: var(--qc-state-due); }

/* A priority on the card: the flag recipe, tinted with the priority's colour
   and inked in the text colour — purple ink on a purple wash would not reach
   4.5:1 on either theme. */
.qc-mapop__flag--priority {
    color: var(--qc-text-primary);
    background: color-mix(in srgb, var(--qc-status-purple) 28%, transparent);
}

/* What the list row says, as label/value pairs. */
.qc-mapop__facts {
    display: grid; grid-template-columns: auto 1fr; gap: .15rem .6rem;
    margin: .1rem 0 .6rem; font-size: var(--qc-fs-sm);
}
.qc-mapop__facts dt { color: var(--qc-text-tertiary); font-weight: 600; }
.qc-mapop__facts dd { margin: 0; color: var(--qc-text-primary); overflow-wrap: anywhere; }
.qc-mapop__actions { display: flex; flex-wrap: wrap; gap: .4rem; }
.qc-mapop__actions .btn { flex: 1 1 auto; justify-content: center; }
/* Leaflet paints every link in a popup its own blue (`.leaflet-container a`,
   one class and a tag), which beats a button's single class: "Apri" came out
   blue text in a green-tinted frame. The glass recipe's ink is put back. */
.qc-mapop__actions .btn-outline-secondary,
.qc-mapop__actions .btn-outline-secondary:hover,
.qc-mapop__actions .btn-outline-secondary:focus { color: var(--qc-btn-tint); }
.qc-mapop__actions .btn-primary,
.qc-mapop__actions .btn-primary:hover,
.qc-mapop__actions .btn-primary:focus { color: var(--qc-on-primary); }

/* A place picked for "Pianifica" on the map: the brand green, a size up, and
   the legend's word — the colour alone is not the whole sign. */
:root { --qc-state-picked: var(--qc-primary); }
.qc-pin__shape--picked { --qc-pin: var(--qc-state-picked); --qc-pin-glyph: var(--qc-on-primary); scale: 1.15; }
.qc-pinlab__box--late { --qc-pin: var(--qc-state-late); }
.qc-pinlab__box--due { --qc-pin: var(--qc-state-due); }
.qc-pinlab__box--picked {
    --qc-pin: var(--qc-state-picked); --qc-pin-glyph: var(--qc-on-primary);
    background: var(--qc-state-picked); color: var(--qc-on-primary);
}
.qc-map__legend-item--picked { --qc-legend-dot: var(--qc-state-picked); }

/* The planning map is the page, not a panel over a list. */
.qc-map--tall { height: min(72vh, 820px); }
