/* Fixed-viewport composition. The map is the page; rails scroll internally. */

#app {
  display: grid;
  height: 100dvh;
  grid-template-rows: var(--header-h) 1fr var(--ticker-h);
  grid-template-columns: var(--rail-l) 1fr var(--rail-r);
  grid-template-areas:
    'header header header'
    'left   map    right'
    'ticker ticker ticker';
}

/* Visually hidden — readable by screen readers, invisible to sighted
   users. Used for the "dashboard ready" announcement that fires when
   the boot screen goes away. The standard sr-only recipe. */
.aria-live-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── Header — light sky instrument panel, NOT a navy command band ─────────
   AQI gradient stripe (4px) is the only saturated color up here. The rest
   is paper-warm white with a teal wordmark. Two rows:
     row 1 (60px): wordmark + subtitle ........ national plate
     row 2 (32px): focus + search ........................ lang + mode + about + clock
   Partner logos, data-quality button, and the "pipes" status row were
   dropped from the header — the partner team now lives inside the About
   overlay, the data-quality indicator is a single small dot, and the
   pipeline status is a hover tooltip on the same dot. */
header {
  grid-area: header;
  background: linear-gradient(180deg, var(--paper-warm) 0%, var(--paper) 100%);
  color: var(--ink);
  display: flex;
  align-items: stretch;
  gap: 0;
  position: relative;
  overflow: hidden;
  min-width: 0;
  border-bottom: 1px solid var(--rule);
}

/* AQI gradient stripe — the only saturated color band on the page. The
   AQI palette itself becomes the AirDash signature: clean air at the
   left edge, severe at the right. */
.aqistripe {
  position: absolute; top: 0; left: 0; right: 0; height: 6px;
  background: linear-gradient(
    to right,
    var(--aqi-good) 0%, var(--aqi-good) 20%,
    var(--aqi-moderate) 20%, var(--aqi-moderate) 40%,
    var(--aqi-watch) 40%, var(--aqi-watch) 60%,
    var(--aqi-unhealthy) 60%, var(--aqi-unhealthy) 80%,
    var(--aqi-hazardous) 80%, var(--aqi-hazardous) 100%);
  z-index: 2;
}

.brand {
  display: flex; flex-direction: column; justify-content: center;
  padding: 12px 18px 0 18px;
  flex: none; min-width: 0;
  border-right: 1px solid var(--rule);
}
.brand .name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 22px;
  letter-spacing: -0.01em;
  color: var(--th-deep);
  line-height: 1.05;
}
/* "AIR · DASH" — the center dot is the AirDash signature mark, not a
   FloodDash orange highlight. */
.brand .name .dot { color: var(--th-sage); padding: 0 1px; }
.brand .name .accent { color: var(--th-deep); }
.brand .sub {
  font-family: var(--font-display);
  font-size: 10.5px;
  font-weight: 500;
  color: var(--ink-mid);
  margin-top: 3px;
  letter-spacing: 0.01em;
  line-height: 1.25;
}

.national {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px 0 16px;
  flex: 1 1 auto;
  overflow: hidden;
  min-width: 0;
  border-right: 1px solid var(--rule);
}
/* HERO — the national Air Watch Score plate. Background now follows the
   AQI palette so it harmonises with the top stripe. */
