/* SNOF live farm dashboard — design system: "Area workspace".
 *
 * The owner picked this direction on 2026-09-24 (design option C): a cool
 * slate canvas, white panels on 1px hairlines, one tinted "farm pulse" panel,
 * big tabular numerals, uppercase eyebrows and a single typeface, Manrope.
 * Colour still only ever means something: brand green for on / live / the
 * current tab, muted brick for unavailable, amber for a stale bridge. Green
 * is a fill (toggle, dot, underline) or text, never a wash behind anything.
 *
 * Shape and depth follow iOS (owner, 2026-09-24: "a soft, elegant iPhone
 * feel" instead of sharp corners): cards are 22px squircle-ish rounds that
 * float on a whisper of shadow with a near-invisible edge, controls are 12px,
 * toggles and segments are drawn at iOS proportions, the top and tab bars
 * are frosted, and presses give a small scale instead of a nudge.
 *
 * Two themes. Light is the mockup, pixel-sampled. Dark is Apple's neutral
 * system dark (black, #1c1c1e, #2c2c2e), not a tinted slate; every text pair
 * re-checked for 4.5:1.
 * Theme resolution:
 *   no [data-theme]  -> follow the OS
 *   [data-theme=...] -> the user's explicit choice, persisted in localStorage
 * Every colour below is a token. Nothing outside the token blocks hardcodes a
 * hex, except the white of a toggle knob and the Google button. */
@font-face{font-family:"Manrope";font-style:normal;font-weight:400 800;font-display:swap;
  src:url(/fonts/manrope-latin.woff2) format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,
    U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}

/* --- light: the mockup ("slate daylight") --- */
:root{
  --bg:#f5f7f7; --bar:#ffffff;
  --panel:#ffffff; --panel-2:#f0f4f4; --panel-3:#e6eced;
  --tint:#eaf0ef; --tint-line:#d2e0df;
  --line:#dce4e4; --line-2:#c9d4d5; --line-soft:#e7eded;
  --text:#17252a; --ink:#25393d; --muted:#56696e; --faint:#5b6e73;

  /* Brand green (the logo's #018843): --brand fills, --accent is green text
     shaded to clear 4.5:1 on every surface, the tint included. */
  --brand:#018843; --on-brand:#ffffff; --accent:#017a3c;
  --accent-soft:var(--panel-2); --accent-line:var(--line-2);
  --accent-glow:rgba(1,136,67,.26); --accent-flash:rgba(23,37,42,.06);
  --warn:#7a5a12; --warn-soft:rgba(122,90,18,.09); --warn-line:rgba(122,90,18,.3);
  --bad:#a0504a;  --bad-soft:rgba(160,80,74,.08);  --bad-line:rgba(160,80,74,.32);
  --off-soft:rgba(86,105,110,.08); --track:#dfe6e7; --knob:#ffffff;
  --chev:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%2356696e' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");

  /* Cards: a near-invisible edge and a soft two-layer lift, like an iOS
     inset-grouped cell. --edge replaces the old 1px --line frame on cards. */
  --edge:rgba(23,37,42,.055);
  --shadow-card:0 1px 2px rgba(23,37,42,.04),0 6px 20px -8px rgba(23,37,42,.10);
  --shadow-card-hover:0 1px 2px rgba(23,37,42,.05),0 12px 28px -10px rgba(23,37,42,.16);
  --shadow:none; --shadow-lg:0 24px 60px -18px rgba(23,37,42,.28),0 2px 8px rgba(23,37,42,.06);
  --glass:rgba(255,255,255,.78); --glass-line:rgba(23,37,42,.08);
  --seg-track:rgba(86,105,110,.12); --seg-thumb:#ffffff;
  --seg-shadow:0 3px 8px rgba(0,0,0,.10),0 1px 1px rgba(0,0,0,.04);
  --field:#eef2f2;
  --r:12px; --r-sm:8px; --r-md:12px; --r-lg:16px; --r-xl:22px;
  --sat:env(safe-area-inset-top,0px); --sab:env(safe-area-inset-bottom,0px);
  --ease:cubic-bezier(.32,.72,0,1); --spring:cubic-bezier(.34,1.3,.64,1);
  --bar-h:76px; --gutter:clamp(16px,2.9vw,42px); --maxw:1440px;
  --font:"Manrope",ui-sans-serif,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
  color-scheme:light;
}
/* --- dark: Apple's neutral dark (owner, 2026-09-24: no charcoal-green).
   True black canvas, #1c1c1e / #2c2c2e graphite cards, white text; no hue in
   any grey. Green stays for on/live only. Repeated for "follow the OS" and
   "user picked dark"; keep the two blocks identical. --- */
@media (prefers-color-scheme: dark){ :root:not([data-theme]){
  --bg:#000000; --bar:#1c1c1e;
  --panel:#1c1c1e; --panel-2:#2c2c2e; --panel-3:#3a3a3c;
  --tint:#242426; --tint-line:#38383a;
  --line:#38383a; --line-2:#48484a; --line-soft:#2c2c2e;
  --text:#ffffff; --ink:#f2f2f7; --muted:#a1a1a6; --faint:#8e8e93;
  --brand:#018843; --on-brand:#ffffff; --accent:#01ae56;
  --accent-soft:var(--panel-2); --accent-line:var(--line-2);
  --accent-glow:rgba(1,174,86,.32); --accent-flash:rgba(255,255,255,.07);
  --warn:#e3b95c; --warn-soft:rgba(227,185,92,.12); --warn-line:rgba(227,185,92,.34);
  --bad:#ff8a80;  --bad-soft:rgba(255,138,128,.12); --bad-line:rgba(255,138,128,.34);
  --off-soft:rgba(142,142,147,.14); --track:#39393d; --knob:#ffffff;
  --chev:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%23a1a1a6' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --shadow-lg:0 24px 60px -18px rgba(0,0,0,.8);
  --edge:rgba(255,255,255,.07);
  --shadow-card:none;
  --shadow-card-hover:0 0 0 1px rgba(255,255,255,.1);
  --glass:rgba(28,28,30,.72); --glass-line:rgba(255,255,255,.08);
  --seg-track:rgba(118,118,128,.24); --seg-thumb:#636366;
  --seg-shadow:0 3px 8px rgba(0,0,0,.4),0 1px 1px rgba(0,0,0,.2);
  --field:#2c2c2e;
  color-scheme:dark;
}}
:root[data-theme="dark"]{
  --bg:#000000; --bar:#1c1c1e;
  --panel:#1c1c1e; --panel-2:#2c2c2e; --panel-3:#3a3a3c;
  --tint:#242426; --tint-line:#38383a;
  --line:#38383a; --line-2:#48484a; --line-soft:#2c2c2e;
  --text:#ffffff; --ink:#f2f2f7; --muted:#a1a1a6; --faint:#8e8e93;
  --brand:#018843; --on-brand:#ffffff; --accent:#01ae56;
  --accent-soft:var(--panel-2); --accent-line:var(--line-2);
  --accent-glow:rgba(1,174,86,.32); --accent-flash:rgba(255,255,255,.07);
  --warn:#e3b95c; --warn-soft:rgba(227,185,92,.12); --warn-line:rgba(227,185,92,.34);
  --bad:#ff8a80;  --bad-soft:rgba(255,138,128,.12); --bad-line:rgba(255,138,128,.34);
  --off-soft:rgba(142,142,147,.14); --track:#39393d; --knob:#ffffff;
  --chev:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%23a1a1a6' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --shadow-lg:0 24px 60px -18px rgba(0,0,0,.8);
  --edge:rgba(255,255,255,.07);
  --shadow-card:none;
  --shadow-card-hover:0 0 0 1px rgba(255,255,255,.1);
  --glass:rgba(28,28,30,.72); --glass-line:rgba(255,255,255,.08);
  --seg-track:rgba(118,118,128,.24); --seg-thumb:#636366;
  --seg-shadow:0 3px 8px rgba(0,0,0,.4),0 1px 1px rgba(0,0,0,.2);
  --field:#2c2c2e;
  color-scheme:dark;
}

*{box-sizing:border-box}
/* Author display rules would otherwise beat the UA [hidden] rule. */
[hidden]{display:none!important}
html,body{height:100%}
body{margin:0;background:var(--bg);color:var(--text);font:14px/1.55 var(--font);
  font-feature-settings:"tnum" 0;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
button,input,select{font:inherit;color:inherit}
button{cursor:pointer;background:none;border:0;padding:0;text-align:inherit}
h1,h2,h3,p{margin:0}
a{color:inherit;text-decoration:none}
.sprite{position:absolute;width:0;height:0;overflow:hidden}
.ico{width:19px;height:19px;flex:none;fill:none;stroke:currentColor;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round;display:block}
.ico-sm{width:15px;height:15px}
.num{font-variant-numeric:tabular-nums}

/* ---------- view switching (the fix for the stacked sign-in page) ---------- */
#boot,#gate,#app{display:none}
body[data-view="boot"] #boot{display:grid}
body[data-view="gate"] #gate{display:grid}
body[data-view="app"]  #app{display:block;min-height:100dvh}
body[data-view="gate"],body[data-view="boot"]{overflow:hidden}

/* ---------- type ---------- */
.eyebrow{font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--faint);
  line-height:1.3}
.wordmark{font-weight:800;font-size:24px;letter-spacing:-.06em;line-height:1;color:var(--text)}
.wordmark-sub{font-size:14px;font-weight:600;color:var(--muted);letter-spacing:-.005em;white-space:nowrap}

/* ---------- shared interaction vocabulary ---------- */
.btn,.chip,.icon-btn,.topnav-item,.tab-item,.acct-btn,#search,.toggle,.area-card,.panel-link,
.stat,.pstat,.acct-item,.att-row{
  transition:background-color .16s,border-color .16s,color .16s,box-shadow .16s,
             transform .14s var(--ease),opacity .16s}
:is(.btn,.chip,.icon-btn,.topnav-item,.tab-item,.acct-btn,#search,.toggle,.area-card,.panel-link,
   .stat,.pstat,.acct-item,.att-row,.brand,.back,input[type=range],
   .tile,.sys-tile,.vcard,.attn-row,.flow,.wmain,.seg-nav a,.vchip):focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.sys-tile:active,.vcard:active,.attn-row:active{transform:scale(.985)}
.sys-tile,.vcard,.attn-row{transition:background-color .16s,box-shadow .16s,transform .14s var(--ease)}
/* Small buttons keep a 44px touch target (the visible pill stays small). */
.btn-sm{position:relative}
.btn-sm::before{content:"";position:absolute;left:0;right:0;top:50%;translate:0 -50%;height:44px}
.btn:active,.chip:active,.icon-btn:active,.seg button:active{transform:scale(.96)}
:is(a.stat,.pstat,.area-card,.rep-head,.dgroup-head,.att-row,.row):active{transform:scale(.985)}
.row,.dgroup-head,.rep-head{transition:background-color .16s,transform .18s var(--ease)}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;min-height:44px;
  padding:0 20px;border-radius:var(--r);font-weight:700;letter-spacing:-.005em}
.btn-block{width:100%}
.btn-ghost{border:1px solid transparent;color:var(--text);background:var(--seg-track)}
.btn-ghost:hover{background:var(--panel-3)}
.btn-google{background:#fff;color:#1f2328;border:1px solid #d8dde0}
.btn-google:hover{background:#f4f6f7}
.btn-google .g{width:19px;height:19px;flex:none}
.icon-btn{position:relative;display:grid;place-items:center;width:40px;height:40px;
  border-radius:50%;color:var(--muted);border:1px solid transparent}
.icon-btn::before{content:"";position:absolute;left:50%;top:50%;translate:-50% -50%;width:44px;height:44px;z-index:1}
.icon-btn:hover{color:var(--text);background:var(--seg-track)}

/* The farm's roundel. Its centre is transparent and its lettering is the
   brand green, so it always sits on a white disc, in both themes. */
.logo{display:block;flex:none;width:30px;height:30px;border-radius:50%;background:#fff;padding:2px;object-fit:contain;
  box-shadow:0 0 0 1px var(--line)}

/* ---------- boot ---------- */
.boot{place-items:center;min-height:100dvh;background:var(--bg)}
/* The loading state (owner, 2026-09-25): the logo, breathing, with a brand
   ring turning round it. Mirrors LogoLoader in the iOS app. */
.loader{position:relative;display:grid;place-items:center;width:152px;height:152px}
.loader::before{content:'';position:absolute;inset:0;border-radius:50%;border:3px solid var(--line-2);
  border-top-color:var(--brand);animation:spin .9s linear infinite}
.loader img{width:128px;height:128px;border-radius:50%;animation:breathe 1.6s ease-in-out infinite}
.loader-block{display:flex;flex-direction:column;align-items:center;gap:14px;padding:80px 0}
.loader-block p{font-size:13.5px;color:var(--muted)}
@keyframes spin{to{transform:rotate(360deg)}}
@keyframes breathe{50%{transform:scale(.94);opacity:.85}}

/* ---------- sign-in page ---------- */
.gate{place-items:center;min-height:100dvh;padding:24px;background:var(--bg)}
.gate-card{width:100%;max-width:440px;background:var(--panel);border:1px solid var(--edge);
  box-shadow:var(--shadow-lg);border-radius:28px;padding:34px 34px 26px;animation:rise .45s var(--ease) both}
@keyframes rise{from{opacity:0;transform:translateY(12px) scale(.98)}to{opacity:1;transform:none}}
.gate-brand{display:flex;align-items:center;gap:10px;margin-bottom:34px}
.gate-brand .wordmark-sub{font-size:13px}
.gate-title{margin:10px 0 12px;font-size:clamp(32px,6vw,40px);font-weight:750;letter-spacing:-.05em;line-height:1.02}
.gate-tag{color:var(--muted);font-size:14px;line-height:1.6}
.gate-msg{margin:24px 0 14px;padding:14px 16px;border-radius:var(--r-lg);font-size:13px;
  color:var(--muted);background:var(--tint);border:1px solid transparent}
.gate-msg strong{color:var(--text)}
.gate-msg code{display:inline-block;margin-top:8px;padding:6px 9px;border-radius:var(--r-sm);
  background:var(--panel);color:var(--accent);font-size:12px;word-break:break-all;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.gate-card .btn-ghost{margin-top:10px}
.gate-foot{margin-top:18px;font-size:12.5px;color:var(--faint)}

/* ---------- top bar ---------- */
/* Frosted, like a UINavigationBar: content scrolls softly under it. Only the
   bars are glass; cards stay opaque. */
.topbar{position:sticky;top:0;z-index:30;background:var(--glass);border-bottom:1px solid var(--glass-line);
  -webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px);
  padding-top:var(--sat)}
.topbar-in{max-width:var(--maxw);margin:0 auto;height:var(--bar-h);padding:0 var(--gutter);
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:20px}
.brand{display:inline-flex;align-items:center;gap:12px;min-width:0;justify-self:start;border-radius:var(--r)}
/* The farm's roundel leads the wordmark on every screen, as it does on the
   app icon. Same white disc as everywhere else it appears. */
/* logo-mark.png is the roundel trimmed to its circle and already on white,
   so the green ring runs to the edge: no disc, no padding, no halo. */
.brand-logo{display:block;flex:none;width:44px;height:44px;border-radius:50%}
.gate-brand .brand-logo{width:52px;height:52px}
.brand .wordmark-sub{margin-left:6px}
/* The destinations sit in one soft capsule, the current one raised on a
   white thumb — an iOS segmented control, not a web tab strip. */
.topnav{display:flex;align-items:center;gap:2px;padding:4px;border-radius:999px;background:var(--seg-track)}
.topnav-item{position:relative;display:flex;align-items:center;min-height:36px;padding:0 16px;border-radius:999px;
  font-size:14px;font-weight:650;color:var(--muted);letter-spacing:-.005em;white-space:nowrap}
.topnav-item::before{content:"";position:absolute;left:0;right:0;top:50%;translate:0 -50%;height:44px}
.topnav-item:hover{color:var(--text)}
.topnav-item.on{color:var(--text);background:var(--seg-thumb);box-shadow:var(--seg-shadow)}
.topnav-item:focus-visible{outline-offset:2px}
.topbar-right{display:flex;align-items:center;gap:6px;justify-self:end;min-width:0}

.pill{display:inline-flex;align-items:center;gap:9px;padding:9px 17px;border-radius:999px;white-space:nowrap;
  font-size:13px;font-weight:700;border:1px solid transparent;background:var(--seg-track);color:var(--muted)}
.pill .dot{width:8px;height:8px;border-radius:50%;background:currentColor;flex:none}
.pill-online{color:var(--accent)}
.pill-online .dot{background:var(--brand);animation:pulse 2.4s infinite}
.pill-stale{color:var(--warn);border-color:var(--warn-line)}
.pill-offline{color:var(--bad);border-color:var(--bad-line)}
@keyframes pulse{0%{box-shadow:0 0 0 0 var(--accent-glow)}70%{box-shadow:0 0 0 6px transparent}100%{box-shadow:0 0 0 0 transparent}}

/* ---------- account ---------- */
.acct{position:relative}
.acct-btn{display:flex;align-items:center;gap:10px;padding:4px 4px 4px 10px;border-radius:999px;min-height:44px;
  border:1px solid transparent}
.acct-btn:hover,.acct-btn[aria-expanded="true"]{background:var(--seg-track)}
.acct-name{font-size:14px;font-weight:700;max-width:160px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.avatar{display:grid;place-items:center;width:30px;height:30px;border-radius:50%;flex:none;
  background:var(--panel-3);color:var(--muted);font-weight:800;font-size:12px;text-transform:uppercase}
.acct-menu{position:absolute;right:0;top:calc(100% + 10px);width:270px;padding:8px;z-index:40;
  background:var(--glass);-webkit-backdrop-filter:saturate(180%) blur(24px);backdrop-filter:saturate(180%) blur(24px);
  border:1px solid var(--glass-line);border-radius:var(--r-lg);
  box-shadow:var(--shadow-lg);transform-origin:top right;animation:pop .22s var(--spring) both}
@keyframes pop{from{opacity:0;transform:scale(.92)}to{opacity:1;transform:none}}
.acct-who{display:flex;flex-direction:column;padding:8px 10px 0;font-weight:700;font-size:14px}
.acct-role{font-size:11.5px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--faint);margin-top:2px}
.acct-email{font-size:12.5px;color:var(--muted);padding:4px 10px 10px;word-break:break-all;border-bottom:1px solid var(--line);margin-bottom:6px}
.acct-item{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;padding:0 10px;border-radius:var(--r-sm);
  font-size:13.5px;font-weight:650;color:var(--text)}
.acct-item:hover{background:var(--seg-track)}
.acct-item .ico{color:var(--muted)}

/* ---------- main / view ---------- */
.main{min-height:calc(100dvh - var(--bar-h));display:flex;flex-direction:column}
.view{flex:1;width:100%;max-width:var(--maxw);margin:0 auto;padding:40px var(--gutter) 28px}
.view:focus{outline:none}

/* Search sits between the bar and the view, and only on pages it filters. */
.searchbar{display:none;position:relative;width:100%;max-width:var(--maxw);margin:0 auto;padding:26px var(--gutter) 0}
body[data-route="areas"] .searchbar,body[data-route="devices"] .searchbar,
body[data-route="area"] .searchbar{display:block}
/* Wide screens: the search takes the empty right end of the title row, so
   the page still opens on where you are, not on a text box. */
@media (min-width:901px){
  .main{position:relative}
  .searchbar{position:absolute;z-index:2;right:max(var(--gutter),calc((100% - var(--maxw)) / 2 + var(--gutter)));
    top:94px;width:min(360px,34vw);max-width:none;margin:0;padding:0}
  .search-icon{left:14px!important;top:22px!important}
  body[data-route] .view .page-head{padding-right:min(380px,36vw)}
  body[data-route="overview"] .view .page-head,body[data-route="irrigation"] .view .page-head,
  body[data-route="sys"] .view .page-head,body[data-route="water"] .view .page-head,body[data-route="motor"] .view .page-head,
  body[data-route="admin"] .view .page-head{padding-right:0}
}
@media (max-width:900px){
  body[data-route="areas"] .view,body[data-route="devices"] .view,body[data-route="area"] .view{padding-top:22px}
}
.search-icon{position:absolute;left:calc(var(--gutter) + 14px);top:calc(26px + 22px);transform:translateY(-50%);
  width:17px;height:17px;stroke:var(--faint);pointer-events:none}
/* A filled, borderless field, like UISearchBar. Focus adds a soft ring. */
#search{width:100%;max-width:520px;min-height:44px;padding:0 14px 0 42px;border-radius:var(--r);
  border:1px solid transparent;background:var(--seg-track);color:var(--text);font-size:15px;font-weight:500}
#search::placeholder{color:var(--faint)}
#search:focus{background:var(--panel);border-color:var(--line-2);box-shadow:0 0 0 4px var(--off-soft);outline:none}

/* ---------- page head ---------- */
.page-head{display:flex;align-items:flex-end;gap:16px 24px;flex-wrap:wrap;margin-bottom:26px}
.page-head .spacer{flex:1}
.page-title{margin-top:8px;font-size:clamp(34px,3.35vw,48px);font-weight:750;letter-spacing:-.05em;line-height:1.02;
  color:var(--text);overflow-wrap:anywhere}
.page-sub{font-size:14px;color:var(--muted);margin-top:10px}
.back{display:inline-flex;align-items:center;gap:7px;min-height:32px;margin:-6px 0 -6px;padding:6px 0;
  font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--faint);border-radius:var(--r-sm)}
