/* =========================================================================
   Ontario Playground design system (Stitch redesign, 2026)
   Tokens from ontario_playground/DESIGN.md — translated to hand-written CSS
   (no Tailwind runtime: architecture decision D5, no build step).
   ========================================================================= */
:root {
  /* Surfaces & text */
  --cream: #f9f8f4;
  --paper: #ffffff;
  --paper-dim: #f4f4f0;
  --ink: #1b1c1a;
  --ink-soft: #454840;
  --muted: #595959;            /* accessible grey */
  --outline: #c5c8bd;
  --surface-variant: #e3e2df;  /* Stitch's border grey — lighter than --outline */

  /* Brand */
  --forest: #2b381f;           /* primary text/buttons */
  --forest-deep: #16220c;
  --sage: #7ca982;
  --mint: #c1e1c1;
  --secondary: #116e00;
  /* Stitch secondary-container / on-secondary-container. Promoted out of
     home.css so the dashboard can use them for active filter chips. */
  --hp-lime: #86fd68;
  --hp-on-lime: #137500;

  /* Age groups (approved new palette) */
  /* Location types. Same hues as the age palette by design — water is blue,
     sand is amber — but named separately so the two can diverge later. */
  --type-playground: #116e00;
  --type-splash: #4a90e2;
  --type-beach: #f39c12;

  --age-toddler: #4a90e2;      /* Toddler Blue */
  --age-preschool: #9b51e0;    /* Preschool Purple */
  --age-school: #f39c12;       /* School-age Orange */
  /* Darkened for text on a tint of the same hue — the raw brand colours are
     2-3:1 on white and fail AA at small sizes. Already proven by .tag.age-*. */
  --age-toddler-ink: #1d5aa8;
  --age-preschool-ink: #7126b8;
  --age-school-ink: #8a5100;

  /* Conditions */
  --cond-good: #2e7d32;
  --cond-fair: #8d9286;
  --cond-poor: #c0392b;

  /* Error (design: warm, non-alarmist) */
  --error: #ba1a1a;
  --warn: #f39c12;

  /* Shape & elevation */
  --r-sm: 0.5rem; --r-md: 1rem; --r-lg: 1.5rem; --r-pill: 999px;
  --shadow-1: 0 4px 20px rgba(43, 56, 31, 0.05);
  --shadow-2: 0 8px 30px rgba(43, 56, 31, 0.10);

  /* Shared layout scale (from the Stitch config) */
  --hp-container: 1200px;
  --hp-gutter-m: 20px;
  --hp-gutter-d: 64px;
  --nav-h: 76px;               /* measured height of the fixed bar */

  --font-head: "Plus Jakarta Sans", system-ui, sans-serif;
  --font-body: "Be Vietnam Pro", system-ui, sans-serif;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation: none !important; transition: none !important; }
}
body {
  margin: 0; background: var(--cream); color: var(--ink);
  font-family: var(--font-body); font-size: 16px; line-height: 1.5;
  /* clip (not hidden) — `hidden` would make body a scroll container and break
     the sticky header. Guards against stray full-bleed overflow on phones. */
  overflow-x: clip;
  -webkit-text-size-adjust: 100%;
}
h1, h2, h3, h4 { font-family: var(--font-head); color: var(--forest); line-height: 1.2; margin: 0 0 0.5rem; }
h1 { font-size: clamp(1.75rem, 4vw, 2.5rem); font-weight: 800; letter-spacing: -0.02em; }
h2 { font-size: 1.5rem; font-weight: 700; }
h3 { font-size: 1.15rem; font-weight: 700; }
a { color: var(--secondary); }
img { max-width: 100%; display: block; }

.ms { /* Material Symbols */
  font-family: "Material Symbols Outlined";
  font-weight: normal; font-style: normal; font-size: 1.25em;
  line-height: 1; letter-spacing: normal; text-transform: none;
  display: inline-block; vertical-align: -0.22em;
  -webkit-font-smoothing: antialiased; font-variation-settings: "FILL" 0, "wght" 400;
}

/* ---- Top bar -------------------------------------------------------------
   Shared by every page. Fixed, translucent cream with a 12px backdrop blur.
   Brand / "Find a Park" / "Add a Park" only, per the design. */
.hp-nav {
  position: fixed; top: 0; left: 0; width: 100%; z-index: 1100;
  background: rgba(249, 248, 244, 0.85);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.hp-nav-inner {
  display: flex; justify-content: space-between; align-items: center;
  width: 100%; max-width: var(--hp-container); margin-inline: auto;
  padding: 16px var(--hp-gutter-m);
}
.hp-brand {
  font-family: var(--font-head); font-size: 24px; font-weight: 400;
  letter-spacing: -0.025em; color: var(--forest); text-decoration: none;
}
.hp-nav-links { display: flex; align-items: center; gap: 32px; }
.hp-nav-only-mobile { display: none; }   /* revealed in the phone menu */
.hp-nav-links a {
  font-family: var(--font-body); font-size: 16px; font-weight: 700;
  color: var(--forest-deep); text-decoration: none; padding-bottom: 2px;
}
.hp-nav-links a.is-current { border-bottom: 2px solid var(--forest-deep); }
.hp-nav-links a:hover { color: var(--secondary); }
.hp-nav-actions { display: flex; align-items: center; gap: 16px; }
.hp-nav-cta {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--forest); color: #fff; text-decoration: none;
  padding: 10px 24px; border-radius: var(--r-pill);
  font-family: var(--font-body); font-size: 16px; font-weight: 600;
  border: 0; cursor: pointer;
}
.hp-nav-cta:hover { opacity: 0.9; }
.hp-nav-cta .ms { font-size: 20px; }
.hp-nav-toggle {
  display: none; background: none; border: 0; cursor: pointer;
  color: var(--forest); padding: 4px; line-height: 0;
  min-width: 44px; min-height: 44px; align-items: center; justify-content: center;
}
.hp-nav-toggle .ms { font-size: 32px; }

