/* Power — one page about one house's panel.
   Light and dark both, following the machine. Nothing here is the wall's
   business: the hall has its own app and its own look. */

:root {
  --bg:        #f6f7f8;
  --card:      #ffffff;
  --ink:       #14181c;
  --quiet:     #6b7680;
  --line:      #e3e7ea;
  --accent:    #5a63d6;
  --accent-soft:#dfe1f7;
  --blue:      #2f7fd1;
  --ok:        #3a9b62;
  --warn:      #c98a12;
  --alarm:     #c8442e;
  --radius:    14px;
  --shadow:    0 1px 2px rgba(20, 24, 28, .06), 0 4px 16px rgba(20, 24, 28, .04);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:        #14181c;
    --card:      #1c2126;
    --ink:       #e8ecef;
    --quiet:     #949ea7;
    --line:      #2a3138;
    --accent:    #8f97ee;
    --accent-soft:#2a2d4a;
    --blue:      #6fb0ea;
    --ok:        #5cbb84;
    --warn:      #e0aa3c;
    --alarm:     #e8705a;
    --shadow:    none;
  }
}

* { box-sizing: border-box; }

/* `display` set by an id selector outbids the browser's own rule for [hidden]. */
[hidden] { display: none !important; }

body {
  margin: 0;
  /* Room for the fixed foot, so the last card clears it rather than
     sitting underneath. */
  padding: 0 16px calc(74px + env(safe-area-inset-bottom, 0px));
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}

main { max-width: 760px; margin: 0 auto; }

header { padding: 28px 4px 8px; }
h1 { margin: 0; font-size: 28px; letter-spacing: -.02em; }
h2 { margin: 0 0 14px; font-size: 15px; font-weight: 600; color: var(--quiet);
     text-transform: uppercase; letter-spacing: .06em; }
h3 { margin: 22px 0 8px; font-size: 14px; font-weight: 600; color: var(--quiet); }

.when { margin: 4px 0 0; color: var(--quiet); font-size: 14px; }
.when.stale { color: var(--warn); }

.card {
  background: var(--card);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 20px;
  margin: 16px 0;
}
.card-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.card-head h2 { margin-bottom: 10px; }

/* ------------------------------- alerts ------------------------------- */

#alerts { margin: 16px 0 0; display: grid; gap: 8px; }
.alert {
  border-radius: 10px; padding: 12px 14px; font-size: 15px;
  border-left: 4px solid var(--quiet); background: var(--card); box-shadow: var(--shadow);
}
.alert.alarm { border-left-color: var(--alarm); }
.alert.warn  { border-left-color: var(--warn); }
.alert.info  { border-left-color: var(--blue); color: var(--quiet); }

/* Cannot reach the app. Said plainly and kept out of the alert list, which
   is the panel's business: this is the page's own problem, not the house's. */
.offline {
  margin: 16px 0 0; padding: 12px 14px; border-radius: 10px;
  background: var(--card); box-shadow: var(--shadow);
  border-left: 4px solid var(--warn); color: var(--quiet); font-size: 15px;
}

/* ------------------------------ figures ------------------------------- */

