/* Greenville Market Tracker page-specific styles.
   Reuses design tokens declared in styles.css (--navy, --orange, etc). */

:root {
  --gv-bldc: #004E89;
  --gv-bldg: #38BDF8;
  --gv-demo: #E07B2E;
  --gv-demo-res: #FCA5A5;
  --gv-planning: #8B5CF6;
  --gv-closure: #DC2626;
  --gv-city: #1F2937;
  --gv-corridors: #F59E0B;
  --gv-districts: #2563EB;
  --gv-neighborhoods: #DB2777;
  --gv-zoning: #10B981;
  --gv-parks: #65A30D;
  --gv-trails: #0EA5E9;
  --gv-schools: #D97706;
  --gv-bus: #94A3B8;
  --gv-border: #E5E7EB;
}

.gv-main { background: #FAFBFC; }
.gv-hidden { display: none !important; }

/* ---------- Intro ---------- */
.gv-intro {
  padding: 2.5rem 0 1.25rem;
  background: linear-gradient(180deg, var(--white) 0%, #FAFBFC 100%);
}
.gv-intro h1 {
  margin: 0.25rem 0 0.75rem;
  font-size: clamp(1.85rem, 3.5vw, 2.5rem);
}
.gv-lede {
  max-width: 820px;
  font-size: 1.05rem;
  color: #4B5563;
  margin-bottom: 0.75rem;
}
/* "About this data" source line under the toolbar, above the map. */
.gv-data-source {
  padding: 0.25rem 1.5rem 0.6rem;
  font-size: 0.8rem;
  color: #6B7280;
  font-style: italic;
  margin: 0;
}

/* Secondary-and-below links on the map page's CTA banner: case study +
   interactive reports. Sits under the "No pitch" tagline so the primary
   Book-a-call button stays the dominant action. */
.cta-banner .cta-more-links {
  margin-top: 1.1rem;
  font-size: 0.9rem;
  color: rgba(255, 255, 255, 0.7);
}
.cta-banner .cta-more-links a {
  color: rgba(255, 255, 255, 0.9);
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.35);
  padding-bottom: 1px;
  margin: 0 0.15rem;
}
.cta-banner .cta-more-links a:hover {
  color: var(--white);
  border-bottom-color: var(--white);
}
.cta-banner .cta-more-sep {
  color: rgba(255, 255, 255, 0.4);
  margin: 0 0.35rem;
}
.gv-meta-row {
  list-style: none;
  margin: 0.6rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  /* Stretch so all chips in a row match the tallest card's height. */
  align-items: stretch;
  gap: 0.5rem 1rem;
  font-size: 0.78rem;
  color: #4B5563;
}
.gv-meta-item {
  display: flex;
  /* Center icon + text vertically within the chip so shorter single-line
     items sit in the middle rather than pinned to the top of taller neighbors. */
  align-items: center;
  gap: 0.5rem;
  background: #F8FAFC;
  border: 1px solid var(--gv-border);
  border-radius: 6px;
  padding: 0.5rem 0.75rem;
  max-width: 480px;
  line-height: 1.4;
}
.gv-meta-icon {
  color: var(--orange);
  flex-shrink: 0;
  width: 14px;
  height: 14px;
}
.gv-meta-privacy {
  background: #FFF7ED;
  border-color: #FED7AA;
  color: #7C2D12;
}
.gv-meta-privacy .gv-meta-icon { color: #C2410C; }
/* Author byline inside the "Built by" meta chip — keeps the name visually
   anchored so a casual visitor can put a face/name to the tool. */
.gv-meta-link {
  color: var(--navy);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid rgba(0, 78, 137, 0.3);
}
.gv-meta-link:hover {
  color: var(--orange);
  border-bottom-color: rgba(224, 123, 46, 0.55);
}
#gv-timestamp.ok::before {
  content: "";
  display: none;
}
.gv-timestamp {
  font-family: var(--font-heading);
  font-size: 0.85rem;
  color: #6B7280;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.gv-timestamp.ok::before {
  content: "● ";
  color: #16A34A;
  font-size: 1.1em;
}

/* ---------- Toolbar ---------- */
.gv-toolbar {
  background: var(--white);
  border-top: 1px solid var(--gv-border);
  border-bottom: 1px solid var(--gv-border);
  padding: 0.6rem 0;
  position: sticky;
  top: 72px;
  z-index: 50;
}
.gv-toolbar-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  align-items: center;
  justify-content: flex-end;
}
.gv-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  align-items: center;
}
.gv-filter-group {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
}
.gv-filter-group label {
  font-family: var(--font-heading);
  font-size: 0.65rem;
  font-weight: 600;
  color: var(--navy);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.gv-filter-valuation { width: 160px; }
.gv-filter-search { width: 200px; }

.gv-pill-group {
  display: inline-flex;
  background: var(--gray-100);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
}
.gv-pill {
  border: none;
  background: transparent;
  font-family: var(--font-heading);
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--gray-700);
  padding: 0.25rem 0.7rem;
  border-radius: 999px;
  cursor: pointer;
  transition: all var(--transition);
  white-space: nowrap;
}
.gv-pill:hover { color: var(--navy); }
.gv-pill.active {
  background: var(--navy);
  color: var(--white);
  box-shadow: 0 1px 3px rgba(0, 78, 137, 0.25);
}

