:root{
  /* Dark tokens — used only by the map canvas and its floating HUD chrome
     (colorbar, playback bar, hover badge, marker pulse, Leaflet/geoman
     controls), which stay dark against the dark basemap. Neutral slate-gray,
     no cyan/teal hue. */
  --ink:       #e7e9ec;
  --deep:      #14161a;
  --deep2:     #1c1e23;
  --panel:     #25272d;
  --line:      rgba(255,255,255,0.10);
  --teal:      #98a0aa;
  --amber:     #e8a355;

  /* Light tokens — the sidebar and everything in it (stats, controls, chart,
     legend). Grafana-style: soft neutral page bg, white cards. */
  --bg:           #f4f5f7;
  --surface:      #ffffff;
  --border:       #e3e6ea;
  --border-faint: #edeff2;
  --text:         #1e2530;
  --text-muted:   #66707d;
  --text-faint:   #99a2ad;
  --accent:       #0f766e;
  --accent-tint:  rgba(15,118,110,0.07);
  --shadow-sm:    0 1px 2px rgba(16,24,40,0.05);

  /* Chart series colors — light-chrome only (not referenced by any dark
     map/HUD element), tuned for AA contrast on a white card. */
  --loss: #d1453d;
  --gain: #3274d9;

  --mono: Arial, 'Helvetica Neue', Helvetica, sans-serif;
  --serif: 'Source Serif 4', Georgia, serif;
}

*{box-sizing:border-box;}
html,body{margin:0;height:100%;background:var(--bg);color:var(--text);font-family:var(--mono);overflow:hidden;}

#app{
  height:100vh;
  width:100vw;
}

/* ── FULL-VIEWPORT MAP ──────────────────────────────────────────────────────
   The map is the background; floating panels overlay it. left/right start at 0
   (full width) and panels.js insets them to the dock-column widths when panels
   are docked, so the map shrinks to the central area instead of hiding behind a
   dock. top/bottom stay 0 (behind the toolbar) so the Leaflet-control offsets
   below still line up. */
#map{
  position:fixed;
  top:0; bottom:0; left:0; right:0;
  z-index:0;
  background:var(--deep);
}
.leaflet-container{
  background:var(--deep) !important;
  font-family:var(--mono);
}
/* Push Leaflet's own top-left controls (zoom + geoman draw tools) below the
   toolbar so the toolbar never covers them. */
.leaflet-top.leaflet-left{ margin-top:46px; }

/* ── TOP TOOLBAR (editor / macOS style) ─────────────────────────────────────
   A compact strip of icon+label toggle buttons, left-aligned. Not a nav/brand
   header -- just the app's tool row. */
#toolbar{
  position:fixed;
  top:0; left:0; right:0;
  height:40px;
  z-index:2000;
  display:flex;
  align-items:center;
  padding:0 8px;
  background:var(--surface);
  border-bottom:1px solid var(--border);
  box-shadow:0 1px 2px rgba(16,24,40,0.05);
}
.tb-group{
  display:flex;
  align-items:center;
  gap:2px;
}
/* Toolbar toggle button — icon + label, quiet by default, tinted-pressed when
   its panel is shown (panels.js sets .active). Like a segmented toolbar button. */
.tb-btn{
  display:inline-flex;
  align-items:center;
  gap:6px;
  height:28px;
  padding:0 9px;
  font-family:var(--mono);
  font-size:11.5px;
  letter-spacing:0.01em;
  color:var(--text-muted);
  background:transparent;
  border:1px solid transparent;
  border-radius:6px;
  cursor:pointer;
  transition:background 0.1s, color 0.1s, border-color 0.1s;
}
.tb-ico{
  width:15px;
  height:15px;
  flex:none;
}
.tb-btn:hover{ background:var(--bg); color:var(--text); }
.tb-btn.active{
  background:var(--accent-tint);
  border-color:rgba(15,118,110,0.28);
  color:var(--accent);
}

/* ── FLOATING PANELS ────────────────────────────────────────────────────────
   position:fixed cards positioned by panels.js (left/top inline styles). */
.panel{
  position:fixed;
  z-index:1200;
  width:300px;
  display:flex;
  flex-direction:column;
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:10px;
  box-shadow:0 6px 24px rgba(16,24,40,0.12);
  overflow:hidden;
}
.panel.panel-wide{ width:420px; }
/* Ghost the dragged panel a touch so the dock drop-line stays visible under it. */
.panel.dragging{ box-shadow:0 12px 32px rgba(16,24,40,0.22); opacity:0.85; }
.panel.snapped{ border-color:rgba(15,118,110,0.4); }
/* Hidden state — panels.js toggles this in tandem with the toolbar button. */
.panel[hidden]{ display:none; }

