:root {
  --bg-dark: #0d1e17; /* Dark earthy green */
  --bg-card: rgba(18, 42, 33, 0.7);
  --text-light: #f4f7f5;
  --text-muted: #8d9a90;
  --accent-blue: #23587b; /* Earthy dark blue */
  --accent-hover: #357ca8;
  --glass-border: rgba(255, 255, 255, 0.08);
  --bg-invert: #ffffff;
  --text-invert: #16241c;
  --font-main: 'Inter', sans-serif;
  --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

body.light-mode {
  --bg-dark: #f2efe9; /* Warm earthy sand backdrop */
  --bg-card: rgba(228, 225, 216, 0.85); /* Slightly darker sand for cards */
  --text-light: #16241c; /* Dark green/grey text */
  --text-muted: #4e6356;
  --accent-blue: #1c523e; /* Earthy natural green to replace the blue */
  --accent-hover: #123729;
  --glass-border: rgba(0, 0, 0, 0.1);
  --bg-invert: #123729; /* Dark earthy green/navy for light mode boxes */
  --text-invert: #ffffff;
}

/* Solid dropdown for the light theme too — see the dark-theme rule
   for rationale. */
body.light-mode .dropdown-menu,
body.light-mode .dropdown-menu-nested {
  background: #e4e1d8;
}

/* Light Mode Overrides for Stats */
body.light-mode .hero-stats {
  background: var(--bg-invert);
}
body.light-mode .stat-item h2, body.light-mode .stat-item p {
  color: var(--text-invert);
}
body.light-mode .stat-item p {
  opacity: 0.9;
}

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

body {
  font-family: var(--font-main);
  background-color: var(--bg-dark);
  color: var(--text-light);
  line-height: 1.6;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  /* Scattered animal-track watermark — 2 paw prints + 2 cloven hoof
     prints per 700 × 700 tile, rotated at different angles for variety.
     Hooves are two tilted teardrop ovals (leaning toward each other at
     the top — the real cloven shape). The tile repeats in both axes so
     prints sprinkle across the viewport. Slightly lighter green than
     the page bg so they read as a subtle wildlife watermark. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='700' height='700' viewBox='0 0 700 700'><g fill='%23254d3a'><g transform='translate(120 150) rotate(20)'><ellipse cx='0' cy='8' rx='10' ry='8'/><ellipse cx='-10' cy='-3' rx='4' ry='5'/><ellipse cx='-4' cy='-9' rx='4' ry='5'/><ellipse cx='4' cy='-9' rx='4' ry='5'/><ellipse cx='10' cy='-3' rx='4' ry='5'/></g><g transform='translate(560 540) rotate(-30)'><ellipse cx='0' cy='8' rx='10' ry='8'/><ellipse cx='-10' cy='-3' rx='4' ry='5'/><ellipse cx='-4' cy='-9' rx='4' ry='5'/><ellipse cx='4' cy='-9' rx='4' ry='5'/><ellipse cx='10' cy='-3' rx='4' ry='5'/></g><g transform='translate(480 180) rotate(-15)'><path d='M0,-13 Q5,-11 5,-2 Q5,8 0,8 Q-5,8 -5,-2 Q-5,-11 0,-13 Z' transform='translate(-5 0) rotate(17)'/><path d='M0,-13 Q5,-11 5,-2 Q5,8 0,8 Q-5,8 -5,-2 Q-5,-11 0,-13 Z' transform='translate(5 0) rotate(-17)'/><ellipse cx='-5' cy='15' rx='2.5' ry='2'/><ellipse cx='5' cy='15' rx='2.5' ry='2'/></g><g transform='translate(200 520) rotate(35)'><path d='M0,-13 Q5,-11 5,-2 Q5,8 0,8 Q-5,8 -5,-2 Q-5,-11 0,-13 Z' transform='translate(-5 0) rotate(17)'/><path d='M0,-13 Q5,-11 5,-2 Q5,8 0,8 Q-5,8 -5,-2 Q-5,-11 0,-13 Z' transform='translate(5 0) rotate(-17)'/><ellipse cx='-5' cy='15' rx='2.5' ry='2'/><ellipse cx='5' cy='15' rx='2.5' ry='2'/></g></g></svg>");
  background-repeat: repeat;
  background-attachment: fixed;
}

/* Mobile drops the paw/hoof watermark entirely. On mobile the prints
   render at a different scale and end up sitting awkwardly next to
   cards — cleaner to just leave the page background plain on phones. */
@media (max-width: 768px) {
  body,
  body.light-mode {
    background-image: none;
  }
}

/* Light mode uses the same paw/hoof pattern in a muted tan, with a
   lower opacity so it reads as a quiet watermark on the sandy
   background. */
body.light-mode {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='700' height='700' viewBox='0 0 700 700'><g fill='%23a07a4f' opacity='0.4'><g transform='translate(120 150) rotate(20)'><ellipse cx='0' cy='8' rx='10' ry='8'/><ellipse cx='-10' cy='-3' rx='4' ry='5'/><ellipse cx='-4' cy='-9' rx='4' ry='5'/><ellipse cx='4' cy='-9' rx='4' ry='5'/><ellipse cx='10' cy='-3' rx='4' ry='5'/></g><g transform='translate(560 540) rotate(-30)'><ellipse cx='0' cy='8' rx='10' ry='8'/><ellipse cx='-10' cy='-3' rx='4' ry='5'/><ellipse cx='-4' cy='-9' rx='4' ry='5'/><ellipse cx='4' cy='-9' rx='4' ry='5'/><ellipse cx='10' cy='-3' rx='4' ry='5'/></g><g transform='translate(480 180) rotate(-15)'><path d='M0,-13 Q5,-11 5,-2 Q5,8 0,8 Q-5,8 -5,-2 Q-5,-11 0,-13 Z' transform='translate(-5 0) rotate(17)'/><path d='M0,-13 Q5,-11 5,-2 Q5,8 0,8 Q-5,8 -5,-2 Q-5,-11 0,-13 Z' transform='translate(5 0) rotate(-17)'/><ellipse cx='-5' cy='15' rx='2.5' ry='2'/><ellipse cx='5' cy='15' rx='2.5' ry='2'/></g><g transform='translate(200 520) rotate(35)'><path d='M0,-13 Q5,-11 5,-2 Q5,8 0,8 Q-5,8 -5,-2 Q-5,-11 0,-13 Z' transform='translate(-5 0) rotate(17)'/><path d='M0,-13 Q5,-11 5,-2 Q5,8 0,8 Q-5,8 -5,-2 Q-5,-11 0,-13 Z' transform='translate(5 0) rotate(-17)'/><ellipse cx='-5' cy='15' rx='2.5' ry='2'/><ellipse cx='5' cy='15' rx='2.5' ry='2'/></g></g></svg>");
}

/* Header & Navigation
   Desktop uses a 3-column grid (1fr | auto | 1fr) so the nav lands in the
   middle `auto` column, naturally centered between two equal-sized
   buffers. The logo sits in the left buffer, the right buffer stays
   empty (the JS-moved Admin button rides inside nav, so the "right side"
   is now just whitespace). Mobile (@media block below) reverts to flex
   with space-between so the hamburger anchors at the right edge while
   nav is taken out of flow as a fixed drawer. */
header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--bg-card);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--glass-border);
  padding: 1rem 5%;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
}