/* "From Feb 2024 forward." sub-hint that only appears while the All pill
   is active. The #gv-date-range group sits immediately before this hint,
   so the :has() selector toggles visibility based on the All pill's state. */
.gv-date-all-hint {
  display: none;
  font-size: 0.66rem;
  color: var(--gray-700);
  margin: 0.35rem 0 0;
  font-style: italic;
}
#gv-date-range:has(.gv-pill[data-range="0"].active) + .gv-date-all-hint {
  display: block;
}

#gv-min-valuation {
  width: 100%;
  accent-color: var(--navy);
}
#gv-min-valuation-label {
  font-weight: 700;
  color: var(--navy);
  font-family: var(--font-heading);
}

#gv-address-search {
  font-family: var(--font-body);
  font-size: 0.82rem;
  padding: 0.35rem 0.7rem;
  border: 1px solid var(--gv-border);
  border-radius: 6px;
  width: 100%;
  outline: none;
  transition: border-color var(--transition);
}
#gv-address-search:focus { border-color: var(--navy); }

.gv-clear-btn {
  padding: 0.35rem 0.8rem !important;
  font-size: 0.75rem !important;
  border: 1px solid var(--gv-border) !important;
  height: fit-content;
  align-self: flex-end;
}

/* Slim chip-style summary stats. Replaces the larger stacked cards.
   One horizontal row, ~28px tall, reads as "687 permits · $678M value · 49% commercial". */
.gv-summary-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
}
.gv-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35rem;
  background: linear-gradient(135deg, var(--navy) 0%, var(--navy-dark) 100%);
  color: rgba(255, 255, 255, 0.85);
  padding: 0.25rem 0.7rem;
  border-radius: 999px;
  font-family: var(--font-heading);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.03em;
  box-shadow: 0 1px 2px rgba(0, 78, 137, 0.18);
  white-space: nowrap;
}
.gv-chip strong {
  color: var(--white);
  font-weight: 800;
  font-size: 0.9rem;
}
/* The split chip packs more text ("339 commercial · 317 residential") so we
   drop the bold-number split and just make the value itself read cleanly. */
