/* ============================================================================
   UgaForestry — shared design system
   ----------------------------------------------------------------------------
   One stylesheet for all four pages. Before 2026-07-25 the palette, cards,
   buttons and header markup were duplicated verbatim in four inline <style>
   blocks, there were zero @media queries anywhere in WEB/, and the dark theme
   was unconditional. All three are fixed here.

   Loaded by WEB/partials/head.php. Page-specific rules live in the sections
   at the bottom (dashboard shell / auth card / admin), not in the pages.

   Theme: the viewer's OS preference wins by default; the ☾/☀ button in the
   header stamps data-theme="light|dark" on <html> and persists the choice in
   localStorage, and that must beat the media query in both directions.
   ============================================================================ */

/* ---------------------------------------------------------------- tokens -- */
:root{
  --leaf-700:#15803d; --leaf-600:#16a34a; --leaf-500:#22c55e;
  --leaf-400:#4ade80; --leaf-300:#86efac;
  --sky-400:#38bdf8; --amber-400:#fbbf24; --rose-400:#fb7185;

  --r-sm:8px; --r-md:12px; --r-lg:16px; --r-xl:22px;
  --ff:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,Inter,Arial,sans-serif;
  --fm:ui-monospace,"SF Mono","Cascadia Mono","Segoe UI Mono",Menlo,monospace;

  --topbar-h:56px;
}

/* dark is the default paint; the light block below overrides it */
:root,
:root[data-theme="dark"]{
  color-scheme:dark;
  --bg:#070d0a;
  --surface:rgba(255,255,255,.045); --surface-2:rgba(255,255,255,.075);
  --glass:rgba(9,17,13,.72); --glass-solid:#0b1410;
  --text:#e7efe9; --text-2:#a8b8ad; --text-3:#6f8377;
  --line:rgba(255,255,255,.10); --line-2:rgba(255,255,255,.17);
  --accent:var(--leaf-500); --accent-soft:rgba(34,197,94,.14); --accent-line:rgba(34,197,94,.40);
  --info:var(--sky-400); --info-soft:rgba(56,189,248,.13); --info-line:rgba(56,189,248,.45);
  --warn:var(--amber-400); --warn-soft:rgba(251,191,36,.13); --warn-line:rgba(251,191,36,.40);
  --danger:var(--rose-400); --danger-soft:rgba(251,113,133,.11); --danger-line:rgba(251,113,133,.34);
  --shadow:0 10px 34px rgba(0,0,0,.45); --shadow-sm:0 3px 12px rgba(0,0,0,.32);
  --map-bg:#0a1210; --logo-ink:#f1f7f3;
  --field-bg:rgba(0,0,0,.28);
  --page-grad-1:rgba(34,197,94,.10); --page-grad-2:rgba(56,189,248,.07);
}
:root[data-theme="light"]{
  color-scheme:light;
  --bg:#f4f7f4;
  --surface:#ffffff; --surface-2:#eef3ef;
  --glass:rgba(255,255,255,.86); --glass-solid:#ffffff;
  --text:#0e1a13; --text-2:#4d5f54; --text-3:#7d8f84;
  --line:rgba(14,26,19,.11); --line-2:rgba(14,26,19,.20);
  --accent:var(--leaf-600); --accent-soft:rgba(22,163,74,.11); --accent-line:rgba(22,163,74,.42);
  --info:#0284c7; --info-soft:rgba(2,132,199,.10); --info-line:rgba(2,132,199,.40);
  --warn:#b45309; --warn-soft:rgba(180,83,9,.10); --warn-line:rgba(180,83,9,.35);
  --danger:#be123c; --danger-soft:rgba(190,18,60,.08); --danger-line:rgba(190,18,60,.30);
  --shadow:0 8px 26px rgba(14,26,19,.10); --shadow-sm:0 2px 8px rgba(14,26,19,.07);
  --map-bg:#e8eee9; --logo-ink:#123d24;
  --field-bg:#ffffff;
  --page-grad-1:rgba(34,197,94,.10); --page-grad-2:rgba(56,189,248,.09);
}
/* OS preference, only while the user has not chosen explicitly */
@media (prefers-color-scheme: light){
  :root:not([data-theme]){
    color-scheme:light;
    --bg:#f4f7f4;
    --surface:#ffffff; --surface-2:#eef3ef;
    --glass:rgba(255,255,255,.86); --glass-solid:#ffffff;
    --text:#0e1a13; --text-2:#4d5f54; --text-3:#7d8f84;
    --line:rgba(14,26,19,.11); --line-2:rgba(14,26,19,.20);
    --accent:var(--leaf-600); --accent-soft:rgba(22,163,74,.11); --accent-line:rgba(22,163,74,.42);
    --info:#0284c7; --info-soft:rgba(2,132,199,.10); --info-line:rgba(2,132,199,.40);
    --warn:#b45309; --warn-soft:rgba(180,83,9,.10); --warn-line:rgba(180,83,9,.35);
    --danger:#be123c; --danger-soft:rgba(190,18,60,.08); --danger-line:rgba(190,18,60,.30);
    --shadow:0 8px 26px rgba(14,26,19,.10); --shadow-sm:0 2px 8px rgba(14,26,19,.07);
    --map-bg:#e8eee9; --logo-ink:#123d24;
    --field-bg:#ffffff;
  }
}