.figures { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 18px; }
.figure .label { color: var(--quiet); font-size: 13px; text-transform: uppercase; letter-spacing: .05em; }
.figure .value { font-size: 26px; font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.figure .unit  { font-size: 15px; color: var(--quiet); margin-left: 3px; }
.figure .under { color: var(--quiet); font-size: 13px; }
.figure.warn  .value { color: var(--warn); }
.figure.alarm .value { color: var(--alarm); }

/* The month's line under the day bars: the number first, the workings after. */
.total { margin: 14px 0 0; padding-top: 12px; border-top: 1px solid var(--line);
         color: var(--quiet); font-size: 15px; }
.total strong { color: var(--ink); font-weight: 600; }

/* ------------------------------ circuits ------------------------------ */

.breaker {
  display: grid; grid-template-columns: 34px 1fr auto; gap: 2px 10px;
  align-items: baseline; padding: 9px 0; border-top: 1px solid var(--line);
}
.breaker:first-child { border-top: 0; }
.breaker .pos  { color: var(--quiet); font-size: 12px; font-variant-numeric: tabular-nums; text-align: right; }
.breaker .name { font-weight: 500; display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.breaker .name .rating { color: var(--quiet); font-size: 12px; font-weight: 400; }
.breaker .num  { color: var(--quiet); font-variant-numeric: tabular-nums; font-size: 14px; white-space: nowrap; }
.breaker .num strong { color: var(--ink); font-weight: 600; }
.breaker .bar  {
  grid-column: 2 / -1; height: 6px; border-radius: 3px;
  background: var(--accent-soft); overflow: hidden;
}
.breaker .fill { height: 100%; background: var(--accent); border-radius: 3px; transition: width .4s ease; }
.breaker.warn  .fill { background: var(--warn); }
.breaker.alarm .fill { background: var(--alarm); }
.breaker .badge {
  font-size: 12px; font-weight: 600; padding: 1px 8px; border-radius: 999px;
  background: var(--line); color: var(--quiet);
}
.breaker.warn  .badge { background: var(--warn); color: #fff; }
.breaker.alarm .badge { background: var(--alarm); color: #fff; }
.breaker.off .num, .breaker.off .name { color: var(--quiet); }
.breaker .tools { grid-column: 2 / -1; display: flex; gap: 8px; align-items: center; margin-top: 4px; }
.breaker .tools input { flex: 1 1 160px; }
.breaker.hidden-row { opacity: .5; }

/* ------------------------------- charts ------------------------------- */

/* The charts, and ONLY the charts. This was `svg { width: 100% }`, which is
   true of a chart and catastrophic for an icon: every glyph in the menu grew
   to fill its row and shoved the labels into wrapping. Named hosts, so a new
   icon anywhere on the page cannot be caught by it again. */
#chart-curve svg, #chart-days svg, #chart-shares svg {
  display: block; width: 100%; height: auto; overflow: visible;
}
.axis { fill: var(--quiet); font-size: 10px; }
.gridline { stroke: var(--line); stroke-width: 1; }
.bar { fill: var(--accent); }
.bar.today { fill: var(--ok); }
.hbar { fill: var(--accent); }
.hlabel { fill: var(--ink); font-size: 11px; }
.hval { fill: var(--quiet); font-size: 11px; }
.area { fill: var(--accent-soft); }
.line { fill: none; stroke: var(--accent); stroke-width: 2; }
.empty { color: var(--quiet); font-size: 14px; padding: 12px 0; }

.range { display: flex; gap: 6px; margin-bottom: 12px; flex-wrap: wrap; }
.range button {
  border: 1px solid var(--line); background: transparent; color: var(--quiet);
  border-radius: 999px; padding: 5px 12px; font-size: 13px; cursor: pointer;
}
.range button.on { background: var(--accent); border-color: var(--accent); color: #fff; }

/* -------------------------------- events ------------------------------ */

#events { list-style: none; margin: 0; padding: 0; }
#events li {
  display: flex; gap: 10px; align-items: baseline;
  padding: 9px 0; border-top: 1px solid var(--line); font-size: 15px;
}
#events li:first-child { border-top: 0; }
#events .at   { color: var(--quiet); font-size: 13px; white-space: nowrap; }
#events .what { flex: 1; }
#events li.alarm .what { color: var(--alarm); }
#events li.warn  .what { color: var(--warn); }
#events li.info  .what { color: var(--quiet); }

/* ------------------------------- sign in ------------------------------ */

#signin { min-height: 80vh; display: grid; place-items: center; }
#signin form { display: grid; gap: 12px; width: min(320px, 90vw); text-align: center; }
#signin p { margin: 0; color: var(--quiet); }
#signin input, #signin button, .breaker .tools input, .breaker .tools button {
  font: inherit; padding: 9px 12px; border-radius: 9px;
  border: 1px solid var(--line); background: var(--bg); color: var(--ink);
}
.breaker .tools input, .breaker .tools button { padding: 5px 10px; font-size: 13px; }
#signin button, #signout { background: var(--accent); border-color: var(--accent); color: #fff; cursor: pointer; }
.err { color: var(--alarm); }

/* The foot the calendar wears, in this app's colours: what it is, which
   version of it -- the answer to "is my phone showing the new one" without
   opening a terminal -- and whose it is. The version is blank until the
   first answer arrives, which is the honest thing offline: the shell came
   out of a cache and does not know what the server is running.

   Always in view, because a foot at the end of a page this long is a foot
   nobody meets: the circuits alone can run past a screen, and the menu
   behind the button is how you install the app and how you escape a stale
   one.

   Fixed rather than sticky. `position: sticky; bottom: 0` only lifts an
   element while its parent's box has room left underneath it, and this one
   is the last thing in <main> -- so it has nowhere to travel and simply
   sits at the end of the document, which is what it did until 0.3.1. The
   body reserves the strip's height instead, so nothing is ever hidden
   under it. */
#appfoot {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 8;
  display: flex; align-items: center; justify-content: flex-end;
  padding: 14px 16px max(14px, env(safe-area-inset-bottom, 0px));
  color: var(--quiet); font-size: 13px;
  border-top: 1px solid var(--line);
  /* Solid. It passes over the cards as you scroll, and a strip this thin
     has no room to show anything through itself. */
  background: var(--card);
}
/* Centred on the strip rather than on what the button left over, and out of
   the way of taps so the button stays reachable under it. */
#appfoot .af-text {
  position: absolute; left: 52px; right: 52px;
  text-align: center; pointer-events: none; line-height: 1.3;
}
#appfoot .af-text a { pointer-events: auto; }
#appfoot .af-name { font-weight: 800; color: var(--ink); }
#appfoot .af-ver  { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-weight: 600; }
#appfoot .af-sep  { color: var(--accent); font-weight: 900; padding: 0 .3em; }
#appfoot a { color: var(--accent); font-weight: 700; text-decoration: none; }
#appfoot a:hover, #appfoot a:focus-visible { text-decoration: underline; }
/* The button the menu hangs off. Round like the calendar's face, but wearing
   the app's bolt: there is no person here to show. */
