/* ============================================================
   yeip — Earthy Field Operations Design System
   Yemen Environmental Intelligence Platform
   ============================================================ */

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

/* ── Design tokens ──────────────────────────────────────────── */
:root {
  /* Fixed brand palette — same hex values in both themes. What changes
     between light/dark is which of these each semantic role below maps
     to, not the palette itself. */
  --forest:       #3e6675;
  --forest-dk:    #26364b;
  --forest-md:    #3e6675;
  --forest-lt:    #4a6150;

  --sage:         #f2fff5;
  --sage-lt:      #b0c9b4;
  --sage-dim:     #99ae9e;

  --cream:        #faf9f6;
  --parchment:    #34625d;
  --parchment-lt: #659791;
  --tan:          #d6cfc0;
  --tan-lt:       #e8e3d8;

  /* Status colors — the saturated hue stays constant across themes;
     only the pale/tinted "-bg" backing changes (pale tint on light,
     translucent tint on dark) so it's always readable against the
     current card surface. */
  --critical:     #c0392b;
  --critical-border: #e8a09a;
  --severe:       #cd853f;
  --severe-border:#e8c49a;
  --moderate:     #b8a832;
  --moderate-border: #ddd098;
  --normal:       #4a7c59;
  --normal-border:#a0c8aa;

  --text-dark:    #202220;
  --text-on-dark: #ffffff;

  /* Typography — same family as the landing pages (static/css/landing.css)
     so the app shell reads as a continuation of the marketing site rather
     than a different product. */
  --font-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;

  /* Layout */
  --topbar-h:   64px;
  --sidebar-w:  200px;
  --breadcrumb-h: 32px;
  --statsbar-h:  62px;
  --right-panel-w: 280px;

  /* Same radius scale as landing.css */
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;

  /* ============================================================
     Theme-reactive semantic tokens — LIGHT (default). Everything
     above this point is a fixed brand color; everything below is a
     *role* ("chrome surface", "card text") that light/dark map onto
     different brand colors. Toggled via [data-theme] on <html>
     (see static/js/theme.js); light is the default so a first-time
     visitor's dashboard matches the always-light landing pages.
     ============================================================ */
  --canvas-bg:          var(--cream);   /* map/main-panel background */

  /* Sidebar, topbar, stats bar, right panel — the app's "chrome".
     Was #f2efe6 with a --tan (#d6cfc0) border and a topbar-bg that
     resolved to within 1.0 contrast of --canvas-bg (i.e. visually
     identical) — the whole shell read as one flat off-white surface
     with no visible seams. Darkened chrome-bg a step and gave it a
     genuinely darker border so panel edges are actually visible;
     topbar-bg now tracks chrome-bg (same tan family) instead of
     nearly matching the cream canvas behind it. */
  --chrome-bg:          #faf9f6;
  --topbar-bg:          #faf9f6;
  --topbar-shadow:      0 2px 16px rgba(0, 0, 0, 0.08);
  --chrome-border:      #9c8d6e;
  --chrome-text:        var(--forest-dk);
  --chrome-text-muted:  #5f6963;
  --chrome-text-faint:  #6d7b71;
  --chrome-icon:        var(--forest);
  --chrome-hover:       rgba(38, 54, 75, 0.09);
  --chrome-active-bg:   var(--forest-dk);
  --chrome-active-text: var(--text-on-dark);
  --chrome-active-icon: var(--text-on-dark);
  --chrome-scrollbar:   var(--tan);
  --chrome-input-bg:    #ffffff;
  --chrome-input-border:#9c8d6e;

  /* Floating cards over the map canvas: legend, trend panel, basemap
     toggle, flash messages. */
  --card-bg:            rgba(255, 255, 255, 0.93);
  --card-border:        var(--tan);
  --card-text:          var(--text-dark);
  --card-text-muted:    #5f6963;
  --card-text-faint:    #66756b;

  --badge-neutral-bg:   var(--tan-lt);
  --badge-neutral-text: #4a4a3d;

  --nav-badge-bg:       #fbe0e0;
  --nav-badge-text:     #b23b3b;

  --critical-bg:  #fdf1f0;
  --severe-bg:    #fdf6ee;
  --moderate-bg:  #e6db92;
  --normal-bg:    #f0f7f1;
}

