:root {
  --bg: #0c0e10;
  --panel: #14171b;
  --panel-2: #1a1e23;
  --ink: #e6edf3;
  --ink-dim: #9aa4ad;
  --accent: #6ee7b7;
  --accent-2: #38bdf8;
  --warn: #fbbf24;
  --line: #262b31;
  --mono: ui-monospace, SFMono-Regular, "JetBrains Mono", Menlo, Consolas, monospace;
  --sans: ui-sans-serif, system-ui, -apple-system, "Inter", sans-serif;
  --brand: #1f8f5f;

  /* Type scale — keep sizes consistent across components.
     micro = uppercase chips/labels, body = default reading text. */
  --fs-micro: 10.5px;
  --fs-label: 11px;
  --fs-sub:   12px;
  --fs-body:  13px;
  --fs-lead:  14px;
  --fs-h3:    16px;
  --fs-h2:    18px;
  --fs-h1:    20px;
}

* { box-sizing: border-box; }
/* The `hidden` attribute must win even on elements with an explicit
   `display` (e.g. the flex chat panel/toggle), so force it. */
[hidden] { display: none !important; }
html, body { margin: 0; padding: 0; background: var(--bg); color: var(--ink); font-family: var(--sans); }
body { min-height: 100vh; display: flex; flex-direction: column; }

header {
  display: flex; align-items: baseline; gap: 18px;
  padding: 14px 22px; border-bottom: 1px solid var(--line);
}
.brand { font-family: var(--mono); font-weight: 600; letter-spacing: 0.5px; font-size: 18px; color: var(--accent); }
.tag { color: var(--ink-dim); font-size: 13px; }
.tag code { background: var(--panel-2); padding: 2px 6px; border-radius: 4px; color: var(--accent-2); font-family: var(--mono); }

/* ---------- Header account menu ---------- */
.header-menu { position: relative; margin-left: auto; align-self: center; }
.menu-btn {
  width: auto; margin: 0; padding: 7px 14px;
  background: var(--panel-2); color: var(--ink);
  border: 1px solid var(--line); border-radius: 6px;
  font-family: var(--mono); font-size: 12.5px; font-weight: 500;
}
.menu-btn:hover { background: var(--line); filter: none; }
.menu-btn .caret { color: var(--ink-dim); font-size: 10px; }
.menu-dropdown {
  position: absolute; right: 0; top: calc(100% + 6px);
  min-width: 200px; z-index: 5000;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 8px; padding: 6px;
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.5);
}
.menu-dropdown button {
  width: 100%; margin: 0; text-align: left;
  background: transparent; color: var(--ink);
  border: none; border-radius: 5px; padding: 9px 10px;
  font-family: var(--mono); font-size: 12.5px; font-weight: 400;
}
.menu-dropdown button:hover { background: var(--panel-2); filter: none; }
.menu-sep { height: 1px; background: var(--line); margin: 5px 4px; }
.menu-label {
  font-family: var(--mono); font-size: 10px;
  text-transform: uppercase; letter-spacing: 1.2px;
  color: var(--ink-dim); padding: 6px 10px 2px;
}
.menu-check { color: var(--accent); margin-right: 2px; font-size: 11px; }

main {
  flex: 1; display: grid;
  grid-template-columns: 340px 1fr;
  min-height: 70vh;
}
aside {
  background: var(--panel); border-right: 1px solid var(--line);
  padding: 18px 18px 24px; overflow-y: auto;
}
aside h2 {
  font-size: 12px; text-transform: uppercase; letter-spacing: 1.2px;
  color: var(--ink-dim); margin: 18px 0 8px;
}
aside h2:first-of-type { margin-top: 0; }
.hint { color: var(--ink-dim); font-size: 12px; margin: 0 0 8px; }

label { display: block; font-size: 13px; color: var(--ink-dim); margin: 8px 0; }
input, select {
  width: 100%; padding: 8px 10px; margin-top: 4px;
  background: var(--panel-2); color: var(--ink);
  border: 1px solid var(--line); border-radius: 6px;
  font-family: var(--mono); font-size: 13px;
}
input:focus, select:focus { outline: none; border-color: var(--accent); }
.coords { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.coords label { margin: 4px 0; }

button {
  width: 100%; margin-top: 14px;
  background: var(--accent); color: #0c1612;
  font-weight: 600; border: none; border-radius: 6px;
  padding: 10px 14px; cursor: pointer; font-family: var(--mono);
}
button:disabled { opacity: 0.45; cursor: not-allowed; }
button:hover:not(:disabled) { filter: brightness(1.06); }

button.btn-secondary {
  background: transparent;
  color: var(--accent-2);
  border: 1px solid var(--accent-2);
  margin-top: 8px;
}
button.btn-secondary:disabled {
  color: var(--ink-dim);
  border-color: var(--line);
  background: transparent;
}
button.btn-secondary:hover:not(:disabled) {
  background: rgba(56, 189, 248, 0.08);
  filter: none;
}

.status { margin-top: 10px; color: var(--accent-2); font-family: var(--mono); font-size: 12px; min-height: 16px; }

#map-wrap { position: relative; }
#map { position: absolute; inset: 0; }

/* Leaflet layer control — page-global `label{display:block}` and
   `input{width:100%}` would otherwise butcher the checkboxes inside the
   control. Everything below is a targeted reset. */
.leaflet-control-layers {
  background: var(--panel) !important;
  border: 1px solid var(--line) !important;
  border-radius: 6px !important;
  color: var(--ink) !important;
  font-family: var(--mono) !important;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35) !important;
  min-width: 0 !important;
}
.leaflet-control-layers-toggle {
  background-image: none !important;
  background-color: var(--panel) !important;
  border-radius: 6px !important;
  width: 36px !important; height: 36px !important;
  position: relative;
}
.leaflet-control-layers-toggle::after {
  content: '\2261'; /* triple-bar / "layers" glyph */
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--ink); font-size: 18px; line-height: 1;
}
.leaflet-control-layers-expanded { padding: 8px 10px !important; min-width: 0 !important; }
.leaflet-control-layers-list { line-height: 1 !important; }
.layers-title {
  color: var(--accent);
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: 0.6px;
  margin: 0 0 6px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--line);
}
.leaflet-control-layers-overlays,
.leaflet-control-layers-base {
  display: flex !important;
  flex-direction: column;
  gap: 2px;
}
.leaflet-control-layers label {
  display: flex !important;
  align-items: center !important;
  width: auto !important;
  margin: 0 !important;
  padding: 4px 4px !important;
  color: var(--ink) !important;
  font-size: 11px !important;
  font-family: var(--mono) !important;
  cursor: pointer !important;
  border-radius: 3px;
  white-space: nowrap;
}
.leaflet-control-layers label:hover { background: var(--panel-2); }
.leaflet-control-layers label > div,
.leaflet-control-layers label > span {
  display: inline-flex !important;
  align-items: center !important;
  gap: 8px !important;
  font-size: 11px !important;
  width: auto !important;
  padding: 0 !important;
  margin: 0 !important;
  background: transparent !important;
  border: none !important;
}
.leaflet-control-layers input[type=checkbox],
.leaflet-control-layers input[type=radio] {
  width: 14px !important;
  height: 14px !important;
  padding: 0 !important;
  margin: 0 !important;
  background: var(--panel-2) !important;
  border: 1px solid var(--line) !important;
  accent-color: var(--accent) !important;
  flex-shrink: 0;
  border-radius: 3px;
}
.leaflet-control-layers-separator {
  border-top-color: var(--line) !important;
  margin: 6px 0 !important;
}

.leaflet-control-attribution {
  background: rgba(20, 23, 27, 0.85) !important;
  color: var(--ink-dim) !important;
  font-family: var(--mono); font-size: 10px;
}
.leaflet-control-attribution a { color: var(--accent-2) !important; }
.leaflet-control-zoom a {
  background: var(--panel) !important; color: var(--ink) !important;
  border: 1px solid var(--line) !important;
}
.leaflet-control-zoom a:hover { background: var(--panel-2) !important; }