.avatar-btn { background: none; border: 0; padding: 0; line-height: 0; cursor: pointer;
              border-radius: 50%; }
.avatar-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.avatar {
  display: grid; place-items: center; width: 34px; height: 34px;
  border-radius: 50%; background: var(--accent);
}
.avatar svg { width: 19px; height: 19px; fill: #fff; }

/* The flyout, anchored to the foot and opening upward, because the foot is
   the bottom of the page and a menu that opened down would be off it. */
.flyout {
  /* Under the button, which now sits at the screen's edge rather than the
     content column's -- the strip is full width. */
  position: fixed; right: 16px; z-index: 20;
  bottom: calc(62px + env(safe-area-inset-bottom, 0px));
  min-width: 210px; padding: 6px;
  background: var(--card); color: var(--ink);
  border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, .18);
}
.fl-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 10px 12px; border: 0; border-radius: 8px;
  background: none; color: inherit; font: inherit; font-size: 14px;
  text-align: left; cursor: pointer; text-decoration: none;
}
.fl-item:hover, .fl-item:focus-visible { background: var(--bg); }
/* Sized here as well as in the markup: an icon that depends on its width
   attribute alone is one stylesheet rule away from filling the room. */
.fl-item svg { flex: 0 0 auto; width: 19px; height: 19px; color: var(--quiet); }
.fl-item span { white-space: nowrap; }
.fl-rule { height: 1px; margin: 5px 6px; background: var(--line); }

/* One line, said once, gone. Never an error the page has to keep. */
.toast {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 30;
  max-width: min(420px, calc(100vw - 32px));
  padding: 11px 16px; border-radius: 999px;
  background: var(--ink); color: var(--bg);
  font-size: 14px; box-shadow: 0 6px 20px rgba(0, 0, 0, .25);
}