/* ------------------------------------------------------------------ base -- */
*{box-sizing:border-box}
html,body{margin:0;height:100%}
body{
  font-family:var(--ff);color:var(--text);background:var(--bg);
  -webkit-font-smoothing:antialiased;
}
/* Full-viewport app (dashboard): the map owns the screen, nothing else scrolls. */
body.shell-app{overflow:hidden}
/* Document pages (admin, auth): normal flow with a soft brand wash. */
body.shell-page{
  min-height:100%;
  background:
    radial-gradient(1200px 700px at 15% 0%, var(--page-grad-2), transparent 55%),
    radial-gradient(900px 600px at 88% 12%, var(--page-grad-1), transparent 55%),
    var(--bg);
}
a{color:var(--info)}
h1,h2,h3{margin:0;font-weight:680;letter-spacing:-.01em}
.mono{font-family:var(--fm)}
.num{font-variant-numeric:tabular-nums}
.muted{color:var(--text-2)}
.small{font-size:12px;color:var(--text-2)}
.spacer{margin-left:auto}
[hidden]{display:none!important}

/* ----------------------------------------------------------------- brand -- */
/* logo.png is a white alpha mask, so it is painted with background-color and
   recolours per theme from the single asset. Painting it as a plain <img>
   would make it invisible on the light theme. Logo-only branding: no wordmark
   text beside it (WEB/CLAUDE.md). */
.brand{display:flex;align-items:center;flex:none;text-decoration:none}
/* Box ratios track the asset (760x204 = 3.72) so `contain` leaves no dead space
   and the mark sits where the box says it does. Widths are unchanged from the
   old wordmark on purpose — the top bar's 390 px budget was measured with them. */
.brand-logo{
  display:block;width:126px;height:34px;background-color:var(--logo-ink);
  -webkit-mask:url(/logo.png) left center/contain no-repeat;
          mask:url(/logo.png) left center/contain no-repeat;
}
.brand-logo.lg{width:200px;height:54px;margin:0 auto}

/* --------------------------------------------------------------- top bar -- */
.topbar{
  height:var(--topbar-h);flex:none;display:flex;align-items:center;gap:12px;
  padding:0 16px;background:var(--glass);border-bottom:1px solid var(--line);
  backdrop-filter:blur(14px);position:relative;z-index:1200;
}
.who{font-size:13px;color:var(--text-2);display:flex;align-items:center;gap:9px;min-width:0}
.who .email{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:26ch}
/* the nav links read as text here and collapse to their icon under 900 px */
.topbar .nav-btn .ic{display:none}

