:root {
  /* Colors. Text and lines are black at different strengths, so they read
     on the white panels and over the map alike. */
  --colorSurface: white;
  --colorInk: black;
  --colorText: rgba(0, 0, 0, 0.8);
  --colorTextSoft: rgba(0, 0, 0, 0.7);
  --colorTextMuted: rgba(0, 0, 0, 0.6);
  --colorTextFaint: rgba(0, 0, 0, 0.5);
  --colorBorderStrong: rgba(0, 0, 0, 0.35);
  --colorBorder: rgba(0, 0, 0, 0.1);
  --colorShadow: rgba(0, 0, 0, 0.2);
  --colorRule: #333;
  /* Error text, 7.3:1 contrast on white */
  --colorError: #b00020;
  /* The House and Senate lines' colors (see map.js), for their labels */
  --colorHouse: #e06aaa;
  --colorSenate: #f8f807;
  /* The logo's darker teal, deepened to 5:1 against white, so text in it and
     white text on it both pass */
  --colorBrand: #38768f;
  --colorBrandDark: #2e667c;
  /* The zone colors, for the key on the Home page. They match zone2color in
     map.js, which colors the map and its legend. */
  --colorZoneResidential: #bb22ca;
  --colorZoneMixed: #4a2b83;
  --colorZoneNonresidential: #aa75b6;
  --colorZoneNotSatisfying: #d0d0d0;

  --fontBody: 'Zodiak', serif;
  --fontHeading: 'Red Hat Display', sans-serif;

  /* Font sizes, smallest to largest. Base is the body text. */
  --fontSize3xs: 10px;
  --fontSize2xs: 12px;
  --fontSizeXs: 13px;
  --fontSizeSm: 14px;
  --fontSizeBase: 16px;
  --fontSizeLg: 20px;
  --fontSizeXl: 24px;
  --fontSize2xl: 32px;

  --spaceXs: 6px;
  --spaceSm: 0.5rem;
  --spaceMd: 1rem;
  --spaceLg: 1.5rem;
  --spaceXl: 2.5rem;

  /* Wider screens: the floating boxes' distance from the screen's edges, the
     sidebar's width, and the area panel's width */
  --edgeGap: 10px;
  --sidebarWidth: 380px;
  --areaPanelWidth: 340px;

  /* The navbar (see Tab bar): the top bar on wider screens, and on phones the
     bottom tab bar plus the home indicator's safe area under it */
  --topBarHeight: 3.5rem;
  --tabBarHeight: 3.75rem;
  --tabBarSpace: calc(var(--tabBarHeight) + env(safe-area-inset-bottom));
  /* Where the map starts: under the top bar, or at the very top on phones */
  --mapTop: var(--topBarHeight);

  /* Phone drawer (see Media queries): the bar that always shows, and the
     share of the screen above the tab bar that the drawer takes when open.
     During the tour it opens lower, which leaves room above it for the tour's
     popovers pinned at the top. map.js reads --drawerOpenShare to pan the map. */
  --drawerBarHeight: 48px;
  --drawerOpenShare: 0.7;
  --drawerTourShare: 0.45;
  --drawerOpenHeight: calc(var(--drawerOpenShare) * (100dvh - var(--tabBarSpace)));
  --drawerTourHeight: calc(var(--drawerTourShare) * (100dvh - var(--tabBarSpace)));
  /* Phone layout (see Media queries): the map fills the screen above the
     drawer's bar and the tab bar, and floating boxes keep this gap from the
     screen edge */
  --phoneMapHeight: calc(100dvh - var(--drawerBarHeight) - var(--tabBarSpace));
  --phoneGap: 8px;
  /* Leaflet's zoom buttons plus a gap, so boxes along the top stop short of them */
  --zoomButtonsClearance: 54px;
  /* Tallest a district's note gets in the area panel before it scrolls */
  --noteMaxHeight: 12em;
}

body {
  padding: 0;
  margin: 0;
  font-family: var(--fontBody);
  font-size: var(--fontSizeBase);
  letter-spacing: 0.02em;
}
/* html, body, #map {
  height: 100%;
  width: 100vw;
} */

h2 {
  font-family: var(--fontHeading);
  font-size: var(--fontSizeLg);
  letter-spacing: 0.03em;
}