.national .plate {
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-num);
  font-weight: 700;
  font-size: 18px;
  color: #fff;
  flex: none;
  align-self: center;
  letter-spacing: -0.02em;
}
.national .label {
  display: flex; flex-direction: column; justify-content: center;
  gap: 1px; line-height: 1.2; min-width: 0;
  overflow: hidden;
}
.mobile-brand { display: none; }
/* The verb (TH/EN) is the headline — bigger, in the display font, deep teal. */
.national .label .verb-th {
  font-family: var(--font-display);
  font-weight: 800; font-size: 18px; line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--th-deep);
  white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.national .label .verb-en {
  font-family: var(--font-num); font-weight: 600;
  font-size: 9.5px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-mid);
  white-space: nowrap;
  line-height: 1.2;
  margin-top: 1px;
}
/* One-line "why" so the user gets the cause without leaving the hero. */
.national .label .why {
  font-size: 10px;
  color: var(--ink-mid);
  margin-top: 2px;
  max-width: 320px;
  line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Dust-season micro-badge. Same role as before: explains why the verb
   isn't "ALL CLEAR" even when the data is calm. */
.national .label .season {
  margin-top: 3px;
  font-family: var(--font-num);
  font-size: 8.5px; letter-spacing: 0.04em;
  color: var(--aqi-unhealthy);
  background: rgba(200,69,58,0.10);
  padding: 1px 5px;
  border-left: 2px solid var(--aqi-unhealthy);
  align-self: flex-start;
  line-height: 1.3;
}
/* Hotline / CI / TTS share one horizontal row so they never stack past
   the 60px brand row and force a zoom-out. */
.national-actions {
  display: flex; align-items: center; gap: 4px;
  margin-top: 3px; flex-wrap: nowrap; min-width: 0;
}
/* Hero CTA — one-tap hotline. The number is the only thing on the
   button; JMA puts hotlines in the action card because under stress the
   "what number do I call" question is what people actually need. */
.national .hotline-btn {
  display: inline-flex; align-items: center; gap: 4px;
  margin-top: 0;
  padding: 2px 7px;
  background: var(--th-red);
  border: 1px solid var(--th-red);
  color: #fff;
  font-family: var(--font-num);
  font-size: 10.5px; font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  align-self: auto;
  white-space: nowrap;
  line-height: 1.3;
}
.national .hotline-btn:hover { background: #B13B30; border-color: #B13B30; }
.national .hotline-btn .icon { font-size: 11px; }

/* Trust signals under stress: confidence interval and TTS read-aloud. */
.national .ci-badge {
  display: inline-block;
  margin-top: 0;
  padding: 1px 5px;
  background: var(--well-dim);
  border: 1px dashed var(--ink-low);
  font-family: var(--font-num);
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.04em;
  color: var(--ink-mid);
  cursor: help;
  align-self: auto;
}
.national .tts-btn {
  display: inline-flex; align-items: center; gap: 3px;
  margin-top: 0; margin-left: 0;
  padding: 2px 7px;
  background: var(--well);
  border: 1px solid var(--rule);
  color: var(--ink);
  font-size: 9.5px; font-weight: 700;
  cursor: pointer;
  align-self: auto;
}
.national .tts-btn:hover { background: var(--th-deep); color: #fff; border-color: var(--th-deep); }
.national .tts-btn.speaking { background: var(--th-deep); color: #fff; border-color: var(--th-deep); }

/* AQI station-level counts (lv1..lv5) — small chips of AQI-colored
   numbers next to the brand. Each chip is the band icon + the count
   rendered in the AQI colour. The badge and number are siblings; we
   use the adjacent-sibling combinator to colour the number from the
   badge's lvN class. */
.levelcounts { display: flex; align-items: center; gap: 4px; padding: 12px 12px 0 12px; flex: none; }
.levelcounts .lc { display: inline-flex; align-items: center; gap: 0; }
.levelcounts .lc .n {
  font-family: var(--font-num);
  font-size: 11.5px;
  font-weight: 700;
  color: #fff;
  background: var(--aqi-good);
  padding: 3px 6px;
  line-height: 1;
  min-width: 22px;
  text-align: center;
}
.levelcounts .lc .badge.lv1 { background: var(--aqi-good); }
.levelcounts .lc .badge.lv2 { background: var(--aqi-moderate); color: #2A2A2A; }
.levelcounts .lc .badge.lv3 { background: var(--aqi-watch); }
.levelcounts .lc .badge.lv4 { background: var(--aqi-unhealthy); }
.levelcounts .lc .badge.lv5 { background: var(--aqi-hazardous); }
.levelcounts .lc .badge.lv1 ~ .n { background: var(--aqi-good); }
.levelcounts .lc .badge.lv2 ~ .n { background: var(--aqi-moderate); color: #2A2A2A; }
.levelcounts .lc .badge.lv3 ~ .n { background: var(--aqi-watch); }
.levelcounts .lc .badge.lv4 ~ .n { background: var(--aqi-unhealthy); }
.levelcounts .lc .badge.lv5 ~ .n { background: var(--aqi-hazardous); }

/* Search box — light theme */
.searchbox {
  position: relative;
  display: flex; align-items: center;
  padding: 12px 8px 0 0;
  flex: 1 1 auto;
  min-width: 160px;
  max-width: 320px;
}
.searchbox input {
  width: 100%;
  font-family: var(--font-ui); font-size: 12.5px;
  padding: 5px 26px 5px 9px;
  background: var(--well);
  border: 1px solid var(--rule);
  color: var(--ink);
}
.searchbox input::placeholder { color: var(--ink-low); }
.searchbox input:focus { outline: 2px solid var(--th-sage); outline-offset: -1px; }
.searchbox #search-clear {
  position: absolute; right: 14px; top: 50%; transform: translateY(-25%);
  background: transparent; border: 0; padding: 0 4px;
  color: var(--ink-low); cursor: pointer; font-size: 12px;
}
.searchbox #search-clear:hover { color: var(--th-deep); }
.searchbox .search-results { position: absolute; top: 100%; left: 0; right: 14px; z-index: 100; }

/* Mode toggle (EASY / FULL) — pill style */
#modetoggle {
  display: flex; align-items: center; padding: 12px 6px 0 6px; gap: 0; flex: none;
}
#modetoggle button {
  border: 1px solid var(--rule);
  background: var(--well); color: var(--ink-mid);
  font-size: 11.5px; font-weight: 700; padding: 4px 9px;
  letter-spacing: 0.04em; text-transform: uppercase;
}
#modetoggle button:hover { background: var(--th-deep); color: #fff; border-color: var(--th-deep); }
#modetoggle button.active { background: var(--th-deep); color: #fff; border-color: var(--th-deep); }

/* ASK AI bar — second row of the header. Light theme now. */
.ask-hero {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; gap: 8px;
  padding: 6px 16px;
  background: var(--well);
  color: var(--ink);
  border-top: 1px solid var(--rule);
  z-index: 5;
}
.ask-hero-icon { font-size: 14px; opacity: 0.7; flex: none; color: var(--th-sage); }
.ask-hero input {
  flex: 1; min-width: 0;
  padding: 5px 10px;
  background: var(--paper);
  border: 1px solid var(--rule);
  color: var(--ink);
  font: inherit; font-size: 13px;
}
.ask-hero input::placeholder { color: var(--ink-low); }
.ask-hero input:focus {
  outline: none;
  background: var(--well);
  border-color: var(--th-sage);
}
.ask-hero button {
  padding: 5px 14px;
  background: var(--th-sage); color: #fff;
  border: 1px solid var(--th-sage);
  font-weight: 700; font-size: 12.5px;
  cursor: pointer;
  flex: none;
  font-family: var(--font-display);
  letter-spacing: 0.01em;
}
.ask-hero button:hover { background: #2E7A5E; border-color: #2E7A5E; }
@media (max-width: 700px) {
  .ask-hero { padding: 5px 10px; }
  .ask-hero button { padding: 6px 10px; font-size: 11px; }
}

header .spacer { flex: 1; }

/* Pipeline status — collapsed to a single dot with hover tooltip. The
   old `.pipes` row was 7 dots + 6 status labels; the dot conveys the
   same information at a glance. */
.pipes { display: flex; align-items: center; gap: 4px; padding: 12px 6px 0 6px; flex: none; }
.pipes .dot { width: 10px; height: 10px; background: var(--ink-low); flex: none; }
.pipes .dot.ok { background: var(--th-sage); }
.pipes .dot.bad { background: var(--th-red); }
.pipes .dot.run { background: var(--aqi-watch); }

/* The old `data-quality` button was a full red/yellow/green pill. Now
   it's a quiet chip in the toolbar; the colour still encodes the
   state, the size no longer competes with the wordmark. */
.data-quality {
  align-self: center;
  margin: 0;
  padding: 3px 8px;
  font-family: var(--font-num);
  font-size: 11px; font-weight: 700;
  color: #fff;
  background: var(--th-sage);
  border: 1px solid var(--th-sage);
  cursor: pointer;
  line-height: 1.2;
}
.data-quality.warn { background: var(--aqi-watch); border-color: var(--aqi-watch); }
.data-quality.bad  { background: var(--th-red); border-color: var(--th-red); }
.data-quality:hover { filter: brightness(0.92); }

.clockbox {
  display: flex; flex-direction: column; align-items: flex-end; justify-content: center;
  padding: 12px 12px 0 8px; flex: none;
}
#clock { font-family: var(--font-num); font-size: 17px; font-weight: 700; line-height: 1; color: var(--th-deep); }
.clockbox .date { font-size: 9.5px; color: var(--ink-mid); margin-top: 2px; }

.focusbox { display: flex; align-items: center; gap: 6px; padding: 12px 8px 0 0; flex: none; }
.focusbox select {
  font-family: var(--font-ui); font-size: 12px; font-weight: 600;
  background: var(--well); color: var(--ink);
  border: 1px solid var(--rule); padding: 4px 6px; max-width: 180px;
}
.focusbox #compare-btn,
.focusbox #split-btn {
  border: 1px solid var(--rule); background: var(--well); color: var(--ink);
  font-size: 14px; line-height: 1; padding: 3px 8px; cursor: pointer;
}
.focusbox #compare-btn:hover,
.focusbox #split-btn:hover { background: var(--th-deep); color: #fff; border-color: var(--th-deep); }
.focusbox #split-btn[aria-pressed="true"] {
  background: var(--th-deep); color: #fff; border-color: var(--th-deep);
}

/* "← All Thailand" pill — appears in the focusbox only when the user has
   drilled into a non-Thailand focus area. */
.focusbox #back-to-thailand {
  border: 1px solid var(--th-red); background: transparent; color: var(--th-red);
  font-family: var(--font-ui); font-size: 11.5px; font-weight: 700;
  letter-spacing: 0.02em; line-height: 1; padding: 4px 8px; cursor: pointer;
  text-transform: uppercase; white-space: nowrap;
}
.focusbox #back-to-thailand:hover { background: var(--th-red); color: #fff; }
.focusbox #back-to-thailand[hidden] { display: none; }

.langtoggle { display: flex; align-items: center; padding: 12px 6px 0 6px; gap: 0; flex: none; }
.langtoggle button {
  border: 1px solid var(--rule);
  background: var(--well); color: var(--ink-mid);
  font-size: 12px; font-weight: 600; padding: 4px 9px;
}
.langtoggle button:hover { background: var(--th-deep); color: #fff; border-color: var(--th-deep); }
.langtoggle button.active { background: var(--th-deep); color: #fff; border-color: var(--th-deep); }

/* ── Rails ────────────────────────────────────────────────────────────────── */
.rail {
  background: var(--paper);
  display: flex; flex-direction: column;
  min-height: 0;                       /* allow children to scroll */
}
#rail-left  { grid-area: left; border-right: 1px solid var(--rule-strong); }
#rail-right { grid-area: right; border-left: 1px solid var(--rule-strong); }

.rail .panel-head {
  padding: 10px 12px 8px;
  border-bottom: 1px solid var(--rule-strong);
  background: var(--well);
  flex: none;
}
.rail .panel-head .sign .th { font-size: 15px; }
.rail .scroll {
  overflow-y: auto;
  overscroll-behavior: contain;
  flex: 1;
  min-height: 0;
}

/* ── Map ─────────────────────────────────────────────────────────────────── */
#map { grid-area: map; background: #E9E6DD; min-height: 0; }
.leaflet-container { font-family: var(--font-ui); background: #E9E6DD; }

/* ── Ticker — the AQI gradient as a thin bar across the bottom of the map
   is the visual signature of AirDash. Light theme now. */
#ticker {
  grid-area: ticker;
  background: var(--well);
  color: var(--ink);
  display: flex; align-items: center;
  overflow: hidden;
  border-top: 2px solid;
  border-image: linear-gradient(
    to right,
    var(--aqi-good) 0%, var(--aqi-good) 20%,
    var(--aqi-moderate) 20%, var(--aqi-moderate) 40%,
    var(--aqi-watch) 40%, var(--aqi-watch) 60%,
    var(--aqi-unhealthy) 60%, var(--aqi-unhealthy) 80%,
    var(--aqi-hazardous) 80%, var(--aqi-hazardous) 100%) 1;
}
#ticker .live {
  flex: none;
  display: flex; align-items: center; gap: 6px;
  padding: 0 12px;
  font-family: var(--font-num); font-size: 11px; font-weight: 700; letter-spacing: 0.12em;
  color: var(--th-sage);
  border-right: 1px solid var(--rule);
  height: 100%;
}
#ticker .live .pip { width: 8px; height: 8px; background: var(--th-sage); animation: blink 1.6s steps(2) infinite; }
@keyframes blink { 50% { opacity: 0.25; } }
#ticker .track { flex: 1; overflow: hidden; white-space: nowrap; }
#ticker .track .crawl {
  display: inline-block; padding-left: 100%;
  animation: crawl 55s linear infinite;
  font-size: 13.5px;
}
#ticker .track .crawl span { margin-right: 48px; }
@keyframes crawl { to { transform: translateX(-100%); } }

/* ── Fine-print footer (real-time disclaimer + standards + core idea) ──
   Sits below the ticker. Three short lines: a real-time disclaimer so
   the user knows the data may be imperfect, the system's published
   standards (sources, freshness, station count, no mock data, audit
   trail), and the project's core idea (mapping out possibilities of
   saving lives). Dual-rendered (.th + .en); the i18n layer toggles
   which is visible. Bilingual on purpose — this is a public-facing
   credibility statement. */
.appfooter {
  background: var(--well-dim);
  border-top: 1px solid var(--rule);
  padding: 10px 24px 12px;
  display: flex; flex-direction: column; gap: 4px;
  font-family: var(--font-ui);
  color: var(--ink-mid);
  text-align: center;
}
.appfooter-line {
  font-size: 10.5px; line-height: 1.5; max-width: 920px; margin: 0 auto;
}
.appfooter-line .en { display: none; }
html[lang="en"] .appfooter-line .th { display: none; }
html[lang="en"] .appfooter-line .en { display: inline; }
.appfooter-standards { font-family: var(--font-num); letter-spacing: 0.01em; }
.appfooter-core { font-style: italic; color: var(--th-navy); opacity: 0.85; }
@media (max-width: 720px) {
  .appfooter { padding: 8px 12px 10px; }
  .appfooter-line { font-size: 9.5px; }
}

/* ── Compare overlay: N independent panes for side-by-side ───────────────── */
#compare-overlay {
  position: fixed; inset: 0; z-index: 5000;
  background: var(--paper);
  display: flex; flex-direction: column;
}
#compare-overlay[hidden] { display: none; }
.compare-head {
  height: var(--header-h); flex: none;
  background: var(--th-navy); color: var(--ink-inv);
  display: flex; align-items: center; justify-content: space-between; padding: 0 16px;
  border-bottom: 3px solid var(--th-red);
}
.compare-head .sign .th { font-weight: 600; }
.compare-head .sign .en { font-family: var(--font-num); font-size: 10px; letter-spacing: 0.1em; opacity: 0.8; margin-left: 8px; }
.compare-actions { display: flex; gap: 6px; align-items: center; }
.compare-actions button {
  border: 1px solid rgba(246,244,239,0.5); background: transparent; color: var(--ink-inv);
  font-weight: 600; padding: 5px 11px;
}
.compare-actions button.active { background: var(--ink-inv); color: var(--th-navy); }
#compare-grid { flex: 1; min-height: 0; display: grid; gap: 2px; background: var(--rule-strong); }
#compare-grid.panes-2 { grid-template-columns: 1fr 1fr; }
#compare-grid.panes-3 { grid-template-columns: 1fr 1fr 1fr; }
#compare-grid.panes-4 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }
.cmp-pane { display: flex; flex-direction: column; min-height: 0; background: var(--paper); position: relative; }
.cmp-pane .cmp-bar {
  flex: none; display: flex; align-items: center; gap: 8px; padding: 5px 8px;
  background: var(--well); border-bottom: 1px solid var(--rule-strong);
}
.cmp-pane .cmp-bar select { font-family: var(--font-ui); font-size: 12px; font-weight: 600; border: 1px solid var(--rule-strong); padding: 3px 5px; background: var(--paper); color: var(--th-navy); }
.cmp-pane .cmp-map { flex: 1; min-height: 0; }
.cmp-pane .cmp-readout {
  flex: none; max-height: 42%; overflow-y: auto; overscroll-behavior: contain;
  border-top: 1px solid var(--rule-strong); background: var(--well);
}
@media (max-width: 860px) {
  #compare-grid.panes-2, #compare-grid.panes-3, #compare-grid.panes-4 {
    grid-template-columns: 1fr; grid-template-rows: none; grid-auto-rows: 1fr;
    overflow-y: auto;
  }
}

