/* Driving-school finder (#/schools) — see web/app/schools.js and docs/schools.md.
   Every colour here is a token from styles.css :root, including the Leaflet overrides
   at the bottom: Leaflet ships hard-coded light greys and whites for its controls,
   popups and attribution bar, so without those blocks the map grows white boxes in
   dark mode. No literal hex in this file. */

/* No width override any more: .view is --page-w (1160px) on every route, and the
   map column sizes itself inside it. The old body.schools cap (1240px) was 80px
   wider than the landing page and made #/schools the one route whose content did
   not line up with the rest of the site. */

.schoolintro { margin-bottom: 1rem; }
.schoolseg { display: none; }              /* mobile-only; see the 860px block */

.schoolwrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 380px;
  gap: 1.1rem;
  align-items: start;
}

/* The search bar sits *over* the map on desktop (the finder's whole premise is a big
   map you type into), and above it on narrow screens where an overlay would cover a
   third of the visible map. One DOM order, two positions. */
.schoolmain { position: relative; }
.schoolhead { position: absolute; z-index: 700; top: .9rem; left: .9rem; right: .9rem; max-width: 30rem; }
.schoolhead .searchbar { margin-bottom: .55rem; }
/* A floating control has to stay readable over whatever the map happens to show under
   it, so the field is opaque-ish glass with a real elevation rather than a flat box. */
.schoolhead .searchbar input {
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(10px) saturate(1.1);
  border-radius: var(--r-pill);
  border-color: color-mix(in srgb, var(--text) 10%, transparent);
  padding: .8rem 1rem .8rem 2.6rem;
  box-shadow: var(--shadow-lg);
  font-size: .96rem;
}
.schoolhead .searchbar input::placeholder { color: var(--muted); }
.schoolhead .searchbar svg { left: 1rem; }
.schoolchips { display: flex; gap: .4rem; flex-wrap: wrap; }
.schoolchips .chip {
  display: inline-flex; align-items: center; gap: .35rem;
  box-shadow: var(--shadow-lg);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(10px) saturate(1.1);
  border-color: color-mix(in srgb, var(--text) 10%, transparent);
  font-weight: 600;
}
.schoolchips .chip svg { width: 1rem; height: 1rem; }
.schoolchips .chip.is-busy { opacity: .7; cursor: progress; }
/* Both floating controls above sit at 92% fill over a live map, so they are the one place
   on this route where the reader's transparency/contrast preference changes legibility
   rather than taste: the remaining 8% is map tiles showing through a search field. Solid
   fill, real border, no blur. */
@media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
  .schoolhead .searchbar input, .schoolchips .chip {
    background: var(--surface); border-color: var(--border); backdrop-filter: none;
  }
}
/* The ?kommune= scope chip. Filled rather than outlined, because it is not an action
   the reader can take — it is state they arrived in, and the ✕ is how they leave it. */
.schoolchips .chip.is-scope {
  background-color: var(--grad-solid); background-image: var(--grad-ui);
  color: var(--brand-ink); border-color: transparent;
}
.schoolchips .chip.is-scope svg { width: .9rem; height: .9rem; opacity: .8; }
.schoolchips .chip.is-scope:hover { filter: brightness(1.06); }

.schoolmap-shell { position: relative; }
.schoolmap {
  height: min(72vh, 700px);
  border-radius: var(--r-xl);
  border: 1px solid var(--border);
  background: var(--surface-2);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}
/* A hairline inside the rounded corner: reads as inset glass rather than a flat
   rectangle, and keeps the map edge crisp where tiles meet the border radius. */
.schoolmap-shell::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  border-radius: var(--r-xl);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text) 8%, transparent);
}

/* The palette treatment. Applied to the *tile pane only* — putting it on
   .leaflet-container would drag our markers, cluster bubbles, popups, tooltips and the
   attribution through the same filter and wash the whole UI out. See the LAYER comment
   in schools.js for why each theme uses a different source layer. */
.leaflet-tile-pane {
  filter: saturate(.35) brightness(1.07) contrast(.94);
}
:root[data-theme="dark"] .leaflet-tile-pane {
  filter: invert(1) hue-rotate(185deg) brightness(.82) contrast(1.05) saturate(.9);
}
@media (min-width: 861px) {
  .schoolmain { position: sticky; top: 4.75rem; }
}

/* Wheel-zoom needs a modifier (schools.js wireWheelZoom), so say so — but only after
   someone actually scrolls over the map, never as permanent chrome. */