/* Tooltip on overlay cell hover */
.leaflet-tooltip {
  background: var(--panel) !important;
  border: 1px solid var(--line) !important;
  color: var(--ink) !important;
  font-family: var(--mono) !important;
  font-size: 11px !important;
  padding: 4px 8px !important;
  border-radius: 4px !important;
  box-shadow: 0 2px 8px rgba(0,0,0,0.35) !important;
}
.leaflet-tooltip::before { display: none !important; }

/* Polygon-draw mode */
#map.drawing { cursor: crosshair !important; }
#map.drawing .leaflet-interactive { cursor: crosshair !important; }
.draw-status {
  margin: 8px 0 10px;
  padding: 8px 10px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 6px;
  color: var(--ink-dim); font-family: var(--mono); font-size: var(--fs-sub);
}
.draw-status strong { color: var(--accent); font-weight: 600; }
button.btn-secondary.drawing { color: var(--warn); border-color: var(--warn); }
button.btn-secondary.drawing:hover:not(:disabled) { background: rgba(251, 191, 36, 0.08); }

/* Map legend (bottom-right). Sits to the left of the chat toggle bubble
   (#chat-widget is fixed bottom-right at 22px), so cap width tight. */
.map-legend {
  background: var(--panel); border: 1px solid var(--line); border-radius: 6px;
  color: var(--ink); font-family: var(--mono);
  padding: 7px 9px; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
  width: 180px;
}
.map-legend .legend-head {
  color: var(--accent); font-size: var(--fs-micro); margin: 0 0 6px;
  text-transform: uppercase; letter-spacing: 0.6px;
  border-bottom: 1px solid var(--line); padding-bottom: 5px;
}
.map-legend .legend-row { margin-bottom: 6px; }
.map-legend .legend-row:last-of-type { margin-bottom: 0; }
.map-legend .legend-label {
  color: var(--ink-dim); font-size: 10px;
  text-transform: uppercase; letter-spacing: 0.4px; margin-bottom: 3px;
}
.map-legend .legend-ramp {
  display: flex; gap: 0; height: 8px; border-radius: 2px; overflow: hidden;
  border: 1px solid var(--line);
}
.map-legend .legend-sw { flex: 1; height: 100%; }
.map-legend .legend-ticks {
  display: flex; justify-content: space-between;
  color: var(--ink-dim); font-size: 9.5px; margin-top: 2px;
}
.map-legend .legend-muted {
  color: var(--ink-dim); font-size: 11px; padding: 2px 0 4px;
}
.map-legend .legend-foot {
  color: var(--ink-dim); font-size: 9.5px; font-style: italic;
  margin-top: 6px; border-top: 1px solid var(--line); padding-top: 5px;
  line-height: 1.3;
}

/* #result is a flex column with a uniform gap so every result-card (the
   2-col grid, water-cost, prediction) gets the same 18px breathing room
   regardless of which order they appear in. Working mode keeps the natural
   DOM order; demo mode reorders via `order` further down. */
#result {
  padding: 22px 28px;
  border-top: 1px solid var(--line);
  background: var(--panel);
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.result-header { display: flex; align-items: center; justify-content: space-between; }
.result-header h2 { margin: 0; font-family: var(--mono); font-size: 16px; }
#reset-btn { width: auto; padding: 6px 12px; margin: 0; background: var(--panel-2); color: var(--ink); border: 1px solid var(--line); }
.result-grid { display: grid; grid-template-columns: 1fr 1.6fr; gap: 18px; }
.result-card {
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 8px; padding: 14px 16px;
}
.result-card h3 { margin: 0 0 8px; font-size: 12px; text-transform: uppercase; letter-spacing: 1px; color: var(--ink-dim); }
.narrative pre { margin: 0; white-space: pre-wrap; font-family: var(--mono); font-size: 13px; color: var(--ink); line-height: 1.55; }

table { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: 12.5px; }
th, td { padding: 6px 8px; border-bottom: 1px solid var(--line); text-align: right; }
th:first-child, td:first-child { text-align: left; }
th { color: var(--ink-dim); font-weight: 500; }
.irrigate-row { background: rgba(110, 231, 183, 0.06); }
.irrigate-row td { color: var(--accent); }
.totals { margin-top: 10px; color: var(--accent-2); font-family: var(--mono); font-size: 13px; }

/* ---------- Economics card ---------- */
/* (margin-top removed — #result's flex gap handles spacing between cards) */
.econ-card h3 { display: flex; align-items: center; gap: 10px; }
.econ-card h4 { margin: 16px 0 6px; font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--ink-dim); }
.tier-tag {
  font-family: var(--mono); font-size: 10.5px; padding: 2px 7px;
  border-radius: 4px; text-transform: uppercase; letter-spacing: 0.8px;
}
.tier-1 { background: rgba(110, 231, 183, 0.15); color: var(--accent); border: 1px solid rgba(110, 231, 183, 0.3); }
.tier-2 { background: rgba(56, 189, 248, 0.15); color: var(--accent-2); border: 1px solid rgba(56, 189, 248, 0.3); }
.tier-3 { background: rgba(251, 191, 36, 0.12); color: var(--warn); border: 1px solid rgba(251, 191, 36, 0.3); }
.econ-grid {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 12px; margin: 8px 0 4px;
}
.econ-stat {
  background: var(--bg); border: 1px solid var(--line); border-radius: 6px;
  padding: 12px 14px;
}
.econ-label { font-size: 10.5px; text-transform: uppercase; letter-spacing: 1px; color: var(--ink-dim); }
.econ-value { font-family: var(--mono); font-size: 20px; color: var(--accent); margin: 4px 0 2px; }
.econ-sub { font-family: var(--mono); font-size: 11.5px; color: var(--ink-dim); }
.econ-notes { margin-top: 12px; color: var(--ink-dim); font-size: 12.5px; font-style: italic; }