.back .ico{width:14px;height:14px}
.back:hover{color:var(--text)}

/* ---------- panels ---------- */
.panel{background:var(--panel);border:1px solid var(--edge);border-radius:var(--r-xl);box-shadow:var(--shadow-card);overflow:hidden}
.panel-head{display:flex;align-items:center;justify-content:space-between;gap:12px;
  min-height:62px;padding:12px 22px;border-bottom:1px solid var(--line-soft)}
.panel-title{font-size:16.5px;font-weight:700;letter-spacing:-.025em;color:var(--text)}
.panel-title .n{margin-left:8px;font-size:13px;font-weight:650;color:var(--faint);letter-spacing:0}
.panel-link{display:inline-flex;align-items:center;gap:5px;min-height:44px;margin:-10px 0;padding:0 2px;
  font-size:13.5px;font-weight:700;color:var(--accent);border-radius:var(--r-sm);white-space:nowrap}
.panel-link .ico{width:15px;height:15px;transition:transform .16s var(--ease)}
.panel-link:hover .ico{transform:translateX(3px)}
.panel-body{padding:12px}
.area-sec + .area-sec{margin-top:16px}
.stats + .list,.stats + .grid,.list + .list{margin-top:12px}
.cache-sec{margin-top:12px}
/* A note after a panel or list is its own line, not a caption glued to it. */
:is(.panel,.list,.dgroups,.rep-card) + .more-note{margin-top:12px}

.section-head{display:flex;align-items:center;gap:10px;margin:30px 0 12px}
.section-head:first-child{margin-top:0}
.section-title{font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--faint)}
.section-rule{flex:1;height:1px;background:var(--line)}

/* ---------- overview ---------- */
.ov{display:grid;grid-template-columns:minmax(0,1fr) minmax(340px,494px);gap:20px;align-items:start}
.ov-main,.ov-side{display:flex;flex-direction:column;gap:16px;min-width:0}

.pulse{display:flex;flex-direction:column;padding:32px 30px 26px;
  background:var(--tint);border:1px solid transparent;border-radius:var(--r-xl)}
.pulse-title{margin:12px 0 10px;font-size:clamp(26px,2.3vw,33px);font-weight:750;letter-spacing:-.045em;
  line-height:1.1;max-width:20ch;color:var(--text);text-wrap:balance}
.pulse-body{font-size:14.5px;line-height:1.6;color:var(--muted);max-width:52ch}
/* The whole farm as one bar: reporting, then offline. No third colour. */
.pulse-meter{display:flex;gap:3px;height:8px;margin:26px 0 6px;border-radius:999px;overflow:hidden}
.pulse-meter span{display:block;height:100%;border-radius:999px}
.pm-ok{background:var(--brand)}
.pm-bad{background:var(--bad);opacity:.75}
.pulse.is-quiet .pm-ok{background:var(--warn)}
.pulse-stats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));margin:0 -12px}
.pstat{display:flex;flex-direction:column;gap:6px;min-height:44px;padding:12px;border-radius:var(--r-md)}
a.pstat:hover{background:var(--tint-line)}
.pstat-value{font-size:30px;font-weight:750;letter-spacing:-.05em;line-height:1;color:var(--ink);
  font-variant-numeric:tabular-nums}
.pstat-of{margin-left:2px;font-size:13px;font-weight:650;letter-spacing:0;color:var(--faint)}
.pstat-label{font-size:11.5px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--faint)}
.pstat-bad .pstat-value{color:var(--bad)}

.stats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}
.stat{display:flex;flex-direction:column;gap:10px;padding:22px 22px 20px;min-height:92px;
  background:var(--panel);border:1px solid var(--edge);border-radius:var(--r-xl);box-shadow:var(--shadow-card)}
a.stat:hover{box-shadow:var(--shadow-card-hover)}
.stat-value{font-size:31px;font-weight:750;letter-spacing:-.05em;line-height:1;color:var(--ink);
  font-variant-numeric:tabular-nums}
.stat-of{margin-left:2px;font-size:13px;font-weight:650;letter-spacing:0;color:var(--faint)}
.stat-label{font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--faint)}
.stat-bad .stat-value{color:var(--bad)}
.stat-on .stat-value{color:var(--ink)}

/* Attention: the one number that should make you act. */
.att{padding:0}
.att-top{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:6px 26px;padding:26px 24px}
.att-n{font-size:clamp(46px,4vw,58px);font-weight:750;letter-spacing:-.06em;line-height:.9;color:var(--bad);
  font-variant-numeric:tabular-nums}
.att.is-clear .att-n{color:var(--faint)}
.att-title{font-size:15.5px;font-weight:700;letter-spacing:-.015em;color:var(--text)}
.att-sub{display:inline-flex;align-items:center;gap:6px;margin-top:4px;font-size:13.5px;color:var(--muted);
  min-width:0;max-width:100%}
.att-sub span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
a.att-sub:hover{color:var(--text)}
.att-sub .ico{width:14px;height:14px;flex:none}
.att-list{border-top:1px solid var(--line-soft)}
.att-row{display:flex;align-items:center;gap:14px;min-height:54px;padding:9px 24px;border-bottom:1px solid var(--line-soft)}
.att-row:last-child{border-bottom:0}
.att-row:hover{background:var(--panel-2)}
.att-main{display:flex;flex-direction:column;min-width:0;flex:1}
.att-name{font-size:13.5px;font-weight:650;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.att-meta{font-size:12.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.att-count{flex:none;font-size:13px;font-weight:700;color:var(--bad);font-variant-numeric:tabular-nums}
.att-of{font-weight:600;color:var(--muted)}
.att-bar{display:block;height:4px;margin-top:8px;max-width:220px;border-radius:999px;background:var(--line-soft);overflow:hidden}
.att-bar span{display:block;height:100%;border-radius:999px;background:var(--bad);opacity:.75}
.att-more{display:flex;align-items:center;justify-content:space-between;min-height:48px;padding:0 24px;
  border-top:1px solid var(--line-soft);font-size:13px;font-weight:700;color:var(--accent)}
.att-more:hover{background:var(--panel-2)}

/* ---------- area cards ---------- */
.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fill,minmax(250px,1fr))}
.area-card{position:relative;display:flex;flex-direction:column;gap:4px;min-height:0;padding:16px 18px;
  background:var(--panel);border:1px solid var(--edge);border-radius:var(--r-xl);box-shadow:var(--shadow-card)}
.area-card:hover{box-shadow:var(--shadow-card-hover);transform:translateY(-1px)}
.area-top{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
.area-name{font-size:16px;font-weight:700;letter-spacing:-.025em;line-height:1.25;overflow-wrap:anywhere}
.area-arrow{width:21px;height:21px;margin:-1px -1px 0 0;color:var(--muted);stroke-width:1.5;
  transition:transform .16s var(--ease),color .16s}
.area-card:hover .area-arrow{color:var(--text);transform:translate(2px,-2px)}
.area-count{font-size:12.5px;color:var(--muted)}
.area-count .bad{color:var(--bad);font-weight:650}
.area-meta{display:flex;align-items:center;gap:6px 14px;flex-wrap:wrap;margin-top:auto;padding-top:22px;
  font-size:12.5px;font-weight:700}
.area-meta .on{color:var(--accent)}
.area-meta .bad{color:var(--bad)}
.area-meta .quiet{color:var(--muted);font-weight:600}

/* Status words in running text: coloured, never pill-shaped washes. */
.tag{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;color:var(--muted);
  font-variant-numeric:tabular-nums;white-space:nowrap}
.tag::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}
.tag-on{color:var(--accent)}
.tag-on::before{background:var(--brand)}
.tag-bad{color:var(--bad)}
.tag-warn{color:var(--warn)}
.tag-plain::before{display:none}

/* ---------- device rows (controls) ----------
   One component for Quick controls and every operable row in an area: name
   first, context under it, the control on the right. The old tile grid put
   one toggle in a 285px card; a list is denser and reads top to bottom. */
.dev-list{background:var(--panel);border:1px solid var(--edge);border-radius:var(--r-xl);box-shadow:var(--shadow-card);overflow:hidden}
.dev-list.cols{column-width:420px;column-gap:0}
.panel .dev-list,.panel .list{border:0;border-radius:0;background:transparent;box-shadow:none}
/* Separators are inset to where the text starts, as in an iOS list. */
.dev-card{position:relative;display:flex;flex-direction:column;gap:4px;padding:8px 22px;break-inside:avoid}
.dev-card + .dev-card::before,.row + .row::before,.ac + .row::before,.row + .ac::before,.ac + .ac::before{content:"";position:absolute;top:0;right:0;height:1px;
  left:var(--sep-inset,22px);background:var(--line-soft);pointer-events:none}
.dev-top{display:flex;align-items:center;gap:14px;min-height:44px}
.dev-text{min-width:0;flex:1;display:flex;flex-direction:column;gap:1px}
.dev-name{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  font-size:14px;font-weight:650;letter-spacing:-.01em;line-height:1.3;overflow-wrap:anywhere}
.dev-meta{display:block;min-width:0;font-size:12.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dev-card.is-bad .dev-name{color:var(--muted)}
.dev-state{flex:none;max-width:45%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-variant-numeric:tabular-nums;font-weight:700;font-size:12.5px;padding:4px 11px;border-radius:999px;
  color:var(--muted);background:var(--panel-2);border:1px solid transparent}
.dev-state.on{color:var(--accent)}
.dev-state.alert{color:var(--bad);background:var(--bad-soft)}
.dev-state.unavail{color:var(--faint);font-style:italic;background:transparent;border:1px dashed var(--line-2)}
.flash{animation:flash 1s ease-out}
@keyframes flash{from{background-color:var(--accent-flash)}to{background-color:transparent}}

/* ---------- toggle (role=switch) ---------- */
/* 40x23 as drawn, 44px tall as a target: ::before pads the hit area without
   moving a pixel of layout. ::after is the knob. */
.toggle::before{content:"";position:absolute;left:50%;top:50%;translate:-50% -50%;width:100%;height:44px;z-index:1}
/* UISwitch proportions: a 51x31 track, a 27px knob on a soft drop shadow. */
.toggle{position:relative;flex:none;width:51px;height:31px;border-radius:999px;
  background:var(--track);box-shadow:none}
.toggle::after{content:"";position:absolute;top:2px;left:2px;width:27px;height:27px;border-radius:50%;
  background:var(--knob);box-shadow:0 3px 8px rgba(0,0,0,.15),0 1px 1px rgba(0,0,0,.16),0 3px 1px rgba(0,0,0,.06);
  transition:transform .32s var(--spring)}
.toggle[aria-checked="true"]{background:var(--brand)}
.toggle[aria-checked="true"]::after{transform:translateX(20px);background:#fff}
.toggle[disabled]{opacity:.42;cursor:not-allowed}
.toggle.busy{opacity:.6;cursor:progress}

/* ---------- range ---------- */
.ctl-row{display:flex;align-items:center;gap:12px;padding-bottom:2px}
.ctl-row .ctl-label{font-size:12px;font-weight:650;color:var(--faint);min-width:48px}
.ctl-row .ctl-val{font-size:12.5px;font-weight:650;color:var(--muted);font-variant-numeric:tabular-nums;min-width:40px;text-align:right}
/* 44px of hit area, 22px of layout: the input grows and margin pulls it back. */
input[type=range]{-webkit-appearance:none;appearance:none;flex:1;min-width:0;
  height:44px;margin-block:-11px;background:none;position:relative;z-index:1}
input[type=range]::-webkit-slider-runnable-track{height:5px;border-radius:999px;
  background:linear-gradient(var(--brand),var(--brand)) 0/var(--fill,0%) 100% no-repeat,var(--track)}
input[type=range]::-moz-range-track{height:4px;border-radius:999px;background:var(--track)}
input[type=range]::-moz-range-progress{height:4px;border-radius:999px;background:var(--brand)}
input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:24px;height:24px;margin-top:-9.5px;
  border-radius:50%;background:var(--knob);box-shadow:0 3px 8px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.18)}
input[type=range]::-moz-range-thumb{width:24px;height:24px;border:0;border-radius:50%;background:var(--knob);
  box-shadow:0 3px 8px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.18)}
input[type=range][disabled]{opacity:.42}

/* ---------- read-only rows (sensors, the all-devices list) ---------- */
.list{background:var(--panel);border:1px solid var(--edge);border-radius:var(--r-xl);box-shadow:var(--shadow-card);overflow:hidden}
.list.cols{column-width:420px;column-gap:0;padding:0}
.row{position:relative;display:flex;align-items:center;gap:13px;min-height:56px;padding:9px 20px;
  break-inside:avoid;--sep-inset:63px}
.row:hover{background:var(--panel-2)}
/* A filled squircle, like an iOS Settings icon, but neutral: the glyph's
   colour carries state, never the tile's. */
.row-icon{display:grid;place-items:center;width:30px;height:30px;border-radius:var(--r-sm);flex:none;
  color:var(--muted);background:var(--panel-2)}