/* The bar is fixed, so every page except the home hero — which deliberately
   sits underneath it — has to reserve its height. */
body:not(.hp-page) { padding-top: var(--nav-h); }

.btn {
  display: inline-flex; align-items: center; gap: 0.45rem; justify-content: center;
  min-height: 48px; padding: 0.6rem 1.4rem; border-radius: var(--r-pill);
  font-family: var(--font-body); font-weight: 600; font-size: 1rem;
  border: none; cursor: pointer; text-decoration: none; transition: transform 0.06s, box-shadow 0.15s;
}
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--forest); color: #fff; box-shadow: var(--shadow-2); }
.btn-primary:hover { background: var(--forest-deep); }
.btn-secondary { background: var(--mint); color: var(--forest-deep); }
.btn-secondary:hover { background: var(--sage); color: #fff; }
.btn-ghost { background: transparent; color: var(--forest); border: 1px solid var(--outline); }
.btn-danger { background: var(--error); color: #fff; }
.btn-sm { min-height: 38px; padding: 0.35rem 1rem; font-size: 0.9rem; }
:focus-visible { outline: 3px solid var(--age-toddler); outline-offset: 2px; border-radius: 4px; }

/* ---- Explore layout -----------------------------------------------------
   Full-height app shell (Stitch): the page itself never scrolls, the map is
   pinned to the viewport, and only the results panel moves. Everything here is
   scoped to .app-shell / the ≥901px branch, so the phone layout below the
   stacking breakpoint is untouched. */
.explore-wrap { display: grid; grid-template-columns: 400px 1fr; min-height: 78vh; }
/* min-width:0 — grid items default to min-content width, and the Leaflet
   attribution bar was wide enough to push the page into horizontal scroll. */
.explore-wrap > * { min-width: 0; }
.rail {
  padding: 1rem; overflow-y: auto; max-height: calc(100vh - var(--nav-h));
  display: flex; flex-direction: column; gap: 1rem; background: var(--cream);
}
.rail-top, .rail-bottom { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }
.map-panel { position: relative; min-width: 0; }
#map, .bigmap { min-height: 60vh; height: 100%; }

@media (min-width: 901px) {
  /* box-sizing:border-box is set globally, so 100dvh composes correctly with
     the padding-top that reserves the fixed header. */
  body.app-shell { height: 100dvh; overflow: hidden; }
  .app-shell .explore-wrap { height: 100%; min-height: 0; }

  /* Stitch inverts our surfaces: white filter panel, cream results area. */
  .app-shell .rail {
    height: 100%; max-height: none; overflow: hidden; padding: 0; gap: 0;
    background: var(--paper); border-right: 1px solid var(--surface-variant);
  }
  .app-shell .rail-top {
    flex: 0 0 auto; padding: 20px; gap: 20px;
    border-bottom: 1px solid var(--surface-variant);
  }
  /* min-height:0 — a flex item's automatic minimum is its content size, which
     would let a long list push the rail taller than the viewport instead of
     scrolling inside it. */
  .app-shell .rail-bottom {
    flex: 1 1 auto; min-height: 0; overflow-y: auto;
    padding: 24px; gap: 16px; background: var(--cream);
  }
  /* The filter panel is the white surface now, so it stops being a card. */
  .app-shell .rail-top .filter-card {
    background: transparent; box-shadow: none; padding: 0; border-radius: 0;
  }
  /* Likewise the results container: Stitch puts white cards on cream, not a
     white block holding white cards. */
  .app-shell .rail-bottom > .card:not(.insights) {
    background: transparent; box-shadow: none; padding: 0;
  }
  .app-shell .map-panel { height: 100%; }
  .app-shell #map { min-height: 0; height: 100%; }
}

@media (min-width: 1280px) {
  .explore-wrap { grid-template-columns: 440px 1fr; }
}

/* Filter card is a <details> so it can collapse on phones; on desktop the
   summary is hidden and explore.js keeps it forced open. */
.filter-card > summary {
  display: none; cursor: pointer; list-style: none;
  font-family: var(--font-head); font-weight: 700; color: var(--forest);
  align-items: center; gap: 0.45rem; min-height: 44px;
}
.filter-card > summary::-webkit-details-marker { display: none; }
.filter-card > summary .chev { margin-left: auto; transition: transform 0.2s; }
.filter-card[open] > summary .chev { transform: rotate(90deg); }
.leaflet-container { font-family: var(--font-body); }

.card {
  background: var(--paper); border-radius: var(--r-lg); padding: 1rem 1.1rem;
  box-shadow: var(--shadow-1);
}
.card h2, .card h3 { margin-top: 0; }

/* Filter rail */
.search-box {
  display: flex; align-items: center; gap: 0.5rem; background: var(--paper);
  border-radius: var(--r-pill); padding: 0.65rem 1rem; box-shadow: var(--shadow-1);
}
/* Explore only — submit.html also uses .search-box and keeps the pill look. */
.app-shell .search-box {
  background: var(--cream); border-radius: var(--r-md); padding: 0 16px;
  gap: 12px; box-shadow: none;
}
/* Height lives on the input, not the wrapper: padding on the wrapper is dead
   space that looks tappable but is not. */
.app-shell .search-box input { min-height: 44px; }
.app-shell .search-box .ms { color: var(--outline); font-size: 20px; }
.app-shell .search-box input { font-size: 12px; line-height: 16px; }
.search-box input { border: none; outline: none; flex: 1; font: inherit; background: transparent; min-width: 0; }
/* Filter chips. Stitch runs a three-level hierarchy and so do we: the primary
   location-type chips are label-md at px-4 py-3, while age and facility chips
   are label-sm pills. Active state is Stitch's secondary-container lime. */
.chip-row { display: flex; flex-wrap: wrap; gap: 12px; }
.chip {
  border-radius: var(--r-md); padding: 10px 14px;
  border: 1px solid var(--surface-variant); background: var(--paper); cursor: pointer;
  font-family: var(--font-body); font-size: 12px; line-height: 16px;
  letter-spacing: 0.01em; font-weight: 600; color: var(--ink-soft);
  display: inline-flex; align-items: center; gap: 6px;
}
.chip .ms { font-size: 16px; }
.chip[aria-pressed="true"] {
  background: var(--hp-lime); border-color: transparent; color: var(--hp-on-lime);
}
/* Secondary chips: age groups and facilities. */
.chip-sm {
  border-radius: var(--r-pill); padding: 6px 12px; gap: 6px;
  font-size: 12px; line-height: 16px; letter-spacing: 0.01em; font-weight: 600;
}
.chip-sm .ms { font-size: 15px; }
/* Age chips carry their hue as a tint, with the darkened ink for AA contrast. */
.chip-age { border-color: transparent; }
.chip-age.age-t { background: rgba(74, 144, 226, 0.14); color: var(--age-toddler-ink); }
.chip-age.age-p { background: rgba(155, 81, 224, 0.14); color: var(--age-preschool-ink); }
.chip-age.age-s { background: rgba(243, 156, 18, 0.20); color: var(--age-school-ink); }
/* Selected = an inset ring in the chip's own ink. Filling with the raw age
   colour would drop the label to ~3:1 and fail AA at 12px. */
.chip-age[aria-pressed="true"] { box-shadow: inset 0 0 0 2px currentColor; }
/* flex-shrink:0 — the dot is an empty element, so its automatic minimum
   size is 0 and a squeezed chip could otherwise collapse it. */
.chip .dot { width: 12px; height: 12px; border-radius: 50%; display: inline-block; flex: 0 0 12px; }

/* Primary type chips ride a single scrolling row, as in Stitch, instead of
   wrapping to a second 46px line. The negative margin cancels the padding that
   exists only so overflow-y:hidden does not clip the focus ring. */
#type-chips {
  flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none; -ms-overflow-style: none;
  padding-block: 6px; margin-block: -6px;
}
#type-chips::-webkit-scrollbar { display: none; }
#type-chips .chip { flex: 0 0 auto; }

/* Facilities: icon-only circles (Stitch's amenity row). The label is kept in
   the DOM rather than swapped for a title attribute, so it is both the
   accessible name and the tooltip — and can simply become visible on touch. */
.fac-row { display: flex; flex-wrap: wrap; gap: 8px; }
.fac-btn {
  position: relative; width: 40px; height: 40px; padding: 0; cursor: pointer;
  border-radius: var(--r-pill); border: 0;
  background: var(--paper-dim); color: var(--ink-soft);
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font-family: var(--font-body);
}
.fac-btn .ms { font-size: 20px; }
.fac-btn:hover { background: var(--mint); color: var(--forest-deep); }
.fac-btn[aria-pressed="true"] {
  background: var(--hp-lime); border-color: transparent; color: var(--hp-on-lime);
}
.fac-label {
  position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%);
  background: var(--forest); color: #fff; font-size: 11px; line-height: 16px;
  font-weight: 600; letter-spacing: 0.02em; padding: 3px 8px;
  border-radius: var(--r-sm); white-space: nowrap;
  opacity: 0; pointer-events: none; transition: opacity 0.12s; z-index: 5;
}
/* :focus-visible too — a keyboard user needs the label as much as a mouse one. */
.fac-btn:hover .fac-label, .fac-btn:focus-visible .fac-label { opacity: 1; }

