/* FindDatBolig
   The chrome stays neutral so the transit line colours - which come straight
   from OpenStreetMap and are the real Copenhagen line colours - are the only
   saturated things on screen. */

:root {
  --ink:        #10141a;
  --panel:      #171d26;
  --panel-2:    #1f2733;
  --edge:       #2c3644;
  --text:       #e8ecf1;
  --text-dim:   #8d9aab;
  --paper:      #f6f7f9;
  --accent:     #00a0af;   /* Hovedstadens Letbane teal */
  --warn:       #e0783f;
  --sidebar-w:  clamp(280px, 22vw, 340px);
  --detail-w:   clamp(320px, 26vw, 420px);
}

* { box-sizing: border-box; }

/* The script hides things by setting el.hidden, which relies on the browser's
   own [hidden] { display: none }. That rule loses to any author rule naming a
   display - so .tags, .kw-add and the filter bar, all of them flex, stayed on
   screen while claiming to be hidden. An empty flex box shows nothing, which
   is why this went unnoticed until one of them had a dashed border. Neutralise
   it once, here, rather than per element and one bug at a time. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
  font-family: Inter, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 14px;
  color: var(--text);
  background: var(--ink);
}

body {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  overflow: hidden;
}

/* Condensed uppercase labels, the way a departure board sets them. */
.eyebrow {
  font-family: "Barlow Condensed", Inter, sans-serif;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 0 0 8px;
  display: block;
}

/* ---------- sidebar ---------- */

#filters {
  background: var(--panel);
  border-right: 1px solid var(--edge);
  display: flex;
  flex-direction: column;
  height: 100vh;
  min-height: 0;
}

.brand {
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 18px 18px 16px;
  border-bottom: 1px solid var(--edge);
}

.collapse {
  margin-left: auto;
  flex: none;
  width: 26px;
  height: 26px;
  padding: 0;
  font-size: 17px;
  line-height: 1;
  color: var(--text-dim);
}
.collapse:hover { color: var(--text); }

/* Collapsing is a grid-column change, so the map simply takes the space. */
body.filters-collapsed { grid-template-columns: 0 1fr; }
body.filters-collapsed #filters { display: none; }

.reopen {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 600;
  background: rgba(23, 29, 38, 0.94);
  border: 1px solid var(--edge);
  backdrop-filter: blur(8px);
  font-family: "Barlow Condensed", sans-serif;
  font-size: 14px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 8px 12px;
}
body.filters-collapsed .view-toggle { left: 108px; }

.brand-mark {
  width: 34px;
  height: 34px;
  flex: none;
}

.brand h1 {
  font-family: "Barlow Condensed", sans-serif;
  font-size: 21px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  margin: 0;
  line-height: 1;
}

/* Whose view: a person and a name, beside the title. One button, since
   there are two views and a click can only mean the other one. */
.brand-text { min-width: 0; flex: 1; }
.brand-title { display: flex; align-items: center; gap: 8px; }
.view-switch {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 9px;
  font-size: 12px;
  font-weight: 600;
  border-radius: 13px;
  fill: currentColor;
}
.view-switch svg { display: block; }

/* What a view hides is not drawn at all, so it takes no space either. */
body.view-marcus [data-hide-in~="marcus"],
body.view-dennis [data-hide-in~="dennis"] { display: none !important; }

.brand-sub {
  margin: 3px 0 0;
  font-size: 11.5px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.filter-scroll {
  overflow-y: auto;
  padding: 4px 18px 20px;
  flex: 1;
  min-height: 0;
  scrollbar-width: thin;
  scrollbar-color: var(--edge) transparent;
}

.group {
  padding: 16px 0;
  border-bottom: 1px solid var(--edge);
}
.group:last-child { border-bottom: 0; }

.pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin-bottom: 6px;
}
.pair:last-child { margin-bottom: 0; }