/* The map fills the screen under the top bar. The ID beats the vh-100 class
   in the markup. */
#map {
  height: calc(100vh - var(--mapTop));
}

#sidebar {
  z-index: 999 !important;
  position: absolute;
  width: var(--sidebarWidth);
  max-height: calc(100vh - var(--mapTop) - 2 * var(--edgeGap));
  overflow-y: scroll;
  background-color: var(--colorSurface);
  top: calc(var(--mapTop) + var(--edgeGap));
  left: var(--edgeGap);
  padding: var(--spaceMd);
  border-radius: 2px;
  opacity: 0.95;
}

.leaflet-control-layers .driver-fix-stacking {
  z-index: 999 !important;
}

.square {
  height: 16px;
  width: 16px;
  display: inline-block;
  border-radius: 2px;
  vertical-align: middle;
}

.leaflet-interactive:hover {
  opacity: 0.8;
}

label {
  cursor: pointer;
}

label:hover {
  opacity: 0.8;
}

hr {
  border-top: 1px solid var(--colorRule);
  border-bottom: 0;
}

#activeAreaCalculator {
  position: absolute;
  top: calc(var(--mapTop) + var(--edgeGap));
  width: var(--areaPanelWidth);
  margin-left: calc(var(--areaPanelWidth) / -2);
  left: 50%;
  z-index: 999;
  /* Room on the right for the close button. The ID beats Tachyons' pa3. */
  padding-right: 40px;
  font-size: 0.95em;
}

/* The ✕ in the panel's top corner (see buildAreaCloseButton) */
.areaCloseButton {
  position: absolute;
  top: var(--spaceXs);
  right: var(--spaceXs);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--colorTextMuted);
  cursor: pointer;
}

/* Two classes, to beat the 24px in Google's .material-icons rule */
.areaCloseButton.material-icons {
  font-size: var(--fontSizeLg);
}

.areaCloseButton:focus-visible {
  outline: 2px solid var(--colorBrand);
  outline-offset: -2px;
}

/* Row of county stats under the area calculation */
.areaStats {
  display: flex;
  font-size: var(--fontSizeXs);
}

/* Two classes so this outranks the 24px in Google's .material-icons rule */
.areaStats .statIcon {
  font-size: var(--fontSizeBase);
}

/* The clicked district under the county stats (see buildDistrictDetails) */
.districtDetails {
  margin-top: 0.75em;
  padding-top: 0.75em;
  border-top: 1px solid var(--colorBorder);
  font-size: var(--fontSizeXs);
}

.districtName {
  margin: 0;
  font-weight: bold;
}

.districtFlags {
  margin: 0.25em 0 0;
  color: var(--colorTextMuted);
}

/* Keeps the notes' own line breaks, and scrolls when a note runs long */
.districtNote {
  margin: 0.25em 0 0;
  max-height: var(--noteMaxHeight);
  overflow-y: auto;
  white-space: pre-line;
}

/* Loading and error message at the top of the map */
.mapStatus {
  position: absolute;
  top: calc(var(--mapTop) + var(--edgeGap));
  left: 50%;
  transform: translateX(-50%);
  z-index: 999;
  margin: 0;
  padding: 8px 12px;
  background-color: var(--colorSurface);
  border-radius: 2px;
  box-shadow: 0 0 4px var(--colorShadow);
  font-size: 0.95em;
}

/* With nothing to say, the box disappears. The element stays on the page
   because screen readers watch it for changes. */
.mapStatus:empty {
  padding: 0;
  box-shadow: none;
}

/* Loading and error line under the Overlays heading */
.overlayStatus {
  margin: 0;
  font-size: var(--fontSizeSm);
  color: var(--colorTextSoft);
}

.statusError {
  color: var(--colorError);
}

.leaflet-control-layers-expanded {
  border: 1px solid var(--colorSurface);
  border-radius: 2px;
}

/* .clearButton's display: inline-flex would beat the hidden attribute (see
   updateResetButton) */
#resetFilters[hidden] {
  display: none;
}

/* The drawer's bar and the area card's toggle are for phones only (see Media
   queries) */
#drawerToggle,
.areaCardToggle {
  display: none;
}

