*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

:root {
  --cream: #f5edd8;
  --beige: #e8d9be;
  --tan: #c9a97a;
  --brown-light: #8b6340;
  --brown: #5c3d1e;
  --brown-dark: #3a2210;
  --sage: #6b8c6b;
  --sage-light: #9ab89a;
  --sage-pale: #dde8dd;
  --rose: #b98a86;
  --rose-pale: #ecdad7;
  --text-main: #2e1a0e;
  --text-muted: #7a5c3f;
  --border: rgba(92, 61, 30, 0.15);
  --card-bg: #fbf5e8;
  --danger: #a4382f;
  --danger-pale: #f6e3e1;
  --focus: #2f6f9e;
  --shadow-card: 0 16px 40px rgba(58, 34, 16, 0.14);
  --radius-lg: 20px;
  --radius-md: 16px;
  --radius-sm: 10px;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: 'DM Sans', system-ui, -apple-system, sans-serif;
  background: var(--cream);
  color: var(--text-main);
  min-height: 100vh;
  line-height: 1.5;
}

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: 4px;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  z-index: 400;
  background: var(--brown-dark);
  color: var(--cream);
  padding: 10px 16px;
  border-radius: 0 0 var(--radius-sm) 0;
}

.skip-link:focus {
  left: 0;
}

/* ---------- nav ---------- */
nav {
  background: var(--brown-dark);
  padding: 0 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 60px;
  position: sticky;
  top: 0;
  z-index: 200;
}

.nav-logo {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 20px;
  color: var(--cream);
  letter-spacing: 0.03em;
  background: none;
  border: 0;
  cursor: pointer;
  padding: 6px 0;
  flex-shrink: 0;
  /* Three quick taps opens the admin; without this, the repeated taps select
     the text and phones pop up a copy/paste bubble mid-gesture. */
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

.nav-logo span {
  color: var(--sage-light);
  font-style: italic;
}

.nav-links {
  display: flex;
  gap: 4px;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.nav-btn {
  background: transparent;
  border: 1px solid transparent;
  color: var(--beige);
  padding: 8px 14px;
  border-radius: 20px;
  font-size: 12px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  cursor: pointer;
  font-family: inherit;
  transition: color 0.2s, background 0.2s, border-color 0.2s;
  opacity: 0.85;
}

.nav-btn:hover {
  opacity: 1;
  color: var(--sage-light);
}

.nav-btn[aria-current='page'] {
  background: rgba(107, 140, 107, 0.25);
  border-color: var(--sage);
  color: var(--sage-light);
  opacity: 1;
}

.nav-city {
  font-size: 11px;
  background: var(--sage);
  color: #fff;
  padding: 5px 10px;
  border-radius: 20px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* ---------- pages ---------- */
.page[hidden] {
  display: none;
}

/* ---------- hero ---------- */
.hero {
  text-align: center;
  padding: 3.5rem 1.5rem 2rem;
  background: linear-gradient(180deg, var(--brown-dark) 0%, var(--brown) 100%);
  color: var(--cream);
  position: relative;
  overflow: hidden;
}

.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: radial-gradient(ellipse at 20% 50%, rgba(155, 184, 154, 0.12) 0%, transparent 60%),
    radial-gradient(ellipse at 80% 20%, rgba(201, 169, 122, 0.1) 0%, transparent 50%);
  pointer-events: none;
}

.hero > * {
  position: relative;
}

.hero-eyebrow {
  font-size: 11px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--sage-light);
  margin-bottom: 0.75rem;
}

.hero h1 {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: clamp(28px, 6vw, 48px);
  font-weight: 400;
  line-height: 1.15;
  margin-bottom: 0.75rem;
}

.hero h1 em {
  font-style: italic;
  color: var(--tan);
}

.hero-sub {
  font-size: 14px;
  color: var(--beige);
  opacity: 0.85;
  max-width: 40ch;
  margin: 0 auto 2rem;
}

.filter-bar {
  display: flex;
  gap: 8px;
  justify-content: center;
  flex-wrap: wrap;
}

.filter-btn {
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.2);
  color: var(--cream);
  padding: 9px 16px;
  border-radius: 20px;
  font-size: 13px;
  letter-spacing: 0.04em;
  cursor: pointer;
  font-family: inherit;
  transition: background 0.2s, border-color 0.2s;
}