input[type="number"],
input[type="search"],
input[type="text"],
input[type="password"],
select {
  width: 100%;
  padding: 7px 9px;
  background: var(--panel-2);
  border: 1px solid var(--edge);
  border-radius: 5px;
  color: var(--text);
  font: inherit;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

input::placeholder { color: #6c7889; }

input:focus-visible,
select:focus-visible,
button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.check {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
  font-size: 13px;
  cursor: pointer;
  color: var(--text);
}
.check input { accent-color: var(--accent); }

.slider { margin-bottom: 12px; }
.slider label {
  display: flex;
  justify-content: space-between;
  font-size: 12.5px;
  color: var(--text-dim);
  margin-bottom: 3px;
}
.slider output {
  color: var(--text);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}
.slider input[type="range"] {
  width: 100%;
  accent-color: var(--accent);
}

/* The noise and water sliders wear the scale they filter on, in hard steps
   rather than a gradient: they stop on bands, and a gradient would offer
   positions between them that they cannot take. The "any" step is not a
   band, so it stays empty. The colours arrive from each layer's own legend,
   so a slider and its wash can never drift apart. */
.banded-slider input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  height: 18px;
  background: transparent;
  /* Shared with the gradient the script builds: the colour boundaries have to
     be placed in the thumb's coordinates, and those depend on its width. */
  --band-thumb: 14px;
}
.banded-slider input[type="range"]::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 3px;
  background: linear-gradient(to right, var(--band-track, var(--panel-2)));
  border: 1px solid var(--edge);
}
.banded-slider input[type="range"]::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background: linear-gradient(to right, var(--band-track, var(--panel-2)));
  border: 1px solid var(--edge);
}
.banded-slider input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: var(--band-thumb);
  height: var(--band-thumb);
  /* Half the track's height less half the thumb's, so it rides the middle of
     the bar rather than a pixel below it. */
  margin-top: -4px;
  border-radius: 50%;
  background: var(--text);
  border: 2px solid var(--panel);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}
.banded-slider input[type="range"]::-moz-range-thumb {
  width: var(--band-thumb);
  height: var(--band-thumb);
  border-radius: 50%;
  background: var(--text);
  border: 2px solid var(--panel);
}

.chips { display: flex; flex-wrap: wrap; gap: 5px; }
.chips.scrollable { max-height: 190px; overflow-y: auto; }

.chip {
  font-family: "Barlow Condensed", sans-serif;
  font-size: 13px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: 4px;
  border: 1px solid var(--edge);
  background: var(--panel-2);
  color: var(--text-dim);
  cursor: pointer;
}
.chip:hover { border-color: #46556a; color: var(--text); }
/* A chip can bring its own colour for when it is pressed - an energy label
   lights up in its own step's colour - and otherwise takes the accent. */
.chip[aria-pressed="true"] {
  background: var(--chip-on, var(--accent));
  border-color: var(--chip-on, var(--accent));
  color: var(--chip-on-ink, #04252a);
  font-weight: 700;
}
.chip .n { opacity: 0.6; margin-left: 4px; font-size: 11px; }

/* The standing offer to finish the word being typed. Dashed, because it is
   not a tag yet - it is the thing that would make one. It is the only way to
   close a tag on a phone, where there is no Tab key and the soft keyboard
   may never report a comma. */
.kw-add {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  margin-top: 8px;
  padding: 7px 9px;
  border: 1px dashed var(--accent);
  border-radius: 5px;
  background: transparent;
  color: var(--accent);
  font: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}
.kw-add:hover { background: rgba(0, 160, 175, 0.12); }
.kw-add .plus { font-size: 15px; line-height: 1; font-weight: 700; }

/* A keyword that has been committed. It carries the accent the pressed chips
   carry, because it is the same statement: this one is chosen. The text is
   left as it was typed rather than upper-cased like the fixed labels around
   it - a keyword is the reader's own word, not one of ours. */
.tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  padding: 4px 9px;
  border-radius: 4px;
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #04252a;
  font-weight: 600;
  cursor: pointer;
  /* A long phrase wraps inside the sidebar rather than widening it. */
  max-width: 100%;
  overflow-wrap: anywhere;
}
.tag .x { font-size: 14px; line-height: 1; opacity: 0.65; }
.tag:hover .x { opacity: 1; }

.filter-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 18px;
  border-top: 1px solid var(--edge);
  background: var(--panel);
}