/* ── Density: fit at 100% zoom on common laptop widths ─────────────
   The brand row is a single flex strip. Without progressive disclosure
   it overflows under ~1600px and people zoom OUT — which kills the
   aha. Hide secondary chrome first; keep brand + verb + search + mode. */
@media (max-width: 1520px) {
  .levelcounts,
  .pipes,
  .clockbox,
  .data-quality { display: none !important; }
  .national .label .why,
  .national .label .season { display: none; }
  .focusbox select { display: none; }
  :root {
    --rail-l: 300px;
    --rail-r: 360px;
  }
}
@media (max-width: 1480px) {
  .focusbox select { max-width: 150px; }
  .focusbox #compare-btn { display: none; } /* places compare (⊟) is the primary */
}
@media (max-width: 1280px) {
  .national .tts-btn,
  .national .hotline-lbl-th,
  .national .hotline-lbl-en { display: none; }
  #about-btn .lbl { display: none; }
  #about-btn { padding: 0 8px; margin-right: 8px; }
  .brand .sub { display: none; }
  .brand { padding: 6px 12px 0 12px; }
  .searchbox input { max-width: 160px; }
  .focusbox { padding-right: 6px; }
  .langtoggle { padding-right: 8px; }
  :root {
    --rail-l: 300px;
    --rail-r: 360px;
  }
}
@media (max-width: 1100px) {
  .national .ci-badge { display: none; }
  :root {
    --rail-l: 280px;
    --rail-r: 320px;
    --header-h: 92px;
  }
}