.logo {
  font-size: 1.5rem;
  font-weight: 800;
  color: var(--text-light);
  text-decoration: none;
  letter-spacing: 1px;
}

.logo span {
  color: var(--accent-blue);
}

nav {
  display: flex;
  gap: 2rem;
  align-items: center;
}

.nav-item {
  position: relative;
}

.nav-link {
  color: var(--text-light);
  text-decoration: none;
  font-weight: 500;
  padding: 0.5rem 1rem;
  border-radius: 8px;
  transition: var(--transition);
}

.nav-link:hover, .nav-link.active {
  background: rgba(59, 130, 246, 0.15);
  color: var(--accent-hover);
}

/* Dropdown */
.dropdown-menu {
  position: absolute;
  top: 100%;
  left: 0;
  /* Solid background — the glass-look --bg-card alpha let hero/stat card
     content bleed through the dropdown. Fully opaque for readability. */
  background: #122a21;
  border: 1px solid var(--glass-border);
  border-radius: 12px;
  min-width: 200px;
  padding: 0.5rem;
  opacity: 0;
  visibility: hidden;
  /* IMPORTANT: do NOT set `transform` here. A non-none transform creates a
     new containing block for descendant `position: fixed` elements, which
     means the nested submenus would be positioned relative to (and clipped
     by) this dropdown rather than the viewport — defeating the whole reason
     they're position: fixed. Same applies to `filter`, `backdrop-filter`,
     `perspective`, etc. */
  transition: opacity 0.25s, visibility 0.25s;
  box-shadow: 0 10px 25px rgba(0,0,0,0.5);
  z-index: 100;
  /* Cap height + allow vertical scroll when the menu has more items than
     fit on screen. Submenus escape the resulting clip via position: fixed
     (see .dropdown-menu-nested rules below). */
  max-height: 80vh;
  overflow-y: auto;
}

/* Dropdown Custom Scrollbar — visible so users can see when a menu is scrollable. */
.dropdown-menu::-webkit-scrollbar,
.dropdown-menu-nested::-webkit-scrollbar {
  width: 8px;
}
.dropdown-menu::-webkit-scrollbar-track,
.dropdown-menu-nested::-webkit-scrollbar-track {
  background: rgba(0, 0, 0, 0.25);
  border-radius: 10px;
}
.dropdown-menu::-webkit-scrollbar-thumb,
.dropdown-menu-nested::-webkit-scrollbar-thumb {
  background-color: rgba(255, 255, 255, 0.4);
  border-radius: 10px;
}
.dropdown-menu::-webkit-scrollbar-thumb:hover,
.dropdown-menu-nested::-webkit-scrollbar-thumb:hover {
  background-color: var(--accent-blue);
}
/* Firefox */
.dropdown-menu, .dropdown-menu-nested {
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.4) rgba(0, 0, 0, 0.25);
}

