.map-toggle-btn { display: none; }

/* Note lines under the map. `display` belongs here, not inline: an inline one
   would outrank the `hidden` attribute and the note could never hide. */
.map-note { display: block; margin-top: calc(var(--pico-spacing) * 0.25); }
.map-note[hidden] { display: none; }

/* The picker map. Taller than wide is useless on a phone; a share of the
   viewport keeps the form reachable around it. */
.picker-map {
  height: 400px;
  border-radius: var(--pico-border-radius);
}

/* --- Place search, in the same corner on the offer search ---------------- */
/*
   The map there carries no cadastral search, so the corner is free. Same panel
   look as the cadastral one below, which is where the two shared variables
   come from.
*/
.place-search {
  --panel-shadow: 0 1px 4px rgb(0 0 0 / 0.25);
  --panel-indent: 0.5rem;

  /* Centred between the result panel and the right edge of the map: left and
     right pinned, width fixed, margins auto — the browser splits what is left
     over evenly. The right inset keeps it clear of the zoom buttons. */
  position: absolute;
  top: 0.75rem;
  left: calc(23rem + 1.5rem);
  right: 3.5rem;
  margin: 0 auto;
  width: 24rem;
  max-width: 100%;
  z-index: 900;
  font-size: 0.9375rem;
  line-height: 1.5;
}

/* Pico styles bare elements, and any author `display` outranks the `hidden`
   attribute. */
.place-search[hidden], .place-suggestions[hidden] { display: none; }

/* Field and locate button are one control: the row carries what the field
   used to carry — background, border, shadow and Pico's rounding for a search
   field — and the two children sit inside it without an edge of their own. */
.place-row {
  display: flex;
  align-items: stretch;
  background-color: var(--pico-background-color);
  border: var(--pico-border-width) solid var(--pico-form-element-border-color);
  border-radius: 5rem;
  box-shadow: var(--panel-shadow);
}

/* The ring belongs to the whole control, whichever half has the focus. */
.place-row:focus-within {
  border-color: var(--pico-form-element-active-border-color);
  box-shadow: var(--panel-shadow), 0 0 0 var(--pico-outline-width) var(--pico-form-element-focus-color);
}

/* A circle at the end of the field, the sign inside it. Outlined, not filled:
   a filled button at the trailing edge of a search field reads as its submit,
   and the filled green on this page belongs to the search itself. It fills
   only under the pointer, where the meaning is already read.
   The padding at the foot is the glyph's: ⌖ sits low in its line box.
   Pico colours a button in every state, so each one is named here. */
.locate-btn,
.locate-btn:is(:hover, :focus, :active, :focus-visible) {
  flex: none;
  align-self: center;
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  margin: 0 0.3rem 0 0;
  padding: 0 0 0.2rem;
  font-size: 1.375rem;
  line-height: 1;
  background: none;
  /* Not --pico-color: inside a button Pico points that at the text colour of a
     filled button, which is the background here. */
  color: var(--pico-contrast);
  border: var(--pico-border-width) solid var(--pico-form-element-border-color);
  border-radius: 50%;
  box-shadow: none;
}

.locate-btn:is(:hover, :focus) {
  background: var(--pico-primary);
  color: var(--pico-primary-inverse);
  border-color: var(--pico-primary);
}

/* While the browser is being asked. Nothing is exchanged for anything, so
   neither the circle nor the sign inside it moves. */
.locate-btn.is-busy { animation: locate-busy 1.1s ease-in-out infinite; }

@keyframes locate-busy {
  50% { opacity: 0.3; }
}

.locate-btn[hidden] { display: none; }

#place-query {
  flex: 1;
  min-width: 0;
  margin: 0;
  height: auto;
  padding: 0.5rem var(--panel-indent);
  font-size: inherit;
  background-color: transparent;
  border: none;
  border-radius: 5rem 0 0 5rem;
  box-shadow: none;
}

/* Pico draws the magnifier as a background image, placed for its own padding —
   which this field does not use. Both move to the panel's indent, and the text
   starts behind the icon instead of on top of it. */
#place-query[type="search"] {
  background-position: center left var(--panel-indent);
  padding-left: calc(var(--panel-indent) + 1.5rem);
}