.schoolzoomhint {
  position: absolute; inset: auto 0 1rem 0; margin: 0 auto; width: fit-content;
  padding: .4rem .8rem; border-radius: var(--r-pill);
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow);
  color: var(--text); font-size: .82rem;
  opacity: 0; transition: opacity var(--dur-base) var(--ease-out);
  pointer-events: none; z-index: 700;
}
.schoolzoomhint.is-on { opacity: 1; }

.schoolside { display: flex; flex-direction: column; gap: .6rem; min-width: 0; }
.schoolcount {
  margin: 0; font-size: .82rem; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .04em;
}
.schoolrows {
  display: flex; flex-direction: column; gap: .5rem;
  max-height: min(72vh, 700px); overflow-y: auto;
  /* Leaves room for the scrollbar so hover doesn't shift the rows sideways. */
  padding-right: .2rem;
}
.schoolmore, .schoolsource { margin: .2rem 0 0; font-size: .8rem; }

.schoolrow {
  position: relative; overflow: hidden;
  /* The rows live in a fixed-height flex column, so without this they shrink to fit
     and the name collides with the address instead of the list scrolling. */
  flex: 0 0 auto;
  display: flex; align-items: center; gap: .6rem; justify-content: space-between;
  padding: .75rem .9rem .75rem 1rem; text-decoration: none; color: inherit;
  transition: border-color var(--dur-quick) var(--ease-out),
              transform var(--dur-quick) var(--ease-out),
              box-shadow var(--dur-quick) var(--ease-out);
}
/* An accent rail that grows in on hover and stays for the selected row — the one place
   the list needs a strong "this is the pin you're looking at" signal. */
.schoolrow::before {
  content: ''; position: absolute; inset: 0 auto 0 0; width: 3px;
  background-image: var(--grad-ui); background-color: var(--grad-solid);
  transform: scaleY(0); transform-origin: center;
  transition: transform var(--dur-quick) var(--ease-out);
}
.schoolrow:hover { border-color: color-mix(in srgb, var(--brand) 45%, var(--border)); transform: translateY(-1px); box-shadow: var(--shadow); }
.schoolrow:hover::before { transform: scaleY(1); }
.schoolrow.is-active { border-color: var(--brand); box-shadow: var(--shadow); }
.schoolrow.is-active::before { transform: scaleY(1); }
.schoolrow-body { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.schoolrow-name { font-size: .95rem; line-height: 1.25; }
.schoolrow-addr { font-size: .82rem; }
.schoolrow-meta { display: flex; flex-direction: column; align-items: flex-end; gap: .25rem; flex-shrink: 0; }
.schoolrow-dist { font-size: .82rem; font-weight: 700; color: var(--brand); white-space: nowrap; }

/* Cluster bubbles are the one marker type that needs a DOM node (canvas can't hold
   cheap text); below zoom 11 there are at most ~80 of them. */
.schoolcluster span {
  display: grid; place-items: center;
  border-radius: var(--r-pill);
  background-color: var(--grad-solid); background-image: var(--grad-ui);
  color: #fff; font-weight: 800; font-size: .8rem; letter-spacing: -.01em;
  border: 2px solid var(--surface);
  /* Two rings and a cast shadow: the halo separates the bubble from a busy map far
     better than a single border, at any zoom and over any terrain. */
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--brand) 18%, transparent), var(--shadow-lg);
  transition: transform var(--dur-quick) var(--ease-spring);
}
.schoolcluster:hover span { transform: scale(1.08); }

/* ---------------------------------------------------------------- detail page */
/* `.schoolback` (the one-way "back to results" link) is now the shared `.crumbs` trail
   in styles.css, which keeps the same query-preserving href and adds Home in front. */
.schooldetail { display: flex; flex-direction: column; gap: .9rem; }
.schooldetail-head h1 { margin-bottom: .35rem; }
.schooltags { display: flex; gap: .4rem; flex-wrap: wrap; margin: 0; }
.schoolcard { display: flex; flex-direction: column; gap: .6rem; border-radius: var(--r-lg); }
.schoolh2 {
  font-size: .78rem; margin: 0; color: var(--muted);
  text-transform: uppercase; letter-spacing: .06em; font-weight: 700;
}
.schooladdr { margin: 0; font-size: 1.05rem; line-height: 1.45; }
.schoolnote { margin: 0; font-size: .82rem; line-height: 1.5; }
.schoolminimap {
  height: 240px; border-radius: var(--r-lg); border: 1px solid var(--border);
  background: var(--surface-2); overflow: hidden; box-shadow: var(--shadow);
}
.schoolacts { display: flex; gap: .5rem; flex-wrap: wrap; }
.schoolact { display: inline-flex; align-items: center; gap: .4rem; }
.schoolact svg { width: 1.05rem; height: 1.05rem; }
.schoolfacts {
  display: grid; grid-template-columns: auto 1fr; gap: .3rem .9rem;
  margin: 0; font-size: .9rem;
}
.schoolfacts dt { color: var(--muted); }
.schoolfacts dd { margin: 0; }