/* ── Dark theme ─────────────────────────────────────────────── */
:root[data-theme="dark"] {
  --canvas-bg:          #161c24;

  --chrome-bg:          var(--forest-dk);
  /* Was rgba(19,26,35,...) — a near-black navy that didn't match
     chrome-bg's forest-dk at all, so the header read as flat black
     instead of the same "chrome" tone as the sidebar/right panel. */
  --topbar-bg:          rgba(38, 54, 75, 0.88);
  --topbar-shadow:      0 2px 16px rgba(0, 0, 0, 0.35);
  --chrome-border:      rgba(255, 255, 255, 0.08);
  --chrome-text:        var(--sage);
  --chrome-text-muted:  var(--sage-dim);
  --chrome-text-faint:  var(--sage-dim);
  --chrome-icon:        var(--sage);
  --chrome-hover:       var(--forest-md);
  --chrome-active-bg:   var(--forest-md);
  --chrome-active-text: #ffffff;
  --chrome-active-icon: var(--sage-lt);
  --chrome-scrollbar:   var(--forest-lt);
  --chrome-input-bg:    var(--forest-dk);
  --chrome-input-border:var(--forest-lt);

  --card-bg:            rgba(28, 36, 46, 0.94);
  --card-border:        rgba(255, 255, 255, 0.1);
  --card-text:          #e8ece9;
  --card-text-muted:    #9bb0a8;
  --card-text-faint:    #7f9690;

  --badge-neutral-bg:   rgba(255, 255, 255, 0.08);
  --badge-neutral-text: var(--sage-lt);

  --nav-badge-bg:       rgba(192, 57, 43, 0.22);
  --nav-badge-text:     #ff9d90;

  --critical-bg:  rgba(192, 57, 43, 0.18);
  --severe-bg:    rgba(205, 133, 63, 0.18);
  --moderate-bg:  rgba(184, 168, 50, 0.18);
  --normal-bg:    rgba(74, 124, 89, 0.2);
}

/* ── Base ───────────────────────────────────────────────────── */
html, body {
  height: 100%;
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--card-text);
  background: var(--canvas-bg);
  -webkit-font-smoothing: antialiased;
}

body.lang-ar { font-family: 'Tajawal', var(--font-sans); }

a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; border: none; background: none; }
select { font-family: inherit; }
input, select { outline: none; }

/* ── App shell ──────────────────────────────────────────────── */
.yeip-shell {
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow: hidden;
}

/* ── Page transition overlay ───────────────────────────────────
   Same visual language as .l-transition-overlay on the landing pages
   (static/css/landing.css) — the brand mark fading/scaling over the
   same forest-dk wash — so leaving the landing page and arriving here
   reads as one continuous motion instead of two unrelated page loads.
   Deliberately NOT theme-reactive — it's a one-shot brand moment, not
   part of the app chrome the user lives in. */
.page-transition-overlay {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: var(--forest-dk);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.45s ease, visibility 0.45s ease;
}