/* --- Cadastral search, sitting in the map's top-left corner --------------- */
/*
   Three panels on a map — box, button, suggestions — so they share one shadow,
   one radius and one text size. Every step away from that reads as noise on a
   surface that is itself busy.
*/
#cadastre-search {
  --panel-shadow: 0 1px 4px rgb(0 0 0 / 0.25);
  /* The field's text lines up with the steps above it, so the padding of the
     one is the indent of the other. */
  --panel-indent: 0.5rem;

  /* Wide enough for the way and the field on one line — the map beneath it is
     up to 40rem, and a flat panel covers less of it than a tall one. */
  width: 30rem;
  max-width: calc(100vw - 7rem);
  font-size: 0.875rem;
  line-height: 1.4;
}

/* Pico styles bare elements, and any author `display` outranks the `hidden`
   attribute — which would leave these three permanently visible. */
#cadastre-search[hidden],
#cadastre-suggestions[hidden],
#cadastre-actions[hidden],
#cadastre-clear[hidden] { display: none; }

.cadastre-search-box {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: baseline;
  background: var(--pico-background-color);
  border-radius: var(--pico-border-radius);
  box-shadow: var(--panel-shadow);
  padding: 0.4rem var(--panel-indent);
}

/* How far the search has come, in front of what it asks for next, on the same
   line: "Gammelby 114 · Flur 4 · " and then the field. Quieter than the field —
   it is context, and it is already decided. It gives way first when the line
   runs out; the full way stands under the map anyway. */
#cadastre-crumbs {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  color: var(--pico-muted-color);
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Pico gives inputs a full-width box model, a border and a margin — none of
   which belong to a field that shares a line with a button. */
#cadastre-query {
  /* Never wraps away from its buttons, and never shrinks to nothing. */
  flex: 1 1 6rem;
  width: auto;
  min-width: 6rem;
  margin: 0;
  padding: 0;
  height: auto;
  border: 0;
  background: none;
  box-shadow: none;
  font-size: inherit;
  line-height: inherit;
}

#cadastre-query:focus { box-shadow: none; }

/* Not part of the search but its way out, so it stands under it rather than
   in it. */
#cadastre-actions { margin-top: 0.25rem; }

#cadastre-actions button {
  width: 100%;
  margin: 0;
  padding: 0.4rem var(--panel-indent);
  border-radius: var(--pico-border-radius);
  box-shadow: var(--panel-shadow);
  font-size: inherit;
  line-height: inherit;
}

/* One step back. Quiet: it undoes, it does not act. */
#cadastre-clear {
  flex: 0 0 auto;
  width: auto;
  margin: 0;
  padding: 0 0 0 var(--panel-indent);
  border: 0;
  background: none;
  color: var(--pico-muted-color);
  font-size: inherit;
  line-height: inherit;
}

#cadastre-clear:hover { color: var(--pico-color); }

#cadastre-suggestions,
.place-suggestions {
  margin: 0.25rem 0 0;
  padding: 0;
  list-style: none;
  max-height: 40vh;
  overflow-y: auto;
  background: var(--pico-background-color);
  border-radius: var(--pico-border-radius);
  box-shadow: var(--panel-shadow);
}

#cadastre-suggestions li,
.place-suggestions li {
  padding: 0.35rem var(--panel-indent);
  cursor: pointer;
}

#cadastre-suggestions li.is-active,
.place-suggestions li.is-active { background: var(--pico-secondary-background); color: var(--pico-secondary-inverse); }
#cadastre-suggestions li.is-note,
.place-suggestions li.is-note { color: var(--pico-muted-color); cursor: default; }

/* Name and number of the Gemarkung, in the manual fields. */
.cadastre-pair {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: calc(var(--pico-spacing) * 0.5);
}

/* The record as one line, in the shape of the field it stands for — Pico's
   `dropdown` does the looks, the popover part of it only applies to a `ul`, so
   the fields below open in place. */
#cadastre-preview {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--pico-color);
}

#cadastre-preview.is-empty { color: var(--pico-form-element-placeholder-color); }

/* Pico floats the chevron right; the mark has to stay next to the text. */
#cadastre-preview::after { margin-left: auto; }

/* A dropdown of Pico's lays an invisible sheet over the whole page while it is
   open, so that a click next to it closes it. That works for its own menu,
   which floats above the sheet — fields opening in place lie under it, and
   every click on one would close the block instead. It opens and closes by its
   own line, like any other details. */
#cadastre-preview::before { display: none; }

/* What the cadastre said about the entry: found, or looked for and not there.
   Grey rather than red — an entry the service cannot confirm is not a wrong
   one, and for a Bundesland it holds no data for it is all it will ever say. */
.cadastre-status {
  font-size: 1.1rem;
  line-height: 1;
  cursor: help;
}

.cadastre-status.is-ok { color: var(--pico-color-green-500); }
.cadastre-status.is-unknown { color: var(--pico-muted-color); }