.filter-btn:hover,
.filter-btn[aria-pressed='true'] {
  background: var(--sage);
  border-color: var(--sage);
  color: #fff;
}

/* ---------- stats ---------- */
.stats-bar {
  background: var(--brown-light);
  display: flex;
  justify-content: center;
  gap: clamp(1.5rem, 8vw, 4rem);
  padding: 1rem 1.5rem;
  flex-wrap: wrap;
}

.stat {
  text-align: center;
}

.stat-num {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 22px;
  color: var(--cream);
  display: block;
}

.stat-label {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--beige);
  opacity: 0.8;
}

/* ---------- layout ---------- */
main {
  max-width: 1100px;
  margin: 0 auto;
  padding: 2.5rem 1.5rem 4rem;
}

.section-header {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}

.section-title {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 22px;
  font-weight: 400;
  color: var(--brown-dark);
}

.section-count {
  font-size: 12px;
  color: var(--text-muted);
  letter-spacing: 0.05em;
}

/* ---------- rating legend ---------- */
.legend {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1rem 1.2rem;
  margin-bottom: 1.75rem;
}

.legend summary {
  cursor: pointer;
  font-size: 13px;
  color: var(--brown);
  letter-spacing: 0.02em;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 8px;
}

.legend summary::-webkit-details-marker {
  display: none;
}

.legend summary::after {
  content: '+';
  margin-left: auto;
  font-size: 16px;
  color: var(--text-muted);
}

.legend[open] summary::after {
  content: '\2212';
}

.legend-items {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 1rem;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
}

.legend-item {
  display: flex;
  gap: 10px;
  align-items: flex-start;
}

.legend-swatch {
  flex-shrink: 0;
  display: flex;
  gap: 2px;
  padding-top: 2px;
}

.legend-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--brown-dark);
  display: block;
}

.legend-desc {
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.5;
}

/* ---------- card grid ---------- */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
  gap: 1.5rem;
}

.card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  text-align: left;
  font-family: inherit;
  cursor: pointer;
  padding: 0;
  transition: transform 0.25s ease, box-shadow 0.25s ease;
  position: relative;
  display: flex;
  flex-direction: column;
}

.card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-card);
}

@media (prefers-reduced-motion: reduce) {
  .card,
  .card:hover {
    transform: none;
    transition: none;
  }
}

.card-media {
  width: 100%;
  aspect-ratio: 3 / 2;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
  background: var(--beige);
}

.card-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.card-badge {
  position: absolute;
  top: 12px;
  right: 12px;
  background: var(--sage);
  color: #fff;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 12px;
}

.card-fav {
  position: absolute;
  top: 12px;
  left: 12px;
  background: rgba(58, 34, 16, 0.75);
  color: var(--tan);
  border-radius: 50%;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
}

.card-body {
  padding: 1.1rem 1.2rem 1.2rem;
  display: flex;
  flex-direction: column;
  flex: 1;
}

.card-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}

.card-neighbourhood {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sage);
}

.card-price {
  font-size: 12px;
  color: var(--text-muted);
  background: var(--sage-pale);
  padding: 2px 8px;
  border-radius: 8px;
}

.card-name {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 19px;
  color: var(--brown-dark);
  margin-bottom: 5px;
  line-height: 1.25;
}

.card-tagline {
  font-size: 13px;
  color: var(--text-muted);
  margin-bottom: 1rem;
  flex: 1;
}

.ratings-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 0.9rem;
  border-top: 1px solid var(--border);
}

.rating-item {
  display: flex;
  align-items: center;
  gap: 8px;
}

.rating-label {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  width: 66px;
  flex-shrink: 0;
}

.marks {
  display: flex;
  gap: 3px;
}