.panel-header{
  display:flex;
  align-items:center;
  gap:8px;
  padding:8px 8px 8px 12px;
  background:var(--bg);
  border-bottom:1px solid var(--border);
  cursor:grab;
  user-select:none;
}
.panel-header:active{ cursor:grabbing; }
.panel-title{
  flex:1;
  font-family:var(--mono);
  font-size:12px;
  font-weight:600;
  letter-spacing:0.01em;
  color:var(--text);
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.panel-actions{ display:flex; gap:2px; }
.panel-btn{
  width:22px;
  height:22px;
  display:flex;
  align-items:center;
  justify-content:center;
  border:none;
  background:transparent;
  color:var(--text-faint);
  border-radius:5px;
  cursor:pointer;
  position:relative;
}
.panel-btn:hover{ background:var(--border); color:var(--text); }
/* Icons drawn in CSS so no assets/fonts are needed. Collapse = a minus bar;
   close = an ×. */
.panel-collapse::before{
  content:"";
  width:10px; height:2px;
  background:currentColor;
  border-radius:1px;
}
.panel.collapsed .panel-collapse::before{
  /* becomes a + affordance (expand) via a crossing bar */
  box-shadow:0 0 0 0 transparent;
}
.panel.collapsed .panel-collapse::after{
  content:"";
  position:absolute;
  width:2px; height:10px;
  background:currentColor;
  border-radius:1px;
}
.panel-close::before,
.panel-close::after{
  content:"";
  position:absolute;
  width:12px; height:2px;
  background:currentColor;
  border-radius:1px;
}
.panel-close::before{ transform:rotate(45deg); }
.panel-close::after{ transform:rotate(-45deg); }

.panel-body{
  padding:16px;
  display:flex;
  flex-direction:column;
  gap:16px;
  overflow-y:auto;
  /* Always reserve the scrollbar gutter so a chart's width never shifts when
     the vertical resizer makes the body scroll -- the height resizer must only
     clip, never rescale the charts. */
  scrollbar-gutter:stable;
  max-height:calc(100vh - 140px);
}
.panel.collapsed .panel-body{ display:none; }

/* Panel resize handles: south edge (height), east edge (width), and the SE
   corner (both). The height handle only sets the body's height -- content past
   it is clipped and reached via the body's own scrollbar, so the chart cards
   keep their fixed size and never rescale. The width/corner handles do resize
   the panel (and the charts reflow to the new width, like the dock resizer).
   When docked, width is the column's job, so only the south handle shows. */
.panel-rz{ position:absolute; z-index:4; }
.panel-rz-s{ left:9px; right:9px; bottom:0; height:8px; cursor:ns-resize; }
.panel-rz-e{ top:0; bottom:9px; right:0; width:8px; cursor:ew-resize; }
.panel-rz-w{ top:0; bottom:9px; left:0; width:8px; cursor:ew-resize; }
.panel-rz-se{ right:0; bottom:0; width:13px; height:13px; cursor:nwse-resize; z-index:5; }
/* Subtle grips, shown on panel hover / while resizing. */
.panel-rz-s::after{
  content:""; position:absolute; left:50%; bottom:2px; transform:translateX(-50%);
  width:26px; height:3px; border-radius:2px; background:var(--border);
  opacity:0; transition:opacity 0.12s;
}
.panel-rz-se::after{
  content:""; position:absolute; right:2px; bottom:2px;
  width:7px; height:7px;
  border-right:2px solid var(--border); border-bottom:2px solid var(--border);
  opacity:0; transition:opacity 0.12s;
}
.panel:hover .panel-rz-s::after,
.panel:hover .panel-rz-se::after{ opacity:1; }
.panel-rz-s:hover::after,
.panel.resizing .panel-rz-s::after{ background:var(--text-faint); opacity:1; }
.panel-rz-se:hover::after,
.panel.resizing .panel-rz-se::after{ border-color:var(--text-faint); opacity:1; }
/* Docked: only vertical height adjust; width + corner belong to the column. */
.panel.docked .panel-rz-e,
.panel.docked .panel-rz-w,
.panel.docked .panel-rz-se,
.panel.collapsed .panel-rz{ display:none; }

/* ── DOCK COLUMNS (Premiere / VS Code style) ────────────────────────────────
   Fixed edge columns that reserve space; the map shrinks to the middle. Empty
   columns are [hidden] (width 0). panels.js re-parents .panel elements in and
   sets the width. */
.dock{
  position:fixed;
  top:40px;              /* below the toolbar */
  bottom:0;
  z-index:1000;          /* above the map, below floating panels (1200) */
  width:340px;
  background:var(--bg);
  display:flex;
  flex-direction:column;
  overflow-y:auto;
  overflow-x:hidden;
}
.dock[hidden]{ display:none; }
#dock-left{ left:0; border-right:1px solid var(--border); }
#dock-right{ right:0; border-left:1px solid var(--border); }

/* Draggable divider on the column's outer edge -> resize the dock width.
   position:fixed (not absolute) so it escapes the column's scroll box: panels.js
   pins it to the column's viewport edge, past the scrollbar, so a mouse coming in
   from the map hits the resize zone before the scrollbar. */
.dock-resizer{
  position:fixed;
  top:40px; bottom:0;      /* below the toolbar, matching the dock */
  width:6px;
  z-index:1100;            /* above dock content + scrollbar, below floating panels (1200) */
  cursor:col-resize;
}
.dock-resizer:hover, .dock-resizer.active{ background:var(--accent-tint); }

/* A docked panel: flush, stacked, full-width; loses the floating chrome. */
.panel.docked{
  position:relative;   /* stays in the column's flow, but anchors the S resizer */
  width:100%;
  z-index:auto;
  border:none;
  border-radius:0;
  border-bottom:1px solid var(--border);
  box-shadow:none;
  flex:none;
}
.panel.docked .panel-header{ cursor:grab; }
.panel.docked .panel-body{ max-height:none; }   /* the column scrolls instead */

/* Drop indicators shown while dragging over a dock. */
.dock.drop-target{ box-shadow:inset 0 0 0 2px rgba(15,118,110,0.45); }
.dock-dropline{
  height:0;
  border-top:2px solid var(--accent);
  margin:-1px 0;
  pointer-events:none;
}

.prompt{
  font-family:var(--serif);
  font-size:17px;
  line-height:1.5;
  color:var(--text);
  padding:14px 16px;
  border:1px solid var(--border);
  border-left:3px solid var(--accent);
  background:var(--accent-tint);
  border-radius:6px;
  box-shadow:var(--shadow-sm);
}
.prompt b{color:var(--accent); font-weight:600;}

.coord-row{
  display:flex;
  gap:10px;
}
.stat{
  flex:1;
  border:1px solid var(--border);
  padding:10px 12px;
  border-radius:8px;
  background:var(--surface);
  box-shadow:var(--shadow-sm);
}
.stat .label{font-size:10.5px;letter-spacing:0.01em;color:var(--text-muted);margin-bottom:4px;}
.stat .value{font-size:16px;font-weight:500;color:var(--text);}
.stat .value.small{font-size:13px;}

/* ── MASK CHIPS ─────────────────────────────────────────────────────────── */
/* Container for mask membership chips shown below the coord stats.         */
/* Inserted into the DOM by app.js; visibility is toggled by updateMaskDisplay(). */
.mask-info{
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  /* negative margin-top pulls it closer to the coord stats row above */
  margin-top: -6px;
}

/* Individual chip — border-color and color are set inline by app.js so each
   mask gets its own tint without extra CSS classes. */
.mask-chip{
  font-size: 10.5px;
  letter-spacing: 0.01em;
  padding: 3px 9px;
  border-radius: 4px;
  border: 1px solid;          /* colour comes from inline style */
  background: rgba(15,23,42,0.04);
  white-space: nowrap;
}
/* ── END MASK CHIPS ─────────────────────────────────────────────────────── */

/* ── BOUNDARY VERTEX LIST ───────────────────────────────────────────────── */
/* Lists the drawn region's vertices (lon/lat). Shown only in region mode;    */
/* visibility toggled by renderVertexList() / enterPointMode() in app.js.      */
.region-vertices{
  margin-top: 2px;
  padding: 8px 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: var(--shadow-sm);
}
.region-vertices .label{
  font-size: 10.5px;
  letter-spacing: 0.01em;
  color: var(--text-muted);
  margin-bottom: 6px;
}
.region-vertices ol{
  list-style: decimal inside;
  margin: 0;
  padding: 0;
  max-height: 150px;
  overflow-y: auto;
  font-size: 11.5px;
  color: var(--text);
}
.region-vertices li{
  padding: 1px 0;
  letter-spacing: 0.02em;
}
.region-vertices li::marker{ color: var(--text-muted); }

/* Unified selection list: one colour-matched card per plotted selection. Point
   cards show the cell + clicked coord (and basin); region cards add cells/area
   and the boundary's vertex list. Several coexist in compare mode. */
.selection-list{ display:flex; flex-direction:column; gap:8px; }
.region-item{
  padding:8px 10px;
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:8px;
  box-shadow:var(--shadow-sm);
}
.region-item-head{
  display:flex;
  align-items:center;
  gap:7px;
  font-size:11px;
  color:var(--text);
  margin-bottom:6px;
}
.region-item-title{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* Inline rename <input>, styled to sit in the same spot the title <span>
   would -- same size/weight, just with a visible edit affordance. */
.region-rename-input{
  min-width:0; flex:1;
  font: inherit; color:var(--text);
  background:var(--surface);
  border:1px solid var(--accent); border-radius:3px;
  padding:1px 4px; margin:-1px 0;
}
.region-rename-input:focus{ outline:none; box-shadow:0 0 0 2px var(--accent-tint); }
/* Per-region action icons (rename, export .xyz, land-only mask), grouped and
   pinned to the right of the card's swatch+title row via the auto left-margin
   on the group itself so buttons stay adjacent regardless of which show. */
.region-item-actions{ flex:none; margin-left:auto; display:flex; gap:2px; }
.region-rename-btn, .region-export-btn, .region-landmask-btn{
  flex:none;
  width:18px; height:18px;
  display:flex; align-items:center; justify-content:center;
  padding:0; border:none; background:transparent;
  color:var(--text-faint); border-radius:4px; cursor:pointer;
}
.region-rename-btn:hover, .region-export-btn:hover, .region-landmask-btn:hover{ background:var(--border); color:var(--text); }
.region-rename-btn svg, .region-export-btn svg, .region-landmask-btn svg{ width:12px; height:12px; }
.region-landmask-btn:disabled{ opacity:0.4; cursor:default; background:transparent; }
.region-item-verts{
  list-style:decimal inside;
  margin:0; padding:0;
  max-height:120px;
  overflow-y:auto;
  font-size:11.5px;
  color:var(--text);
}
.region-item-verts li{ padding:1px 0; letter-spacing:0.02em; }
.region-item-verts li::marker{ color:var(--text-muted); }
/* Point card: reuses the region card shell (.region-item), with muted sub-lines
   for the clicked coord + basin membership. */
.sel-card-sub{ font-size:10.5px; color:var(--text-muted); margin-top:2px; letter-spacing:0.01em; }
.selection-empty{ font-size:11.5px; color:var(--text-faint); line-height:1.5; }
/* ── END BOUNDARY VERTEX LIST ───────────────────────────────────────────── */

/* The main chart card and each basin mini-chart share these rules so a basin
   chart looks identical to the main one -- same rounded card, title, and trend. */
.chart-card,
.basin-chart-block{
  position:relative;
  height:292px;
  border:1px solid var(--border);
  border-radius:8px;
  background:var(--surface);
  box-shadow:var(--shadow-sm);
  /* Extra bottom padding keeps the rotated year labels inside the card with
     clearance instead of sitting on the border / bleeding toward the next
     chart. */
  padding:12px 14px 18px;
}
.chart-title,
.basin-chart-title{
  font-size:12px;
  color:var(--text-muted);
  letter-spacing:0.03em;
  margin-bottom:6px;
  display:flex;
  justify-content:space-between;
  align-items:center;
  gap:10px;
}
/* Main chart title truncates on one line (like the basin titles) so a long
   "Mass anomaly at ..." never wraps and pushes the plot down when the panel is
   narrow. The full text is on hover via the tooltip below. */
.chart-title-text{
  min-width:0;
  overflow:hidden;
  white-space:nowrap;
  /* text-overflow:ellipsis; */
}
.chart-rename-input{
  min-width:80px;
  width:100%;
  height:22px;
  padding:2px 5px;
  font:inherit;
  color:var(--text);
  background:var(--surface);
  border:1px solid var(--accent);
  border-radius:4px;
}
.chart-rename-input:focus{ outline:none; box-shadow:0 0 0 2px var(--accent-tint); }
.chart-rename-btn{
  flex:none;
  width:20px; height:20px;
  display:flex; align-items:center; justify-content:center;
  padding:0; margin:0;
  border:none; background:transparent;
  color:var(--text-faint);
  border-radius:5px;
  cursor:pointer;
}
.chart-rename-btn:hover{ background:var(--border); color:var(--text); }
.chart-rename-btn svg{ width:12px; height:12px; }
.chart-title .trend,
.basin-chart-title .trend{font-family:var(--mono); font-size:12px; white-space:nowrap; flex:none;}
/* "Export chart as PNG" icon button, sits after the trend badge -- on both
   the main chart's title row (static markup) and each basin mini-chart's
   title row (built at render time in renderBasinCharts). */
.chart-export-btn{
  flex:none;
  width:20px; height:20px;
  display:flex; align-items:center; justify-content:center;
  padding:0; margin:0;
  border:none; background:transparent;
  color:var(--text-faint);
  border-radius:5px;
  cursor:pointer;
}
.chart-export-btn:hover{ background:var(--border); color:var(--text); }
.chart-export-btn:disabled{ opacity:0.4; cursor:default; background:transparent; }
.chart-export-btn svg{ width:13px; height:13px; }
.chart-title .trend.gain,
.basin-chart-title .trend.gain{color:var(--gain);}
.chart-title .trend.loss,
.basin-chart-title .trend.loss{color:var(--loss);}

.empty-note{
  font-size:13px;
  color:var(--text-faint);
  line-height:1.6;
  padding-top:4px;
}

#loading-note{
  position:absolute;
  top:50%;
  left:50%;
  z-index:1000;
  transform:translate(-50%, -50%);
  width:max-content;
  max-width:min(560px, calc(100% - 40px));
  padding:12px 18px;
  color:var(--ink);
  background:rgba(37,39,45,0.94);
  border:1px solid var(--line);
  border-radius:7px;
  box-shadow:0 8px 28px rgba(0,0,0,0.32);
  font-size:13px;
  font-weight:600;
  line-height:1.5;
  text-align:center;
  pointer-events:none;
}

.region-loading{
  position:absolute;
  inset:0;
  display:flex;
  align-items:center;
  justify-content:center;
  background:rgba(255,255,255,0.85);
  font-size:12.5px;
  color:var(--accent);
  letter-spacing:0.03em;
  border-radius:8px;
}

/* #clearRegionBtn and #applyVertexBtn both use .panel-btn-action (below). */
#applyVertexBtn {
    width: fit-content;
}
#clearRegionBtn {
    width: fit-content;
    display: block;   /* Forces the button to act as a block element */
    margin: 0 auto;   /* Automatically splits the remaining space on the left and right */
}
/* ── INSERT-BOUNDARY-FROM-VERTICES INPUT ────────────────────────────────────
   Paste a vertex list to draw a boundary (the inverse of the vertex display). */