/* ---------- Prediction module ---------- */
/* (margin-top removed — #result's flex gap handles spacing between cards) */
.prediction-header { display: flex; align-items: center; justify-content: space-between; }
.trend-pill {
  font-family: var(--mono); font-size: 11px; padding: 4px 10px;
  border-radius: 999px; text-transform: uppercase; letter-spacing: 1px;
}
.trend-flat    { background: rgba(154, 164, 173, 0.18); color: var(--ink-dim); }
.trend-rising  { background: rgba(251, 113, 133, 0.15); color: #fb7185; border: 1px solid rgba(251, 113, 133, 0.35); }
.trend-falling { background: rgba(110, 231, 183, 0.15); color: var(--accent); border: 1px solid rgba(110, 231, 183, 0.35); }
.prediction-message {
  color: var(--ink); font-family: var(--mono); font-size: 13px; margin: 8px 0 14px;
}
.prediction-chart { display: flex; flex-direction: column; gap: 4px; margin: 8px 0 14px; }
.pred-row {
  display: grid;
  grid-template-columns: 64px 80px 1fr 64px 140px;
  align-items: center; gap: 10px;
  font-family: var(--mono); font-size: 12px;
}
.pred-date { color: var(--ink-dim); }
.pred-temp { color: var(--ink-dim); font-size: 11.5px; }
.pred-bar-wrap { position: relative; height: 18px; background: var(--bg); border-radius: 3px; overflow: hidden; }
.pred-bar { height: 100%; background: linear-gradient(90deg, var(--accent-2), var(--accent)); }
.pred-mm { text-align: right; color: var(--ink); font-size: 12px; }
.pred-flags { font-size: 10px; text-align: right; letter-spacing: 0.8px; }
.flag {
  display: inline-block; padding: 2px 6px; margin-left: 4px;
  border-radius: 3px; font-weight: 600;
}
.flag-heat { background: rgba(251, 113, 133, 0.15); color: #fb7185; border: 1px solid rgba(251, 113, 133, 0.3); }
.flag-rain { background: rgba(56, 189, 248, 0.15); color: var(--accent-2); border: 1px solid rgba(56, 189, 248, 0.3); }
.flag-et   { background: rgba(251, 191, 36, 0.12); color: var(--warn); border: 1px solid rgba(251, 191, 36, 0.3); }
.prediction-totals {
  display: flex; flex-wrap: wrap; gap: 18px;
  font-family: var(--mono); font-size: 12.5px; color: var(--ink-dim);
  border-top: 1px solid var(--line); padding-top: 12px; margin-top: 8px;
}
.prediction-totals strong { color: var(--ink); font-weight: 500; }
.anomalies { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; }
.anom-row {
  background: var(--bg); border: 1px solid var(--line); border-left: 3px solid var(--warn);
  border-radius: 4px; padding: 8px 12px;
  font-family: var(--mono); font-size: 12px; color: var(--ink);
}
.anom-calm { border-left-color: var(--accent); color: var(--ink-dim); }

/* ---------- Valve actuation modal ---------- */
.modal { position: fixed; inset: 0; z-index: 9999; }
.modal-backdrop {
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, 0.65);
  backdrop-filter: blur(2px);
}
.modal-panel {
  position: relative; max-width: 760px; width: calc(100% - 40px);
  margin: 60px auto; max-height: calc(100vh - 120px); overflow-y: auto;
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 25px 60px rgba(0, 0, 0, 0.5);
}
.modal-header {
  display: flex; align-items: flex-start; justify-content: space-between;
  padding: 18px 22px 14px; border-bottom: 1px solid var(--line);
}
.modal-header h3 { margin: 0; font-family: var(--mono); font-size: 16px; color: var(--ink); }
.dry-run-tag {
  display: inline-block; margin-top: 4px;
  background: rgba(251, 191, 36, 0.12); color: var(--warn);
  border: 1px solid rgba(251, 191, 36, 0.35);
  font-family: var(--mono); font-size: 10.5px; letter-spacing: 1.2px;
  padding: 2px 8px; border-radius: 4px;
}
.modal-close {
  width: auto; margin: 0; padding: 4px 10px;
  background: transparent; color: var(--ink-dim);
  border: 1px solid var(--line); font-family: var(--mono); font-size: 11px;
}
.modal-body { padding: 18px 22px 22px; }
.modal-intro { color: var(--ink-dim); font-size: 13px; line-height: 1.55; margin: 0 0 14px; }
.modal-intro code {
  background: var(--panel-2); color: var(--accent-2);
  padding: 1px 6px; border-radius: 3px; font-family: var(--mono); font-size: 12px;
}
.cmd-row {
  display: grid;
  grid-template-columns: 100px 70px 80px 80px 110px 80px;
  gap: 10px; padding: 8px 0;
  border-bottom: 1px solid var(--line);
  font-family: var(--mono); font-size: 12.5px;
}
.cmd-row:last-child { border-bottom: none; }
.cmd-date { color: var(--ink-dim); }
.cmd-zone { color: var(--ink); }
.cmd-open {
  background: rgba(110, 231, 183, 0.12); color: var(--accent);
  border: 1px solid rgba(110, 231, 183, 0.3);
  padding: 1px 8px; border-radius: 3px; font-size: 11px; letter-spacing: 1px;
}
.cmd-runtime, .cmd-volume, .cmd-depth { color: var(--ink); text-align: right; }
.cmd-empty {
  color: var(--ink-dim); font-family: var(--mono); font-size: 13px;
  padding: 16px; text-align: center; background: var(--bg);
  border: 1px dashed var(--line); border-radius: 6px;
}
.valve-totals {
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line);
  font-family: var(--mono); font-size: 12.5px; color: var(--ink-dim);
}
.valve-totals strong { color: var(--ink); font-weight: 500; }
.raw-payload { margin-top: 16px; }
.raw-payload summary {
  cursor: pointer; color: var(--ink-dim); font-family: var(--mono);
  font-size: 11.5px; text-transform: uppercase; letter-spacing: 1px;
  padding: 6px 0;
}
.raw-payload pre {
  background: var(--bg); border: 1px solid var(--line); border-radius: 6px;
  padding: 12px 14px; color: var(--ink); font-size: 11.5px;
  white-space: pre-wrap; word-break: break-word; max-height: 280px; overflow-y: auto;
}

.modal-narrow { max-width: 420px; }
.modal-wide   { max-width: 880px; }

/* First-visit welcome popup. CTA-only dismiss (no backdrop/Esc).
   .welcome-modal flex-centers the panel — overrides the default
   .modal-panel `margin: 60px auto` so the card sits in the middle of
   the screen vertically, not pinned 60px from the top. */
.welcome-modal {
  display: flex;
  align-items: center;
  justify-content: center;
}
.welcome-modal .modal-panel {
  margin: 20px;
  max-height: calc(100vh - 40px);
}
.welcome-panel { max-width: 520px; width: calc(100% - 40px); }

.welcome-hero {
  background: var(--panel-2);
  border-bottom: 1px solid var(--line);
  padding: 28px 28px 20px;
  text-align: center;
}
.welcome-logo {
  width: 160px;
  max-width: 70%;
  height: auto;
  display: block;
  margin: 0 auto 8px;
}
.welcome-tagline {
  margin: 0;
  color: var(--ink-dim);
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.4px;
}

.welcome-body {
  padding: 22px 28px 8px;
}
.welcome-body h4 {
  margin: 0 0 10px;
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 1.2px;
  color: var(--ink-dim);
  font-family: var(--mono);
}
.welcome-body h4:not(:first-child) { margin-top: 18px; }
.welcome-body p {
  margin: 0;
  color: var(--ink);
  font-size: 13px;
  line-height: 1.6;
}

.welcome-list {
  margin: 0;
  padding-left: 20px;
  color: var(--ink);
}
.welcome-list li {
  font-size: 13px;
  line-height: 1.6;
  margin: 6px 0;
}
.welcome-list li::marker { color: var(--ink-dim); }
.welcome-list strong { color: var(--accent); font-weight: 600; }
.welcome-list em {
  color: var(--accent-2);
  font-style: normal;
  font-family: var(--mono);
  font-size: 12px;
}

.welcome-cta {
  display: flex;
  justify-content: center;
  padding: 20px 28px 26px;
}
.welcome-cta button {
  width: auto;
  min-width: 220px;
  margin: 0;
  padding: 12px 28px;
  font-size: 14px;
}
.stacked-form label { display: block; margin: 10px 0; }
.stacked-form button { margin-top: 12px; }

/* ---------- Info modal (How it works) ---------- */
.info-sub { font-family: var(--mono); font-size: 11.5px; color: var(--ink-dim); margin-top: 4px; }
.info-body h4 {
  font-family: var(--mono); font-size: 11.5px; text-transform: uppercase;
  letter-spacing: 1.4px; color: var(--accent); margin: 22px 0 10px;
  padding-bottom: 6px; border-bottom: 1px solid var(--line);
}
.info-body h4:first-of-type { margin-top: 0; }
.info-body p, .info-body li, .info-body dd {
  font-size: 13px; line-height: 1.6; color: var(--ink);
}
.info-body code {
  background: var(--bg); border: 1px solid var(--line); border-radius: 3px;
  padding: 1px 5px; font-family: var(--mono); font-size: 12px; color: var(--accent-2);
}
.info-list { margin: 0; padding-left: 22px; }
.info-list li { margin: 6px 0; }
.info-list strong { color: var(--accent); }
.info-dl { margin: 0; }
.info-dl dt {
  font-family: var(--mono); font-size: 13px; font-weight: 600;
  color: var(--ink); margin: 14px 0 4px;
}
.info-dl dt:first-child { margin-top: 0; }
.info-dl dd { margin: 0 0 4px 0; color: var(--ink-dim); }
.info-dl dd ul { margin: 6px 0 0 0; padding-left: 20px; }
.info-dl dd ul li { color: var(--ink-dim); margin: 3px 0; }
.info-dl dd strong { color: var(--accent); }
.info-paragraph { color: var(--ink-dim); }

