/* Lviv rentals & blackouts.

   DATA PALETTE — validated, do not retune by eye:
     light  #2a78d6 / #e87ba4 / #0ca30c   worst all-pairs CVD ΔE 13.0, normal 27.5
     dark   #3987e5 / #d55181 / #0ca30c   worst all-pairs CVD ΔE  9.9, normal 26.5
   Streets are lines and listings are dots, so geometry carries identity as well as
   hue — the secondary encoding the palette rules require.

   The basemap is standard OSM, muted by a filter on .leaflet-tile-pane. Default OSM
   is saturated and busy, so the data competes with the map instead of owning it —
   but every hosted neutral basemap (CARTO Positron, Stadia) now requires an API key
   and stamps unkeyed tiles. Filtering tiles we are entitled to use gets the same
   recessive result with no key and no licensing question.

   The filter is scoped to the TILE PANE only. Vectors and markers live in the
   overlay pane, so the data keeps the exact colours validated above — filtering the
   whole map would have silently invalidated the palette. */

:root {
  color-scheme: light;

  --surface-0: #f4f4f2;     /* app backdrop */
  --surface-1: #fcfcfb;     /* panel / cards — the validated light surface */
  --surface-2: #eeeeec;
  --border:    #e3e3df;
  --border-strong: #d2d2cc;

  --text-primary:   #14140f;
  --text-secondary: #55544f;
  --text-muted:     #85847d;

  --street-sched:  #2a78d6;
  --street-never:  #0ca30c;
  --street-nodata: #a8a7a2;
  --flat:          #e87ba4;
  --flat-never:    #0ca30c;
  --flat-unknown:  #9b9a93;
  --flat-ring:     #fcfcfb;

  --accent:      #2a78d6;
  --accent-soft: #2a78d614;

  --radius:   14px;
  --radius-s: 9px;
  --shadow-1: 0 1px 2px rgb(20 20 15 / 6%), 0 4px 14px rgb(20 20 15 / 5%);
  --shadow-2: 0 10px 34px rgb(20 20 15 / 12%);
  --ring: 0 0 0 3px var(--accent-soft);
}

/* Dark is a selected set stepped for the dark surface, not an automatic flip. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --surface-0: #101114;
    --surface-1: #1a1a19;
    --surface-2: #232324;
    --border:    #32322f;
    --border-strong: #45453f;
    --text-primary:   #f7f7f4;
    --text-secondary: #c3c2b7;
    --text-muted:     #8b8a82;
    --street-sched:  #3987e5;
    --street-never:  #0ca30c;
    --street-nodata: #575652;
    --flat:          #d55181;
    --flat-never:    #0ca30c;
    --flat-unknown:  #6f6e68;
    --flat-ring:     #1a1a19;
    --accent:      #3987e5;
    --accent-soft: #3987e526;
    --shadow-1: 0 1px 2px rgb(0 0 0 / 40%), 0 4px 14px rgb(0 0 0 / 30%);
    --shadow-2: 0 10px 34px rgb(0 0 0 / 46%);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --surface-0: #101114;
  --surface-1: #1a1a19;
  --surface-2: #232324;
  --border:    #32322f;
  --border-strong: #45453f;
  --text-primary:   #f7f7f4;
  --text-secondary: #c3c2b7;
  --text-muted:     #8b8a82;
  --street-sched:  #3987e5;
  --street-never:  #0ca30c;
  --street-nodata: #575652;
  --flat:          #d55181;
  --flat-never:    #0ca30c;
  --flat-unknown:  #6f6e68;
  --flat-ring:     #1a1a19;
  --accent:      #3987e5;
  --accent-soft: #3987e526;
  --shadow-1: 0 1px 2px rgb(0 0 0 / 40%), 0 4px 14px rgb(0 0 0 / 30%);
  --shadow-2: 0 10px 34px rgb(0 0 0 / 46%);
}

* { box-sizing: border-box; }
#sheetToggle { display: none; }

html, body {
  margin: 0; height: 100%;
  background: var(--surface-0);
  color: var(--text-primary);
  font-family: Manrope, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 14px; line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

#app { display: flex; height: 100%; }

#panel {
  width: 356px; flex: 0 0 356px;
  overflow-y: auto;
  padding: 18px 16px 24px;
  background: var(--surface-1);
  border-right: 1px solid var(--border);
  scrollbar-width: thin;
}
#map { flex: 1; min-width: 0; background: var(--surface-2); }

/* ---- brand ---------------------------------------------------------------- */
.brandRow { display: flex; align-items: center; gap: 9px; }
.mark {
  width: 11px; height: 11px; border-radius: 3px; flex: none;
  background: linear-gradient(140deg, var(--street-never), var(--accent) 60%, var(--flat));
  box-shadow: 0 0 0 3px var(--accent-soft);
}
h1 {
  margin: 0; font-size: 17px; font-weight: 800;
  letter-spacing: -0.022em; line-height: 1.2;
}
h1 .amp { color: var(--text-muted); font-weight: 500; }
.brand #meta { margin: 7px 0 0; font-size: 11.5px; }