.page-transition-overlay.is-active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.page-transition-mark {
  width: 60px;
  height: 60px;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
  transform: scale(0.7);
  transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.page-transition-overlay.is-active .page-transition-mark { transform: scale(1); }

.page-transition-mark img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ── Topbar ─────────────────────────────────────────────────────
   Matches the landing pages' .l-nav (static/css/landing.css) in light
   mode — same frosted-glass background, brand lockup, and button
   shapes — so arriving here from the marketing site doesn't feel like
   a jump to a different product. In dark mode it becomes a dark
   frosted variant of the same shape so the whole shell (topbar +
   sidebar + stats bar + right panel) reads as one coherent theme
   rather than a light header stuck above a dark app. */
.topbar {
  height: var(--topbar-h);
  background: var(--topbar-bg);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  display: flex;
  align-items: center;
  padding: 0 20px;
  gap: 16px;
  flex-shrink: 0;
  border-bottom: 1px solid var(--chrome-border);
  box-shadow: var(--topbar-shadow);
  transition: background 0.2s ease, border-color 0.2s ease;
}

.topbar-logo {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Two <img> tags, one per theme (see templates/base.html) — pure CSS
   display toggle so the correct logo shows from first paint with no
   JS needed and no flash of the wrong mark. */
.topbar-logo-img-dark { display: none; }
:root[data-theme="dark"] .topbar-logo-img-light { display: none; }
:root[data-theme="dark"] .topbar-logo-img-dark { display: block; }

.topbar-name {
  font-size: 15px;
  font-weight: 800;
  color: var(--chrome-text);
  letter-spacing: 0.2px;
  white-space: nowrap;
}

/* Purely decorative in the old dark topbar; the light nav doesn't need
   it (matches the landing nav, which has no such divider either). */
.topbar-divider { display: none; }

.topbar-spacer { flex: 1; }

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.topbar-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 34px;
  padding: 0 14px;
  border-radius: var(--radius-md);
  background: transparent;
  border: 1.5px solid var(--chrome-border);
  color: var(--chrome-text);
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.topbar-btn i { font-size: 15px; }
.topbar-btn:hover { border-color: var(--chrome-icon); background: var(--chrome-hover); }

.topbar-theme-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-md);
  background: transparent;
  border: 1.5px solid var(--chrome-border);
  color: var(--chrome-text);
  font-size: 16px;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.topbar-theme-toggle:hover { border-color: var(--chrome-icon); background: var(--chrome-hover); }

/* Only one of these is ever visible at a time (see static/js/theme.js) */
.topbar-theme-toggle .ti-sun { display: none; }
:root[data-theme="dark"] .topbar-theme-toggle .ti-moon { display: none; }
:root[data-theme="dark"] .topbar-theme-toggle .ti-sun { display: block; }

.topbar-lang-switch {
  display: flex;
  border: 1px solid var(--chrome-border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.topbar-lang-switch a {
  padding: 7px 11px;
  font-size: 11px;
  font-weight: 600;
  color: var(--chrome-text-muted);
  transition: background 0.15s ease, color 0.15s ease;
}

.topbar-lang-switch a.active { background: var(--chrome-active-bg); color: var(--chrome-active-text); }
.topbar-lang-switch a:not(.active):hover { background: var(--chrome-hover); color: var(--chrome-text); }

/* ── Body row ───────────────────────────────────────────────── */
.body-row {
  display: flex;
  flex: 1;
  overflow: hidden;
}

/* ── Sidebar ────────────────────────────────────────────────── */
.sidebar {
  width: var(--sidebar-w);
  background: var(--chrome-bg);
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  border-inline-end: 1px solid var(--chrome-border);
  /* The module list (first .sidebar-section) stays fixed; only the
     description section below it scrolls — see .sidebar-description-section.
     Was overflow-y:auto here, scrolling the whole sidebar (nav included)
     as one unit. */
  overflow: hidden;
  transition: background 0.2s ease, border-color 0.2s ease;
}

.sidebar-section { padding: 14px 10px 8px; flex-shrink: 0; }

/* Module Description — the only part of the sidebar that scrolls.
   min-height: 0 is required for a flex child to actually shrink and
   scroll instead of overflowing its flex parent. */
.sidebar-description-section {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

.sidebar-description-section::-webkit-scrollbar { width: 4px; }
.sidebar-description-section::-webkit-scrollbar-track { background: transparent; }
.sidebar-description-section::-webkit-scrollbar-thumb { background: var(--chrome-scrollbar); border-radius: 4px; }

.sidebar-label {
  font-size: 9px;
  color: var(--chrome-text-faint);
  letter-spacing: 1.2px;
  text-transform: uppercase;
  padding: 0 6px;
  margin-bottom: 6px;
}

.sidebar_subtitle {
  font-size: 8px;
  color: var(--chrome-text);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  padding: 0 6px;
  margin-bottom: 4px;
  margin-top: 10px;
}

/* Nav items */
.nav-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 10px;
  border-radius: var(--radius-md);
  margin-bottom: 2px;
  cursor: pointer;
  transition: background 0.12s;
  text-decoration: none;
  border-inline-start: 2px solid transparent;
}

.nav-item:hover { background: var(--chrome-hover); }

.nav-item.active {
  background: var(--chrome-active-bg);
  border-inline-start-color: var(--chrome-active-icon);
  padding-inline-start: 8px;
  border-radius: var(--radius-md);
}

.nav-item i {
  font-size: 16px;
  color: var(--chrome-icon);
  flex-shrink: 0;
}

.nav-item.active i { color: var(--chrome-active-icon); }


.nav-item.disabled {
  pointer-events: none;
  opacity: 0.5;
  cursor: not-allowed;
}

.nav-text {
  font-size: 11px;
  color: var(--chrome-text);
  flex: 1;
}

.nav-item.active .nav-text { color: var(--chrome-active-text); }

.nav-badge {
  font-size: 9px;
  font-weight: 500;
  background: var(--nav-badge-bg);
  color: var(--nav-badge-text);
  padding: 1px 5px;
  border-radius: 8px;
}

.sidebar-divider {
    height: 1px;
    background: var(--chrome-border);
    margin-top: 12px;
}

/* Layer toggles */
.layer-item {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 10px;
  font-size: 10px;
  color: var(--chrome-text);
  cursor: pointer;
  border-radius: var(--radius-sm);
  transition: background 0.1s;
}

.layer-item:hover { background: var(--chrome-hover); }
.layer-item input[type=checkbox] { accent-color: var(--chrome-icon); width: 11px; height: 11px; }
.layer-item.disabled { color: var(--chrome-text-faint); opacity: 0.5; }

/* Sidebar filters */
.sidebar-filter { padding: 0 10px 10px; }

.filter-label {
  font-size: 9px;
  color: var(--chrome-text-faint);
  letter-spacing: 0.8px;
  text-transform: uppercase;
  margin-bottom: 5px;
  display: block;
}

.filter-select {
  width: 100%;
  background: var(--chrome-input-bg);
  border: 0.5px solid var(--chrome-input-border);
  border-radius: var(--radius-sm);
  color: var(--chrome-text);
  font-size: 10px;
  padding: 5px 8px;
  appearance: none;
  cursor: pointer;
  transition: border-color 0.1s;
}

.filter-select:hover { border-color: var(--chrome-icon); }
.filter-select:focus { border-color: var(--chrome-icon); }

/* Map layer toggle (e.g. Groundwater's GW Anomaly / GW Trend switcher) */
.layer-toggle {
  display: flex;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 0.5px solid var(--chrome-input-border);
}

.layer-toggle-btn {
  flex: 1;
  padding: 7px 6px;
  font-size: 9.5px;
  line-height: 1.3;
  color: var(--chrome-text);
  background: var(--chrome-input-bg);
  text-align: center;
  border-inline-end: 0.5px solid var(--chrome-input-border);
  transition: background 0.12s, color 0.12s;
}

.layer-toggle-btn:last-child { border-inline-end: none; }
.layer-toggle-btn:hover { background: var(--chrome-hover); }

.layer-toggle-btn.active {
  background: var(--chrome-active-bg);
  color: var(--text-on-dark);
  font-weight: 500;
}

/* ── Main panel ─────────────────────────────────────────────── */
.main-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--canvas-bg);
}

/* Stats bar */
.statsbar {
  height: var(--statsbar-h);
  background: var(--chrome-bg);
  border-bottom: 1px solid var(--chrome-border);
  display: flex;
  align-items: center;
  padding: 0 16px;
  flex-shrink: 0;
  transition: background 0.2s ease, border-color 0.2s ease;
}

.stat-cell {
  flex: 1;
  padding: 0 16px;
  border-inline-end: 1px solid var(--chrome-border);
}

.stat-cell:first-child { padding-inline-start: 0; }
.stat-cell:last-child  { border-inline-end: none; }

.stat-label {
  font-size: 9px;
  color: var(--chrome-text-faint);
  text-transform: uppercase;
  letter-spacing: 0.7px;
  margin-bottom: 2px;
}

.stat-value {
  font-size: 22px;
  font-weight: 500;
  color: var(--chrome-text);
  line-height: 1.1;
}

.stat-value .stat-unit {
  font-size: 13px;
  font-weight: 400;
  color: var(--chrome-text-muted);
}

.stat-value.is-critical { color: var(--critical); }
.stat-value.is-severe   { color: var(--severe); }
.stat-value.is-moderate { color: var(--moderate); }
.stat-value.is-normal   { color: var(--normal); }

.stat-badge {
  display: inline-block;
  font-size: 8px;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  margin-top: 3px;
}

.badge-critical  { background: var(--critical-bg);  color: var(--critical); }
.badge-severe    { background: var(--severe-bg);    color: var(--severe); }
.badge-moderate  { background: var(--moderate-bg);  color: var(--moderate); }
.badge-normal    { background: var(--normal-bg);    color: var(--normal); }
.badge-neutral   { background: var(--badge-neutral-bg); color: var(--badge-neutral-text); }

/* Content area */
.content-area {
  flex: 1;
  display: flex;
  overflow: hidden;
}

/* ── Map panel ──────────────────────────────────────────────── */
.map-panel {
  flex: 1;
  position: relative;
  background: var(--canvas-bg);
  overflow: hidden;
}

#main-map {
  width: 100%;
  height: 100%;
}

