:root{
  --bg:#0e1116; --bg2:#161b22; --card:#1b212b; --line:#2a3340;
  --txt:#e6edf3; --muted:#8b98a8; --accent:#ffb300;
  --pv:#ffc83d; --grid:#5aa9ff; --home:#9b8cff; --batt:#3ddc84; --car:#ff7ab2;
  --push:#3ddc84; --pull:#ff6b6b;
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--txt);overflow-x:hidden;
  font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;-webkit-font-smoothing:antialiased}
h3{margin:0;font-size:15px;font-weight:600}
.muted{color:var(--muted);font-size:13px}

.topbar{display:flex;align-items:center;justify-content:space-between;
  padding:14px 18px;background:var(--bg2);border-bottom:1px solid var(--line);
  position:sticky;top:0;z-index:10}
.brand{display:flex;align-items:center;gap:10px;font-weight:700;font-size:18px}
.logo{color:var(--accent);font-size:22px}
.status-pill{display:flex;align-items:center;gap:8px;background:var(--card);
  padding:6px 12px;border-radius:20px;font-size:13px;color:var(--muted)}
.dot{width:9px;height:9px;border-radius:50%;background:#888}
.dot.ok{background:var(--batt);box-shadow:0 0 8px var(--batt)}
.dot.bad{background:var(--pull)}

.tabs{display:flex;gap:4px;overflow-x:auto;padding:8px 12px;background:var(--bg2);
  border-bottom:1px solid var(--line);position:sticky;top:57px;z-index:9}
.tab{background:none;border:none;color:var(--muted);padding:8px 14px;border-radius:8px;
  font-size:14px;cursor:pointer;white-space:nowrap}
.tab.active{background:var(--card);color:var(--txt)}

main{max-width:880px;margin:0 auto;padding:16px}
.view{display:none}
.view.active{display:block;animation:fade .2s ease}
@keyframes fade{from{opacity:0;transform:translateY(4px)}to{opacity:1}}

.card{background:var(--card);border:1px solid var(--line);border-radius:14px;
  padding:16px;margin-bottom:16px}
.card-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
/* Fixed-height wrapper stops the Chart.js infinite-grow loop that happens with
   maintainAspectRatio:false when the canvas parent has no constrained height. */
.chart-box{position:relative;width:100%;height:260px}
.chart-box canvas{position:absolute;inset:0}
@media(max-width:620px){.chart-box{height:220px}}

.kpi-row{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:16px}
.kpi-row.col{grid-template-columns:repeat(2,1fr)}
.kpi{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:12px 14px}
.kpi-label{color:var(--muted);font-size:12px;margin-bottom:6px}
.kpi-val{font-size:20px;font-weight:700}
.kpi-val.pull{color:var(--pull)} .kpi-val.push{color:var(--push)}
.kpi-val.small{font-size:14px;font-weight:600;line-height:1.5}
@media(max-width:620px){.kpi-row{grid-template-columns:repeat(2,1fr)}}

/* energy flow */
.flow-wrap{position:relative;background:var(--card);border:1px solid var(--line);
  border-radius:16px;padding:8px;margin-bottom:16px}
.flow-lines{position:absolute;inset:0;width:100%;height:100%}
.flow-grid{position:relative;display:grid;grid-template-columns:1fr 1fr 1fr;
  grid-template-rows:1fr 1fr 1fr;gap:8px;min-height:380px;
  grid-template-areas:"pv pv pv" "grid home batt" "car car car";align-items:center;justify-items:center}
.node{display:flex;flex-direction:column;align-items:center;gap:2px;
  background:var(--bg2);border:1px solid var(--line);border-radius:14px;
  padding:12px 18px;min-width:120px;z-index:2}
.node-icon{font-size:26px}
.node-label{color:var(--muted);font-size:12px}
.node-val{font-size:17px;font-weight:700}
.node-sub{font-size:13px;color:var(--batt)}
.node-pv{grid-area:pv} .node-grid{grid-area:grid} .node-home{grid-area:home;
  border-color:var(--home);box-shadow:0 0 0 1px var(--home) inset}
.node-batt{grid-area:batt} .node-car{grid-area:car}
.flow-path{fill:none;stroke:var(--line);stroke-width:3}
.flow-path.active{stroke-dasharray:6 8;animation:dash 1s linear infinite}
@keyframes dash{to{stroke-dashoffset:-28}}
/* mobile: shrink nodes so the 3-across row fits, centre the wallbox */
@media(max-width:600px){
  .flow-wrap{padding:4px}
  .flow-grid{min-height:320px;gap:4px}
  .node{min-width:0;padding:9px 6px;border-radius:11px}
  .node-icon{font-size:20px}
  .node-label{font-size:10px}
  .node-val{font-size:13px}
  .node-sub{font-size:11px}
}
@media(max-width:360px){
  .node-val{font-size:12px}
  .node{padding:8px 4px}
}

/* segmented controls */
.seg{display:inline-flex;background:var(--card);border:1px solid var(--line);
  border-radius:10px;padding:3px;margin-bottom:14px}
.seg button{background:none;border:none;color:var(--muted);padding:6px 14px;
  border-radius:8px;cursor:pointer;font-size:13px}
.seg button.active{background:var(--bg2);color:var(--txt)}
.seg.small button{padding:4px 10px}

/* battery */
.batt-hero{display:flex;gap:18px;align-items:center;flex-wrap:wrap;margin-bottom:16px}
.gauge{position:relative;width:140px;height:140px}
.gauge svg{transform:rotate(-90deg)}
.g-bg{fill:none;stroke:var(--line);stroke-width:10}
.g-fg{fill:none;stroke:var(--batt);stroke-width:10;stroke-linecap:round;
  stroke-dasharray:327;stroke-dashoffset:327;transition:stroke-dashoffset .6s}
.gauge-text{position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center}
.gauge-text div{font-size:30px;font-weight:800}
.batt-hero .kpi-row{flex:1;margin:0;min-width:260px}

.phase-row{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.phase{background:var(--bg2);border:1px solid var(--line);border-radius:10px;padding:10px;text-align:center}
.phase b{display:block;font-size:18px;margin-top:4px}

.dev-table{width:100%;border-collapse:collapse;font-size:14px}
.dev-table td{padding:8px 6px;border-bottom:1px solid var(--line)}
.badge{padding:2px 8px;border-radius:10px;font-size:12px}
.badge.on{background:rgba(61,220,132,.15);color:var(--batt)}
.badge.off{background:rgba(255,107,107,.15);color:var(--pull)}

.probe{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px}
.probe input,.probe select{background:var(--bg2);border:1px solid var(--line);
  color:var(--txt);border-radius:8px;padding:8px 10px;font-size:14px}
.probe button,#probe-go{background:var(--accent);color:#222;border:none;
  border-radius:8px;padding:8px 16px;font-weight:600;cursor:pointer}
.probe-out{background:var(--bg);border:1px solid var(--line);border-radius:10px;
  padding:12px;overflow:auto;font-size:12.5px;color:var(--muted);max-height:340px}
.empty-hint{color:var(--muted);font-size:13px;padding:10px 4px}

/* wallbox controls */
.wb-controls{display:flex;gap:10px;flex-wrap:wrap}
.ctl{background:var(--bg2);border:1px solid var(--line);color:var(--txt);
  border-radius:10px;padding:12px 16px;font-size:14px;cursor:pointer;transition:.15s}
.ctl:hover{border-color:var(--car);background:#222937}
.ctl.active{background:rgba(255,200,61,.15);border-color:var(--pv);color:var(--pv)}
.ctl:disabled{opacity:.4;cursor:not-allowed}
.ctl:disabled:hover{border-color:var(--line);background:var(--bg2)}
.ctl.small{padding:8px 12px;font-size:13px}
a.ctl{display:inline-block;text-decoration:none}

/* login page (/login) */
.login-wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px}
.login-card{background:var(--card);border:1px solid var(--line);border-radius:16px;
  padding:28px;width:100%;max-width:340px;display:flex;flex-direction:column;gap:12px;text-align:center}
.login-logo{font-size:42px;color:var(--accent)}
.login-card h2{margin:0}
.login-card input{background:var(--bg2);border:1px solid var(--line);color:var(--txt);
  border-radius:8px;padding:12px;font-size:15px}
.login-card button{background:var(--accent);color:#222;border:none;border-radius:8px;
  padding:12px;font-weight:600;font-size:15px;cursor:pointer}
.login-err{color:var(--pull);min-height:18px;font-size:14px}
.login-card a{font-size:13px;text-decoration:none;color:var(--muted)}
.ctl-msg{margin-top:10px;min-height:18px}
.wb-switch{font-size:13px;color:var(--muted);margin-bottom:10px}
.wb-switch.warn{color:var(--pull)}
.wb-auth{display:flex;gap:8px;align-items:center;margin-bottom:12px;flex-wrap:wrap}
.wb-auth input{background:var(--bg2);border:1px solid var(--line);color:var(--txt);
  border-radius:8px;padding:8px 10px;font-size:14px}
.auth-ok{color:var(--batt);font-size:14px}