.nav-item:hover .dropdown-menu {
  opacity: 1;
  visibility: visible;
}

.drag-over-top {
  border-top: 2px solid #ffffff !important;
  border-top-left-radius: 0 !important;
  border-top-right-radius: 0 !important;
}

.dropdown-link {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.75rem 1rem;
  color: var(--text-light);
  text-decoration: none;
  border-radius: 6px;
  transition: var(--transition);
  cursor: pointer;
}

.dropdown-link:hover {
  background: var(--accent-blue);
  color: white;
}

/* Nested Submenus */
.dropdown-submenu {
  position: relative;
}

.dropdown-menu-nested {
  /* Fixed positioning so the submenu escapes the parent's overflow clip
     when the parent is scrollable. Coordinates AND max-height are written
     by installSubmenuPositioning() in app.js on each mouseenter, based on
     the parent item's bounding rect plus available viewport space. */
  position: fixed;
  /* Match the parent dropdown's solid background. */
  background: #122a21;
  border: 1px solid var(--glass-border);
  border-radius: 12px;
  min-width: 180px;
  padding: 0.5rem;
  opacity: 0;
  visibility: hidden;
  /* No `transform` for the same containing-block reason explained on
     .dropdown-menu — a transformed level-1 submenu would clip its
     own level-2 submenu (Zoos / Wild → Region → Country → State). */
  transition: opacity 0.25s, visibility 0.25s;
  box-shadow: 0 10px 25px rgba(0,0,0,0.5);
  margin-left: 0.25rem;
  overflow-y: auto;
  /* Above the parent dropdown so it isn't covered by the scrollable
     parent's content. */
  z-index: 110;
}

/* Direct-child combinator (>) is intentional. With a plain descendant
   selector, hovering a deeply-nested wrapper (e.g. Italy inside Europe)
   keeps EVERY .dropdown-menu-nested under Europe visible — including the
   state submenus of every sibling country (Spain, Croatia, …). The result
   is that an Italian state flyout opened by an earlier hover stays stuck
   on screen when the user mouses over to Spain. Limiting the match to the
   immediate child means each .dropdown-submenu only shows its own one
   level, so siblings hide as soon as the user moves to a different one. */
.dropdown-submenu:hover > .dropdown-menu-nested {
  opacity: 1;
  visibility: visible;
}

/* Admin Button */
.admin-btn {
  background: transparent;
  border: 1px solid var(--accent-blue);
  color: var(--accent-blue);
  padding: 0.5rem 1.25rem;
  border-radius: 20px;
  font-size: 0.9rem;
  text-decoration: none;
  transition: var(--transition);
  /* Grid items default to justify-self: stretch, which would otherwise
     blow the pill out to fill its entire 1fr column on desktop. Pin to
     the right end of the column instead so the pill stays compact. */
  justify-self: end;
}
/* Same fix for the logo — without it, the logo's anchor element stretches
   across the left 1fr column, which doesn't cause a visible bug (text
   stays at the start) but is sloppy. Stop it from claiming clickable
   surface area outside the logo text. */
.logo { justify-self: start; }

.admin-btn:hover {
  background: var(--accent-blue);
  color: white;
}

/* Stats Section */
.hero-stats {
  max-width: 800px;
  margin: 4rem auto;
  background: white;
  border-radius: 24px;
  padding: 3rem;
  text-align: center;
  box-shadow: 0 20px 40px rgba(0,0,0,0.3);
  transform: translateY(0);
  transition: var(--transition);
  animation: fadeInDown 0.8s ease-out forwards;
}

.hero-stats:hover {
  transform: translateY(-5px);
  box-shadow: 0 25px 50px rgba(59, 130, 246, 0.2);
}

.stats-container {
  display: flex;
  justify-content: space-around;
  flex-wrap: wrap;
  gap: 2rem;
}

.stat-item h2 {
  font-size: 4rem;
  font-weight: 800;
  color: var(--accent-blue);
  line-height: 1;
  margin-bottom: 0.5rem;
}

.stat-item p {
  color: #475569;
  font-size: 1.2rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 2px;
}

/* Main Content Area */
main {
  flex: 1;
  padding: 2rem 5%;
  max-width: 1400px;
  margin: 0 auto;
  width: 100%;
}

.section-title {
  font-size: 2.5rem;
  font-weight: 700;
  margin-bottom: 1rem;
  color: var(--text-light);
  text-align: center;
}

#class-title {
  font-size: clamp(1.4rem, 4.5vw, 2.5rem);
  line-height: 1.3;
  margin: 0 auto 1.5rem auto;
  word-wrap: break-word;
}

.section-subtitle {
  text-align: center;
  color: var(--text-muted);
  font-size: 1.1rem;
  margin-bottom: 3rem;
  max-width: 600px;
  margin-left: auto;
  margin-right: auto;
}

.grid-container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 2rem;
  padding: 1rem 0;
  align-items: start;
}