.leaflet-tooltip {
  width: 230px;
  white-space: normal !important;
}

/* Tooltip title */
.t-t {
  margin: 0;
  padding: 0;
  color: var(--colorTextFaint);
  font-size: 1em;
}

.t-t:not(:first-child) {
  margin-top: 5px;
}

/* House and Senate district labels. They ignore the mouse (Leaflet tooltips
   do by default), so clicks still reach the zones underneath. The !important
   beats the zone tooltips' white-space rule above. */
.leaflet-tooltip.districtLabel {
  width: auto;
  white-space: nowrap !important;
  padding: 1px var(--spaceXs);
  border: 1px solid var(--colorBorderStrong);
  border-radius: 9px;
  box-shadow: none;
  color: var(--colorInk);
  font-size: var(--fontSize2xs);
  font-weight: bold;
  line-height: 1.4;
}

/* Filled with each overlay's line color: black text is 6.8:1 on the pink
   and 18:1 on the yellow */
.leaflet-tooltip.houseLabel {
  background-color: var(--colorHouse);
}

.leaflet-tooltip.senateLabel {
  background-color: var(--colorSenate);
}

/* Hidden while the label has no room on screen (see updateDistrictLabels).
   visibility, not display: Leaflet centers each label using its size, and a
   display: none label has no size, so it would drift off its spot. */
.leaflet-tooltip.districtLabelHidden {
  visibility: hidden;
}

#driver-popover-item {
  max-width: 450px !important;
}

#driver-popover-item * {
  font-family: var(--fontBody) !important;
  font-size: var(--fontSizeBase) !important;
  letter-spacing: 0.02em;
}

/* A teal ring around whatever the tour highlights, so the lit area reads as
   a deliberate highlight. Inset, so it stays inside the hole in the dimmed
   overlay. */
#driver-highlighted-element-stage {
  box-shadow: inset 0 0 0 3px var(--colorBrand);
}

.bb-dotted {
  border-bottom: 1px dotted var(--colorRule);
}

.sidebarLogo {
  width: auto;
  height: 45px;
}

/**************************************************************
Utilities
***************************************************************/

/* Hidden on screen, but still read by screen readers */
.visuallyHidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/**************************************************************
Map sidebar
***************************************************************/

.sidebarIntro {
  margin: var(--spaceSm) 0;
  font-size: var(--fontSizeBase);
}

.sidebarHelp {
  margin: var(--spaceSm) 0;
  font-size: var(--fontSizeSm);
}

#form {
  font-size: var(--fontSizeSm);
  line-height: 1.25;
}

/* The section headings, the Overlays legend, and the opacity label. The
   muted color passes AA, which the old 40% black didn't. */
.sidebarHeading {
  display: block;
  margin: var(--spaceMd) 0 var(--spaceXs);
  padding: 0;
  color: var(--colorTextMuted);
  font-family: var(--fontHeading);
  font-size: var(--fontSizeBase);
  font-weight: bold;
  letter-spacing: 0.03em;
}

/* The zone-type key */
.legendList {
  margin: 0;
  padding: 0;
  list-style: none;
}

.legendNote {
  color: var(--colorTextMuted);
  font-style: italic;
}

/* "Housing types" with the Clear button beside it */
.sectionHeader {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spaceSm);
  margin: var(--spaceMd) 0 var(--spaceXs);
}

.sectionHeader .sidebarHeading {
  margin: 0;
}

.clearButton {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px var(--spaceSm) 2px var(--spaceXs);
  border: 0;
  border-radius: 999px;
  background-color: var(--colorBorder);
  color: var(--colorText);
  font: inherit;
  cursor: pointer;
}

/* Two classes, to beat the 24px in Google's .material-icons rule */
.clearButton .material-icons {
  font-size: var(--fontSizeBase);
}

/* The housing types (built by buildFilterControls in map.js) */
.housingTypeList {
  margin: 0;
  padding: 0;
  list-style: none;
}

.housingType {
  padding: var(--spaceXs) 0;
  border-bottom: 1px solid var(--colorBorder);
}

/* A type's on/off checkbox. A type that's on is bold. */
.typeToggle {
  display: flex;
  align-items: center;
  gap: var(--spaceXs);
  font-size: var(--fontSizeBase);
}

