:root{
  --bg:#f4f5fa; --panel:#ffffff; --panel-2:#f7f8fc; --border:#e4e7f2;
  --text:#000000; --text-dim:#000000; --text-dimmer:#000000;
  --purple:#4338ca; --purple-light:#eef0ff;
  --red:#d10404; --red-light:#fbdada;
  --green:#15eb1c; --green-light:#d9fbda;
  --yellow:#ebe315; --yellow-light:#fbf9d6;
  --orange:#eb7915; --orange-light:#fce4d0;
  --blue:#2563eb; --blue-light:#dbeafe;
  --radius:14px; --radius-sm:9px;
  --sidebar-w:300px; --gutter:20px;
}
*{box-sizing:border-box;}
html,body{margin:0;padding:0;}
body{background:var(--bg);color:var(--text);font-family:'Segoe UI',Roboto,Helvetica,Arial,sans-serif;font-size:16px;-webkit-font-smoothing:antialiased;}
a{color:inherit;text-decoration:none;}
html,body{height:100%;overflow-x:hidden;}
/* app-shell now pins to the viewport height exactly (not just min-height),
   so at 100% zoom the whole dashboard fills the screen with no leftover
   space, and at smaller zoom levels the content stretches to fill instead
   of leaving a blank gap under the footer. */
.app-shell{height:100vh;display:flex;flex-direction:column;}
/* Everything between the header and the very bottom (sidebar+main row,
   weekly forecast panel, footer) shares this flex column so it grows to
   fill remaining height and the footer/tagline is always reachable. */
.page-body{display:flex;flex-direction:column;flex:1;min-height:0;overflow-y:auto;}

/* ---------- Top-level header: full width, logo + title, sits above everything ---------- */
.app-header{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;background:var(--panel);border-bottom:1px solid var(--border);padding:16px 24px;min-height:78px;}
.app-header-left{display:flex;align-items:center;gap:16px;}
.app-logo{width:90px;height:90px;object-fit:contain;flex:none;}

/* Sidebar given a little more room (was 250px) */
.app{display:grid;grid-template-columns:var(--sidebar-w) 1fr;flex:1;min-height:0;}