/* ---------- Chat widget ---------- */
#chat-widget { position: fixed; right: 22px; bottom: 22px; z-index: 8000; }
.chat-toggle {
  width: auto; margin: 0; padding: 11px 18px;
  background: var(--accent); color: #0c1612;
  border: none; border-radius: 999px; font-weight: 600;
  font-family: var(--mono); font-size: 13px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  display: flex; align-items: center; gap: 7px;
}
.chat-toggle-icon { font-size: 15px; }
.chat-panel {
  width: 360px; max-width: calc(100vw - 44px);
  height: 480px; max-height: calc(100vh - 120px);
  display: flex; flex-direction: column;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 12px; overflow: hidden;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.55);
}
.chat-header {
  display: flex; align-items: flex-start; justify-content: space-between;
  padding: 12px 14px; border-bottom: 1px solid var(--line);
}
.chat-header strong { font-family: var(--mono); font-size: 13px; color: var(--ink); }
.chat-sub { font-size: 10.5px; color: var(--ink-dim); font-family: var(--mono); margin-top: 2px; }
.chat-sub code { color: var(--accent-2); }
.chat-messages {
  flex: 1; overflow-y: auto; padding: 14px;
  display: flex; flex-direction: column; gap: 8px;
}
.chat-bubble {
  max-width: 85%; padding: 9px 12px; border-radius: 10px;
  font-size: 12.5px; line-height: 1.5; white-space: pre-wrap;
}
.chat-user {
  align-self: flex-end;
  background: var(--accent); color: #0c1612;
  border-bottom-right-radius: 3px;
}
.chat-assistant {
  align-self: flex-start;
  background: var(--panel-2); color: var(--ink);
  border: 1px solid var(--line); border-bottom-left-radius: 3px;
}
.chat-input-row {
  display: flex; gap: 8px; padding: 10px;
  border-top: 1px solid var(--line);
}
.chat-input-row input {
  flex: 1; margin: 0;
  background: var(--panel-2); color: var(--ink);
  border: 1px solid var(--line); border-radius: 6px;
  padding: 9px 10px; font-family: var(--sans); font-size: 12.5px;
}
.chat-input-row input:focus { outline: none; border-color: var(--accent); }
.chat-input-row button {
  width: auto; margin: 0; padding: 9px 16px; font-size: 12.5px;
}

@media (max-width: 800px) {
  .chat-panel { width: calc(100vw - 44px); }
  .tag { display: none; }
}

/* ---------- Field recommendations marketplace ---------- */
.coupon-banner {
  background: linear-gradient(90deg, rgba(110, 231, 183, 0.10), rgba(56, 189, 248, 0.10));
  border: 1px solid rgba(110, 231, 183, 0.3);
  border-radius: 6px; padding: 12px 14px; margin-bottom: 16px;
  font-family: var(--mono); font-size: 13px; color: var(--ink);
}
.coupon-banner strong { color: var(--accent); }
.coupon-sub { color: var(--ink-dim); font-size: 11.5px; margin-top: 4px; }
.recs-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
  margin-bottom: 8px;
}
.rec-card {
  background: var(--bg); border: 1px solid var(--line); border-radius: 8px;
  padding: 12px 14px; display: flex; flex-direction: column; gap: 6px;
}
.rec-head { display: flex; justify-content: space-between; align-items: center; }
.rec-tag {
  background: rgba(56, 189, 248, 0.12); color: var(--accent-2);
  border: 1px solid rgba(56, 189, 248, 0.3);
  padding: 2px 7px; border-radius: 3px;
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.8px;
  text-transform: uppercase;
}
.rec-sku { font-family: var(--mono); font-size: 10.5px; color: var(--ink-dim); }
.rec-name { font-family: var(--mono); font-size: 13px; color: var(--ink); font-weight: 500; }
.rec-desc { font-size: 12px; color: var(--ink-dim); line-height: 1.45; flex: 1; }
.rec-pricing { display: flex; align-items: baseline; gap: 8px; margin-top: 4px; }
.rec-sale { font-family: var(--mono); font-size: 17px; color: var(--accent); font-weight: 600; }
.rec-regular { font-family: var(--mono); font-size: 12px; color: var(--ink-dim); text-decoration: line-through; }
.rec-discount {
  background: rgba(251, 113, 133, 0.15); color: #fb7185;
  border: 1px solid rgba(251, 113, 133, 0.3);
  padding: 1px 6px; border-radius: 3px;
  font-family: var(--mono); font-size: 10.5px;
}
.rec-buy {
  width: 100%; margin-top: 8px; padding: 8px 10px;
  background: var(--accent-2); color: #0c1612;
  border: none; border-radius: 5px; font-weight: 600;
  font-family: var(--mono); font-size: 12px; cursor: pointer;
}
.rec-buy:hover:not(:disabled) { filter: brightness(1.08); }

/* ---------- Demo-mode hide rules ---------- */
/* The "demo" view trims internal-looking detail for prospect demos.
   Toggle from the dropdown's "Demo" / "Working model" items. */
body[data-mode="demo"] .narrative,
body[data-mode="demo"] .anomalies,
body[data-mode="demo"] .raw-payload,
body[data-mode="demo"] #econ-notes,
body[data-mode="demo"] .modal-intro,
body[data-mode="demo"] .econ-notes {
  display: none !important;
}
/* In demo mode, soften some labels that read internal */
body[data-mode="demo"] .dry-run-tag { display: none; }
body[data-mode="demo"] .pred-flags  { font-size: 9px; }

/* Demo view: with the narrative card hidden the 2-col .result-grid would
   leave a wide empty column next to a narrow schedule. Flatten the inner
   grid to one column so the schedule fills the width, and reorder so the
   flow reads header → water-cost → 7-day schedule → 14-day prediction.
   #result is already a flex column above, so `order` just works. */
body[data-mode="demo"] .result-header   { order: 0; }
body[data-mode="demo"] #econ-card       { order: 1; }
body[data-mode="demo"] .result-grid {
  order: 2;
  grid-template-columns: 1fr;
}
body[data-mode="demo"] #prediction-card { order: 3; }

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

footer { padding: 14px 22px; border-top: 1px solid var(--line); color: var(--ink-dim); font-size: 12px; font-family: var(--mono); }

@media (max-width: 800px) {
  main { grid-template-columns: 1fr; }
  aside { border-right: none; border-bottom: 1px solid var(--line); }
  #map-wrap { height: 360px; }
  #map { position: relative; height: 360px; }
  .result-grid { grid-template-columns: 1fr; }
  .econ-grid { grid-template-columns: 1fr 1fr; }
  .pred-row { grid-template-columns: 50px 60px 1fr 54px 60px; gap: 6px; font-size: 11px; }
}

/* =====================================================================
   App shell + left side nav rail (icon-only, hover/focus expands)
   ===================================================================== */
/* App pages carry <body class="app"> — the fixed rail lives in the gutter. */
body.app { padding-left: 56px; }

.sidenav {
  position: fixed; left: 0; top: 0; bottom: 0; width: 56px;
  z-index: 7000; overflow: hidden;
  display: flex; flex-direction: column; padding: 10px 0;
  background: var(--panel); border-right: 1px solid var(--line);
  transition: width 0.16s ease;
}
.sidenav:hover, .sidenav:focus-within {
  width: 220px;
  box-shadow: 6px 0 28px rgba(0, 0, 0, 0.4);
}

.sidenav-group { display: flex; flex-direction: column; gap: 2px; padding: 0 8px; }
.sidenav-bottom { margin-top: auto; border-top: 1px solid var(--line); padding-top: 8px; }

.sidenav-brand {
  display: flex; align-items: center; gap: 12px;
  padding: 6px 8px; margin-bottom: 8px;
  color: var(--accent); font-family: var(--mono); font-weight: 600;
  white-space: nowrap; overflow: hidden; text-decoration: none;
}
.sidenav-brand .sidenav-label { font-size: 15px; letter-spacing: 0.5px; }