#cadastre-manual > .grid:first-of-type { margin-top: var(--pico-spacing); }

.map-error { color: var(--pico-color-red-600); font-weight: bold; }


/* --- The filter bar over the map ---------------------------------------- */
/*
   One chip per criterion, each opening its own panel — the whole block of
   filters used to fold as one, which hid what was set. Every chip says what
   it is filtering for while it is closed (the wording comes from search.html).
*/
.filter-bar {
  /* Over the map: Leaflet's panes reach to 400, its controls to 800, and a
     menu of Pico's would open beneath them. */
  position: relative;
  z-index: 1000;
  display: flex;
  /* One line: a wrapping row breaks before it shrinks, so the filters would
     jump to the next line instead of giving way. Phones wrap, see below. */
  flex-wrap: nowrap;
  align-items: stretch;
  /* The field takes the left end and the search the right; what is left over
     falls between the filters. */
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

/* Under the row rather than in it: it appears only after a failed submit,
   and a row that does not wrap has no place for it. */
.filter-bar > .map-note { position: absolute; top: 100%; left: 0; margin-top: 0.25rem; }

/* Clearing and searching belong together at the right end, and keep their
   width — the filters give way instead. */
.filter-actions { display: flex; flex: 0 0 auto; gap: 0.5rem; }

/* The same plain field as the search on the dashboard, its own height and
   all — the chips and buttons take theirs from the same Pico variables. */
#search-form input[type="text"] { flex: 0 1 16rem; min-width: 8rem; margin: 0; }
.filter-actions > button { width: auto; margin: 0; white-space: nowrap; }
/* Pico's `dropdown` gives the summary the looks of a select — the popover
   part of it only applies to a `ul`, so the panel below brings its own (the
   same trick as #cadastre-preview).

   Every filter the same width, so the row does not jump about when a summary
   grows. What does not fit is cut off — the panel has it in full. */
.filter-chip { flex: 0 1 12rem; min-width: 6rem; margin-bottom: 0; }
/* On a desktop the wrapper is not a box at all: the chips are items of the
   bar, exactly as they were before the phone got a button to fold them
   behind. */
.filter-chips { display: contents; }
.filter-toggle { display: none; }
/* Takes the whole line so Pico's chevron ends up at the right edge — its
   float has no effect in a flex row. min-width:0 lets the text be cut. */
.chip-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Pico fills the summary's height with its line box; a block label inside
   would sit at the top and leave the chevron looking dropped. */
.filter-chip > summary { display: flex; align-items: center; }

/* A dropdown of Pico's lays an invisible sheet over the page to catch the
   click next to it. The panel floats above the sheet, but its fields would
   still be reached through it — the click outside is handled in search.html. */
.filter-chip > summary::before { display: none; }

/* As wide as its fields need. Pico sizes its menu to the summary above it,
   and does so from a selector that outweighs a lone class. */
.filter-chip > summary + .filter-panel {
  width: max-content;
  min-width: 100%;
  max-width: calc(100vw - 2rem);
}
/* The chips at the end of the row open towards the middle, or the panel
   would stand outside the window. */
.filter-chip:nth-last-of-type(-n+2) > summary + .filter-panel { left: auto; right: 0; }
.filter-panel label { margin-bottom: 0; }
/* Its own line under the wording, and a width of its own: "100%" of a menu
   that is as wide as its content is a circle. */
.filter-panel input[type="range"] { display: block; width: 12rem; margin: 0.35rem 0 0; }
/* Both ends and the unit on one line; the chip above already names what is
   being limited. */
.limit-row { display: flex; align-items: center; gap: 0.5rem; margin: 0; }
/* Wide enough for "Von" next to the stepper, which eats a third of the box.
   A width rather than a flex basis: the menu sizes itself to its content, and
   an input without one contributes the twenty characters it defaults to. */
.limit-row input[type="number"] { flex: 0 0 auto; width: 7rem; }
.limit-dash { color: var(--pico-muted-color); }
.limit-row .input-suffix { flex: 0 0 auto; }

.filter-check { display: flex; align-items: center; gap: 0.5rem; margin: 0; }
.filter-check input { margin: 0; }
/* One line only while there is room for one: the row does not wrap, so
   below this it would run out of the page instead. */
@media (max-width: 1024px) {
  .filter-bar { flex-wrap: wrap; }
}

@media (max-width: 768px) {
  /* The panel sits at the bottom here, so the field takes the full width. */
  .place-search { left: 0.75rem; right: 0.75rem; }

  /* Seven filters would fill the screen that the map is supposed to be, so
     they fold away behind one button and come back two to a line. */
  .filter-toggle { display: block; flex: 0 0 auto; width: auto; margin: 0; }
  /* The field takes what is left over. Without that, space-between above has
     free space to spread and puts a gap between the field and the button. */
  #search-form input[type="text"] { flex: 1 1 8rem; }
  .filter-chips {
    display: none;
    flex-basis: 100%;
    flex-wrap: wrap;
    gap: 0.5rem;
  }
  .filter-bar.is-open .filter-chips { display: flex; }

  /* A half-wide chip is too narrow to hang a menu under, so the menu takes
     the width of the bar instead. The chip gives up being the positioned
     ancestor and .filter-bar takes over, while the menu keeps its place in
     the flow and still opens below its own chip. */
  .filter-chip { flex-basis: calc(50% - 0.25rem); position: static; }
  .filter-chip > summary + .filter-panel,
  .filter-chip:nth-last-of-type(-n+2) > summary + .filter-panel {
    left: 0;
    right: 0;
    width: auto;
    min-width: 0;
    max-width: none;
  }
}

/* --- Property search: the map is the page ------------------------------- */
/*
   Panel over the map, as a navigation app lays it out: filters and results on
   the left, the map behind them. On a phone the panel sits at the bottom and
   the results open from their own bar.
*/

/* The heading of a page whose content is a map would only take room. */
main:has(.search-shell) h1 { display: none; }
/* The room the floating actions need on a list page; there are none here. */
main:has(.search-shell) { padding-bottom: 0.75rem; }

/* Height comes from JS — it reaches to the bottom edge of the window. */
.search-shell { position: relative; min-height: 20rem; }

.search-map {
  position: absolute;
  inset: 0;
  border-radius: var(--pico-border-radius);
}

.search-panel {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  bottom: 0.75rem;
  width: 23rem;
  max-width: calc(100% - 1.5rem);
  /* Over Leaflet's own controls, which stop at 800. */
  z-index: 900;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.75rem;
  overflow: hidden;
  background: var(--pico-background-color);
  border-radius: var(--pico-border-radius);
  box-shadow: 0 1px 6px rgb(0 0 0 / 0.3);
}

.search-panel > * { margin-bottom: 0; }

/* The list scrolls, the line above it stays. */
.search-results { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.search-results-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
  margin: 0;
  font-weight: 600;
}

/* What the pins say. Small: it steers the map, it is not a heading. */
.marker-mode { display: flex; align-items: center; gap: 0.3rem; margin: 0; font-size: 0.8rem; font-weight: normal; color: var(--pico-muted-color); }
.marker-mode select { width: auto; margin: 0; padding: 0.1rem 1.6rem 0.1rem 0.4rem; font-size: 0.8rem; background-position: center right 0.4rem; }

.search-results .cards { margin-top: 0.5rem; overflow-y: auto; }

/* The pills go below the text, so they do not narrow heading and price. */
.search-results .card { flex-wrap: wrap; row-gap: 0.4rem; }
.search-results .card-body { flex-basis: 100%; }
.search-results .card-aside { flex-wrap: wrap; }

/* Pointing at a result marks it on both sides. */
.search-results .card.is-marked { border-color: var(--pico-primary); }
/* "20.000 € (1.000 €/ha)" breaks between the two figures, never inside one:
   the non-breaking space comes from views::labels. */
.search-results .card-price {
  display: block;
  margin-top: 0.15rem;
}

/* The one button that runs the search, on the map beside the result panel and
   clear of the zoom buttons on the other side. Size as everywhere else — it is
   the page's main action, not a map control. */
/* By id: Pico stretches a submit button to the width of its form, and the form
   this one belongs to is the whole filter bar. Under the pin's tip, which sits
   on the point itself. */
#search-here {
  width: auto;
  margin: 0;
  padding: 0.35rem 0.75rem;
  font-size: 0.85rem;
  white-space: nowrap;
  transform: translate(-50%, 0.5rem);
  box-shadow: 0 1px 6px rgb(0 0 0 / 0.4);
}
#search-here[hidden] { display: none; }
/* What the last position found, while a new one waits to be searched. Only
   the results themselves: the count and the way to an account are not what
   went out of date, and the circle and the point are the new state. */