/* Water fountain lives here now: worth seeing on a park, not worth a filter. */
.more-check {
  display: flex; align-items: center; gap: 8px; cursor: pointer;
  font-family: var(--font-body); font-size: 14px; font-weight: 600; color: var(--ink-soft);
}
.more-check input { width: 18px; height: 18px; flex: 0 0 18px; }

/* Headings removed — the chips label themselves, and each row keeps its
   role="group" + aria-label so screen readers still get the grouping. */
.filter-group + .filter-group { margin-top: 16px; }

/* "More filters" + "Clear all" share one row; align-items:flex-start keeps the
   button level with the summary when the disclosure opens. */
.filter-foot {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 16px; margin-top: 16px;
}
.more-filters { flex: 1 1 auto; min-width: 0; }
.more-filters > summary {
  cursor: pointer; list-style: none; display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--font-body); font-size: 12px; line-height: 16px; font-weight: 600;
  letter-spacing: 0.01em; color: var(--muted);
  min-height: 24px;
}
.more-filters > summary::-webkit-details-marker { display: none; }
.more-filters > summary .chev { font-size: 16px; transition: transform 0.2s; }
.more-filters[open] > summary .chev { transform: rotate(90deg); }
.more-grid { display: grid; gap: 12px; margin-top: 12px; }
.more-grid .field label {
  font-size: 12px; line-height: 16px; font-weight: 600; letter-spacing: 0.01em;
  color: var(--muted); margin-bottom: 6px;
}
.more-grid select {
  font-size: 14px; padding: 10px 12px; border: 1px solid var(--surface-variant);
  background: var(--paper); border-radius: var(--r-md);
}
.filter-foot .linkbtn {
  font-size: 12px; line-height: 16px; font-weight: 600; letter-spacing: 0.01em;
  white-space: nowrap; text-decoration: none;
  border-bottom: 1px solid currentColor; padding-bottom: 1px;
  /* WCAG 2.2 SC 2.5.8 wants 24px minimum; the text box alone was 18px. */
  min-height: 24px; display: inline-flex; align-items: center;
}
.field label { display: block; font-weight: 600; font-size: 0.88rem; margin-bottom: 0.25rem; color: var(--ink-soft); }
select, input[type="text"], input[type="number"], input[type="search"],
input[type="password"], input[type="email"], input[type="tel"], input[type="url"],
textarea {
  width: 100%; padding: 0.65rem 0.8rem; border-radius: var(--r-md);
  border: 1px solid var(--sage); background: var(--cream); font: inherit; color: var(--ink);
}
select:focus, input:focus, textarea:focus { border-width: 2px; border-color: var(--sage); outline: none; }
/* Re-assert the bare look for inputs inside a .search-box pill. The generic
   field rule above matches with equal specificity but comes later, so it was
   drawing a second border inside the pill. */