.sidenav-item {
  display: flex; align-items: center; gap: 12px;
  width: 100%; margin: 0; padding: 9px 8px;
  background: transparent; color: var(--ink-dim);
  border: none; border-left: 2px solid transparent; border-radius: 6px;
  font-family: var(--mono); font-size: 12.5px; font-weight: 400;
  text-align: left; text-decoration: none; white-space: nowrap; cursor: pointer;
}
.sidenav-item:hover { background: var(--panel-2); color: var(--ink); filter: none; }
.sidenav-item.active {
  color: var(--accent); background: var(--panel-2);
  border-left-color: var(--accent);
}
.sidenav-icon {
  flex: 0 0 24px; width: 24px; height: 24px;
  display: flex; align-items: center; justify-content: center;
}
.sidenav-icon svg { width: 20px; height: 20px; display: block; }
.sidenav-label { opacity: 0; transition: opacity 0.12s ease; }
.sidenav:hover .sidenav-label,
.sidenav:focus-within .sidenav-label { opacity: 1; }
.sidenav-state {
  display: block; font-size: 10px; color: var(--ink-dim);
  margin-top: 1px; font-family: var(--mono);
}
.sidenav-item.active .sidenav-state { color: var(--accent); }

/* =====================================================================
   Login landing page
   ===================================================================== */
body.login { align-items: center; justify-content: center; padding: 24px; }
.login-wrap { width: 100%; max-width: 420px; margin: auto; }
.login-brand {
  display: flex; align-items: center; justify-content: center; gap: 14px;
}
.login-logo { width: 52px; height: 52px; flex: 0 0 auto; }
.login-wordmark { display: flex; flex-direction: column; line-height: 1; text-align: left; }
.wm-saturn {
  font-family: var(--sans); font-weight: 800; letter-spacing: 2px;
  font-size: 30px; color: var(--ink);
}
.wm-terminal {
  font-family: var(--sans); font-weight: 600; letter-spacing: 6px;
  font-size: 13px; color: var(--ink-dim); margin-top: 4px;
}
.login-tag { color: var(--ink-dim); font-size: var(--fs-body); text-align: center; margin-top: 14px; }
.login-tag code {
  background: var(--panel-2); color: var(--accent-2);
  padding: 2px 6px; border-radius: 4px; font-family: var(--mono);
}
.login-card {
  background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
  padding: 24px; margin-top: 22px; box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
}
.login-card .dry-run-tag { margin: 0 0 14px; }
.login-divider {
  display: flex; align-items: center; gap: 10px;
  color: var(--ink-dim); font-family: var(--mono); font-size: 10.5px;
  text-transform: uppercase; letter-spacing: 1.2px; margin: 18px 0;
}
.login-divider::before, .login-divider::after {
  content: ""; flex: 1; height: 1px; background: var(--line);
}
.login-links { text-align: center; margin-top: 18px; }
.login-links button {
  width: auto; margin: 0; padding: 4px 8px;
  background: transparent; color: var(--accent-2);
  border: none; font-family: var(--mono); font-size: 12.5px;
  text-decoration: underline; cursor: pointer;
}
.login-links button:hover { filter: brightness(1.15); }

/* =====================================================================
   Generic content page wrapper (history, billing, shop)
   ===================================================================== */
/* Content pages fill the available width (A1). */
.page { padding: 24px 32px; width: 100%; }
.page-header {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; margin-bottom: 2px;
}
.page-header h1 { font-family: var(--mono); font-size: var(--fs-h1); margin: 0; color: var(--ink); }
.page-sub { color: var(--ink-dim); font-size: var(--fs-body); margin: 4px 0 22px; max-width: 70ch; }
.page h2 {
  font-size: var(--fs-sub); text-transform: uppercase; letter-spacing: 1.2px;
  color: var(--ink-dim); margin: 22px 0 10px;
}
/* Consistent vertical rhythm: every card below the grid gets the same gap (A7). */
.page .result-card { margin-top: 18px; }

/* Stat grid fills the row and reflows: 4→2→1 (A2). Scoped to pages so the
   planner's economics grid keeps its own layout. */
.page .econ-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }

/* Recommendation grid fills the width: 3-4 wide, 1 on mobile (A2). */
.recs-grid { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }

/* Data tables fill their card; text left, numbers right, row hover (A3/R8). */
.data-table { width: 100%; }
.data-table th, .data-table td { text-align: left; padding: 9px 16px; }
.data-table .num { text-align: right; }
.data-table tbody tr { transition: background 0.1s ease; }
.data-table tbody tr:hover { background: rgba(255, 255, 255, 0.025); }

/* Inline crop/acres controls on the Shopping page */
.shop-controls { display: flex; gap: 12px; max-width: 460px; margin: 0 0 16px; }
.shop-controls label { flex: 1; margin: 0; }

@media (max-width: 800px) {
  .page { padding: 18px; }
}
@media (max-width: 600px) {
  .page-header { flex-direction: column; align-items: flex-start; gap: 8px; }
}

/* =====================================================================
   UX audit round 2
   ===================================================================== */
/* Square (1:1) icon wrappers with the icon centered. */
.sidenav-icon { aspect-ratio: 1; }

/* Nav brand: collapsed shows the icon mark; expanding cross-fades to the full
   Saturn Terminal lockup (icon + wordmark) from logo-full.svg. The full logo's
   icon aligns with the standalone mark, so it reads as the wordmark appearing. */
.sidenav-brand {
  display: block; position: relative; height: 44px;
  margin-bottom: 6px; overflow: visible;
}
/* left:16 = group(8) + item(8) so the mark lines up with the nav item icons;
   vertically centered so the 24px mark isn't clipped. */
.brand-mark, .brand-full {
  position: absolute; left: 16px; top: 50%; transform: translateY(-50%);
  transition: opacity 0.16s ease;
}
.brand-mark { width: 24px; height: 24px; opacity: 1; }
.brand-mark svg { width: 24px; height: 24px; display: block; }
.brand-full { height: 24px; width: auto; opacity: 0; }
.sidenav:hover .brand-mark,
.sidenav:focus-within .brand-mark { opacity: 0; }
.sidenav:hover .brand-full,
.sidenav:focus-within .brand-full { opacity: 1; }

/* Custom select chevron with even right padding (native arrow sat against
   the wall). Even gap on both sides of the indicator. */
select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239aa4ad' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; background-size: 16px;
  padding-right: 34px;
}

/* Breathing room between a control/button and its helper text. */
button + .hint, button + .status, .btn-secondary + .hint, form + .hint { margin-top: 10px; }

/* Two-line table headers: short label on top, unit/qualifier below — keeps
   headers from wrapping at awkward spots. Wide tables scroll on small screens. */
.table-wrap { overflow-x: auto; }
.units-table thead th { vertical-align: bottom; white-space: nowrap; }
.units-table thead th small {
  display: block; margin-top: 2px;
  font-weight: 400; text-transform: none; letter-spacing: 0;
  font-size: 10px; color: var(--ink-dim);
}

/* =====================================================================
   UX audit round 3 — mobile/responsive sweep
   =====================================================================
   The planner's #result is a flex column with `align-items: stretch`, so
   the widest sibling's min-content forces every other card to that width.
   That cascade made big mono numbers (e.g. "11,900,939 gal") push the
   layout past the viewport on phones. The rules below either let the
   wide content wrap or restructure the offending grid so each row's
   intrinsic min-width fits comfortably on a 320–414px screen. */

/* Make flex/grid children actually shrink — `min-width: auto` (the
   default) lets long mono values force horizontal overflow on phones. */
.result-card, .prediction-card, .econ-card,
.econ-stat, .anom-row, .pred-row,
.prediction-totals span, .prediction-message,
.narrative pre, .modal-panel, .modal-body,
.recs-grid, .rec-card, .data-table, .units-table {
  min-width: 0;
}

/* Long unbreakable runs (mono numbers, units, hashes) wrap before they
   blow out the column. Keep on the high-risk values only — body text
   already wraps fine. */