h2 {
  font-size: 10.5px; margin: 18px 0 8px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .09em; color: var(--text-muted);
}
.muted { color: var(--text-muted); font-size: 12px; }

/* ---- hero stats ----------------------------------------------------------- */
.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 16px; }
.stat {
  background: var(--surface-0);
  border: 1px solid var(--border);
  border-radius: var(--radius-s);
  padding: 10px 9px 9px;
  display: grid; gap: 2px;
}
.stat.good { border-color: color-mix(in srgb, var(--street-never) 34%, var(--border)); }
.statNum {
  font-size: 21px; font-weight: 800; letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums; line-height: 1.1;
}
.stat.good .statNum { color: var(--street-never); }
.statLbl { font-size: 10.5px; color: var(--text-muted); letter-spacing: .01em; }

/* ---- filters -------------------------------------------------------------- */
.filters { margin-top: 18px; display: grid; gap: 12px; }
.field { display: grid; gap: 5px; }
.fieldLbl {
  font-size: 11px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--text-muted);
}
output { color: var(--text-primary); font-weight: 700; font-variant-numeric: tabular-nums;
         text-transform: none; letter-spacing: 0; }

select {
  width: 100%; font: inherit; font-weight: 600; font-size: 13.5px;
  color: var(--text-primary);
  background-color: var(--surface-0);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-s);
  padding: 9px 30px 9px 11px;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 15px) 55%, calc(100% - 10px) 55%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  transition: border-color .15s, box-shadow .15s;
}
select:hover { border-color: var(--accent); }
select:focus-visible { outline: none; border-color: var(--accent); box-shadow: var(--ring); }

input[type="range"] {
  width: 100%; appearance: none; background: transparent; height: 22px; margin: 0;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 5px; border-radius: 3px; background: var(--surface-2);
  border: 1px solid var(--border);
}
input[type="range"]::-webkit-slider-thumb {
  appearance: none; width: 17px; height: 17px; border-radius: 50%; margin-top: -7px;
  background: var(--accent); border: 2px solid var(--surface-1);
  box-shadow: 0 1px 4px rgb(0 0 0 / 28%); cursor: pointer;
  transition: transform .12s;
}
input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.12); }
input[type="range"]::-moz-range-track {
  height: 5px; border-radius: 3px; background: var(--surface-2); border: 1px solid var(--border);
}
input[type="range"]::-moz-range-thumb {
  width: 15px; height: 15px; border-radius: 50%; background: var(--accent);
  border: 2px solid var(--surface-1); cursor: pointer;
}

.toggles {
  border: 1px solid var(--border); border-radius: var(--radius-s);
  padding: 9px 11px 10px; margin: 0; background: var(--surface-0);
}
.toggles legend {
  font-size: 10px; text-transform: uppercase; letter-spacing: .09em; font-weight: 700;
  color: var(--text-muted); padding: 0 5px;
}
.sw { display: flex; align-items: center; gap: 9px; padding: 4px 0;
      font-size: 13.5px; cursor: pointer; }
.sw input { accent-color: var(--accent); width: 15px; height: 15px; cursor: pointer; }
.sw:hover span { color: var(--accent); }