/* ------------------------------------------------------- buttons + chips -- */
button,.btn{
  font-family:inherit;color:var(--text);cursor:pointer;
  height:34px;padding:0 13px;font-size:13px;border-radius:10px;
  border:1px solid var(--line-2);background:var(--surface);
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  white-space:nowrap;text-decoration:none;
  transition:background .15s,border-color .15s,transform .05s;
}
button:hover,.btn:hover{background:var(--surface-2);border-color:var(--line-2)}
button:active,.btn:active{transform:translateY(1px)}
button:disabled,.btn:disabled{opacity:.55;cursor:not-allowed;transform:none}
button:focus-visible,.btn:focus-visible,
input:focus-visible,select:focus-visible,.chip:focus-visible{
  outline:2px solid var(--info);outline-offset:2px;
}
.btn-mini{height:28px;padding:0 10px;font-size:12px;border-radius:8px}
.btn-primary{border-color:var(--accent-line);background:var(--accent-soft);color:var(--accent);font-weight:600}
.btn-accent {border-color:var(--info-line);background:var(--info-soft);color:var(--info);font-weight:600}
.btn-warn   {border-color:var(--warn-line);background:var(--warn-soft);color:var(--warn)}
.btn-danger {border-color:var(--danger-line);background:var(--danger-soft);color:var(--danger)}
.btn-block{width:100%;height:42px;font-size:15px;font-weight:650}

.iconbtn{
  width:34px;height:34px;padding:0;flex:none;display:grid;place-items:center;
  border-radius:9px;border:1px solid var(--line-2);background:var(--surface);
  font-size:14px;line-height:1;cursor:pointer;color:var(--text);text-decoration:none;
}
.iconbtn:hover{background:var(--surface-2)}

.chip{
  display:inline-flex;align-items:center;gap:7px;height:32px;padding:0 11px;
  font-size:13px;border-radius:999px;border:1px solid var(--line-2);
  background:var(--surface);white-space:nowrap;color:var(--text);
}
.chip .dot{width:7px;height:7px;border-radius:50%;background:var(--accent);
  box-shadow:0 0 0 3px var(--accent-soft);flex:none}
.pill-role{
  display:inline-flex;align-items:center;height:24px;padding:0 9px;border-radius:999px;
  background:var(--info-soft);color:var(--info);
  font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;
}

/* -------------------------------------------------------- form controls -- */
input,select,textarea{
  font-family:inherit;font-size:13px;color:var(--text);
  height:34px;padding:0 10px;border-radius:9px;
  border:1px solid var(--line-2);background:var(--field-bg);outline:none;
  transition:border-color .15s,box-shadow .15s;
  max-width:100%;
}
input[type=checkbox]{height:auto;width:16px;padding:0;cursor:pointer;accent-color:var(--accent)}
input:focus,select:focus{border-color:var(--info-line);box-shadow:0 0 0 3px var(--info-soft)}
select{cursor:pointer}
.field{display:grid;gap:6px;margin-bottom:14px}
.field > span{font-size:11px;color:var(--text-2);text-transform:uppercase;letter-spacing:.06em;font-weight:650}
.field input{height:42px;font-size:14px;border-radius:11px}

/* ----------------------------------------------------------------- cards -- */
.card{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--shadow-sm);padding:16px 18px;margin-bottom:14px;
}
.card > h2{margin:0 0 12px;font-size:14px;font-weight:650}

/* -------------------------------------------------------------- messages -- */
.err,.ok,.notice{padding:10px 12px;border-radius:11px;font-size:13px;margin-bottom:12px}
.err   {color:var(--danger);background:var(--danger-soft);border:1px solid var(--danger-line)}
.ok    {color:var(--accent);background:var(--accent-soft);border:1px solid var(--accent-line)}
.notice{color:var(--warn);  background:var(--warn-soft);  border:1px solid var(--warn-line)}

@keyframes spin{to{transform:rotate(360deg)}}
.spinner{
  display:inline-block;width:12px;height:12px;border:2px solid var(--line-2);
  border-top-color:var(--info);border-radius:50%;animation:spin .7s linear infinite;
  vertical-align:middle;flex:none;
}

/* ---------------------------------------------------------------- tables -- */
/* Every table on the site is wider than a phone. `.table-scroll` is the only
   thing standing between the admin matrix and a horizontally scrolling body,
   so admin tables must always be wrapped in one. */
.table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:0 -18px;padding:0 18px}
table{width:100%;border-collapse:collapse;font-size:13px}
th{font-weight:600;color:var(--text-2);text-align:left;padding:8px 10px;
   border-bottom:1px solid var(--line);white-space:nowrap}