.row.is-on .row-icon{color:var(--accent)}
.row.is-bad .row-icon{color:var(--bad);background:var(--bad-soft)}
.row-main{min-width:0;flex:1;display:flex;flex-direction:column;gap:1px}
/* Two lines before it clips: "Car Shed Smart Switch Initial…" hid what it was. */
.row-name{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;min-width:0;overflow:hidden;font-size:14px;font-weight:600}
.row-meta{display:block;min-width:0;font-size:12.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ---------- all devices: one line per device, opening to its readings ---------- */
.dgroups{background:var(--panel);border:1px solid var(--edge);border-radius:var(--r-xl);box-shadow:var(--shadow-card);overflow:hidden}
.dgroup{border-bottom:1px solid var(--line-soft)}
.dgroup:last-child{border-bottom:0}
.dgroup-head{display:flex;align-items:center;gap:16px;width:100%;min-height:64px;padding:10px 22px;text-align:left}
.dgroup-head:hover{background:var(--panel-2)}
.dgroup-head:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.dgroup-main{display:flex;flex-direction:column;min-width:0;flex:1}
.dgroup-name{font-size:14.5px;font-weight:700;letter-spacing:-.015em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dgroup-meta{font-size:12.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dgroup-chev{width:16px;height:16px;color:var(--faint);transition:transform .18s var(--ease)}
.dgroup.open .dgroup-chev{transform:rotate(90deg)}
.dgroup-body{border-top:1px solid var(--line-soft);background:var(--bg);column-width:420px;column-gap:0}
.dgroup-body .row{padding-left:22px}
.dgroup-body .row:hover{background:var(--panel-2)}
.dgroup-solo{border:0;border-radius:0;box-shadow:none;border-bottom:1px solid var(--line-soft)}
.dgroup-solo:last-child{border-bottom:0}

/* ---------- Mobitech account ---------- */
.mb-panel{padding:20px 22px;display:flex;flex-direction:column;gap:14px}
.mb-panel .rep-builder{padding:0;border:0;background:transparent}
.mb-panel .more-note,.panel.mb-panel .more-note{margin:0;padding:0;border:0}
.mb-lead{font-size:13.5px;color:var(--muted);max-width:70ch}
.mb-facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:12px 20px;
  padding:14px 0;border-top:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft)}
.mb-facts div{display:flex;flex-direction:column;gap:3px;min-width:0}
.mb-facts span{font-size:12.5px;font-weight:600;color:var(--faint)}
.mb-facts strong{font-size:14px;font-weight:650;overflow-wrap:anywhere}
.mb-facts .as-of{font-size:12px;font-style:normal;font-weight:600;color:var(--warn)}
.mb-actions{display:flex;gap:10px;flex-wrap:wrap}

/* ---------- admin ---------- */
.acl-row{flex-wrap:wrap;row-gap:8px}
.acl-actions{display:flex;gap:8px;flex-wrap:wrap;margin-left:auto}
.acl-actions .btn{padding:0 14px;font-size:12.5px;min-height:38px}

/* ---------- chips and segments ---------- */
.chips{display:flex;gap:7px;flex-wrap:wrap;margin-bottom:18px}
/* 32px visual pill, 44px hit box: the 6px transparent border belongs to the
   button itself, so hit testing really is 44px (a pseudo-element would not be). */
.chip{padding:6px 14px;border-radius:999px;font-size:13px;font-weight:650;color:var(--text);
  background:var(--seg-track);background-clip:padding-box;border:6px solid transparent;margin:-6px 0;
  text-transform:capitalize}
.chip:hover{background-color:var(--panel-3)}
.chip:focus-visible{outline-offset:-4px}
/* Selected is the ink colour, not green: green means on, not "picked". */
.chip.on{background-color:var(--text);color:var(--panel)}
.chip .n{opacity:.65;margin-left:6px;font-variant-numeric:tabular-nums}

/* UISegmentedControl: a grey track, the choice on a raised white thumb. */
.seg{display:inline-flex;padding:3px;border-radius:11px;background:var(--seg-track);gap:2px}
.seg button{position:relative;padding:7px 14px;border-radius:8px;font-size:13px;
  font-weight:650;color:var(--muted);min-height:38px;white-space:nowrap}
.seg button::before{content:"";position:absolute;left:0;top:50%;translate:0 -50%;width:100%;height:44px}
.seg button:hover{color:var(--text)}
.seg button[aria-pressed="true"]{background:var(--seg-thumb);color:var(--text);box-shadow:var(--seg-shadow)}
.seg .n{margin-left:4px;color:var(--faint);font-variant-numeric:tabular-nums}
.seg button[aria-pressed="true"] .n{color:var(--muted)}
/* An AC (2026-09-25): power, the set temperature between − and +, then its
   mode, fan and preset as segmented rows that scroll when they do not fit. */
.ac{position:relative;display:flex;flex-direction:column;gap:12px;padding:8px 22px 18px;break-inside:avoid}
.ac-temp{display:flex;align-items:center;justify-content:center;gap:28px;padding:4px 0}
.ac-step{width:52px;height:52px;border-radius:50%;background:var(--panel-2);color:var(--text);
  font-size:26px;font-weight:500;line-height:1;display:grid;place-items:center}
.ac-step:active{transform:scale(.94)}
.ac-step[disabled]{opacity:.4}
.ac-set{display:flex;align-items:baseline;gap:3px;min-width:96px;justify-content:center}
.ac-set b{font-size:44px;font-weight:750;letter-spacing:-.05em;line-height:1;font-variant-numeric:tabular-nums;color:var(--ink,var(--text))}
.ac-set small{font-size:15px;font-weight:650;color:var(--faint)}
.ac.is-on .ac-set b{color:var(--accent)}
.ac-line{display:flex;flex-direction:column;align-items:stretch;gap:6px;min-width:0}
.ac-seg{display:flex}
.ac-seg button{flex:1 1 0;min-width:0;padding:7px 2px;text-align:center;justify-content:center;overflow:hidden;text-overflow:ellipsis}
.ac-chips{display:flex;flex-wrap:wrap;gap:6px}
.ac-chips button{padding:7px 13px;min-height:36px;border-radius:999px;font-size:13px;font-weight:650;
  color:var(--muted);background:var(--seg-track)}
.ac-chips button[aria-pressed="true"]{background:var(--brand);color:#fff}
.seg button[disabled]{cursor:default}
/* Off or offline: drawn like the rest, faded, nothing to press. */
.is-faded{opacity:.5;filter:saturate(.4)}
.is-faded :is(button,input,a){pointer-events:none}
.is-faded .panel-head .tag{margin-left:auto}
.toolbar-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-bottom:16px}

.more-note{font-size:13px;color:var(--muted);margin:0 0 14px}
.more-note a{color:var(--accent);font-weight:700}
.panel .more-note{margin:0;padding:12px 22px;border-bottom:1px solid var(--line-soft)}
/* A switched-off capability is not an error: warn-coloured, so a dead control
   has a visible reason next to it without crying failure. */
.more-note.note-off{color:var(--warn)}
.qc-more{display:flex;align-items:center;justify-content:space-between;min-height:48px;padding:0 22px;
  border-top:1px solid var(--line-soft);font-size:13px;font-weight:700;color:var(--accent)}
.qc-more:hover{background:var(--panel-2)}

/* ---------- irrigation report builder ---------- */
/* ---------- forms (report builder, add a person) ----------
   One field system: every control is 44px tall with the same border, radius,
   fill and type, the label sits above it at a fixed height, and the button is
   the same 44px, so a row of them shares one top line and one bottom line.
   Before this, only <select> and date inputs were styled: the email box fell
   back to the browser's own, and the button stood taller than both. */
.rep-builder{display:flex;gap:14px 12px;flex-wrap:wrap;align-items:flex-end;padding:18px 20px 20px;
  background:var(--panel);border:1px solid var(--edge);border-radius:var(--r-xl);box-shadow:var(--shadow-card)}
.rep-field{display:flex;flex-direction:column;gap:7px;min-width:0}
.rep-field > span{display:block;height:16px;line-height:16px;font-size:12px;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:var(--faint)}
.rep-field :is(input,select){display:block;box-sizing:border-box;height:44px;margin:0;padding:0 14px;
  border:1px solid transparent;border-radius:var(--r);background-color:var(--field);color:var(--text);
  font:500 14.5px/1 var(--font);letter-spacing:0;text-transform:none;min-width:0}
.rep-field input[type=email]{width:min(320px,100%)}
.rep-field select{-webkit-appearance:none;appearance:none;padding-right:40px;min-width:220px;cursor:pointer;
  background-image:var(--chev);background-repeat:no-repeat;background-position:right 15px center;background-size:12px 8px}
.rep-field input[type=date]{min-width:170px}
.rep-field :is(input,select)::placeholder{color:var(--faint)}
.rep-field :is(input,select):hover{border-color:var(--line-2)}
.rep-field :is(input,select):focus{background-color:var(--panel);border-color:var(--line-2);box-shadow:0 0 0 4px var(--off-soft);outline:none}
.rep-builder .btn{height:44px;min-height:44px;padding:0 22px;font-size:14.5px}
.rep-builder + .more-note{margin-top:10px}
.btn-primary{background:var(--brand);color:var(--on-brand);box-shadow:var(--shadow)}
.btn-primary:hover{filter:brightness(1.07)}
/* Grey on grey at full strength, not a faded green: white on a 55% brand was ~2:1. */
.btn-primary[disabled]{background:var(--panel-3);border-color:var(--panel-3);color:var(--muted);cursor:default}
.rep-card{padding:0;background:var(--panel);border:1px solid var(--edge);border-radius:var(--r-xl);box-shadow:var(--shadow-card);margin-bottom:12px}
.rep-card:last-child{margin-bottom:0}
.rep-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap;width:100%;min-height:56px;
  padding:14px 20px 4px;text-align:left;border-radius:var(--r-xl)}
.rep-head:hover .rep-title{text-decoration:underline;text-underline-offset:3px;text-decoration-color:var(--line-2)}
.rep-head:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.rep-title{font-size:15px;font-weight:700;letter-spacing:-.015em}
.rep-when{margin-left:auto;font-size:12.5px;color:var(--faint);font-variant-numeric:tabular-nums}
.rep-chev{width:16px;height:16px;color:var(--faint);transition:transform .18s var(--ease)}
.rep-card.open .rep-chev{transform:rotate(90deg)}
.rep-summary{margin:0;padding:0 20px 14px;font-size:13.5px;color:var(--muted)}
.rep-summary.rep-err{color:var(--bad)}
.rep-body{padding:4px 20px 18px;border-top:1px solid var(--line-soft)}
/* A list inside a report is part of the card, not a card within it: it runs
   edge to edge with hairlines above and below instead of its own frame. */
.rep-card .list{margin:10px -20px 0;border-left:0;border-right:0;border-radius:0;background:transparent;box-shadow:none;
  border-color:var(--line-soft)}
.rep-card .list .row{padding-left:20px;padding-right:20px}
.rep-body > .list:first-child{margin-top:-4px;border-top:0}
.rep-body > .list:last-child{margin-bottom:-18px;border-bottom:0}

/* ---------- inline report charts (irrigation: readings + valve runtime) ---------- */
.spark{margin-top:10px}
.spark-svg{width:100%;height:44px;display:block;overflow:visible}
.spark-area{fill:var(--accent-soft);stroke:none}
.spark-line{fill:none;stroke:var(--brand);stroke-width:2;stroke-linecap:round;
  stroke-linejoin:round;vector-effect:non-scaling-stroke}
.spark-dot{fill:var(--brand)}
.spark-labels{display:flex;justify-content:space-between;margin-top:4px;
  font-size:12px;color:var(--faint);font-variant-numeric:tabular-nums}
.spark-last{color:var(--text);font-weight:600}

.bars{margin-top:10px;display:flex;flex-direction:column;gap:8px}
.bar-row{display:grid;grid-template-columns:22px minmax(76px,1fr) 2fr auto;align-items:center;gap:10px}
.bar-label{font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bar-track{height:8px;border-radius:999px;background:var(--off-soft);overflow:hidden}
.bar-fill{display:block;height:100%;border-radius:999px;background:var(--muted)}
.bar-fill.is-on{background:var(--brand)}
/* Farm illustrations (DCON assets) beside valves, bars and log rows. Full
   colour on purpose: they say what a valve waters, which the name alone
   often does not. Never used for state — the tag beside them does that. */
.row-icon-art{background:transparent}
.row-art{width:28px;height:28px;object-fit:contain;display:block}
.bar-art{width:22px;height:22px;object-fit:contain;flex:none}
.tl-art{width:20px;height:20px;object-fit:contain;flex:none}
.bar-value{flex:none;font-size:12px;color:var(--faint);font-variant-numeric:tabular-nums}

/* Multi-series line chart (voltage per phase, inlet vs outlet). Series are
   told apart by weight and dash, not by hue: the accent for the first, the
   page's text and muted greys for the rest. Shaded windows mark where the
   pump was running. */
.chart{position:relative;margin-top:2px}
.chart-plot{position:relative;padding-bottom:18px}
.chart-svg{width:100%;height:150px;display:block;overflow:visible}
.ln-ax{position:absolute;font-size:11px;color:var(--faint);font-variant-numeric:tabular-nums;
  line-height:1;white-space:nowrap;pointer-events:none}
.ln-ay{left:0;width:30px;text-align:right;transform:translateY(-50%)}
.ln-xs{position:absolute;left:0;right:0;bottom:0;height:14px}
.ln-ax-s{transform:none}.ln-ax-m{transform:translateX(-50%)}.ln-ax-e{transform:translateX(-100%)}
.ln{fill:none;stroke-width:1.8;stroke-linejoin:round;stroke-linecap:round;
  vector-effect:non-scaling-stroke}
.ln-0{stroke:var(--brand);stroke-width:2.2}
.ln-1{stroke:var(--text);opacity:.62}
.ln-2{stroke:var(--muted);stroke-dasharray:5 4}
.ln-3{stroke:var(--faint);stroke-dasharray:2 3}
.ln-grid{stroke:var(--line);stroke-width:1;vector-effect:non-scaling-stroke}
.ln-on{fill:var(--accent-soft)}
.ln-hit{fill:transparent}
.ln-hit:hover{fill:var(--off-soft)}
.chart-legend{display:flex;flex-wrap:wrap;gap:4px 14px;margin-top:6px;font-size:12px;color:var(--muted)}
.lg{display:inline-flex;align-items:center;gap:6px}
.lg i{display:inline-block;width:16px;height:0;border-top:2px solid var(--muted)}
.lg i.ln-0{border-top:2.5px solid var(--brand)}
.lg i.ln-1{border-top-color:var(--text);opacity:.62}
.lg i.ln-2{border-top:2px dashed var(--muted)}
.lg i.ln-3{border-top:2px dotted var(--faint)}
.lg-note{color:var(--faint)}

/* Stacked day bars: the whole is power available, the part inside it is
   the pump's share of that. */
.stk{display:flex;align-items:flex-end;gap:3px;height:120px;padding-bottom:16px;position:relative}
.stk-col{flex:1;min-width:0;height:100%;display:flex;flex-direction:column;justify-content:flex-end;
  align-items:stretch;position:relative}
.stk-whole{display:flex;flex-direction:column;justify-content:flex-end;border-radius:4px 4px 2px 2px;
  background:var(--track);overflow:hidden;min-height:2px}
.stk-part{display:block;background:var(--brand);border-radius:3px 3px 0 0}
.stk-at{position:absolute;bottom:-16px;left:0;right:0;text-align:center;font-size:11px;
  color:var(--faint);font-variant-numeric:tabular-nums}
.lg i.stk-k-whole{width:10px;height:10px;border:0;border-radius:2px;background:var(--track)}
.lg i.stk-k-part{width:10px;height:10px;border:0;border-radius:2px;background:var(--brand)}

/* Every valve at a glance. One that got nothing stays in the grid, dimmed
   with the word "none": an idle valve is the thing to notice, not hide. */
.vgrid{display:grid;gap:7px;grid-template-columns:repeat(auto-fill,minmax(112px,1fr))}
.vg{display:grid;grid-template-columns:24px 1fr;grid-template-rows:auto auto;column-gap:8px;
  align-items:center;padding:9px 11px;border-radius:var(--r);background:var(--off-soft)}
.vg-art{grid-row:1 / 3;width:24px;height:24px;object-fit:contain}
.vg-name{font-size:12.5px;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vg-val{font-size:13px;font-weight:700;font-variant-numeric:tabular-nums;color:var(--accent)}
.vg-idle{background:transparent;box-shadow:inset 0 0 0 1px var(--line-2)}
.vg-idle .vg-val{color:var(--faint);font-weight:600}
.vg-idle .vg-art{opacity:.45;filter:grayscale(1)}

/* Valve × day. Heat is the accent at an opacity proportional to minutes. */
.mx-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;border-radius:var(--r-lg);
  box-shadow:inset 0 0 0 1px var(--line)}
.mx{border-collapse:collapse;width:100%;font-size:12px;font-variant-numeric:tabular-nums}
.mx th,.mx td{padding:5px 7px;text-align:center;white-space:nowrap;border-bottom:1px solid var(--line)}
.mx tr:last-child th,.mx tr:last-child td{border-bottom:0}
.mx th{font-weight:600;color:var(--muted);font-size:11.5px}
.mx .mx-name{position:sticky;left:0;text-align:left;background:var(--panel);color:var(--text);
  font-weight:550;font-size:12px;z-index:1}
.mx td{color:var(--text);background:rgb(1 136 67 / var(--heat,0))}
.mx td.mx-zero{color:var(--faint)}
.mx .mx-total{font-weight:700;color:var(--text);background:var(--panel)}

/* ---------- report sections ----------
   One block per vendor call, drawn by the kind the bridge declared: tiles for
   headline numbers, a key/value grid for a controller, a day-grouped timeline
   for logs. Everything reuses the page's existing weights and hues — a report
   should read like the rest of the dashboard, not like a vendor's app. */
.rep-sec{margin-top:11px}
.rep-sec:first-of-type{margin-top:9px}
.sec-title{display:flex;align-items:baseline;gap:8px;margin-bottom:8px;font-size:12px;
  font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--muted)}