.mark {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

/* Placeholder tints and zone dots live here rather than as inline styles, so
   the CSP never needs 'unsafe-inline' in style-src. */
[data-tint='0'] {
  background: #d6c4a5;
}
[data-tint='1'] {
  background: #c8b89a;
}
[data-tint='2'] {
  background: #dccdb0;
}
[data-tint='3'] {
  background: #cfc0a2;
}

.map-card-dot[data-zone='downtown'] {
  background: #5c3d1e;
}
.map-card-dot[data-zone='east'] {
  background: #c9a97a;
}
.map-card-dot[data-zone='west'] {
  background: #6b8c6b;
}
.map-card-dot[data-zone='north'] {
  background: #8b6340;
}
.map-card-dot[data-zone='central'] {
  background: #b98a86;
}

body.is-modal-open {
  overflow: hidden;
}

/* ---------- states ---------- */
.state-wrap {
  grid-column: 1 / -1;
}

.state {
  text-align: center;
  padding: 3rem 1.5rem;
  background: var(--card-bg);
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
}

.state-title {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 20px;
  color: var(--brown-dark);
  margin-bottom: 0.4rem;
}

.state-body {
  font-size: 14px;
  color: var(--text-muted);
  max-width: 44ch;
  margin: 0 auto 1.2rem;
}

.state-action {
  background: var(--brown-dark);
  color: var(--cream);
  border: 0;
  border-radius: 20px;
  padding: 10px 20px;
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
}

.state-action:hover {
  background: var(--brown);
}

.state--error {
  border-style: solid;
  border-color: rgba(164, 56, 47, 0.35);
  background: var(--danger-pale);
}

.skeleton-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  min-height: 380px;
}