td{padding:8px 10px;border-bottom:1px solid var(--line)}
tbody tr:last-child td{border-bottom:0}
tbody tr:hover td{background:var(--surface-2)}
.right{text-align:right}
.cell-actions{display:flex;gap:6px;justify-content:flex-end;flex-wrap:wrap}

/* ============================================================================
   DASHBOARD  (index.php)  —  variant A, "operations console"
   ============================================================================ */
.shell{display:flex;height:calc(100% - var(--topbar-h));position:relative}

/* ---- left rail of live figures ---- */
.side{
  width:286px;flex:none;padding:14px;overflow-y:auto;
  background:var(--glass);border-right:1px solid var(--line);backdrop-filter:blur(14px);
  display:flex;flex-direction:column;gap:12px;
}
/* the rail is a scrolling flex column: without this, cards that carry
   overflow:hidden (min-content height 0) get squashed flat instead of
   scrolling, and the figure rows disappear entirely on a phone */
.side > *{flex:none}

.hero{
  padding:15px 16px 16px;border-radius:var(--r-lg);border:1px solid var(--line);
  background:radial-gradient(120% 90% at 100% 0%, var(--accent-soft), transparent 62%),var(--surface);
}
.hero .lbl{font-size:10.5px;text-transform:uppercase;letter-spacing:.1em;color:var(--text-2);font-weight:650}
.hero .val{font-size:48px;font-weight:760;letter-spacing:-2px;line-height:1;margin:8px 0 2px;
  font-variant-numeric:tabular-nums}
.hero .sub{font-size:12px;color:var(--text-2);display:flex;align-items:center;gap:6px}

.mini-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.mini{padding:11px 12px;border-radius:var(--r-md);border:1px solid var(--line);background:var(--surface)}
.mini .lbl{font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-3);font-weight:650}
.mini .val{font-size:21px;font-weight:700;letter-spacing:-.5px;margin-top:5px;font-variant-numeric:tabular-nums}
.mini .val.i{color:var(--info)}
.mini .val.a{color:var(--accent)}

.rows{border-radius:var(--r-md);border:1px solid var(--line);background:var(--surface);overflow:hidden}
.rows .row{display:flex;align-items:center;gap:10px;padding:10px 12px;font-size:13px;
  border-bottom:1px solid var(--line)}
.rows .row:last-child{border-bottom:0}
.rows .k{color:var(--text-2);font-size:12px}
.rows .v{margin-left:auto;font-weight:620;font-variant-numeric:tabular-nums}
.rows .ico{width:16px;text-align:center;opacity:.8;font-size:13px;flex:none}

.spark-card{padding:11px 12px 9px;border-radius:var(--r-md);border:1px solid var(--line);background:var(--surface)}
.spark-card .lbl{font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-3);
  font-weight:650;margin-bottom:6px}
.spark{height:34px}
.spark-x{display:flex;justify-content:space-between;font-size:10px;color:var(--text-3);margin-top:3px;
  font-variant-numeric:tabular-nums}

/* data-flow pill — the thing that would have made the 17–19 Jul loss obvious */
.uplink{display:flex;align-items:flex-start;gap:9px;padding:10px 12px;border-radius:var(--r-md);
  border:1px solid var(--line);background:var(--surface);font-size:12px;line-height:1.45}
.uplink .dot{width:7px;height:7px;border-radius:50%;background:var(--accent);margin-top:5px;flex:none;
  box-shadow:0 0 0 3px var(--accent-soft)}
.uplink .warnish{color:var(--warn)}

/* ---- map ---- */
.mapwrap{flex:1;position:relative;min-width:0}
#map{position:absolute;inset:0;background:var(--map-bg)}
.leaflet-container{background:var(--map-bg);font-family:var(--ff)}
.map-tools{position:absolute;top:12px;right:12px;z-index:900;display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}
.tool{
  height:34px;padding:0 13px;display:inline-flex;align-items:center;gap:7px;font-size:13px;
  border-radius:10px;border:1px solid var(--line-2);background:var(--glass);
  backdrop-filter:blur(12px);box-shadow:var(--shadow-sm);cursor:pointer;white-space:nowrap;color:var(--text);
}
.tool:hover{background:var(--surface-2)}
.tool.primary{border-color:var(--info-line);background:var(--info-soft);color:var(--info);font-weight:600}
/* Basemap switch: the dock's .seg in the map's glass idiom, sized to sit level
   with the .tool buttons it shares the row with. */