.vertex-input{
  display:flex;
  flex-direction:column;
  gap:6px;
}
.vertex-input .label{
  font-size:10.5px;
  letter-spacing:0.01em;
  color:var(--text-muted);
}
#vertexInputBlock {
    display: flex;
    flex-direction: column; /* ensuring it stacks vertically */
    align-items: center;    /* centers children horizontally */
}
#vertexInput{
  width:100%;
  resize:vertical;
  min-height:70px;
  /* Real monospace here (unlike the app's proportional --mono) so pasted
     coordinate columns line up -- reads as a data field, not a text box. */
  font-family:'SFMono-Regular', ui-monospace, 'JetBrains Mono', Consolas, monospace;
  font-size:11px;
  line-height:1.6;
  color:var(--text);
  background:var(--bg);
  border:1px solid var(--border);
  border-radius:6px;
  padding:8px 10px;
}
#vertexInput:focus{
  outline:none;
  background:var(--surface);
  border-color:rgba(15,118,110,0.55);
  box-shadow:0 0 0 3px var(--accent-tint);
}
#vertexInput::placeholder{ color:var(--text-faint); }
.vertex-input-hint{
  font-size:10px;
  line-height:1.45;
  color:var(--text-faint);
}

#importMaskBtn {
    width: fit-content;
    margin: 0 auto;   /* Automatically centers horizontally */
}
.vertex-input-hint b{ color:var(--text-muted); font-weight:600; font-family:'SFMono-Regular', ui-monospace, Consolas, monospace; }
/* Shared style for the panel action buttons (Draw boundary / Clear boundary).
   Uses the app's restrained emphasis -- the same light accent tint an active
   toolbar button uses, never a solid fill -- with an icon + label so it reads
   as a designed control (the toolbar's vocabulary), not a default button. The
   two region buttons are deliberately identical: this tool favours calm
   consistency over shouted primary/secondary hierarchy. */