/* ── Compact view: map on top, tabbed sheet below ────────────────────────
   Three fixed columns stop being readable well before phone width. At
   1100px and below, one map + one focused sheet preserves real text sizes. */
#sheettabs { display: none; }

@media (max-width: 1100px) {
  #app {
    grid-template-rows: 92px minmax(0, 44fr) auto minmax(0, 56fr) var(--ticker-h);
    grid-template-columns: 1fr;
    grid-template-areas: 'header' 'map' 'tabs' 'sheet' 'ticker';
  }
  header {
    display: grid; grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: 46px 46px; overflow: visible;
  }
  .brand, .clockbox, .levelcounts, .pipes,
  .data-quality, header .spacer, .focusbox, #about-btn, .ask-hero {
    display: none !important;
  }
  .national {
    grid-column: 1; grid-row: 1; width: auto; height: 46px;
    padding: 5px 10px; gap: 7px; min-width: 0; border-right: 0;
  }
  .national .plate { width: 32px; height: 32px; font-size: 13px; }
  .national .label { gap: 0; }
  .mobile-brand {
    display: block; font-family: var(--font-num); font-size: 8px;
    font-weight: 700; letter-spacing: .1em; opacity: .65;
  }
  .national .label .verb-th { font-size: 13.5px; line-height: 1.1; }
  .national .label .verb-en { font-size: 8px; }
  .national .label .why, .national .label .season,
  .national .hotline-btn, .national .ci-badge,
  .national .tts-btn { display: none; }

  #modetoggle {
    grid-column: 2; grid-row: 1; height: 46px;
    align-items: center; padding: 5px 8px 0 4px;
  }
  #modetoggle button { min-width: 44px; min-height: 34px; padding: 5px 7px; }
  .searchbox {
    grid-column: 1; grid-row: 2; display: flex !important;
    width: auto; padding: 6px 4px 6px 10px;
  }
  .searchbox input, .searchbox input:focus {
    width: 100%; max-width: none; min-height: 34px; padding: 6px 38px 6px 9px;
  }
  .searchbox #search-clear {
    right: 5px; min-width: 34px; min-height: 34px; color: var(--ink-mid);
  }
  #langtoggle {
    grid-column: 2; grid-row: 2; height: 46px;
    align-items: center; padding: 5px 8px 5px 4px;
  }
  #langtoggle button { min-width: 44px; min-height: 34px; padding: 5px 7px; }
  .legend { display: none; }

  #rail-left, #rail-right { display: none; }
  #rail-left.sheet-active, #rail-right.sheet-active {
    display: flex;
    grid-area: sheet;
    border: none;
    min-height: 0;
  }
  /* The bottom sheet nav already selects the pane — hide the rail's own tab bar. */
  #rail-right.sheet-active .tabs { display: none; }

  #sheettabs {
    grid-area: tabs;
    display: flex;
    background: var(--well);
    border-top: 1px solid var(--rule-strong);
    border-bottom: 1px solid var(--rule-strong);
  }
  #sheettabs button {
    /* min-width:0 — same flexbox fix as the right-rail tabs. Without it,
       wider labels steal space from narrower ones. */
    flex: 1; min-width: 0; border: none; border-right: 1px solid var(--rule);
    min-height: 48px; padding: 7px 4px; font-size: 12.5px; font-weight: 600;
    overflow: hidden;
  }
  #sheettabs button[data-sheet="tap"],
  #sheettabs button[data-sheet="sources"],
  #sheettabs button[data-sheet="library"] { display: none; }
}

