/* ============================================================
   Bangladesh Air Quality Atlas — FIXED single-page dashboard
   100vh, no scrollbars. Left = analytics, Right = full map.
   Same visual design system as the BDHS Health Atlas.
   ============================================================ */
:root{
  --bg:#eef2f7; --panel:#ffffff; --ink:#1b2a41; --muted:#6b7a90;
  --line:#e6ecf5; --brand:#7209b7; --brand2:#0077b6; --accent:#e63946;
  --good:#2a9d8f; --warn:#e9a020; --shadow:0 6px 20px rgba(23,42,73,.08);
  --toph:54px; --radius:14px;
}
*{box-sizing:border-box}
html,body{margin:0;height:100%;overflow:hidden}          /* NO SCROLL */
/* Hardened stack: if the Google Fonts request is blocked or slow, this falls
   back to a real UI sans on every OS instead of a symbol/serif substitute.
   The trailing emoji faces keep any residual ₂ / → / › glyphs rendering. */
body{font-family:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",
  Arial,"Noto Sans","Liberation Sans",sans-serif,"Segoe UI Symbol","Apple Color Emoji","Segoe UI Emoji";
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  font-variant-ligatures:none;color:var(--ink);
  background:radial-gradient(1200px 500px at 100% -10%, #e7dcff55, transparent),
             radial-gradient(1000px 500px at -10% 110%, #cdeeff55, transparent), var(--bg);
  display:flex;flex-direction:column}

/* ---- top bar ---- */
.topbar{height:var(--toph);flex:0 0 auto;display:flex;justify-content:space-between;align-items:center;
  gap:14px;padding:0 18px;background:linear-gradient(90deg,#2a0a52,#5a189a 45%,#0077b6);color:#fff;
  box-shadow:var(--shadow);z-index:1000}
.brand{display:flex;align-items:center;gap:12px;min-width:0}
.logo{width:36px;height:36px;border-radius:10px;display:grid;place-items:center;font-weight:800;
  background:#fff;color:var(--brand);font-size:14px}
.topbar h1{font-size:16px;margin:0;font-weight:800;white-space:nowrap}
.topbar p{margin:1px 0 0;font-size:11px;opacity:.8;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.topbar-actions{display:flex;gap:8px;align-items:center;flex:0 0 auto}
.topbar-actions button,.topbar-actions .ext{background:rgba(255,255,255,.16);color:#fff;border:0;
  padding:7px 12px;border-radius:9px;font-size:12.5px;font-weight:600;cursor:pointer;text-decoration:none;white-space:nowrap}
.topbar-actions button:hover,.topbar-actions .ext:hover{background:rgba(255,255,255,.3)}
.status-badge{display:flex;align-items:center;gap:6px;font-size:11.5px;background:rgba(255,255,255,.15);
  padding:6px 10px;border-radius:20px;cursor:pointer;color:#fff;text-decoration:none}
.status-badge:hover{background:rgba(255,255,255,.28)}
.status-badge .d{width:9px;height:9px;border-radius:50%;background:#ffd166}
.status-badge.live .d{background:#4ade80}

/* ---- main split ---- */
.stage{flex:1 1 auto;min-height:0;display:grid;grid-template-columns:57% 43%;gap:12px;padding:12px}
.panel{background:var(--panel);border-radius:var(--radius);box-shadow:var(--shadow);min-height:0;overflow:hidden}
.left{display:flex;flex-direction:column;padding:12px;gap:10px;min-height:0}
.right{display:flex;flex-direction:column;position:relative;min-height:0}

/* ---- filter strip ----
   A 4-column grid on the same 10px rhythm as the KPI cards directly below,
   so the two rows of controls line up with the four flashcards instead of
   wrapping into a ragged flex row. */
.filters{flex:0 0 auto;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  gap:9px 10px;align-items:end;padding:11px 12px;
  background:linear-gradient(180deg,#fbfcfe,#f4f7fc);
  border:1px solid var(--line);border-radius:12px}
.field{display:flex;flex-direction:column;gap:5px;min-width:0}
.field label{font-size:9.5px;font-weight:800;text-transform:uppercase;letter-spacing:.6px;
  color:#8996a8;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding-left:1px}

/* native select chrome replaced with a consistent control */
.field select{
  width:100%;max-width:none;height:35px;
  border:1px solid #dbe3ee;background-color:#fff;border-radius:9px;
  padding:0 30px 0 11px;font-size:13px;font-weight:500;font-family:inherit;
  color:var(--ink);cursor:pointer;text-overflow:ellipsis;
  appearance:none;-webkit-appearance:none;-moz-appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1.4 1.4 6 6 10.6 1.4' fill='none' stroke='%237b8798' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 11px center;background-size:11px 7px;
  transition:border-color .15s,box-shadow .15s,background-color .15s}
.field select:hover{border-color:#bcccdf;background-color:#fdfdff}
.field select:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px rgba(114,9,183,.14)}
.field select:disabled{background-color:#f3f5f9;color:#aeb8c7;cursor:not-allowed;border-color:#e6ecf5}
/* the pollutant picker is the primary control — give it presence */
.field.var select{font-weight:700;color:var(--brand);border-color:#d6c2f2;background-color:#faf7ff}
.field.var select:hover{border-color:#c4a9ec}
.field.var label{color:var(--brand);opacity:.75}
/* grouped lists (all 64 districts / all 600 upazilas) stay scannable */
.field select optgroup{font-weight:800;color:var(--brand);background:#f7f4fd;font-size:12px}
.field select option{font-weight:500;color:var(--ink);background:#fff;font-size:13px}
.field select option:disabled{color:#b3bcc9}

.year-wrap{display:flex;align-items:center;gap:8px}
.pill{background:var(--brand);color:#fff;padding:1px 8px;border-radius:20px;font-size:11px}
.mini{flex:1 1 auto;height:35px;background:linear-gradient(135deg,var(--brand),var(--brand2));
  border:0;color:#fff;border-radius:9px;padding:0 14px;font-weight:700;font-size:12.5px;
  font-family:inherit;cursor:pointer;white-space:nowrap;
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  box-shadow:0 2px 8px rgba(114,9,183,.24);transition:filter .15s,box-shadow .15s}
.mini:hover{filter:brightness(1.09);box-shadow:0 3px 12px rgba(114,9,183,.32)}
.mini:active{filter:brightness(.96)}
.mini-icon{flex:0 0 auto;width:35px;padding:0}

/* ---- inline SVG icon system --------------------------------------------
   Replaces the old emoji/dingbat glyphs (⇄ ✕ ⤢ 🏷). Those depended on an
   emoji or symbol font being present and rendered as tofu / mismatched
   colour glyphs on machines without one. SVG renders identically anywhere. */
.ico{width:14px;height:14px;flex:0 0 auto;fill:none;stroke:currentColor;
  stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.ico-ink{stroke:var(--brand);vertical-align:-2px;margin-right:6px}

/* ---- KPI flashcards ---- */
/* same 4 columns / same gap as .filters above, so the two strips align */
.kpi-row{flex:0 0 auto;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}
.kpi{border-radius:12px;padding:9px 11px;color:#fff;position:relative;overflow:hidden;box-shadow:0 3px 10px rgba(23,42,73,.12)}
.kpi.c0{background:linear-gradient(135deg,#e63946,#b5179e)}
.kpi.c1{background:linear-gradient(135deg,#7209b7,#560bad)}
.kpi.c2{background:linear-gradient(135deg,#0077b6,#0096c7)}
.kpi.c3{background:linear-gradient(135deg,#2a9d8f,#1b9aaa)}
.kpi-name{font-size:10.5px;font-weight:600;opacity:.9;text-transform:uppercase;letter-spacing:.3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.kpi-val{font-size:24px;font-weight:800;line-height:1.15}
.kpi-val span{font-size:12px;font-weight:600;opacity:.85}
.kpi-delta{font-size:10.5px;font-weight:700;opacity:.95}
.kpi-flag{position:absolute;top:8px;right:9px;width:9px;height:9px;border-radius:50%;border:1.5px solid rgba(255,255,255,.7)}

/* ---- Satellite Column Index (SCI) on the KPI cards ----
   Index is the headline number; the raw column value drops to the
   delta line so it stays verifiable against the source CSV. */
.kpi-idx .kpi-val{font-size:27px;letter-spacing:-.5px}
.kpi-scale{font-size:11px;font-weight:700;opacity:.75;letter-spacing:.4px}
.kpi-band{display:inline-flex;align-items:center;gap:5px;margin-top:1px;
  font-size:11px;font-weight:800;letter-spacing:.2px}
.kpi-dot{width:9px;height:9px;border-radius:50%;box-shadow:0 0 0 2px rgba(255,255,255,.55)}
.kpi-idx .kpi-delta{opacity:.82;font-weight:600}

/* ---- narrative ---- */
.narrative{flex:0 0 auto;background:#f7f9fc;border:1px solid var(--line);border-left:4px solid var(--brand);
  border-radius:9px;padding:7px 11px;font-size:12.5px;line-height:1.45;
  overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.muted{color:var(--muted)}
.nar-idx{display:inline-block;padding:1px 8px;border-radius:20px;font-size:11px;font-weight:800;
  letter-spacing:.2px;vertical-align:1px}
.nar-cov{font-weight:700}
.nar-caveat{font-style:italic}

/* ---- fixed 3×2 chart grid — fills the panel, NO scroll ---- */
.cgrid{flex:1 1 auto;min-height:0;display:grid;grid-template-columns:1fr 1fr;grid-template-rows:repeat(3,1fr);gap:10px}
.card{background:#fff;border:1px solid var(--line);border-radius:12px;padding:8px 10px;
  box-shadow:0 2px 8px rgba(23,42,73,.05);display:flex;flex-direction:column;min-width:0;min-height:0}
.card-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:4px;gap:8px;flex:0 0 auto}
.card-head h3{margin:0;font-size:12px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.head-opts{display:flex;gap:5px;align-items:center;font-size:11px;color:var(--muted)}
.head-opts select{border:1px solid #dbe3ee;border-radius:7px;padding:3px 22px 3px 8px;font-size:11px;
  font-family:inherit;color:var(--ink);background-color:#fff;cursor:pointer;max-width:120px;
  appearance:none;-webkit-appearance:none;-moz-appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 12 8'%3E%3Cpath d='M1.4 1.4 6 6 10.6 1.4' fill='none' stroke='%237b8798' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 7px center;background-size:9px 6px}
.head-opts select:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 2px rgba(114,9,183,.13)}
.ch{position:relative;flex:1 1 auto;min-height:0}
.ch canvas{position:absolute;inset:0}

/* ---- data table ---- */
.dtable{width:100%;border-collapse:collapse;font-size:12px}
.dtable th,.dtable td{padding:6px 9px;border-bottom:1px solid var(--line);text-align:left}
.dtable th{position:sticky;top:0;background:#f5f7fb;font-weight:700;color:var(--muted);font-size:10.5px;
  text-transform:uppercase;letter-spacing:.3px}
.dtable th.sortable{cursor:pointer;user-select:none}.dtable th.sortable:hover{color:var(--brand)}
.dtable td.num{text-align:right;font-variant-numeric:tabular-nums;font-weight:600}
.dtable tbody tr:hover{background:#f7f9fd}
.rel-dot{display:inline-block;width:9px;height:9px;border-radius:50%;margin-right:5px}

/* ---- map ---- */
#map{flex:1 1 auto;min-height:0;width:100%;border-radius:var(--radius);z-index:1}
.map-bar{position:absolute;top:10px;left:10px;right:10px;z-index:500;display:flex;justify-content:space-between;
  align-items:flex-start;gap:8px;pointer-events:none}
.breadcrumb{display:flex;flex-wrap:wrap;align-items:center;gap:3px;background:rgba(255,255,255,.94);
  border:1px solid var(--line);border-radius:20px;padding:5px 11px;font-size:12px;box-shadow:var(--shadow);pointer-events:auto}
/* crumbs are <button>s now (keyboard reachable) — strip the native chrome */
.crumb{cursor:pointer;color:var(--brand2);font-weight:600;font-family:inherit;font-size:inherit;
  background:none;border:0;padding:0;line-height:inherit}
.crumb:hover{text-decoration:underline}
.crumb.current{color:var(--ink);cursor:default}
.crumb-sep{color:var(--muted)}
/* ---- map control cluster (top-right of the map) ----------------------
   One glass card rather than three loose pills, using the same radius,
   border and shadow language as the filter card on the left so the two
   panels read as a pair. Inside: a context strip, a segmented level
   picker (all options visible at once), and icon toggles. -------------- */
.map-right{display:flex;flex-direction:column;gap:7px;align-items:flex-end;pointer-events:auto}
.mapctl{min-width:248px;border-radius:14px;overflow:hidden;
  border:1px solid rgba(255,255,255,.75);
  background:rgba(255,255,255,.86);
  -webkit-backdrop-filter:blur(14px) saturate(170%);backdrop-filter:blur(14px) saturate(170%);
  box-shadow:0 10px 30px rgba(23,42,73,.20)}

/* context strip — what you are looking at, right now */
.mapctl-head{display:flex;align-items:center;justify-content:space-between;gap:8px;
  padding:7px 11px;background:linear-gradient(90deg,var(--brand),var(--brand2));color:#fff}
.mapctl-period{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:800;
  letter-spacing:.2px;white-space:nowrap}
.mapctl-period svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}
.mapctl-scope{font-size:10.5px;font-weight:600;opacity:.92;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;text-align:right;min-width:0}

/* two equal actions — the map itself follows the left-hand selection, so
   there is nothing else to configure here */
.mapctl-body{padding:9px 10px 10px;display:grid;grid-template-columns:1fr 1fr;gap:6px}
.ico-btn{height:30px;display:inline-flex;align-items:center;justify-content:center;gap:6px;
  padding:0 10px;border:1px solid #dbe3ee;border-radius:9px;background:#fff;
  font-family:inherit;font-size:10.5px;font-weight:800;color:var(--ink);cursor:pointer;
  transition:background .15s,border-color .15s,color .15s,box-shadow .15s,transform .12s}
.ico-btn svg{width:13px;height:13px;flex:0 0 auto;fill:none;stroke:currentColor;
  stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.ico-btn svg circle.dot{fill:currentColor;stroke:none}
.ico-btn:hover{border-color:#bcccdf;background:#fbfcff;color:var(--brand)}
.ico-btn:active{transform:translateY(1px)}
.ico-btn:focus-visible{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px rgba(114,9,183,.2)}
.ico-btn.is-on{background:linear-gradient(135deg,var(--brand),var(--brand2));
  border-color:transparent;color:#fff;box-shadow:0 3px 10px rgba(114,9,183,.3)}
.ico-btn.is-on:hover{filter:brightness(1.08);color:#fff}
.ico-btn:disabled{opacity:.4;cursor:not-allowed;transform:none}
.ico-btn.icon-only{padding:0 9px}

@media (max-width:1200px){
  .mapctl{min-width:214px}
  .ico-btn{font-size:9.5px;padding:0 8px}
}
/* glassmorphism info flashcard */
.map-info{background:rgba(255,255,255,.62);backdrop-filter:blur(10px) saturate(160%);
  -webkit-backdrop-filter:blur(10px) saturate(160%);border:1px solid rgba(255,255,255,.6);
  padding:11px 13px;border-radius:14px;box-shadow:0 8px 26px rgba(23,42,73,.18);font-size:12px;
  line-height:1.5;max-width:230px}
.map-info .gi-name{font-size:14px;font-weight:800;color:#1b2a41;margin-bottom:2px}
.map-info .gi-val{font-size:26px;font-weight:800;line-height:1.1;background:linear-gradient(90deg,var(--brand),var(--brand2));
  -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.map-info .gi-val small{font-size:13px;-webkit-text-fill-color:initial;color:var(--muted)}
/* index-first hover card */
.map-info .gi-idx{display:flex;align-items:center;gap:9px;margin:4px 0 2px}
.map-info .gi-idx-n{min-width:46px;padding:3px 8px;border-radius:9px;text-align:center;
  font-size:20px;font-weight:800;line-height:1.15}
.map-info .gi-idx-b{display:flex;flex-direction:column;font-size:12.5px;font-weight:800;color:#1b2a41;line-height:1.25}
.map-info .gi-idx-b small{font-size:9.5px;font-weight:700;color:var(--muted);letter-spacing:.4px}
.map-info .gi-raw{font-size:13px;font-weight:700;color:#3f4a5c}
.map-info .gi-raw small{font-weight:600;color:var(--muted)}
.map-info .gi-rel{display:inline-flex;align-items:center;gap:5px;font-weight:600;margin-top:3px}
.map-info .rel-dot{width:9px;height:9px}
.map-info .gi-sub{color:var(--muted);margin-top:2px}

/* ---- map labels ------------------------------------------------------
   Rendered as divIcon markers rather than Leaflet tooltips, because the
   placement pass in map.js needs to decide which ones survive. Each label
   is centred on its region, so the marker is shifted by half its own size
   with a transform — its width isn't known until it is in the DOM. ------ */
.map-label{background:rgba(255,255,255,.9);border:1px solid rgba(255,255,255,.85);
  border-radius:9px;padding:3px 7px 4px;
  box-shadow:0 2px 8px rgba(23,42,73,.18);
  white-space:nowrap;text-align:center;line-height:1.2;
  width:max-content;transform:translate(-50%,-50%);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  pointer-events:none}
.map-label .ml-n{display:block;font-size:10px;font-weight:700;color:#33415c;
  letter-spacing:.1px;max-width:150px;overflow:hidden;text-overflow:ellipsis}
.map-label .ml-v{display:block;font-size:11.5px;font-weight:800;color:var(--brand);
  letter-spacing:.2px}
.map-label.is-hi{background:#fff;border-color:var(--brand);
  box-shadow:0 3px 12px rgba(114,9,183,.35)}
.map-label.is-hi .ml-n{color:#1b2a41}
/* Leaflet gives divIcons a default box — strip it so only our chrome shows */
.leaflet-div-icon.map-label{background:rgba(255,255,255,.9);border:1px solid rgba(255,255,255,.85)}
.map-legend{background:#fff;padding:8px 10px;border-radius:10px;box-shadow:var(--shadow);font-size:10.5px;line-height:1.6}
.map-legend .legend-title{font-weight:700;margin-bottom:3px;font-size:11px}
.map-legend i{width:13px;height:13px;display:inline-block;margin-right:5px;border-radius:3px;vertical-align:-2px}
.map-legend .legend-note{margin-top:4px;color:var(--muted);border-top:1px solid var(--line);padding-top:4px}
/* SCI ladder: swatch · index range · band name · raw column window */
.map-legend .legend-title small{display:block;font-weight:600;color:var(--muted);font-size:9.5px;letter-spacing:.3px}
.map-legend .lg-row{display:grid;grid-template-columns:18px 46px 1fr auto;align-items:center;
  gap:2px;line-height:1.7}
.map-legend .lg-row b{font-weight:800}
.map-legend .lg-row span{color:#42506a;padding-right:8px}
.map-legend .lg-row em{font-style:normal;color:var(--muted);font-variant-numeric:tabular-nums}
.map-legend .legend-warn{color:#a04a00}
.map-legend .legend-warn a{color:var(--brand);font-weight:700}
/* raw value beside the index inside a permanent map label */
.map-label .ml-raw{font-weight:600;color:#5d6982;font-size:9.5px}

/* ---- compare modal ---- */
.cmodal{position:fixed;inset:0;background:rgba(20,10,45,.45);backdrop-filter:blur(3px);
  display:flex;align-items:center;justify-content:center;z-index:3000}
.cmodal-box{background:#fff;width:min(860px,94vw);max-height:92vh;overflow:auto;border-radius:16px;
  box-shadow:0 24px 60px rgba(0,0,0,.35);padding:18px 20px;display:flex;flex-direction:column;gap:12px}
.cmodal-head{display:flex;justify-content:space-between;align-items:center}
.cmodal-head h3{margin:0;font-size:16px;font-weight:800}
.cmodal-controls{display:flex;align-items:flex-end;gap:14px;flex-wrap:wrap}
.cmodal-controls .field select{max-width:230px}
.cmp-vs{color:var(--muted);font-weight:700;padding-bottom:7px}
.var-checks{display:flex;gap:7px;flex-wrap:wrap}
.var-check{display:flex;align-items:center;gap:6px;font-size:12px;font-weight:700;cursor:pointer;
  padding:6px 10px;border-radius:9px;border:1.5px solid var(--line);background:#fff;user-select:none}
.var-check input{margin:0;accent-color:currentColor}
.var-check .sw{width:10px;height:10px;border-radius:50%;display:inline-block;flex:0 0 auto}
.var-check.on{background:#f7f4fd}
.cmp-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px}
.cmp-kpi{border-radius:12px;padding:12px 14px;color:#fff}
.cmp-kpi.a{background:linear-gradient(135deg,#7209b7,#560bad)}
.cmp-kpi.b{background:linear-gradient(135deg,#0077b6,#0096c7)}
.cmp-kpi.c{background:linear-gradient(135deg,#e63946,#b5179e)}
.cmp-kpi.d{background:linear-gradient(135deg,#2a9d8f,#1b9aaa)}
.cmp-kpi .n{font-size:12px;font-weight:600;opacity:.9}
.cmp-kpi .v{font-size:30px;font-weight:800;line-height:1.1}
.cmp-kpi .v span{font-size:14px;opacity:.85}
.cmp-kpi .d{font-size:11.5px;opacity:.95;margin-top:2px}
.cmp-chart{position:relative;height:300px}
.cmp-chart canvas{position:absolute;inset:0}

/* ---- status / loading overlay -----------------------------------------
   The first visit has real work to do, so instead of a bare spinner this
   says what is happening and how far along it is. Same card language as
   the rest of the app. ------------------------------------------------- */
.status{position:fixed;inset:0;z-index:2000;display:flex;align-items:center;justify-content:center;padding:24px;
  background:radial-gradient(900px 460px at 50% -10%, #e7dcff88, transparent), rgba(238,242,247,.96);
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}
.status-card{width:min(430px,100%);background:#fff;border:1px solid var(--line);border-radius:18px;
  box-shadow:0 22px 60px rgba(23,42,73,.20);padding:26px 26px 22px;text-align:left}

.status-brand{display:flex;align-items:center;gap:11px;margin-bottom:18px}
.status-logo{width:34px;height:34px;border-radius:10px;display:grid;place-items:center;
  background:linear-gradient(135deg,var(--brand),var(--brand2));color:#fff;font-weight:800;font-size:13px;
  box-shadow:0 4px 12px rgba(114,9,183,.3)}
.status-title{font-size:14.5px;font-weight:800;color:var(--ink);line-height:1.25}

/* indeterminate progress bar */
.status-bar{height:5px;border-radius:99px;background:#eceff5;overflow:hidden;margin-bottom:15px}
.status-bar span{display:block;height:100%;width:38%;border-radius:99px;
  background:linear-gradient(90deg,var(--brand),var(--brand2));
  animation:slide 1.25s cubic-bezier(.55,.1,.35,.9) infinite}
@keyframes slide{0%{transform:translateX(-105%)}100%{transform:translateX(320%)}}

.status-msg{margin:0 0 14px;font-size:14px;font-weight:700;color:var(--brand);line-height:1.45}

/* step checklist */
.status-steps{list-style:none;margin:0 0 14px;padding:0;display:flex;flex-direction:column;gap:7px}
.status-steps li{display:flex;align-items:center;gap:9px;font-size:12.5px;font-weight:600;color:#a4aebd}
.status-steps li i{width:15px;height:15px;border-radius:50%;flex:0 0 auto;border:2px solid #dde3ec;
  background:#fff;position:relative;transition:background .2s,border-color .2s}
.status-steps li.on{color:var(--brand)}
.status-steps li.on i{border-color:var(--brand);
  background:radial-gradient(circle at 50% 50%, var(--brand) 0 38%, #fff 39%)}
.status-steps li.done{color:var(--good)}
.status-steps li.done i{border-color:var(--good);background:var(--good)}
.status-steps li.done i:after{content:"";position:absolute;left:3.4px;top:1px;width:3.5px;height:7px;
  border:solid #fff;border-width:0 2px 2px 0;transform:rotate(43deg)}

/* which gases have arrived */
.status-gases{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:14px}
.sg{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:800;
  padding:4px 9px;border-radius:20px;background:#f3f5f9;color:#a4aebd;
  border:1px solid transparent;transition:background .2s,color .2s,border-color .2s}
.sg i{width:7px;height:7px;border-radius:50%;background:currentColor;opacity:.5}
.sg.on{background:#fff;color:var(--ink);border-color:var(--line);box-shadow:0 2px 6px rgba(23,42,73,.08)}
.sg.on i{opacity:1}

.status-note{display:block;font-size:11.5px;font-weight:500;color:var(--muted);line-height:1.55;
  border-top:1px solid var(--line);padding-top:12px}

/* error state — same card, no motion, red headline */
.status.err .status-bar,
.status.err .status-steps,
.status.err .status-gases,
.status.err .status-note{display:none}
.status.err .status-msg{color:var(--accent);font-weight:600;font-size:13.5px}
.status.err .status-card{border-color:#f3c9ce}

/* ---- legend: hatched "no data" swatch ---- */
.map-legend .lg-nodata i.i-hatch{
  background:repeating-linear-gradient(45deg,#c8cedb 0 2px,#8d97a8 2px 4px);
  border:1px solid #b3bcc9}
.map-legend .lg-nodata{opacity:.9}

/* ---- accessibility ----------------------------------------------------
   A dashboard driven entirely by pointer gestures locks out keyboard and
   screen-reader users, so: a skip link, a visible focus ring on every
   interactive surface, and honouring reduced-motion. -------------------- */
.skip-link{position:absolute;left:-9999px;top:0;z-index:5000;
  background:var(--brand);color:#fff;padding:10px 16px;border-radius:0 0 10px 0;
  font-size:13px;font-weight:700;text-decoration:none}
.skip-link:focus{left:0}
.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}

/* one consistent focus treatment across the whole app */
a:focus-visible,button:focus-visible,select:focus-visible,input:focus-visible,
.crumb:focus-visible{outline:3px solid rgba(114,9,183,.45);outline-offset:2px;border-radius:6px}
.topbar a:focus-visible{outline-color:rgba(255,255,255,.9)}

/* keyboard users need the breadcrumb to be reachable */
.crumb{cursor:pointer;color:var(--brand2);font-weight:600}
.crumb:not(.current){text-decoration:underline;text-decoration-color:transparent;
  transition:text-decoration-color .15s}
.crumb:not(.current):hover{text-decoration-color:currentColor}

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

/* ---- responsive ---- */
/* narrow desktop / small laptop: 4 equal columns get too tight to read */
@media(max-width:1280px){
  .filters{grid-template-columns:repeat(3,minmax(0,1fr))}
}
@media(max-width:1000px){
  html,body{overflow:auto}
  .stage{grid-template-columns:1fr;height:auto}
  .right{height:70vh}
  .filters{grid-template-columns:repeat(2,minmax(0,1fr))}
  .kpi-row{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media(max-width:560px){
  .filters{grid-template-columns:1fr}
  .kpi-row{grid-template-columns:1fr}
}