.skeleton-bar {
  background: linear-gradient(90deg, var(--beige) 25%, #f0e5cd 50%, var(--beige) 75%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease-in-out infinite;
}

.skeleton-media {
  aspect-ratio: 3 / 2;
}

.skeleton-line {
  height: 12px;
  border-radius: 6px;
  margin: 14px 1.2rem 0;
}

.skeleton-line--short {
  width: 45%;
}

@keyframes shimmer {
  0% {
    background-position: 100% 0;
  }
  100% {
    background-position: 0 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .skeleton-bar {
    animation: none;
  }
}

/* ---------- modal ---------- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(30, 16, 6, 0.82);
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  overflow-y: auto;
}

.modal-overlay[hidden] {
  display: none;
}

.modal {
  background: var(--card-bg);
  border-radius: var(--radius-lg);
  max-width: 700px;
  width: 100%;
  max-height: 92vh;
  overflow-y: auto;
  position: relative;
  animation: slide-up 0.3s ease;
}

@keyframes slide-up {
  from {
    transform: translateY(24px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .modal {
    animation: none;
  }
}

.modal-close {
  position: absolute;
  top: 14px;
  right: 16px;
  width: 40px;
  height: 40px;
  background: var(--brown-dark);
  color: var(--cream);
  border: none;
  border-radius: 50%;
  font-size: 20px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  line-height: 1;
}

.modal-media {
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: var(--beige);
}

.modal-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.modal-media-fill {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-content {
  padding: 1.6rem 1.6rem 2rem;
}

.modal-eyebrow {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-bottom: 0.5rem;
  flex-wrap: wrap;
}

.modal-neighbourhood {
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sage);
}

.modal-date {
  font-size: 12px;
  color: var(--text-muted);
}

.modal-name {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: clamp(22px, 5vw, 28px);
  font-weight: 400;
  color: var(--brown-dark);
  margin-bottom: 0.5rem;
  line-height: 1.2;
  padding-right: 3rem;
}

.modal-tags {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 1.2rem;
}

.tag {
  font-size: 11px;
  letter-spacing: 0.05em;
  background: var(--beige);
  color: var(--brown-light);
  padding: 4px 10px;
  border-radius: 10px;
}

.modal-desc {
  font-size: 14px;
  color: var(--text-muted);
  line-height: 1.75;
  margin-bottom: 1.6rem;
  white-space: pre-wrap;
}

.modal-ratings {
  background: var(--cream);
  border-radius: 14px;
  padding: 1.2rem;
  border: 1px solid var(--border);
  margin-bottom: 1.2rem;
}

.modal-ratings-title {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 16px;
  color: var(--brown-dark);
  margin-bottom: 0.8rem;
}

.modal-rating-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
}

.modal-rating-row:last-child {
  border-bottom: none;
}

.modal-rating-label {
  font-size: 13px;
  font-weight: 500;
  color: var(--brown);
}

.modal-rating-right {
  display: flex;
  align-items: center;
  gap: 10px;
}

.modal-rating-score {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 15px;
  color: var(--brown-dark);
  min-width: 34px;
  text-align: right;
}

.modal-overall {
  background: var(--brown-dark);
  border-radius: 12px;
  padding: 1rem 1.4rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.modal-overall-label {
  font-size: 13px;
  color: var(--beige);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.modal-overall-score {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 32px;
  color: var(--tan);
  line-height: 1;
}

.modal-overall-sub {
  font-size: 11px;
  color: var(--beige);
  opacity: 0.6;
  margin-top: 2px;
}

.modal-verdict {
  font-size: 13px;
  color: var(--sage-light);
  font-style: italic;
  margin-top: 0.4rem;
}

/* ---------- map ---------- */
.map-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 1.5rem;
  align-items: start;
}

.map-container {
  background: var(--beige);
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  position: relative;
  overflow: hidden;
}

.map-container svg {
  display: block;
  width: 100%;
  height: auto;
}

/* ---------- map rendering ----------
   Sizes are in SVG user units. Because the SVG scales to its container, a
   media query that bumps these makes the labels bigger *relative to the map*
   — which is the only way text stays legible when 660 units are squeezed
   into a 360px phone screen. */
.map-water {
  fill: #a9c9dd;
}

.map-land {
  fill: #f2e7d0;
  stroke: #dccdb0;
  stroke-width: 1;
}

.map-island {
  fill: #d9e2c8;
  stroke: #c3d0ae;
  stroke-width: 0.8;
}

.map-park {
  fill: #cfdcbb;
  stroke: none;
}

.map-valley {
  fill: none;
  stroke: #cfdcbb;
  stroke-width: 9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.map-river {
  fill: none;
  stroke: #a9c9dd;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.map-highway-casing {
  fill: none;
  stroke: #d8b98a;
  stroke-width: 5.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.map-highway {
  fill: none;
  stroke: #f6e2be;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.map-street {
  fill: none;
  stroke: #ffffff;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.95;
}

.map-street--1 {
  stroke-width: 3.2;
}

.map-street--2 {
  stroke-width: 1.8;
  opacity: 0.75;
}

/* Label sizes are written in the pixels they will be read at. --map-unit is
   how many map units make one CSS pixel, set from JS after layout, so text
   stays the same physical size whether the map is showing the whole city on
   a desktop or two streets on a phone.

   paint-order puts the halo behind the glyph, so names stay readable
   wherever they cross a road. */
.map-label-street,
.map-label-highway,
.map-label-district,
.map-label-water,
.map-label-hood,
.map-label-furniture {
  /* No --map-unit declaration here: declaring it would shadow the value
     inherited from the <svg>, which is where JS sets it. */
  font-family: 'DM Sans', system-ui, sans-serif;
  paint-order: stroke fill;
  stroke: #f2e7d0;
  stroke-width: calc(3 * var(--map-unit, 1) * 1px);
  stroke-linejoin: round;
  pointer-events: none;
}

.map-label-street {
  font-size: calc(10.5 * var(--map-unit, 1) * 1px);
  fill: #8a6d47;
  letter-spacing: 0.02em;
}

.map-label-highway {
  font-size: calc(10.5 * var(--map-unit, 1) * 1px);
  fill: #b07f3c;
  font-weight: 500;
}

.map-label-district {
  font-size: calc(12.5 * var(--map-unit, 1) * 1px);
  fill: #9c7a52;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.map-label-water {
  font-size: calc(12.5 * var(--map-unit, 1) * 1px);
  fill: #6f93aa;
  stroke: #a9c9dd;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.map-label-hood {
  font-size: calc(12 * var(--map-unit, 1) * 1px);
  fill: #3a2210;
  font-weight: 500;
}

.map-label-furniture {
  font-size: calc(10 * var(--map-unit, 1) * 1px);
  fill: #7a5c3f;
}

.map-scale {
  fill: none;
  stroke: #7a5c3f;
  stroke-width: 1.4;
}

.map-compass {
  fill: #7a5c3f;
}

.map-pin {
  cursor: pointer;
}

/* Invisible, and much larger than the drawing: the tap target should not be
   the size of the artwork. */
.map-pin-hit {
  fill: transparent;
}

.map-pin-shadow {
  fill: rgba(58, 34, 16, 0.28);
}

.map-pin-body {
  stroke: #fbf5e8;
  stroke-width: 1.6;
}

.map-pin:hover .map-pin-body,
.map-pin:focus .map-pin-body {
  stroke-width: 2.6;
}

.map-pin:focus {
  outline: none;
}

.map-pin:focus .map-pin-shadow {
  fill: rgba(47, 111, 158, 0.6);
}

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

.map-sidebar {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-height: 520px;
  overflow-y: auto;
}

.map-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 0.9rem 1rem;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  width: 100%;
  transition: border-color 0.2s, background 0.2s;
}

.map-card:hover,
.map-card.is-highlighted {
  border-color: var(--sage);
  background: var(--sage-pale);
}

.map-card-zone {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sage);
}

.map-card-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

.map-card-name {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 15px;
  color: var(--brown-dark);
  margin-bottom: 3px;
}

.map-card-meta {
  font-size: 12px;
  color: var(--text-muted);
}

.page-title {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: clamp(24px, 5vw, 30px);
  font-weight: 400;
  color: var(--brown-dark);
  margin-bottom: 0.35rem;
}

.page-sub {
  font-size: 14px;
  color: var(--text-muted);
  margin-bottom: 1.5rem;
}

/* ---------- best of ---------- */
.awards-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(255px, 1fr));
  gap: 1.2rem;
  margin-bottom: 2.5rem;
}