.typeToggle:has(input:checked) {
  color: var(--colorText);
  font-weight: bold;
}

/* A type's options, indented under it */
.typeOptions {
  margin: var(--spaceXs) 0 var(--spaceXs) var(--spaceMd);
}

/* The radio buttons and checkboxes under a type, and the overlays */
.filterOption {
  display: flex;
  align-items: center;
  gap: var(--spaceXs);
  padding: 2px 0;
}

/* display: flex above would beat the hidden attribute (see
   hideNoEffectOptions in map.js) */
.filterOption[hidden] {
  display: none;
}

.typeToggle input,
.filterOption input {
  flex: none;
  width: 16px;
  height: 16px;
  margin: 0;
}

/* Fieldsets without the browser's border and padding */
.filterGroup,
.overlayGroup {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.filterGroup + .filterGroup {
  margin-top: var(--spaceSm);
}

.filterGroup legend {
  margin-bottom: 2px;
  padding: 0;
  color: var(--colorText);
  font-weight: bold;
}

.overlayGroup {
  margin-top: var(--spaceMd);
}

.overlayGroup > .sidebarHeading {
  margin-top: 0;
}

/* A sentence that explains a type or a group */
.filterHint {
  margin: 2px 0 0;
  color: var(--colorTextMuted);
  font-size: var(--fontSizeXs);
}

/* Under a type's name, lined up with its text */
.housingType > .filterHint {
  margin-left: calc(16px + var(--spaceXs));
}

.sidebarCredits {
  margin: var(--spaceSm) 0 0;
  color: var(--colorTextMuted);
  font-size: var(--fontSizeSm);
}

.sidebarCredits a {
  color: var(--colorText);
}

.typeToggle input:focus-visible,
.filterOption input:focus-visible,
.clearButton:focus-visible,
#opacity:focus-visible {
  outline: 2px solid var(--colorBrand);
  outline-offset: 2px;
}

/**************************************************************
Tab bar
***************************************************************/
/* Home · Map. It's the top bar on wider screens. On phones it moves to the
   bottom, within thumb reach (see Media queries). */
.tabBar {
  position: relative;
  z-index: 1100; /* Above Leaflet's controls (1000) and the phone drawer (1001) */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spaceMd);
  box-sizing: border-box;
  height: var(--topBarHeight);
  padding: 0 var(--spaceMd);
  border-bottom: 1px solid var(--colorBorder);
  background-color: var(--colorSurface);
}

.tabBarBrand,
.siteBrand {
  display: inline-flex;
  align-items: center;
  gap: var(--spaceSm);
  min-height: 44px;
  color: var(--colorText);
  font-family: var(--fontHeading);
  font-size: var(--fontSizeLg);
  font-weight: bold;
  letter-spacing: 0.03em;
  text-decoration: none;
}

.tabBarLogo,
.siteLogo {
  width: auto;
  height: 2.25rem;
}

.tabList {
  display: flex;
  gap: var(--spaceSm);
  height: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}

.tabLink {
  display: flex;
  align-items: center;
  gap: var(--spaceSm);
  box-sizing: border-box;
  height: 100%;
  padding: 0 var(--spaceMd);
  border-bottom: 3px solid transparent;
  color: var(--colorTextMuted);
  font-family: var(--fontHeading);
  font-size: var(--fontSizeBase);
  font-weight: bold;
  letter-spacing: 0.03em;
  text-decoration: none;
}

/* The current tab gets a bar as well as color, so it doesn't rely on color alone */
.tabLink[aria-current='page'] {
  border-bottom-color: var(--colorBrand);
  color: var(--colorBrand);
}

.tabLink:focus-visible,
.tabBarBrand:focus-visible,
.siteBrand:focus-visible {
  outline: 2px solid var(--colorBrand);
  outline-offset: -4px;
}

.tabIcon {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
}

/**************************************************************
Home
***************************************************************/
/* Phones only: the brand at the top of Home (see Media queries). Wider
   screens show it in the top bar. */
.siteHeader {
  display: none;
}

.homePage {
  max-width: 42rem;
  margin: 0 auto;
  padding: var(--spaceXl) var(--spaceMd) var(--spaceLg);
  color: var(--colorText);
  line-height: 1.6;
}