/* Masonry / mosaic layout for Homepage Favorites.
   CSS `columns` is the cleanest way to get a Pinterest-style tight pack:
   browser auto-decides how many columns fit at the current width (column-width
   is the minimum, columns are added/removed as the viewport changes).
   Result on typical widths:
     ~1500px desktop → 4 columns
     ~1200px desktop → 3 columns
     ~ 800px tablet  → 2 columns
     ~ 400px phone   → 1 column
   `break-inside: avoid` keeps each card whole instead of splitting an image
   across a column break. Captions are intentionally suppressed — the user
   wants a clean image-only grid, click navigates to the species page. */
.collage-grid {
  columns: 350px;
  column-gap: 6px;
  padding: 1.5rem 0.5rem;
  max-width: 1600px;
  margin: 0 auto;
}

.collage-card {
  display: block;
  width: 100%;
  margin: 0 0 6px 0;        /* vertical gap between stacked cards in a column */
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 6px;
  box-shadow: none;
  cursor: pointer;
  break-inside: avoid;       /* prevent the card from splitting across columns */
  overflow: hidden;
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.collage-card img {
  display: block;
  width: 100%;
  height: auto;
  max-height: none;
  object-fit: cover;
  border-radius: 6px;
}

/* Caption isn't rendered (JS omits it), but defensive in case any other
   caller still emits .collage-info — keeps the grid clean. */
.collage-info { display: none; }

.collage-card:hover {
  opacity: 0.88;
  transform: scale(0.99);    /* tiny shrink so the cursor still feels active */
}

/* Big Category Cards */
.category-card {
  position: relative;
  border-radius: 20px;
  overflow: hidden;
  aspect-ratio: 4/3;
  cursor: pointer;
  box-shadow: 0 10px 20px rgba(0,0,0,0.2);
  transition: var(--transition);
  transform-origin: center;
}

.category-card:hover {
  transform: scale(1.03);
  box-shadow: 0 20px 30px rgba(0,0,0,0.4);
}

.category-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.7s ease;
}

.category-card:hover img {
  transform: scale(1.1);
}

.card-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(15, 23, 42, 0.9) 0%, rgba(15, 23, 42, 0) 60%);
  /* Column layout pins both title and subtitle to the bottom of the card,
     stacked vertically. Previously this was a flex ROW which only worked
     while titles fit on one line — long localized names (e.g. Russian
     "Восточноамериканский крот") pushed the italic subtitle off the
     right edge where overflow:hidden on .category-card clipped it. The
     column layout always lets both lines breathe. */
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-start;
  padding: 2rem;
  gap: 0.25rem;
}

.card-overlay h3 {
  /* Title size chosen so the longest realistic localized species name
     (e.g. Russian "Восточноамериканский крот") still wraps at the
     space between words on a typical desktop card. Was 1.8rem with
     break-word, which produced ugly cuts like
     "Восточноамериканск / ий крот"; was then 1.2rem which fixed the
     cut but felt too small. 1.55rem is the comfortable middle. */
  font-size: 1.55rem;
  font-weight: 700;
  color: white;
  margin: 0;
  text-shadow: 0 2px 10px rgba(0,0,0,0.5);
  line-height: 1.2;
  /* Only wrap at word boundaries (spaces, hyphens). An extremely long
     single word will overflow the card edge and be clipped by the
     parent's overflow:hidden — visually preferable to a mid-word split
     per admin preference. */
  word-break: normal;
  overflow-wrap: normal;
  hyphens: none;
}

/* Zoo Header Area */
.zoo-header {
  margin-top: 4rem;
  border-bottom: 1px solid var(--glass-border);
  padding-bottom: 1rem;
  margin-bottom: 2rem;
}

.zoo-header h2 {
  font-size: 2rem;
  color: var(--accent-blue);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* Photo Cards */
.photo-card {
  border-radius: 12px;
  overflow: hidden;
  background: var(--bg-card);
  border: 1px solid var(--glass-border);
  transition: var(--transition);
}

.photo-card:hover {
  transform: translateY(-5px);
  border-color: var(--accent-blue);
}

.photo-card img {
  width: 100%;
  height: auto;
  max-height: 85vh;
  object-fit: contain;
  display: block;
  background: rgba(0,0,0,0.3);
  cursor: zoom-in;
}

.photo-info {
  padding: 1rem;
}

.photo-info h4 {
  margin-bottom: 0.25rem;
  font-size: 1.1rem;
}

.photo-info p {
  color: var(--text-muted);
  font-size: 0.9rem;
}

/* Admin Form */
.admin-container {
  max-width: 800px;
  margin: 0 auto;
  background: var(--bg-card);
  border: 1px solid var(--glass-border);
  border-radius: 20px;
  padding: 3rem;
  backdrop-filter: blur(10px);
}

.form-group {
  margin-bottom: 1.5rem;
}

.form-group label {
  display: block;
  margin-bottom: 0.5rem;
  font-weight: 500;
  color: var(--text-muted);
}

.form-control {
  width: 100%;
  background: rgba(15, 23, 42, 0.5);
  border: 1px solid var(--glass-border);
  color: white;
  padding: 0.75rem 1rem;
  border-radius: 8px;
  font-size: 1rem;
  font-family: var(--font-main);
  transition: var(--transition);
}

.form-control:focus {
  outline: none;
  border-color: var(--accent-blue);
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.25);
}