.award-card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1.3rem 1.4rem;
  position: relative;
  overflow: hidden;
}

.award-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 4px;
  height: 100%;
  background: var(--sage);
}

.award-category {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sage);
  margin-bottom: 6px;
}

.award-title {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 17px;
  color: var(--brown-dark);
  margin-bottom: 3px;
}

.award-winner {
  font-size: 13px;
  color: var(--brown-light);
  font-weight: 500;
  margin-bottom: 6px;
}

.award-reason {
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.55;
}

.top-list {
  background: var(--brown-dark);
  border-radius: var(--radius-lg);
  padding: 1.75rem;
  color: var(--cream);
}

.top-list-title {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 22px;
  color: var(--tan);
  margin-bottom: 1rem;
}

.top-list-item {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.9rem 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  width: 100%;
  background: none;
  border-left: 0;
  border-right: 0;
  border-top: 0;
  color: inherit;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}

.top-list-item:last-child {
  border-bottom: none;
}

.top-rank {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 28px;
  color: var(--tan);
  opacity: 0.5;
  width: 32px;
  flex-shrink: 0;
  line-height: 1;
}

.top-info-name {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 16px;
  color: var(--cream);
  margin-bottom: 2px;
}

.top-info-sub {
  font-size: 12px;
  color: var(--beige);
  opacity: 0.65;
}

.top-score {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 20px;
  color: var(--sage-light);
  margin-left: auto;
  padding-left: 12px;
}

/* ---------- footer ---------- */
footer {
  background: var(--brown-dark);
  color: var(--beige);
  text-align: center;
  padding: 2rem 1.5rem;
  font-size: 12px;
  opacity: 0.9;
  letter-spacing: 0.04em;
}

footer span {
  color: var(--sage-light);
}

