/* POI Map — screen styles.
   Every colour, font and radius here comes from the Organic tokens in
   ds/styles.css. The raw numbers left are geometry: the breakpoint, and the
   marker sizes. The map itself is a MapLibre GL canvas (see src/basemap.js);
   the markers and the popup are DOM over it, and basemap.js writes their
   `left`/`top` in pixels every frame from `map.project([lon, lat])`.

   The map is the page — the finder, the results and the map's own controls
   float on top of it. It fills the window above the results on a phone, and
   the whole window once there is room for the results beside it:

     under 900px          900px and up
     ┌─────────────┐      ┌─────────────────────────┐
     │  [Find ▾ ]  │      │ [Find ▾ ]               │
     │             │      │ ┌────────┐    map       │
     │   map ● you │      │ │ 1 ...  │  ● you       │
     ├─────────────┤      │ │ 2 ...  │              │
     │ ▁ Nearest   │      │ │ scroll │          [◎] │
     └─────────────┘      │ └────────┘              │
                          └─────────────────────────┘ */

/* ─────────────────────────────────────────────────────────────
   Motion
   ───────────────────────────────────────────────────────────── */
@keyframes poiPop {
  0%   { transform: translate(-50%, -100%) scale(0); }
  70%  { transform: translate(-50%, -100%) scale(1.12); }
  100% { transform: translate(-50%, -100%) scale(1); }
}
@keyframes popupIn {
  from { opacity: 0; transform: translate(-50%, calc(-100% - 46px)); }
  to   { opacity: 1; transform: translate(-50%, calc(-100% - 54px)); }
}
@keyframes sheetUp {
  from { transform: translateY(48px); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}
@keyframes dropIn {
  from { transform: translateY(-8px); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}

/* ─────────────────────────────────────────────────────────────
   Page
   ───────────────────────────────────────────────────────────── */
html, body {
  margin: 0;
  height: 100%;
  /* the palette is a light one and stays light: without this, Chrome's
     automatic dark mode re-tints the whole map to mud */
  color-scheme: light;
}

/* ─────────────────────────────────────────────────────────────
   Screen — the layout grid
   ───────────────────────────────────────────────────────────── */
.screen {
  display: grid;
  /* minmax(0, …) throughout: long POI names are min-content-wide, and a plain
     `auto` track would let them push the layout past the window */
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: 1fr auto;
  min-height: 100dvh;
  background: var(--color-surface);
  font-family: var(--font-body);
}

/* The map takes the first row, the row everything but the results is placed in
   — so where you are is where the map opens. It still keeps clear of the
   sheet: what the sheet covers can now be dragged back into view, but a corner
   of the map you have to pan to reach is a corner nobody finds.

   The map opens zoomed so the 1500 m search radius spans 42% of the pane's
   shorter side; basemap.js derives that zoom (see `restZoom` in mercator.js).
   The MapLibre canvas fills `.map`; the markers and popup are DOM siblings
   positioned over it in pixels.

   The pane is dragged and pinched, so the browser must not claim either gesture
   for scrolling or for zooming the page first: `touch-action: none` is what
   makes a touch reach MapLibre's pointer handlers at all, and MapLibre gives
   back the pinch it takes away. A mouse drag, meanwhile, would otherwise sweep
   a text selection across the results as it went — the pane holds no text of
   its own, so the browser anchors one in the nearest thing that does. */
/* `.map` shares a grid row with the results card and the "search this area"
   pill — both sized by their own content, which changes with the catalogue.
   Pinning its height to the viewport keeps the map constant regardless of what
   its neighbours are doing, and gives the GL canvas a stable box to size to. */
.map {
  grid-area: 1 / 1;
  position: sticky;
  top: 0;
  height: 100dvh;
  min-width: 0;
  overflow: hidden;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  cursor: grab;
}
.map:active { cursor: grabbing; }

/* The overlay box for the POI markers and the selected-marker popup. It sits
   exactly over the MapLibre canvas (both `inset: 0` in `.map`), so a pixel
   basemap.js gets from `map.project([lon, lat])` is written straight to a
   child's `left`/`top`. It takes no pointer events itself — a drag between
   markers must reach the canvas — so each marker and the popup re-assert
   `pointer-events: auto`. */
.map-view {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* The MapLibre GL WebGL canvas host: prepended into `.map` by basemap.js, so it
   sits behind the marker overlay and the centre pin. Needs pointer input —
   MapLibre reads drags, wheels and pinches off it. */
.basemap {
  position: absolute;
  inset: 0;
}

/* Loading, or nothing to show — the map waits until it has real POIs on it */
.screen--status {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px;
}
.status {
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-align: center;
}
.status__title {
  margin: 0;
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 22px;
  color: var(--color-text);
}
.status__detail {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
  color: var(--color-neutral-700);
}

/* ─────────────────────────────────────────────────────────────
   The search centre
   ───────────────────────────────────────────────────────────── */
/* Where the current search is centred. Fixed at the middle of the pane —
   unlike a `.poi` marker, it does not live in the panned `.map-view`, so it
   never moves off the point "search this area" will actually search. */
.center-pin {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -100%);
  width: 40px;
  height: 48px;
  pointer-events: none;
}
.center-pin__pin {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin: 0 2px;
  border-radius: 999px 999px 999px 6px;
  transform: rotate(-45deg);
  background: var(--color-pin);
  border: 2.5px solid var(--color-neutral-100);
  box-shadow: var(--shadow-md);
}
.center-pin__pin svg {
  transform: rotate(45deg);
  stroke: #fff;
}

/* ─────────────────────────────────────────────────────────────
   Map markers
   ───────────────────────────────────────────────────────────── */
/* the layer spans the screen so markers can be positioned in %, but only the
   markers themselves take pointer events */
.poi-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.poi {
  pointer-events: auto;
  position: absolute;
  /* left/top come from basemap.js in px (map.project of the POI's lon/lat),
     re-applied every frame; animation-delay comes from JS too */
  transform: translate(-50%, -100%);
  width: 44px;
  height: 52px;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  animation: poiPop .35s ease both;
}
.poi__pin {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin: 0 2px;
  border-radius: 999px 999px 999px 6px;
  transform: rotate(-45deg);
  background: var(--color-neutral-100);
  border: 2.5px solid var(--color-neutral-100);
  box-shadow: var(--shadow-md);
}
.poi__pin svg {
  transform: rotate(45deg);
  stroke: var(--color-neutral-700);
}
/* the closest POI in the category reads in the sage second voice… */
.poi[data-variant="nearest"] .poi__pin { background: var(--color-accent-2-500); }
.poi[data-variant="nearest"] .poi__pin svg { stroke: #fff; }
/* …and an explicit selection takes over in terracotta */
.poi[data-variant="selected"] .poi__pin { background: var(--color-accent-500); }
.poi[data-variant="selected"] .poi__pin svg { stroke: #fff; }

/* The selected marker's popup: its name, and the way to directions, without
   hunting down its row in the results. Placed at the same projected pixel as
   the pin by basemap.js, so it travels with it through every pan and zoom. */
.poi-popup {
  position: absolute;
  /* its parent .map-view is pointer-events:none; the buttons inside need this */
  pointer-events: auto;
  /* left/top come from basemap.js in px, re-applied every frame */
  /* the pin stands 52px tall from its point; clear it */
  transform: translate(-50%, calc(-100% - 54px));
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(20rem, 82vw);
  padding: 12px 14px;
  border-radius: var(--radius-lg);
  background: var(--color-neutral-100);
  box-shadow: var(--shadow-lg);
  animation: popupIn .18s ease both;
}
/* `hidden` is a UA display:none, and the flex above would otherwise beat it */
.poi-popup[hidden] { display: none; }

.poi-popup__name {
  font-size: 15px;
  font-weight: 700;
  color: var(--color-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Confirm, report and go, in one row — go is the one that leaves the app, so
   it is pushed to the far side rather than reading as one of a set of three. */
.poi-popup__actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}

/* Confirm and report: secondary weight against Go's pill, since they are the
   quieter, no-consequence actions next to the one that actually leaves. */
.poi-popup__action {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  border: none;
  border-radius: 999px;
  background: var(--color-neutral-200);
  color: var(--color-text);
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
}
.poi-popup__action svg { stroke: var(--color-accent-700); }
.poi-popup__action:hover:not(:disabled) { background: var(--color-neutral-300); }
.poi-popup__action:disabled { opacity: .6; cursor: default; }

/* the same pill as a result row's, so the two read as one control in two places */
.poi-popup__go {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
  margin-left: auto;
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--color-accent-500);
  color: #fff;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}
/* icon() paints no stroke of its own; without this the arrow is invisible but
   still occupies its box, which pushes the label off centre */
.poi-popup__go svg { stroke: currentColor; }
.poi-popup__go:hover { background: var(--color-accent-600); }
.poi-popup__go:active { background: var(--color-accent-700); }

/* The report reason picker: a plain group of buttons under the report
   action, the same idiom the category finder's own menu uses. */
.poi-popup__reasons[hidden] { display: none; }
.poi-popup__reasons {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.poi-popup__reason {
  padding: 6px 10px;
  border: none;
  border-radius: 999px;
  background: var(--color-accent-100);
  color: var(--color-accent-800);
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 700;
}
.poi-popup__reason:hover { background: var(--color-accent-200); }

/* The last word on a confirm or a report: busy while in flight, then exactly
   what happened. Never silent — a swallowed 4xx is worse than no button. */
.poi-popup__status[hidden] { display: none; }
.poi-popup__status {
  margin: 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--color-neutral-700);
}
.poi-popup__status--error { color: var(--color-accent-700); }

/* ─────────────────────────────────────────────────────────────
   Category finder (top dropdown)
   ───────────────────────────────────────────────────────────── */
/* the search pill, top-left over the map */
.finder {
  grid-area: 1 / 1;
  align-self: start;
  z-index: 3;
  margin: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.finder__trigger {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 54px;
  padding: 8px 16px;
  border: none;
  border-radius: 999px;
  background: var(--color-neutral-100);
  box-shadow: var(--shadow-md);
  cursor: pointer;
  font-family: var(--font-body);
}
.finder__trigger:hover { background: var(--color-neutral-200); }
.finder__trigger:active { background: var(--color-neutral-300); }
.finder__chip {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 999px;
  background: var(--color-accent-200);
  flex: none;
}
.finder__chip svg { stroke: var(--color-accent-800); }
.finder__labels {
  flex: 1;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.finder__kicker {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--color-neutral-600);
}
.finder__value {
  font-size: 17px;
  font-weight: 700;
  color: var(--color-text);
}
.finder__chevron {
  stroke: var(--color-neutral-700);
  transition: transform .2s;
  flex: none;
}
.finder__trigger[aria-expanded="true"] .finder__chevron { transform: rotate(180deg); }

/* `display: flex` below would otherwise out-specify the UA's [hidden] rule */
.finder__menu[hidden] { display: none; }
.finder__menu {
  border-radius: var(--radius-lg);
  background: var(--color-neutral-100);
  box-shadow: var(--shadow-lg);
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  animation: dropIn .18s ease both;
}
.finder__option {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 48px;
  padding: 6px 10px;
  border: none;
  border-radius: 999px;
  background: transparent;
  cursor: pointer;
  font-family: var(--font-body);
  text-align: left;
}
.finder__option:hover { background: var(--color-accent-100); }
.finder__option[aria-current="true"] { background: var(--color-accent-200); }
.finder__option-chip {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 999px;
  background: var(--color-accent-2-200);
  flex: none;
}
.finder__option-chip svg { stroke: var(--color-accent-2-800); }
.finder__option[aria-current="true"] .finder__option-chip { background: var(--color-accent-500); }
.finder__option[aria-current="true"] .finder__option-chip svg { stroke: #fff; }
.finder__option-label {
  flex: 1;
  font-size: 16px;
  font-weight: 600;
  color: var(--color-text);
}
.finder__option-count {
  font-size: 13px;
  font-weight: 600;
  color: var(--color-neutral-600);
}

/* A category with nothing inside the search radius. Quieter than a count and
   not bold, so the row reads as available-but-empty rather than as a result —
   it is still a real choice, and picking it is how you find out how far away
   the nearest one is. */
.finder__option-count--none {
  font-weight: 400;
  font-style: italic;
  color: var(--color-neutral-500);
}

/* ─────────────────────────────────────────────────────────────
   Place search — search the curated cities by name, in the same pill
   language as the category finder above it.
   ───────────────────────────────────────────────────────────── */
.places__trigger {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 44px;
  padding: 8px 16px;
  border: none;
  border-radius: 999px;
  background: var(--color-neutral-100);
  box-shadow: var(--shadow-md);
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 700;
  color: var(--color-text);
}
.places__trigger:hover { background: var(--color-neutral-200); }
.places__trigger:active { background: var(--color-neutral-300); }
.places__trigger svg { stroke: var(--color-accent-700); flex: none; }

.places__panel[hidden] { display: none; }
.places__panel {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
  padding: 10px;
  border-radius: var(--radius-lg);
  background: var(--color-neutral-100);
  box-shadow: var(--shadow-lg);
  animation: dropIn .18s ease both;
}
.places__input {
  box-sizing: border-box;
  width: 100%;
  padding: 10px 12px;
  border: none;
  border-radius: var(--radius-lg);
  background: var(--color-neutral-200);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 15px;
}
.places__input:focus-visible {
  outline: 2px solid var(--color-accent-700);
  outline-offset: 2px;
}
.places__status[hidden] { display: none; }
.places__status {
  margin: 0;
  padding: 4px 6px;
  font-size: 13px;
  font-weight: 600;
  color: var(--color-neutral-600);
}
/* the directory is a handful of cities, not hundreds of POIs, so the list
   never needs the sheet's own scroll cap */
.places__list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.places__option {
  display: block;
  padding: 8px 10px;
  border-radius: var(--radius-lg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
}
.places__option:hover { background: var(--color-accent-100); }

/* ─────────────────────────────────────────────────────────────
   Map controls — zoom, and locate
   ───────────────────────────────────────────────────────────── */
/* the zoom buttons and the locate button, stacked bottom-right of the map */
.map-controls {
  grid-area: 1 / 1;
  align-self: end;
  justify-self: end;
  z-index: 3;
  margin: var(--space-3);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
/* one pill holding both steps, the way every map has it */
.map-zoom {
  display: flex;
  flex-direction: column;
  border-radius: var(--radius-lg);
  background: var(--color-neutral-100);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.map-zoom__button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 44px;
  border: none;
  background: none;
  cursor: pointer;
}
.map-zoom__button + .map-zoom__button { border-top: 1px solid var(--color-divider); }
.map-zoom__button:hover { background: var(--color-neutral-200); }
.map-zoom__button:active { background: var(--color-neutral-300); }
/* at zoom 5, the whole of France, there is no zooming out; at 19 no zooming in */
.map-zoom__button:disabled { opacity: .45; cursor: default; }
.map-zoom__button:disabled:hover { background: none; }
.map-zoom__button svg { stroke: var(--color-accent-700); }

.locate {
  width: 48px;
  height: 48px;
  border: none;
  border-radius: 999px;
  background: var(--color-neutral-100);
  box-shadow: var(--shadow-md);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.locate:hover { background: var(--color-neutral-200); }
.locate:active { background: var(--color-neutral-300); }
.locate svg { stroke: var(--color-accent-700); }
/* asking the device where it is takes a moment, and the button says so */
.locate:disabled { opacity: .55; cursor: default; }
.locate:disabled:hover { background: var(--color-neutral-100); }

/* ─────────────────────────────────────────────────────────────
   Search this area — a floating pill in the same language as the
   zoom/locate controls, offered once a pan or a zoom has carried the view
   past what the catalogue on screen was fetched for.
   ───────────────────────────────────────────────────────────── */
.research {
  grid-area: 1 / 1;
  align-self: start;
  justify-self: center;
  z-index: 3;
  /* On the narrow layout the finder spans the top full-width, and it is two
     stacked pills: the category trigger (54px) and the city search below it
     (8px gap + 44px). This top margin clears the whole stack plus its own
     margin, so the two floating bars never touch. The 900px layout drops all
     of this — the finder no longer spans the map there (see the override). */
  margin: calc(54px + 8px + 44px + var(--space-3) * 2) var(--space-3) 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
.research[hidden] { display: none; }
.research__button {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 8px 18px;
  border: none;
  border-radius: 999px;
  background: var(--color-neutral-100);
  box-shadow: var(--shadow-md);
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 700;
  color: var(--color-text);
}
.research__button:hover:not(:disabled) { background: var(--color-neutral-200); }
.research__button:active:not(:disabled) { background: var(--color-neutral-300); }
.research__button:disabled { opacity: .6; cursor: default; }
.research__button svg { stroke: var(--color-accent-700); flex: none; }
/* unlike `.research` itself, nothing here sets `display`, so the UA's own
   `[hidden]` rule is never outranked and needs no override to hold */
.research__problem {
  margin: 0;
  padding: 8px 16px;
  border-radius: var(--radius-lg);
  background: var(--color-neutral-100);
  box-shadow: var(--shadow-md);
  font-size: 13px;
  font-weight: 600;
  color: var(--color-text);
  text-align: center;
}

/* ─────────────────────────────────────────────────────────────
   Attribution
   ───────────────────────────────────────────────────────────── */
/* Not decoration: OpenStreetMap's licence asks for it, so it stays visible at
   every size, on the opposite corner from the controls, and it is a real link. */
.attribution {
  grid-area: 1 / 1;
  align-self: end;
  justify-self: start;
  z-index: 3;
  margin: var(--space-3);
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--color-neutral-100);
  box-shadow: var(--shadow-sm);
  font-size: 11px;
  color: var(--color-neutral-700);
  text-decoration: none;
}
.attribution:hover { text-decoration: underline; }

/* ─────────────────────────────────────────────────────────────
   Bottom sheet — nearest results
   ───────────────────────────────────────────────────────────── */
.sheet {
  grid-area: 2 / 1;
  min-width: 0;
  min-height: 0;
  z-index: 2;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  background: var(--color-neutral-100);
  box-shadow: 0 -8px 30px rgba(32, 30, 29, .14);
  padding: 10px 16px calc(18px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* carried by a class so picking a category can replay it, as the markers do */
.sheet--in { animation: sheetUp .3s ease both; }
.sheet__grabber {
  width: 40px;
  height: 5px;
  border-radius: 999px;
  background: var(--color-neutral-300);
  margin: 0 auto;
}
.sheet__head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
}
.sheet__title {
  flex: 1;
  margin: 0;
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 22px;
  color: var(--color-text);
}
/* the API's labels run long ("Bicycle repair station"), so the title takes the
   wrap and the hint keeps its one line */
.sheet__note {
  margin: 0 0 var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--color-neutral-100);
  font-size: 13px;
  color: var(--color-neutral-700);
}

.sheet__hint {
  flex: none;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--color-neutral-600);
}
/* every result in the category is listed, so the list is what scrolls */
.sheet__list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  overflow-y: auto;
  max-height: 40dvh;
  /* room for the scrollbar and the rows' focus rings */
  padding-right: 2px;
}

/* The row is a box holding two controls — the one that selects the place here
   and the one that leaves for it — so it is the box that is tinted and the
   controls that are transparent. Hovering anywhere on the row lights it,
   because the row still reads as one thing even though it answers to two. */
.result {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-radius: var(--radius-lg);
  background: var(--color-neutral-200);
}
.result:hover { background: var(--color-accent-100); }
.result--selected { background: var(--color-accent-200); }

/* it fills the row apart from the Go link, so the whole of the name and the
   distance is a target, as it was when the row itself was the button */
.result__select {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  font-family: var(--font-body);
  text-align: left;
}
.result__rank {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 999px;
  background: var(--color-neutral-300);
  color: var(--color-neutral-800);
  flex: none;
  font-size: 15px;
  font-weight: 700;
}
/* rank 1 carries the sage voice, matching its map marker */
.result:first-child .result__rank {
  background: var(--color-accent-2-500);
  color: #fff;
}
.result__text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.result__name {
  font-size: 16px;
  font-weight: 700;
  color: var(--color-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.result__meta {
  font-size: 13px;
  color: var(--color-neutral-700);
}
/* A real link now — it leaves for Google Maps — so it is drawn as the pill it
   always looked like, and told not to underline itself like body prose. */
.result__go {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 9px 16px;
  border-radius: 999px;
  background: var(--color-accent-500);
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  flex: none;
  box-shadow: var(--shadow-sm);
  text-decoration: none;
  font-family: var(--font-body);
  white-space: nowrap;
}
.result__go:hover { background: var(--color-accent-600); }
.result__go:active { background: var(--color-accent-700); }
/* SVG's initial stroke is `none`, so icons must always be given one */
.result__go svg { stroke: currentColor; }

/* The last row once the list is capped — plain text weight, so it reads as
   "more of the same list" rather than another call to action like Go. */
.sheet__more {
  padding: 10px 12px;
  border: none;
  border-radius: var(--radius-lg);
  background: none;
  color: var(--color-accent-700);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 700;
  text-align: center;
  cursor: pointer;
}
.sheet__more:hover { background: var(--color-accent-100); }

/* Two focusable things sit inside one tinted row, so the ring has to say which
   of them Tab has landed on — the row's own background cannot. */
.result__select:focus-visible,
.result__go:focus-visible,
.sheet__more:focus-visible,
.poi-popup__action:focus-visible,
.poi-popup__go:focus-visible,
.poi-popup__reason:focus-visible,
.places__option:focus-visible {
  outline: 2px solid var(--color-accent-700);
  outline-offset: 2px;
}

/* ─────────────────────────────────────────────────────────────
   Wide screens — the map still fills the window; the results move out of
   the way, from a sheet across the bottom to a card down the left.
   ───────────────────────────────────────────────────────────── */
@media (min-width: 900px) {
  .screen {
    grid-template-columns: 25rem minmax(0, 1fr);
    grid-template-rows: auto 1fr;
  }

  /* the results are a card down one side here, and leave the middle of the
     window free, so the map can have all of it */
  .map { grid-area: 1 / 1 / -1 / -1; }

  .finder { margin: var(--space-4) var(--space-4) var(--space-2); }

  /* a card down the left, not a sheet across the bottom — it hangs from the
     search pill and stops where its contents do */
  .sheet {
    grid-area: 2 / 1;
    align-self: start;
    max-height: 100%;
    margin: 0 var(--space-4) var(--space-4);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    padding: var(--space-4) var(--space-4) var(--space-2);
  }
  /* both corners move into the map column, clear of the results card */
  .map-controls,
  .attribution {
    grid-area: 2 / 2;
    margin: var(--space-4);
  }
  /* the finder no longer spans the map here, so the pill needs none of the
     mobile layout's clearance under it — it sits over the map itself, in
     the map's own column */
  .research {
    grid-area: 1 / 2;
    margin: var(--space-4);
  }
  .sheet__grabber { display: none; }
  .sheet__list {
    max-height: none;
    flex: 1;
  }
  /* the column is narrower than a phone's sheet, so names wrap instead of
     being cut — there is height to spare here, not width */
  .result__name { white-space: normal; }
}

/* ─────────────────────────────────────────────────────────────
   Reduced motion — keep the state changes, drop the movement
   ───────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .poi, .poi-popup, .sheet--in, .finder__menu, .places__panel {
    animation: none;
  }
  .finder__chevron { transition: none; }
}