.upload-area {
  border: 2px dashed var(--glass-border);
  border-radius: 12px;
  padding: 3rem;
  text-align: center;
  cursor: pointer;
  transition: var(--transition);
  margin-bottom: 1.5rem;
}

.upload-area:hover, .upload-area.dragover {
  border-color: var(--accent-blue);
  background: rgba(59, 130, 246, 0.05);
}

.upload-area i {
  font-size: 3rem;
  color: var(--accent-blue);
  margin-bottom: 1rem;
}

.btn-primary {
  background: var(--accent-blue);
  color: white;
  border: none;
  padding: 1rem 2rem;
  font-size: 1.1rem;
  font-weight: 600;
  border-radius: 8px;
  cursor: pointer;
  width: 100%;
  transition: var(--transition);
}

.btn-primary:hover {
  background: var(--accent-hover);
  transform: translateY(-2px);
  box-shadow: 0 10px 20px rgba(59, 130, 246, 0.3);
}

.btn-invert {
  background: var(--bg-invert) !important;
  color: var(--text-invert) !important;
  box-shadow: 0 10px 25px rgba(0,0,0,0.2);
  border: none !important;
}

.btn-invert span, .btn-invert strong {
  color: var(--text-invert) !important;
}

.btn-invert:hover {
  transform: translateY(-5px);
  box-shadow: 0 15px 35px rgba(0,0,0,0.3);
}

/* Breadcrumbs for Zoos */
.breadcrumbs {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin-bottom: 2rem;
  color: var(--text-muted);
}

.breadcrumb-item {
  cursor: pointer;
  transition: var(--transition);
}

.breadcrumb-item:hover {
  color: var(--accent-blue);
}

.breadcrumb-separator {
  color: #475569;
}

.breadcrumb-item.current {
    cursor: default;
    color: var(--text-light);
    font-weight: 600;
}

.breadcrumb-item.current:hover {
    color: var(--text-light);
}
/* Animations */
@keyframes fadeInDown {
  from {
    opacity: 0;
    transform: translateY(-20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.animate-fade-in {
  animation: fadeInDown 0.6s ease-out forwards;
}

/* Map specific styles */
#map-container {
  height: 600px;
  width: 100%;
  border-radius: 20px;
  overflow: hidden;
  border: 1px solid var(--glass-border);
}

/* Camera Shutter Theme Transition */
.shutter-top, .shutter-bottom {
  position: fixed;
  left: 0;
  width: 100vw;
  height: 0;
  background-color: #000;
  z-index: 9999;
  transition: height 0.4s cubic-bezier(0.8, 0, 0.2, 1);
  pointer-events: none;
}

.shutter-top {
  top: 0;
  border-bottom: 2px solid var(--accent-blue);
}

.shutter-bottom {
  bottom: 0;
  border-top: 2px solid var(--accent-blue);
}

.shutter-top.animating, .shutter-bottom.animating {
  height: 50vh;
}

/* Utilities */
.hidden {
  display: none !important;
}

/* Lightbox Styles */
.lightbox {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0, 0, 0, 0.92);
  z-index: 10000;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
  backdrop-filter: blur(10px);
}

.lightbox.active {
  opacity: 1;
  pointer-events: auto;
}

.lightbox-content {
  position: relative;
  max-width: 90vw;
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.lightbox img {
  max-width: 100%;
  /* 78vh leaves ~7 vh below the image for the single-line caption so
     it doesn't get clipped on laptops with shorter viewports. The
     caption code in app.js puts species name · Latin · zoo · year ·
     X/N on a single row, so this much space is plenty. */
  max-height: 78vh;
  object-fit: contain;
  border-radius: 8px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
  transform: scale(0.95);
  transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.lightbox.active img {
  transform: scale(1);
}

.lightbox-caption {
  color: white;
  margin-top: 15px;
  font-size: 1.2rem;
  font-weight: 500;
  text-align: center;
  text-shadow: 0 2px 4px rgba(0,0,0,0.8);
}

.lightbox-close {
  position: absolute;
  top: 20px;
  right: 30px;
  color: white;
  font-size: 3rem;
  cursor: pointer;
  z-index: 10001;
  transition: color 0.2s;
  line-height: 1;
}

.lightbox-close:hover {
  color: var(--accent-blue);
}

.tree-drop-target {
  background: rgba(59, 130, 246, 0.4) !important;
  box-shadow: inset 0 0 0 2px var(--accent-blue);
  border-radius: 4px;
}

.text-center {
  text-align: center;
}

/* Map loading state */
.map-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  background: var(--bg-card);
  color: var(--text-muted);
  font-size: 1.2rem;
}

/* Search box at top of dropdown menus */
.dropdown-search {
  padding: 0.5rem 0.75rem 0.75rem;
  border-bottom: 1px solid var(--glass-border);
  margin-bottom: 0.25rem;
}
.dropdown-search input {
  width: 100%;
  padding: 0.5rem 0.75rem;
  border-radius: 6px;
  border: 1px solid var(--glass-border);
  background: rgba(15, 23, 42, 0.5);
  color: var(--text-light);
  font-family: var(--font-main);
  font-size: 0.9rem;
}
.dropdown-search input:focus {
  outline: none;
  border-color: var(--accent-blue);
}

.dropdown-suggestions {
  margin-top: 0.5rem;
  max-height: 220px;
  overflow-y: auto;
  display: none;
}
.dropdown-suggestions.open { display: block; }

.dropdown-suggestion {
  padding: 0.4rem 0.6rem;
  border-radius: 4px;
  cursor: pointer;
  font-size: 0.85rem;
}
.dropdown-suggestion:hover {
  background: var(--accent-blue);
  color: white;
}

.dropdown-loading {
  padding: 0.6rem 0.75rem;
  color: var(--text-muted);
  font-size: 0.85rem;
  font-style: italic;
}

.dropdown-heading {
  padding: 0.4rem 0.75rem;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-muted);
}

/* For dropdown-link elements that have a submenu, show a › indicator */
.dropdown-link.has-submenu::after {
  content: '›';
  opacity: 0.5;
  font-size: 1.1em;
  margin-left: 0.5rem;
}

/* Lightbox navigation arrows */
.lightbox-arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background: rgba(0, 0, 0, 0.5);
    border: 2px solid rgba(255, 255, 255, 0.3);
    color: white;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    font-size: 2rem;
    line-height: 1;
    cursor: pointer;
    z-index: 10001;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: inherit;
    transition: 0.2s;
    user-select: none;
}
.lightbox-arrow:hover:not(:disabled) {
    background: rgba(0, 0, 0, 0.85);
    border-color: white;
    transform: translateY(-50%) scale(1.05);
}
.lightbox-arrow:disabled {
    opacity: 0.25;
    cursor: not-allowed;
}
.lightbox-prev { left: 2rem; }
.lightbox-next { right: 2rem; }

