/* ============================================================
   TYPE SCALE — one knob.
   Every font-size in this file is in rem, relative to this value.
   Raise it to enlarge the entire interface proportionally
   (19px = original, 23px = current, try 25-26px for more).
   ============================================================ */
html{font-size:23px}

/* ============================================================
   Chl-a Bloom Explorer — design system
   Identity: hydrographic instrument. Deep-water slate, one cyan
   accent, a chlorophyll green→amber→red ramp reserved for data.
   The map and the numbers are the hero; chrome stays quiet.
   ============================================================ */
:root{
  /* palette — Daylight Lab (light + cyan) */
  --abyss:#eef3f6; --panel:#ffffff; --panel2:#e8eff3; --line:#cfdbe2;
  --foam:#153341; --muted:#5a7581; --hydro:#0e86b0; --hydro-dim:#57aac2;
  --lo:#2a9d5c; --mid:#e0aa00; --bloom:#e0483d;
  --warn-bg:#fff4df; --warn-line:#e6c079; --warn-fg:#8a5a12;
  --focus:#0e86b0;
  /* scale */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:22px; --s6:32px;
  --r:8px; --r-lg:12px; --r-sm:6px;
  --shadow:0 8px 24px rgba(21,51,65,.10);
  --t:.15s ease;
  --mono:"IBM Plex Mono",ui-monospace,monospace;
  --sans:"Space Grotesk",system-ui,-apple-system,sans-serif;
}
*{box-sizing:border-box}
html,body{margin:0;height:100%}
body{background:var(--abyss);color:var(--foam);font-family:var(--sans);
  font-size:1.0rem;line-height:1.65;display:flex;flex-direction:column;
  -webkit-font-smoothing:antialiased}
h1,h2,h3,p{margin:0}
a{color:var(--hydro)}
::selection{background:var(--hydro-dim);color:var(--foam)}

/* focus — visible for keyboard users only */
:focus-visible{outline:2px solid var(--focus);outline-offset:2px;border-radius:var(--r-sm)}
:focus:not(:focus-visible){outline:none}

/* scrollbars */
*{scrollbar-width:thin;scrollbar-color:var(--line) transparent}
*::-webkit-scrollbar{width:10px;height:10px}
*::-webkit-scrollbar-thumb{background:var(--line);border-radius:6px}

/* ---------- top nav ----------
   Two rows, two different marks for "selected". Tier one (water body) is a
   filled pill because it switches the whole context; tier two (tool) is an
   underline on a recessed strip because it is subordinate to it. Same colour,
   different shape — the hierarchy survives a glance. */
.nav{background:var(--panel);border-bottom:1px solid var(--line);flex:0 0 auto}
.navbar{display:flex;align-items:center;gap:var(--s4);
  padding:0 var(--s5);min-height:74px}
.nav .brand{margin:0;display:flex;align-items:center;gap:var(--s2);
  font-weight:700;font-size:1.105rem;letter-spacing:.2px;
  color:var(--foam);text-decoration:none}
.dot{width:9px;height:9px;border-radius:50%;background:var(--hydro);
  box-shadow:0 0 10px var(--hydro);flex:none}
.logo{width:34px;height:34px;flex:none;display:block}

/* tier 1 — water body */
.navlinks{display:flex;gap:var(--s1);margin-left:auto}
.navlinks a{color:var(--muted);text-decoration:none;font-family:var(--mono);
  font-size:0.789rem;letter-spacing:1px;text-transform:uppercase;
  padding:11px 17px;border-radius:var(--r-sm);display:flex;align-items:center;
  gap:7px;transition:background var(--t),color var(--t)}