.panel-btn-action{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:7px;
  width:100%;
  padding:8px 12px;
  font-family:var(--mono);
  font-size:11.5px;
  letter-spacing:0.02em;
  color:var(--accent);
  background:var(--accent-tint);
  border:1px solid rgba(15,118,110,0.28);
  border-radius:6px;
  cursor:pointer;
  transition:background 0.1s, border-color 0.1s;
}
.panel-btn-action:hover{ background:rgba(15,118,110,0.13); border-color:rgba(15,118,110,0.45); }
.panel-btn-action:active{ background:rgba(15,118,110,0.18); }
.panel-btn-action .btn-ico{ width:14px; height:14px; flex:none; }
/* Result/validation line under the textarea. Styled as a left-bar callout
   (the app's .prompt pattern) -- deliberately NOT a rounded tinted pill, so a
   status message never reads as a clickable button like the actions above it. */
.input-msg{
  font-size:11px;
  line-height:1.4;
  padding:6px 10px;
  border-radius:0 4px 4px 0;
  border-left:3px solid transparent;
}
.input-msg.error{ color:var(--loss);   background:rgba(209,69,61,0.07);  border-left-color:var(--loss); }
.input-msg.warn{  color:#9a6a12;        background:rgba(232,163,85,0.10); border-left-color:var(--amber); }
.input-msg.ok{    color:var(--text-muted); background:rgba(15,118,110,0.05); border-left-color:var(--accent); }

/* geoman toolbar, restyled to match the dark theme */
.leaflet-pm-toolbar .leaflet-pm-icon-polygon,
.leaflet-pm-toolbar .leaflet-pm-icon-rectangle,
.leaflet-pm-toolbar .leaflet-pm-icon-edit,
.leaflet-pm-toolbar .leaflet-pm-icon-delete{
  filter: invert(0.9);
}
.leaflet-pm-toolbar a{
  background:var(--panel) !important;
  border-color:var(--line) !important;
}
.leaflet-pm-toolbar a:hover{
  background:#2a2d33 !important;
}
.leaflet-pm-actions-container a{
  background:var(--panel) !important;
  color:var(--ink) !important;
  border-color:var(--line) !important;
}

.legend{
  display:flex;
  align-items:center;
  gap:8px;
  font-size:10.5px;
  color:var(--text-muted);
  letter-spacing:0.03em;
}
.swatch{width:16px;height:4px;border-radius:2px;display:inline-block;}

footer.note{
  margin-top:auto;
  padding:14px 22px 18px;
  font-size:10.5px;
  color:var(--text-faint);
  line-height:1.6;
  border-top:1px solid var(--border);
}
footer.note a{color:var(--text-muted);}

/* ── HOVER COORDINATE TOOLTIP ──────────────────────────────────────────── */
/* Small badge that follows the cursor over the map, showing the lat/lon    */
/* under the pointer. Position (left/top) is updated by app.js on every     */
/* Leaflet 'mousemove' event; visibility toggled on mouseover/mouseout.     */
.hover-coord{
  position:absolute;
  z-index:1000;
  pointer-events:none;
  display:none;
  transform:translate(14px, 14px);
  background:rgba(20,22,26,0.88);
  color:var(--ink);
  font-family:var(--mono);
  font-size:11px;
  letter-spacing:0.02em;
  padding:4px 8px;
  border:1px solid var(--line);
  border-radius:4px;
  white-space:nowrap;
}
/* ── END HOVER COORDINATE TOOLTIP ──────────────────────────────────────── */

/* The point marker. --pulse-color is set inline per marker (app.js) so each
   Time Series window's point is drawn in that window's colour; it falls back to
   the neutral teal when unset. */
.marker-pulse{
  width:16px;height:16px;
  border-radius:50%;
  background:var(--pulse-color, var(--teal));
  box-shadow:0 0 0 0 color-mix(in srgb, var(--pulse-color, var(--teal)) 55%, transparent);
  animation:pulse 1.8s infinite;
  border:2px solid var(--deep);
}
@keyframes pulse{
  0%{box-shadow:0 0 0 0 color-mix(in srgb, var(--pulse-color, var(--teal)) 55%, transparent);}
  70%{box-shadow:0 0 0 14px color-mix(in srgb, var(--pulse-color, var(--teal)) 0%, transparent);}
  100%{box-shadow:0 0 0 0 color-mix(in srgb, var(--pulse-color, var(--teal)) 0%, transparent);}
}

/* A window's colour chip in its chart title, matching that window's map marker
   so several open windows stay easy to tell apart. Hidden until a selection is
   plotted (app.js toggles display). */
.chart-title-main{ display:inline-flex; align-items:center; gap:7px; min-width:0; }
.ts-swatch{
  display:inline-block;
  width:9px; height:9px;
  border-radius:50%;
  flex:none;
  border:1px solid rgba(16,24,40,0.15);
}

::-webkit-scrollbar{width:8px;}
::-webkit-scrollbar-track{background:transparent;}
::-webkit-scrollbar-thumb{background:#d5d9df;border-radius:4px;}

.leaflet-control-attribution{
  background:rgba(20,22,26,0.75) !important;
  color:#8a929c !important;
}
.leaflet-control-attribution a{color:#aab0b8 !important;}
.leaflet-control-zoom a{
  background:var(--panel) !important;
  color:var(--ink) !important;
  border-color:var(--line) !important;
}

/* On narrow screens a floating layout stops making sense: pin panels to a
   single full-width column below the toolbar and let the page scroll. */
@media (max-width: 820px){
  .panel{
    position:static !important;
    width:auto !important;
    margin:12px;
    left:auto !important;
    top:auto !important;
  }
  .panel.panel-wide{ width:auto !important; }
  #app{ padding-top:48px; height:auto; overflow-y:auto; }
  body{ overflow:auto; }
}

  /* Stack the basin cards with the same 18px rhythm the sidebar uses between
     sections -- identical cards, one after another, no separator line. */
  .basin-wrap { display:flex; flex-direction:column; gap:18px; }
  /* Left side of the title (swatch + basin name); truncates instead of wrapping
     so the card height and trend position stay identical to the main chart. */
  .basin-chart-label {
    display:inline-flex;
    align-items:center;
    gap:6px;
    min-width:0;
    overflow:hidden;
    white-space:nowrap;
    text-overflow:ellipsis;
  }
  .basin-chart-swatch {
    display:inline-block;
    width:14px;
    height:4px;
    border-radius:2px;
    flex:none;
  }
  /* Hover tooltip revealing the basin name the label truncates. It hangs off
     the title row rather than the label itself, because the label's
     overflow:hidden (which draws the ellipsis) would clip it. z-index lifts it
     over the chart canvas that follows it in the card. */
  .basin-chart-title[data-tooltip],
  .chart-title[data-tooltip]{ position:relative; z-index:2; }
  .basin-chart-title[data-tooltip]:has(.basin-chart-label:hover)::after,
  .chart-title[data-tooltip]:has(.chart-title-text:hover)::after{
    content:attr(data-tooltip);
    position:absolute;
    left:0;
    top:100%;
    margin-top:6px;
    background:var(--text);
    color:#fff;
    font-family:var(--mono);
    font-size:11px;
    line-height:1.45;
    letter-spacing:0.01em;
    white-space:normal;
    max-width:280px;
    padding:6px 9px;
    border-radius:6px;
    box-shadow:0 4px 12px rgba(16,24,40,0.18);
    pointer-events:none;
  }

.mask-controls{
  display:flex;
  flex-direction:column;
  gap:8px;
  margin:10px 0;
  padding:10px 12px;
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:8px;
  box-shadow:var(--shadow-sm);
  font-family:var(--mono);
  font-size:12.5px;
  color:var(--text);
}
/* Sub-section header inside the Controls card ("Map", "Time series"). Quiet,
   sentence-case (no all-caps), with a hairline divider above the 2nd+ group. */
.mask-controls .control-group-title{
  font-family:var(--mono);
  font-size:11px;
  font-weight:600;
  letter-spacing:0.01em;
  color:var(--text-muted);
}
.mask-controls .control-group-title:not(:first-child){
  margin-top:4px;
  padding-top:12px;
  border-top:1px solid var(--border-faint);
}
.mask-controls .mask-visible-toggle{
  display:flex;
  align-items:center;
  gap:6px;
  cursor:pointer;
}
/* "Show mask overlay" + "Mask set" share a row when there's room, wrapping to
   two lines instead of overflowing/squeezing once the column gets narrow
   (e.g. docked). */
.mask-overlay-row{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:6px 16px;
}
.mask-overlay-row .mask-set-picker{ flex:1 1 auto; min-width:0; }
.mask-import-row{ width:100%; }
/* Session-only imported masks (see importMask* in app.js) -- name, cell
   count, and a remove button, since these can't be un-imported any other
   way (they aren't files on disk to delete). */
.imported-masks-list{
  display:flex; flex-direction:column; gap:4px;
  width:100%;
}
.imported-mask-chip{
  display:flex; align-items:center; gap:6px;
  padding:5px 8px;
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:6px;
  font-size:11px;
  color:var(--text);
}
.imported-mask-chip .ts-swatch{ flex:none; }
.imported-mask-chip .imported-mask-name{
  flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.imported-mask-chip .imported-mask-count{ flex:none; color:var(--text-muted); font-family:var(--mono); font-size:10px; }
.imported-mask-remove{
  flex:none; width:16px; height:16px;
  display:flex; align-items:center; justify-content:center;
  padding:0; border:none; background:transparent; color:var(--text-faint);
  border-radius:4px; cursor:pointer; font-size:13px; line-height:1;
}
.imported-mask-remove:hover{ background:var(--border); color:var(--text); }
.imported-mask-export{
  flex:none; width:16px; height:16px;
  display:flex; align-items:center; justify-content:center;
  padding:0; border:none; background:transparent; color:var(--text-faint);
  border-radius:4px; cursor:pointer;
}
.imported-mask-export svg{ width:11px; height:11px; }
.imported-mask-export:hover{ background:var(--border); color:var(--text); }
/* Eye icon: whether this mask's time series is currently shown (derived
   state, see renderImportedMasksList) -- open+dot when on, slashed when off. */
.mask-eye-btn{
  flex:none; width:18px; height:18px;
  display:flex; align-items:center; justify-content:center;
  padding:0; border:none; background:transparent; color:var(--text-faint);
  border-radius:4px; cursor:pointer;
}
.mask-eye-btn svg{ width:13px; height:13px; }
.mask-eye-btn:hover{ background:var(--border); color:var(--text); }
.mask-eye-btn.active{ color:var(--accent); }
.mask-eye-btn.active:hover{ background:var(--accent-tint); }
/* "Show data gaps" toggle — same look as the other mask-control toggles
   (inherits the .mask-controls 12.5px / --ink colour rather than the smaller
   grey it used to have). */
.gap-toggle{
  display:flex;
  align-items:center;
  gap:6px;
  cursor:pointer;
}
/* Fit-type sub-toggles nested under "Show best-fit line(s)" — indented,
   each with a colour swatch matching its line/label colour on the chart. */
.fit-subtoggles{
  display:flex;
  flex-direction:column;
  gap:4px;
  margin-left:22px;
  padding:2px 0 2px 8px;
  border-left:1px solid var(--border-faint);
}
.fit-subtoggle .label{ font-size:12px; }
.fit-swatch{
  width:9px; height:9px; border-radius:2px; flex:0 0 auto;
}
/* "Show coefficients & equation" is a display option, not a fit type -- set
   it apart from the fit-type checkboxes above with a hairline + extra gap. */
.fit-subtoggle-option{
  margin-top:4px;
  padding-top:6px;
  border-top:1px dashed var(--border-faint);
}
.mask-controls .mask-set-picker{
  display:flex;
  align-items:center;
  justify-content:flex-start;
  gap:8px;
}
.mask-controls .mask-set-picker select{
  font-family:inherit;
  font-size:inherit;
  background:var(--bg);
  color:inherit;
  border:1px solid var(--border);
  border-radius:4px;
  padding:3px 6px;
  flex: 0 1 auto;
  min-width: 0;
  width: 100%;
  max-width: max-content;
}

/* ── SPATIAL-EDA DATA RASTERS ───────────────────────────────────────────── */
/* On-map colour legend (viz/colorbar.js) and the temporal playback bar        */
/* (viz/playback.js) float over the map; raster toggles (viz/heatmap.js,       */
/* viz/trendLayer.js) live in #rasterControls in the sidebar. All positioned   */
/* relative to #map, which Leaflet makes a positioning context.                */
#colorbarBox{
  position:absolute;
  left:12px;
  bottom:72px;
  /* Above Leaflet's own panes (marker 600 / tooltip 650 / popup 700) but below
     the hover-coord badge (1000). */
  z-index:800;
  display:flex;
  flex-direction:column;
  gap:8px;
  pointer-events:none;
}
.colorbar-entry{
  width:196px;
  padding:8px 10px 7px;
  background:rgba(20,22,26,0.86);
  border:1px solid var(--line);
  border-radius:6px;
  font-family:var(--mono);
}
.colorbar-title{
  font-size:10px;
  letter-spacing:0.01em;
  color:#a0a6ad;
  margin-bottom:6px;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.colorbar-bar{
  height:10px;
  border-radius:2px;
  border:1px solid rgba(255,255,255,0.15);
}
.colorbar-scale{
  display:flex;
  justify-content:space-between;
  margin-top:4px;
  font-size:10px;
  color:#8a929c;
}

#playbackBar{
  position:absolute;
  left:50%;
  transform:translateX(-50%);
  bottom:14px;
  z-index:800;   /* above Leaflet panes; slider stays clickable */
  display:flex;
  align-items:center;
  gap:12px;
  width:min(680px, calc(100% - 32px));
  padding:8px 14px;
  background:rgba(20,22,26,0.88);
  border:1px solid var(--line);
  border-radius:8px;
  font-family:var(--mono);
}
/* Bare icon — an inline SVG (▶ triangle / ⏸ two bars, same 16×16 box so both
   render identically) is the button; no circular chrome behind it. */
#playbackBar .pb-play{
  flex:none;
  display:flex;align-items:center;justify-content:center;
  padding:0;
  border:none;
  background:none;
  color:var(--teal);
  cursor:pointer;
}
#playbackBar .pb-play svg{display:block;}
#playbackBar .pb-play:hover{color:#c3c8ce;}
#playbackBar input[type=range]{
  flex:1;
  accent-color:var(--teal);
  cursor:pointer;
}
#playbackBar .pb-date{
  flex:none;
  min-width:96px;
  text-align:right;
  font-size:12.5px;
  color:var(--ink);
  letter-spacing:0.02em;
}