/* ---- legend --------------------------------------------------------------- */
.legend ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; }
.legend li {
  display: flex; align-items: center; gap: 9px; font-size: 13px;
  padding: 4px 6px; border-radius: 7px;
}
.legend li b { margin-left: auto; font-weight: 700; font-size: 11.5px;
               color: var(--text-muted); font-variant-numeric: tabular-nums; }
.swatch { flex: 0 0 auto; display: inline-block; }
.swatch.line { width: 18px; height: 3px; border-radius: 2px; }
.swatch.line.sched  { background: var(--street-sched); }
.swatch.line.never  { background: var(--street-never); }
.swatch.line.nodata { background: var(--street-nodata); }
.swatch.dot { width: 10px; height: 10px; border-radius: 50%; margin: 0 4px;
              background: var(--flat); box-shadow: 0 0 0 2px var(--flat-ring); }
.swatch.dot.never   { background: var(--flat-never); }
.swatch.dot.unknown { background: var(--flat-unknown); }

/* ---- results (the table view the accessibility pass requires) -------------- */
#list {
  display: grid; gap: 1px; background: var(--border);
  border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden; max-height: 42vh; overflow-y: auto;
}
.row {
  background: var(--surface-1); padding: 10px 11px; cursor: pointer;
  border-left: 3px solid transparent;
  transition: background .12s, border-color .12s;
}
.row:hover, .row:focus-visible {
  background: var(--surface-0); border-left-color: var(--accent); outline: none;
}
.row.isNever { border-left-color: color-mix(in srgb, var(--street-never) 55%, transparent); }
.row .top { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; }
.row .addr { font-weight: 700; font-size: 13.5px; letter-spacing: -0.01em; }
.row .price { font-variant-numeric: tabular-nums; white-space: nowrap;
              font-weight: 700; font-size: 13px; }
.row .sub { color: var(--text-muted); font-size: 11.5px; margin-top: 2px; }
.row .q { font-variant-numeric: tabular-nums; }
.row .tag {
  display: inline-block; padding: 1px 6px; border-radius: 20px; font-size: 10.5px;
  font-weight: 700; letter-spacing: .02em;
  background: color-mix(in srgb, var(--street-never) 16%, transparent);
  color: var(--street-never);
}