.mapsw{
  height:34px;padding:3px;border-radius:10px;border-color:var(--line-2);
  background:var(--glass);backdrop-filter:blur(12px);box-shadow:var(--shadow-sm);
}
.mapsw button{height:26px;padding:0 11px;font-size:12.5px;cursor:pointer;color:var(--text-2)}
.mapsw button:hover{color:var(--text)}
.mapsw button[aria-pressed="true"]{background:var(--info-soft);color:var(--info)}
.signal{
  position:absolute;left:12px;bottom:12px;z-index:900;
  height:30px;padding:0 11px;display:inline-flex;align-items:center;gap:8px;
  font-size:12px;color:var(--text-2);border-radius:999px;border:1px solid var(--line);
  background:var(--glass);backdrop-filter:blur(12px);
}
.pulse{width:7px;height:7px;border-radius:50%;background:var(--accent);animation:pulse 2s ease-in-out infinite;flex:none}
.pulse.stale{background:var(--warn);animation:none}
@keyframes pulse{0%,100%{opacity:1;box-shadow:0 0 0 0 var(--accent-soft)}50%{opacity:.55;box-shadow:0 0 0 5px transparent}}

/* history-view banner, floats over the map */
.hist-banner{
  position:absolute;left:12px;top:12px;z-index:901;max-width:calc(100% - 24px);
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:8px 12px;border-radius:11px;font-size:13px;
  color:var(--warn);border:1px solid var(--warn-line);background:var(--warn-soft);
  backdrop-filter:blur(12px);
}

/* ---- markers + cluster bubbles (Part 3) ---- */
.leaflet-marker-icon.uf-leaf{background:none;border:0}
.uf-dot{display:block;width:11px;height:11px;border-radius:50%;
  background:var(--leaf-400);border:1.5px solid rgba(4,20,11,.85);
  box-shadow:0 1px 3px rgba(0,0,0,.45)}
.uf-dot.hist{background:var(--amber-400)}
/* Aerial imagery is far busier than either flat basemap, and it is the same
   photo under both themes — an 11 px dot needs a light ring to stay readable
   over canopy, ploughed soil and stubble alike. */
#map.sat .uf-dot{border-color:rgba(255,255,255,.92);box-shadow:0 1px 4px rgba(0,0,0,.7)}
.uf-tractor{display:grid;place-items:center;width:30px;height:30px;border-radius:50%;
  background:var(--sky-400);border:2.5px solid rgba(255,255,255,.9);
  box-shadow:0 3px 12px rgba(0,0,0,.45),0 0 0 7px rgba(56,189,248,.22);font-size:14px}
.uf-cluster{
  display:grid;place-items:center;border-radius:50%;font-family:var(--ff);
  font-weight:700;color:#04140b;background:var(--leaf-400);
  border:2px solid rgba(255,255,255,.85);
  box-shadow:0 2px 10px rgba(0,0,0,.4),0 0 0 6px rgba(34,197,94,.20);
}
.uf-cluster.s{width:34px;height:34px;font-size:12px}
.uf-cluster.m{width:42px;height:42px;font-size:13px;background:var(--leaf-500);
  box-shadow:0 2px 10px rgba(0,0,0,.4),0 0 0 8px rgba(34,197,94,.18)}
.uf-cluster.l{width:52px;height:52px;font-size:14px;background:var(--leaf-600);color:#eafff1;
  box-shadow:0 2px 12px rgba(0,0,0,.45),0 0 0 10px rgba(34,197,94,.16)}