.count {
  font-family: "Barlow Condensed", sans-serif;
  font-size: 15px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

button {
  font: inherit;
  cursor: pointer;
  border-radius: 5px;
  border: 1px solid var(--edge);
  background: var(--panel-2);
  color: var(--text);
  padding: 6px 12px;
  font-size: 13px;
}
button:hover { border-color: #46556a; }
.ghost { background: transparent; }

/* ---------- map ---------- */

main { position: relative; height: 100vh; }
#map { position: absolute; inset: 0; background: #dfe3e8; }

.layer-panel {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 500;
  width: 232px;
  padding: 13px 14px;
  background: rgba(23, 29, 38, 0.94);
  border: 1px solid var(--edge);
  border-radius: 8px;
  backdrop-filter: blur(8px);
}

/* The signature element: Copenhagen's line bullets, doing real work as the
   layer toggles. Colour and letter are the line's own. */

.bullet[aria-pressed="true"] {
  opacity: 1;
  filter: none;
  border-color: rgba(255, 255, 255, 0.75);
}

.layer-check { font-size: 12.5px; color: var(--text-dim); }

/* A wash's legend only appears with the layer it explains, because a scale
   for something that is not on screen is furniture. */
.wash-legend {
  margin-top: 9px;
  padding-top: 9px;
  border-top: 1px solid var(--edge);
}

/* One continuous bar rather than a row of swatches, because that is what the map
   draws: the wash grades from band to band instead of stepping. */
.wash-caption {
  margin: 0 0 5px;
  font-size: 11px;
  color: var(--text-dim);
}

.wash-bar {
  height: 9px;
  border-radius: 2px;
  background: linear-gradient(to right, var(--wash-ramp));
}

.wash-scale {
  display: flex;
  margin-top: 3px;
}

.wash-step {
  flex: 1;
  font-size: 9.5px;
  line-height: 1.35;
  text-align: center;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

/* The overlay is drawn on a graded scale rather than in five flat colours, so
   the browser is left to interpolate it as it scales: pinning it to
   `pixelated` turned 20 m cells into a mosaic of hard squares at every zoom
   past the one it was built for. The numbers are not smoothed - the grid a
   home is filtered on keeps its edges - only the picture is. */
.wash-overlay { image-rendering: auto; }

.area-tag {
  display: inline-block;
  font-family: "Barlow Condensed", sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #fff;
  border-radius: 3px;
  padding: 2px 7px;
  margin-bottom: 6px;
}

.view-toggle {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 500;
  display: flex;
  gap: 6px;
  background: rgba(23, 29, 38, 0.94);
  border: 1px solid var(--edge);
  border-radius: 8px;
  padding: 6px;
  backdrop-filter: blur(8px);
}
.view-toggle button.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #04252a;
  font-weight: 600;
}
.view-toggle select { width: auto; }

/* Lifted clear of the attribution line, which runs along the bottom edge and
   reaches all the way across on a narrow window. */
.leaflet-bottom.leaflet-left .leaflet-control-scale { margin-bottom: 26px; }

/* Leaflet's scale bar, in the same dark furniture as the other map controls. */
.leaflet-control-scale-line {
  background: rgba(23, 29, 38, 0.9);
  border: 1px solid var(--edge);
  border-top: none;
  color: var(--text);
  font-family: "Barlow Condensed", sans-serif;
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-shadow: none;
  padding: 1px 6px 2px;
  line-height: 1.35;
}

/* ---------- table view ---------- */

/* Catches a click on the map showing round the table, which is one of the two
   ways out of it. Transparent: the point is to see the map is still there. */
.table-backdrop {
  position: absolute;
  inset: 0;
  z-index: 440;
}

.table-close {
  position: absolute;
  top: 74px;
  right: 26px;
  z-index: 460;
  font-family: "Barlow Condensed", sans-serif;
  font-size: 13px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 5px 12px;
  border-radius: 4px;
  border: 1px solid var(--edge);
  background: var(--panel-2);
  color: var(--text-dim);
  cursor: pointer;
}
.table-close:hover { border-color: #46556a; color: var(--text); }

#table-view {
  position: absolute;
  /* Wider margins than a panel needs, so that the map around it is plainly
     still there and plainly clickable. */
  inset: 64px 32px 32px;
  z-index: 450;
  background: var(--panel);
  border: 1px solid var(--edge);
  border-radius: 8px;
  overflow: auto;
}
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td {
  text-align: left;
  padding: 7px 10px;
  border-bottom: 1px solid var(--edge);
  white-space: nowrap;
}
th {
  position: sticky;
  top: 0;
  background: var(--panel-2);
  font-family: "Barlow Condensed", sans-serif;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-size: 12px;
  color: var(--text-dim);
}
td.num { text-align: right; font-variant-numeric: tabular-nums; }

th.sortable { cursor: pointer; user-select: none; }
th.sortable:hover { color: var(--text); }
th.sortable.on { color: var(--accent); }
tbody tr { cursor: pointer; }
tbody tr:hover { background: var(--panel-2); }

/* ---------- detail panel ---------- */

/* The favorites list takes the same place as a home; app.js keeps only one of
   the two open at a time. */
#detail,
#favorites {
  position: fixed;
  top: 0;
  right: 0;
  width: var(--detail-w);
  height: 100vh;
  background: var(--panel);
  border-left: 1px solid var(--edge);
  z-index: 700;
  overflow-y: auto;
  padding: 0 0 24px;
}

.detail-img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; background: var(--panel-2); }