.navlinks a:hover{color:var(--foam);background:var(--panel2)}
.navlinks a.nav-active{color:#ffffff;background:var(--hydro);font-weight:600}
/* the expectation is set before the click, not after it */
.navbadge{font-size:0.5rem;letter-spacing:.5px;padding:1px 5px;border-radius:3px;
  background:var(--warn-bg);color:var(--warn-fg);border:1px solid var(--warn-line);
  font-weight:600;line-height:1.5}
.navlinks a.nav-active .navbadge{background:rgba(255,255,255,.22);
  color:#ffffff;border-color:rgba(255,255,255,.4)}

/* About is a page, not a water body: separated, and it collapses tier 2 */
.navutil{display:flex;padding-left:var(--s3);margin-left:var(--s2);
  border-left:1px solid var(--line)}
.navutil a{color:var(--muted);text-decoration:none;font-family:var(--mono);
  font-size:0.737rem;letter-spacing:1px;text-transform:uppercase;
  padding:9px 14px;border-radius:var(--r-sm);transition:background var(--t),color var(--t)}
.navutil a:hover{color:var(--foam);background:var(--panel2)}
.navutil a.nav-active{color:#ffffff;background:var(--hydro);font-weight:600}

/* tier 2 — tool */
.navtools{display:flex;gap:var(--s5);padding:0 var(--s5);
  background:var(--panel2);border-top:1px solid var(--line)}
.navtools a,.navtools .navtool-off{font-family:var(--mono);font-size:0.684rem;
  letter-spacing:1.2px;text-transform:uppercase;padding:10px 2px;
  border-bottom:2px solid transparent;text-decoration:none;white-space:nowrap}
.navtools a{color:var(--muted);transition:color var(--t),border-color var(--t)}
.navtools a:hover{color:var(--foam);border-bottom-color:var(--line)}
.navtools a.tool-active{color:var(--hydro);border-bottom-color:var(--hydro);
  font-weight:600}
.navtools .navtool-off{color:var(--muted);opacity:.45;cursor:default}

/* ---------- app shell (Lakes, Sample) ---------- */
.app{flex:1;min-height:0;display:grid;grid-template-columns:500px 1fr}
.rail{background:var(--panel);border-right:1px solid var(--line);
  padding:var(--s5) var(--s4);overflow-y:auto;overflow-x:hidden;min-width:0}
.sub{color:var(--muted);font-size:0.789rem;margin-bottom:var(--s5)}
.group{margin-bottom:var(--s5)}
.eyebrow{font-family:var(--mono);font-size:0.711rem;letter-spacing:2px;
  text-transform:uppercase;color:var(--hydro);margin-bottom:var(--s3);font-weight:600}
label{display:block;font-size:0.816rem;color:var(--muted);margin:var(--s3) 0 var(--s1)}
select,input{width:100%;background:var(--panel2);color:var(--foam);
  border:1px solid var(--line);border-radius:var(--r-sm);padding:13px 14px;
  font:inherit;transition:border-color var(--t),box-shadow var(--t)}
select:hover,input:hover{border-color:var(--hydro-dim)}
select:focus,input:focus{border-color:var(--hydro);
  box-shadow:0 0 0 3px rgba(51,188,203,.18);outline:none}
.row{display:flex;gap:var(--s2);flex-wrap:wrap}
.row>*{flex:1 1 8.5rem;min-width:0}
/* a date field must never be clipped: give it room, or let it take a line */
.row input[type=date]{flex:1 1 8.8rem}
.hr{height:1px;background:var(--line);margin:var(--s5) 0}
.hint{font-size:0.789rem;color:var(--muted);margin-top:var(--s2);line-height:1.5}

/* buttons — one coherent system */
button{width:100%;margin-top:var(--s3);background:var(--hydro);color:#ffffff;
  border:0;border-radius:var(--r-sm);padding:14px 18px;font:inherit;font-weight:600;
  font-size:0.895rem;cursor:pointer;transition:background var(--t),transform var(--t),opacity var(--t)}
button:hover{background:#49cddb}
button:active{transform:translateY(1px)}
button:disabled{background:var(--hydro-dim);color:#eef8fb;cursor:progress;opacity:.8}
button.ghost{background:transparent;color:var(--hydro);
  border:1px solid var(--hydro-dim)}
button.ghost:hover{background:var(--panel2);color:var(--foam)}

/* layer toggles */
.layers{margin-top:var(--s3);display:flex;flex-direction:column;gap:var(--s2)}
.lyr{display:flex;align-items:center;gap:var(--s3)}
.lyr .ck{display:flex;align-items:center;gap:7px;margin:0;color:var(--foam);
  font-size:0.842rem;min-width:132px;cursor:pointer}
.lyr .ck input{width:auto;accent-color:var(--hydro)}
.lyr .sw{width:12px;height:12px;border-radius:3px;flex:none}
.lyr .sw.chla{background:linear-gradient(90deg,var(--lo),var(--mid),var(--bloom))}
.lyr .sw.bloom{background:var(--bloom)}
.lyr input[type=range]{flex:1;padding:0;accent-color:var(--hydro);cursor:pointer}
input[type=range]{accent-color:var(--hydro)}

/* ---------- main / map ---------- */
.main{display:flex;flex-direction:column;min-width:0}
.mapwrap{position:relative;flex:1 1 56%;min-height:300px;background:#06121a}
.mapwrap #map{position:absolute;inset:0}
.maploading{position:absolute;inset:0;z-index:640;display:flex;align-items:center;
  justify-content:center;gap:10px;background:rgba(6,18,26,.62);
  color:#eaf4f8;font-family:var(--mono);font-size:0.895rem;letter-spacing:.5px;
  backdrop-filter:blur(1px)}
.maploading[hidden]{display:none}
.results{flex:1 1 44%;overflow-y:auto;border-top:1px solid var(--line);
  background:var(--abyss);padding:var(--s4) var(--s5)}

/* readouts */
.readouts{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));
  gap:var(--s3);margin-bottom:var(--s4)}
.readout{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);
  padding:var(--s3) var(--s4);min-width:0;overflow-wrap:anywhere}
.readout .k{font-size:0.684rem;letter-spacing:1px;text-transform:uppercase;
  color:var(--muted);font-family:var(--mono)}
.readout .v{font-family:var(--mono);font-size:1.789rem;font-weight:600;margin-top:3px;
  line-height:1.1}
.readout .u{font-size:0.737rem;color:var(--muted);margin-top:3px}
.readout.bloom{border-color:#5e2a26}
.readout.bloom .v{color:var(--bloom)}

/* warning / status banner */
.warn{display:none;gap:10px;background:var(--warn-bg);border:1px solid var(--warn-line);
  color:var(--warn-fg);padding:10px 14px;border-radius:var(--r);
  font-size:0.842rem;margin-bottom:var(--s4);line-height:1.5}

/* legend */
.legend{display:flex;align-items:center;gap:12px;font-size:0.789rem;
  color:var(--muted);margin:2px 0 var(--s4);flex-wrap:wrap}
.ramp{height:12px;width:170px;border-radius:5px;
  background:linear-gradient(90deg,var(--lo),var(--mid),var(--bloom))}

/* tabs */
.tabs{display:flex;gap:var(--s1);margin-bottom:var(--s3);flex-wrap:wrap}
.tab{font-family:var(--mono);font-size:0.737rem;letter-spacing:1px;text-transform:uppercase;
  padding:11px 17px;border:1px solid var(--line);border-radius:var(--r-sm);
  color:var(--muted);cursor:pointer;background:var(--panel);
  transition:background var(--t),color var(--t),border-color var(--t)}
.tab:hover{color:var(--foam);border-color:var(--hydro-dim)}
.tab.active{color:#ffffff;background:var(--hydro);border-color:var(--hydro);font-weight:600}
.pane{display:none}
.pane.active{display:block}

/* charts */
.chartbox{position:relative;height:400px;width:100%}
.chartbox canvas{position:absolute;inset:0}

/* tables */
.tablewrap{max-height:380px;overflow:auto;border:1px solid var(--line);border-radius:var(--r)}
table{width:100%;border-collapse:collapse;font-family:var(--mono);font-size:0.842rem}
th,td{padding:11px 13px;text-align:right;border-bottom:1px solid var(--line);white-space:nowrap}
th{color:var(--hydro);font-weight:600;position:sticky;top:0;background:var(--abyss);
  letter-spacing:.5px}
th:first-child,td:first-child{text-align:left}
tr:hover td{background:rgba(14,134,176,.06)}
tr.isbloom td{color:var(--bloom)}
.empty{color:var(--muted);font-size:0.895rem;padding:30px 22px;text-align:center}

/* spinner */
.spin{display:inline-block;width:13px;height:13px;border:2px solid currentColor;
  border-top-color:transparent;border-radius:50%;animation:spin .7s linear infinite;
  vertical-align:-2px}
@keyframes spin{to{transform:rotate(360deg)}}

/* validate input rows */
.vrow{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap}
.vrow input[type=number],.vrow input[type=date]{width:auto;flex:1;min-width:96px}
.vrow input[type=file]{color:var(--muted);font-size:0.816rem}
.vrow button{margin:0;flex:0 0 auto;width:auto}

/* ---------- content pages (Validate / About) ---------- */
.page{flex:1;overflow:auto;padding:var(--s6) var(--s5)}
.page .wrap{max-width:920px;margin:0 auto}
.page h2{font-size:1.684rem;font-weight:700;margin:var(--s2) 0 var(--s2)}
.page h3{font-size:0.895rem;color:var(--hydro);letter-spacing:1.5px;text-transform:uppercase;
  font-family:var(--mono);margin:var(--s5) 0 var(--s2);font-weight:600}
.page p,.page li{color:var(--foam);opacity:.9;max-width:72ch}
.page li{margin:var(--s1) 0}
.page .muted{color:var(--muted);opacity:1}
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--s5);box-shadow:var(--shadow)}


code{font-family:var(--mono);font-size:.92em;background:var(--panel2);
  border:1px solid var(--line);border-radius:4px;padding:1px 5px}


/* confusion matrix */
table.cm td,table.cm th{text-align:center;vertical-align:middle}
table.cm th.rh{text-align:left;color:var(--foam);font-weight:600;white-space:nowrap}
table.cm td b{font-size:1.368rem;font-family:var(--mono);display:block;line-height:1.15}
table.cm td .cell{font-size:0.632rem;color:var(--muted);font-family:var(--sans);display:block;margin-top:2px}
table.cm td.good{background:rgba(42,157,92,.10)}
table.cm td.good b{color:var(--lo)}
table.cm td.bad{background:rgba(224,72,61,.10)}
table.cm td.bad b{color:var(--bloom)}

/* raster overlays: crisp 20 m pixels, not blurred */
.leaflet-container{font-family:inherit}
.leaflet-image-layer{image-rendering:pixelated;image-rendering:-moz-crisp-edges;
  image-rendering:crisp-edges}

/* ---------- responsive ----------
   The desktop shell is viewport-locked: a fixed-height grid holding two panes
   that scroll independently. That model cannot survive a phone, where the
   control rail alone is taller than the screen and nested scroll panes fight
   the page. So below 860px the document scrolls normally, the map takes an
   explicit height instead of a share of one, and the map is ordered above the
   controls so it is the first thing on screen.

   Every font-size in this file is a rem off html{font-size}, so that is the
   main knob: 23px suits a desktop monitor and is far too large on a handset. */

@media(max-width:1080px){
  .app{grid-template-columns:380px 1fr}
}

@media(max-width:860px){
  html{font-size:19px}

  /* one scrolling document, not three */
  html,body{height:auto;min-height:100%}
  .app{display:flex;flex-direction:column}
  .main{order:1}
  .rail{order:2;overflow:visible;max-height:none;
    border-right:0;border-top:1px solid var(--line)}
  .results,.page{overflow:visible}

  .mapwrap{flex:none;height:58vh;height:58dvh;min-height:300px}
  .navbar{padding:0 var(--s3);min-height:64px}
  .navtools{padding:0 var(--s3);gap:var(--s4)}
  .navlinks a{padding:8px 10px}

  /* comfortable tap targets on touch */
  button,select,input,.tab,.navlinks a{min-height:44px}
  .lyr input[type=range]{min-height:auto}
}

@media(max-width:560px){
  html{font-size:17px}

  .navbar{flex-wrap:wrap;gap:var(--s2);min-height:0;padding:10px var(--s3)}
  .logo{width:28px;height:28px}
  /* the logo carries the identity at this width; the wordmark costs a whole row */
  .nav .brand span{display:none}
  .navlinks{gap:0}
  .navlinks a{padding:9px 11px;font-size:0.737rem}
  .navutil a{padding:9px 11px}
  /* three short labels fit, but a long domain name should scroll, not wrap */
  .navtools{gap:var(--s4);overflow-x:auto;scrollbar-width:none}
  .navtools::-webkit-scrollbar{display:none}
  .rail{padding:var(--s4) var(--s3)}
  .results{padding:var(--s3)}
  .mapwrap{height:52vh;height:52dvh;min-height:260px}

  /* two short cards a row reads better than six tall ones */
  .readouts{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s2)}
  .readout{padding:var(--s2) var(--s3)}
  .readout .v{font-size:1.25rem}

  .legend{gap:8px;font-size:0.72rem}
  .ramp{width:auto;flex:1 1 70px;min-width:60px}

  .tab{flex:1 1 auto;text-align:center;padding:11px 10px}
  .lyr .ck{min-width:104px;font-size:0.8rem}
  .lyr input[type=range]{flex:1 1 70px}

  .chartbox{height:300px}
  /* a scroll box inside a scrolling page is a trap on touch: let the table
     grow downward and scroll only sideways when the columns need it */
  .tablewrap{max-height:none}
  th,td{padding:9px 10px}

  .page{padding:var(--s4) var(--s3)}
  .page h2{font-size:1.35rem}
  /* bare DOIs are one long unbreakable token */
  .page li a{overflow-wrap:anywhere}
}

/* ---------- Sample page additions ----------
   Same instrument identity as the Lakes page; the only new ideas are the sampling
   footprint on the map, a coordinate readout that stays legible over imagery,
   and status chips that name which screen stopped a scene. */

/* live coordinate over the map, monospaced so digits do not shift as it updates */
.coordbadge{position:absolute;left:12px;bottom:12px;z-index:620;
  font-family:var(--mono);font-size:0.737rem;letter-spacing:.5px;
  background:rgba(255,255,255,.92);color:var(--foam);
  border:1px solid var(--line);border-radius:var(--r-sm);padding:6px 10px;
  box-shadow:var(--shadow);pointer-events:none}

/* the 3x3 window outline: dashed, so it reads as a measurement, not a feature */
.footprint{stroke-dasharray:5 4}

/* small pill buttons; they sit in a row, so they opt out of the full-width rule */
.chip{width:auto;margin:0;background:transparent;color:var(--hydro);
  border:1px solid var(--line);border-radius:999px;padding:8px 14px;
  font-size:0.763rem;font-weight:500;font-family:var(--mono);letter-spacing:.3px}
.chip:hover{background:var(--panel2);color:var(--foam);border-color:var(--hydro-dim)}
.quickrange{display:flex;gap:var(--s2);flex-wrap:wrap;margin-top:var(--s3)}
.chip.csv{border-color:var(--hydro-dim)}
.chip.csv:disabled{background:transparent;color:var(--muted);
  border-color:var(--line);cursor:not-allowed;opacity:.7}
.tabs .spacer{flex:1}

/* the screens, as a labelled list: the term is the control, the rest is the rule */
ul.protocol{list-style:none;margin:var(--s3) 0 0;padding:0}
ul.protocol li{font-size:0.789rem;color:var(--muted);line-height:1.5;
  padding:5px 0;border-bottom:1px solid var(--line)}
ul.protocol li:last-child{border-bottom:0}
ul.protocol li span{display:inline-block;min-width:8.2rem;color:var(--foam);
  font-family:var(--mono);font-size:0.711rem;letter-spacing:.6px;
  text-transform:uppercase}

/* status chips in the scene table */
.chip-s{display:inline-block;font-family:var(--mono);font-size:0.658rem;
  letter-spacing:.4px;padding:3px 9px;border-radius:999px;white-space:nowrap;
  border:1px solid transparent}
.chip-s.s-ok{color:#1d6f42;background:rgba(42,157,92,.13);border-color:rgba(42,157,92,.35)}
.chip-s.s-bloom{color:#a5322a;background:rgba(224,72,61,.13);border-color:rgba(224,72,61,.35)}
.chip-s.s-no{color:var(--muted);background:var(--panel2);border-color:var(--line)}

/* spectra ramp legend: the ramp is the measurement, so it gets a real key */
.speclegend{display:flex;align-items:center;gap:8px;margin-top:var(--s2);
  font-family:var(--mono);font-size:0.711rem;color:var(--muted)}
.speclegend .specramp{height:10px;flex:0 1 160px;border-radius:5px;
  background:linear-gradient(90deg,rgb(139,90,43),rgb(201,162,39),rgb(42,157,92))}
.speclegend .specunit{font-family:var(--sans);margin-left:2px}

@media(max-width:560px){
  ul.protocol li span{min-width:0;display:block}
  .coordbadge{font-size:0.68rem;left:8px;bottom:8px}
}

/* ---------- reduced motion ---------- */
@media(prefers-reduced-motion:reduce){
  *{transition:none!important;animation:none!important}
  .spin{border-top-color:currentColor;opacity:.6}
}