.map-overlay-title {
  display: none !important;
}

/* Basemap toggle — same floating-card language as .map-legend /
   .map-trend-panel, opposite corner from the Leaflet zoom control.
   Kept at a fixed physical corner regardless of language, like the
   other map overlays (map chrome doesn't mirror for RTL). */
.map-basemap-toggle {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 400;
  display: flex;
  background: var(--card-bg);
  border: 0.5px solid var(--card-border);
  border-radius: var(--radius-md);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
  overflow: hidden;
}

.map-basemap-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  font-size: 11px;
  font-weight: 500;
  color: var(--card-text);
  background: transparent;
  border-inline-end: 0.5px solid var(--card-border);
  transition: background 0.12s ease, color 0.12s ease;
  white-space: nowrap;
}

.map-basemap-btn:last-child { border-inline-end: none; }
.map-basemap-btn i { font-size: 14px; }
.map-basemap-btn:hover { background: var(--chrome-hover); }

.map-basemap-btn.active {
  background: var(--forest-dk);
  color: var(--text-on-dark);
}

:root[data-theme="dark"] .map-basemap-btn { background: var(--forest-dk); }
:root[data-theme="dark"] .map-basemap-btn.active { background: var(--chrome-active-bg); }

@media (max-width: 900px) {
  .map-basemap-btn span { display: none; }
}