/* ── Compare Places overlay — the redesigned split view. ────────────
   Up to 4 panes in a responsive grid; each pane has its own search
   input (70k+ places via /api/search) and Leaflet instance. The data
   bar on the left shows a card per selected place with JMA verb,
   score+CI, water, rain, forecast, soil sat. The whole overlay is
   above #app (z-index 5000) so it can paint over the live dashboard. */
#places-overlay {
  position: fixed; inset: 0; z-index: 5000;
  background: var(--paper);
  display: flex; flex-direction: column;
  overflow: hidden;
}
#places-overlay[hidden] { display: none; }
.places-head {
  flex: none;
  height: 44px; min-height: 44px;
  padding: 0 16px;
  background: var(--th-navy); color: var(--ink-inv);
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px;
  border-bottom: 2px solid var(--th-red);
}
.places-title.sign {
  display: flex; align-items: baseline; gap: 8px;
  min-width: 0; flex: 1;
}
.places-title.sign .th { font-size: 15px; font-weight: 700; white-space: nowrap; }
.places-title.sign .en {
  font-family: var(--font-num); font-size: 10px;
  letter-spacing: 0.12em; opacity: 0.75; text-transform: uppercase;
  white-space: nowrap;
}
.places-actions { display: flex; align-items: center; gap: 6px; flex: none; }
.places-actions .pane-count-lbl {
  font-size: 11px; font-weight: 600; opacity: 0.75;
  margin-right: 4px;
}
.places-actions button {
  border: 1px solid rgba(246,244,239,0.4); background: transparent;
  color: var(--ink-inv); padding: 4px 10px; font-weight: 700;
  font-family: var(--font-num); font-size: 12px; line-height: 1;
  cursor: pointer; min-width: 32px;
}
.places-actions button:hover { background: var(--ink-inv); color: var(--th-navy); }
.places-actions button.active { background: var(--ink-inv); color: var(--th-navy); }
#places-actions #split-close {
  margin-left: 6px; padding: 4px 10px;
  border-color: rgba(246,244,239,0.5);
}
.places-body {
  flex: 1 1 0; min-height: 0;
  display: grid;
  grid-template-columns: 300px 1fr;
  grid-template-rows: minmax(0, 1fr);
}
.places-data-bar { min-height: 0; }
.places-grid { min-height: 0; min-width: 0; }
.places-data-bar {
  background: #fff; border-right: 1px solid var(--rule-strong);
  overflow-y: auto;
  padding: 10px;
  display: flex; flex-direction: column; gap: 8px;
}
.places-grid {
  min-height: 0;
  display: grid; gap: 2px;
  background: var(--rule-strong);
  overflow: hidden;
}
.places-grid.panes-2 { grid-template-columns: 1fr 1fr; }
.places-grid.panes-3 { grid-template-columns: 1fr 1fr 1fr; }
.places-grid.panes-4 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }
@media (max-width: 1100px) {
  .places-body { grid-template-columns: 260px 1fr; }
}
@media (max-width: 860px) {
  /* Hide the overlay entirely on mobile — the data bar is too cramped
     and the grid of 2-4 maps doesn't fit a phone. The split button is
     also hidden in this case. The user can use the main place search
     + focus dropdown for one-place-at-a-time exploration. */
  #places-overlay, #split-btn { display: none !important; }
}