.search-box input[type="search"], .search-box input[type="text"] {
  border: none; background: transparent; padding: 0; border-radius: 0; min-width: 0;
}
.search-box input:focus { border-width: 0; }
.linkbtn {
  background: none; border: none; color: var(--secondary); text-decoration: underline;
  cursor: pointer; font: inherit; padding: 0;
  /* WCAG 2.2 SC 2.5.8 — text-styled buttons still need a 24px target. */
  min-height: 24px; display: inline-flex; align-items: center;
}

/* KPI strip — lives inside Community Insights now, so it reads as data rather
   than as the first thing on the page. */
.kpis { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.kpi { background: var(--paper); border-radius: var(--r-md); text-align: center; padding: 0.5rem 0.25rem; box-shadow: var(--shadow-1); }
.kpi b { display: block; font-size: 1.3rem; font-family: var(--font-head); color: var(--forest); }
.kpi span { font-size: 0.75rem; color: var(--muted); }
.insights .kpis { margin-bottom: 4px; }
.insights .kpi {
  background: var(--cream); box-shadow: none; padding: 10px 6px;
}
.insights .kpi b { font-size: 18px; line-height: 24px; }
.insights .kpi span { font-size: 10px; line-height: 14px; letter-spacing: 0.02em; }

/* Result cards — Stitch: rounded-3xl, p-4, 96px thumb, gap-4, transparent
   border that turns mint on hover. */
.results-head {
  display: flex; align-items: center; gap: 8px;
  font-size: 16px; font-weight: 700; margin: 0 0 12px;
}
.results { display: flex; flex-direction: column; gap: 12px; }
.park-card {
  display: grid; grid-template-columns: 96px 1fr; gap: 16px; align-items: center;
  background: var(--paper); border-radius: var(--r-lg); padding: 16px;
  box-shadow: var(--shadow-1); cursor: pointer; border: 1px solid transparent;
  text-align: left; width: 100%; font: inherit;
}
.park-card:hover { box-shadow: var(--shadow-2); border-color: var(--mint); }
.park-card.selected { border-color: var(--sage); }
.park-card img, .park-card .ph {
  width: 96px; height: 96px; object-fit: cover; border-radius: var(--r-md);
}
.park-card .ph { background: var(--mint); display: grid; place-items: center; color: var(--forest); }
.park-card h3 { margin: 0; font-size: 16px; line-height: 24px; font-weight: 700; }
.park-card .sub {
  color: var(--muted); font-size: 12px; line-height: 16px; letter-spacing: 0.03em;
  margin: 2px 0 8px;
}
/* 10px/700 per Stitch. Scoped so admin.html's chips keep their own size. */
.park-card .mini-chip, #count-pill { font-size: 10px; letter-spacing: 0.02em; }
.mini-chips { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.mini-chip {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.03em;
  background: var(--paper-dim); color: var(--ink-soft);
  border-radius: var(--r-pill); padding: 0.15rem 0.55rem; display: inline-flex; gap: 0.25rem; align-items: center;
}
.mini-chip.ok { background: rgba(17, 110, 0, 0.12); color: var(--secondary); }
.mini-chip.a11y { background: rgba(74, 144, 226, 0.14); color: var(--age-toddler-ink); }
/* Washroom had been sharing the green with Shade. */
.mini-chip.wc { background: rgba(155, 81, 224, 0.14); color: var(--age-preschool-ink); }

/* Footer line when filter matches fall outside the current map view. */
.list-more {
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
  margin: 0.2rem 0 0; padding: 0.55rem 0.2rem; font-size: 0.82rem; color: var(--muted);
}

/* ---- Map markers -------------------------------------------------------
   Stitch: a coloured circle in a white ring, icon only. Colour = type. */
.park-marker {
  width: 100%; height: 100%; border-radius: var(--r-pill);
  border: 3px solid #fff; box-shadow: 0 3px 10px rgba(43, 56, 31, 0.30);
  display: flex; align-items: center; justify-content: center;
  background: var(--type-playground); color: #fff;
  transition: box-shadow 0.15s;
}
.park-marker .ms { font-size: 15px; color: inherit; }
.park-marker.t-playground { background: var(--type-playground); }
.park-marker.t-splash_pad { background: var(--type-splash); }
/* Amber is light: a white glyph on it is 2.2:1, well under the 3:1 WCAG 1.4.11
   asks of meaningful graphics. Dark ink on the light fill instead. */
.park-marker.t-beach { background: var(--type-beach); color: var(--forest-deep); }
.park-marker.hl { box-shadow: 0 6px 18px rgba(43, 56, 31, 0.45); }
.park-marker.hl .ms { font-size: 19px; }

/* ---- Legend: Stitch's horizontal glass panel, top-right ----------------- */
.legend {
  position: absolute; top: 16px; right: 16px; z-index: 1000;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: var(--r-lg); padding: 12px 16px; box-shadow: var(--shadow-1);
  display: flex; align-items: center; gap: 20px;
  font-size: 12px; line-height: 16px; letter-spacing: 0.01em; color: var(--ink);
}
.legend div { display: flex; align-items: center; gap: 8px; margin: 0; }
/* The hairline keeps the light sage dot distinguishable from the panel. */
.lg-dot {
  width: 12px; height: 12px; border-radius: 50%; flex: 0 0 12px;
  border: 1px solid rgba(43, 56, 31, 0.25);
  /* inline-block so it still renders as a dot in running text (about.html),
     not only as a flex item inside .legend. */
  display: inline-block; vertical-align: -1px;
}
.lg-dot.t-playground { background: var(--type-playground); }
.lg-dot.t-splash_pad { background: var(--type-splash); }
.lg-dot.t-beach { background: var(--type-beach); }
/* Shrunk when it rides inside a 10px result-card chip. */
.mini-chip .lg-dot { width: 8px; height: 8px; flex: 0 0 8px; border-width: 1px; }

/* ---- Floating map controls (replacing Leaflet's default zoom) ----------- */
.map-controls {
  position: absolute; right: 16px; bottom: 16px; z-index: 1000;
  display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
}
.map-btn {
  width: 44px; height: 44px; border: 0; cursor: pointer; padding: 0;
  background: var(--paper); color: var(--ink);
  display: grid; place-items: center;
}
.map-btn:hover { background: var(--cream); }
.map-btn:disabled { opacity: 0.5; cursor: default; }
.map-btn .ms { font-size: 22px; }
.map-controls > .map-btn { border-radius: var(--r-pill); box-shadow: var(--shadow-2); }
.map-zoom {
  display: flex; flex-direction: column;
  border-radius: var(--r-md); overflow: hidden; box-shadow: var(--shadow-2);
}
.map-zoom .map-btn + .map-btn { border-top: 1px solid var(--surface-variant); }

/* ---- Age chips (result cards + map popup) ------------------------------- */
.age-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.age-chip {
  font-size: 10px; line-height: 14px; font-weight: 600; letter-spacing: 0.01em;
  padding: 3px 8px; border-radius: var(--r-pill); white-space: nowrap;
  display: inline-flex; align-items: center;
}
.age-chip.age-t { background: rgba(74, 144, 226, 0.14); color: var(--age-toddler-ink); }
.age-chip.age-p { background: rgba(155, 81, 224, 0.14); color: var(--age-preschool-ink); }
.age-chip.age-s { background: rgba(243, 156, 18, 0.20); color: var(--age-school-ink); }

/* Insights (collapsible) */
details.insights > summary {
  cursor: pointer; font-family: var(--font-head); font-weight: 700; color: var(--forest);
  list-style: none; display: flex; align-items: center; gap: 0.4rem;
}
details.insights > summary::-webkit-details-marker { display: none; }
details.insights > summary .ms { transition: transform 0.2s; }
details.insights[open] > summary .ms { transform: rotate(90deg); }
.chart-block { margin-top: 0.8rem; }
.chart-block h4 { margin: 0 0 0.3rem; font-size: 0.9rem; color: var(--ink-soft); }

/* Popup */
.popup { font-family: var(--font-body); max-width: 240px; }
.popup h3 { margin: 0 0 0.2rem; font-size: 1rem; }
.popup .sub { color: var(--muted); font-size: 0.82rem; margin-bottom: 0.4rem; }

/* ---- Park detail page ---------------------------------------------------- */
.detail-wrap { max-width: 1200px; margin: 0 auto; padding: 1.2rem clamp(1rem, 3vw, 2rem); display: grid; grid-template-columns: 1.7fr 1fr; gap: 1.2rem; align-items: start; }
.gallery { display: grid; grid-template-columns: 2fr 1fr; gap: 0.6rem; }
.gallery a img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--r-lg); }
.gallery .main img { height: 320px; }
.gallery .side { display: grid; gap: 0.6rem; }
.gallery .side img { height: 154px; }
.gallery-empty { background: var(--mint); border-radius: var(--r-lg); display: grid; place-items: center; height: 240px; color: var(--forest); font-weight: 600; gap: 0.2rem; text-align: center; }
.tag-row { display: flex; flex-wrap: wrap; gap: 0.45rem; margin: 0.6rem 0; }
.tag { border-radius: var(--r-pill); padding: 0.3rem 0.85rem; font-weight: 700; font-size: 0.82rem; }
.tag.type { background: var(--forest); color: #fff; }
.tag.age-t { background: rgba(74, 144, 226, 0.15); color: var(--age-toddler-ink); }
.tag.age-p { background: rgba(155, 81, 224, 0.15); color: var(--age-preschool-ink); }
.tag.age-s { background: rgba(243, 156, 18, 0.18); color: var(--age-school-ink); }
.tag.ok { background: rgba(17, 110, 0, 0.12); color: var(--secondary); }
.amenity-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 0.6rem; }
.amenity {
  background: var(--paper-dim); border-radius: var(--r-md); text-align: center;
  padding: 0.7rem 0.3rem; font-size: 0.78rem; font-weight: 600; color: var(--ink-soft);
}
.amenity .ms { display: block; margin: 0 auto 0.3rem; font-size: 1.5rem; color: var(--forest); background: #fff; border-radius: var(--r-pill); width: 44px; height: 44px; line-height: 44px; }
.amenity.off { opacity: 0.45; }
.amenity.off .ms { color: var(--muted); }
.equip-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.6rem; }
.equip-card { background: var(--paper-dim); border-radius: var(--r-md); padding: 0.7rem; display: flex; flex-direction: column; gap: 0.3rem; }
.equip-card b { font-size: 0.95rem; }
.cond-pill { border-radius: var(--r-pill); font-size: 0.72rem; font-weight: 700; width: fit-content; padding: 0.1rem 0.6rem; }
.cond-pill[data-c="Like new"] { background: rgba(46, 125, 50, 0.14); color: var(--cond-good); }
.cond-pill[data-c="Acceptable"] { background: rgba(141, 146, 134, 0.2); color: #565b52; }
.cond-pill[data-c="Very old"] { background: rgba(192, 57, 43, 0.12); color: var(--cond-poor); }
.side-map { height: 260px; border-radius: var(--r-lg); }
.addr-row { display: flex; gap: 0.5rem; align-items: center; margin-top: 0.6rem; flex-wrap: wrap; }
.detail-wrap .card { margin-bottom: 1.2rem; }

/* ---- Trust cards (submit page) -------------------------------------------
   Previously borrowed the landing's .cat-card, which became a 3-column grid
   during the home rebuild and laid these out sideways. Own rule now. */
.trust-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1rem; padding: 1.5rem 0;
}
.trust-card {
  background: var(--paper); border-radius: var(--r-lg); padding: 1.4rem;
  box-shadow: var(--shadow-1); display: flex; flex-direction: column; gap: 0.4rem;
}
.trust-card .ms {
  font-size: 1.6rem; color: var(--forest); background: var(--mint);
  border-radius: var(--r-pill); width: 48px; height: 48px;
  display: grid; place-items: center; margin-bottom: 0.3rem;
}
.trust-card h3 { margin: 0; font-size: 1.05rem; }
.trust-card p { margin: 0; color: var(--muted); font-size: 0.92rem; }