.uf-cluster.hist{background:var(--amber-400);color:#2a1a02}

.leaflet-popup-content-wrapper,.leaflet-popup-tip{
  background:var(--glass-solid)!important;color:var(--text)!important;
  border:1px solid var(--line)!important;box-shadow:var(--shadow)!important;
}
.leaflet-popup-content-wrapper{border-radius:var(--r-md)!important}
.leaflet-popup-content{margin:9px 12px;font-size:12.5px;line-height:1.5}
.leaflet-popup-close-button{color:var(--text-2)!important}
.leaflet-control-attribution{background:var(--glass)!important;color:var(--text-3)!important;font-size:10px!important}
.leaflet-control-attribution a{color:var(--info)!important}
.leaflet-bar,.leaflet-bar a{background:var(--glass)!important;color:var(--text)!important;
  border-color:var(--line)!important;backdrop-filter:blur(12px)}
.leaflet-bar a:hover{background:var(--surface-2)!important}

/* ---- floating dock: chart + sapling list ---- */
.dock{
  position:absolute;right:12px;bottom:12px;z-index:900;width:min(680px,calc(100% - 24px));
  border-radius:var(--r-lg);border:1px solid var(--line);background:var(--glass);
  backdrop-filter:blur(18px);box-shadow:var(--shadow);overflow:hidden;
}
.dock-head{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid var(--line);flex-wrap:wrap}
.tab{
  height:28px;padding:0 12px;font-size:12.5px;border-radius:8px;cursor:pointer;
  border:1px solid transparent;background:transparent;color:var(--text-2);font-weight:600;
}
.tab[aria-selected="true"]{background:var(--surface-2);border-color:var(--line-2);color:var(--text)}
.dock-body{padding:14px 14px 12px}
.seg{display:inline-flex;padding:2px;gap:2px;border-radius:9px;border:1px solid var(--line);background:var(--surface)}
.seg button{height:24px;padding:0 10px;font-size:12px;border:0;border-radius:7px;background:transparent;
  color:var(--text-2);font-weight:600}
.seg button[aria-pressed="true"]{background:var(--info-soft);color:var(--info)}

/* From/To period — one range feeds the chart, the list and both downloads */
.range{display:inline-flex;align-items:center;gap:5px;flex:none}
.range input[type=date]{height:28px;width:136px;font-size:12px;padding:0 8px;border-radius:8px}
.range .sep{color:var(--text-3);font-size:12px}

/* chart */
.chart{position:relative;height:184px;display:flex;align-items:flex-end;gap:3px;padding-top:14px}
.grid-line{position:absolute;left:0;right:0;height:1px;background:var(--line);opacity:.7}
.bar-wrap{flex:1;min-width:0;height:100%;display:flex;flex-direction:column;
  justify-content:flex-end;align-items:center;cursor:pointer;position:relative}
.bar{width:100%;max-width:26px;border-radius:4px 4px 2px 2px;min-height:2px;
  background:linear-gradient(180deg,var(--leaf-400),rgba(34,197,94,.34));transition:filter .12s}
.bar-wrap:hover .bar{filter:brightness(1.18)}
.bar-wrap.sel .bar{background:linear-gradient(180deg,var(--amber-400),rgba(251,191,36,.38));
  box-shadow:0 0 0 2px rgba(251,191,36,.35)}
/* bar counts stay out of the way until the bar matters — keeps a 24- or
   31-bucket chart readable at any width without reserving space for labels */
.bar-wrap .n{font-size:10px;color:var(--text-3);margin-bottom:3px;font-variant-numeric:tabular-nums;
  opacity:0;transition:opacity .12s}
.bar-wrap.sel .n,.bar-wrap:hover .n{opacity:1}
.xlabels{display:flex;gap:3px;margin-top:6px}
.xlabels span{flex:1;min-width:0;text-align:center;font-size:10px;color:var(--text-3);
  overflow:hidden;white-space:nowrap}
.hint{font-size:11.5px;color:var(--text-3);margin-top:8px}

/* sapling list */
.list-head{display:flex;align-items:center;gap:10px;margin:0 0 8px}
.list-head h2{margin:0;display:flex;align-items:baseline;gap:8px;min-width:0}
.list-head .per{font-size:11px;font-weight:650;color:var(--text-3);white-space:nowrap;
  font-variant-numeric:tabular-nums;overflow:hidden;text-overflow:ellipsis}

/* download menu — the file covers whatever period the head shows */
.dl{position:relative;margin-left:auto;flex:none}
.dl #dl-btn{font-weight:600}
.dl .caret{font-size:9px;color:var(--text-3)}
.dl-menu{
  position:absolute;right:0;top:calc(100% + 6px);z-index:20;min-width:236px;padding:5px;
  display:grid;gap:2px;border-radius:var(--r-md);border:1px solid var(--line-2);
  background:var(--glass-solid);box-shadow:var(--shadow);
}
.dl-menu button{
  width:100%;height:auto;padding:8px 9px;gap:10px;justify-content:flex-start;text-align:left;
  border:0;border-radius:9px;background:transparent;
}
.dl-menu button:hover{background:var(--surface-2)}
.dl-menu .ic{
  flex:none;display:grid;place-items:center;width:36px;height:26px;border-radius:7px;
  font-family:var(--fm);font-size:9.5px;font-weight:800;letter-spacing:.04em;
}
.dl-menu .ic.xls{color:var(--accent);background:var(--accent-soft);border:1px solid var(--accent-line)}
.dl-menu .ic.pdf{color:var(--danger);background:var(--danger-soft);border:1px solid var(--danger-line)}
.dl-menu .tx{display:grid;gap:1px;min-width:0}
.dl-menu .tx b{font-size:12.5px;font-weight:650;color:var(--text)}
.dl-menu .tx em{font-style:normal;font-size:11px;color:var(--text-3)}
.dl-msg{margin:0 0 8px;padding:7px 10px;border-radius:9px;font-size:11.5px;
  border:1px solid transparent;overflow-wrap:anywhere}
.dl-msg.ok {color:var(--accent);background:var(--accent-soft);border-color:var(--accent-line)}
.dl-msg.err{color:var(--danger);background:var(--danger-soft);border-color:var(--danger-line)}

.list{max-height:300px;overflow-y:auto;margin:-4px -4px 0}
.li{display:flex;align-items:center;gap:10px;padding:8px 8px;border-radius:9px;font-size:12.5px;cursor:pointer}
.li:hover{background:var(--surface-2)}
.li .id{font-family:var(--fm);font-size:11.5px;color:var(--accent);font-weight:600;flex:none;width:56px}
.li .t{color:var(--text-2);flex:none;width:64px;font-variant-numeric:tabular-nums}
.li .c{font-family:var(--fm);font-size:11px;color:var(--text-3);margin-left:auto;white-space:nowrap}
.pager{display:flex;align-items:center;gap:6px;padding-top:8px;margin-top:6px;border-top:1px solid var(--line);
  font-size:11.5px;color:var(--text-3);flex-wrap:wrap}
.pager button{height:24px;min-width:24px;padding:0 7px;font-size:11.5px;border-radius:7px}
.pager button[aria-current="true"]{background:var(--accent-soft);border-color:var(--accent-line);
  color:var(--accent);font-weight:700}

/* mobile drag handle, hidden on desktop */
.handle{display:none}

/* ============================================================================
   AUTH PAGES  (login.php, changepw.php)
   ============================================================================ */
.auth-wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px}
.auth-wrap.with-nav{min-height:calc(100vh - var(--topbar-h))}
.auth-card{
  width:100%;max-width:400px;padding:32px;
  background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r-xl);
  box-shadow:var(--shadow);
}
.auth-card .logo-wrap{display:flex;justify-content:center;margin-bottom:22px}
.auth-card h1{font-size:19px;text-align:center;margin-bottom:4px}
.auth-card .who{justify-content:center;font-size:12px;margin-bottom:18px}
.auth-card .err,.auth-card .ok{margin:14px 0 0}
.auth-foot{margin-top:16px;text-align:center;font-size:11.5px;color:var(--text-3)}