/* ── About button (fine-print, project credit, methodology) ─────────────── */
#about-btn {
  align-self: center; display: inline-flex; align-items: center;
  margin: 0; padding: 4px 11px;
  background: var(--well); color: var(--ink);
  border: 1px solid var(--rule);
  font-family: var(--font-ui); font-size: 12px; font-weight: 600;
  cursor: pointer;
}
#about-btn:hover { background: var(--th-deep); color: #fff; border-color: var(--th-deep); }

#about-overlay {
  position: fixed; inset: 0; z-index: 5500;
  background: var(--paper);
  display: flex; flex-direction: column;
  overflow: hidden;
}
#about-overlay[hidden] { display: none; }
.about-head {
  height: var(--header-h); flex: none;
  background: var(--th-navy); color: var(--ink-inv);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 16px;
  border-bottom: 3px solid var(--th-red);
}
.about-head .sign .th { font-weight: 700; font-size: 16px; }
.about-head .sign .en {
  font-family: var(--font-num); font-size: 10px; letter-spacing: 0.1em;
  text-transform: uppercase; opacity: 0.85; margin-left: 8px;
}
.about-head button {
  border: 1px solid rgba(246,244,239,0.5);
  background: transparent; color: var(--ink-inv);
  font-weight: 600; padding: 5px 12px;
}
.about-head button:hover { background: var(--ink-inv); color: var(--th-navy); }

.about-body {
  flex: 1; overflow-y: auto; overscroll-behavior: contain;
  padding: 28px clamp(20px, 5vw, 80px);
  max-width: 980px; margin: 0 auto; width: 100%;
}
.about-card {
  background: var(--well); border: 1px solid var(--rule);
  padding: 20px 24px; margin-bottom: 18px;
}
.about-owner {
  display: grid;
  grid-template-columns: 96px 1fr;
  gap: 22px;
  align-items: center;
}
.about-portrait {
  width: 96px; height: 96px;
  border-radius: 50%;
  object-fit: cover;
  object-position: center 22%;
  border: 2px solid var(--rule-strong);
  background: linear-gradient(135deg, #241E4E 0%, #3D3663 100%);
  flex: none;
}
.about-name    { font-size: 18px; font-weight: 700; color: var(--ink); }
.about-name-en { font-family: var(--font-num); font-size: 11.5px;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-mid); margin-top: 1px; }
.about-role    { font-size: 13px; color: var(--ink); margin-top: 8px; line-height: 1.5; }
.about-blurb   { font-size: 13.5px; color: var(--ink-mid); margin-top: 6px; line-height: 1.55; }

.about-partners {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 22px;
  align-items: center;
}
.about-partner {
  display: grid;
  grid-template-columns: 132px 1fr;
  gap: 14px; align-items: center;
}
.partner-logo {
  width: 132px; max-height: 90px; object-fit: contain;
  background: transparent;
}
.partner-text .th { font-weight: 700; font-size: 14px; color: var(--ink); }
.partner-text .en {
  font-family: var(--font-num); font-size: 10.5px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink-mid); margin-top: 2px;
}
.partner-meta { font-size: 11.5px; color: var(--ink-mid); margin-top: 6px; }
.partner-meta a { color: var(--ink); text-decoration: underline dotted; }

.about-links {
  display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px;
}
.about-links a {
  display: inline-block; padding: 5px 12px;
  border: 1px solid var(--rule-strong);
  font-size: 12.5px; font-weight: 600;
  text-decoration: none;
  background: var(--paper);
}
.about-links a:hover { background: var(--th-navy); color: var(--ink-inv); }

.about-fineprint {
  font-size: 11px; color: var(--ink-low);
  line-height: 1.55;
  padding: 14px 4px 8px;
  border-top: 1px solid var(--rule);
}

/* ── About — "Why this is personal" section ─────────────────────────────
   The most important block on the About overlay. The visual treatment
   has to honour the weight of the story: a hero quote up top, generous
   prose spacing, large display-numerals on the three philosophy
   points, an AQI-accent vertical bar on the FloodDash callout.
   No stock images, no decorative noise — the words and the numbers do
   the work. The display font (Manrope) is reserved for this section so
   it reads as a different voice from the bio and the papers. */
.about-personal {
  /* Distinguish from the cream bio / paper cards: white paper with a
     coloured AQI vertical bar on the left. */
  background: var(--well);
  border: 1px solid var(--rule);
  border-left: 4px solid;
  border-image: linear-gradient(180deg,
    var(--aqi-good) 0%, var(--aqi-good) 20%,
    var(--aqi-moderate) 20%, var(--aqi-moderate) 40%,
    var(--aqi-watch) 40%, var(--aqi-watch) 60%,
    var(--aqi-unhealthy) 60%, var(--aqi-unhealthy) 80%,
    var(--aqi-hazardous) 80%, var(--aqi-hazardous) 100%) 1;
  padding: 24px 28px 26px;
}