/* The way out to the listing sits on the photo itself, across its foot as
   Close sits across its head, so it is the first thing under the eye rather
   than the last thing in a long panel. A fade behind it keeps it legible on
   a white kitchen; without a photo it is simply the top of the panel. */
.detail-hero { position: relative; }
.detail-hero .detail-links {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  padding: 28px 14px 12px;
  background: linear-gradient(to top, rgba(16, 20, 26, 0.75), rgba(16, 20, 26, 0));
}
.detail-hero.no-img .detail-links { position: static; background: none; padding: 52px 18px 0; }
.detail-hero .detail-link.ghost-link { background: rgba(16, 20, 26, 0.8); border-color: rgba(255, 255, 255, 0.25); }
.detail-body { padding: 16px 18px; }
.detail-actions {
  position: absolute;
  top: 10px;
  right: 12px;
  display: flex;
  gap: 6px;
  /* Over the photo, whose wrapper is positioned too (for the links across
     its foot) and comes later in the panel, so would otherwise paint on top. */
  z-index: 2;
}
.detail-actions button { background: rgba(16, 20, 26, 0.8); }

/* Hollow until pressed, then filled in gold: a saved home should be told
   apart at a glance, not by reading a label. */
.detail-star { display: grid; place-items: center; padding: 5px 9px; }
.detail-star svg {
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linejoin: round;
}
.detail-star[aria-pressed="true"] { color: #f5c400; border-color: #f5c400; }
.detail-star[aria-pressed="true"] svg { fill: currentColor; }
.detail-price {
  font-family: "Barlow Condensed", sans-serif;
  font-size: 30px;
  font-weight: 700;
  letter-spacing: 0.02em;
  margin: 0;
  font-variant-numeric: tabular-nums;
}
.detail-addr { margin: 2px 0 14px; color: var(--text-dim); font-size: 13.5px; }
/* The energy label follows the home type on the address line: what the home
   is, and how much it costs to heat, read together. No label, no chip. */
.detail-addr .energy { margin-left: 4px; vertical-align: 1px; }
/* The type and its label wrap as one, never the label alone. */
.detail-addr .addr-type { white-space: nowrap; }

.spec {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--edge);
  border: 1px solid var(--edge);
  border-radius: 6px;
  overflow: hidden;
  margin-bottom: 16px;
}
.spec div { background: var(--panel); padding: 8px 10px; }
.spec dt {
  font-family: "Barlow Condensed", sans-serif;
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.spec dd { margin: 1px 0 0; font-variant-numeric: tabular-nums; font-weight: 600; }
/* One cell holding two figures, lot and basement, divided by the same hair
   line as the grid around it - the cell split down the middle. */
.spec .split { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; padding: 0; background: var(--edge); }
/* Half the width, so the labels close up a little to stay on one line. */
.spec .split > div { padding: 8px 8px; }
.spec .split dt { letter-spacing: 0.03em; white-space: nowrap; }
/* An odd cell out takes the whole last row rather than leaving a blank
   half beside it. */
.spec > div:last-child:nth-child(odd) { grid-column: 1 / -1; }

/* The energy label wears the scale's own colour, so A2020 and G are told
   apart without reading them. */
.energy {
  display: inline-block;
  min-width: 34px;
  text-align: center;
  padding: 1px 7px;
  border-radius: 4px;
  font-family: "Barlow Condensed", sans-serif;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
}

/* The proximity strip: which lines you can actually reach from this house. */
.proximity { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
.prox-row {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.prox-row .badge { width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; font-family: "Barlow Condensed", sans-serif; font-weight: 700; font-size: 13px; color: #fff; }
.prox-row .walk { color: var(--text-dim); margin-left: auto; }

/* The commute: a row per workplace, and under it the journey drawn as a
   bar - walks hatched, waits empty, rides in their line's colour - with the
   stops and times folded away beneath it. */
.commute { display: flex; flex-direction: column; gap: 6px; }

/* The commute heading, with the way to work chosen at its right: three
   icons in one pill, the chosen one filled. */
.commute-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 0 0 8px; }
.commute-head .eyebrow { margin: 0; }
.mode-toggle {
  display: inline-flex;
  border: 1px solid var(--edge);
  border-radius: 7px;
  overflow: hidden;
}
.mode-toggle .mode {
  display: grid;
  place-items: center;
  padding: 4px 9px;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--text-dim);
  fill: currentColor;
}
.mode-toggle .mode + .mode { border-left: 1px solid var(--edge); }
.mode-toggle .mode:hover { color: var(--text); }
.mode-toggle .mode.on { background: var(--accent); color: #04252a; }
/* One stretch by car or bike: the glyph and the distance side by side. */
.journey-bar .seg.direct { display: flex; justify-content: center; gap: 6px; font-size: 13px; }
.journey-bar .seg.direct svg { display: block; }
.direct-note { margin: 5px 0 0; font-size: 12px; color: var(--text-dim); }
.journey:empty { display: none; }
.journey { margin-left: 33px; }
.journey-bar {
  display: flex;
  gap: 2px;
  height: 20px;
  border-radius: 4px;
  overflow: hidden;
}
.journey-bar .seg {
  flex-basis: 0;
  min-width: 6px;
  display: grid;
  place-items: center;
  overflow: hidden;
  white-space: nowrap;
}
.journey-bar .ride {
  min-width: 28px;
  font-family: "Barlow Condensed", sans-serif;
  font-size: 13px;
  font-weight: 700;
  border-radius: 3px;
}
.journey-bar .walk {
  background: repeating-linear-gradient(90deg, var(--edge) 0 3px, transparent 3px 6px);
  color: var(--text-dim);
  fill: currentColor;
}
.journey-bar .walk svg { background: var(--panel); border-radius: 2px; }
.journey-bar .wait { border-bottom: 2px dotted var(--edge); height: 11px; align-self: start; }

.journey-steps { margin-top: 5px; font-size: 12px; color: var(--text-dim); }
.journey-steps summary { cursor: pointer; font-variant-numeric: tabular-nums; }
.journey-steps summary:hover { color: var(--text); }
.journey-steps ol { list-style: none; margin: 8px 0 4px; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.journey-steps .step { display: flex; align-items: baseline; gap: 8px; color: var(--text); }
.journey-steps .step.quiet { color: var(--text-dim); }
.journey-steps .t { flex: 0 0 36px; font-variant-numeric: tabular-nums; color: var(--text-dim); }
.journey-steps .line {
  flex: none;
  min-width: 30px;
  text-align: center;
  padding: 0 5px;
  border-radius: 3px;
  font-family: "Barlow Condensed", sans-serif;
  font-weight: 700;
  font-size: 13px;
}
.journey-steps .what { line-height: 1.35; }
.journey-steps .dim { display: block; color: var(--text-dim); font-size: 11px; }

.detail-links { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.detail-link {
  display: inline-block;
  background: var(--accent);
  color: #04252a;
  font-weight: 600;
  padding: 9px 14px;
  border-radius: 6px;
  text-decoration: none;
}
/* Leaving for Google Maps is a smaller errand than leaving for the agent. */
.detail-link.ghost-link {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--edge);
}
.detail-link.ghost-link:hover { border-color: var(--accent); color: var(--accent); }

/* ---------- favorites ---------- */

.view-toggle button .n { opacity: 0.7; margin-left: 3px; font-size: 11px; }

/* Level with the Close button across from it, so the two read as one header. */
.fav-title { line-height: 30px; margin: -6px 0 12px; }
.fav-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.fav {
  display: grid;
  grid-template-columns: 104px 1fr;
  gap: 12px;
  padding: 8px;
  border: 1px solid var(--edge);
  border-radius: 8px;
  background: var(--panel-2);
  cursor: pointer;
}
.fav:hover { border-color: #46556a; }
.fav-img {
  width: 104px;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 5px;
  background: var(--panel);
  display: block;
}
.fav-price {
  font-family: "Barlow Condensed", sans-serif;
  font-size: 20px;
  font-weight: 700;
  margin: 0;
  font-variant-numeric: tabular-nums;
}
.fav-addr { margin: 1px 0 0; color: var(--text-dim); font-size: 12.5px; }
.fav-actions { display: flex; align-items: center; gap: 12px; margin-top: 6px; }
.fav-actions a { color: var(--accent); font-size: 12.5px; text-decoration: none; }
.fav-actions a:hover { text-decoration: underline; }
.fav-remove {
  padding: 2px 8px;
  font-size: 12px;
  background: transparent;
  color: var(--text-dim);
}
.fav-empty { color: var(--text-dim); line-height: 1.6; }

/* The setup box, over a dimmed page. */
.fav-setup {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  place-items: center;
  padding: 16px;
  background: rgba(8, 11, 15, 0.6);
}
.fav-setup-card {
  width: min(420px, 100%);
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 18px;
  background: var(--panel);
  border: 1px solid var(--edge);
  border-radius: 10px;
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5);
}
.fav-setup-card .eyebrow { margin: 0; }
.fav-setup-card p { margin: 0 0 10px; font-size: 13px; line-height: 1.55; color: #c2ccd8; }
.fav-setup-card input { margin-bottom: 10px; }
.fav-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #04252a;
  font-weight: 600;
}
.fav-setup-msg { margin: 0; font-size: 13px; color: var(--text); }
.fav-setup-msg:empty { display: none; }
#fav-setup-close { align-self: flex-end; }

/* ---------- map markers ---------- */

/* One house shape for every listing. The white outline is what keeps it
   legible against both the pale basemap and a coloured route line under it. */
.house-marker { background: none; border: 0; }

.house-pin {
  display: block;
  fill: var(--accent);
  stroke: #fff;
  stroke-width: 1.4;
  paint-order: stroke;
  filter: drop-shadow(0 1px 1.5px rgba(0, 0, 0, 0.45));
}
/* Starred: amber, the one warm colour among the markers. */
.house-marker.favorite .house-pin { fill: #f5a300; }

/* The journeys on the map: a chip per leg saying what it is, centred on the
   leg, and the house they start from in a ring of its own. */
.route-chip-anchor { background: none; border: 0; }
.route-chip {
  position: absolute;
  transform: translate(-50%, -50%);
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 1px 6px 1px 4px;
  border-radius: 10px;
  border: 1.5px solid #fff;
  background: #2b3542;
  color: #fff;
  fill: currentColor;
  font-family: "Barlow Condensed", sans-serif;
  font-size: 13px;
  font-weight: 700;
  line-height: 16px;
  white-space: nowrap;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}
.route-chip svg { display: block; }
/* While a house's journeys are up, every other home steps back. On what is
   inside each marker, not the marker: the cluster plugin writes an inline
   opacity onto the markers themselves as it animates them. */
body.commuting .house-marker .house-pin,
body.commuting .cluster-disc { opacity: 0.3; }

.route-home {
  display: grid;
  place-items: center;
  background: #fff;
  border: 2.5px solid #2b3542;
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}
.route-home .house-pin { fill: var(--accent); stroke: none; filter: none; }

/* Work: the one red pin on the map, outlined in white like the houses. */
.work-marker { background: none; border: 0; }
.work-pin {
  display: block;
  fill: #d62839;
  stroke: #fff;
  stroke-width: 1.5;
  paint-order: stroke;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5));
}

.station-dot {
  background: #fff;
  border: 3px solid #10141a;
  border-radius: 50%;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.8);
}

.leaflet-popup-content-wrapper {
  background: var(--panel);
  color: var(--text);
  border-radius: 8px;
}
.leaflet-popup-tip { background: var(--panel); }
.leaflet-popup-content { margin: 0; width: 232px !important; }
.popup { padding: 10px 12px; }
.popup img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; border-radius: 5px; margin-bottom: 8px; }
.popup .p { font-family: "Barlow Condensed", sans-serif; font-size: 20px; font-weight: 700; }
.popup .a { color: var(--text-dim); font-size: 12.5px; margin-bottom: 6px; }


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

.only-narrow { display: none; }

/* ---------- the narrow layout ----------

   One column, and no room to put anything beside anything else. So the two
   panels that sit at the edges of the wide layout - the filters and a house -
   each take the whole screen in turn, and the table, which is a wide thing by
   nature, is not offered at all.

   app.js asks for this same width, because two of these controls have to
   behave differently down here, not just look different. */

@media (max-width: 860px) {
  .only-narrow { display: inline-block; }
  body { grid-template-columns: 1fr; }

  /* dvh, not vh: mobile browsers count their own collapsing toolbars into vh,
     which leaves the bottom of a full-height panel under the address bar. */
  #filters {
    position: fixed;
    z-index: 900;
    width: 100%;
    height: 100dvh;
    transform: translateX(-100%);
    transition: transform .2s;
  }
  #filters.open { transform: none; }

  /* Same button, same label, different promise: "<" reads as sliding a column
     out of the way, which is what it does beside the map. Over the map it is
     closing what is in front of you, and "x" is how that reads. */
  .collapse { font-size: 0; width: 30px; height: 30px; }
  .collapse::after { content: "\00d7"; font-size: 21px; line-height: 1; }

  /* The wide layout's way back into the filters. Down here the "Filters"
     button in the view toggle is already that, and two would be one too many. */
  #reopen { display: none; }

  /* Nowhere to put a table this narrow, so it is not offered. */
  #view-table { display: none; }

  /* A house takes the screen instead of a panel at the side of it, and sits
     above the filter sheet, since it is opened from the map underneath. */
  #detail,
  #favorites {
    inset: 0;
    width: 100%;
    height: 100dvh;
    border-left: none;
    z-index: 950;
  }

  /* The panel scrolls, and these buttons live inside it: keeping them
     absolute would scroll the way out off the top of a long listing. */
  .detail-actions { position: fixed; }

  /* The layer panel is 232px of controls - most of a phone's width - and it
     sat over the filter chips, quietly clipping them. Behind a button it
     costs nothing until asked for, and the top row reads as a pair:
     "Filters" on the left, "Lines" on the right. */
  #layers-toggle {
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 600;
    padding: 8px 12px;
    background: rgba(23, 29, 38, 0.94);
    border: 1px solid var(--edge);
    border-radius: 8px;
    backdrop-filter: blur(8px);
    font-family: "Barlow Condensed", sans-serif;
    font-size: 14px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }
  /* Lit while its panel is down, the way the view toggle marks the view you
     are in - so the button says which state you are looking at. */
  #layers-toggle[aria-expanded="true"] {
    background: var(--accent);
    border-color: var(--accent);
    color: #04252a;
    font-weight: 600;
  }

  .layer-panel { display: none; }

  /* Open, it is the top of the screen rather than a card floating over it:
     edge to edge, square across the top, and rounded only where it ends.
     Nothing shows through beside it, so there is nothing to read past. */
  .layer-panel.open {
    display: block;
    top: 0;
    left: 0;
    right: 0;
    width: auto;
    padding: 12px 14px 16px;
    border-width: 0 0 1px;
    border-radius: 0 0 12px 12px;
    background: rgba(23, 29, 38, 0.98);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45);
    z-index: 700;
  }

  /* The panel is opaque and covers this ground anyway; hiding it outright
     stops a third row of chips peeking out below the sheet's edge. */
  body.layers-open .view-toggle { display: none; }

  /* Left above the sheet as the way back out, since everything else up here
     has gone. Lit, so it reads as the control that is currently doing
     something rather than one more thing to press. */
  body.layers-open #layers-toggle { z-index: 800; }

  /* The button sits over the sheet's own top-left title, so the title takes
     the button's height: the two read as one header row, and the transit
     toggles below start clear of the button instead of under it. */
  .layer-panel.open > .eyebrow {
    min-height: 33px;
    line-height: 33px;
    margin-bottom: 6px;
  }
}