.gv-chip-split strong {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

/* ---------- Map ---------- */
.gv-map-section { padding: 0.75rem 0 1.25rem; }
.gv-map-layout {
  display: grid;
  grid-template-columns: minmax(0, 320px) 1fr;
  gap: 1.25rem;
  padding: 0 1.5rem;
}
.gv-stories-sidebar {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  max-height: clamp(560px, 78vh, 860px);
}
.gv-stories-sidebar-header {
  background: var(--white);
  border: 1px solid var(--gv-border);
  border-radius: var(--radius-lg);
  padding: 1rem 1.1rem;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
}
.gv-stories-sidebar-header h2 {
  font-size: 1.05rem;
  margin: 0.25rem 0 0.4rem;
  line-height: 1.25;
}
.gv-stories-sidebar-hint {
  font-size: 0.78rem;
  color: #4B5563;
  margin: 0;
  line-height: 1.5;
}
.gv-stories-sidebar .gv-stories-strip {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin: 0;
  overflow-y: auto;
  padding-right: 2px; /* room for scrollbar */
}
.gv-map-wrap {
  position: relative;
  height: clamp(560px, 78vh, 860px);
  min-height: 520px;
  margin: 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
  border: 1px solid var(--gv-border);
  background: #E6EAF0;
}
/* When MapLibre takes the wrap fullscreen, override our rounded-corner styling
   so the map + legend fill the entire viewport cleanly. */
.gv-map-wrap:fullscreen {
  width: 100vw;
  height: 100vh;
  max-width: none;
  max-height: none;
  margin: 0;
  border-radius: 0;
  border: none;
  box-shadow: none;
}
#gv-map { width: 100%; height: 100%; }

.gv-legend {
  position: absolute;
  top: 1rem;
  right: 1rem;
  width: 260px;
  /* Use flex so the toggle button stays fixed-height at the top and the
     body is the only thing that scrolls — prevents the double scrollbar
     you get when both container and content have overflow:auto. */
  display: flex;
  flex-direction: column;
  max-height: calc(100% - 2rem);
  background: rgba(255, 255, 255, 0.97);
  backdrop-filter: blur(6px);
  border-radius: 10px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.12);
  font-size: 0.85rem;
  z-index: 5;
  overflow: hidden;
}
.gv-legend-toggle {
  width: 100%;
  padding: 0.7rem 1rem;
  border: none;
  background: var(--navy);
  color: var(--white);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 0.85rem;
  text-align: left;
  cursor: pointer;
  border-top-left-radius: 10px;
  border-top-right-radius: 10px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.gv-legend-toggle::after {
  content: "▾";
  transition: transform 0.2s;
}
.gv-legend-toggle[aria-expanded="false"]::after { transform: rotate(-90deg); }
.gv-legend-toggle[aria-expanded="false"] + .gv-legend-body { display: none; }
.gv-legend-body {
  padding: 0.6rem 0.75rem;
  font-size: 0.8rem;
  /* Body is the single scroll container: flex:1 + min-height:0 lets it
     take the leftover height inside .gv-legend (which caps the overall
     height). No max-height of its own — the parent flex bound is what
     stops it from exceeding the map area. */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  word-break: break-word;
}
.gv-legend-toggle { flex: 0 0 auto; }
.gv-legend-section {
  padding-bottom: 0.5rem;
  margin-bottom: 0.5rem;
  border-bottom: 1px solid var(--gv-border);
}
.gv-legend-section:last-of-type { border-bottom: none; margin-bottom: 0; }
/* Inline header+toggle row — puts a small "Clear all / Show all" button
   next to the DATA label so the user can mass-toggle plot points without
   clicking each sub-layer. */
.gv-legend-section-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.gv-legend-toggle-all {
  background: transparent;
  border: 1px solid var(--gv-border);
  border-radius: 999px;
  padding: 0.1rem 0.55rem;
  font-family: var(--font-heading);
  font-size: 0.62rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--gray-700);
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.gv-legend-toggle-all:hover {
  border-color: var(--navy);
  color: var(--navy);
}
.gv-legend-section-label,
.gv-legend-section h4 {
  font-family: var(--font-heading);
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--navy);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  margin-bottom: 0.3rem;
}
.gv-legend-row {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.1rem 0;
  cursor: pointer;
  user-select: none;
  font-size: 0.75rem;
  color: #374151;
  line-height: 1.3;
  /* Ensure rows never push horizontal scroll */
  min-width: 0;
  flex-wrap: wrap;
}
/* Sub-items indent a consistent amount without having to inline style. */
.gv-legend-row.gv-legend-sub { padding-left: 1.2rem; font-size: 0.72rem; }
.gv-legend-row input[type="checkbox"] {
  accent-color: var(--navy);
  cursor: pointer;
}
.gv-swatch {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 3px;
  flex-shrink: 0;
}
.gv-swatch-commercial { background: var(--gv-bldc); }
.gv-swatch-residential { background: var(--gv-bldg); }
.gv-swatch-demo { background: var(--gv-demo); }
.gv-swatch-planning { background: #440154; border: 2px solid var(--white); outline: 1px solid #440154; width: 10px; height: 10px; border-radius: 50%; }
.gv-swatch-planning-rezone { background: #440154; border: 2px solid #FFFFFF; outline: 1px solid #440154; width: 10px; height: 10px; border-radius: 50%; }
.gv-swatch-planning-annex { background: #21918C; border: 2px solid #FFFFFF; outline: 1px solid #21918C; width: 10px; height: 10px; border-radius: 50%; }
.gv-swatch-planning-subdiv { background: #FDE725; border: 2px solid #FFFFFF; outline: 1px solid #B45309; width: 10px; height: 10px; border-radius: 50%; }
.gv-swatch-residential-cluster {
  background: rgba(14, 124, 123, 0.22);
  border: 1px solid #0E7C7B;
  width: 14px;
  height: 14px;
  border-radius: 2px;
}
.gv-swatch-closures { background: var(--gv-closure); }
.gv-swatch-city { background: transparent; border: 2px solid var(--gv-city); }
.gv-swatch-corridors { background: var(--gv-corridors); opacity: 0.4; border: 1px solid var(--gv-corridors); }
.gv-swatch-districts { background: var(--gv-districts); opacity: 0.3; border: 1px solid var(--gv-districts); }
.gv-swatch-neighborhoods { background: var(--gv-neighborhoods); opacity: 0.35; border: 1px solid var(--gv-neighborhoods); }
.gv-swatch-zoning { background: var(--gv-zoning); opacity: 0.25; border: 1px solid var(--gv-zoning); }
.gv-swatch-parks { background: var(--gv-parks); opacity: 0.4; border: 1px solid var(--gv-parks); }
.gv-swatch-trails { background: var(--gv-trails); height: 3px; border-radius: 1px; margin-top: 5px; }
.gv-swatch-schools { background: var(--gv-schools); border-radius: 50%; }
.gv-swatch-bus { background: var(--gv-bus); border-radius: 50%; }

.gv-legend-hint {
  font-size: 0.72rem;
  color: #6B7280;
  margin: 0.75rem 0 0;
  line-height: 1.4;
}
/* Reset-filters button at the bottom of the legend panel. Replaces the
   toolbar Reset/Fit-to-screen pair, which crowded the summary chips. */
.gv-legend-reset {
  display: block;
  width: 100%;
  margin-top: 0.75rem;
  font-size: 0.78rem;
  padding: 0.4rem 0.6rem;
}

/* ---------- Detail panel ---------- */
.gv-detail-panel {
  position: absolute;
  top: 1rem;
  left: 1rem;
  bottom: 1rem;
  width: 360px;
  max-width: calc(100% - 2rem);
  background: var(--white);
  border-radius: var(--radius-lg);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
  transform: translateX(calc(-100% - 1rem));
  transition: transform 0.3s ease;
  z-index: 10;
  overflow-y: auto;
}
.gv-detail-panel[aria-hidden="false"] { transform: translateX(0); }
.gv-detail-close {
  position: absolute;
  top: 0.4rem;
  right: 0.5rem;
  width: 28px;
  height: 28px;
  background: var(--white);
  border: 1px solid var(--gv-border);
  border-radius: 50%;
  font-size: 1.1rem;
  color: var(--gray-700);
  cursor: pointer;
  line-height: 1;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  z-index: 2; /* sit above the picker-nav bar's border */
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
  transition: color 0.15s ease, border-color 0.15s ease;
}
.gv-detail-close:hover { color: var(--navy); border-color: var(--navy); }
.gv-detail-content { padding: 1.5rem 1.5rem 1.25rem; }
.gv-detail-content h3 {
  font-size: 1.05rem;
  margin: 0.25rem 0 0.5rem;
  line-height: 1.3;
  padding-right: 1.5rem;
}
.gv-detail-type {
  display: inline-block;
  font-family: var(--font-heading);
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--orange);
  margin-bottom: 0.4rem;
}
.gv-detail-valuation {
  font-family: var(--font-heading);
  font-size: 1.5rem;
  font-weight: 800;
  color: var(--navy);
  margin: 0.75rem 0;
}
.gv-detail-field {
  padding: 0.5rem 0;
  border-top: 1px solid var(--gray-100);
  font-size: 0.88rem;
  line-height: 1.5;
}
.gv-detail-field strong {
  display: block;
  font-family: var(--font-heading);
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--gray-700);
  margin-bottom: 0.15rem;
}
.gv-detail-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-top: 0.75rem;
}
.gv-detail-footnote {
  margin-top: 1rem;
  padding: 0.6rem 0.75rem;
  background: #F3F4F6;
  border-left: 3px solid #9CA3AF;
  border-radius: 6px;
  font-size: 0.75rem;
  font-style: italic;
  color: #4B5563;
  line-height: 1.5;
}

.gv-detail-tag {
  background: var(--gray-100);
  color: #374151;
  font-size: 0.72rem;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  font-family: var(--font-heading);
  font-weight: 600;
}

/* Cluster KPI strip above the picker list */
.gv-cluster-kpis {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.4rem;
  margin: 0.75rem 0 0.5rem;
}
.gv-cluster-kpi {
  background: linear-gradient(135deg, var(--navy) 0%, var(--navy-dark) 100%);
  color: var(--white);
  padding: 0.4rem 0.5rem;
  border-radius: 8px;
  text-align: center;
  line-height: 1.1;
}
/* Each KPI tile matches its permit-type pin color so the cluster summary
   visually connects to the pins the user will see after zooming in. */
.gv-cluster-kpi[data-kpi="commercial"] { background: var(--gv-bldc); }
.gv-cluster-kpi[data-kpi="residential"] { background: var(--gv-bldg); color: #0C4A6E; }
.gv-cluster-kpi[data-kpi="residential"] span { color: rgba(12, 74, 110, 0.75); }
.gv-cluster-kpi[data-kpi="demo"] { background: var(--gv-demo); }
.gv-cluster-kpi strong {
  display: block;
  font-family: var(--font-heading);
  font-size: 0.92rem;
  font-weight: 800;
}
.gv-cluster-kpi span {
  font-size: 0.62rem;
  color: rgba(255,255,255,0.85);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* "Zoom to expand" button below cluster KPIs */
.gv-picker-zoom-btn {
  display: block;
  width: 100%;
  background: var(--white);
  color: var(--navy);
  border: 1px solid rgba(0,78,137,0.3);
  padding: 0.5rem 0.9rem;
  border-radius: 8px;
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 0.82rem;
  cursor: pointer;
  margin-bottom: 0.5rem;
  transition: all 0.15s ease;
}
.gv-picker-zoom-btn:hover { background: var(--navy); color: var(--white); }

/* Hint text inside picker list */
.gv-picker-hint {
  font-size: 0.8rem;
  color: #6B7280;
  font-style: italic;
  margin: 0 0 0.5rem;
  line-height: 1.4;
}

/* Multi-permit picker list inside detail panel */
.gv-picker-list { list-style: none; margin: 0.75rem 0 0; padding: 0; }
.gv-picker-list li { margin: 0; }
.gv-picker-item {
  width: 100%;
  text-align: left;
  background: var(--white);
  border: 1px solid var(--gv-border);
  border-radius: 8px;
  padding: 0.7rem 0.9rem;
  margin-bottom: 0.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  cursor: pointer;
  transition: all 0.15s ease;
  font-family: var(--font-body);
}
.gv-picker-item:hover {
  border-color: var(--navy);
  background: #F8FAFC;
  transform: translateX(2px);
}
.gv-picker-title {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--navy);
}
.gv-picker-sub { font-size: 0.78rem; color: #4B5563; line-height: 1.4; }
.gv-picker-meta {
  font-family: var(--font-heading);
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--orange);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* Picker prev/next navigation */
.gv-picker-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
  margin: 0 2rem 0.9rem 0; /* right-margin clears the floating close button */
  padding: 0.4rem 0.6rem;
  background: linear-gradient(90deg, rgba(0,78,137,0.06), rgba(0,78,137,0.02));
  border-radius: 8px;
  border: 1px solid rgba(0,78,137,0.1);
}
.gv-picker-back-btn {
  background: var(--white);
  color: var(--navy);
  border: 1px solid rgba(0,78,137,0.25);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 0.7rem;
  padding: 0.25rem 0.65rem;
  border-radius: 999px;
  cursor: pointer;
  transition: all 0.15s ease;
  white-space: nowrap;
}
.gv-picker-back-btn:hover { background: var(--navy); color: var(--white); }
.gv-picker-nav-btn {
  background: var(--navy);
  color: var(--white);
  border: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.9rem;
  cursor: pointer;
  transition: all 0.15s ease;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.gv-picker-nav-btn:hover { background: var(--orange); }
.gv-picker-nav-label {
  font-family: var(--font-heading);
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--navy);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* Legend helper hint text */
.gv-hint {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.65rem;
  color: #9CA3AF;
  font-style: italic;
  margin-left: 0.25rem;
}
.gv-legend-explainer {
  font-size: 0.66rem;
  color: #4B5563;
  font-style: italic;
  margin: 0 0 0.25rem 1.2rem;
  line-height: 1.35;
}

/* ---------- Section subtitle override (left aligned on this page) ---------- */
.gv-charts-section .section-subtitle {
  text-align: left;
  margin-left: 0;
  margin-right: 0;
}

/* Story exit button is page-level fixed so it's reachable from any view
   (map, table, data-only). Sticks to bottom-right on desktop, full-width
   pill at the bottom on mobile for thumb reach. */
/* Story overlay — floating card on the map during story mode that shows
   the story title + blurb so the user has context right where they're
   looking, without needing to scroll back to the sidebar. */
.gv-story-overlay {
  position: absolute;
  bottom: 1rem;
  left: 1rem;
  right: auto;
  width: 300px;
  max-width: calc(100% - 2rem);
  background: rgba(255, 255, 255, 0.96);
  backdrop-filter: blur(6px);
  border-radius: var(--radius-lg);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
  padding: 0.8rem 1rem;
  z-index: 10;
  font-size: 0.85rem;
}
.gv-story-overlay[hidden] { display: none; }
.gv-story-overlay h3 {
  font-size: 0.9rem;
  margin: 0 0 0.3rem;
  line-height: 1.3;
  color: var(--navy);
}
.gv-story-overlay p {
  font-size: 0.78rem;
  color: #4B5563;
  line-height: 1.4;
  margin: 0 0 0.5rem;
}
.gv-story-overlay-exit {
  display: inline-block;
  background: none;
  border: 1px solid var(--gv-border);
  border-radius: 999px;
  padding: 0.25rem 0.7rem;
  font-family: var(--font-heading);
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--navy);
  cursor: pointer;
  transition: all var(--transition);
}
.gv-story-overlay-exit:hover {
  background: var(--navy);
  color: var(--white);
  border-color: var(--navy);
}

/* The old floating exit button is replaced by the exit button inside
   .gv-story-overlay — kept in the DOM for JS compatibility but hidden. */
.gv-story-exit { display: none !important; }

/* While in story mode, visually indicate that map filters are paused. */
body.gv-in-story .gv-summary-chips {
  opacity: 0.55;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
/* Dim the legend's filter controls (date range, valuation, data layers, and
   overlays) in story mode. Story mode owns the filter state while active —
   any mid-story toggle would silently mutate the user's pre-story snapshot,
   so we freeze the controls visually AND with pointer-events until exit. */
body.gv-in-story #gv-date-range,
body.gv-in-story .gv-legend-section[aria-labelledby="gv-legend-data"],
body.gv-in-story .gv-legend-section[aria-labelledby="gv-legend-overlays"],
body.gv-in-story .gv-date-all-hint {
  opacity: 0.45;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.gv-story-card {
  background: var(--white);
  border: 1px solid var(--gv-border);
  border-radius: var(--radius-lg);
  padding: 0.55rem 0.9rem;
  /* Row layout so the count pill can sit on the right of the title.
     p and cta wrap to the next line when expanded. */
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.6rem;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
  transition: all var(--transition);
  cursor: pointer;
  outline: none;
  text-align: left;
}
.gv-story-card h3 { order: 1; flex: 1 1 auto; min-width: 0; }
.gv-story-card .gv-story-count {
  order: 2;
  flex: 0 0 auto;
  margin-left: auto;
  font-size: 0.62rem;
  font-weight: 700;
  color: var(--navy);
  background: #EAF1F7;
  border-radius: 999px;
  padding: 0.15rem 0.55rem;
  text-transform: none;
  letter-spacing: 0;
  white-space: nowrap;
}
.gv-story-card p,
.gv-story-card .gv-story-cta { order: 3; flex: 0 0 100%; display: none; }
/* Cards stay compact even when active — the story overlay on the map
   shows the full blurb, so expanding the card is redundant. */
.gv-story-card.is-active p {
  font-size: 0.78rem;
  color: #4B5563;
  line-height: 1.4;
  margin: 0;
}
.gv-story-card:hover,
.gv-story-card:focus-visible {
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(0, 78, 137, 0.14);
  border-color: var(--navy);
}
.gv-story-card:focus-visible { outline: 2px solid var(--orange); outline-offset: 2px; }
.gv-story-card.is-active {
  border-color: var(--orange);
  box-shadow: 0 4px 14px rgba(224, 123, 46, 0.22);
  background: linear-gradient(135deg, #FFFBF5 0%, #FFFFFF 100%);
}
.gv-story-card.is-active .gv-story-cta::before {
  content: "✓ Showing on map — ";
  color: var(--orange);
}
.gv-story-card.is-active .gv-story-cta::after { content: " — click to exit"; }
.gv-story-card h3 {
  font-size: 0.92rem;
  line-height: 1.3;
  margin: 0;
}
/* .gv-story-card p defined earlier with line-clamp; no override here. */
.gv-story-cta {
  font-family: var(--font-heading);
  font-weight: 600;
  /* Stronger contrast — the previous #94A3B8 was legally-compliant but visually
     invisible against a white card. Mid-gray reads without screaming. */
  color: #475569;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  align-self: flex-start;
  padding: 0;
  margin-top: 0.25rem;
  transition: color 0.15s ease;
}
.gv-story-card:hover .gv-story-cta,
.gv-story-card:focus-visible .gv-story-cta { color: var(--navy); }
.gv-story-cta::after { content: " \2192"; }
/* Base .gv-story-count styling lives under .gv-story-card above; this
   selector is retained only so other future uses of the class have a sane
   default (nothing shared styles today). */

/* ---------- Charts ---------- */
.gv-charts-section { padding: 3rem 0 4rem; }
.gv-charts-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem;
  margin-top: 1.5rem;
}
.gv-chart-card {
  background: var(--white);
  border: 1px solid var(--gv-border);
  border-radius: var(--radius-lg);
  padding: 1.25rem;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
  display: flex;
  flex-direction: column;
  min-width: 0; /* prevents grid item expansion loop */
}
.gv-chart-card h3 {
  font-size: 0.9rem;
  margin-bottom: 0.75rem;
  font-family: var(--font-heading);
  font-weight: 700;
  color: var(--navy);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.gv-chart-card > .gv-chart-body {
  position: relative;
  width: 100%;
  height: 320px;
}
.gv-chart-card canvas {
  /* Chart.js will size to the parent .gv-chart-body's box. */
  display: block;
  width: 100% !important;
  height: 100% !important;
}

/* ---------- Responsive ---------- */
@media (max-width: 1024px) {
  .gv-toolbar-inner { gap: 0.6rem; }
  .gv-summary-chips { min-width: 0; }
  .gv-charts-grid { grid-template-columns: 1fr; }
  .gv-legend { width: 220px; }
  .gv-detail-panel { width: 300px; }
  .gv-map-layout { grid-template-columns: 1fr; }
  .gv-stories-sidebar { max-height: none; }
  .gv-stories-sidebar .gv-stories-strip {
    flex-direction: row;
    overflow-x: auto;
    padding-bottom: 0.5rem;
  }
  .gv-stories-sidebar .gv-story-card {
    /* Fixed width so long blurbs wrap inside each card instead of stretching
       the flex item to its content's natural width. */
    flex: 0 0 260px;
  }
  .gv-stories-sidebar .gv-story-card p { overflow-wrap: anywhere; }
}
@media (max-width: 768px) {
  .gv-toolbar { position: static; }
  /* #5 — Compact toolbar: tighter padding so the share/badge/chips row
     doesn't eat 13% of the viewport. */
  .gv-toolbar-inner { padding: 0.4rem 0.75rem; gap: 0.35rem 0.6rem; }
  .gv-chip { font-size: 0.65rem; padding: 0.2rem 0.55rem; }
  .gv-chip strong { font-size: 0.78rem; }
  /* #2 — Hide the split chip on mobile (too long to read at small width). */
  .gv-chip-split { display: none; }
  /* #3 — Hide data source italic line on mobile. */
  .gv-data-source { display: none; }
  /* #4 — Compact stories header: hide the hint, shrink h2. */
  .gv-stories-sidebar-hint { display: none; }
  .gv-stories-sidebar-header h2 { font-size: 0.9rem; margin: 0.15rem 0 0.2rem; }
  .gv-stories-sidebar-header { padding: 0.6rem 0.8rem; }
  /* Story overlay on mobile: bottom-positioned so it doesn't cover
     the map zoom controls at the top-left. */
  .gv-story-overlay {
    top: auto;
    bottom: 3.5rem;
    left: 0.75rem;
    right: 0.75rem;
    width: auto;
  }
  /* Story mode on mobile: cards stay compact even when active. The map
     is the focal point — expanding the blurb pushes it off-screen. */
  .gv-story-card.is-active { padding: 0.55rem 0.9rem; }
  .gv-story-card.is-active p,
  .gv-story-card.is-active .gv-story-cta { display: none; }
  /* Exit button: fixed pill centered above the map, not overlapping cards. */
  .gv-story-exit {
    position: fixed;
    top: auto;
    bottom: 1rem;
    left: 50%;
    transform: translateX(-50%);
    right: auto;
    z-index: 20;
    font-size: 0.8rem;
    padding: 0.5rem 1.2rem;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
  }

  .gv-filters { flex-direction: column; align-items: stretch; gap: 0.5rem; }
  .gv-filter-valuation, .gv-filter-search { width: 100%; }
  .gv-map-layout { padding: 0 0.75rem; }
  .gv-map-wrap { margin: 0; height: clamp(450px, 60vh, 600px); min-height: 420px; }
  .gv-chart-card > .gv-chart-body { height: 220px; }
  /* .gv-story-exit mobile override is in the first 768px block above */
  .gv-legend {
    top: auto;
    /* Clear the MapLibre attribution strip (~28px) that sits across the bottom. */
    bottom: 2.4rem;
    left: 0.75rem;
    right: 0.75rem;
    width: auto;
  }
  .gv-legend-body { max-height: 40vh; overflow-y: auto; }
  .gv-detail-panel {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    max-width: 100%;
    height: 65%;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    transform: translateY(100%);
  }
  .gv-detail-panel[aria-hidden="false"] { transform: translateY(0); }
}

/* ---------- Section head: view toggle + explainer ---------- */
.gv-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0 1.5rem 0.75rem;
  flex-wrap: wrap;
}
.gv-view-toggle {
  display: inline-flex;
  background: var(--gray-100);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
}
.gv-view-btn {
  border: none;
  background: transparent;
  font-family: var(--font-heading);
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--gray-700);
  padding: 0.45rem 1.1rem;
  border-radius: 999px;
  cursor: pointer;
  transition: all var(--transition);
  white-space: nowrap;
}
.gv-view-btn:hover { color: var(--navy); }
.gv-view-btn.active {
  background: var(--navy);
  color: var(--white);
  box-shadow: 0 1px 3px rgba(0, 78, 137, 0.25);
}
.gv-map-explainer {
  font-size: 0.85rem;
  color: #4B5563;
  margin: 0;
  flex: 1 1 320px;
  text-align: right;
  line-height: 1.5;
}
.gv-map-explainer strong { color: var(--navy); font-weight: 600; }

/* ---------- Privacy notice in detail panel ---------- */
.gv-detail-privacy {
  margin: 0.75rem 0 0.25rem;
  padding: 0.7rem 0.85rem;
  background: #FFF7ED;
  border: 1px solid #FED7AA;
  border-radius: 8px;
  font-size: 0.82rem;
  line-height: 1.5;
  color: #7C2D12;
}
.gv-detail-privacy strong { color: #7C2D12; }

/* ---------- Table view ---------- */
.gv-table-wrap {
  margin: 0 1.5rem;
  background: var(--white);
  border: 1px solid var(--gv-border);
  border-radius: var(--radius-lg);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
  overflow: hidden;
}
.gv-table-wrap[hidden] { display: none; }
.gv-table-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem 1.25rem;
  border-bottom: 1px solid var(--gv-border);
  background: #FAFBFC;
  flex-wrap: wrap;
}
.gv-table-count {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--navy);
}
.gv-table-hint {
  font-size: 0.78rem;
  color: #6B7280;
  font-style: italic;
}
.gv-table-scroll {
  max-height: clamp(520px, 75vh, 820px);
  overflow: auto;
}
.gv-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}
.gv-table thead th {
  position: sticky;
  top: 0;
  background: var(--white);
  text-align: left;
  font-family: var(--font-heading);
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--navy);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 0.7rem 0.9rem;
  border-bottom: 2px solid var(--gv-border);
  white-space: nowrap;
  z-index: 1;
}
.gv-table thead th.sortable { cursor: pointer; user-select: none; }
.gv-table thead th.sortable:hover { color: var(--orange); }
.gv-table thead th.sortable::after {
  content: " ↕";
  color: #CBD5E1;
  font-weight: 400;
  font-size: 0.85em;
}
.gv-table thead th.sort-asc::after { content: " ↑"; color: var(--orange); }
.gv-table thead th.sort-desc::after { content: " ↓"; color: var(--orange); }
.gv-table th.num, .gv-table td.num { text-align: right; }
.gv-table tbody tr {
  border-bottom: 1px solid #F1F5F9;
  transition: background 0.1s ease;
}
.gv-table tbody tr:hover { background: #F8FAFC; }
.gv-table td {
  padding: 0.6rem 0.9rem;
  vertical-align: top;
  color: var(--gray-800);
  line-height: 1.45;
}
.gv-table-desc {
  max-width: 320px;
  font-size: 0.8rem;
  color: #4B5563;
}
/* Closure prev/next nav inside the detail panel when multiple closures. */
.gv-closure-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.4rem 0;
  margin-bottom: 0.4rem;
  border-bottom: 1px solid var(--gv-border);
  font-family: var(--font-heading);
  font-size: 0.72rem;
  color: var(--gray-700);
}
.gv-closure-nav-btn {
  background: none;
  border: 1px solid var(--gv-border);
  border-radius: 999px;
  padding: 0.2rem 0.6rem;
  font-family: var(--font-heading);
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--navy);
  cursor: pointer;
  transition: all var(--transition);
}
.gv-closure-nav-btn:hover {
  background: var(--navy);
  color: var(--white);
  border-color: var(--navy);
}