.sec-src{font-size:11.5px;font-weight:600;letter-spacing:.04em;color:var(--faint);
  text-transform:none}
.rep-note{margin:7px 0 0;font-size:12.5px;color:var(--faint)}
.rep-note.rep-err{color:var(--bad)}
.rep-sec .list,.rep-sec .bars,.rep-sec .spark,.rep-sec .chart{margin-top:0}

/* auto-fill, not auto-fit: a section with one reading gets a tile the size of
   every other tile, instead of one stretched across the card. */
.tiles{display:grid;gap:9px;grid-template-columns:repeat(auto-fill,minmax(148px,1fr))}
.tile{display:flex;flex-direction:column;gap:2px;padding:12px 14px;border-radius:var(--r-lg);
  background:var(--off-soft)}
.tile-label{font-size:11.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted)}
.tile-value{font-size:21px;font-weight:700;letter-spacing:-.03em;line-height:1.2;
  font-variant-numeric:tabular-nums}
.tile-unit{margin-left:3px;font-size:12px;font-weight:600;color:var(--muted)}
.tile-note{font-size:12px;color:var(--faint)}

.facts{display:grid;gap:1px;border-radius:var(--r-lg);overflow:hidden;background:var(--line-soft)}
.fact{display:flex;align-items:baseline;justify-content:space-between;gap:12px;
  padding:9px 12px;background:var(--panel)}
.fact-label{flex:none;font-size:12px;color:var(--muted)}
.fact-value{font-size:13px;font-weight:600;text-align:right;overflow-wrap:anywhere}

.tl{display:flex;flex-direction:column;gap:2px}
.tl-day{margin:7px 0 3px;font-size:12px;font-weight:700;letter-spacing:.06em;
  color:var(--faint);font-variant-numeric:tabular-nums}
.tl-day:first-child{margin-top:0}
.tl-row{display:flex;align-items:baseline;gap:10px;padding:5px 0}
.tl-at{flex:none;width:44px;font-size:12px;color:var(--faint);font-variant-numeric:tabular-nums}
.tl-main{display:block;min-width:0;flex:1}
.tl-main .row-name,.tl-main .row-meta{display:block;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
/* Scoped to the timeline: a bare .chip here silently restyled every filter chip
   on All devices, which is defined further up with the same name. */
.tl-chip{flex:none;font-size:11.5px;font-weight:650;letter-spacing:.04em;padding:2px 7px;
  border-radius:999px;color:var(--muted);background:var(--off-soft)}

/* ---------- empty ---------- */

.empty{display:flex;flex-direction:column;align-items:center;gap:12px;padding:56px 20px;
  color:var(--muted);text-align:center}
.empty-mark{display:grid;place-items:center;width:48px;height:48px;border-radius:50%;
  background:var(--panel-2);color:var(--faint)}
.empty h3{font-size:16px;font-weight:700;letter-spacing:-.02em;color:var(--text)}
.empty p{font-size:13.5px;max-width:36ch}
.panel .empty{padding:36px 20px}

.foot{width:100%;max-width:var(--maxw);margin:0 auto;padding:18px var(--gutter) calc(22px + var(--sab));
  font-size:12.5px;color:var(--faint);font-variant-numeric:tabular-nums}

/* ---------- toasts ---------- */
.toasts{position:fixed;right:18px;bottom:calc(18px + var(--sab));z-index:80;
  display:flex;flex-direction:column;gap:8px;pointer-events:none;max-width:min(380px,calc(100vw - 32px))}
/* Toasts arrive like an iOS banner: frosted, fully rounded, on a spring. */
.toast{display:flex;align-items:center;gap:10px;padding:13px 18px;border-radius:var(--r-xl);font-size:13px;font-weight:600;
  background:var(--glass);-webkit-backdrop-filter:saturate(180%) blur(24px);backdrop-filter:saturate(180%) blur(24px);
  border:1px solid var(--glass-line);box-shadow:var(--shadow-lg);
  animation:toast-in .42s var(--spring) both}
.toast .ico{width:16px;height:16px}
.toast.ok{color:var(--accent)}
.toast.err{border-color:var(--bad-line);color:var(--bad)}
.toast.out{animation:toast-out .22s var(--ease) both}
@keyframes toast-in{from{opacity:0;transform:translateY(14px) scale(.96)}to{opacity:1;transform:none}}
@keyframes toast-out{to{opacity:0;transform:translateY(6px)}}

/* The theme control offers the theme you are not in: a moon while light, a
   sun while dark. Only ever one glyph. */
.ico-sun{display:none}
:root[data-theme="dark"] .ico-sun{display:block}
:root[data-theme="dark"] .ico-moon{display:none}
@media (prefers-color-scheme: dark){
  :root:not([data-theme]) .ico-sun{display:block}
  :root:not([data-theme]) .ico-moon{display:none}
}

/* ---------- modules (2026-09-25 simplification) ----------
   Home rows, the irrigation modules and folded account sections. Built from
   the same tokens as everything else; nothing new in colour. */
.btn-sm{min-height:36px;padding:0 14px;font-size:13px}
.btn-danger{background:var(--bad-soft);color:var(--bad);border:1px solid var(--bad-line)}
.seg-nav{margin:0 0 18px}
.seg-nav a{padding:7px 16px;border-radius:8px;font-size:13.5px;font-weight:650;color:var(--muted)}
.seg-nav a[aria-current="page"]{background:var(--seg-thumb);color:var(--text);box-shadow:var(--seg-shadow)}

.hrows{display:flex;flex-direction:column}
.hrow{display:flex;align-items:center;gap:12px;min-height:64px;padding:12px 22px;border-bottom:1px solid var(--line-soft);color:inherit}
.hrow:last-child{border-bottom:0}
.hrow:hover{background:var(--panel-2)}
.hrow-main{display:grid;grid-template-columns:110px minmax(0,1fr);column-gap:14px;row-gap:2px;flex:1;min-width:0}
.hrow-title{grid-row:1 / span 2;align-self:center;font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--faint)}
.hrow-value{font-size:15.5px;font-weight:700;color:var(--text)}
.hrow-value.on{color:var(--accent)}
.hrow-meta{font-size:13px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hrow-chev{width:16px;height:16px;color:var(--faint);flex:none}
.ov-main > * + *{margin-top:14px}

/* The controller's page (2026-11-01): Now on top, Watered + Pump beside each
   other, Reports as list + one report beside it, the account last. The
   container is .irr-page (not .wmd-detail, whose containment would trap the
   Run valves drawer). */
.irr-page{container-type:inline-size;display:flex;flex-direction:column;gap:14px;min-width:0}
.irr-duo{display:grid;grid-template-columns:minmax(0,1fr);gap:14px;align-items:stretch}
.irr-duo:empty{display:none}
@container (min-width:720px){
  .irr-duo{grid-template-columns:minmax(0,1.3fr) minmax(0,1fr)}
  .irr-duo > :only-child{grid-column:1 / -1}
}
@media (min-width:901px){ .watered .crop-list{display:grid;grid-template-columns:1fr 1fr;column-gap:0}
  .watered .crop-row{border-right:1px solid var(--line-soft)} .watered .crop-row:nth-child(2n){border-right:0}
  .watered .crop-row:nth-last-child(2):nth-child(odd){border-bottom:0} }
.head-actions{display:flex;align-items:center;gap:10px}
@media (max-width:900px){ .head-actions .pill-head{display:none} }
.now{display:flex;flex-direction:column;gap:8px;padding:20px 22px;background:var(--tint);border-color:var(--tint-line);box-shadow:none}
.now-top{display:flex;align-items:center;gap:10px}
@media (max-width:480px){ .now-top{flex-wrap:wrap} .now-checked{margin-left:0;flex:1 1 auto} .now-top .btn{flex:none} }
.now-label{white-space:nowrap;display:inline-flex;align-items:center;gap:8px;font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--faint)}
.now-label .dot{width:8px;height:8px;border-radius:50%;background:var(--line-2)}
.now.is-on .now-label{color:var(--accent)}
.now.is-on .now-label .dot{background:var(--brand)}
.now-checked{margin-left:auto;font-size:12.5px;color:var(--faint);white-space:nowrap}
.now-top .btn{margin-left:auto}
.now-checked + .btn{margin-left:4px}
.now-title{font-size:clamp(22px,2vw,27px);font-weight:750;letter-spacing:-.035em;color:var(--text)}
.now-detail{font-size:14px;color:var(--muted)}
.now-next{font-size:13.5px;color:var(--text);padding-top:8px;border-top:1px solid var(--tint-line)}
.now-next span{margin-right:8px;font-size:11.5px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--faint)}
.now-actions{display:flex;gap:10px;margin-top:6px}
.now-actions .btn{flex:1}
.now-main{display:flex;align-items:center;gap:22px;min-width:0}
.now-text{display:flex;flex-direction:column;gap:8px;min-width:0;flex:1}
.now .ring{width:112px;height:112px}
.now .ring-mid strong{font-size:19px}
.now .ring-mid small{font-size:12px}
@container (min-width:720px){
  .now{padding:24px 28px}
  .now-title{font-size:clamp(26px,3cqi,34px)}
  .now-actions{margin-top:10px;max-width:420px}
}
@media (max-width:480px){ .now .ring{width:88px;height:88px} .now .ring-mid strong{font-size:16px} .now-main{gap:16px} }
.now .more-note{margin:0;padding:0;border:0}

.irr-mod .panel-head{border-bottom:0;padding-bottom:4px}
.valve-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(128px,1fr));gap:8px;padding:6px 16px 16px}
.vchip{position:relative;display:flex;align-items:center;gap:9px;min-height:48px;padding:6px 10px;border-radius:var(--r);
  background:var(--panel-2);border:1px solid transparent;color:var(--text);text-align:left;font:inherit}
.vchip-art{width:28px;height:28px;flex:none;object-fit:contain}
.vchip-ico{display:grid;place-items:center;color:var(--faint)}
.vchip-ico .ico{width:18px;height:18px}
.vchip-name{font-size:13px;font-weight:650;line-height:1.2;overflow:hidden;text-overflow:ellipsis}
.vchip-dot{position:absolute;top:7px;right:7px;width:7px;height:7px;border-radius:50%;background:var(--brand)}
.vchip.is-on{border-color:var(--accent-line)}
.vchip.is-off{opacity:.4}
.vchip.is-pick{cursor:pointer}
.vchip.is-pick:hover{border-color:var(--line-2)}
.vchip.picked{background:var(--panel);border-color:var(--brand);box-shadow:0 0 0 1px var(--brand) inset}
.vchip:disabled{opacity:.4;cursor:not-allowed}
.run-bar{display:flex;align-items:flex-end;gap:10px;flex-wrap:wrap;padding:14px 16px 16px;border-top:1px solid var(--line-soft)}
.run-bar .rep-field{flex:0 0 96px}
.run-bar .btn{white-space:nowrap}
.run-bar .btn-primary{flex:1}

.figs{display:grid;grid-template-columns:repeat(auto-fit,minmax(70px,1fr));gap:12px;padding:8px 22px 16px}
.fig{display:flex;flex-direction:column;gap:4px;min-width:0}
.fig-v{font-size:24px;font-weight:750;letter-spacing:-.04em;color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap}
.fig-v small{margin-left:3px;font-size:12px;font-weight:650;letter-spacing:0;color:var(--faint)}
.fig-l{font-size:11.5px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--faint)}
.tags{display:flex;gap:14px;flex-wrap:wrap;padding:0 22px 16px}
.run-row{gap:14px}
.run-time{flex:none;width:44px;font-size:13px;font-weight:650;color:var(--faint);font-variant-numeric:tabular-nums}
.run-amt{flex:none;font-size:13px;font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums}
.run-amt.warn{color:var(--warn)}

.irr-reports{margin-top:6px}
.panel-head.bare{padding:0 0 12px;border:0}
.irr-reports .rep-builder{margin-bottom:14px}

details.acct-sec{margin-top:0;padding:0 20px;background:var(--panel);border:1px solid var(--edge);border-radius:var(--r-xl);box-shadow:var(--shadow-card)}
details.acct-sec[open]{padding-bottom:14px}
details.acct-sec > summary,.wdetails > summary{cursor:pointer;list-style:none;display:flex;align-items:center;gap:8px;
  font-size:13px;font-weight:700;color:var(--muted);min-height:44px}
details.acct-sec > summary{font-size:15px;font-weight:700;color:var(--text)}
details.acct-sec > summary::-webkit-details-marker,.wdetails > summary::-webkit-details-marker{display:none}
details.acct-sec > summary::after,.wdetails > summary::after{content:"";width:7px;height:7px;margin-left:2px;
  border-right:1.8px solid currentColor;border-bottom:1.8px solid currentColor;rotate:45deg;translate:0 -2px;transition:rotate .2s var(--ease)}
details[open].acct-sec > summary::after,.wdetails[open] > summary::after{rotate:225deg;translate:0 2px}
.wdetails{border-top:1px solid var(--line-soft);margin-top:-4px}
.wdetails > summary{min-height:40px;font-weight:600;color:var(--faint)}
.wdetails .mb-facts{padding:4px 0 6px}

@media (max-width:900px){
  .hrow{padding:12px 16px}
  .hrow-main{grid-template-columns:minmax(0,1fr)}
  .hrow-title{grid-row:auto}
  .figs{padding:6px 16px 14px}
  .fig-v{font-size:19px}
  .run-bar .btn-ghost{padding:0 12px}
}

/* ---------- Home, drawn (2026-09-25) ----------
   The water chain as pipes, rings for irrigation and devices, solar, and the
   switches as tiles. Green = on / flowing, brick = offline, nothing else. */