/* Quiet, not invisible. 0.6 against the footer is 4.80:1 — over the 4.5:1 a
   link needs to be readable. 0.45 looked nicer and measured 3.34:1, which is
   not a trade worth making for something she has to find on a phone.
   :focus is listed alongside :focus-visible because a faint link that only
   brightens for one of them is a link some keyboard users cannot see. */
.footer-admin {
  color: var(--beige);
  opacity: 0.6;
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
  transition: opacity 0.2s, color 0.2s;
}

.footer-admin:hover,
.footer-admin:focus,
.footer-admin:focus-visible {
  opacity: 1;
  color: var(--sage-light);
}

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

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

/* ---------- admin ---------- */
.admin-shell {
  max-width: 940px;
  margin: 0 auto;
  padding: 2rem 1.5rem 4rem;
}

.admin-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
}

.admin-who {
  font-size: 12px;
  color: var(--text-muted);
}

.panel {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 1.5rem;
  margin-bottom: 1.5rem;
}

.panel h2 {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 20px;
  font-weight: 400;
  color: var(--brown-dark);
  margin-bottom: 1.2rem;
}

.field-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.field--wide {
  grid-column: 1 / -1;
}

.field label {
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--brown);
}

.field-hint {
  font-size: 12px;
  color: var(--text-muted);
}

/* 16px minimum: anything smaller makes iOS Safari zoom on focus. */
.field input,
.field select,
.field textarea {
  font-family: inherit;
  font-size: 16px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--text-main);
  width: 100%;
}

.field textarea {
  min-height: 120px;
  resize: vertical;
  line-height: 1.6;
}

.field input[aria-invalid='true'],
.field select[aria-invalid='true'],
.field textarea[aria-invalid='true'] {
  border-color: var(--danger);
  background: var(--danger-pale);
}

.field-error {
  font-size: 12px;
  color: var(--danger);
  min-height: 1em;
}

.field-check {
  flex-direction: row;
  align-items: center;
  gap: 10px;
}

.field-check input {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}

.field-check label {
  text-transform: none;
  letter-spacing: 0;
  font-size: 14px;
  color: var(--text-main);
}

/* ---------- sign in ---------- */
.admin-gate {
  max-width: 420px;
  margin: 0 auto;
  padding: 3rem 1.5rem 4rem;
}

.admin-gate[hidden],
.admin-shell[hidden] {
  display: none;
}

.login-panel .page-title {
  margin-bottom: 1.4rem;
}

.login-panel .field {
  margin-bottom: 1rem;
}

.login-panel .form-actions .btn {
  width: 100%;
}

.btn--tiny {
  padding: 4px 12px;
  min-height: 32px;
  font-size: 12px;
  margin-left: 10px;
}

.admin-who {
  display: flex;
  align-items: center;
}

/* ---------- maps lookup ---------- */
.lookup {
  background: var(--sage-pale);
  border: 1px solid var(--sage);
  border-radius: var(--radius-md);
  padding: 1.2rem;
  margin-bottom: 1.5rem;
}

.lookup h3 {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 17px;
  font-weight: 400;
  color: var(--brown-dark);
  margin-bottom: 0.3rem;
}

.lookup p {
  font-size: 13px;
  color: var(--text-muted);
  margin-bottom: 0.9rem;
}

.lookup-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.lookup-row input {
  flex: 1;
  min-width: 200px;
  font-family: inherit;
  font-size: 16px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--text-main);
}

.lookup-result {
  margin-top: 0.9rem;
  padding-top: 0.9rem;
  border-top: 1px solid rgba(92, 61, 30, 0.15);
  font-size: 14px;
  color: var(--brown-dark);
}

.lookup-result[hidden] {
  display: none;
}

.lookup-name {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 18px;
  display: block;
}

.lookup-where {
  font-size: 13px;
  color: var(--text-muted);
}

/* ---------- sliders ---------- */
.slider-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 1rem 0;
  border-bottom: 1px solid var(--border);
}

.slider-field:last-of-type {
  border-bottom: none;
}