/* Leaflet overrides */
.leaflet-control-zoom {
  border: 0.5px solid var(--card-border) !important;
  border-radius: var(--radius-md) !important;
}

.leaflet-control-zoom a {
  background: var(--forest-dk) !important;
  color: var(--sage) !important;
  border-bottom-color: var(--card-border) !important;
  font-size: 16px !important;
  line-height: 26px !important;
  width: 26px !important;
  height: 26px !important;
}

.leaflet-control-zoom a:hover {
  background: var(--forest) !important;
  color: var(--text-on-dark) !important;
  cursor: pointer !important;
}

/* Map legend */
.map-legend {
  position: absolute;
  bottom: 14px;
  left: 14px;
  background: var(--card-bg);
  border-radius: var(--radius-md);
  border: 0.5px solid var(--card-border);
  padding: 9px 12px;
  z-index: 400;
  min-width: 140px;
}

.legend-title {
  font-size: 9px;
  font-weight: 500;
  color: var(--card-text);
  text-transform: uppercase;
  letter-spacing: 0.7px;
  margin-bottom: 6px;
}

.legend-row {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 4px;
  font-size: 10px;
  color: var(--card-text);
}

.legend-swatch {
  width: 11px;
  height: 11px;
  border-radius: 2px;
  flex-shrink: 0;
}

.legend-count {
  margin-inline-start: auto;
  font-size: 9px;
  color: var(--card-text-muted);
  padding-inline-start: 10px;
}

/* Map trend panel (Groundwater's "Fastest Depleting Districts") — same
   light-card visual language as .map-legend, opposite corner. Each row
   pairs a current-status dot with a trend figure on purpose: they're
   different measurements (see functions.js:populateMapTrendPanel), and
   showing both side by side is what makes that legible at a glance. */
.map-trend-panel {
  position: absolute;
  bottom: 22px;
  right: 14px;
  background: var(--card-bg);
  border-radius: var(--radius-md);
  border: 0.5px solid var(--card-border);
  padding: 10px 12px;
  z-index: 400;
  min-width: 220px;
  max-width: 270px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
}

.map-trend-title {
  font-size: 9px;
  font-weight: 500;
  color: var(--card-text);
  text-transform: uppercase;
  letter-spacing: 0.7px;
}

.map-trend-subtitle {
  font-size: 8.5px;
  color: var(--card-text-faint);
  margin-bottom: 8px;
  line-height: 1.3;
}

.map-trend-row {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 3px 0;
  font-size: 10.5px;
  border-top: 1px solid var(--card-border);
  cursor: default;
}

.map-trend-row:first-child { border-top: none; padding-top: 0; }
.map-trend-row:last-child { padding-bottom: 0; }

.map-trend-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  border: 0.5px solid rgba(0, 0, 0, 0.15);
}