/* Dark-green container background — paints the area inside the map
   container that isn't covered by world tiles. On desktop the world
   at zoom 2 (1024 px) is narrower than a wide browser, so without
   this the leftover space showed the default Leaflet light-gray
   bands. The green here matches the page background so the empty
   area blends invisibly. Harmless on phones because the mobile
   container is already fully covered by tiles (worldCopyJump). */
.leaflet-container { background: #122a21 !important; }
body.light-mode .leaflet-container { background: #e4e1d8 !important; }

/* Hide arrows on small screens — swipe-to-navigate handled by JS touch
   listeners in buildLightboxDom. */
@media (max-width: 600px) {
    .lightbox-arrow {
        width: 40px;
        height: 40px;
        font-size: 1.5rem;
    }
    .lightbox-prev { left: 0.5rem; }
    .lightbox-next { right: 0.5rem; }
}

/* =========================================================================
   Mobile / touch layout (≤ 768px).

   What's broken on phones without this block:
     - Top nav uses :hover to open dropdowns, which never fires on touch
     - Five top-level items + theme + lang + admin button overflow narrow
       viewports horizontally
     - Nested submenus rely on position:fixed coordinates that the
       installSubmenuPositioning helper computes from hover events
     - Touch targets ≤ 36 px miss the WCAG / Apple-HIG minimum of 44 px

   The pieces below give us a hamburger drawer with accordion-style
   dropdowns, larger tap zones, and inline (not floating) nested submenus.
   The matching JS lives in initMobileNav() / lightbox-swipe handlers in
   app.js — both halves are needed for it to work.
   ========================================================================= */

/* Hamburger toggle: rendered on every page by initMobileNav(). Hidden on
   desktop, shown by the mobile @media block below. Live in the static rule
   set so the JS doesn't have to inject style tags. */
.hamburger {
    display: none;
    align-items: center;
    justify-content: center;
    width: 44px; height: 44px;
    background: none;
    border: none;
    color: var(--text-light);
    font-size: 1.75rem;
    cursor: pointer;
    padding: 0;
    line-height: 1;
}

@media (max-width: 768px) {
    /* ---- Header ----
       backdrop-filter (and filter/transform/perspective) promotes an element
       to a containing block for any descendant with position:fixed — which
       is what `<nav>` becomes in the drawer. Leaving the blur on header
       traps nav inside header's ~60px box and the drawer ends up one row
       tall. We drop the blur on mobile and use a solid background so the
       sticky-header look stays consistent. */
    header {
        padding: 0.5rem 1rem;
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        background: #122a21;
        /* Revert the desktop 3-column grid — on mobile <nav> is a fixed
           drawer (taken out of flow), so the visible header children are
           just the logo and the hamburger. Flex with space-between pins
           one to each edge, which is what we want. */
        display: flex;
        justify-content: space-between;
    }
    body.light-mode header { background: #e4e1d8; }
    .logo  { font-size: 1.25rem; }
    .hamburger { display: inline-flex; }

    /* The standalone admin button moves into the drawer via JS, so the
       direct-child version in <header> is hidden. The drawer-resident
       copy keeps its pill style. */
    header > .admin-btn { display: none; }

    /* ---- Nav becomes a full-width drawer ---- */
    nav {
        display: none;                    /* hidden until .open */
        position: fixed;
        top: 60px;                        /* sits below the sticky header */
        left: 0; right: 0; bottom: 0;
        background: #122a21;
        flex-direction: column;
        align-items: stretch;
        gap: 0;
        padding: 0 0 5rem 0;              /* room for safe-area + last item */
        overflow-y: auto;
        z-index: 99;
    }
    body.light-mode nav { background: #e4e1d8; }
    nav.open { display: flex; }

    .nav-item { width: 100%; position: static; }

    .nav-link {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 1rem 1.25rem;
        border-radius: 0;
        border-bottom: 1px solid var(--glass-border);
        min-height: 56px;
        font-size: 1.05rem;
    }
    /* Active highlight reads better as a left-edge band than a full
       background pill at drawer width. */
    .nav-link.active {
        background: rgba(35, 88, 123, 0.18);
        box-shadow: inset 4px 0 0 var(--accent-blue);
    }

    /* Chevron on parent items that own a dropdown. Marker class
       (.has-dropdown) is added by initMobileNav() so we only decorate the
       items that actually have nested content. */
    .nav-item.has-dropdown > .nav-link::after {
        content: "▾";
        margin-left: 0.75rem;
        transition: transform 0.2s;
        opacity: 0.7;
    }
    .nav-item.has-dropdown.open > .nav-link::after { transform: rotate(180deg); }

    /* Language toggle has a chevron span hardcoded inside its <a> link
       (added by injectLanguageDropdown for the desktop nav). On mobile
       the generic .has-dropdown rule above already inserts a chevron via
       ::after, so hiding the inline span here avoids a double arrow on
       the RU / EN / LA row. The :not() keeps the label span visible. */
    #lang-toggle-link > span:not(#lang-toggle-label) { display: none; }

    /* ---- Dropdowns become inline accordion sections ---- */
    .dropdown-menu {
        position: static;
        max-height: none;
        opacity: 1;
        visibility: visible;
        box-shadow: none;
        border: 0;
        border-radius: 0;
        padding: 0;
        background: rgba(0, 0, 0, 0.15);
        display: none;                    /* closed by default */
        min-width: 0;
    }
    body.light-mode .dropdown-menu { background: rgba(0, 0, 0, 0.05); }
    .nav-item.has-dropdown.open > .dropdown-menu { display: block; }

    /* Nested submenus (orders → families, regions → countries) — same
       accordion pattern. installSubmenuPositioning() writes inline top/
       left/maxHeight via the desktop hover path; the !importants below
       win on mobile so the inline coords don't escape the drawer flow. */
    .dropdown-menu-nested {
        position: static !important;
        top: auto !important;
        left: auto !important;
        max-height: none !important;
        display: none;
        background: rgba(0, 0, 0, 0.18);
        padding: 0;
        border: 0;
        border-radius: 0;
        box-shadow: none;
    }
    body.light-mode .dropdown-menu-nested { background: rgba(0, 0, 0, 0.08); }
    .dropdown-submenu.open > .dropdown-menu-nested { display: block; }

    /* Tap targets — every link inside the drawer hits the 44 px minimum. */
    .dropdown-link {
        padding: 0.9rem 1.25rem;
        min-height: 44px;
    }
    .dropdown-submenu > .dropdown-link.has-submenu::after {
        content: "▾";
        margin-left: 0.5rem;
        transition: transform 0.2s;
        opacity: 0.7;
    }
    .dropdown-submenu.open > .dropdown-link.has-submenu::after {
        transform: rotate(180deg);
    }

    /* Search inputs inside dropdowns: full-width with bigger touch padding. */
    .dropdown-search input {
        padding: 0.8rem 1rem;
        font-size: 1rem;
    }

    /* Admin pill — hidden entirely on phones. Admin tasks (uploads,
       editing photo metadata) are desk-bound work in practice, so a
       link to the login page would just add clutter to the mobile
       drawer. The element is still moved into <nav> by
       initMobileNav() so that a viewport resize back above 768 px
       (e.g. rotating an iPad, or DevTools device-mode toggle) restores
       it at the right end of the desktop nav row without a page
       reload. */
    nav .admin-btn { display: none; }

    /* ---- Page-content tweaks ---- */
    .breadcrumbs { flex-wrap: wrap; row-gap: 0.25rem; }
    .breadcrumb-item { padding: 0.25rem 0; }

    /* Card overlay — stack the title above the subtitle on phones.
       The desktop layout is `display: flex` with default `row` direction,
       which puts the H3 and the subtitle <p> side by side at the bottom
       of the card. That only works when the card is wide enough to fit
       both names on one line each. On a 166 px-wide card both names get
       ~ 80 px and wrap to one character per line, which reads as gibberish
       (e.g. "Eulemur collaris" → "col / lari / s").

       Switching to column direction + flex-start lets the title use the
       full overlay width, then the subtitle drops below it. Tighter
       padding + smaller fonts give the cover image more room. */
    /* flex-direction flip note: the desktop overlay uses `align-items:
       flex-end` to push title + subtitle to the BOTTOM of the card in
       row mode (cross axis is vertical there). Switching to column mode
       reuses cross axis for horizontal alignment, so we need
       `justify-content: flex-end` to keep the text at the bottom and
       `align-items: flex-start` to left-align it. */
    .card-overlay {
        flex-direction: column;
        justify-content: flex-end;
        align-items: flex-start;
        padding: 0.9rem;
        gap: 0.2rem;
    }
    .card-overlay h3 {
        font-size: 1.2rem;
        line-height: 1.2;
        /* Same "no mid-word breaks" rule as the desktop overlay above —
           the Cyrillic / Latin long-name problem applies on phones too. */
        word-break: normal;
        overflow-wrap: normal;
        hyphens: none;
    }
    /* Subtitle inside .card-overlay (the italic English / Latin pair line
       on species cards). Keep it just one notch smaller than the title
       and let it wrap at word boundaries too. */
    .card-overlay p {
        font-size: 0.8rem !important;
        line-height: 1.2;
        word-break: normal;
        overflow-wrap: normal;
        hyphens: none;
    }

    /* Slightly taller card so two short lines of text + the cover image
       all breathe — 4:3 gives only ~ 124 px height at 166 px width,
       which is too cramped for stacked text. */
    .category-card { aspect-ratio: 5 / 4; }

    /* Stats hero stacks. */
    .stats-container { flex-direction: column; gap: 1rem; padding: 1rem; }

    /* Grid sizing on phones —
       `auto-fit` (vs the previous `auto-fill`) collapses empty column
       tracks, so a family with a single species fills the row width
       instead of stuck in column 1 with column 2 blank (Tenrecidae was the
       trigger case). minmax bumped to 160 px so the cards stay readable
       when 2 columns DO fit. */
    .grid-container { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 0.75rem; }

    /* Headings dial down so they don't dominate the viewport. */
    .section-title { font-size: 1.5rem; }

    /* Lightbox close: thumb-sized. */
    .lightbox-close { width: 48px; height: 48px; font-size: 2rem; line-height: 1; }

    /* Landscape 16:9 rectangle on phones — wider than tall so the entire
       world can fit horizontally at zoom 0. On a 375 px-wide phone the
       container is ~211 px tall. At zoom 0 the world tiles are 256 px
       square, so width is covered (with horizontal wrap filling the
       extra ~120 px) and height crops the top / bottom ~9 % of
       Mercator latitudes — which is mostly empty polar distortion
       anyway. End result: visitor sees the whole world at once on
       first paint, no gray strips, no green camouflage. */
    #map-container {
        height: auto !important;
        min-height: 0 !important;
        aspect-ratio: 16 / 9;
        max-height: 50vh;
    }
    /* Map controls — keep the three filter buttons on a single row at the
       top, and put the "N locations · M zoo · K wild" stats on its own
       row below. Smaller padding + font on each pill so all three fit
       on a typical 360-414 px phone width without wrapping. */
    .map-controls {
        flex-direction: row;
        flex-wrap: wrap;
        gap: 0.3rem;
    }
    .map-toggle {
        /* !important needed because map.html has its own inline <style>
           with desktop sizing (0.4rem 0.9rem / 0.9em font) that loads
           AFTER style.css. Same specificity, later source order ⇒ the
           inline values would otherwise win even on mobile. */
        padding: 0.3rem 0.5rem !important;
        font-size: 0.72em !important;
        gap: 3px !important;
        flex: 0 0 auto;
        /* Don't allow the button's own label to wrap to 2 lines inside
           the pill — without this, a button that's just barely too
           wide grows taller instead of pushing to the next row, which
           reads worse than the wrap. */
        white-space: nowrap;
    }
    .map-stats {
        margin-left: 0;
        flex-basis: 100%;
        margin-top: 0.25rem;
    }
    /* Leaflet attribution — much smaller on phones so it doesn't eat a
       noticeable strip at the bottom of the now-shorter (16:9) map
       container. Legal credit just needs to be readable, not loud. */
    .leaflet-control-attribution {
        font-size: 0.5rem !important;
        padding: 0 4px !important;
        line-height: 1.4 !important;
    }
}

/* iOS safe-area insets — applies at every viewport size so notch / home
   indicator never overlap the header or fixed drawer. The max() falls
   back to the existing percentage padding on browsers without env()
   support. */
@supports (padding: env(safe-area-inset-left)) {
    header {
        padding-left: max(5%, env(safe-area-inset-left));
        padding-right: max(5%, env(safe-area-inset-right));
    }
    @media (max-width: 768px) {
        header {
            padding-left: max(1rem, env(safe-area-inset-left));
            padding-right: max(1rem, env(safe-area-inset-right));
        }
        nav { padding-bottom: max(5rem, calc(env(safe-area-inset-bottom) + 5rem)); }
    }
}