.flow{padding:18px 0 8px}
.flow-head{display:flex;align-items:center;gap:10px;margin-bottom:8px;padding:0 22px}
.flow-head .panel-link{margin-left:auto}
.card-age{font-size:12px;font-weight:500;font-style:normal;letter-spacing:0;text-transform:none;color:var(--faint)}
.card-age.is-warn{color:var(--warn)}
.pw-fig.pw-unread{font-size:13.5px;letter-spacing:0;color:var(--warn)}
/* Zone change on the zoned Niagara controller. */
.wzones{display:flex;flex-direction:column;gap:6px;margin-top:10px}
.zchips{display:grid;grid-template-columns:repeat(8,1fr);gap:6px}
.zchip{min-height:44px;border-radius:var(--r-sm, 10px);border:1px solid var(--line-2);background:var(--panel);color:var(--text);font:inherit;font-weight:700;cursor:pointer}
.zchip.is-now{background:var(--brand);border-color:var(--brand);color:var(--on-brand, #fff);cursor:default}
.zchip:disabled:not(.is-now){color:var(--muted);background:var(--panel-2);cursor:default}
.wzones-label{font-size:12px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--faint)}

/* Power: a meter board, not the water chain's circles. Square tiles, rows
 * that read across, one solar bar split by inverter. */
.power{padding:18px 22px 10px}
/* Power beside Irrigation and Security, stacked: the rows set the height. */
.vcards:has(> .power){grid-template-columns:minmax(0,1.25fr) minmax(0,1fr)}
.vcards > .power{grid-row:span 2}
/* With the water card: Water | Power, then Irrigation | Security. */
.vcards:has(> .flow){grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
.vcards:has(> .flow) > .power{grid-row:auto}
.pw-head{display:flex;align-items:center;gap:10px}
.pw-head .panel-link{margin-left:auto}
.pw-solar{display:flex;align-items:baseline;gap:8px;margin-top:10px}
.pw-solar-n{font-size:30px;font-weight:750;letter-spacing:-.045em;color:var(--ink);font-variant-numeric:tabular-nums}
.pw-solar-l{font-size:13px;color:var(--muted)}
.pw-split{display:flex;gap:3px;height:8px;margin:10px 0 6px;border-radius:999px;overflow:hidden}
.pw-seg{display:block;height:100%;border-radius:999px}
.pw-seg.s0,.pw-key.s0{background:var(--brand)}
.pw-seg.s1,.pw-key.s1{background:var(--brand);opacity:.42}
.pw-key{display:inline-block;width:8px;height:8px;margin-right:7px;border-radius:2px;vertical-align:1px}
.pw-rows{margin:6px -22px 0}
.pw-line{display:flex;align-items:center;gap:14px;min-height:68px;padding:10px 22px;border-top:1px solid var(--line-soft);color:inherit;
  transition:background-color .16s,transform .14s var(--ease)}
.pw-line:hover{background:var(--panel-2)}
.pw-line:active{transform:scale(.985)}
.pw-tile{display:grid;place-items:center;flex:none;width:44px;height:44px;border-radius:12px;background:var(--panel-2)}
.pw-art{width:30px;height:30px;object-fit:contain}
.pw-ico{width:24px;height:24px;color:var(--ink);stroke-width:1.7}
.pw-main{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
.pw-title{font-size:14.5px;font-weight:700;color:var(--text)}
.pw-phase{font-size:12.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pw-right{display:flex;flex-direction:column;align-items:flex-end;gap:2px;flex:none;text-align:right}
.pw-fig{font-size:20px;font-weight:750;letter-spacing:-.03em;line-height:1.1;color:var(--ink);font-variant-numeric:tabular-nums}
.pw-fig small{margin-left:3px;font-size:12px;font-weight:650;letter-spacing:0;color:var(--muted)}
.pw-line.is-on .pw-fig{color:var(--accent)}
.pw-line.is-offline .pw-fig,.pw-line.is-off .pw-fig{font-size:14px;color:var(--warn)}
.pw-line.is-rest .pw-fig{font-size:15px;color:var(--muted)}
.pw-line.is-bad .pw-fig{color:var(--bad)}
.pw-line.is-stale .pw-fig{color:var(--muted)}
.pw-sub{font-size:12px;color:var(--muted)}
.pw-mini{display:flex;align-items:flex-end;gap:3px;height:22px}
.pw-mini i{display:block;width:6px;border-radius:2px;background:var(--brand)}
.pw-mini i.warn{background:var(--warn)}
.pw-mini i.dead{background:var(--bad)}
.pw-line.is-stale .pw-mini i{background:var(--faint)}
.pw-sec{padding:18px 22px 20px;margin-bottom:14px;display:flex;flex-direction:column;gap:16px}
.pw-sec-head{display:flex;align-items:center;gap:14px}
.pw-sec-head > div{flex:1;min-width:0}
.pw-sec-sub{margin-top:2px;font-size:13px;color:var(--muted)}
.pw-sec-head .pw-fig{margin:0;font-size:24px;text-align:right}
.pw-sec.is-on .pw-sec-head .pw-fig{color:var(--accent)}
.pw-sec.is-offline .pw-sec-head .pw-fig,.pw-sec.is-off .pw-sec-head .pw-fig{font-size:15px;color:var(--warn)}
.pw-sec.is-rest .pw-sec-head .pw-fig{font-size:17px;color:var(--muted)}
.pw-sec.is-bad .pw-sec-head .pw-fig{color:var(--bad)}
.pw-more{align-self:flex-start}
.vcards{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:14px;margin-bottom:28px}
.vcard{display:flex;flex-direction:column;gap:12px;padding:18px 20px;color:inherit}
.vcard:hover{box-shadow:var(--shadow-card-hover)}
.vcard-body{display:flex;align-items:center;gap:16px}
.vcard-text{display:flex;flex-direction:column;gap:3px;min-width:0}
.vcard-text strong{font-size:16px;font-weight:750;letter-spacing:-.02em;color:var(--text)}
.vcard-text strong.big{font-size:32px;letter-spacing:-.05em;line-height:1}
.vcard-text strong.big small{margin-left:4px;font-size:14px;font-weight:650;letter-spacing:0;color:var(--faint)}
.vcard-text span{font-size:13px;color:var(--muted)}
.vcard-empty{font-size:14px;color:var(--muted)}
.crops{display:flex;gap:4px;margin-top:4px}
.crops .crop{width:26px;height:26px;object-fit:contain}
.ring{position:relative;flex:none;width:92px;height:92px}
.ring svg{width:100%;height:100%;rotate:-90deg}
.ring circle{fill:none;stroke-width:9;stroke-linecap:round}
.ring-track{stroke:var(--panel-3)}
.ring-track.bad{stroke:var(--bad-line)}
.ring-fill{stroke:var(--faint);transition:stroke-dasharray .6s var(--ease)}
.ring.is-on .ring-fill,.ring.donut .ring-fill,.ring.is-done .ring-fill{stroke:var(--brand)}
.ring.is-warn .ring-fill{stroke:var(--warn)}
.ring-mid{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;line-height:1.1}
.ring-mid strong{font-size:17px;font-weight:750;letter-spacing:-.03em;color:var(--ink);font-variant-numeric:tabular-nums}
.ring-mid small{font-size:11px;font-weight:650;color:var(--faint)}
.sun{flex:none;display:grid;place-items:center;width:92px;height:92px;border-radius:50%;background:var(--warn-soft)}
.sun svg{width:52px;height:52px}
.sun circle{fill:var(--warn)}
.sun line{stroke:var(--warn);stroke-width:3;stroke-linecap:round}

.tiles-sec{margin-bottom:8px}
.tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px}
.tile{position:relative;display:flex;flex-direction:column;align-items:flex-start;gap:4px;min-height:118px;padding:14px;
  border-radius:var(--r-lg);background:var(--panel);border:1px solid var(--edge);box-shadow:var(--shadow-card);
  color:var(--text);text-align:left;font:inherit;cursor:pointer;transition:background .2s var(--ease),transform .12s var(--ease)}
.tile:active{transform:scale(.97)}
.tile:disabled{cursor:default}
.tile-ico{display:grid;place-items:center;width:38px;height:38px;border-radius:50%;background:var(--panel-2);color:var(--muted);margin-bottom:auto}
.tile-ico .ico{width:20px;height:20px}
.tile-name{font-size:14px;font-weight:700;line-height:1.25;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.tile-meta{font-size:12px;color:var(--muted)}
.tile.is-on{background:var(--brand);border-color:var(--brand);color:var(--on-brand)}
.tile.is-on .tile-ico{background:rgba(255,255,255,.2);color:var(--on-brand)}
.tile.is-on .tile-meta{color:#fff}
.tile.busy{opacity:.7}
/* Not pressable: flat, the icon dimmed, the words at full strength. A whole-
 * tile fade left the name at 2.2:1 and hid the state a viewer came to read. */
.tile:disabled{box-shadow:none}
.tile:disabled .tile-ico{opacity:.6}

@media (max-width:620px){
  .flow{padding:16px 0 6px} .flow-head{padding:0 16px}
  .vcards{grid-template-columns:1fr 1fr;gap:10px}
  .vcards:has(> .power){grid-template-columns:1fr}
  .vcards > *,.vcards > .power{grid-column:1 / -1;grid-row:auto}
  .power{padding:16px 16px 6px}
  .pw-rows{margin:6px -16px 0}
  .pw-line{padding:10px 16px;gap:12px}
  .pw-solar-n{font-size:26px}
  .pw-fig{font-size:18px}
  .pw-sec{padding:16px}
  .pw-sec .mb-facts{grid-template-columns:repeat(2,minmax(0,1fr))}

  .vcard{padding:16px}
  .vcard-body{gap:12px}
  .ring,.sun{width:76px;height:76px}
  .sun svg{width:42px;height:42px}
  .tiles{grid-template-columns:1fr 1fr}
}

/* ---------- Home v3: needs a look, systems (2026-09-25 night) ---------- */
.attn{margin-bottom:14px;padding:0}
.attn-head{display:flex;align-items:center;gap:12px;width:100%;min-height:60px;padding:12px 22px;border:0;background:none;
  font:inherit;text-align:left;color:inherit;cursor:pointer;transition:background-color .16s}
.attn-head:hover{background:var(--panel-2)}
.attn-head:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.attn-title{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
.attn-peek{font-size:12.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.attn-toggle{transition:transform .18s var(--ease)}
.attn.open .attn-toggle{transform:rotate(90deg)}
.attn-n{display:grid;place-items:center;min-width:30px;height:30px;padding:0 8px;border-radius:999px;background:var(--warn-soft);color:var(--warn);font-weight:750;font-variant-numeric:tabular-nums}
.attn.is-bad .attn-n{background:var(--bad-soft);color:var(--bad)}
.attn-row{display:flex;align-items:center;gap:12px;min-height:56px;padding:9px 22px;border-top:1px solid var(--line-soft);color:inherit}
.attn-row:hover{background:var(--panel-2)}
.attn-dot{flex:none;width:10px;height:10px;border-radius:50%;background:var(--warn)}
.attn-row.bad .attn-dot{background:var(--bad)}
.attn-main{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1}
.attn-main strong{font-size:14.5px;font-weight:700;color:var(--text)}
.attn-row.bad .attn-main strong{color:var(--bad)}
/* Two lines before it clips: "quiet for 7m" was cut to "quiet f…". */
.attn-main span{font-size:12.5px;color:var(--muted);overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.attn-chev{width:15px;height:15px;color:var(--faint);flex:none}
.attn-more{display:block;width:100%;min-height:44px;padding:8px 22px;border:0;border-top:1px solid var(--line-soft);background:none;
  text-align:left;font:inherit;font-size:13px;font-weight:700;color:var(--accent);cursor:pointer}
.attn-more:hover{background:var(--panel-2)}
.attn.is-clear{display:flex;align-items:center;gap:14px;padding:14px 22px}
.attn.is-clear > span:last-child{display:flex;flex-direction:column}
.attn.is-clear strong{font-size:15px;color:var(--text)}
.attn.is-clear span span{font-size:13px;color:var(--muted)}
.attn-ok{display:grid;place-items:center;width:34px;height:34px;border-radius:50%;background:var(--brand);color:var(--on-brand)}
.attn-ok .ico{width:18px;height:18px;stroke-width:2.4}

.shield{flex:none;display:grid;place-items:center;width:92px;height:92px;border-radius:50%;background:var(--panel-2);color:var(--faint)}
.shield .ico{width:44px;height:44px}
.sec.is-on .shield{background:var(--accent-glow);color:var(--accent)}
.sec.is-bad .shield{background:var(--bad-soft);color:var(--bad)}
.cam-dots{display:flex;gap:5px;margin-top:6px}
.cam-dots i{width:9px;height:9px;border-radius:50%;background:var(--brand)}
.cam-dots i.off{background:var(--bad)}
.solar.is-rest .sun,.solar.is-offline .sun{background:var(--panel-2)}
.solar.is-rest .sun circle,.solar.is-offline .sun circle{fill:var(--faint)}
.solar.is-rest .sun line,.solar.is-offline .sun line{stroke:var(--faint)}

.sys-sec{margin-top:28px}
.sys-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(170px,1fr));gap:10px}
.sys-tile{display:flex;flex-direction:column;gap:3px;min-height:112px;padding:14px;border-radius:var(--r-lg);background:var(--panel);
  border:1px solid var(--edge);box-shadow:var(--shadow-card);color:inherit}
.sys-tile:hover{box-shadow:var(--shadow-card-hover)}
.sys-ico{display:grid;place-items:center;width:36px;height:36px;border-radius:50%;background:var(--panel-2);color:var(--muted);margin-bottom:10px}
.sys-ico .ico{width:19px;height:19px}
.sys-ico.big{width:64px;height:64px;margin:0}
.sys-ico.big .ico{width:30px;height:30px}
.sys-tile.is-on .sys-ico,.sys-hero.is-on .sys-ico{background:var(--accent-glow);color:var(--accent)}
.sys-name{font-size:14px;font-weight:700;color:var(--text)}
.sys-line{font-size:13px;font-weight:650;color:var(--muted)}
.sys-tile.is-on .sys-line{color:var(--accent)}
.sys-tile.is-offline .sys-line,.sys-tile.is-warn .sys-line{color:var(--warn)}
.sys-sub{font-size:12px;color:var(--faint)}
.sys-hero{display:flex;align-items:center;gap:20px;padding:20px 22px;margin-bottom:14px}
.sys-hero .mb-facts{flex:1;border:0;padding:0}
.sys-hero-body{flex:1;display:flex;flex-direction:column;gap:12px;min-width:0}
.sys-hero-title{font-size:24px;font-weight:750;letter-spacing:-.035em;color:var(--text)}
.sys-hero.is-on .sys-hero-title{color:var(--accent)}
.sys-hero.is-bad .sys-hero-title{color:var(--bad)}
.sys-hero-sub{font-size:14px;color:var(--muted)}
@media (max-width:620px){
  .attn-head,.attn-row{padding-left:16px;padding-right:16px}
  .sys-grid{grid-template-columns:1fr 1fr}
  .sys-hero{flex-direction:column;align-items:flex-start}
  .shield{width:76px;height:76px}
  .shield .ico{width:36px;height:36px}
}

/* ---------- Irrigation v3: watered by crop, pump & power ---------- */
.seg-sm{margin-left:auto}
.seg-sm button{padding:5px 11px;font-size:12.5px}
.watered .figs{padding-top:4px}
.crop-list{display:flex;flex-direction:column;border-top:1px solid var(--line-soft)}
.crop-row{display:flex;align-items:center;gap:12px;padding:10px 22px;border-bottom:1px solid var(--line-soft)}
.crop-row:last-child{border-bottom:0}
.crop-art{flex:none;width:34px;height:34px;object-fit:contain}
.crop-ico{display:grid;place-items:center;border-radius:50%;background:var(--panel-2);color:var(--faint)}
.crop-ico .ico{width:18px;height:18px}
.crop-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.crop-name{font-size:14.5px;font-weight:700;color:var(--text)}
.crop-valves{font-size:12px;color:var(--muted);overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.crop-row.is-cut .crop-valves{color:var(--warn)}
.crop-bar{display:block;height:5px;border-radius:3px;background:var(--panel-3);overflow:hidden}
.crop-bar i{display:block;height:100%;border-radius:3px;background:var(--brand)}
.crop-row.is-cut .crop-bar i{background:var(--warn)}
.crop-min{flex:none;min-width:58px;text-align:right;font-size:14px;font-weight:750;color:var(--ink);font-variant-numeric:tabular-nums}
.crop-dry,.crop-empty{padding:12px 22px 16px!important;margin:0!important;border:0!important}
.supply{display:flex;align-items:flex-end;gap:26px;padding:6px 22px 14px}
.phases{display:flex;gap:14px}
.phase{display:flex;flex-direction:column;align-items:center;gap:4px}
.phase-bar{display:flex;align-items:flex-end;width:22px;height:72px;border-radius:6px;background:var(--panel-3);overflow:hidden}
.phase-bar i{display:block;width:100%;background:var(--brand);border-radius:6px 6px 0 0}
.phase.warn .phase-bar i{background:var(--warn)}
.phase.dead .phase-bar i{background:var(--bad)}
.phase strong{font-size:14px;font-weight:750;color:var(--ink);font-variant-numeric:tabular-nums}
.phase.warn strong{color:var(--warn)}
.phase.dead strong{color:var(--bad)}
.phase small{font-size:11px;font-weight:700;color:var(--faint)}
.pressure{display:flex;flex-direction:column;gap:3px;padding-bottom:4px}
.pressure-out{font-size:12.5px;color:var(--muted)}
@media (max-width:620px){ .crop-row{padding:10px 16px} .supply{padding:6px 16px 14px;gap:20px} }

/* ---------- water chain ----------
   Three numbered stages joined by a thin vertical flow line, so the page
   reads top to bottom the way the water goes: river, other farm, main farm.
   Motor cards reuse .panel and .mb-facts; only the stage frame is new. */
.more-note.note-bad{color:var(--bad)}
.wchain{display:flex;flex-direction:column}
.wstage-head{display:flex;align-items:flex-start;gap:14px;margin-bottom:14px}
.wstage-n{flex:none;display:grid;place-items:center;width:32px;height:32px;border-radius:50%;
  background:var(--panel-3);color:var(--ink);font-size:14px;font-weight:750;font-variant-numeric:tabular-nums}
.wstage-title{font-size:19px;font-weight:750;letter-spacing:-.03em;color:var(--text);line-height:32px}
.wstage-lead{font-size:13.5px;color:var(--muted)}
.wstage-body{padding-left:46px}
.wstage-body > .more-note{margin:0 0 12px}
.wflow{display:flex;align-items:center;gap:12px;min-height:46px;padding-left:15px}
.wflow span{width:2px;align-self:stretch;border-radius:2px;background:var(--line-2)}
.wflow em{font-style:normal;font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--faint)}
.wmotors{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,360px),1fr));gap:14px}
.wmotor{display:flex;flex-direction:column;gap:14px;padding:18px 22px 16px}
.wmotor .more-note{margin:0;padding:0;border:0}
.wmotor .mb-facts{padding:0;border:0;grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}
.wmotor-head{display:flex;align-items:center;gap:14px}
.wmotor-art{flex:none;box-sizing:border-box;width:44px;height:44px;padding:7px;border-radius:12px;background:var(--panel-2);object-fit:contain}
.wmotor-title{flex:1;min-width:0}
.wmotor-title h3{font-size:16.5px;font-weight:750;letter-spacing:-.025em;color:var(--text);overflow-wrap:anywhere}
.wmotor-title p{font-size:13px;color:var(--muted)}
.wmotor-when{font-size:12.5px;color:var(--faint);border-top:1px solid var(--line-soft);padding-top:10px}
.wmain{display:flex;align-items:center;gap:14px;padding:16px 22px;color:inherit}
.wmain:hover{box-shadow:var(--shadow-card-hover)}
.wmain > .ico{width:18px;height:18px;color:var(--faint)}
@media (max-width:620px){
  .wstage-body{padding-left:0}
  .wmotor{padding:16px 16px 14px}
  .wmotor .mb-facts{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* ---------- bottom tab bar (phones) ---------- */
.tabbar{display:none}
.only-narrow{display:none}

/* ---------- responsive ---------- */
@media (max-width:1180px){
  .topnav-item{padding:0 11px}
  .brand{gap:10px}
  .acct-name{display:none}
  .acct-btn{padding:4px}
}
@media (max-width:1080px){
  .ov{grid-template-columns:minmax(0,1fr) minmax(300px,400px)}
}
/* Phones and small tablets: the destinations move to the bottom, the bridge
   state moves up, and the overview becomes one column in the order you need
   it — what is wrong, how the farm is, the numbers, what you can switch,
   then the rooms. */
@media (max-width:900px){
  :root{--bar-h:60px}
  .topbar-in{grid-template-columns:1fr auto;gap:10px}
  .topnav,.only-wide{display:none}
  .only-narrow{display:inline-flex}
  .brand .wordmark-sub{display:none}
  .wordmark{font-size:21px}
  .brand-logo{width:36px;height:36px}
  #m-bridge{padding:7px 12px;font-size:12.5px;gap:7px}
  .page-head .pill-head{display:none}
  .main{padding-bottom:calc(64px + var(--sab))}
  /* Frosted like a UITabBar; the current tab sits on a soft capsule. */
  .tabbar{display:flex;position:fixed;left:0;right:0;bottom:0;z-index:40;gap:4px;
    padding:8px 10px calc(8px + var(--sab));background:var(--glass);border-top:1px solid var(--glass-line);
    -webkit-backdrop-filter:saturate(180%) blur(20px);backdrop-filter:saturate(180%) blur(20px)}
  .tab-item{position:relative;flex:1;display:flex;align-items:center;justify-content:center;
    min-height:44px;border-radius:999px;color:var(--muted);font-size:13px;font-weight:650;letter-spacing:-.005em}
  .tab-item:hover{color:var(--text)}
  .tab-item.on{color:var(--text);background:var(--seg-track)}
  .tab-item:focus-visible{outline-offset:-2px}

  .view{padding-top:30px}
  .ov{display:flex;flex-direction:column;align-items:stretch;gap:14px}
  .ov-main,.ov-side{display:contents}
  .att{order:1} .pulse{order:2} .qc{order:3} .ov-areas{order:4}
  .toasts{left:16px;right:16px;bottom:calc(76px + var(--sab));max-width:none}
}
@media (max-width:620px){
  .tabbar{gap:2px;padding-left:6px;padding-right:6px}
  .tab-item{font-size:12px;letter-spacing:-.02em}
  .page-title{font-size:34px}
  .page-head{margin-bottom:20px}
  .pulse{padding:22px 18px 16px}
  .pulse-title{font-size:24px;margin:10px 0 8px}
  .pulse-body{font-size:13.5px}
  .pulse-meter{margin-top:20px}
  .pulse-stats{margin:0 -8px}
  .pstat{padding:10px 8px}
  .pstat-value{font-size:24px;white-space:nowrap}
  .pstat-label{font-size:10.5px;letter-spacing:.08em}
  .stats{gap:8px}
  .stat{padding:18px 14px 16px;min-height:0}
  .stat-value{font-size:22px;white-space:nowrap}
  .stat-note{font-size:12px}
  /* Report header on a phone: title and status on one line, the date under
     it from the left edge, the chevron pinned top right. */
  .rep-head{position:relative;padding:14px 44px 4px 16px;row-gap:4px}
  .rep-when{margin-left:0;width:100%}
  .rep-chev{position:absolute;right:16px;top:18px}
  .rep-summary{padding:0 16px 14px}
  .rep-body{padding:4px 16px 16px}
  .rep-card .list{margin-left:-16px;margin-right:-16px}
  .rep-card .list .row{padding-left:16px;padding-right:16px}
  .rep-body > .list:last-child{margin-bottom:-16px}
  .stat-label{font-size:11px;letter-spacing:.1em}
  .att-top{padding:22px 18px;gap:4px 20px}
  .att-row,.att-more{padding-left:18px;padding-right:18px}
  .panel-head{padding:10px 18px;min-height:58px}
  .panel-body{padding:10px}
  .dev-card{padding:8px 18px;--sep-inset:18px}
  .row{padding:9px 16px;--sep-inset:59px}
  .grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
  .area-card{padding:14px;border-radius:var(--r-lg)}
  .stat{border-radius:var(--r-lg)}
  .area-name{font-size:15px}
  .area-meta{padding-top:18px;gap:4px 10px;font-size:12px}
  .area-meta .quiet{display:none}
  .dev-list.cols,.list.cols,.dgroup-body{column-width:auto}
  .chips{flex-wrap:nowrap;overflow-x:auto;margin:0 calc(-1 * var(--gutter)) 14px;padding:6px var(--gutter);
    scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .chips::-webkit-scrollbar{display:none}
  .chip{flex:none}
  .dgroup-head{padding:10px 18px;gap:12px}
  .dgroup-body .row{padding-left:18px}
  .gate-card{padding:28px 22px 22px}
  .rep-builder{padding:16px}
  .rep-field,.rep-field :is(input,select),.rep-builder .btn{width:100%;min-width:0}
  .rep-field input[type=email]{width:100%}
}
@media (max-width:360px){
  .grid{grid-template-columns:1fr}
  .stat-label{font-size:11px;letter-spacing:.04em}
}

/* The bridge dot pulse, the change flash and card lifts are motivated motion,
   but they still yield to the OS setting. Colour and words carry meaning. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
  /* The ring still turns (it says "still working"); the logo stops breathing. */
  .loader::before{animation:spin 1.2s linear infinite!important}
}

/* Water: the water's path (waterPath). One row per motor on the pipe the
 * water takes; every motor row alike, each opening its own page. A pipe
 * segment is green only while its motor runs on a current reading. */
.wpath{padding:6px 0;max-width:760px;overflow:hidden}
.wpath + .wpath{margin-top:12px}
.wp-row{display:grid;grid-template-columns:56px minmax(0,1fr) auto auto;align-items:center;column-gap:12px;
  position:relative;padding-right:14px;color:inherit;text-decoration:none}
.wp-place{grid-template-columns:56px 1fr;min-height:30px}
.wp-motor{min-height:68px}
.wp-branch{grid-template-columns:56px 50px minmax(0,1fr) auto auto;column-gap:0}
.wp-branch .wp-text{padding-left:10px}
.wp-branch .wp-state{margin-left:12px}
.wp-branch .wp-go{margin-left:12px}
.wp-motor:hover{background:var(--panel-2)}
.wp-motor:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.wp-g{position:relative;align-self:stretch;display:grid;place-items:center}
/* The pipe: two halves, above and below the row's centre. */
.wp-rail{position:relative;align-self:stretch;width:56px;display:block}
.wp-g .wp-rail{position:absolute;inset:0}
.wp-rail::before,.wp-rail::after{content:"";position:absolute;left:26px;width:4px;background:var(--line-2)}
.wp-rail::before{top:0;height:50%}
.wp-rail::after{top:50%;bottom:0}
.wp-rail.up-on::before,.wp-rail.dn-on::after{background:var(--brand)}
.wp-rail.no-up::before,.wp-rail.no-dn::after{display:none}
.wp-place .wp-rail::after{top:50%}
.wp-place .wp-rail{background:radial-gradient(circle at 28px 50%, var(--line-2) 0 5px, transparent 5.5px)}
.wp-place-name{font-size:11px;font-weight:750;letter-spacing:.08em;text-transform:uppercase;color:var(--faint)}
.wp-st{position:relative;z-index:1;width:40px;height:40px;border-radius:50%;display:grid;place-items:center;
  background:var(--panel-2);border:2px solid var(--line-2)}
.wp-st img{width:26px;height:26px;object-fit:contain}
.wp-st.is-on{border:3px solid var(--brand);box-shadow:0 0 0 4px rgba(1,136,67,.14)}
/* The branch: a short pipe from the rail to the Well motor. */
.wp-stub{position:relative;align-self:stretch;display:grid;place-items:center end}
.wp-stub::before{content:"";position:absolute;left:-28px;right:40px;top:calc(50% - 2px);height:4px;background:var(--line-2)}
.wp-stub.is-on::before{background:var(--brand)}
.wp-text{display:flex;flex-direction:column;gap:2px;min-width:0;padding:10px 0}
.wp-text strong{font-size:15px;font-weight:700;color:var(--text);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
/* Two lines at most, so "Niagara did not answer" is said whole on the
   indented Well motor row instead of cut. */
.wp-text small{font-size:12.5px;color:var(--muted);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.wp-state{display:flex;flex-direction:column;align-items:flex-end;gap:2px}
.wp-state em{font-style:normal;font-size:11.5px;color:var(--faint);white-space:nowrap}
.wp-go{width:16px;height:16px;color:var(--faint)}
/* Home: the same path, tighter, inside the water card. */
.wpath.is-compact{max-width:none;padding:0 0 6px;overflow:visible}
.wpath.is-compact .wp-motor{min-height:58px}
.wpath.is-compact .wp-text{padding-top:7px;padding-bottom:7px}
.wpath.is-compact .wp-rail.no-up::before,.wpath.is-compact .wp-rail.no-dn::after{display:none}

/* Phone: switch tiles read across (icon, then name and state), half the
 * height, so seven switches no longer take a whole screen. */
@media (max-width:620px){
  .tile{display:grid;grid-template-columns:34px minmax(0,1fr);grid-template-rows:auto auto;column-gap:10px;row-gap:1px;
    align-content:center;min-height:60px;padding:10px 12px}
  .tile-ico{grid-row:1 / 3;width:34px;height:34px;margin:0;align-self:center}
  .tile-name{-webkit-line-clamp:2}
  .sys-tile{display:grid;grid-template-columns:36px minmax(0,1fr);column-gap:10px;row-gap:1px;align-content:center;min-height:64px;padding:10px 12px}
  .sys-tile .sys-ico{grid-row:1 / 4;margin:0;align-self:center}
}

/* A source that cannot be read, in place of its last reading (2026-09-26). */
.unread-hero{display:flex;flex-direction:column;gap:10px;padding:22px}
.uh-ico{display:grid;place-items:center;width:56px;height:56px;border-radius:50%;background:color-mix(in srgb,var(--warn) 14%,transparent);color:var(--warn)}
.uh-ico .ico{width:26px;height:26px}
.uh-title{font-size:20px;font-weight:750;letter-spacing:-.02em;color:var(--text)}
.uh-reason{font-size:14.5px;color:var(--muted);line-height:1.45}
.uh-do{font-size:14px;font-weight:600;color:var(--text)}
.uh-btn{align-self:stretch;min-height:48px;font-size:15.5px}
.uh-inline{color:var(--warn)}
/* ---------- Home on a wide screen (chunk 3) ----------
   Water leads across the full width, Power beside Irrigation + Security
   stacked to its height (rows share height, so no card is stretched past its
   content), then Switches with the farm's systems beside them. */
@media (min-width:621px){
  .vcards:has(> .flow){grid-template-columns:minmax(0,1.25fr) minmax(0,1fr)}
  .vcards > .flow{grid-column:1 / -1}
  .vcards:has(> .flow) > .power{grid-row:span 2}
}
.flow{container-type:inline-size}
.wchain{display:none;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);padding:4px 12px 12px}
.wc-cell{display:flex;flex-direction:column;align-items:center;text-align:center;gap:3px;padding:6px 0 10px;border-radius:var(--r);color:inherit;min-width:0}
.wc-cell:hover{background:var(--panel-2)}
.wc-cell > strong,.wc-cell > small,.wc-state{padding:0 10px;max-width:100%}
.wc-cell > strong{font-size:15px;font-weight:700;color:var(--text);overflow-wrap:anywhere}
.wc-cell > small{font-size:12.5px;color:var(--muted)}
.wc-pipe{display:flex;align-items:center;width:100%;height:48px;margin-bottom:6px}
.wc-pipe i{flex:1;height:4px;background:var(--line-2)}
.wc-pipe i.on{background:var(--brand)}
.wc-pipe i.none{background:transparent}
.wc-state{display:flex;flex-direction:column;align-items:center;gap:2px;margin-top:5px}
.wc-state em{font-style:normal;font-size:11.5px;color:var(--faint);white-space:nowrap}
@container (min-width:680px){
  .wpath.is-compact{display:none}
  .wchain{display:grid}
}
.home-low{display:block}
.home-low .tiles{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
@media (min-width:1100px){
  .home-low.two{display:grid;grid-template-columns:minmax(0,2fr) minmax(0,1fr);gap:0 28px;align-items:start}
  /* Around the farm: one row per system beside the switches. */
  .home-low.two .sys-sec{margin-top:0}
  .home-low.two .sys-grid{grid-template-columns:1fr}
  .home-low.two .sys-tile{display:grid;grid-template-columns:36px minmax(0,1fr);column-gap:12px;row-gap:1px;align-content:center;min-height:66px;padding:10px 14px}
  .home-low.two .sys-tile .sys-ico{grid-row:1 / 4;margin:0;align-self:center}
}
.sys-grid{grid-template-columns:repeat(auto-fit,minmax(170px,1fr))}
@media (max-width:620px){ .sys-grid{grid-template-columns:1fr 1fr} }

/* ---------- Water: two panes, and the motor page (chunk 4) ---------- */
.wmd-list .wpath{max-width:none}
.wp-motor.is-sel{background:var(--panel-2);box-shadow:inset 3px 0 0 var(--brand)}
.wsum{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px;align-items:stretch}
.wsum-card{display:flex;flex-direction:column;gap:4px;padding:18px 20px;color:inherit;min-width:0}
.wsum-card:hover{box-shadow:var(--shadow-card-hover)}
.wsum-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}
.wsum-name{font-size:17px;font-weight:750;letter-spacing:-.02em;color:var(--text)}
.wsum-line{font-size:13px;color:var(--muted)}
.wsum-age{font-style:normal;font-size:12px;color:var(--faint)}
.wsum-facts{display:flex;flex-wrap:wrap;gap:6px 18px;margin-top:auto;padding-top:12px;font-size:14px;font-weight:650;color:var(--text);font-variant-numeric:tabular-nums}
.wsum-facts span{display:flex;flex-direction:column;gap:1px}
.wsum-facts small{font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--faint)}
@media (max-width:1099px){
  .wmd.is-motor .wmd-list,.wmd.is-water .wmd-detail{display:none}
}
.wmd-detail .now-top{flex-wrap:wrap}
.wmd-detail .now-checked{flex:1 1 auto;margin-left:0}
@media (min-width:1100px){
  .wmd{display:grid;grid-template-columns:minmax(330px,380px) minmax(0,1fr);gap:20px;align-items:start}
  .wmd-list{position:sticky;top:84px}
  .wmd-list .wp-go{display:none}
  .wmd-list .wp-row{grid-template-columns:56px minmax(0,1fr) auto}
  .wmd-list .wp-branch{grid-template-columns:56px 50px minmax(0,1fr) auto}
  .wmd-detail .unread-hero{max-width:640px}
  /* The list is the way back to Water. */
  body[data-route="motor"] .view .page-head .back{display:none}
}
.wmd-detail{min-width:0}
.wm-hero{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:18px 28px;padding:22px 24px}
.wm-state{display:flex;align-items:flex-start;gap:16px;min-width:0}
.wm-art{width:56px;height:56px;padding:9px;border-radius:16px}
.wm-word{display:flex;flex-direction:column;gap:5px;min-width:0}
.wm-word > strong{font-size:30px;font-weight:750;letter-spacing:-.04em;line-height:1.05;color:var(--ink)}
.wm-hero.is-on .wm-word > strong{color:var(--accent)}
.wm-word > span{font-size:14px;color:var(--muted)}
.wm-line{display:flex;flex-direction:column;gap:1px;margin-top:4px}
.wm-line i{font-style:normal;font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--faint)}
.wm-line b{font-size:15px;font-weight:650;color:var(--text)}
.wm-line .as-of{font-size:12px;font-style:normal;font-weight:600;color:var(--warn)}
.wm-word > small{font-size:12.5px;color:var(--faint)}
.wm-metrics{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:10px;align-content:start}
.wm-metrics > div{display:flex;flex-direction:column;gap:3px;min-width:0;padding:12px 14px;border-radius:var(--r);background:var(--panel-2)}
.wm-metrics span{font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--faint)}
.wm-metrics strong{font-size:16px;font-weight:700;letter-spacing:-.015em;color:var(--text);overflow-wrap:anywhere;font-variant-numeric:tabular-nums}
.wm-metrics .as-of{font-size:12px;font-style:normal;font-weight:600;color:var(--warn)}
.wm-notes{grid-column:1 / -1;display:flex;flex-direction:column;gap:6px}
.wm-hero .wm-notes .more-note{margin:0}
.wm-control{margin-top:14px;padding:18px 24px;display:flex;flex-direction:column;gap:10px}
.wm-control .wzones{margin-top:0}
.wm-control .more-note{margin:0;padding:0;border:0}
/* Page bar: Refresh and the on/off button at the right edge. */
.wm-acts{margin-left:auto}
.wm-acts .now-actions{margin:0}
.wm-acts .now-actions .btn{flex:none;min-height:36px;padding:0 18px;font-size:13.5px}
@media (max-width:1099px) and (min-width:621px){ .wm-hero{grid-template-columns:minmax(0,5fr) minmax(0,7fr)} }
@media (max-width:760px) and (min-width:621px){ .wm-hero{grid-template-columns:1fr} }
@media (max-width:620px){
  .wm-hero{grid-template-columns:1fr;padding:18px 16px;gap:16px}
  .wm-word > strong{font-size:26px}
  .wm-metrics{grid-template-columns:repeat(2,minmax(0,1fr))}
  .wm-control{padding:16px}
  /* On a phone the bar's buttons take a full row, the on/off one first and big. */
  .page-head:has(.wm-acts){flex-wrap:wrap}
  .wm-acts{flex:1 1 100%;margin-left:0;flex-direction:row-reverse;gap:10px}
  .wm-acts .now-actions{flex:1}
  .wm-acts .now-actions .btn{width:100%;min-height:48px;font-size:15.5px}
  .wm-acts .btn-ghost{min-height:48px;padding:0 18px}
}
/* One sign-in card (Mobitech / Livesky): title, why, then number and code. */
.signin-card{display:flex;flex-direction:column;gap:12px;padding:22px}
.signin-card .uh-reason{margin-bottom:2px}
.si-row{display:flex;gap:12px;align-items:flex-end;flex-wrap:wrap}
.signin-card .rep-field{flex:1 1 220px;max-width:340px}
.signin-card .rep-field > span{height:auto;line-height:1.3;font-size:13px;font-weight:600;letter-spacing:0;text-transform:none;color:var(--muted)}
.signin-card .btn{height:44px;min-height:44px;padding:0 22px;font-size:14.5px}
.si-sent{font-size:14px;font-weight:600;color:var(--text)}
.si-hint{font-size:13px;color:var(--faint)}
.si-err{font-size:13.5px;font-weight:600;color:var(--warn)}
.si-links{display:flex;gap:18px;flex-wrap:wrap}
.si-link{appearance:none;border:0;background:none;padding:2px 0;font:inherit;font-size:13.5px;font-weight:600;color:var(--muted);cursor:pointer;text-decoration:underline;text-underline-offset:3px}
.si-link:hover:not(:disabled){color:var(--text)}
.si-link:disabled{opacity:.5;cursor:default;text-decoration:none}
@media (max-width:640px){.signin-card .rep-field{flex-basis:100%;max-width:none}.signin-card .btn{width:100%}}

/* ---------- Water: the journey, drawn (2026-11-01) ----------
 * River, Thoppu and the farm as three places joined by pipes, one equal card
 * per motor beneath. Water is blue; brand green still means "running".
 * Everything moves with CSS only. Each animation's delay is the clock's phase
 * (--ph-*, set inline at render), so a re-render on new data resumes where the
 * motion was instead of restarting. Reduced motion: no animation at all, the
 * state is still readable (blue pipe with its dashes, rotor stopped). */
.wscene{--water:#2f86d6;--water-2:#6dbaf0;--water-deep:#1d5fa8;--water-dash:#d9efff;
  --land:color-mix(in srgb,var(--brand) 6%,var(--panel-2));--pipe:var(--panel-3);--pipe-rim:var(--line-2);
  container-type:inline-size;margin-top:4px}
:root[data-theme="dark"] .wscene{--land:#232325;--water-2:#4aa0e6;--water-deep:#1b5da6}
@media (prefers-color-scheme:dark){:root:not([data-theme]) .wscene{--land:#232325;--water-2:#4aa0e6;--water-deep:#1b5da6}}
/* --tw: the width of one scene. The art is drawn in 1000 x 660 units and the
 * gap between scenes is 60, so the pipes' overlay (one SVG over the whole row
 * or stack, `wsOverlay`) lines up with the cards at any width. */
.ws-grid{--tw:min(100cqw,520px);--lw:calc(var(--tw)*.06);position:relative;
  display:grid;grid-template-columns:minmax(0,1fr);row-gap:0;max-width:520px;margin:0 auto}
.ws-stage{display:contents}
.ws-tile,.ws-link,.ws-beds,.ws-cards{order:var(--o,0)}
.ws-cards{display:flex;flex-direction:column;gap:12px;margin-top:var(--lw);min-width:0}
.ws-tile{position:relative;aspect-ratio:1000/660;border-radius:var(--r-xl);overflow:hidden;background:var(--panel);
  box-shadow:var(--shadow-card),inset 0 0 0 1px var(--edge)}
.ws-art{position:absolute;inset:0;display:block;width:100%;height:100%;overflow:hidden}
.ws-place{position:absolute;left:12px;bottom:12px;z-index:3;display:flex;flex-direction:column;align-items:flex-start;gap:1px;
  padding:5px 11px 6px;border-radius:14px;font-size:12.5px;font-weight:750;letter-spacing:.01em;color:var(--text);
  background:var(--glass);border:1px solid var(--glass-line);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}
.ws-place small{font-size:10.5px;font-weight:600;color:var(--faint);letter-spacing:.01em}
.ws-link{height:var(--lw);width:100%}
/* the pipes: one drawing over the row, so nothing clips them */
.ws-pipes{position:absolute;left:0;top:0;width:100%;height:auto;display:block;pointer-events:none;z-index:2;overflow:visible}
.ws-pipes-h{display:none}
.ws-pipes-v{display:block}
/* pipes: clear glass. Running, they are full of water: the baked caustic
 * texture sliding along under cylinder shading, round the bends. Nothing is
 * a dot or a dash. */
.ws-pg-rim,.ws-pg-glass,.ws-pw-e,.ws-pw-m,.ws-pw-h,.ws-pg-spec,.ws-pg-shd{fill:none;stroke-linejoin:round;stroke-linecap:butt}
.ws-pg-rim{stroke:#2a3741;stroke-opacity:.9}
.ws-pg-glass{stroke:#b4cfdf;stroke-opacity:.22}
.ws-pg-shd{stroke:#0a2a45;opacity:.13}
.ws-pg-spec{stroke:#fff;opacity:.6}
.ws-pw-e{stroke:#14558f}
.ws-pw-m{stroke:#2b86cf}
.ws-pw-h{stroke:#5cb8f2;opacity:.65}
.ws-pipe.is-still .ws-pg-rim{stroke:#10161b;stroke-opacity:.9}
.ws-pipe.is-still .ws-pw-e{stroke:#0e3a5e}
.ws-pipe.is-still .ws-pw-m{stroke:#1c4f7a}
.ws-pipe.is-still .ws-pw-h{stroke:#2f6e9c}
.ws-pipe.is-unread{filter:grayscale(1);opacity:.6}
.ws-tx-px{animation:ws-px var(--sp,7s) linear infinite}
.ws-tx-nx{animation:ws-nx var(--sp,7s) linear infinite}
.ws-tx-py{animation:ws-py var(--sp,7s) linear infinite}
.ws-tx-ny{animation:ws-ny var(--sp,7s) linear infinite}
@keyframes ws-px{to{transform:translateX(600px)}}
@keyframes ws-nx{to{transform:translateX(-600px)}}
@keyframes ws-py{to{transform:translateY(600px)}}
@keyframes ws-ny{to{transform:translateY(-600px)}}
.ws-art:not(.is-live) .ws-tx-px,.ws-art:not(.is-live) .ws-tx-nx,.ws-art:not(.is-live) .ws-tx-py,.ws-art:not(.is-live) .ws-tx-ny{animation:none}
/* what sits in the scenes */
.ws-flange{fill:#2b3640;stroke:#10161b;stroke-width:2}
.ws-emit{fill:#1d2830;stroke:#0b1014;stroke-width:1.5}
.ws-drop-c{fill:#6fbcf2;opacity:0}
.ws-art.is-live .ws-drop-c{animation:ws-drip 1.5s ease-in infinite;animation-delay:calc(var(--ph-drop,0s) - var(--di,0) * .5s)}
@keyframes ws-drip{0%{translate:0 -4px;opacity:0}15%{opacity:.95}85%{opacity:.85}100%{translate:0 13px;opacity:0}}
.ws-wet{transform-box:fill-box;transform-origin:center;opacity:.9}
.ws-art.is-live .ws-wet{animation:ws-wet 6s ease-in-out infinite;animation-delay:var(--ph-a,0s)}
@keyframes ws-wet{0%,100%{transform:scale(.8);opacity:.7}50%{transform:scale(1.06);opacity:1}}
.ws-cropb .ws-crop-bg{fill:var(--panel);stroke:var(--brand);stroke-width:3}
.ws-glow{transform-box:fill-box;transform-origin:center;animation:ws-glow2 2.6s ease-in-out infinite;animation-delay:var(--ph-glow,0s)}
@keyframes ws-glow2{0%,100%{opacity:.5}50%{opacity:1}}
.ws-foam{animation:ws-foam 1.2s ease-in-out infinite;animation-delay:var(--ph-splash,0s)}
@keyframes ws-foam{0%,100%{opacity:.78}50%{opacity:1}}
.ws-ring{fill:none;stroke:#eaf7ff;stroke-width:2;opacity:0;transform-box:fill-box;transform-origin:center;
  animation:ws-ring 2s ease-out infinite;animation-delay:var(--ph-splash,0s)}
.ws-ring-b{animation-delay:calc(var(--ph-splash,0s) - 1s)}
@keyframes ws-ring{0%{opacity:.8;transform:scale(.35)}100%{opacity:0;transform:scale(1.15)}}
/* unreadable: grey and hatched, nothing moving */
.ws-tile.is-unread .ws-art{filter:grayscale(1);opacity:.55}
.ws-tile.is-unread::after{content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:repeating-linear-gradient(135deg,transparent 0 8px,color-mix(in srgb,var(--faint) 26%,transparent) 8px 10px)}
.ws-cant{position:absolute;right:12px;bottom:12px;z-index:3;padding:4px 10px;border-radius:999px;font-size:12px;font-weight:750;
  color:var(--warn);background:var(--panel);border:1px solid var(--warn-line)}
/* motor cards: all alike */
.ws-card{position:relative;display:flex;align-items:center;gap:14px;padding:14px 16px;min-height:88px;border-radius:var(--r-xl);
  background:var(--panel);box-shadow:var(--shadow-card),inset 0 0 0 1px var(--edge);transition:box-shadow .2s var(--ease),transform .2s var(--ease)}
.ws-card:hover{box-shadow:var(--shadow-card-hover),inset 0 0 0 1px var(--edge)}
.ws-card:active{transform:scale(.99)}
.ws-card.is-on{box-shadow:var(--shadow-card),inset 0 0 0 1.5px color-mix(in srgb,var(--brand) 55%,transparent)}
.ws-card.is-unread{background:repeating-linear-gradient(135deg,var(--panel) 0 9px,color-mix(in srgb,var(--faint) 9%,var(--panel)) 9px 11px)}
.ws-body{display:flex;flex-direction:column;align-items:flex-start;gap:3px;min-width:0;flex:1}
.ws-top{display:flex;flex-wrap:wrap;align-items:center;gap:2px 10px;min-width:0}
.ws-name{font-size:16px;font-weight:750;letter-spacing:-.01em;color:var(--text);text-decoration:none}
.ws-name::after{content:"";position:absolute;inset:0;border-radius:inherit}
.ws-name:focus-visible{outline:none}
.ws-card:has(.ws-name:focus-visible){outline:2px solid var(--accent);outline-offset:2px}
.ws-line{font-size:13px;color:var(--muted);overflow-wrap:anywhere}
.ws-age{font-style:normal;font-size:12px;color:var(--faint)}
.ws-signin{position:relative;z-index:2;margin-top:6px}
.ws-badge{position:relative;flex:none;width:58px;height:58px}
.ws-badge svg{display:block;width:100%;height:100%}
.ws-house{fill:var(--panel-2);stroke:var(--line-2);stroke-width:4}
.ws-rotor path{fill:var(--faint);opacity:.75}
.ws-hub{fill:var(--panel);stroke:var(--line-2);stroke-width:2}
.ws-ring-t{fill:none;stroke:var(--line);stroke-width:5}
.ws-ring-f{fill:none;stroke:var(--brand);stroke-width:5;stroke-linecap:round}
.ws-badge.is-on .ws-house{stroke:var(--brand)}
.ws-badge.is-on .ws-rotor path{fill:var(--brand);opacity:1}
.ws-badge.is-on .ws-rotor{transform-origin:50px 50px;animation:ws-spin 1.6s linear infinite;animation-delay:var(--ph-spin,0s)}
.ws-badge.is-on::after{content:"";position:absolute;inset:-5px;border-radius:50%;border:2px solid var(--brand);opacity:0;
  animation:ws-glow 2.4s ease-out infinite;animation-delay:var(--ph-glow,0s);pointer-events:none}
.ws-badge.is-unread svg{opacity:.45;filter:grayscale(1)}
@keyframes ws-spin{to{transform:rotate(360deg)}}
@keyframes ws-glow{0%{opacity:.5;transform:scale(.92)}100%{opacity:0;transform:scale(1.18)}}
/* the beds being watered */
.ws-beds{padding:14px 16px;border-radius:var(--r-xl);background:var(--panel);box-shadow:var(--shadow-card),inset 0 0 0 1px var(--edge);
  display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:13.5px;color:var(--muted)}
.ws-beds strong{font-size:14px;font-weight:750;color:var(--text)}
.ws-beds.is-unread{background:repeating-linear-gradient(135deg,var(--panel) 0 9px,color-mix(in srgb,var(--faint) 9%,var(--panel)) 9px 11px)}
.ws-beds.is-on{display:block;box-shadow:var(--shadow-card),inset 0 0 0 1.5px color-mix(in srgb,var(--brand) 45%,transparent)}
.ws-beds-h{display:flex;justify-content:space-between;align-items:baseline;gap:10px;margin-bottom:12px}
.ws-beds-h span{font-size:13px;font-weight:700;color:var(--accent);font-variant-numeric:tabular-nums}
.ws-chips{display:flex;flex-wrap:wrap;gap:10px 8px}
.ws-chip{display:flex;flex-direction:column;align-items:center;gap:5px;width:64px}
.ws-chip em{font-style:normal;font-size:11.5px;font-weight:650;color:var(--ink);text-align:center;line-height:1.2}
.ws-crop{position:relative;width:52px;height:52px;border-radius:50%;display:grid;place-items:center;background:var(--panel-2);
  box-shadow:0 0 0 2.5px var(--brand),0 0 14px 1px var(--accent-glow)}
.ws-crop::after{content:"";position:absolute;inset:-4px;border-radius:50%;border:2px solid var(--brand);opacity:0;
  animation:ws-glow 2.4s ease-out infinite;animation-delay:var(--ph-glow,0s)}
.ws-crop-img{width:34px;height:34px;object-fit:contain}
.ws-crop .ico{width:24px;height:24px;color:var(--accent)}
/* wide: three places across, pipes over the gaps */
@container (min-width:880px){
  .ws-grid{--tw:calc(100cqw/3.12);--lw:calc(var(--tw)*.06);max-width:none;
    grid-template-columns:minmax(0,1fr) var(--lw) minmax(0,1fr) var(--lw) minmax(0,1fr)}
  .ws-pipes-h{display:block}
  .ws-pipes-v{display:none}
  .ws-link{height:auto;width:var(--lw);order:0}
  .ws-stage{display:flex;flex-direction:column;gap:var(--lw);min-width:0}
  .ws-cards,.ws-beds{margin-top:0}
}
@container (min-width:880px) and (max-width:1000px){
  .ws-card{flex-direction:column;text-align:center;padding:14px 10px}
  .ws-body,.ws-top{align-items:center;justify-content:center}
  .ws-chips{justify-content:center}
}
@media (prefers-reduced-motion:reduce){
  .wscene *,.wscene *::before,.wscene *::after{animation:none!important;transition:none!important}
  .ws-badge.is-on::after,.ws-crop::after{display:none}
  .ws-drop-c,.ws-ring{display:none}
}
/* The valves panel is the text of what the plants above are being watered with. */
.ws-beds{position:relative;margin-top:var(--lw)}
.ws-chips{gap:8px}
.ws-chip{flex-direction:row;gap:6px;width:auto;padding:4px 11px 4px 5px;border-radius:999px;background:var(--panel-2)}
.ws-chip em{text-align:left}
.ws-chip .ws-crop{width:24px;height:24px;box-shadow:none;background:transparent}
.ws-chip .ws-crop::after{display:none}
.ws-chip .ws-crop-img{width:22px;height:22px}
@container (min-width:880px){.ws-beds{margin-top:0}}

/* ---------- Controller page, chunk 5 (2026-11-01) ---------- */
/* Reports: rows in a compact list; wide, the opened one shows beside it. */
.rep-pane-head{display:none}
.rep-list{display:block}
@container (min-width:900px){
  .rep-list{display:grid;grid-template-columns:minmax(300px,340px) minmax(0,1fr);
    grid-template-rows:repeat(8,min-content) 1fr;column-gap:16px;row-gap:0;align-items:start}
  .rep-card,.rep-card:last-child{display:contents}
  .rep-row{grid-column:1;background:var(--panel);border:1px solid var(--edge);border-bottom-color:var(--line-soft);
    padding-bottom:10px;min-width:0}
  .rep-card:first-child .rep-row{border-top-left-radius:var(--r-xl);border-top-right-radius:var(--r-xl)}
  .rep-card:last-child .rep-row{border-bottom-color:var(--edge);border-bottom-left-radius:var(--r-xl);border-bottom-right-radius:var(--r-xl)}
  .rep-card.is-sel .rep-row{background:var(--panel-2);box-shadow:inset 3px 0 0 var(--brand)}
  .rep-head{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:2px 10px;min-height:48px;padding:12px 16px 2px}
  .rep-head .rep-when{grid-column:1 / -1;margin:0;width:auto}
  .rep-summary{padding:0 16px}
  .rep-chev{display:none}
  .rep-body,.rep-body[hidden]{display:none;grid-column:2;grid-row:1 / -1;padding:18px 22px 22px;
    background:var(--panel);border:1px solid var(--edge);border-radius:var(--r-xl);box-shadow:var(--shadow-card);min-width:0}
  .rep-card.is-sel .rep-body,.rep-card.is-sel .rep-body[hidden]{display:block!important}
  .rep-pane-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding-bottom:12px;margin-bottom:6px;border-bottom:1px solid var(--line-soft)}
  .rep-pane-head .rep-title{font-size:17px}
  .rep-card .list{margin-left:-22px;margin-right:-22px}
  .rep-card .list .row{padding-left:22px;padding-right:22px}
  .rep-body > .list:last-child{margin-bottom:-22px}
}

/* Run valves: a drawer from the right, a sheet from the bottom on a phone. */
.run-scrim{position:fixed;inset:0;z-index:60;background:rgba(15,20,25,.38);animation:run-fade .2s var(--ease)}
.run-drawer{position:fixed;top:0;right:0;bottom:0;z-index:61;width:min(440px,100vw);display:flex;flex-direction:column;
  background:var(--panel);box-shadow:-18px 0 48px rgba(15,20,25,.22);animation:run-in .26s var(--ease)}
.run-drawer > .panel{flex:1;display:flex;flex-direction:column;min-height:0;overflow:auto;border:0;border-radius:0;box-shadow:none;padding-top:8px}
.run-drawer .panel-head{padding-top:14px}
.run-drawer .valve-grid{grid-template-columns:repeat(auto-fill,minmax(120px,1fr));align-content:start}
.run-drawer .run-bar{order:2;position:sticky;bottom:0;margin-top:auto;background:var(--panel);padding-bottom:calc(16px + var(--sab))}
.run-drawer .run-bar .btn-primary{flex:1 1 140px}
@keyframes run-in{from{transform:translateX(24px);opacity:0}to{transform:none;opacity:1}}
@keyframes run-fade{from{opacity:0}to{opacity:1}}
@media (max-width:700px){
  .run-drawer{top:auto;left:0;width:100%;max-height:86vh;border-radius:22px 22px 0 0;box-shadow:0 -12px 40px rgba(15,20,25,.25);animation:run-up .26s var(--ease)}
  @keyframes run-up{from{transform:translateY(24px);opacity:0}to{transform:none;opacity:1}}
}
@media (prefers-reduced-motion:reduce){.run-scrim,.run-drawer{animation:none}}
@media (max-width:480px){ .now-top .btn{margin-left:auto} }

/* ============ Rooms, All devices, a room, system pages, Admin (web redesign, chunks 6-9) ============ */

/* Rooms: a card per room with one dot per device. */
.grid:has(> .area-card){grid-template-columns:repeat(auto-fill,minmax(230px,1fr))}
.area-card{gap:6px;padding:16px 18px 15px}
.area-dots{display:flex;flex-wrap:wrap;gap:5px;margin-top:6px;min-height:9px}
.area-dots i{width:9px;height:9px;border-radius:50%;background:var(--line-2)}
.area-dots i.on{background:var(--accent)}
.area-dots i.idle{background:var(--faint);opacity:.55}
.area-dots i.off{background:transparent;box-shadow:inset 0 0 0 1.5px var(--faint);opacity:.7}
.area-dots i.bad{background:var(--bad)}

/* A room: its list of rooms beside it on a wide screen, its panels in columns. */
.rooms-rail{display:none}
@media (min-width:1100px){
  .rooms-split{display:grid;grid-template-columns:200px minmax(0,1fr);gap:28px;align-items:start}
  .rooms-rail{display:flex;flex-direction:column;gap:2px;position:sticky;top:calc(var(--bar-h) + 16px);
    max-height:calc(100vh - var(--bar-h) - 40px);overflow:auto}
  .rooms-rail a{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:40px;padding:0 12px;
    border-radius:var(--r);font-size:14px;font-weight:600;color:var(--muted)}
  .rooms-rail a:hover{background:var(--panel-2);color:var(--text)}
  .rooms-rail a[aria-current="page"]{background:var(--panel);color:var(--text);box-shadow:var(--shadow-card)}
  .rooms-rail em{font-style:normal;font-size:12px;font-weight:650;color:var(--faint);font-variant-numeric:tabular-nums}
  .rooms-rail em.bad{color:var(--bad)}
  .rooms-main{column-count:2;column-gap:16px}
  .rooms-main > .panel{break-inside:avoid;margin:0 0 16px}
  .rooms-main > .panel + .panel{margin-top:0}
  .rooms-main > :not(.panel){column-span:all}
  .rooms-main .dev-list.cols,.rooms-main .list.cols{column-width:auto;column-count:1}
}
@media (min-width:1500px){ .rooms-main{column-count:3} }

/* All devices: the status sits next to the name, rooms are headed, filters stay in view. */
.toolbar-row:has(.seg[aria-label="Filter by status"]){position:sticky;top:var(--bar-h);z-index:5;margin:0 calc(var(--gutter) * -1) 12px;
  padding:10px var(--gutter);background:color-mix(in srgb,var(--bg) 88%,transparent);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px)}
.dgroups{max-width:none}
.dgroup-set{break-inside:avoid}
@media (min-width:1000px){ .dgroups{column-count:2;column-gap:0;column-rule:1px solid var(--line-soft)} .dgroup,.dgroup-solo{break-inside:avoid} .dgroup-set:last-child .dgroup:last-child,.dgroup-set{border-bottom:1px solid var(--line-soft)} }
.dgroup-room{padding:16px 22px 6px;font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--faint);background:var(--panel)}
.dgroups > .dgroup-room:first-child{padding-top:18px}
.dgroups .row{min-height:52px}

/* Climate: running ACs as a grid of cards; an AC that is off is one quiet line. */
.ac-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:16px;align-items:start}
.ac-grid > .panel{margin:0}
.ac-grid .area-sec + .area-sec{margin-top:0}
.ac-off-list{margin-top:16px}
.ac-off-list.is-faded{display:block}
.ac-off-row,.ac-off{padding:0}
.ac-off-row{display:flex;align-items:center;gap:12px;min-height:48px;padding:0 22px}
.ac-off-row .dev-name{flex:1}
.ac-off-row + .ac-off-row,.ac-off + .ac-off{border-top:1px solid var(--line-soft)}
.ac-off .ac{padding:4px 22px;opacity:.75}
.ac-off .ac:hover{opacity:1}
.ac-mini .dev-top{min-height:48px}
@media (min-width:900px){
  .ac-off-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}
  .ac-off-list.is-faded{display:block;column-count:2;column-gap:0}
  .ac-off-list.is-faded .ac-off-row{break-inside:avoid}
  .ac-off-list:not(.is-faded) .ac-off + .ac-off{border-top:0}
  .ac-off-list:not(.is-faded) .ac-off:nth-child(odd){border-right:1px solid var(--line-soft)}
  .ac-off-list:not(.is-faded) .ac-off{border-bottom:1px solid var(--line-soft)}
}
.ac-grid .ac-temp{gap:22px}
.ac-grid .ac-set b{font-size:38px}

/* Security: cameras as a grid. */
@media (min-width:900px){
  .list.cams{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr))}
  .list.cams .row::before{display:none}
  .list.cams .row{border-bottom:1px solid var(--line-soft);border-right:1px solid var(--line-soft)}
}

/* Admin: the person form on the left, the people on the right. */
@media (min-width:1000px){
  .admin-cols{display:grid;grid-template-columns:minmax(300px,380px) minmax(0,1fr);gap:0 32px;align-items:start}
  .admin-side .rep-builder{flex-direction:column;align-items:stretch}
  .admin-side .rep-field input[type=email],.admin-side .rep-field select{width:100%;min-width:0;box-sizing:border-box}
  .admin-side .rep-builder .btn{width:100%}
}

/* Power: the hero, then the lines side by side on a wide screen. */
@media (min-width:1100px){
  .power-lines{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px;align-items:start}
  .power-lines > .panel{margin:0}
  .power-lines > .panel:last-child:nth-child(odd){grid-column:1 / -1}
  .power-lines .mb-facts{grid-template-columns:repeat(auto-fill,minmax(120px,1fr))}
}

/* Mobile density: 44px targets without growing the look (hit areas extend past the box). */
@media (max-width:620px){
  .btn,.btn-sm{min-height:44px}
  .page-head .btn-sm,.head-actions .btn-sm{min-height:44px;padding-top:0;padding-bottom:0}
  .seg-nav a{position:relative}
  .seg-nav a::before{content:"";position:absolute;left:0;top:50%;translate:0 -50%;width:100%;height:44px}
  .back{min-height:44px;margin:-10px 0 -10px}
  .ac-chips button{position:relative}
  .ac-chips button::before{content:"";position:absolute;left:0;top:50%;translate:0 -50%;width:100%;height:44px}
  .rooms-split{display:block}
  .area-card{padding:14px 16px 13px}
  .grid:has(> .area-card){grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
  .page-head{margin-bottom:16px}
  .dgroup-room{padding:14px 16px 4px}
  .dgroup-head{padding:10px 16px}
  .dgroups .row{padding-left:16px;padding-right:16px}
  .ac-off-row{padding:0 16px}
  .ac-off .ac{padding:4px 16px}
  .toolbar-row:has(.seg[aria-label="Filter by status"]){top:var(--bar-h)}
}
@media (max-width:360px){ .grid:has(> .area-card){grid-template-columns:1fr} }

@media (max-width:620px){ .row .btn{height:44px;min-height:44px} }
@media (max-width:620px){ .admin-main .row{flex-wrap:wrap;row-gap:8px} .admin-main .row-main{flex:1 1 60%} }

/* ---------- programs, rain, controller facts ---------- */
.prog-row{display:flex;align-items:center;gap:12px;padding:10px 22px;border-bottom:1px solid var(--line-soft)}
.prog-row:last-child{border-bottom:0}
.prog-no{flex:none;width:30px;height:30px;border-radius:50%;display:grid;place-items:center;background:var(--panel-2);color:var(--muted);font-size:13px;font-weight:750;font-variant-numeric:tabular-nums}
.prog-row.is-running .prog-no{background:var(--brand);color:#fff}
.prog-row .crop-name{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.prog-row .tag{font-size:11.5px;white-space:nowrap}
.prog-row .btn{flex:none}
.prog-row.is-faded{opacity:.5;filter:saturate(.4)}
@media (min-width:901px){ .prog-list{display:grid;grid-template-columns:1fr 1fr}
  .prog-list .prog-row{border-right:1px solid var(--line-soft)} .prog-list .prog-row:nth-child(2n){border-right:0} }
@media (max-width:620px){ .prog-row{padding:10px 16px} }
.rain-line{margin:0;padding:6px 22px 16px;font-size:15px;color:var(--muted)}
.rain-line b{color:var(--ink);font-weight:750;font-variant-numeric:tabular-nums}
.fig-t{font-size:17px;letter-spacing:-.02em;white-space:normal}
.fig.is-warn .fig-v,.fig.is-warn .fig-l{color:var(--warn)}
.prog-row .btn:disabled{opacity:.4;cursor:not-allowed}

/* ---------- developer console (owner only, #/dev) ----------
   A tool, not a dashboard: the same panels and fields as the rest, with
   monospace for anything the farm will read or say. */
.dev{display:flex;flex-direction:column;gap:16px;--mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
.dev-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);gap:16px;align-items:start}
.dev-col{display:flex;flex-direction:column;gap:16px;min-width:0}
.dev-sec{min-width:0}
.dev-pad{padding:4px 20px 20px;min-width:0}
.dev-stack{display:flex;flex-direction:column;gap:12px}
.dev-gate{display:flex;align-items:flex-start;gap:10px;padding:12px 16px;border-radius:var(--r);background:var(--warn-soft);
  border:1px solid var(--warn-line);color:var(--warn);font-size:13.5px;font-weight:600}
.dev-gate .ico{flex:none;margin-top:2px}
.dev-lab{font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--faint);margin-bottom:-4px}
.dev-line{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.dev-line .dev-in{flex:1 1 200px}
.dev-in{box-sizing:border-box;width:100%;min-width:0;height:40px;padding:0 12px;border:1px solid transparent;border-radius:var(--r);
  background:var(--field);color:var(--text);font:500 13px/1 var(--mono);letter-spacing:0}
.dev-in::placeholder{color:var(--faint)}
.dev-in:hover{border-color:var(--line-2)}
.dev-in:focus{background:var(--panel);border-color:var(--line-2);box-shadow:0 0 0 4px var(--off-soft);outline:none}
.dev-ta{height:auto;padding:10px 12px;line-height:1.5;resize:vertical;white-space:pre;overflow:auto}
.dev-rows{display:flex;flex-direction:column;gap:8px}
.dev-row{display:grid;grid-template-columns:minmax(0,.8fr) minmax(0,1.4fr) 40px;gap:8px;align-items:center}
.dev-x{width:40px;height:40px;border-radius:50%;display:grid;place-items:center;color:var(--muted)}
.dev-x:hover{background:var(--seg-track);color:var(--text)}
.dev-add{align-self:flex-start;font-size:13px;font-weight:700;color:var(--accent);padding:6px 2px;min-height:32px}
.dev-check{display:flex;align-items:center;gap:10px;font-size:14px;font-weight:600;cursor:pointer;min-height:36px}
.dev-check input{width:18px;height:18px;accent-color:var(--brand);margin:0}
.dev-chips{display:flex;flex-wrap:wrap;gap:8px}
.dev-chip{padding:7px 12px;min-height:34px;border-radius:999px;background:var(--seg-track);color:var(--text);font-size:12.5px;font-weight:650}
.dev-chip.mono{font-family:var(--mono);font-size:12px}
.dev-chip:hover{background:var(--panel-3)}
.dev-chip:active{transform:scale(.96)}
.dev-actions{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
.dev-msg{font-size:13px;color:var(--muted)}
.dev-msg.bad,.dev-err{color:var(--bad)}
.dev-err{margin:0;font-size:13.5px;font-weight:600;word-break:break-word}
.dev-paste{display:flex;flex-direction:column;gap:10px}
.dev-paste .more-note{margin:0;padding:0;border:0}
.dev-empty{margin:0;color:var(--muted);font-size:14px;padding:6px 0}
.dev-wait{display:flex;align-items:center;gap:12px;color:var(--muted);font-weight:600;padding:8px 0}
.dev-spin{width:18px;height:18px;border-radius:50%;border:2.5px solid var(--line-2);border-top-color:var(--brand);animation:spin .8s linear infinite}
.dev-meta{display:flex;flex-wrap:wrap;gap:10px;align-items:center}
.dev-stat{font:600 13px/1 var(--mono);color:var(--muted)}
.dev-pill{display:inline-flex;align-items:center;padding:5px 11px;border-radius:999px;font:700 12.5px/1 var(--mono);border:1px solid var(--line-2);color:var(--muted)}
.dev-pill.ok{color:var(--accent);border-color:var(--accent-line)}
.dev-pill.bad{color:var(--bad);border-color:var(--bad-line);background:var(--bad-soft)}
.dev-pill.warn{color:var(--warn);border-color:var(--warn-line);background:var(--warn-soft)}
.dev-note{padding:0;border:0;margin:0}
.dev-tools{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.dev-tools .dev-copy{margin-left:auto}
.dev-tree,.dev-pre{font:500 12.5px/1.6 var(--mono);background:var(--field);border-radius:var(--r);padding:12px 14px;
  max-height:min(70vh,640px);overflow:auto;color:var(--text);min-width:0}
.dev-pre{margin:0;white-space:pre-wrap;word-break:break-all}
.dev-tree .jt>summary{cursor:pointer;list-style:none;padding:1px 0;word-break:break-all}
.dev-tree .jt>summary::-webkit-details-marker{display:none}
.dev-tree .jt>summary::before{content:"▸";display:inline-block;width:14px;color:var(--faint);font-size:11px}
.dev-tree .jt[open]>summary::before{content:"▾"}
.dev-tree .jc{margin-left:7px;padding-left:12px;border-left:1px solid var(--line)}
.dev-tree .jl{padding-left:14px;word-break:break-all}
.dev-tree .jc .jl{padding-left:0}
.dev-tree .jclose{padding-left:14px}
.dev-tree .jk{color:var(--ink,var(--text));font-weight:700}
.dev-tree .jp,.dev-tree .jn{color:var(--faint)}
.dev-tree .str{color:var(--accent)}
.dev-tree .num{color:var(--warn)}
.dev-tree .boo,.dev-tree .nul{color:var(--bad)}
.dev-hlist{display:flex;flex-direction:column}
.dev-h{display:grid;grid-template-columns:auto auto minmax(0,1fr) auto;gap:10px;align-items:center;text-align:left;
  padding:10px 4px;min-height:48px;border-bottom:1px solid var(--line-soft)}
.dev-h:hover{background:var(--off-soft)}
.dev-hm{font:700 12px/1 var(--mono);color:var(--faint)}
.dev-hl{font:600 13px/1.3 var(--mono);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dev-ht{font-size:12.5px;color:var(--muted);white-space:nowrap}
@media (max-width:900px){.dev-grid{grid-template-columns:minmax(0,1fr)}}
@media (max-width:480px){.dev-pad{padding:4px 14px 16px}.dev-row{grid-template-columns:minmax(0,.9fr) minmax(0,1.3fr) 36px;gap:6px}.dev-x{width:36px}.dev-tools .dev-copy{margin-left:0}}
body[data-route="dev"] .view .page-head{padding-right:0}