/* ---------- status line: empty results, failures ---------- */

.status {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 550;
  max-width: 460px;
  padding: 16px 18px;
  border-radius: 10px;
  background: rgba(23, 29, 38, 0.96);
  border: 1px solid var(--edge);
  backdrop-filter: blur(10px);
  text-align: center;
  line-height: 1.7;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
}
.status .muted { color: var(--text-dim); font-variant-numeric: tabular-nums; }
.status code {
  background: var(--panel-2);
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 12.5px;
}
.relax {
  border-color: var(--accent);
  color: var(--accent);
  background: transparent;
  padding: 3px 9px;
  font-size: 13px;
}
.relax:hover { background: var(--accent); color: #04252a; }

/* ---------- shortlist ---------- */







@media (max-width: 860px) {
  /* iOS Safari zooms the whole page in when a field smaller than 16px takes
     focus, and does not zoom back out. Every filter field is 13px, so every
     one of them did that; the keyword box, which is typed into over and over
     rather than once, is where it became impossible to ignore. The type is
     only bigger where the sidebar is a full-width sheet, so nothing about
     the desktop column changes. */
  input[type="number"],
  input[type="search"],
  input[type="text"],
  input[type="password"],
  select { font-size: 16px; }

  /* The offer is the way a keyword gets finished down here, so it is sized
     to be tapped rather than noticed. */
  .kw-add { font-size: 15px; padding: 11px 12px; }

  /* A tag is a button before it is a label, and 24px of it is a poor target
     for a thumb. */
  .tag { font-size: 14px; padding: 7px 11px; }
  .tag .x { font-size: 16px; }
  .tags { gap: 8px; }
}




/* ---------- system toggles ---------- */

/* One equal column per system, however many there are: a fixed count here
   went stale the moment a system was dropped and left the row short of the
   panel it sits in. */
.systems {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 4px;
  margin-bottom: 10px;
}

/* One button per system, all the same shape, so no system looks more
   important than another. Off is grey; on takes the system's own colour. */
.system {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 6px 1px 5px;
  border-radius: 6px;
  border: 1px solid var(--edge);
  background: var(--panel-2);
  color: var(--text-dim);
  cursor: pointer;
  transition: color 0.14s, border-color 0.14s, background 0.14s;
}
.system svg { width: 19px; height: 19px; fill: currentColor; display: block; }
.system span {
  font-family: "Barlow Condensed", sans-serif;
  font-size: 9px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1;
}
.system:hover { color: var(--text); border-color: #46556a; }
.system[aria-pressed="true"] {
  color: var(--system-colour);
  border-color: var(--system-colour);
  background: color-mix(in srgb, var(--system-colour) 18%, var(--panel-2));
}

/* Cluster discs, replacing leaflet.markercluster's square defaults. */
.cluster { background: none; border: 0; }
.cluster-disc {
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(0, 160, 175, 0.9);
  border: 2px solid rgba(255, 255, 255, 0.9);
  box-shadow: 0 0 0 4px rgba(0, 160, 175, 0.22);
  color: #04252a;
  font-family: "Barlow Condensed", sans-serif;
  font-weight: 700;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}

/* ---------- the table view owns the screen ---------- */

body.table-open #layers,
body.table-open #status,
body.table-open #reopen { display: none; }
body.table-open #detail { z-index: 800; }

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