.gv-table-dash { color: #CBD5E1; }
.gv-table-row-clickable { cursor: pointer; transition: background var(--transition); }
.gv-table-row-clickable:hover { background: #F0F7FF; }
.gv-table-row-expanded { background: #F0F7FF; }
/* Inline expansion row that slides in below the clicked permit row. */
.gv-table-expand td {
  padding: 0 !important;
  border-top: none !important;
}
.gv-table-expand-inner {
  padding: 0.75rem 1rem;
  background: #F8FAFC;
  border-top: 1px solid var(--gv-border);
  display: flex;
  align-items: flex-start;
  gap: 1rem;
}
.gv-table-expand-fields { flex: 1 1 auto; }
.gv-table-expand-field {
  font-size: 0.82rem;
  line-height: 1.5;
  margin-bottom: 0.3rem;
}
.gv-table-expand-field strong {
  display: inline;
  font-family: var(--font-heading);
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--gray-700);
  margin-right: 0.5rem;
}
.gv-table-map-btn {
  flex: 0 0 auto;
  align-self: center;
  white-space: nowrap;
  font-size: 0.78rem;
}

/* Pagination controls under the table */
.gv-table-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding: 0.85rem 1.25rem;
  border-top: 1px solid var(--gv-border);
  background: #FAFBFC;
  font-family: var(--font-heading);
}
.gv-table-pager[hidden] { display: none; }
.gv-table-pager-btn {
  background: var(--white);
  border: 1px solid var(--gv-border);
  color: var(--navy);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 0.82rem;
  padding: 0.45rem 0.95rem;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.15s ease;
}
.gv-table-pager-btn:hover:not(:disabled) {
  background: var(--navy);
  color: var(--white);
  border-color: var(--navy);
}
.gv-table-pager-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.gv-table-pager-label {
  font-size: 0.78rem;
  color: var(--gray-700);
  font-weight: 500;
}

@media (max-width: 1024px) {
  .gv-section-head { flex-direction: column; align-items: stretch; }
  .gv-map-explainer { text-align: left; }
}
@media (max-width: 768px) {
  .gv-section-head { padding: 0 0.75rem 0.6rem; }
  .gv-table-wrap { margin: 0 0.75rem; }
  .gv-table-desc { max-width: none; }
  .gv-table { font-size: 0.78rem; }
  .gv-table th, .gv-table td { padding: 0.5rem 0.6rem; }
}

/* ---------- Share button ---------- */
.gv-share-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--gv-border);
  border-radius: 999px;
  background: var(--white);
  color: var(--navy);
  font-family: var(--font-heading);
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
  transition: all var(--transition);
  white-space: nowrap;
  flex: 0 0 auto;
}
.gv-share-btn:hover {
  background: var(--navy);
  color: var(--white);
  border-color: var(--navy);
}
.gv-share-btn.is-copied {
  background: #059669;
  color: var(--white);
  border-color: #059669;
}