.homeTitle {
  margin: 0 0 var(--spaceMd);
  font-family: var(--fontHeading);
  font-size: var(--fontSize2xl);
  letter-spacing: 0.02em;
  line-height: 1.2;
}

.homeLead {
  margin: 0 0 var(--spaceLg);
  font-size: var(--fontSizeLg);
}

/* Open the map: white on the brand teal, 5:1 */
.buttonLink {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  padding: 0 var(--spaceLg);
  border-radius: 6px;
  background-color: var(--colorBrand);
  color: var(--colorSurface);
  font-family: var(--fontHeading);
  font-size: var(--fontSizeBase);
  font-weight: bold;
  letter-spacing: 0.03em;
  text-decoration: none;
}

.buttonLink:focus-visible {
  outline: 3px solid var(--colorBrand);
  outline-offset: 3px;
}

.homeSection {
  margin-top: var(--spaceXl);
}

.homeSection h2 {
  margin: 0 0 var(--spaceSm);
  font-size: var(--fontSizeXl);
}

.homePage a:not(.buttonLink),
.homeFooter a {
  color: var(--colorBrand);
}

/* The zone colors, as on the map's legend */
.zoneKey {
  margin: 0 0 var(--spaceMd);
  padding: 0;
  list-style: none;
}

.zoneKey li {
  display: flex;
  align-items: baseline;
  gap: var(--spaceSm);
  margin-bottom: var(--spaceXs);
}

.zoneSwatch {
  display: inline-block;
  flex: none;
  width: 1em;
  height: 1em;
  border-radius: 2px;
  vertical-align: -0.125em;
}

/* The gray swatch sits inside a sentence */
p .zoneSwatch {
  margin-right: 0.25em;
}

.zoneSwatchResidential {
  background-color: var(--colorZoneResidential);
}

.zoneSwatchMixed {
  background-color: var(--colorZoneMixed);
}

.zoneSwatchNonresidential {
  background-color: var(--colorZoneNonresidential);
}

.zoneSwatchNotSatisfying {
  background-color: var(--colorZoneNotSatisfying);
}

/* The four counties at a glance (see countyStats.js). On a narrow screen the
   table scrolls sideways inside this box, never the page. */
.tableScroll {
  overflow-x: auto;
}

.countyStatsNote {
  color: var(--colorTextMuted);
}

.countyTable {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fontSizeSm);
  line-height: 1.4;
}

.countyTable caption {
  caption-side: bottom;
  padding-top: var(--spaceSm);
  color: var(--colorTextMuted);
  text-align: left;
}

.countyTable th,
.countyTable td {
  padding: var(--spaceSm) var(--spaceXs);
  border-bottom: 1px solid var(--colorBorder);
  text-align: right;
}

.countyTable thead th {
  font-family: var(--fontHeading);
  letter-spacing: 0.02em;
  vertical-align: bottom;
}

/* County names read left to right, and numbers line up on the right */
.countyTable th:first-child {
  text-align: left;
}

.countyTable td {
  font-variant-numeric: tabular-nums;
}

/* "Try it" cards, each a link that opens the map already set up */
.tryList {
  display: grid;
  gap: var(--spaceMd);
  margin: var(--spaceMd) 0 0;
  padding: 0;
  list-style: none;
}

.tryCard {
  padding: var(--spaceMd);
  border: 1px solid var(--colorBorder);
  border-radius: 8px;
}

.tryCard h3 {
  margin: 0 0 var(--spaceXs);
  font-family: var(--fontHeading);
  font-size: var(--fontSizeBase);
  letter-spacing: 0.02em;
  line-height: 1.4;
}

.tryCard p {
  margin: 0 0 var(--spaceSm);
}

/* A full-size touch target, though it reads as a text link */
.tryLink {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  min-height: 44px;
  font-family: var(--fontHeading);
  font-weight: bold;
  letter-spacing: 0.03em;
}

/* How current the research is: each county's code, and the changes since */
.sourceList {
  display: grid;
  gap: var(--spaceMd);
  margin: var(--spaceMd) 0 0;
  padding: 0;
  list-style: none;
}