/* Trend date-range picker (viz/trendLayer.js) -- a dual-handle slider built
   from two overlapping <input type=range>, a shared visual track, and a
   filled span between the two thumbs. Standard "two native range inputs,
   transparent everywhere except the thumb" technique: pointer-events:none on
   the input lets clicks pass through to whichever thumb is on top, with the
   thumb itself opted back in via pointer-events:auto. */
.trend-range{ width:100%; margin-top:4px; }
.trend-range-hint{
  font-size:10.5px; color:var(--text-faint);
  margin-bottom:4px;
}
.trend-range-labels{
  display:flex; justify-content:space-between;
  font-family:var(--mono); font-size:10px; color:var(--text-muted);
  margin-bottom:3px;
}
.trend-range-slider{ position:relative; height:20px; }
.trend-range-track{
  position:absolute; left:7px; right:7px; top:9px; height:3px;
  background:var(--border); border-radius:2px;
}
.trend-range-fill{
  position:absolute; top:9px; height:3px;
  background:var(--accent); border-radius:2px;
}
.trend-range-slider input[type=range]{
  position:absolute; left:0; top:0;
  width:100%; height:20px; margin:0;
  background:transparent; pointer-events:none;
  -webkit-appearance:none; appearance:none;
}
.trend-range-slider input[type=range]::-webkit-slider-runnable-track{ background:transparent; height:20px; }
.trend-range-slider input[type=range]::-moz-range-track{ background:transparent; height:20px; }
.trend-range-slider input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none; appearance:none;
  width:14px; height:14px; margin-top:3px; border-radius:50%;
  background:var(--surface); border:2px solid var(--accent);
  cursor:pointer; pointer-events:auto;
}
.trend-range-slider input[type=range]::-moz-range-thumb{
  width:12px; height:12px; border-radius:50%;
  background:var(--surface); border:2px solid var(--accent);
  cursor:pointer; pointer-events:auto;
}
.trend-raster-note{ font-size:11px; color:var(--text-muted); margin-left:22px; }

/* Raster show/hide toggles appended into #rasterControls by the feature files. */
#rasterControls .raster-toggle{
  display:flex;
  align-items:center;
  gap:6px;
  cursor:pointer;
}
#rasterControls .raster-note{
  font-size:11px;
  color:var(--text-muted);
  margin-left:22px;
}
/* ── END SPATIAL-EDA DATA RASTERS ───────────────────────────────────────── */