/* Hero quote — the reason the project was started. */
.about-hero-quote {
  position: relative;
  margin: 0 0 22px;
  padding: 8px 0 12px 56px;
  border-bottom: 1px dashed var(--rule);
}
.about-hero-quote .quote-mark {
  position: absolute; left: 0; top: -8px;
  font-family: var(--font-display);
  font-size: 64px; line-height: 1; font-weight: 800;
  color: var(--th-sage);
  letter-spacing: -0.04em;
}
.about-hero-quote .quote-text {
  font-family: var(--font-display);
  font-size: 24px; line-height: 1.35; font-weight: 700;
  color: var(--th-deep);
  letter-spacing: -0.01em;
  margin: 0 0 8px;
}
.about-hero-quote .quote-attr {
  font-family: var(--font-num);
  font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-mid);
}

/* Photos inside the personal story.
   Design contract: the TEXT is the story; the photos are visual
   punctuation. Every photo is constrained to magazine-size (~240px)
   and floated so the surrounding prose wraps around it. Nothing
   full-width, nothing dominant — the reader should see the text
   first and encounter the photo as a moment of 'ah, this is what
   that felt like', not as a hero image that pushes the words off
   the page. */
.about-photo {
  margin: 4px 0 12px;
  text-align: left;
}
.about-photo img {
  display: block;
  width: 100%;
  max-width: 240px;
  max-height: 240px;
  object-fit: cover;
  border: 1px solid var(--rule);
}
.about-photo figcaption {
  font-family: var(--font-ui);
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--ink-mid);
  margin-top: 6px;
  font-style: italic;
  padding: 0 2px;
}

/* Float the figure so the surrounding paragraph text wraps around it.
   --right: image on the right, text flows on the left.
   --left: image on the left, text flows on the right.
   The figure is always a narrow column (max-width 240px) so the
   wrapped text has plenty of column width to stay readable. */
.about-photo--right {
  float: right;
  margin: 4px 0 12px 18px;
  shape-outside: margin-box;
}
.about-photo--left {
  float: left;
  margin: 4px 18px 12px 0;
  shape-outside: margin-box;
}

/* A larger "feature" image, still constrained but allowed to take
   more of the column — used for ONE image per section (the visual
   climax), never for a strip. */
.about-photo--feature {
  float: none;
  clear: both;
  display: block;
  margin: 16px auto;
  text-align: center;
  max-width: 100%;
}
.about-photo--feature img {
  max-width: 100%;
  max-height: 320px;
  margin: 0 auto;
}
.about-photo--feature figcaption {
  font-size: 12px;
  margin-top: 8px;
  font-style: normal;
  color: var(--ink);
}

/* On narrow viewports the float breaks down — stack the figure
   above the paragraph at full width with a sensible max. */
@media (max-width: 720px) {
  .about-photo--right,
  .about-photo--left {
    float: none;
    margin: 14px 0;
    max-width: 100%;
  }
  .about-photo--right img,
  .about-photo--left img {
    max-width: 100%;
    max-height: 280px;
  }
}

/* The story prose — generous line-height and a paragraph rhythm. */
.about-story { margin: 0 0 22px; }
.about-story .eyebrow {
  margin: 0 0 14px;
  color: var(--th-red);
}
.about-story p {
  font-size: 14.5px; line-height: 1.75;
  color: var(--ink);
  margin: 0 0 16px;
}
.about-story p:last-child { margin-bottom: 0; }

/* Three philosophy points — display numerals + body, side by side. */
.about-philosophy { margin: 0 0 22px; }
.about-philosophy .eyebrow {
  margin: 0 0 12px;
  color: var(--th-deep);
}
.philosophy-list {
  list-style: none; padding: 0; margin: 0;
  display: grid; gap: 14px;
}
.phil-item {
  display: grid;
  grid-template-columns: 76px 1fr;
  gap: 18px; align-items: start;
  padding: 14px 16px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--th-sage);
}
.phil-item:nth-child(2) { border-left-color: var(--aqi-watch); }
.phil-item:nth-child(3) { border-left-color: var(--th-red); }
.phil-item .phil-num {
  font-family: var(--font-num);
  font-size: 32px; font-weight: 700; line-height: 1;
  color: var(--th-deep);
  letter-spacing: -0.02em;
}
.phil-item:nth-child(2) .phil-num { color: var(--aqi-watch); }
.phil-item:nth-child(3) .phil-num { color: var(--th-red); }
.phil-item .phil-body h4 {
  font-family: var(--font-display);
  font-size: 16px; font-weight: 700;
  color: var(--th-deep);
  letter-spacing: -0.005em;
  margin: 0 0 6px;
}
.phil-item .phil-body p {
  font-size: 13.5px; line-height: 1.6;
  color: var(--ink);
  margin: 0;
}

/* FloodDash → AirDash callout. Two tag-pills and an arrow, in a
   callout frame. */
.about-flooddash {
  margin: 0 0 22px;
  padding: 14px 18px;
  background: var(--well-dim);
  border: 1px solid var(--rule);
}
.about-flooddash .flooddash-mark {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 10px;
  font-family: var(--font-num);
}
.about-flooddash .fd-tag {
  display: inline-block;
  padding: 4px 10px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase;
  background: var(--well);
  border: 1px solid var(--rule-strong);
  color: var(--ink);
}
.about-flooddash .fd-tag-air {
  background: var(--th-sage);
  border-color: var(--th-sage);
  color: #fff;
}
.about-flooddash .fd-arrow {
  font-size: 18px; font-weight: 700; color: var(--ink-mid);
}
.about-flooddash p {
  font-size: 13px; line-height: 1.6;
  color: var(--ink-mid);
  margin: 0;
}
.about-flooddash p a { color: var(--th-deep); text-decoration: underline dotted; }

/* Closing line — the personal contract. */
.about-closing {
  margin: 6px 0 0;
  padding: 14px 18px;
  font-family: var(--font-display);
  font-size: 17px; font-weight: 700;
  line-height: 1.45;
  color: var(--th-deep);
  background: var(--well-dim);
  border-left: 3px solid var(--th-deep);
  letter-spacing: -0.005em;
}