/* ---- Wizard (submit) ----------------------------------------------------- */
.wizard-wrap { max-width: 860px; margin: 0 auto; padding: 1.2rem clamp(1rem, 3vw, 2rem); }
.wizard-head { text-align: center; margin-bottom: 1.2rem; }
.steps { display: flex; align-items: center; gap: 0.5rem; background: var(--paper); border-radius: var(--r-lg) var(--r-lg) 0 0; padding: 0.9rem 1.2rem; box-shadow: var(--shadow-1); }
.steps .bar { flex: 1; height: 6px; border-radius: var(--r-pill); background: var(--paper-dim); }
.steps .bar.done { background: var(--forest); }
.steps .label { font-size: 0.85rem; font-weight: 700; color: var(--ink-soft); white-space: nowrap; }
.wizard-body { background: var(--paper); padding: 1.4rem; box-shadow: var(--shadow-1); }
.wizard-foot { display: flex; justify-content: space-between; gap: 1rem; background: var(--paper-dim); border-radius: 0 0 var(--r-lg) var(--r-lg); padding: 0.9rem 1.2rem; }
.step-panel[hidden] { display: none; }
.type-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 0.8rem; margin-bottom: 1rem; }
.type-card {
  border: 2px solid var(--outline); border-radius: var(--r-lg); background: var(--cream);
  padding: 1rem; text-align: center; cursor: pointer; font: inherit; font-weight: 700; color: var(--ink-soft);
}
.type-card .ms { display: block; font-size: 1.8rem; margin-bottom: 0.3rem; color: var(--forest); }
.type-card[aria-pressed="true"] { border-color: var(--forest); background: var(--mint); color: var(--forest-deep); }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.9rem 1.2rem; }
.form-grid .full { grid-column: 1 / -1; }
.pickmap { height: 300px; border-radius: var(--r-lg); }
/* Step 1 location finder: type-ahead search + GPS button, then the pin map. */
.geo-row { display: flex; gap: 0.6rem; align-items: stretch; flex-wrap: wrap; }
.geo-wrap { position: relative; flex: 1 1 260px; min-width: 0; }
.geo-row #use-gps { white-space: nowrap; }
/* Above Leaflet's panes (400) and controls (1000) — the map sits right below. */
.geo-list {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 1100;
  margin: 0; padding: 0.3rem 0; list-style: none; background: var(--paper);
  border: 1px solid var(--outline); border-radius: var(--r-md); box-shadow: var(--shadow-2);
  max-height: 320px; overflow-y: auto;
}
.geo-list li[role="option"] {
  display: flex; gap: 0.6rem; align-items: center; min-height: 44px;
  padding: 0.45rem 0.8rem; cursor: pointer;
}
.geo-list li[role="option"] .ms { color: var(--sage); font-size: 20px; flex: none; }
.geo-list li[aria-selected="true"], .geo-list li[role="option"]:hover { background: var(--paper-dim); }
.geo-list .geo-main { display: block; font-weight: 600; color: var(--ink); }
.geo-list .geo-sub { display: block; font-size: 0.8rem; color: var(--muted); }
.geo-list .geo-attrib { padding: 0.3rem 0.8rem 0.1rem; font-size: 0.72rem; color: var(--muted); }
.geo-msg { display: block; min-height: 1.2em; margin-top: 0.3rem; color: var(--muted); }
.pin-status { margin: 0.4rem 0 0; font-size: 0.88rem; color: var(--muted); }
.pin-status.set { color: var(--secondary); font-weight: 600; }
.coords-manual summary { cursor: pointer; font-size: 0.88rem; font-weight: 600; color: var(--ink-soft); min-height: 24px; }
.coords-row { display: flex; gap: 0.5rem; margin-top: 0.5rem; }
@media (max-width: 560px) {
  .geo-row #use-gps { flex: 1 1 100%; justify-content: center; min-height: 44px; }
}
.tri { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.tri label {
  border: 1px solid var(--outline); border-radius: var(--r-pill); padding: 0.4rem 0.9rem;
  cursor: pointer; font-size: 0.88rem; font-weight: 600; background: var(--paper);
}
.tri input { position: absolute; opacity: 0; }
.tri label:has(input:checked) { background: var(--forest); color: #fff; border-color: var(--forest); }
.tri label:has(input:focus-visible) { outline: 3px solid var(--age-toddler); }
.equip-entry { border: 1px solid var(--outline); border-radius: var(--r-md); padding: 0.8rem; margin-bottom: 0.7rem; display: grid; grid-template-columns: 1fr 1fr 1fr auto; gap: 0.6rem; align-items: end; background: var(--cream); }
.equip-entry .full { grid-column: 1 / -1; }
.dropzone {
  border: 2px dashed var(--sage); border-radius: var(--r-lg); background: var(--cream);
  padding: 1.6rem; text-align: center; color: var(--ink-soft); cursor: pointer;
}
.dropzone .ms { font-size: 2rem; color: var(--forest); background: #fff; border-radius: var(--r-pill); padding: 0.5rem; }
.previews { display: flex; gap: 0.6rem; flex-wrap: wrap; margin-top: 0.8rem; }
.previews figure { margin: 0; position: relative; }
.previews img { width: 96px; height: 96px; object-fit: cover; border-radius: var(--r-md); }
.previews button { position: absolute; top: -8px; right: -8px; border-radius: 50%; border: none; width: 24px; height: 24px; background: var(--error); color: #fff; cursor: pointer; }
.review-list dt { font-weight: 700; color: var(--ink-soft); font-size: 0.85rem; margin-top: 0.6rem; }
.review-list dd { margin: 0.1rem 0 0; }
.notice { border-radius: var(--r-md); padding: 0.7rem 1rem; margin: 0.8rem 0; font-size: 0.92rem; }
.notice.info { background: rgba(74, 144, 226, 0.1); border-left: 4px solid var(--age-toddler); }
.notice.ok { background: rgba(17, 110, 0, 0.1); border-left: 4px solid var(--secondary); }
.notice.err { background: rgba(243, 156, 18, 0.14); border-left: 4px solid var(--warn); }
.hidden { display: none !important; }
.hp { position: absolute; left: -9999px; height: 0; overflow: hidden; }

/* ---- Admin ---------------------------------------------------------------- */
.admin-wrap { max-width: 1100px; margin: 0 auto; padding: 1.2rem clamp(1rem, 3vw, 2rem); }
.tabs { display: flex; gap: 0.5rem; flex-wrap: wrap; margin: 1rem 0; }
.tabs .chip[aria-pressed="true"] { background: var(--forest); color: #fff; }
.sub-card { margin-bottom: 1rem; }
.sub-card header { display: flex; align-items: baseline; gap: 0.7rem; flex-wrap: wrap; }
.sub-card .meta { color: var(--muted); font-size: 0.83rem; }
.status-pill { border-radius: var(--r-pill); font-size: 0.72rem; font-weight: 800; padding: 0.15rem 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; }
.status-pill.pending { background: rgba(243, 156, 18, 0.18); color: #a36000; }
.status-pill.approved { background: rgba(17, 110, 0, 0.14); color: var(--secondary); }
.status-pill.rejected { background: rgba(186, 26, 26, 0.12); color: var(--error); }
.status-pill.archived { background: var(--paper-dim); color: var(--muted); }
.sub-card .actions { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.7rem; }
.sub-card table { border-collapse: collapse; font-size: 0.88rem; margin: 0.5rem 0; }
.sub-card td { padding: 0.15rem 0.6rem 0.15rem 0; }
.thumbs { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-top: 0.4rem; }
.thumbs img { width: 74px; height: 74px; object-fit: cover; border-radius: var(--r-sm); }
.rev-diff { margin: 0.4rem 0; padding: 0.45rem 0.6rem; border-left: 3px solid var(--age-preschool); background: rgba(155, 81, 224, 0.07); font-size: 0.9rem; border-radius: 0 var(--r-sm) var(--r-sm) 0; }
dialog.editor { border: none; border-radius: var(--r-lg); box-shadow: var(--shadow-2); max-width: 720px; width: 92vw; padding: 1.2rem; }
dialog.editor::backdrop { background: rgba(27, 28, 26, 0.45); }

/* ---- About / prose -------------------------------------------------------- */
.prose { max-width: 760px; margin: 0 auto; padding: 1.5rem clamp(1rem, 3vw, 2rem); }
.prose .card { margin-bottom: 1rem; }

/* ---- Footer ---------------------------------------------------------------- */
.site-footer {
  background: var(--forest-deep); color: #cfd8c4; margin-top: 2.5rem;
  padding: 1.6rem clamp(1rem, 4vw, 4rem); display: flex; gap: 1.5rem; flex-wrap: wrap;
  justify-content: space-between; align-items: center; font-size: 0.9rem;
}
.site-footer a { color: #e7ecdf; }
/* WCAG 2.2 SC 2.5.8: these were 15-18px tall and too closely packed to qualify
   for the spacing exception. */
.site-footer a, .site-footer .brand {
  display: inline-block; min-height: 24px; min-width: 24px; padding-block: 3px;
  text-align: center;
}
.site-footer .brand { color: #fff; }
/* Staff entry point: reachable, but deliberately quiet — it is not a
   destination for the families the site is built for. */
.footer-admin { opacity: 0.6; font-size: 0.85em; }
.footer-admin:hover { opacity: 1; }

/* =========================================================================
   Responsive layers
   1100px  desktop → narrow desktop      900px  → tablet / stacked explore
    860px  nav collapses behind toggle   560px  → phone
   ========================================================================= */

@media (max-width: 1100px) {
  .explore-wrap { grid-template-columns: 350px 1fr; }
}

/* ---- Nav collapses ------------------------------------------------------ */
@media (max-width: 860px) {
}

/* ---- Explore stacks: filters → map → results ---------------------------- */
@media (max-width: 900px) {
  .explore-wrap { display: flex; flex-direction: column; min-height: 0; }
  /* display:contents lets .rail's two halves become siblings of the map so the
     map can be ordered between them instead of above or below the whole rail. */
  .rail { display: contents; }
  .rail-top    { order: 1; padding: 0.9rem clamp(1rem, 4vw, 2rem) 0; gap: 0.8rem; }
  .map-panel   { order: 2; height: 58vh; min-height: 300px; margin: 0.9rem 0; }
  .rail-bottom { order: 3; padding: 0 clamp(1rem, 4vw, 2rem) 96px; gap: 0.9rem; }
  #map, .bigmap { min-height: 0; height: 100%; border-radius: 0; }
  .leaflet-container { border-radius: 0; }

  .filter-card > summary { display: flex; }
  .filter-card[open] > summary { margin-bottom: 0.8rem; }

  /* Bottom-left: the Leaflet attribution bar owns the bottom-right corner, and
     the two were overlapping once the map got narrow. */
  .legend { font-size: 11px; padding: 8px 10px; gap: 12px; top: 8px; right: 8px; }
  .legend div { margin: 0; gap: 6px; }
  .map-controls {
    left: 8px; right: auto; bottom: 26px; flex-direction: row; align-items: center;
  }
  .map-zoom { flex-direction: row; }
  .map-zoom .map-btn + .map-btn {
    border-top: 0; border-left: 1px solid var(--surface-variant);
  }

  .detail-wrap { grid-template-columns: 1fr; }
  .form-grid, .equip-entry { grid-template-columns: 1fr; }
  .gallery { grid-template-columns: 1fr; }
  .gallery .side { grid-template-columns: 1fr 1fr; }
  .gallery .main img { height: 240px; }
  .steps .label { display: none; }

}

@media (max-width: 900px) and (min-height: 480px) {
  .map-panel { height: 58dvh; }
}

/* ---- Phone -------------------------------------------------------------- */
@media (max-width: 560px) {
  h1 { font-size: 1.65rem; }
  h2 { font-size: 1.3rem; }


  .card { padding: 0.9rem; border-radius: var(--r-md); }
  .kpis { gap: 0.4rem; }
  .kpi b { font-size: 1.1rem; }
  .kpi span { font-size: 0.68rem; }

  .chip-row { gap: 8px; }

  .park-card { grid-template-columns: 80px 1fr; gap: 12px; padding: 12px; }
  .park-card img, .park-card .ph { width: 80px; height: 80px; }
  .map-panel { height: 52vh; min-height: 280px; }

  .detail-wrap, .wizard-wrap, .admin-wrap, .prose { padding-left: 1.1rem; padding-right: 1.1rem; }
  .gallery .main img { height: 190px; }
  .gallery .side img { height: 96px; }
  .amenity-grid { grid-template-columns: repeat(auto-fill, minmax(78px, 1fr)); }

  .wizard-body { padding: 1.05rem; }
  .steps { padding: 0.75rem 0.9rem; }
  .wizard-foot { padding: 0.75rem 0.9rem; gap: 0.6rem; }
  .wizard-foot .btn { flex: 1 1 0; padding-inline: 0.8rem; }
  .type-cards { grid-template-columns: 1fr 1fr; gap: 0.6rem; }
  .dropzone { padding: 1.1rem; }
  .previews img { width: 78px; height: 78px; }

  /* Admin tables are generated markup with no wrapper element, so the table
     itself becomes the scroll container rather than widening the page. */
  .sub-card table { display: block; overflow-x: auto; white-space: nowrap; max-width: 100%; }
  .sub-card .actions .btn { flex: 1 1 auto; }
  dialog.editor { width: 96vw; max-height: 88vh; overflow-y: auto; padding: 1rem; border-radius: var(--r-md); }

  .site-footer { flex-direction: column; align-items: flex-start; gap: 0.9rem; padding: 1.4rem 1.25rem; }

  /* Drop the age ranges; the shape and colour already carry the meaning and the
     full labels were taking half the map width. */
  .lg-long { display: none; }
  .legend { font-size: 10px; gap: 10px; padding: 7px 9px; }
  .lg-dot { width: 10px; height: 10px; flex-basis: 10px; }

}

/* ---- Coarse pointers: no hover-only affordances ------------------------- */
@media (hover: none) {
  .park-card:hover { box-shadow: var(--shadow-1); }
}

/* ---- Top bar: phone ------------------------------------------------------ */
@media (min-width: 768px) {
  .hp-nav-inner { padding-inline: var(--hp-gutter-d); }
}
@media (max-width: 767px) {
  .hp-nav-links {
    display: none; position: absolute; top: 100%; left: 0; width: 100%;
    flex-direction: column; align-items: stretch; gap: 0;
    background: rgba(249, 248, 244, 0.97); padding: 8px var(--hp-gutter-m) 16px;
    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.06);
  }
  .hp-nav-links[data-open="true"] { display: flex; }
  .hp-nav-links a { padding: 14px 0; min-height: 48px; display: flex; align-items: center; }
  .hp-nav-links a.is-current { border-bottom: 0; color: var(--secondary); }
  .hp-nav-only-mobile { display: flex; }
  .hp-nav-toggle { display: inline-flex; }
}
@media (max-width: 639px) {
  .hp-nav-cta { display: none; }
}

/* ---- Touch: keep the tightened chips at a comfortable target size --------
   Two guards on purpose. `pointer: coarse` covers touch laptops and tablets at
   desktop widths; the width query covers the stacked phone layout and is the
   one that is actually testable (CDP cannot emulate the pointer media feature). */
@media (pointer: coarse), (max-width: 900px) {
  .chip { min-height: 48px; }
  .chip-sm { min-height: 44px; padding-inline: 14px; }
  .more-filters > summary { min-height: 44px; }
  .filter-foot .linkbtn { min-height: 44px; display: inline-flex; align-items: center; }
  /* No hover here, so an icon-only control would be unlabelled. Promote the
     tooltip to a visible inline label and let the button grow into a pill. */
  .fac-btn { width: auto; height: auto; min-height: 44px; padding: 6px 14px; }
  .more-grid select, .more-check { min-height: 44px; }
  .fac-label {
    position: static; transform: none; opacity: 1; z-index: auto;
    background: none; color: inherit; padding: 0; white-space: nowrap;
    font-size: 12px; line-height: 16px; font-weight: 600; letter-spacing: 0.01em;
  }
}

/* ---- Mobile FAB --------------------------------------------------------
   Desktop keeps the header pill; on a phone that pill is hidden under 640px
   and this page has no footer, so the FAB is the contribution route. */
.fab { display: none; }
@media (max-width: 900px) {
  .fab {
    position: fixed; right: 16px; bottom: 16px; z-index: 1050;
    display: inline-flex; align-items: center; justify-content: center;
    width: 56px; height: 56px; border-radius: var(--r-pill);
    background: var(--forest); color: #fff; text-decoration: none;
    box-shadow: 0 8px 24px rgba(43, 56, 31, 0.45);
    transition: transform 0.08s;
  }
  .fab .ms { font-size: 28px; }
  .fab:active { transform: scale(0.94); }
}