/* ---------- Sidebar ---------- */
.sidebar{background:var(--panel);border-right:1px solid var(--border);padding:16px 16px 18px;display:flex;flex-direction:column;min-height:100%;position:sticky;top:0;overflow-y:auto;}
.brand{display:flex;align-items:center;gap:10px;padding:0 4px 14px;}
.brand-icon{width:34px;height:34px;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,var(--purple),#6366f1);border-radius:10px;font-size:21.2px;flex:none;}
.brand-name{font-weight:800;font-size:23.8px;line-height:1.2;color:var(--text);}
.brand-sub{font-size:16.9px;color:var(--text-dim);margin-top:1px;}

.nav{display:flex;flex-direction:column;gap:1px;}
.nav-item{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:var(--radius-sm);color:var(--text-dim);font-size:18.8px;font-weight:600;cursor:pointer;}
.nav-item .nav-icon{width:16px;text-align:center;font-size:19.4px;}
.nav-item:hover{background:var(--panel-2);color:var(--text);}
.nav-item.active{background:var(--purple);color:#fff;}

.sidebar-controls{margin-top:0;background:var(--panel-2);border:1px solid var(--border);border-radius:var(--radius);padding:16px 15px;display:flex;flex-direction:column;gap:14px;}
.controls-title{font-weight:800;font-size:19px;color:var(--text);margin-bottom:1px;}
.side-field{display:flex;flex-direction:column;gap:8px;}
.side-field label{font-size:15.5px;font-weight:700;letter-spacing:.03em;color:var(--text-dim);text-transform:uppercase;}
select{width:100%;background:#fff;border:1px solid var(--border);color:var(--text);padding:9px 10px;border-radius:8px;font-size:17px;outline:none;cursor:pointer;font-family:inherit;}
select:focus{border-color:var(--purple);}
.side-play-row{display:flex;justify-content:center}
.side-play-btn{width:240px;justify-content:center;height:auto;padding:10px 12px;border-radius:8px;font-size:18px;font-weight:700;}
.btn-apply{width:100%;padding:10px 12px;border-radius:8px;border:none;background:var(--purple);color:#fff;font-size:18px;font-weight:700;cursor:pointer;margin-top:1px;font-family:inherit;}
.btn-apply:hover{filter:brightness(1.08);}

.sidebar-footer{margin-top:auto;padding-top:13px;border-top:1px solid var(--border);font-size:15.5px;color:var(--text-dim);}
.sidebar-footer .sf-label{font-weight:700;color:var(--text);}
.sidebar-footer .sf-note{font-size:12px;color:#9aa0bd;}
.sidebar-footer div{margin-bottom:8px;}
.sidebar-footer div{padding:8px 0;border-bottom:1px solid #eee;}
.sidebar-footer div:last-child{border-bottom:none;}
.sidebar-snapshot{margin-top:14px;padding-top:14px;border-top:1px solid var(--border);flex:1 1 auto;display:flex;flex-direction:column;gap:9px;min-height:0;}
.snap-title{font-weight:800;font-size:17.5px;color:var(--text);margin-bottom:2px;}
.snap-row{background:var(--panel-2);border:1px solid var(--border);border-radius:var(--radius-sm);padding:9px 11px;display:flex;flex-direction:column;gap:3px;}
.snap-label{font-size:14.4px;font-weight:700;color:var(--text-dim);text-transform:uppercase;letter-spacing:.03em;}
.snap-value{font-size:20px;font-weight:800;color:var(--text);}
.legacy-hidden{display:none !important;}

/* ---------- Main ---------- */
.main{padding:16px 20px 16px;display:flex;flex-direction:column;gap:12px;min-width:0;height:100%;min-height:0;}
.title-block h1{margin:0;font-size:40px;font-weight:800;letter-spacing:-.01em;color:var(--text);line-height:1.1;}
.title-block .subtitle{margin:3px 0 0;color:var(--text);font-weight:600;font-size:18px;}
.topbar-links{display:flex;gap:8px;flex-wrap:wrap;}
.topbar-link{display:flex;align-items:center;gap:6px;background:var(--panel);border:1px solid var(--border);border-radius:20px;padding:8px 14px;font-size:16px;font-weight:700;color:var(--text);cursor:pointer;}
.topbar-link:hover{background:var(--panel-2);color:var(--text);border-color:var(--purple);}
.topbar-link .tl-icon{font-size:15px;}
.modal-overlay{position:fixed;inset:0;background:rgba(24,28,50,.45);z-index:2000;display:flex;align-items:center;justify-content:center;}
.modal-box{background:#fff;border-radius:var(--radius);padding:22px 24px;max-width:380px;width:90%;box-shadow:0 20px 60px rgba(20,20,50,.25);}
.modal-box h3{margin:0 0 10px;font-size:20px;font-weight:800;color:var(--text);}
.modal-box p{margin:0 0 8px;font-size:16.2px;line-height:1.5;color:var(--text-dim);}
/* Larger popup window for About / Help & Guide / Contact — roughly 3x the
   original modal-box footprint (~380px wide) in both width and text. */
.modal-box-lg{max-width:1140px;width:94%;padding:66px 72px;}
.modal-box-lg h3{font-size:42px;margin-bottom:26px;}
.modal-box-lg .modal-body{font-size:20px;line-height:1.75;max-height:70vh;overflow-y:auto;padding-right:10px;}
.modal-box-lg .modal-body p{margin:0 0 16px;color:var(--text-dim);}
.modal-box-lg .modal-body h4{margin:24px 0 10px;font-size:24px;font-weight:800;color:var(--text);}
.modal-box-lg .modal-body ul{margin:0 0 16px;padding-left:24px;}
.modal-box-lg .modal-body li{margin-bottom:6px;color:var(--text-dim);}
.modal-box-lg .modal-body strong{color:var(--text);}
.modal-close{margin-top:10px;padding:7px 16px;border-radius:8px;border:none;background:var(--purple);color:#fff;font-size:15.6px;font-weight:700;cursor:pointer;font-family:inherit;}
.modal-close:hover{filter:brightness(1.08);}

/* About DEWS: slightly smaller heading than the other topbar modals */
.modal-about h3{font-size:30px;}

/* Disclaimer paragraph inside About: smaller, ash/grey text */
.disclaimer-text{font-size:14px !important;color:#8a8f9c !important;}

/* Help modal: force every element to share the same font family/weight so
   headings, bold labels and body text all read as one consistent typeface. */
.modal-help .modal-body,
.modal-help .modal-body h4,
.modal-help .modal-body p,
.modal-help .modal-body strong,
.modal-help .modal-body li{
  font-family:'Segoe UI';
  font-weight:400;
  font-size:15px;
}
.modal-help .modal-body h4{font-size:20px;}
.modal-help .modal-body strong{font-weight:600;}
.top-badges{display:flex;gap:10px;flex-wrap:wrap;}
.badge{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius-sm);padding:8px 14px;min-width:130px;display:flex;align-items:center;gap:9px;}
.badge-icon{width:30px;height:30px;border-radius:8px;background:var(--purple-light);color:var(--purple);display:flex;align-items:center;justify-content:center;font-size:17.5px;flex:none;}
.badge-text{display:flex;flex-direction:column;}
.badge-label{font-size:15px;color:var(--text-dim);text-transform:uppercase;letter-spacing:.05em;margin-bottom:2px;}
.badge-value{font-size:16.9px;font-weight:700;color:var(--text);}

/* ---------- KPI cards ---------- */
.kpi-card{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);padding:12px 14px;min-width:0;display:flex;flex-direction:column;gap:2px;overflow:hidden;}
.kpi-top{display:flex;align-items:center;gap:10px;margin-bottom:6px;flex-wrap:wrap;}
.kpi-icon-circle{width:32px;height:32px;border-radius:9px;display:flex;align-items:center;justify-content:center;font-size:18.8px;flex:none;}
.kpi-blue .kpi-icon-circle{background:var(--blue-light);color:var(--blue);}
.kpi-red .kpi-icon-circle{background:var(--orange-light);color:var(--orange);}
.kpi-green .kpi-icon-circle{background:var(--green-light);color:var(--green);}
.kpi-amber .kpi-icon-circle{background:var(--purple-light);color:var(--purple);}
.kpi-label{font-size:14.5px;font-weight:700;color:#000;}
.kpi-sub-label{font-size:12.5px;color:#000;}
.kpi-value{font-size:26px;font-weight:800;color:#000;}

/* Risk-level tile: color follows the same legend as the map */
.kpi-value.risk-low{color:var(--green);}
.kpi-value.risk-moderate{color:#b8a600;} /* darker than raw yellow so it stays readable on white */
.kpi-value.risk-high{color:var(--orange);}
.kpi-value.risk-severe{color:var(--red);}

.kpi-sub{font-size:13px;color:#000;font-weight:600;margin-top:1px;}
/* Change-over-last-week tile: increasing=red, decreasing=green, stable=yellow */
.kpi-sub.trend-up,.kpi-value.trend-up{color:var(--red);}
.kpi-sub.trend-down,.kpi-value.trend-down{color:var(--green);}
.kpi-sub.trend-flat,.kpi-value.trend-flat{color:#b8a600;}

/* Single-row KPI strip: Expected Cases / Risk Level / Change / Forecast Week
   side by side — auto-wraps to 2 rows instead of squeezing/overlapping text
   once tiles would drop below a legible width (e.g. browser zoom-in). */
.kpi-grid-4up{display:grid;grid-template-columns:1fr 1fr;grid-template-rows:1fr 1fr;gap:10px;flex:0 0 auto;}
.kpi-grid-4up .kpi-card{height:110px;justify-content:space-between;}
.kpi-mini{padding:12px 14px;gap:2px;min-width:0;}
.kpi-mini .kpi-top{margin-bottom:6px;gap:8px;}
.kpi-mini .kpi-icon-circle{width:26px;height:26px;font-size:15px;border-radius:7px;}
.kpi-mini .kpi-label{font-size:13.5px;color:#000;}
.kpi-mini .kpi-sub-label{font-size:12px;color:#000;}
.kpi-mini .kpi-value{font-size:24px;color:#000;white-space:nowrap;}
/* Re-assert risk/trend text colors — otherwise the rule above (same
   specificity, but later in the file) overrides them back to black. */
.kpi-mini .kpi-value.risk-low{color:var(--green);}
.kpi-mini .kpi-value.risk-moderate{color:#b8a600;}
.kpi-mini .kpi-value.risk-high{color:var(--orange);}
.kpi-mini .kpi-value.risk-severe{color:var(--red);}
.kpi-mini .kpi-value.trend-up{color:var(--red);}
.kpi-mini .kpi-value.trend-down{color:var(--green);}
.kpi-mini .kpi-value.trend-flat{color:#b8a600;}
.kpi-mini .kpi-sub{font-size:12.5px;color:#000;}

/* ---------- content grid: map is dominant, right column stacks KPI grid + trend.
   Both columns share one explicit height (set via JS to match viewport) so
   there's no leftover empty space under the shorter column. ---------- */
.content-grid{display:grid;grid-template-columns:1.65fr 1fr;gap:14px;flex:1;min-height:0;}
.content-grid > *{min-width:0;height:100%;}
.panel{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);padding:13px 14px;min-width:0;}
.map-panel{display:flex;flex-direction:column;min-height:0;}
.panel-title{font-size:17px;font-weight:800;margin:0 0 2px;color:var(--text);}
.panel-sub{font-size:13.5px;color:var(--text-dim);margin:0 0 6px;}
.panel-header{display:flex;align-items:flex-start;justify-content:space-between;flex-wrap:wrap;gap:8px;margin-bottom:4px;}

/* Map fills the entire map-panel height (matches right column, no fixed px) —
   tiles fetch a light basemap showing the surrounding region so Kerala isn't
   floating in blank space */
/* .map-stage fills the panel and centers #map, which JS sizes in px to
   Kerala's real aspect ratio — this is what actually eliminates the
   leftover grey space (a plain flex/percentage box can't fix an aspect
   mismatch between a wide panel and Kerala's tall, narrow shape). */
.map-stage{flex:1;min-height:0;display:flex;align-items:center;justify-content:center;overflow:hidden;}
#map{width:100%;height:100%;background:#e7ebf5;border-radius:var(--radius-sm);position:relative;overflow:hidden;}
/* Fallback backdrop used only if the basemap tiles fail to load (no
   internet / blocked CDN) — a lightweight drawn silhouette suggesting the
   surrounding land/coastline so the area around Kerala doesn't read as an
   empty void, without depending on any network request. Hidden by default;
   always painted first as a backdrop; real tiles render on top and simply
   cover it wherever they load successfully. */
/* (offline tile-fallback backdrop removed — neighbouring states are now
   drawn from real local geojson data instead, see dashboard.js) */
/* Leaflet raster tiles are positioned with sub-pixel CSS transforms, which
   on some browsers/zoom levels leaves faint 1px seams between adjacent
   tiles (visible as a light grid over the basemap). Forcing each tile image
   to round to whole pixels and hiding the tiny overlap removes the seams. */
#map .leaflet-tile{image-rendering:-webkit-optimize-contrast;outline:1px solid transparent;}
#map .leaflet-tile-container{filter:none;}
#map .leaflet-tile-pane{will-change:transform;}
/* Nudge every tile 1px larger than its box and center it — hides the seam
   between adjacent tiles regardless of sub-pixel rounding differences. */
#map .leaflet-tile-container img{width:calc(100% + 2px) !important;height:calc(100% + 2px) !important;margin-left:-1px !important;margin-top:-1px !important;max-width:none !important;}
.map-controls{position:absolute;top:10px;left:10px;z-index:500;display:flex;flex-direction:column;gap:6px;}
.map-btn{width:28px;height:28px;background:#fff;border:1px solid var(--border);border-radius:8px;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text);font-size:17.5px;box-shadow:0 1px 3px rgba(20,20,50,.08);}
.map-btn:hover{background:var(--panel-2);}
.map-loading{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--text-dim);font-size:15px;text-align:center;padding:0 20px;}

/* Legend now lives in the sidebar, before "Last Updated" */
.sidebar-legend{margin-top:14px;background:var(--panel-2);border:1px solid var(--border);border-radius:var(--radius-sm);padding:12px 13px;font-size:14px;}
.sidebar-legend .lg-title{font-weight:800;margin-bottom:7px;font-size:15px;color:var(--text);}
.sidebar-legend .lg-row{display:flex;align-items:center;gap:8px;margin:5px 0;color:var(--text-dim);font-size:14.5px;}
.sidebar-legend .sw{width:11px;height:11px;border-radius:50%;flex:none;}
.sidebar{margin-bottom:18px;}
.leaflet-tooltip.district-tip{background:#fff;border:1px solid var(--border);color:var(--text);border-radius:8px;padding:8px 10px;font-size:15px;box-shadow:0 6px 20px rgba(20,20,50,.15);}
.district-tip b{font-size:16.2px;}
.tip-badge{display:inline-block;margin-left:6px;padding:1px 7px;border-radius:20px;font-size:14px;font-weight:700;}

.right-col{display:grid;grid-template-rows:auto 1fr;gap:12px;min-height:0;}
.trend-panel-sm{display:flex;flex-direction:column;min-height:0;height:100%;}
.trend-select{background:#fff;border:1px solid var(--border);color:var(--text);border-radius:8px;padding:6px 10px;font-size:14.4px;font-family:inherit;}
/* Fills remaining right-column space (bounded by content-grid's fixed
   height), while smaller dots (in dashboard.js) keep it visually calm */
.chart-wrap{position:relative;flex:1;min-height:160px;}
.chart-wrap svg{width:100%;height:100%;display:block;}

/* ---------- Timeline: full-width row, starts at the page's left edge, sits
   directly below the sidebar+main row instead of being squeezed into the
   right column ---------- */
/* Starts exactly where .main's content starts (sidebar width + main's own
   left padding) instead of the page's left edge, so it lines up with the
   panels above it and never sits underneath/against the sidebar. */
.timeline-panel-full{margin-top:12px;margin-bottom:12px;margin-left:20px;margin-right:20px;width:calc(100% - 40px);align-self:stretch;}
.timeline-panel{flex:0 0 auto;}
.timeline-wrap{display:flex;align-items:center;gap:8px;min-width:0;min-height:78px;}
.timeline-nav{width:26px;height:26px;flex:none;border-radius:50%;background:#fff;border:1px solid var(--border);color:var(--text);font-size:15px;display:flex;align-items:center;justify-content:center;cursor:pointer;}
.timeline-nav:hover{background:var(--panel-2);}
.timeline-play-btn{flex:none;height:26px;border-radius:20px;background:var(--purple);border:1px solid var(--purple);color:#fff;font-size:14.4px;font-weight:700;display:flex;align-items:center;gap:6px;padding:0 12px;cursor:pointer;font-family:inherit;}
.timeline-play-btn:hover{filter:brightness(1.08);}
.timeline-play-btn .tpb-icon{font-size:13px;}
.timeline-track{flex:1;position:relative;display:flex;gap:0;overflow-x:auto;padding:6px 4px 2px;min-width:0;}
.timeline-node-col{flex:0 0 100px;display:flex;flex-direction:column;align-items:center;position:relative;cursor:pointer;padding:8px 3px;border-radius:9px;}
.timeline-node-col:hover{background:var(--panel-2);}
.timeline-node-col.active{background:var(--purple-light);}
.timeline-line{position:absolute;top:9px;left:-50px;right:50px;height:2px;background:var(--border);z-index:0;}
.timeline-node-col:first-child .timeline-line{left:50%;}
.timeline-line.filled{background:var(--purple);}
.timeline-dot{width:9px;height:9px;border-radius:50%;background:var(--border);border:2px solid var(--panel);z-index:1;margin-bottom:5px;}
.timeline-node-col.active .timeline-dot{background:var(--purple);box-shadow:0 0 0 3px rgba(67,56,202,.18);}
.timeline-node-col.past .timeline-dot{background:#c7c2f5;}
.ti-week{font-size:16px;font-weight:700;color:var(--text);}
.timeline-node-col.active .ti-week{color:var(--purple);}
.ti-range{font-size:12.5px;color:var(--text-dim);margin:2px 0;display:flex;flex-direction:column;align-items:center;line-height:1.25;}
.ti-range-date{white-space:nowrap;}
.ti-range-dash{font-size:11px;}
.ti-cases{font-size:16.9px;font-weight:800;color:var(--text);margin-top:1px;}
.timeline-node-col.active .ti-cases{color:var(--purple);}

.footer-note-full{margin-top:8px;margin-left:20px;margin-right:20px;margin-bottom:15px;}
.footer-note{font-size:13.5px;color:var(--text-dim);display:flex;justify-content:space-between;padding-top:2px;flex-wrap:wrap;gap:6px;flex:0 0 auto;}

.alert-box{background:var(--red-light);border:1px solid #fecaca;border-radius:var(--radius-sm);padding:12px;font-size:16.2px;color:#7f1d1d;margin-top:12px;}
.alert-box .alert-title{display:flex;align-items:center;gap:6px;font-weight:800;color:#7f1d1d;margin-bottom:3px;font-size:16.9px;}
.sample-badge{font-size:15px;color:#854d0e;background:var(--yellow-light);border:1px solid #fde68a;border-radius:8px;padding:8px 9px;margin-top:12px;}

@media (max-width:1400px){
  .content-grid{grid-template-columns:1fr 1fr;}
}

@media (max-width:1150px){
  .content-grid{grid-template-columns:1fr;height:auto;}
  .app{grid-template-columns:1fr;}
}