.map-trend-name {
  flex: 1;
  color: var(--card-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.map-trend-val {
  color: var(--critical);
  font-weight: 500;
  flex-shrink: 0;
}

/* ── Right panel ────────────────────────────────────────────── */
.right-panel {
  width: var(--right-panel-w);
  background: var(--chrome-bg);
  border-inline-start: 1px solid var(--chrome-border);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  flex-shrink: 0;
  transition: background 0.2s ease, border-color 0.2s ease;
}

.right-panel::-webkit-scrollbar { width: 4px; }
.right-panel::-webkit-scrollbar-thumb { background: var(--chrome-scrollbar); border-radius: 4px; }

.rp-section {
  padding: 12px 12px 10px;
  border-bottom: 1px solid var(--chrome-border);
}

.rp-section:last-child { border-bottom: none; }

/* Pins a section (e.g. groundwater's "Map Layer" toggle) to the top of
   .right-panel while the rest of the panel (e.g. "Active Alerts") scrolls
   past/under it. Needs its own background since sticky elements are
   otherwise transparent against whatever scrolls beneath them, and a
   shadow once stuck so it doesn't visually blend into the scrolled
   content. .right-panel is already the scrolling ancestor
   (overflow-y: auto), so no container changes are needed elsewhere —
   this only affects the section it's applied to. */
.rp-section-sticky {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--chrome-bg);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
}

.rp-heading {
  font-size: 9px;
  font-weight: 500;
  color: var(--chrome-text);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  margin-bottom: 8px;
}

/* Alert cards — these sit on the chrome (right panel), but use the
   card-* surface tokens for their fill/text since the severity tint
   backgrounds (pale on light, translucent on dark) are the same ones
   the map legend/badges use, and read best against a near-white/
   near-black card rather than the chrome's flat tan/navy fill. */
.alert-card {
  padding: 7px 9px;
  margin-bottom: 5px;
  border-inline-start: 2px solid transparent;
  border-radius: var(--radius-sm);
}

.alert-card:last-child { margin-bottom: 0; }
.alert-card.critical  { background: var(--critical-bg);  border-inline-start-color: var(--critical); }
.alert-card.severe    { background: var(--severe-bg);    border-inline-start-color: var(--severe); }
.alert-card.moderate  { background: var(--moderate-bg);  border-inline-start-color: var(--moderate); }

.alert-gov  { font-size: 10px; font-weight: 500; color: var(--card-text); }
.alert-desc { font-size: 9px; color: var(--card-text); opacity: 0.75; margin-top: 1px; }
.alert-time { font-size: 8px; color: var(--card-text-faint); margin-top: 2px; }

/* Coverage bars */
.coverage-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 7px;
}

.coverage-row:last-child { margin-bottom: 0; }

.coverage-name {
  font-size: 10px;
  color: var(--chrome-text);
  width: 52px;
  flex-shrink: 0;
}

.coverage-track {
  flex: 1;
  height: 4px;
  background: var(--chrome-border);
  border-radius: 2px;
  overflow: hidden;
}

.coverage-fill {
  height: 100%;
  border-radius: 2px;
  transition: width 0.4s ease;
}

.coverage-pct {
  font-size: 9px;
  color: var(--chrome-text-muted);
  width: 28px;
  text-align: end;
  flex-shrink: 0;
}

/* Trend rows */
.trend-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 5px;
  font-size: 10px;
}