/* ---- popups --------------------------------------------------------------- */
.leaflet-popup-content-wrapper {
  border-radius: var(--radius); background: var(--surface-1);
  color: var(--text-primary); box-shadow: var(--shadow-2);
  border: 1px solid var(--border);
}
.leaflet-popup-tip { background: var(--surface-1); border: 1px solid var(--border); }
.leaflet-popup-content { margin: 12px 14px; font: inherit; min-width: 210px; }
.leaflet-container a.leaflet-popup-close-button { color: var(--text-muted); }
.pop h3 { margin: 0 0 2px; font-size: 14.5px; font-weight: 800; letter-spacing: -0.015em; }
.pop dl { display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; margin: 9px 0 0; }
.pop dt { color: var(--text-muted); font-size: 11.5px; }
.pop dd { margin: 0; font-size: 12.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.pop-actions { margin-top: 11px; display: flex; flex-wrap: wrap; gap: 7px; align-items: center; }
.pop-actions a {
  font-size: 12px; font-weight: 700; color: var(--accent); text-decoration: none;
}
.pop-actions a:hover { text-decoration: underline; }
.copyAddr {
  font: inherit; font-size: 11.5px; font-weight: 700;
  padding: 5px 9px; min-height: 30px;
  border: 1px solid var(--border-strong); border-radius: 7px;
  background: var(--surface-0); color: var(--text-primary); cursor: pointer;
  transition: border-color .15s, color .15s;
}
.copyAddr:hover { border-color: var(--accent); color: var(--accent); }

/* Leaflet chrome restyled to match, rather than sitting on top as a foreign object */
.leaflet-bar a, .leaflet-bar a:hover {
  background: var(--surface-1); color: var(--text-primary);
  border-bottom-color: var(--border);
}
.leaflet-bar { border: 1px solid var(--border); border-radius: var(--radius-s);
               overflow: hidden; box-shadow: var(--shadow-1); }
.leaflet-container { background: var(--surface-2); font-family: inherit; }

/* Mute the basemap so the data reads as the foreground. Tile pane only — the
   overlay pane (streets, markers) must keep its validated colours. */
.leaflet-tile-pane { filter: saturate(.32) brightness(1.05) contrast(.94); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .leaflet-tile-pane {
    filter: invert(1) hue-rotate(180deg) saturate(.22) brightness(.88) contrast(1.02);
  }
}
:root[data-theme="dark"] .leaflet-tile-pane {
  filter: invert(1) hue-rotate(180deg) saturate(.22) brightness(.88) contrast(1.02);
}
.leaflet-control-attribution {
  background: color-mix(in srgb, var(--surface-1) 86%, transparent);
  color: var(--text-muted); font-size: 10.5px;
}
.leaflet-control-attribution a { color: var(--text-secondary); }
.leaflet-tooltip {
  background: var(--surface-1); color: var(--text-primary);
  border: 1px solid var(--border); border-radius: 8px;
  box-shadow: var(--shadow-1); font-size: 12px; font-weight: 600;
}
.leaflet-tooltip::before { display: none; }

#theme {
  position: fixed; right: 14px; bottom: 14px; z-index: 1000;
  width: 38px; height: 38px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1px solid var(--border); background: var(--surface-1);
  color: var(--text-secondary); cursor: pointer; box-shadow: var(--shadow-1);
  transition: transform .15s, color .15s, border-color .15s;
}
#theme:hover { transform: scale(1.07); color: var(--accent); border-color: var(--accent); }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ---- phones & portrait tablets --------------------------------------------
   900px, not 760: a tablet in portrait (768–834) is better served by a full-screen
   map with a sheet than by a 356px sidebar eating 44% of the width. Landscape
   tablets (1024+) still get the sidebar. */
@media (max-width: 900px) {
  #app { display: block; height: 100%; }

  #map { position: fixed; inset: 0; height: 100%; width: 100%; }

  #panel {
    --sheet-handle: 54px;
    position: fixed; left: 0; right: 0; bottom: 0;
    width: auto; max-width: 100%; flex: none;
    max-height: 86vh;
    padding: 0 16px calc(18px + env(safe-area-inset-bottom));
    border-right: 0; border-top: 1px solid var(--border);
    border-radius: var(--radius) var(--radius) 0 0;
    box-shadow: var(--shadow-2);
    z-index: 1000;
    overscroll-behavior: contain;
    /* Sliding beats toggling display: the sheet keeps its scroll position. */
    transform: translateY(calc(100% - var(--sheet-handle)));
    transition: transform .28s cubic-bezier(.32, .72, 0, 1);
  }
  body.sheet-open #panel { transform: translateY(0); }

  #sheetToggle {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 7px; height: 54px;
    width: calc(100% + 32px); margin: 0 -16px; padding: 0 16px;
    background: var(--surface-1); border: 0;
    border-radius: var(--radius) var(--radius) 0 0;
    color: var(--text-secondary); font: inherit; font-size: 13px; font-weight: 700;
    cursor: pointer; position: sticky; top: 0; z-index: 2;
  }
  .grip { width: 40px; height: 4px; border-radius: 2px; background: var(--border-strong); }
  #sheetCount { color: var(--text-muted); font-weight: 600; }

  h1 { font-size: 16px; }
  .statNum { font-size: 19px; }

  /* 44px minimum touch targets */
  select { min-height: 44px; }
  .sw { padding: 8px 0; font-size: 14px; }
  .sw input { width: 18px; height: 18px; }
  .row { padding: 12px 11px; }
  .legend li { padding: 6px; }

  /* The sheet scrolls; the list must not trap a second scroller. */
  #list { max-height: none; overflow: visible; }

  #theme { bottom: auto; top: 14px; right: 14px; }
  .leaflet-bottom { bottom: 58px; }
}

/* Short viewports (phone held sideways): an 86vh sheet leaves almost no map. */
@media (max-width: 900px) and (max-height: 500px) {
  #panel { max-height: 78vh; }
}