.search-shell.is-stale .cards { opacity: 0.45; }
.search-shell.is-stale .result-marker,
.search-shell.is-stale .result-area { opacity: 0.35; }

/* The area a visitor's offer lies in — same two colours as the markers, so
   lease and sale read the same way with and without an account. */
.result-area { stroke: var(--brand-blue); fill: var(--brand-blue); fill-opacity: 0.18; }
.result-area.is-sale { stroke: var(--brand-green); fill: var(--brand-green); }

.result-marker,
.search-here-anchor {
  /* Leaflet's own div icon draws a white box with a border. */
  background: none;
  border: none;
  width: auto !important;
  height: auto !important;
}
.result-marker > span {
  display: inline-flex;
  align-items: baseline;
  gap: 0.3rem;
  transform: translate(-50%, -100%);
  padding: 0.15rem 0.45rem;
  border-radius: 1rem;
  white-space: nowrap;
  font-size: 0.75rem;
  font-weight: 500;
  color: #fff;
  background: var(--brand-blue);
  box-shadow: 0 1px 4px rgb(0 0 0 / 0.4);
}
/* Lease and sale are two markets; a bare number only reads as one of them
   once the colour says which. The colours of the roles: whoever searches in
   blue as a Pächter is after the blue offers. */
/* A heading can be a sentence; on the map it is a label, and it is the part
   that gives way — the price stays. */