.trend-month {
  color: var(--chrome-text-muted);
  width: 92px;
  flex-shrink: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.trend-val   { font-weight: 500; min-width: 40px; text-align: end; }

.trend-bar-track {
  flex: 1;
  height: 4px;
  background: var(--chrome-border);
  border-radius: 2px;
  overflow: hidden;
}

.trend-bar-fill {
  height: 100%;
  border-radius: 2px;
}

/* ── Utility classes ────────────────────────────────────────── */
.text-critical { color: var(--critical); }
.text-severe   { color: var(--severe); }
.text-moderate { color: var(--moderate); }
.text-normal   { color: var(--normal); }
.text-muted    { color: var(--chrome-text-muted); }
.text-faint    { color: var(--chrome-text-faint); }

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

/* ── Flash messages ─────────────────────────────────────────── */
.messages { position: fixed; top: 52px; right: 16px; z-index: 1000; display: flex; flex-direction: column; gap: 6px; }

.message {
  padding: 8px 14px;
  border-radius: var(--radius-md);
  font-size: 12px;
  border-inline-start: 3px solid transparent;
  background: var(--card-bg);
  border: 0.5px solid var(--card-border);
  color: var(--card-text);
  max-width: 280px;
}

.message.success { border-inline-start-color: var(--normal); background: var(--normal-bg); }
.message.warning { border-inline-start-color: var(--severe); background: var(--severe-bg); }
.message.error   { border-inline-start-color: var(--critical); background: var(--critical-bg); }

/* ── Loading spinner ────────────────────────────────────────── */
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Responsive ─────────────────────────────────────────────── */
@media (max-width: 900px) {
  :root { --sidebar-w: 46px; }
  .nav-text, .sidebar-label, .filter-label,
  .filter-select, .layer-item span { display: none; }
  .nav-item { justify-content: center; padding: 8px; }
  .nav-item.active { border-inline-start: none; padding: 8px; border-bottom: 2px solid var(--chrome-active-icon); }
  .topbar-name { display: none; }
  .topbar-btn span { display: none; }
}

/* Full-screen scrim — covers the entire dashboard (topbar, sidebar,
   map, right panel), not just the map panel it happens to sit inside;
   position:fixed escapes .map-panel's overflow:hidden since nothing
   between it and the viewport sets a transform/filter of its own.
   Blurs + dims everything behind it and captures all clicks so the
   user can't navigate away mid-load. Holds a centered .loading-card
   rather than floating the spinner/text directly on the scrim. */
.loading-overlay {
    position: fixed;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(15, 23, 32, 0.4);
    z-index: 9999;
    backdrop-filter: blur(6px);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.25s ease, visibility 0.25s ease;
}

/* Active state (when shown via JS display:flex). Was opacity: 0.3 here,
   which washed out the spinner/text along with the scrim instead of
   just dimming the dashboard behind it — the card below is what should
   read as translucent-backed, not the whole loading UI. */
.loading-overlay[style*="display: flex"] {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}

/* Centered card (spinner + message) rather than bare elements floating
   on the scrim — same card-surface tokens used by the map's floating
   legend/trend panels, so this reads as the same design language. */
.loading-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    padding: 26px 34px;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: var(--radius-lg);
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);
    transform: scale(0.96);
    transition: transform 0.25s ease;
}

.loading-overlay[style*="display: flex"] .loading-card {
    transform: scale(1);
}

/* Spinner */
.spinner {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 3px solid var(--card-border);
    border-top-color: var(--parchment);
    animation: spin 0.8s linear infinite;
}

/* Loading text */
.loading-text {
    font-size: 13px;
    font-weight: 500;
    color: var(--card-text);
    letter-spacing: 0.2px;
    text-align: center;
}

/* Map-scoped loading overlay — used for in-module map layer switches
   (Groundwater's water-stress/anomaly/trend toggle, Explorer's "Show on
   Map"), as opposed to .loading-overlay's full-screen scrim used for
   switching modules entirely. Absolutely positioned (not fixed), so
   .map-panel's own position:relative + overflow:hidden contains it —
   the topbar/sidebar/right-panel stay interactive and untouched while
   only the map re-renders. */
.map-loading-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(15, 23, 32, 0.12);
    backdrop-filter: blur(2px);
    z-index: 500;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.2s ease, visibility 0.2s ease;
}

.map-loading-overlay[style*="display: flex"] {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
}

/* Thin indeterminate sweep across the top edge of the map panel —
   reads as "this panel is refreshing" without a scrim-covering card. */
.map-loading-overlay::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: linear-gradient(90deg, transparent, var(--parchment), transparent);
    background-size: 200% 100%;
    animation: map-loading-sweep 1.1s ease-in-out infinite;
}

@keyframes map-loading-sweep {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

.map-loading-chip {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-radius: var(--radius-md);
    padding: 9px 16px;
    box-shadow: 0 8px 26px rgba(0, 0, 0, 0.22);
    opacity: 0;
    transform: translateY(4px) scale(0.98);
    transition: opacity 0.25s ease, transform 0.25s ease;
}

.map-loading-overlay[style*="display: flex"] .map-loading-chip {
    opacity: 1;
    transform: translateY(0) scale(1);
}

.map-spinner-sm {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 2px solid var(--card-border);
    border-top-color: var(--parchment);
    animation: spin 0.7s linear infinite;
    flex-shrink: 0;
}

.map-loading-text {
    font-size: 11px;
    font-weight: 500;
    color: var(--card-text);
    letter-spacing: 0.2px;
}

#module-description{
  font-size: 11px;
  text-align: justify;
  color: var(--chrome-text-muted);
}

