:root {
  --terracotta: #B5652F;
  --wine: #6B2737;
  --olive-vine: #6B7A4F;
  --stone: #C9BFA8;
  --cream: #F3E9DD;
  --ink: #2E2620;
  --paper: #FFFDFA;

  --font-heading: 'Vollkorn', Georgia, serif;
  --font-body: 'Karla', -apple-system, sans-serif;

  --shadow-card: 0 1px 2px rgba(46,38,32,0.06), 0 8px 24px rgba(46,38,32,0.10);
  --shadow-card-hover: 0 2px 4px rgba(46,38,32,0.08), 0 14px 32px rgba(46,38,32,0.14);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-body);
}

h1, h2, h3 { font-family: var(--font-heading); margin: 0; }

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

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--wine);
  color: var(--cream);
  padding: 0.75rem 1rem;
  z-index: 2000;
}
.skip-link:focus {
  left: 0;
}

/* Keeps content in the accessibility tree while removing it from view. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

main {
  /* Widened from 1500px and tightened from 1.75rem/1.5rem now the banner is gone
     — on a 1920px screen the old cap left ~210px of dead cream either side. The
     cap stays so the map does not stretch absurdly on an ultrawide display. */
  max-width: 1840px;
  margin: 0 auto;
  padding: 1rem 1.25rem 2.25rem;
}

.map-layout {
  display: flex;
  gap: 1.25rem;
  align-items: flex-start;
}

.legend-sidebar {
  /* 280px still fits the longest chip ("Montepulciano d'Abruzzo") on one line;
     going narrower starts wrapping them. */
  flex: 0 0 280px;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  /* Matches #map so the two columns cap at the same height when every section
     is expanded; it shrink-wraps when they are collapsed. */
  max-height: min(91vh, 1150px);
  overflow-y: auto;
  /* Paper, not a floating white card: the surface-card tone from the design
     system, a stone hairline, and only the faintest lift. */
  background: #FBF5EC;
  border: 1px solid var(--stone);
  border-radius: 16px;
  box-shadow: 0 1px 2px rgba(46,38,32,0.04);
  padding: 1.5rem 1.5rem 1.75rem;
}

.filter-group {
  position: relative;
}

.filter-group-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--stone);
  cursor: pointer;
  /* Suppress the native disclosure triangle in favour of the chevron below.
     Both properties are needed: `list-style` for Firefox and current Chrome,
     the pseudo-element for older WebKit. */
  list-style: none;
}
.filter-group-header::-webkit-details-marker {
  display: none;
}
.filter-group-header:focus-visible {
  outline: 2px solid var(--terracotta);
  outline-offset: 2px;
  border-radius: 2px;
}

.filter-group-label {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 700;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  /* Softer than the old wine: these are labels for the content, not headlines. */
  color: #5A5047;
}
.filter-group[open] > .filter-group-header .filter-group-label { color: var(--wine); }

/* Chevron: a rotated corner, so it needs no icon font or SVG. */
.filter-group-label::before {
  content: '';
  width: 0.34rem;
  height: 0.34rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform 0.15s ease;
  flex-shrink: 0;
}
.filter-group[open] > .filter-group-header .filter-group-label::before {
  transform: translateY(1px) rotate(-135deg);
}
@media (prefers-reduced-motion: reduce) {
  .filter-group-label::before { transition: none; }
}

/* Utility, so it sits back until you look for it. */
.select-all-btn {
  appearance: none;
  -webkit-appearance: none;
  background: none;
  border: none;
  padding: 0;
  font-family: var(--font-body);
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: #A99E82;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.12s ease;
}
.select-all-btn:hover {
  color: var(--terracotta);
}
.select-all-btn:focus-visible {
  outline: 2px solid var(--terracotta);
  outline-offset: 3px;
  border-radius: 2px;
}

.chip-row {
  display: flex;
  flex-direction: column;
}

.chip {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  min-height: 44px;
  padding: 0.3rem 0.5rem;
  margin: 0 -0.5rem;
  border-radius: 8px;
  color: #5A5047;
  font-family: var(--font-body);
  font-size: 0.94rem;
  cursor: pointer;
  transition: background-color 0.12s ease, color 0.12s ease;
}
.chip:hover {
  background-color: rgba(107,39,55,0.045);
}