@media (max-width: 720px) {
  .about-personal { padding: 20px 18px 22px; }
  .about-hero-quote { padding-left: 42px; }
  .about-hero-quote .quote-mark { font-size: 48px; top: -4px; }
  .about-hero-quote .quote-text { font-size: 19px; }
  .phil-item { grid-template-columns: 56px 1fr; gap: 12px; padding: 12px 12px; }
  .phil-item .phil-num { font-size: 24px; }
}

/* ── About — Dr Non bio + selected papers ─────────────────────────────── */
.about-bio .eyebrow,
.about-papers .eyebrow { margin-bottom: 10px; }
.about-bio .bio-intro {
  font-size: 14px; line-height: 1.6; color: var(--ink);
  margin: 0 0 14px;
}
.about-bio .bio-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 22px;
  margin-bottom: 14px;
}
.about-bio .bio-block h4 {
  font-size: 11px; font-family: var(--font-num);
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--th-navy);
  margin: 0 0 8px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--rule);
}
.about-bio .bio-block ul {
  list-style: none; padding: 0; margin: 0;
  font-size: 12.5px; line-height: 1.55;
  color: var(--ink);
}
.about-bio .bio-block li {
  position: relative; padding-left: 12px; margin-bottom: 4px;
}
.about-bio .bio-block li::before {
  content: ""; position: absolute; left: 0; top: 9px;
  width: 4px; height: 4px; background: var(--th-navy);
}
.about-bio .bio-extra {
  font-size: 12.5px; line-height: 1.6;
  color: var(--ink-mid);
  margin: 12px 0 0;
  padding-top: 12px;
  border-top: 1px dashed var(--rule);
}

.about-papers .papers-meta {
  font-size: 11.5px; color: var(--ink-mid);
  font-family: var(--font-num); letter-spacing: 0.04em;
  margin: -2px 0 14px;
}
.about-papers .papers-list {
  list-style: none; padding: 0; margin: 0;
  counter-reset: paper;
  display: grid; gap: 10px;
}
.about-papers .paper {
  counter-increment: paper;
  position: relative;
  padding: 10px 12px 10px 36px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--th-navy);
}
.about-papers .paper::before {
  content: counter(paper);
  position: absolute; left: 10px; top: 10px;
  font-family: var(--font-num); font-weight: 700; font-size: 14px;
  color: var(--th-navy);
  width: 18px; text-align: center;
}
.about-papers .paper-head {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin-bottom: 4px;
}
.about-papers .paper-title {
  font-size: 13.5px; font-weight: 600; color: var(--ink);
  line-height: 1.4; flex: 1 1 auto;
}
.about-papers .paper-cites {
  font-family: var(--font-num); font-size: 11px; font-weight: 700;
  color: #fff; background: var(--th-red);
  padding: 2px 7px; border-radius: 9px;
  flex: none;
}
.about-papers .paper-venue {
  font-size: 11.5px; color: var(--ink-mid);
  font-style: italic; margin-bottom: 6px;
}
.about-papers .paper-link {
  font-size: 12px; font-weight: 600;
  color: var(--th-navy);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.about-papers .paper-link:hover { border-bottom-color: var(--th-navy); }

@media (max-width: 720px) {
  .about-partners { grid-template-columns: 1fr; }
  .about-owner { grid-template-columns: 72px 1fr; }
  .about-portrait { width: 72px; height: 72px; }
  .partner-logo { width: 110px; }
  .about-bio .bio-cols { grid-template-columns: 1fr; gap: 16px; }
  .about-papers .paper { padding: 10px 10px 10px 32px; }
  .about-papers .paper::before { left: 8px; top: 10px; }
}

/* ── Citizen mode ("ง่าย") — the stripped-down view for non-technical users.
   What stays: map, search, city verdict card, national ranking, ticker,
   and the national verdict banner at the top of the ranking.
   What goes: the whole right rail (analytics/tap/signals/…), the forecast
   strip, the what-if widget, compare + split-screen, and the operator-only
   header elements (pipeline health, level counts, data-quality button,
   national score plate — a citizen doesn't need these).
   On compact screens, the bottom sheet keeps MY AREA + RISK + ALERTS.
   The full dashboard is one click away on the "เต็ม / FULL" toggle. ──── */
body.mode-citizen #forecast-strip,
body.mode-citizen #whatif,
body.mode-citizen #compare-btn,
body.mode-citizen #split-btn,
body.mode-citizen #levelcounts,
body.mode-citizen #pipes,
body.mode-citizen #data-quality { display: none !important; }

/* Mobile: strip the bottom sheet to just the two panes a citizen needs. */
body.mode-citizen #sheettabs button:not([data-sheet="citizen"]):not([data-sheet="risk"]):not([data-sheet="alerts"]) {
  display: none !important;
}

/* Citizen mode: the right rail is My Area + Alerts only. Risk remains the
   map/ranking sheet on compact screens; advanced analysis stays in Full. */
body.mode-citizen #rail-right .tabs #righttabs button:not([data-pane="citizen"]):not([data-pane="alerts"]),
body.mode-citizen #righttabs button:not([data-pane="citizen"]):not([data-pane="alerts"]) {
  display: none !important;
}
body.mode-citizen #pane-analytics,
body.mode-citizen #pane-waterways,
body.mode-citizen #pane-tap,
body.mode-citizen #pane-sources,
body.mode-citizen #pane-insights,
body.mode-citizen #pane-history,
body.mode-citizen #pane-library,
body.mode-citizen #pane-news,
body.mode-citizen #pane-chat { display: none !important; }
body.mode-citizen #pane-citizen:not([hidden]) { display: flex !important; }
@media (min-width: 1101px) {
  body.mode-citizen #app {
    grid-template-columns: 1fr 360px;
    grid-template-areas:
      'header header'
      'map    right'
      'ticker ticker';
  }
  body.mode-citizen #rail-left { display: none; }
}