/* ---------- Closure alert badge ---------- */
.gv-closure-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.65rem;
  border: 1px solid #DC2626;
  border-radius: 999px;
  background: #DC2626;
  color: var(--white);
  font-family: var(--font-heading);
  font-size: 0.72rem;
  font-weight: 700;
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
  /* Cap the width + flex so one closure doesn't eat half the toolbar. */
  flex: 0 0 auto;
  max-width: 220px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gv-closure-badge:hover { background: #B91C1C; border-color: #B91C1C; color: var(--white); }
.gv-closure-badge[hidden] { display: none; }
/* When the user has deliberately hidden the closures layer the badge softens
   to a red-outline chip — still visible and clickable (as a recovery path
   that re-enables the layer) but no longer shouting. */
.gv-closure-badge.is-dim {
  background: transparent;
  color: #DC2626;
}

/* Zoning legend — shown beneath the zoning toggle to explain the color groups.
   Lightly boxed so the category swatches read as one grouped key rather than
   floating color squares. Hidden until the Zoning overlay is toggled on so
   the legend doesn't carry dead weight. */
.gv-zoning-legend { display: none; }
.gv-legend-section:has(input[data-overlay="zoning"]:checked) .gv-zoning-legend {
  display: block;
}
.gv-zoning-legend {
  margin: 0.3rem 0 0.15rem 1.2rem;
  padding: 0.3rem 0.45rem;
  border: 1px solid var(--gv-border);
  border-radius: 5px;
  background: rgba(248, 250, 252, 0.7);
}
.gv-zoning-legend-title {
  display: block;
  font-family: var(--font-heading);
  font-size: 0.6rem;
  font-weight: 700;
  color: var(--gray-700);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 0.2rem;
}
.gv-zoning-legend-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.1rem 0.5rem;
  font-size: 0.62rem;
  color: var(--gray-700);
}
.gv-zoning-legend-grid > span {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}
.gv-zoning-legend .gv-swatch { width: 10px; height: 10px; border-radius: 2px; }

/* When the table view is active, the map layout (sidebar + map) hides via
   the existing `hidden` attribute on .gv-map-layout. The story banner is
   also hidden in JS, so the table sits cleanly under the section header. */
.gv-map-section.gv-view-table .gv-map-layout { display: none; }
/* The "click any pin" copy only makes sense with the map visible. */
.gv-map-section.gv-view-table .gv-map-explainer { display: none; }

/* Charts default to 2x2 on desktop. On wider screens they breathe; on
   narrower ones they collapse to a single column. */
@media (max-width: 768px) {
  .gv-charts-grid { grid-template-columns: 1fr; }
  .gv-chart-card > .gv-chart-body { height: 260px; }
}