/* ------------------------------------------------------------------ narrow */
/* A 40vh map *and* a list on a phone leaves neither usable, so they take turns.
   Defaults to the list: results are the answer, the map is for exploring. */
@media (max-width: 860px) {
  .schoolseg { display: inline-flex; }
  .schoolwrap { grid-template-columns: 1fr; }
  .schoolhead { position: static; margin-bottom: .7rem; }
  .schoolhead .searchbar { box-shadow: none; }
  .schoolmap { height: 60vh; }
  .schoolrows { max-height: none; overflow-y: visible; }
  .schoolwrap[data-pane="list"] .schoolmap-shell { display: none; }
  .schoolwrap[data-pane="map"] .schoolside { display: none; }
}
@media (max-width: 560px) {
  .schoolrow { padding: .65rem .7rem; }
  .schoolact { flex: 1 1 8rem; justify-content: center; }
}

/* --------------------------------------------------------- leaflet overrides */
/* Vendored Leaflet is never edited (web/vendor/README.md), so its light-only chrome
   is re-tokenised here. Check both themes after any Leaflet upgrade. */
.leaflet-container {
  font: inherit;
  background: var(--surface-2);
  /* Leaflet's default focus ring is invisible against our surfaces. */
  outline-color: var(--brand);
}
/* Specificity matters here, and getting it wrong is invisible in light mode: Leaflet's
   own rules are `.leaflet-container .leaflet-control-attribution` and
   `.leaflet-touch .leaflet-bar a`, so a bare `.leaflet-bar a` loses and the map keeps a
   white attribution box on a dark page. Every override below is scoped through
   .leaflet-container to outrank them. */
.leaflet-container a { color: var(--brand); }
.leaflet-container .leaflet-bar,
.leaflet-container .leaflet-bar a,
.leaflet-container .leaflet-control-attribution {
  background: var(--surface);
  color: var(--muted);
  border-color: var(--border);
}
.leaflet-container .leaflet-bar {
  border-radius: var(--r-md); overflow: hidden; box-shadow: var(--shadow-lg); border: 0;
}
.leaflet-container .leaflet-bar a { color: var(--text); border-bottom-color: var(--border); }
.leaflet-container .leaflet-bar a:hover,
.leaflet-container .leaflet-bar a:focus { background: var(--surface-2); color: var(--text); }
.leaflet-container .leaflet-control-attribution {
  padding: .1rem .45rem; font-size: .68rem; border-radius: var(--r-xs) 0 0 0;
}
/* The attribution links are ~10.9px text in a 13px box — under the WCAG 2.5.8 24px
   floor. The "inline text" exception would cover them (they sit in a sentence), but
   this codebase gives inline links the floor rather than leaning on the exception, so
   they get it here too. Vertical padding only: it grows the hit area without moving
   the text, and the bar's own `padding: .1rem .45rem` keeps the corner tidy. The
   licence text itself is untouched — Kartverket's NLOD attribution is a condition. */
.leaflet-container .leaflet-control-attribution a {
  color: var(--brand); display: inline-block; padding-block: 7px;
}
.leaflet-container .leaflet-control-attribution { line-height: 1; }
.leaflet-container .leaflet-popup-content-wrapper,
.leaflet-container .leaflet-popup-tip {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-lg);
}
.leaflet-container .leaflet-popup-content { margin: .7rem .85rem; font-size: .88rem; line-height: 1.5; }
.leaflet-container .leaflet-popup-content a { font-weight: 650; }
.leaflet-container .leaflet-popup-close-button { color: var(--muted); }
.leaflet-container .leaflet-tooltip,
.leaflet-tooltip {
  background: var(--surface); color: var(--text);
  border-color: var(--border); box-shadow: var(--shadow);
  font-size: .8rem; font-weight: 650;
}
.leaflet-tooltip-top::before { border-top-color: var(--border); }

/* Leaflet's own zoom/pan easings ignore the media query; ours must not. */
@media (prefers-reduced-motion: reduce) {
  .schoolrow, .schoolzoomhint { transition: none; }
  .schoolrow:hover { transform: none; }
  .schoolrow::before, .schoolcluster span { transition: none; }
  .schoolcluster:hover span { transform: none; }
}