.econ-value, .econ-sub, .econ-label,
.totals, .anom-row, .narrative pre,
.rec-name, .rec-desc, .rec-sku {
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* ----- Prediction chart (14-day "graph"): mobile restructure -----
   Desktop: date | temp | bar | mm | flags  (5-col, ~440px min).
   <=600px: stack temp under date, flags under mm; bar spans both rows,
   so the bar still gets the bulk of the width. */
@media (max-width: 600px) {
  .pred-row {
    grid-template-columns: 48px 1fr 56px;
    grid-template-rows: auto auto;
    column-gap: 8px;
    row-gap: 0;
    font-size: 11px;
    padding: 4px 0;
    border-bottom: 1px solid rgba(38, 43, 49, 0.6);
  }
  .pred-row:last-child { border-bottom: none; }
  .pred-date     { grid-column: 1; grid-row: 1; }
  .pred-temp     { grid-column: 1; grid-row: 2; text-align: left; font-size: 10px; }
  .pred-bar-wrap { grid-column: 2; grid-row: 1 / span 2; align-self: center; height: 14px; }
  .pred-mm       { grid-column: 3; grid-row: 1; }
  .pred-flags    { grid-column: 3; grid-row: 2; text-align: right; font-size: 9px; letter-spacing: 0.4px; }
  .pred-flags .flag { padding: 1px 4px; margin-left: 2px; }
}

/* ----- Valve actuation modal commands: 6-col 520px → 2-col stacked.
   Each command becomes a small card-like row with date+OPEN top, then
   zone+runtime, then volume+depth. */
@media (max-width: 700px) {
  .cmd-row {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "date    open"
      "zone    runtime"
      "volume  depth";
    gap: 4px 12px;
    padding: 10px 0;
    font-size: 12px;
  }
  .cmd-date    { grid-area: date; }
  .cmd-zone    { grid-area: zone; }
  .cmd-action  { grid-area: open; justify-self: end; }
  .cmd-runtime { grid-area: runtime; text-align: right; }
  .cmd-volume  { grid-area: volume; text-align: left; }
  .cmd-depth   { grid-area: depth; text-align: right; }
}

/* ----- Economics stat grid: at narrow widths the mono $-values push
   the 2-col layout wider than the viewport. Stack to one column and
   shrink the value font. */
@media (max-width: 480px) {
  .econ-grid { grid-template-columns: 1fr; gap: 10px; }
  .econ-value { font-size: 17px; }
  .econ-stat { padding: 10px 12px; }
}

/* ----- Schedule/savings table: tighten cell padding on narrow phones
   so the table needs less horizontal scroll inside .table-wrap. */
@media (max-width: 600px) {
  .units-table { font-size: 11.5px; }
  .units-table th, .units-table td { padding: 5px 6px; }
}

/* ----- Generic data-table (history/billing): same tightening. */
@media (max-width: 600px) {
  .data-table { font-size: 12px; }
  .data-table th, .data-table td { padding: 7px 10px; }
}

/* ----- Map legend collides with the fixed chat-toggle bubble at
   bottom-right on phones. Shrink legend and nudge the chat bubble. */
@media (max-width: 600px) {
  .map-legend {
    width: 138px; padding: 6px 8px;
  }
  .map-legend .legend-label { font-size: 9px; }
  .map-legend .legend-ticks { font-size: 8.5px; }
  .map-legend .legend-foot { font-size: 8.5px; }
  #chat-widget { right: 12px; bottom: 12px; }
  .chat-toggle { padding: 9px 14px; font-size: 12px; }
}

/* ----- Welcome modal: at very narrow widths the 220px CTA button and
   28px hero/body padding crowd the card. */
@media (max-width: 420px) {
  .welcome-cta button { min-width: 0; width: 100%; }
  .welcome-cta  { padding: 16px 20px 22px; }
  .welcome-hero { padding: 22px 20px 16px; }
  .welcome-body { padding: 18px 20px 6px; }
  .welcome-logo { width: 130px; }
}

/* ----- Shop crop/acres controls stack on very narrow phones. */
@media (max-width: 420px) {
  .shop-controls { flex-direction: column; gap: 8px; max-width: none; }
}

/* ----- Recommendation cards: the 280px minmax floor forced horizontal
   overflow at <=336px (content area after the 56px sidenav). Drop the
   floor so cards always shrink to fit the viewport. */
@media (max-width: 380px) {
  .recs-grid { grid-template-columns: 1fr; }
}

/* ----- Page + result paddings on phones. Each card needs ~14px of
   inner padding to breathe; the outer shell can give some up. */
@media (max-width: 600px) {
  #result { padding: 18px 14px; gap: 14px; }
  .result-card { padding: 12px 14px; }
}
@media (max-width: 480px) {
  .page { padding: 16px 14px; }
}

/* ----- Sidenav rail eats 56px of every page. On the narrowest phones
   that's a meaningful chunk — drop it to 48px and re-anchor the brand
   mark so the nav icons still center. */
@media (max-width: 380px) {
  body.app { padding-left: 48px; }
  .sidenav { width: 48px; }
  .sidenav:hover, .sidenav:focus-within { width: 200px; }
  .brand-mark, .brand-full { left: 12px; }
  .sidenav-group { padding: 0 6px; }
  .sidenav-item { padding: 9px 6px; gap: 10px; }
}

/* ----- Chat panel: full-screen-ish on narrow phones, no fixed 480px
   height that pushes off the bottom. */
@media (max-width: 480px) {
  .chat-panel {
    width: calc(100vw - 24px);
    height: calc(100vh - 80px);
    max-height: calc(100vh - 80px);
  }
}

/* ----- Result header on tiny screens: keep "New plan" from spilling. */
@media (max-width: 480px) {
  .result-header { flex-wrap: wrap; gap: 8px; }
  .result-header h2 { font-size: 14px; word-break: break-word; }
  #reset-btn { font-size: 11px; padding: 5px 10px; }
}

/* ----- Prediction totals: each span used to want its own line on narrow
   widths anyway — give them a tighter font + wrap inside the span. */
@media (max-width: 600px) {
  .prediction-totals { gap: 10px 14px; font-size: 12px; }
  .prediction-totals span { display: block; }
}

/* =====================================================================
   Small badges / pills — never wrap mid-token at any viewport.
   ===================================================================== */
/* These elements carry short, label-like text ("Tier 1 · must-water",
   "Flat +0%", "RAIN", "OPEN"). Letting them wrap on hyphens or spaces
   breaks the visual unit — e.g. "MUST-" / "WATER" on one tier-tag, or
   "FLAT" / "+0%" stacking inside a small trend pill. nowrap them and
   let their flex parent re-flow instead. */
.tier-tag, .trend-pill, .flag,
.cmd-open, .rec-tag, .rec-discount,
.layers-title {
  white-space: nowrap;
}

/* =====================================================================
   PHASE 7 — Mobile restructure (<=700px)
   ===================================================================== */

/* The appbar + drawer pattern replaces the side rail on phones. Both
   elements exist in the DOM on every page (built by js/app.js) but are
   display:none above 700px. Same for the map control toolbars — the
   in-map Leaflet controls handle the desktop experience. */
.appbar { display: none; }
.nav-backdrop { display: none; }
#map-controls-top, #map-controls-bottom { display: none; }

/* The map pane wraps the map plus its optional mobile toolbars. On
   desktop it's a flex column that fills the grid cell so #map-wrap (the
   actual map container) stretches; the toolbars stay display:none. */
#map-pane { display: flex; flex-direction: column; }
#map-pane #map-wrap { flex: 1; min-height: 0; }

@media (max-width: 700px) {
  /* ----- App shell: hide the rail, expose the appbar ----- */
  body.app { padding-left: 0; padding-top: 60px; }
  .sidenav {
    width: 240px;
    transform: translateX(-100%);
    transition: transform 0.22s ease;
    box-shadow: 6px 0 28px rgba(0, 0, 0, 0.55);
    padding-top: 14px;
  }
  /* Hover/focus expand is meaningless on touch — make the drawer's only
     "open" trigger be body.nav-open. */
  .sidenav:hover, .sidenav:focus-within {
    width: 240px; box-shadow: 6px 0 28px rgba(0, 0, 0, 0.55);
  }
  body.nav-open .sidenav { transform: translateX(0); }
  /* Labels are always visible in the drawer (no collapsed state on phones). */
  .sidenav .sidenav-label { opacity: 1 !important; }
  /* Brand cross-fade trick from desktop doesn't apply — show the full mark. */
  .sidenav .brand-mark { opacity: 1; }
  .sidenav .brand-full { opacity: 0; }

  .appbar {
    /* 3-col grid: burger left, brand center, mirror-width spacer right.
       The mirror keeps the brand visually centered even when only the
       left cell has content. */
    display: grid;
    grid-template-columns: 44px 1fr 44px;
    align-items: center;
    position: fixed; top: 0; left: 0; right: 0;
    height: 60px; padding: 0 14px;
    background: var(--panel);
    border-bottom: 1px solid var(--line);
    z-index: 6800;
  }
  .appbar-burger {
    /* Raised above the drawer so the same icon both opens and closes —
       the drawer is 240px wide and would otherwise cover the button on
       narrow phones. */
    position: relative; z-index: 7100;
    width: 44px; height: 44px;
    margin: 0; padding: 0;
    background: transparent; color: var(--ink);
    border: none; border-radius: 8px;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 5px;
    cursor: pointer;
  }
  .appbar-burger:hover:not(:disabled) { background: var(--panel-2); filter: none; }
  .appbar-burger:active { background: var(--line); }
  .appbar-burger span {
    display: block; width: 22px; height: 2px;
    background: var(--ink); border-radius: 2px;
    transition: transform 0.18s ease, opacity 0.18s ease;
    transform-origin: center;
  }
  /* Burger → X when the drawer is open. */
  body.nav-open .appbar-burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  body.nav-open .appbar-burger span:nth-child(2) { opacity: 0; }
  body.nav-open .appbar-burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
  .appbar-brand {
    grid-column: 2;
    justify-self: center;
    display: flex; align-items: center;
    text-decoration: none; height: 100%;
  }
  .appbar-brand img { height: 30px; width: auto; display: block; }
  /* The right spacer cell exists only to balance the grid; nothing in it. */
  .appbar-spacer { display: none; }

  .nav-backdrop {
    display: block;
    position: fixed; inset: 0;
    background: rgba(0, 0, 0, 0.55);
    z-index: 6900;
    opacity: 0; pointer-events: none;
    transition: opacity 0.22s ease;
  }
  body.nav-open .nav-backdrop { opacity: 1; pointer-events: auto; }
  /* The drawer rides above the backdrop. */
  .sidenav { z-index: 7000; }

  /* ----- Generic page chrome on phones ----- */
  .page { padding: 16px 14px; }
  .page-header { flex-direction: column; align-items: flex-start; gap: 8px; }
  .page-header h1 { font-size: 18px; }

  /* ----- Tables → stacked label/value cards.
     The tbody rows become individual cards; headers are visually hidden
     but stay in the markup for accessibility. Each <td> shows its label
     (from data-label) on the left and the value on the right. The first
     cell becomes the card header. ----- */
  .table-wrap { overflow-x: visible; }
  .data-table, .units-table {
    display: block; width: 100%;
    font-family: var(--mono);
  }
  .data-table thead, .units-table thead { display: none; }
  .data-table tbody, .units-table tbody { display: block; }
  .data-table tr, .units-table tr {
    display: block;
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 10px 12px;
    margin-bottom: 10px;
  }
  .data-table tr:last-child, .units-table tr:last-child { margin-bottom: 0; }
  .data-table .irrigate-row,
  .units-table .irrigate-row {
    background: rgba(110, 231, 183, 0.06);
    border-color: rgba(110, 231, 183, 0.35);
  }
  .data-table td, .units-table td {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 12px;
    text-align: right;
    padding: 5px 0;
    border-bottom: none;
    font-size: 13px;
    color: var(--ink);
  }
  .data-table td::before, .units-table td::before {
    content: attr(data-label);
    color: var(--ink-dim);
    font-weight: 500;
    font-size: 11.5px;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    text-align: left;
    flex: 0 0 auto;
    margin-right: 8px;
  }
  /* First cell of each row = the card header (date / scenario). */
  .data-table tr > td:first-child,
  .units-table tr > td:first-child {
    text-align: left;
    justify-content: flex-start;
    padding: 2px 0 8px;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--line);
    font-weight: 600;
    font-size: 14px;
    color: var(--ink);
  }
  .data-table tr > td:first-child::before,
  .units-table tr > td:first-child::before { content: none; }
  /* The "irrigate" cell on the schedule reads "✓" or "" — when empty,
     skip the row entirely so we don't get a label with no value. */
  .units-table td:empty { display: none; }

  /* ----- #schedule (7-day plan) → horizontal swipe carousel.
     Each row is a day-card the user swipes through, no visible scrollbar.
     The carousel breaks out of the .result-card padding (-14px) so cards
     have room to fill ~80vw and the next card peeks past the right edge. */
  #schedule { margin: 4px -14px 0; }
  #schedule tbody {
    display: flex;
    flex-direction: row;
    overflow-x: auto;
    overflow-y: visible;
    /* `proximity` (not `mandatory`) lets the user free-scroll naturally;
       the browser only nudges to a snap point when momentum ends close
       to one. `mandatory` made even a tiny swipe jump a whole card. */
    scroll-snap-type: x proximity;
    scroll-behavior: smooth;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    gap: 12px;
    padding: 2px 14px 12px;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  #schedule tbody::-webkit-scrollbar { display: none; width: 0; height: 0; }
  #schedule tbody tr {
    /* One whole card visible + a tiny peek of the next as a swipe hint.
       At 375vw: card = 281, peek ≈ 40px past the right edge. */
    flex: 0 0 75vw;
    max-width: 290px;
    scroll-snap-align: start;
    margin-bottom: 0;
  }
  /* The .totals line sits beneath the carousel, back at normal padding. */
  #schedule + .totals,
  .totals { margin-top: 10px; }

  /* ----- 14-day prediction → compact card layout.
     All metadata sits in a single row ABOVE the bar (date + temp on the
     left, mm + flags on the right), saving roughly a third of the
     vertical space vs. the previous 3-row layout. */
  .pred-row {
    display: grid;
    grid-template-areas:
      "date temp mm flags"
      "bar  bar  bar bar";
    grid-template-columns: auto auto 1fr auto;
    column-gap: 10px;
    row-gap: 6px;
    align-items: center;
    padding: 8px 12px 10px;
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 10px;
    margin-bottom: 6px;
    font-size: 13px;
  }
  .pred-row:last-child { margin-bottom: 0; }
  .pred-date     { grid-area: date; font-size: 13px; color: var(--ink); font-weight: 500; }
  .pred-temp     { grid-area: temp; font-size: 12px; color: var(--ink-dim); }
  .pred-mm       { grid-area: mm; font-size: 12.5px; color: var(--ink); text-align: right; }
  .pred-flags    { grid-area: flags; font-size: 10px; text-align: right; letter-spacing: 0.4px; }
  .pred-flags .flag { padding: 2px 6px; margin-left: 4px; font-size: 9.5px; }
  .pred-bar-wrap { grid-area: bar; height: 12px; background: var(--panel-2); border-radius: 4px; }
  .prediction-chart { gap: 6px; }

  /* ----- Map controls toolbars + edge-to-edge map ----- */
  #map-controls-top, #map-controls-bottom { display: flex; }
  .leaflet-control-zoom,
  .leaflet-control-layers,
  .leaflet-control-attribution { display: none !important; }
  /* The custom .map-legend (Leaflet bottomleft) is hidden on phones —
     the same data renders inside #map-controls-bottom instead. */
  .leaflet-bottom .map-legend { display: none !important; }

  main { grid-template-columns: 1fr; min-height: 0; }
  aside {
    border-right: none;
    border-bottom: 1px solid var(--line);
    padding: 16px 14px 20px;
  }
  /* Map area on phones: locked to a 1:1 aspect ratio so the map is ALWAYS
     visible regardless of parent flex/grid sizing. (Previously a flex:1
     inheritance + grid auto-row could collapse #map-wrap to 0 height when
     the aside was tall.) The aspect-ratio + auto height takes the column
     width and squares it — so the map fills the screen edge-to-edge. */
  #map-pane #map-wrap {
    flex: 0 0 auto;
    height: auto;
    min-height: 0;
    aspect-ratio: 1 / 1;
    position: relative;
    border-top: 1px solid var(--line);
  }
  #map { position: absolute; inset: 0; height: 100%; }

  #map-controls-top {
    flex-wrap: wrap;
    gap: 8px;
    padding: 10px 14px;
    background: var(--panel);
    border-bottom: 1px solid var(--line);
  }
  #map-controls-bottom {
    flex-direction: column;
    gap: 10px;
    padding: 12px 14px 16px;
    background: var(--panel);
    border-top: 1px solid var(--line);
  }
  .map-btn {
    width: 44px; height: 44px;
    margin: 0; padding: 0;
    background: var(--panel-2); color: var(--ink);
    border: 1px solid var(--line); border-radius: 8px;
    font-family: var(--mono); font-size: 18px; font-weight: 600;
    display: inline-flex; align-items: center; justify-content: center;
  }
  .map-btn:hover:not(:disabled) { background: var(--line); filter: none; }
  .map-btn-wide {
    width: auto; padding: 0 14px; font-size: 12.5px;
    letter-spacing: 0.4px; text-transform: uppercase;
  }
  .map-pills {
    display: flex; gap: 8px; flex-wrap: wrap;
  }
  .map-pill {
    width: auto; margin: 0;
    padding: 9px 14px; min-height: 40px;
    background: var(--panel-2); color: var(--ink-dim);
    border: 1px solid var(--line); border-radius: 999px;
    font-family: var(--mono); font-size: 12px; letter-spacing: 0.3px;
    display: inline-flex; align-items: center; gap: 6px;
  }
  .map-pill:hover:not(:disabled) { background: var(--line); filter: none; }
  .map-pill.active {
    background: rgba(110, 231, 183, 0.12);
    color: var(--accent);
    border-color: rgba(110, 231, 183, 0.45);
  }
  .map-pill .dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--ink-dim);
  }
  .map-pill.active .dot { background: var(--accent); }
  .map-legend-inline {
    background: var(--panel-2);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 10px 12px;
    font-family: var(--mono);
    color: var(--ink-dim); font-size: 11px;
  }
  .map-legend-inline .legend-head {
    color: var(--accent); font-size: 10.5px;
    text-transform: uppercase; letter-spacing: 0.6px;
    margin: 0 0 6px; padding-bottom: 6px;
    border-bottom: 1px solid var(--line);
  }
  .map-legend-inline .legend-row { margin-bottom: 8px; }
  .map-legend-inline .legend-row:last-of-type { margin-bottom: 0; }
  .map-legend-inline .legend-label {
    color: var(--ink-dim); font-size: 10px;
    text-transform: uppercase; letter-spacing: 0.5px;
    margin-bottom: 4px;
  }
  .map-legend-inline .legend-ramp {
    display: flex; gap: 0; height: 10px; border-radius: 3px;
    overflow: hidden; border: 1px solid var(--line);
  }
  .map-legend-inline .legend-sw { flex: 1; height: 100%; }
  .map-legend-inline .legend-ticks {
    display: flex; justify-content: space-between;
    color: var(--ink-dim); font-size: 10px; margin-top: 3px;
  }
  .map-legend-inline .legend-foot {
    color: var(--ink-dim); font-size: 10px; font-style: italic;
    margin-top: 8px; border-top: 1px solid var(--line); padding-top: 6px;
  }
  .map-draw-row {
    display: flex; gap: 8px; flex-wrap: wrap;
  }
  .map-draw-row .map-btn-wide { flex: 1 1 auto; min-height: 44px; }

  /* The desktop draw status hint and the in-form Draw field button hide on
     phones — the bottom toolbar's buttons make the flow obvious, and a
     duplicate button in the aside would be confusing. */
  .draw-status { display: none; }
  #draw-field { display: none; }

  /* ----- Form controls: bigger touch targets ----- */
  input, select {
    padding: 12px 12px;
    font-size: 14px;
    min-height: 44px;
  }
  select { padding-right: 38px; }
  label { font-size: 13.5px; }
  button {
    min-height: 44px;
    font-size: 13.5px;
    padding: 12px 14px;
  }
  button.btn-secondary { min-height: 44px; }
  .coords { gap: 10px; }

  /* ----- Result area on phones ----- */
  #result { padding: 16px 14px; gap: 14px; }
  .result-card { padding: 14px 14px; }
  .result-grid { grid-template-columns: 1fr; gap: 14px; }
  .result-header { flex-wrap: wrap; gap: 8px; }
  .result-header h2 { font-size: 14px; word-break: break-word; }
  #reset-btn { font-size: 12px; padding: 8px 14px; min-height: 40px; }

  /* ----- Card titles + their trailing pill: wrap cleanly.
     The flex row (h3 + .tier-tag / .trend-pill) is wider than narrow
     phones can hold, so let the pill drop to its own line instead of
     squeezing into a few pixels. */
  .econ-card h3 {
    flex-wrap: wrap;
    gap: 8px 10px;
    align-items: center;
  }
  .prediction-header {
    flex-wrap: wrap;
    gap: 8px 10px;
    align-items: center;
  }
  /* Once the h3 has the row to itself it doesn't need to push the pill
     to the far edge; the pill aligns naturally to the start. */
  .econ-card h3 .tier-tag,
  .prediction-header .trend-pill { align-self: flex-start; }

  /* The prediction h3 is the longest title ("14-day weather → water
     demand prediction"); on a 320-360 viewport it'd take 3 lines at
     desktop sizing. Trim a step. */
  .prediction-card h3,
  .result-card h3 { line-height: 1.35; }

  /* ----- Economics grid: stack on all phones, big readable values ----- */
  .econ-grid { grid-template-columns: 1fr 1fr; gap: 10px; }
  .econ-value { font-size: 18px; }
  .econ-stat { padding: 12px 14px; }
  .page .econ-grid { grid-template-columns: 1fr 1fr; }

  /* ----- Valve modal command rows: keep the 2-col stacked layout but
     restyle as cards (matches the rest of the mobile feel). ----- */
  .cmd-row {
    background: var(--bg);
    border: 1px solid var(--line) !important;
    border-radius: 10px;
    padding: 12px !important;
    margin-bottom: 8px;
    font-size: 13px !important;
  }
  .cmd-row:last-child { margin-bottom: 0; }
  .modal-body { padding: 16px 16px 20px; }

  /* ----- Chat: full viewport panel; bubble in appbar to avoid map overlap ----- */
  #chat-widget { right: 12px; bottom: 12px; z-index: 9100; }
  .chat-panel {
    position: fixed;
    top: 0; left: 0; right: 0; bottom: 0;
    width: 100vw; height: 100vh;
    max-width: 100vw; max-height: 100vh;
    border-radius: 0;
    z-index: 9300;
  }
  .chat-header { padding: 14px 16px; }
  .chat-input-row { padding: 12px; gap: 10px; }
  .chat-input-row input { padding: 12px; font-size: 14px; min-height: 44px; }
  .chat-input-row button { min-height: 44px; padding: 12px 18px; font-size: 13px; }
  .chat-bubble { max-width: 90%; font-size: 13.5px; }

  /* ----- Recommendations grid: one column on phones ----- */
  .recs-grid { grid-template-columns: 1fr; }

  /* ----- Shop controls: stack ----- */
  .shop-controls { flex-direction: column; gap: 10px; max-width: none; }

  /* ----- Welcome modal: lighter padding ----- */
  .welcome-cta button { min-width: 0; width: 100%; }
  .welcome-cta  { padding: 16px 18px 22px; }
  .welcome-hero { padding: 22px 20px 16px; }
  .welcome-body { padding: 18px 20px 6px; }
  .welcome-logo { width: 130px; }
}