.slider-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.slider-head label {
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--brown);
}

.slider-word {
  margin-left: auto;
  font-size: 13px;
  color: var(--brown-dark);
  font-weight: 500;
}

.slider-marks {
  display: flex;
  gap: 3px;
}

/* Chunky enough to hit with a thumb, and the same in both engines.
   --fill is set from JS as the thumb moves, so the track fills behind it. */
.slider-field input[type='range'] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 40px;
  background: transparent;
  cursor: pointer;
  margin: 0;
  --fill: 75%;
}

.slider-field input[type='range']::-webkit-slider-runnable-track {
  height: 10px;
  border-radius: 5px;
  background: linear-gradient(
    90deg,
    var(--sage) 0%,
    var(--sage) var(--fill),
    var(--beige) var(--fill),
    var(--beige) 100%
  );
}

.slider-field input[type='range']::-moz-range-track {
  height: 10px;
  border-radius: 5px;
  background: linear-gradient(
    90deg,
    var(--sage) 0%,
    var(--sage) var(--fill),
    var(--beige) var(--fill),
    var(--beige) 100%
  );
}

.slider-field input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 32px;
  height: 32px;
  margin-top: -11px;
  border-radius: 50%;
  background: var(--brown-dark);
  border: 4px solid var(--card-bg);
  box-shadow: 0 2px 8px rgba(58, 34, 16, 0.35);
}

.slider-field input[type='range']::-moz-range-thumb {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--brown-dark);
  border: 4px solid var(--card-bg);
  box-shadow: 0 2px 8px rgba(58, 34, 16, 0.35);
}

.slider-ticks {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  color: var(--text-muted);
  padding: 0 12px;
}

.slider-word {
  margin-left: auto;
  font-size: 14px;
  color: var(--brown-dark);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

/* ---------- photo thumbnails ---------- */
.photo-picker-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 0.6rem;
}

.photo-cover {
  position: absolute;
  bottom: 3px;
  left: 3px;
  background: rgba(58, 34, 16, 0.85);
  color: var(--cream);
  font-size: 9px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: 6px;
}

.photo-order {
  position: absolute;
  bottom: 3px;
  right: 3px;
  display: flex;
  gap: 3px;
}

.photo-order button {
  width: 24px;
  height: 24px;
  border: none;
  border-radius: 6px;
  background: rgba(58, 34, 16, 0.85);
  color: var(--cream);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}

.photo-order button:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

/* ---------- photos ---------- */
.photo-picker {
  border: 1px dashed var(--tan);
  border-radius: var(--radius-md);
  padding: 1.1rem;
  text-align: center;
}

.photo-picker input[type='file'] {
  display: block;
  margin: 0 auto;
  font-size: 15px;
  max-width: 100%;
}

.photo-strip {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 1rem;
}

.photo-strip:empty {
  margin-top: 0;
}

.photo-thumb {
  position: relative;
  width: 108px;
  height: 108px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--beige);
}

.photo-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.photo-remove {
  position: absolute;
  top: 3px;
  right: 3px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: none;
  background: rgba(58, 34, 16, 0.85);
  color: var(--cream);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}

.photo-thumb.is-busy {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  color: var(--text-muted);
}

/* ---------- gallery ---------- */
.modal-gallery {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 0 1.6rem 1rem;
  scroll-snap-type: x mandatory;
}

.modal-gallery:empty {
  display: none;
}

.modal-gallery img {
  height: 120px;
  border-radius: var(--radius-sm);
  scroll-snap-align: start;
  flex-shrink: 0;
}

.paid-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 1.2rem;
  font-size: 13px;
  color: var(--text-muted);
}

.paid-amount {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 17px;
  color: var(--brown-dark);
}

.form-actions {
  display: flex;
  gap: 10px;
  margin-top: 1.4rem;
  flex-wrap: wrap;
}

.btn {
  font-family: inherit;
  font-size: 14px;
  padding: 11px 22px;
  border-radius: 20px;
  border: 1px solid transparent;
  cursor: pointer;
  min-height: 44px;
}