/* The colour IS the control.
   The old row carried a wine-filled checkbox next to a coloured dot: two marks
   for one binary, and the checkbox was the heaviest thing in the panel. Now the
   swatch does both jobs — filled when the layer is on, a hollow ring when it is
   off — which also makes the panel read as the map's legend rather than a form.
   The native checkbox is still there for keyboard and screen readers, just not
   drawn. */
.chip input[type="checkbox"] {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.chip .swatch {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  flex-shrink: 0;
  background: transparent;
  box-shadow: inset 0 0 0 1.5px var(--swatch, var(--stone));
  transition: background-color 0.12s ease, box-shadow 0.12s ease;
}
.chip input[type="checkbox"]:checked ~ .swatch {
  background: var(--swatch, var(--stone));
  box-shadow: inset 0 0 0 1.5px var(--swatch, var(--stone));
}
/* An active layer's label sits in full ink; an inactive one stays muted, so the
   panel can be read at a glance without counting ticks. */
.chip:has(input[type="checkbox"]:checked) {
  color: var(--ink);
}
.chip input[type="checkbox"]:focus-visible ~ .swatch {
  outline: 2px solid var(--terracotta);
  outline-offset: 3px;
}
.chip[data-hatched="true"] .swatch {
  background-image: repeating-linear-gradient(45deg, var(--swatch, var(--stone)) 0 2px, transparent 2px 4px);
}

/* Denomination tier (DOC / DOCG). The name takes the space it needs and the
   badge holds its own column at the end, so tiers line up down the list and can
   be scanned without reading every label. */
.chip-text {
  flex: 1 1 auto;
  min-width: 0;
}
.chip-badge {
  flex-shrink: 0;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  line-height: 1;
  padding: 0.22rem 0.36rem;
  border-radius: 4px;
  color: var(--wine);
  background: rgba(107,39,55,0.09);
  /* Sits level with the label's x-height rather than its box. */
  align-self: center;
}
/* DOCG is the higher tier, so it reads as the stronger mark — filled rather than
   tinted. Two tiers, two weights: no legend needed to tell them apart. */
.chip-badge[data-tier="DOCG"] {
  color: var(--cream, #F3E9DD);
  background: var(--wine);
}
/* An unticked zone keeps its badge quiet along with the rest of the row. */
.chip:not(:has(input[type="checkbox"]:checked)) .chip-badge {
  opacity: 0.55;
}

#map {
  flex: 1;
  min-width: 0;
  width: 100%;
  /* Deliberately kept just under the viewport: with gestureHandling 'greedy' a
     wheel over the map zooms rather than scrolling, so a map taller than the
     screen would be awkward to scroll past. 91vh + the trimmed page padding
     still leaves the caveat line reachable. */
  height: min(91vh, 1150px);
  min-height: 360px;
  border-radius: 16px;
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

.data-caveat {
  font-size: 0.8rem;
  color: var(--ink);
  opacity: 0.75;
  margin-top: 0.75rem;
}

.site-footer {
  text-align: center;
  padding: 1.5rem 1rem;
  font-size: 0.85rem;
  color: var(--ink);
  background: var(--stone);
}
.footer-seal {
  display: block;
  margin: 0 auto 0.5rem;
  opacity: 0.85;
}

/* --- Google Maps InfoWindow theming ---
   Google wraps our content in its own .gm-style-iw chrome (rounded corners aside,
   left mostly at Google's defaults rather than fought over across API versions);
   our own card styling lives on the .wv-popup wrapper we control. */
.gm-style .gm-style-iw-c {
  border-radius: 10px;
  padding: 0 !important;
}
.gm-style .gm-style-iw-d {
  overflow: auto !important;
}
.wv-popup {
  background: var(--cream);
  color: var(--ink);
  padding: 0.9rem 1rem;
  max-height: 320px;
  font-family: var(--font-body);
  min-width: 220px;
}
.popup-title {
  font-family: var(--font-heading);
  font-size: 1.1rem;
  color: var(--wine);
  margin: 0 0 0.25rem;
}
.popup-town {
  margin: 0 0 0.5rem;
  color: var(--ink);
  opacity: 0.8;
  font-size: 0.9rem;
}
.badge {
  display: inline-block;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--cream);
  margin-bottom: 0.5rem;
}
.badge-perceived {
  background: repeating-linear-gradient(45deg, var(--olive-vine) 0 4px, var(--terracotta) 4px 8px);
  color: var(--cream);
}
.popup-note {
  font-size: 0.85rem;
  margin: 0 0 0.6rem;
}
.popup-soil {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.35rem;
  font-size: 0.85rem;
  margin: 0 0 0.6rem;
  padding: 0.45rem 0.55rem;
  background: rgba(107,39,55,0.05);
  border-left: 3px solid var(--stone);
  border-radius: 4px;
}
/* The chip rule is scoped to .chip, so the popup swatch needs its own. */
.popup-soil .swatch {
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
  flex-shrink: 0;
  border: 1px solid rgba(0,0,0,0.25);
  align-self: center;
}
.popup-soil-unit {
  font-style: italic;
}
.popup-soil-age {
  opacity: 0.7;
}
.filter-group-note {
  font-size: 0.72rem;
  line-height: 1.45;
  opacity: 0.75;
  margin: 0.7rem 0 0;
}
.popup-places {
  border-top: 1px solid var(--stone);
  padding-top: 0.5rem;
  margin-top: 0.5rem;
  font-size: 0.85rem;
}
.popup-places img {
  max-width: 100%;
  border-radius: 6px;
  margin: 0.4rem 0;
}
.popup-links {
  margin-top: 0.6rem;
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.popup-links a {
  color: var(--terracotta);
  font-weight: 700;
  text-decoration: none;
  font-size: 0.9rem;
}
.popup-links a:hover,
.popup-links a:focus {
  text-decoration: underline;
}
.approx-tag {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--wine);
  background: var(--stone);
  padding: 0.15rem 0.5rem;
  border-radius: 4px;
  margin-bottom: 0.5rem;
}
.source-link {
  font-size: 0.75rem;
  display: block;
  margin-top: 0.5rem;
  color: var(--olive-vine);
}

@media (max-width: 640px) {
  main { padding: 1.25rem 1rem 2rem; }
  /* Map first, filters below — otherwise the full checkbox list (12+ items)
     sits above the map and a phone visitor has to scroll past all of it before
     seeing any map at all. #map keeps its source order (filters, then map)
     for screen readers/tab order; only the visual position moves. */
  .map-layout { flex-direction: column; }
  #map { order: -1; }
  .legend-sidebar { flex: 0 0 auto; width: 100%; max-height: none; overflow-y: visible; margin-top: 1rem; padding: 1.25rem 1.25rem 1.5rem; }
  #map { height: 55vh; }
}

/* ---- Shared site nav ---------------------------------------------------
   Mirrors .site-nav in site.css, but written against this file's own tokens so
   the map page does not have to load both stylesheets (they collide on body,
   headings and .site-footer). Keep the two in sync when the nav changes. */
.site-nav {
  position: sticky;
  top: 0;
  z-index: 1500;
  background: rgba(243, 233, 221, 0.97);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--stone);
}
.site-nav__inner {
  max-width: 1160px;
  margin: 0 auto;
  padding: 16px 32px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.site-nav__logo { display: flex; }
.site-nav__logo img { height: 51px; width: auto; }
.site-nav__links {
  display: flex;
  align-items: center;
  gap: 22px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.site-nav__links a {
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.site-nav__links a:hover { color: var(--wine); }
.site-nav__links a[aria-current="page"] { font-weight: 700; color: var(--wine); }
.site-nav__cta {
  display: inline-flex;
  align-items: center;
  padding: 8px 16px;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  color: var(--cream);
  background: var(--terracotta);
  border: 1px solid var(--terracotta);
  border-radius: 5px;
  text-decoration: none;
  white-space: nowrap;
}
.site-nav__cta:hover { background: #9A5225; border-color: #9A5225; }

@media (max-width: 900px) {
  .site-nav__inner { flex-wrap: wrap; row-gap: 10px; padding: 12px 20px; }
  .site-nav__links { gap: 8px; width: 100%; justify-content: space-between; flex-wrap: nowrap; }
  .site-nav__cta { display: none; }
  .site-nav__links a { font-size: 15px; }
}

/* Comuni: 80-odd rows, so this group gets its own scroll and a tighter rhythm
   than the legend groups above it. */
.filter-group--long .chip-row {
  max-height: 320px;
  overflow-y: auto;
  padding-right: 0.25rem;
}
.filter-group--long .chip {
  min-height: 34px;
  font-size: 0.88rem;
}
.filter-group--long .chip .swatch {
  width: 9px;
  height: 9px;
}

/* Province sub-groups inside Comuni. 82 comuni is too many to scan flat, so
   they sit under their province; the section holds four rows until opened. */
.filter-group--long > .chip-row { max-height: none; overflow: visible; }

.subgroup { border-bottom: 1px solid var(--stone); }
.subgroup:last-child { border-bottom: 0; }
.subgroup-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.55rem 0;
  cursor: pointer;
  list-style: none;
}
.subgroup-header::-webkit-details-marker { display: none; }
.subgroup-header:focus-visible { outline: 2px solid var(--terracotta); outline-offset: 2px; border-radius: 2px; }
.subgroup-label {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-family: var(--font-body);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink);
}
.subgroup-label::before {
  content: '';
  width: 0.3rem;
  height: 0.3rem;
  border-right: 1.5px solid #A99E82;
  border-bottom: 1.5px solid #A99E82;
  transform: translateY(-2px) rotate(45deg);
  transition: transform 0.15s ease;
  flex-shrink: 0;
}
.subgroup[open] > .subgroup-header .subgroup-label::before { transform: translateY(1px) rotate(-135deg); }
@media (prefers-reduced-motion: reduce) { .subgroup-label::before { transition: none; } }

/* How many producers sit under this province. */
.subgroup-count {
  font-size: 0.7rem;
  font-weight: 700;
  color: #A99E82;
  font-variant-numeric: tabular-nums;
}
/* A province with nothing selected recedes rather than disappearing. */
.subgroup.is-off .subgroup-label { color: #A99E82; }

.subgroup > .chip-row {
  max-height: 260px;
  overflow-y: auto;
  padding: 0 0 0.4rem 0.9rem;
}

/* Producer index — the text version of the map.
   The map is a canvas drawn from JSON, so nothing in it is readable by a
   crawler, an AI agent or a screen reader. This lists the same producers as
   real HTML beneath it. Generated by scripts/build-site-index.js. */
.producer-index {
  max-width: 1160px;
  margin: 2.5rem auto 0;
  padding: 0 0.25rem;
}
.producer-index h2 {
  font-size: 1.6rem;
  color: var(--wine);
  margin: 0 0 0.75rem;
}
.producer-index__intro {
  font-size: 0.95rem;
  line-height: 1.7;
  color: var(--ink);
  max-width: 68ch;
  margin: 0 0 2rem;
}
.producer-index h3 {
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: #5A5047;
  margin: 2rem 0 0.6rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--stone);
}
.index-count { color: #A99E82; letter-spacing: 0; }
.producer-index__list {
  list-style: none;
  margin: 0;
  padding: 0;
  columns: 2;
  column-gap: 2.5rem;
}
.producer-index__list li {
  break-inside: avoid;
  font-size: 0.9rem;
  line-height: 1.6;
  padding: 0.45rem 0;
  border-bottom: 1px solid rgba(201,191,168,0.45);
}
.producer-index__list strong { font-weight: 600; }
.producer-index__list a { color: var(--terracotta); }

@media (max-width: 800px) {
  .producer-index__list { columns: 1; }
}

/* The producer index is collapsed by default: 156 entries is a lot of page for
   someone who came to look at a map. It stays in the DOM either way — visible
   to crawlers, agents and screen readers — which is the difference between
   collapsing content and hiding it. */
.producer-index__details { border-top: 1px solid var(--stone); }
.producer-index__summary {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  padding: 1.1rem 0;
  cursor: pointer;
  list-style: none;
}
.producer-index__summary::-webkit-details-marker { display: none; }
.producer-index__summary:focus-visible { outline: 2px solid var(--terracotta); outline-offset: 3px; border-radius: 2px; }
.producer-index__summary h2 {
  display: inline;
  font-size: 1.25rem;
  color: var(--wine);
  margin: 0;
}
.producer-index__summary::after {
  content: '';
  width: 0.4rem;
  height: 0.4rem;
  margin-left: auto;
  align-self: center;
  border-right: 1.5px solid #A99E82;
  border-bottom: 1.5px solid #A99E82;
  transform: translateY(-2px) rotate(45deg);
  transition: transform 0.15s ease;
}
.producer-index__details[open] > .producer-index__summary::after { transform: translateY(1px) rotate(-135deg); }
@media (prefers-reduced-motion: reduce) { .producer-index__summary::after { transition: none; } }