/* ============================================================================
   ADMIN  (admin.php)
   ============================================================================ */
.page{max-width:1400px;margin:0 auto;padding:18px 18px 48px}
.tabs{display:flex;gap:8px;margin-bottom:14px;flex-wrap:wrap}
.tabs .tab{height:34px;padding:0 14px;font-size:13px;border-radius:11px;
  border:1px solid var(--line-2);background:var(--surface);color:var(--text)}
.tabs .tab.active{background:var(--info-soft);border-color:var(--info-line);color:var(--info)}
.form-row{display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end}
.form-row > div{display:flex;flex-direction:column;gap:4px;min-width:0}
.form-row label{font-size:11px;color:var(--text-2);text-transform:uppercase;letter-spacing:.05em;font-weight:650}
.matrix th,.matrix td{padding:6px 8px;text-align:center}
.matrix th.name,.matrix td.name{text-align:left;white-space:nowrap}

/* ============================================================================
   RESPONSIVE
   ============================================================================ */
@media (max-width:1280px){
  .side{width:252px}
  .dock{width:min(600px,calc(100% - 24px))}
  .chart{height:164px}
  .list{max-height:252px}
}

/* --- phones / small tablets: the map fills the screen and everything else
       lives in a drag-up bottom sheet (variant A, mobile) --- */