.btn--primary {
  background: var(--brown-dark);
  color: var(--cream);
}

.btn--primary:hover:not(:disabled) {
  background: var(--brown);
}

.btn--ghost {
  background: transparent;
  border-color: var(--border);
  color: var(--brown);
}

.btn--danger {
  background: var(--danger);
  color: #fff;
}

.btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.notice {
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  font-size: 14px;
  margin-bottom: 1rem;
}

.notice[hidden] {
  display: none;
}

.notice--ok {
  background: var(--sage-pale);
  color: #2f4a2f;
  border: 1px solid var(--sage);
}

.notice--bad {
  background: var(--danger-pale);
  color: var(--danger);
  border: 1px solid rgba(164, 56, 47, 0.4);
}

.admin-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.admin-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
  flex-wrap: wrap;
}

.admin-row-main {
  flex: 1;
  min-width: 180px;
}

.admin-row-name {
  font-size: 15px;
  color: var(--brown-dark);
}

.admin-row-meta {
  font-size: 12px;
  color: var(--text-muted);
}

.pill {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 8px;
  background: var(--beige);
  color: var(--brown);
}

.pill--draft {
  background: var(--rose-pale);
  color: #7c4b46;
}

.admin-row-actions {
  display: flex;
  gap: 8px;
}

.admin-row-actions .btn {
  padding: 8px 14px;
  font-size: 13px;
  min-height: 40px;
}

/* ---------- confirm sheet ---------- */
/* A custom sheet rather than confirm(): iOS Safari suppresses native dialogs
   in enough situations that the delete button silently did nothing. */
.sheet-overlay {
  position: fixed;
  inset: 0;
  background: rgba(30, 16, 6, 0.6);
  z-index: 1100;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.sheet-overlay[hidden] {
  display: none;
}

.sheet {
  background: var(--card-bg);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  padding: 1.5rem;
  width: 100%;
  max-width: 520px;
  animation: slide-up 0.25s ease;
}

@media (min-width: 700px) {
  .sheet-overlay {
    align-items: center;
  }

  .sheet {
    border-radius: var(--radius-lg);
  }
}

.sheet h2 {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 19px;
  font-weight: 400;
  color: var(--brown-dark);
  margin-bottom: 0.5rem;
}

.sheet p {
  font-size: 14px;
  color: var(--text-muted);
  margin-bottom: 1.2rem;
}

.sheet-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sheet-actions .btn {
  width: 100%;
}

/* ---------- responsive ---------- */
@media (max-width: 860px) {
  .map-layout {
    grid-template-columns: 1fr;
  }

  .map-sidebar {
    max-height: none;
  }
}

/* Below this the whole 660-unit map is under ~600 CSS px, so 9px of label
   renders at 8px or less. Scale the type up and drop the minor street names
   rather than shipping something nobody can read. */
/* Label sizes need no breakpoint — --map-unit holds them at a fixed number of
   CSS pixels whatever the zoom. What a phone needs is fewer of them, and a
   map tall enough to be worth looking at. */
@media (max-width: 700px) {
  .map-label-minor {
    display: none;
  }

  .map-container svg {
    max-height: 64vh;
  }
}

@media (max-width: 640px) {
  nav {
    padding: 0.6rem 1rem;
    flex-wrap: wrap;
    gap: 0.5rem;
  }

  .nav-links {
    width: 100%;
    justify-content: flex-start;
  }

  .nav-city {
    margin-left: auto;
  }

  .hero {
    padding: 2.5rem 1.25rem 1.75rem;
  }

  main,
  .admin-shell {
    padding: 1.75rem 1rem 3rem;
  }

  .grid {
    grid-template-columns: 1fr;
  }

  .modal-content {
    padding: 1.3rem 1.15rem 1.75rem;
  }

  .panel {
    padding: 1.15rem;
  }

  .stats-bar {
    gap: 1.5rem;
  }

  .admin-row-actions {
    width: 100%;
  }

  .admin-row-actions .btn {
    flex: 1;
  }
}