.sourceCard {
  padding: var(--spaceMd);
  border: 1px solid var(--colorBorder);
  border-radius: 8px;
}

.sourceCard h3 {
  margin: 0 0 var(--spaceXs);
  font-family: var(--fontHeading);
  font-size: var(--fontSizeBase);
  letter-spacing: 0.02em;
}

.sourceCard p {
  margin: 0 0 var(--spaceSm);
}

.changeList {
  margin: 0;
  padding: 0;
  list-style: none;
}

.changeList li + li {
  margin-top: var(--spaceSm);
}

/* The status reads as text, so it doesn't rely on its color */
.changeStatus {
  display: inline-block;
  margin-right: var(--spaceXs);
  padding: 0 var(--spaceXs);
  border: 1px solid var(--colorTextMuted);
  border-radius: 999px;
  color: var(--colorTextMuted);
  font-family: var(--fontHeading);
  font-size: var(--fontSizeSm);
  font-weight: bold;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.changeStatusOnMap {
  border-color: var(--colorBrand);
  color: var(--colorBrand);
}

.sourceNote {
  margin-top: var(--spaceMd);
  color: var(--colorTextMuted);
  font-size: var(--fontSizeSm);
}

.homeFooter {
  max-width: 42rem;
  margin: 0 auto;
  padding: var(--spaceLg) var(--spaceMd);
  border-top: 1px solid var(--colorBorder);
  color: var(--colorTextMuted);
  font-size: var(--fontSizeSm);
  line-height: 1.6;
}

.homeFooter p {
  margin: 0;
}

/**************************************************************
Media queries
***************************************************************/

/* Phones: the map fills the screen above a drawer that holds the sidebar,
   and the tab bar sits along the bottom. initMap() uses the same 600px
   breakpoint to start phones zoomed out. */
@media screen and (max-width: 600px) {
  /* No top bar on phones, so the map starts at the very top */
  :root {
    --mapTop: 0px;
  }

  /* The tab bar moves to the bottom. Its height includes its top border and
     the home indicator's safe area, so it's exactly --tabBarSpace. */
  .tabBar {
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    height: var(--tabBarSpace);
    padding: 0 0 env(safe-area-inset-bottom);
    border-top: 1px solid var(--colorBorder);
    border-bottom: 0;
  }

  .tabBarBrand {
    display: none;
  }

  .tabList {
    display: grid;
    grid-auto-columns: 1fr;
    grid-auto-flow: column;
    gap: 0;
    width: 100%;
  }

  .tabLink {
    flex-direction: column;
    justify-content: center;
    gap: var(--spaceXs);
    padding: 0;
    border-top: 3px solid transparent;
    border-bottom: 0;
    font-size: var(--fontSizeSm);
    line-height: 1;
  }

  .tabLink[aria-current='page'] {
    border-top-color: var(--colorBrand);
  }

  .tabIcon {
    width: 1.5rem;
    height: 1.5rem;
  }

  /* Home: the brand at the top, and room at the bottom for the tab bar */
  .siteHeader {
    display: flex;
    align-items: center;
    padding: calc(var(--spaceSm) + env(safe-area-inset-top)) var(--spaceMd) var(--spaceSm);
    border-bottom: 1px solid var(--colorBorder);
  }

  .homeBody {
    padding-bottom: var(--tabBarSpace);
  }

  .homePage {
    padding-top: var(--spaceLg);
  }

  /* Ending above the drawer's bar keeps the Map/Satellite switch and the
     credits clear of it */
  #map {
    height: var(--phoneMapHeight);
  }

  /* The sidebar becomes a drawer just above the tab bar. Closed, only its bar
     shows (see setDrawerOpen). It grows instead of sliding, because Driver.js
     turns off transforms on the parents of the tour's highlighted elements.
     Open, it covers part of the map, so it goes above Leaflet's controls
     (z-index 1000). The !important beats the one in the #sidebar rule
     above. */
  #sidebar {
    z-index: 1001 !important;
    top: auto;
    bottom: var(--tabBarSpace);
    left: 0;
    display: flex;
    flex-direction: column;
    width: 100%;
    height: var(--drawerBarHeight);
    max-height: none;
    padding: 0;
    /* clip, unlike hidden, can't be scrolled, so a rotation or a #link can't
       shift the bar out of place. hidden is the fallback for older Safari. */
    overflow: hidden;
    overflow: clip;
    border-radius: 0;
    opacity: 1;
    box-shadow: 0 -2px 6px var(--colorShadow);
    transition: height 0.2s ease-out;
  }

  /* Open, it leaves the top of the map showing, so the filters' effect stays
     in view */
  #sidebar.drawerOpen {
    height: var(--drawerOpenHeight);
  }

  #sidebar.drawerOpen.drawerTour {
    height: var(--drawerTourHeight);
  }

  /* For changes that happen at once, like the tour's */
  #sidebar.drawerNoTransition {
    transition: none;
  }

  /* Its side padding matches the drawer's contents, so the label lines up
     with them */
  #drawerToggle {
    display: flex;
    flex: none;
    align-items: center;
    gap: var(--spaceXs);
    width: 100%;
    height: var(--drawerBarHeight);
    padding: 0 var(--spaceMd);
    border: 0;
    background-color: var(--colorSurface);
    color: var(--colorText);
    font-family: var(--fontHeading);
    font-size: var(--fontSizeBase);
    font-weight: bold;
    letter-spacing: 0.03em;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
  }

  #sidebar.drawerOpen #drawerToggle {
    border-bottom: 1px solid var(--colorBorder);
  }

  /* On the narrowest phones the label gives way to the count */
  .drawerLabel {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* How many housing filters are on, at the bar's right end */
  #drawerFilterCount {
    flex: none;
    margin-left: auto;
    color: var(--colorTextMuted);
    font-size: var(--fontSizeSm);
  }

  /* Focus rings go inside the buttons, because the drawer and the area card
     clip anything outside their edges */
  #drawerToggle:focus-visible,
  .areaCardToggle:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: -4px;
  }

  /* The drawer's contents scroll on their own, under the bar */
  #HiZoningAtlas {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: var(--spaceMd);
  }

  /* Full-size touch targets for the filters, the overlays, and Clear */
  .typeToggle,
  .filterOption,
  .clearButton {
    min-height: 44px;
  }

  /* Across the top of the map, clear of the zoom buttons */
  #activeAreaCalculator {
    left: var(--phoneGap);
    right: var(--zoomButtonsClearance);
    width: auto;
    margin-left: 0;
    padding-right: 48px;
  }

  /* A full-size touch target in the card's corner, beside the header */
  .areaCloseButton {
    top: 2px;
    right: 2px;
    width: 44px;
    height: 44px;
  }

  /* The area card keeps to the top of the map, so the middle stays free for
     tapping. It scrolls as one box, rather than a note box scrolling inside
     a scrolling panel. */
  #activeAreaCalculator {
    max-height: calc(var(--phoneMapHeight) * 0.4);
    overflow-y: auto;
  }

  /* With the drawer open, the card fits in the strip of map above it */
  body:has(#sidebar.drawerOpen) #activeAreaCalculator {
    max-height: calc(100dvh - var(--tabBarSpace) - var(--drawerOpenHeight) - var(--edgeGap) - var(--phoneGap));
  }

  :root {
    --noteMaxHeight: none;
  }

  /* Phones have no tooltip, so the card leads with the county's percentage
     and the tapped district, above the county stats. :not(.dn) keeps
     Tachyons' dn able to hide the card. */
  #activeAreaCalculator:not(.dn) {
    display: flex;
    flex-direction: column;
  }

  /* The card's header: the percentage, and the button that expands the card
     (see buildAreaCardToggle) */
  .areaCardToggle {
    display: flex;
    order: -2;
    align-items: center;
    justify-content: space-between;
    gap: var(--spaceXs);
    /* Reaches into the card's 1rem padding (Tachyons' pa3), so the whole top
       of the card is a 48px touch target while the text stays put */
    width: calc(100% + 2 * var(--spaceMd));
    margin: calc(-1 * var(--spaceMd)) calc(-1 * var(--spaceMd)) calc(-1 * var(--spaceSm));
    padding: var(--spaceMd) var(--spaceMd) var(--spaceSm);
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    font-weight: bold;
    letter-spacing: inherit;
    text-align: left;
    cursor: pointer;
  }

  .districtDetails {
    order: -1;
    margin: 0.5em 0 0;
    padding: 0 0 0.75em;
    border-top: 0;
    border-bottom: 1px solid var(--colorBorder);
  }

  #activeAreaCalculator .areaSummary {
    margin-top: 0.75em;
  }

  /* Collapsed, the card shows just the percentage, the district's name, and
     the first line of its note */
  #activeAreaCalculator:not(.areaExpanded) .areaSummary,
  #activeAreaCalculator:not(.areaExpanded) .areaStats,
  #activeAreaCalculator:not(.areaExpanded) .districtFlags {
    display: none;
  }

  #activeAreaCalculator:not(.areaExpanded) .districtDetails {
    padding-bottom: 0;
    border-bottom: 0;
  }

  #activeAreaCalculator:not(.areaExpanded) .districtNote {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  /* Two classes to match Leaflet's own rule, which this file loads after */
  .leaflet-container .leaflet-control-attribution {
    font-size: var(--fontSize3xs);
  }

  /* There's no room beside the sidebar for the tour's popovers, so each one
     sits across the top of the screen and scrolls when it's long. The
     !important beats the position Driver.js sets inline. */
  #driver-popover-item {
    top: var(--phoneGap) !important;
    right: var(--phoneGap) !important;
    bottom: auto !important;
    left: var(--phoneGap) !important;
    min-width: 0 !important;
    max-width: none !important;
    max-height: calc(100dvh - 2 * var(--phoneGap));
    overflow-y: auto;
  }

  /* On the steps inside the drawer, a popover keeps to the space above it,
     so it never covers what the tour points at. Long text scrolls, with the
     buttons pinned. */
  body:has(#sidebar.drawerTour) #driver-popover-item {
    max-height: calc(100dvh - var(--tabBarSpace) - var(--drawerTourHeight) - 2 * var(--phoneGap));
  }

  /* When a popover scrolls, its buttons stay pinned at its bottom. The
     footer takes over the popover's 15px bottom padding, so no text shows
     below it (driver.min.css loads after this file, hence the !important).
     flow-root contains Driver.js's floated buttons. */
  #driver-popover-item {
    padding-bottom: 0 !important;
  }

  #driver-popover-item .driver-popover-footer {
    position: sticky;
    bottom: 0;
    display: flow-root;
    padding: var(--spaceSm) 0 15px;
    background-color: var(--colorSurface);
  }

  /* A tour step taller than the drawer is cut to the drawer's height, so its
     highlight ends at the drawer's edge (see showTourStep) */
  .tourStepClamp {
    max-height: calc(var(--drawerTourHeight) - var(--drawerBarHeight));
    overflow: hidden;
  }

  /* During the tour the highlight hugs each step, so the sidebar's sections
     and the map's Map/Satellite switch get room on their sides for its ring,
     which would otherwise cover the letters at their edges. The negative
     margin keeps their content where it is. (map.js sets .tourRunning before
     Driver.js measures a step, and removes it when the tour ends.) */
  .tourRunning :is(#form > *, .leaflet-control-layers-list) {
    margin-inline: calc(-1 * var(--spaceXs));
    padding-inline: var(--spaceXs);
  }

  /* The popover's arrow would point at the wrong place. driver.min.css loads
     after this file, hence the !important */
  #driver-popover-item .driver-popover-tip {
    display: none !important;
  }
}

/* Tablets and phones held sideways: below 1140px wide, the centered area
   panel would slide under the sidebar, so it sits beside it instead: past
   the sidebar's offset and width, plus a gap the size of that offset. */
@media screen and (min-width: 601px) and (max-width: 1139px) {
  #activeAreaCalculator {
    left: calc(2 * var(--edgeGap) + var(--sidebarWidth));
    right: var(--zoomButtonsClearance);
    width: auto;
    margin-left: 0;
  }
}

/* Hover effects only with a mouse, so they don't stay stuck after a tap */
@media (hover: hover) {
  .tabLink:hover {
    color: var(--colorText);
  }

  .tabLink[aria-current='page']:hover {
    color: var(--colorBrand);
  }

  .buttonLink:hover {
    background-color: var(--colorBrandDark);
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