.btn-primary {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  background: var(--parchment);
  color: var(--text-on-dark);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.2px;
  padding: 9px 14px;
  margin-top: 12px;
  border-radius: var(--radius-md);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
  transition: background 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
}

.btn-primary i { font-size: 14px; }

.btn-primary:hover {
  background: var(--parchment-lt);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
}

.btn-primary:active {
  transform: translateY(1px);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
}

.btn-primary:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}

input[type="month"] {
  width: 100%;
  padding: 6px 6px;
  font-size: 10px;
  border: 1px solid var(--chrome-input-border);
  border-radius: 8px;
  background-color: var(--chrome-input-bg);
  color: var(--chrome-text);
  outline: none;
  transition: 0.2s ease;
}


input[type="month"]:focus {
  border-color: #4c9ffe;
  box-shadow: 0 0 0 3px rgba(76, 159, 254, 0.2);
}

input[type="month"]:hover {
  border-color: var(--chrome-icon);
}

/* =============================================================
   LEAFLET POPUP — YEIP Professional Style
   Deliberately fixed-dark regardless of dashboard theme (same
   reasoning as the page-transition overlay above) — a dark popup
   reads as an intentional map-UI convention rather than something
   that needs to track the surrounding page.
   ============================================================= */

.leaflet-popup-tip { background: #0f1923; box-shadow: none; }
.leaflet-popup-content { margin: 10px 12px; }

/* Header: district name + governorate, built by popupCard() in functions.js */
.popup-header {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin-bottom: 7px;
    padding-bottom: 7px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.popup-place { font-size: 14px; font-weight: 600; color: #f4f7f6; }
.popup-gov   { font-size: 11px; font-weight: 400; color: #9fb0aa; white-space: nowrap; }

/* Stat rows: one per label/value pair passed to popupCard() */
.popup-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    padding: 2px 0;
}

.popup-label { font-size: 11px; color: #9fb0aa; }
.popup-value { font-size: 13px; font-weight: 600; color: #e8edf2; text-align: end; }

/* Footer: muted metadata (date/source), visually separated from the stats */
.popup-footer {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    margin-top: 7px;
    padding-top: 6px;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    font-size: 10px;
    color: #7b8c85;
}

/* Wrapper */
.leaflet-popup-content-wrapper {
    background: var(--forest-dk);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 8px;
    box-shadow:
        0 4px 24px rgba(0, 0, 0, 0.5),
        0 1px 4px rgba(0, 0, 0, 0.3),
        inset 0 1px 0 rgba(255, 255, 255, 0.06);
    padding: 10px;
    overflow: hidden;
}

/* Content area */
.leaflet-popup-content {
    margin: 0;
    padding: 0;
    color: #e8edf2;
    font-family: 'Inter', 'Segoe UI', system-ui, sans-serif;
    font-size: 13px;
    line-height: 1.5;
    min-width: 220px;
}

/* Tip / arrow container */
.leaflet-popup-tip-container {
    margin-top: -1px;
}

/* Close button
   Selector matches Leaflet's own default rule (.leaflet-container
   a.leaflet-popup-close-button) — that exact selector is more specific
   than a bare .leaflet-popup-close-button, so leaflet's own `right: 0`
   was winning over our override regardless of !important. Matching its
   specificity here, not just the class, is what actually overrides it. */
.leaflet-container a.leaflet-popup-close-button {
    color: rgba(255, 255, 255, 0.3) !important;
    font-size: 18px !important;
    font-weight: 300 !important;
    top: 10px !important;
    right: auto !important;
    /* Logical property (like border-inline-start elsewhere in this file)
       so it sits at the popup's trailing edge — right in LTR (English),
       left in RTL (Arabic, <html dir="rtl">, see apps/core/views.py). */
    inset-inline-end: 10px !important;
    width: 20px !important;
    height: 20px !important;
    line-height: 20px !important;
    transition: color 0.2s ease;
}

.leaflet-popup-close-button:hover {
    color: rgba(255, 255, 255, 0.8) !important;
    background: none !important;
}