@media (max-width:900px){
  :root{--topbar-h:52px}
  .topbar{padding:0 12px;gap:10px}
  /* the topbar is a no-wrap flex row, so anything that will not shrink pushes
     the theme / admin / logout buttons clean off a 390 px screen */
  .who{display:none}
  .chip .site{display:none}
  /* a planter can be named anything, and the <select> sizes to its longest
     option — cap it or one long name reopens the overflow on its own */
  .chip select{max-width:118px;text-overflow:ellipsis}
  .topbar .nav-btn{width:32px;padding:0;font-size:14px}
  .topbar .nav-btn .ic{display:block}
  .topbar .nav-btn .lbl{display:none}

  .side{
    position:absolute;left:0;right:0;bottom:0;top:auto;z-index:1000;
    width:auto;height:86vh;padding:0 14px 14px;border-right:0;
    border-top:1px solid var(--line-2);border-radius:var(--r-xl) var(--r-xl) 0 0;
    transform:translateY(calc(100% - 148px));transition:transform .3s cubic-bezier(.32,.72,0,1);
    box-shadow:0 -12px 34px rgba(0,0,0,.34);
  }
  .side.open{transform:translateY(0)}
  .handle{
    display:block;flex:none;position:sticky;top:0;z-index:2;
    padding:9px 0 11px;background:inherit;cursor:grab;border:0;width:100%;height:auto;
    border-radius:0;
  }
  .handle:hover{background:inherit}
  .handle i{display:block;width:42px;height:4px;border-radius:999px;background:var(--line-2);margin:0 auto}
  .handle span{display:block;font-size:11px;color:var(--text-3);text-align:center;margin-top:6px}
  /* on a phone the chart earns its place directly under the headline figure;
     every child needs an explicit order or it falls back to 0 and jumps to the top */
  .handle{order:0} .side .hero{order:1} .side .dock{order:2}
  .side .mini-grid{order:3} .side .rows{order:4}
  .side .spark-card{order:5} .side .uplink{order:6}
  .dock{
    position:static;width:auto;background:var(--surface);backdrop-filter:none;box-shadow:none;
  }
  .mapwrap{position:absolute;inset:0}
  .map-tools{top:10px;right:10px;left:10px}
  .signal{bottom:auto;top:auto;left:10px;bottom:calc(148px + 10px)}
  .hist-banner{left:10px;right:10px;top:10px;max-width:none}
  .hero .val{font-size:40px}
  .list{max-height:none}

  .page{padding:14px 12px 40px}
  .card{padding:14px;border-radius:var(--r-md)}
  .table-scroll{margin:0 -14px;padding:0 14px}
}

@media (max-width:640px){
  .auth-card{padding:24px 20px;border-radius:var(--r-lg)}
  .form-row > div{flex:1 1 100%}
  .form-row > div > input,.form-row > div > select{width:100%}
}

@media (max-width:420px){
  .brand-logo{width:96px;height:26px}
  .chart{height:140px}
  /* three controls over a 390 px map already wrap to two rows — don't let the
     basemap switch push a third */
  .mapsw button{padding:0 8px}
  /* two full-width date fields side by side leave ~150 px each on a 390 px screen */
  .range{flex:1 1 100%}
  .range input[type=date]{flex:1;width:auto;min-width:0}
  .dl-menu{min-width:0;left:0;right:0}
  .li .c{display:none}
  .topbar{gap:8px;padding:0 10px}
  .topbar .nav-btn{width:28px}
  .iconbtn{width:28px;height:28px}
  .chip{height:28px;padding:0 9px}
  .chip select{max-width:96px}
}

/* the map tiles are the one thing that never respects a colour scheme, so keep
   motion off for people who ask for it rather than fighting the tile server */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important}
}