.result-marker > span > b { max-width: 9rem; overflow: hidden; text-overflow: ellipsis; }
.result-marker.is-sale > span { background: var(--brand-green); }
.result-marker.is-marked > span { background: var(--brand-blue-dark); box-shadow: 0 0 0 2px #fff; }
.result-marker.is-sale.is-marked > span { background: var(--brand-green-dark); }
/* The viewer's own: outlined in the kind's colour instead of filled. */
.result-marker.is-own:not(.is-marked) > span { background: #fff; color: var(--brand-blue); box-shadow: inset 0 0 0 2px var(--brand-blue), 0 1px 4px rgb(0 0 0 / 0.4); }
.result-marker.is-own.is-sale:not(.is-marked) > span { color: var(--brand-green); box-shadow: inset 0 0 0 2px var(--brand-green), 0 1px 4px rgb(0 0 0 / 0.4); }

/* The way to the author of someone else's offer or want, beside its pills;
   the viewer's own carry "Eigene" there instead. */
.card-contact { font-size: 0.8rem; white-space: nowrap; }

/* Offers or wants, as two tabs over the results. */
.search-show {
  display: flex;
  margin-bottom: 0.75rem;
  border-bottom: var(--pico-border-width) solid var(--pico-muted-border-color);
}
.search-show label {
  flex: 1;
  margin: 0 0 calc(var(--pico-border-width) * -1);
  padding: 0.35rem 0.5rem;
  text-align: center;
  color: var(--pico-muted-color);
  border-bottom: 2px solid transparent;
  cursor: pointer;
}
.search-show input { position: absolute; opacity: 0; pointer-events: none; }
.search-show label:has(input:checked) { color: var(--pico-primary); border-bottom-color: var(--pico-primary); font-weight: 600; }
.search-show label:has(input:focus-visible) { outline: 2px solid var(--pico-primary-focus); outline-offset: -2px; }

/* Not a filter: saving the search, and putting up an own want or offer,
   sit below the results. */
.search-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: auto; }
.search-actions > * { margin: 0; flex: 1; font-size: 0.8rem; padding: 0.4rem 0.5rem; }
.search-own { flex-basis: 100%; }

@media (max-width: 768px) {
  .search-panel {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    max-width: none;
    max-height: 70%;
    border-radius: var(--pico-border-radius) var(--pico-border-radius) 0 0;
  }

  /* All three actions in one row; a label may take two lines instead. */
  .search-actions { flex-wrap: nowrap; }
  .search-actions > * { white-space: normal; line-height: 1.2; }
  .search-own { flex-basis: auto; }

  .location-map { display: none; }
  .map-toggle-btn { display: inline-block; }

  /* Room for the fields around it, and the search box needs the map's width. */
  .picker-map { height: 65vh; min-height: 16rem; }

  #cadastre-search { width: calc(100vw - 4.5rem); }

  /* iOS zooms the page into any field below 16px on focus. */
  #cadastre-query { font-size: 1rem; }

  /* A finger is not a mouse pointer. */
  #cadastre-suggestions li { padding: 0.7rem var(--panel-indent); }
}

@scope (#map, #properties-map) {
  [role="button"] {
    border: revert;
    outline: revert;
    color: revert;
    background-color: revert;
    font-weight: revert;
    font-size: revert;
    text-align: revert;
    padding: revert;
    box-shadow: revert;
  }
}
