/* tempmon: an instrument panel for a house.
   Warm graphite, one amber accent, hairlines, numbers that read from across a room.
   Chart colors follow the validated dataviz palette; text never wears a series color. */

@font-face {
  font-family: "Instrument Sans";
  src: url("/static/fonts/instrument-sans.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
}

:root {
  color-scheme: dark;
  --plane: #0d0d0d;
  --surface: #1a1a19;
  --surface-2: #232321;
  --ink: #f0efec;
  --ink-2: #c3c2b7;
  --muted: #898781;
  --grid: #2c2c2a;
  --axis: #383835;
  --hair: rgba(255, 255, 255, 0.10);
  --accent: #f2a14b;
  --accent-ink: #1a1206;
  --good: #0ca30c;
  --warning: #fab219;
  --serious: #ec835a;
  --critical: #d03b3b;
  --good-ink: #3fcf5b;
  --s1: #3987e5; --s2: #d95926; --s3: #199e70; --s4: #c98500;
  --s5: #d55181; --s6: #008300; --s7: #9085e9; --s8: #e66767;
  --legend-tint: 70%; /* line color share in colored legend text */
  --radius: 14px;
  --gap: 16px;
  --font: "Instrument Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  background: var(--plane);
}

@media (prefers-color-scheme: light) {
  :root {
    --legend-tint: 60%;
    color-scheme: light;
    --plane: #f9f9f7;
    --surface: #fcfcfb;
    --surface-2: #f2f1ed;
    --ink: #0b0b0b;
    --ink-2: #52514e;
    --muted: #6f6d68;
    --grid: #e1e0d9;
    --axis: #c3c2b7;
    --hair: rgba(11, 11, 11, 0.10);
    --accent: #c46a0c;
    --accent-ink: #ffffff;
    --good-ink: #006300;
    --s1: #2a78d6; --s2: #eb6834; --s3: #1baf7a; --s4: #eda100;
    --s5: #e87ba4; --s6: #008300; --s7: #6250d6; --s8: #e34948;
  }
}

* { box-sizing: border-box; }
html, body { margin: 0; }
body {
  background: var(--plane);
  color: var(--ink);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
  text-rendering: optimizeLegibility;
}
a { color: inherit; text-decoration-color: var(--hair); text-underline-offset: 3px; }
a:hover { text-decoration-color: currentColor; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }
button, input, select { font: inherit; color: inherit; }
code { font-size: 0.9em; background: var(--surface-2); padding: 1px 6px; border-radius: 6px; }

/* ---------- Header ---------- */
.top {
  position: sticky; top: 0; z-index: 10;
  display: flex; align-items: center; gap: 24px;
  padding: max(12px, env(safe-area-inset-top)) max(24px, env(safe-area-inset-right)) 12px max(24px, env(safe-area-inset-left));
  background: var(--plane);
  border-bottom: 1px solid var(--hair);
}
.brand { display: inline-flex; align-items: center; gap: 10px; font-weight: 650; letter-spacing: -0.01em; text-decoration: none; font-size: 16px; }
.brand-mark {
  width: 20px; height: 20px; border-radius: 50%;
  background: conic-gradient(from 200deg, var(--accent) 0 300deg, transparent 300deg);
  -webkit-mask: radial-gradient(circle, transparent 5.5px, #000 6px);
          mask: radial-gradient(circle, transparent 5.5px, #000 6px);
}
.brand-lg { font-size: 24px; gap: 12px; }
.brand-lg .brand-mark { width: 28px; height: 28px; }
.nav { display: flex; gap: 4px; overflow-x: auto; scrollbar-width: none; flex: 1; }
.nav::-webkit-scrollbar { display: none; }
.nav a {
  padding: 6px 12px; border-radius: 999px; text-decoration: none; color: var(--ink-2); white-space: nowrap;
  transition: background .15s, color .15s;
}
.nav a:hover { background: var(--surface-2); color: var(--ink); }
.nav a[aria-current="page"] { color: var(--ink); background: var(--surface-2); box-shadow: inset 0 -2px 0 var(--accent); }
.logout { margin: 0; }

.main { max-width: 1320px; margin: 0 auto; padding: 24px max(24px, env(safe-area-inset-right)) 64px max(24px, env(safe-area-inset-left)); }

/* ---------- Typography ---------- */
.page-head { margin: 8px 0 24px; }
.page-title { margin: 0; font-size: clamp(26px, 3.2vw, 36px); font-weight: 650; letter-spacing: -0.02em; line-height: 1.1; }
.page-sub { margin: 8px 0 0; color: var(--ink-2); max-width: 64ch; }
.section-title { margin: 36px 0 14px; font-size: 13px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); display: flex; align-items: center; gap: 8px; }
.muted { color: var(--muted); }
.src { font-size: 12px; color: var(--muted); padding: 1px 8px; border: 1px solid var(--hair); border-radius: 999px; }
.u { color: var(--muted); font-size: 0.82em; margin-left: 2px; font-weight: 450; }
.empty { color: var(--ink-2); }

/* ---------- Status badges (icon + label, never color alone) ---------- */
.ico { width: 14px; height: 14px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.age { display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; color: var(--muted); white-space: nowrap; font-weight: 500; }
.age.fresh .ico { color: var(--good); }
.age.stale { color: var(--ink-2); }
.age.stale .ico { color: var(--warning); }
.age.bad { color: var(--ink-2); }
.age.bad .ico { color: var(--critical); }

/* ---------- Header toolbar ---------- */
.top .ranges { margin: 0; flex-wrap: nowrap; }
.top .ranges .chip { min-height: 32px; padding: 4px 12px; font-size: 13.5px; }
.top .nav { flex: 0 1 auto; margin-left: auto; }
.icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; padding: 0; }
.icon-btn .ico { width: 16px; height: 16px; }
.icon-btn[hidden] { display: none; }
.group[hidden], .group.user-hidden { display: none !important; }
.view-menu { position: relative; }
.tabbar, .group-dots, .logout-bottom, .range-select { display: none; }
.legend-pop { position: absolute; z-index: 30; max-width: 260px; padding: 10px 12px; border-radius: 12px; background: var(--surface-2);
  border: 1px solid var(--hair); box-shadow: 0 12px 32px rgb(0 0 0 / .4); font-size: 13px; color: var(--ink-2); line-height: 1.5; }
.legend-pop b { color: var(--ink); font-weight: 650; }
.legend-pop .pop-name { display: block; margin-bottom: 4px; color: var(--ink); font-weight: 600; }
.legend-pop .pop-when { display: block; margin-top: 4px; color: var(--muted); font-size: 12px; }
.value-nums { cursor: help; }
.view-menu > summary { list-style: none; cursor: pointer; }
.view-menu > summary::-webkit-details-marker { display: none; }
.view-menu[open] > summary { background: var(--surface-2); color: var(--ink); }
.view-menu .menu { position: absolute; z-index: 20; top: calc(100% + 6px); left: 0; min-width: 210px; padding: 10px 12px;
  border-radius: 12px; background: var(--surface-2); border: 1px solid var(--hair); box-shadow: 0 10px 30px rgba(0,0,0,.4); }
.menu-title { margin: 0 0 6px; font-size: 12px; color: var(--muted); font-weight: 600; }
.menu-item { display: flex; align-items: center; gap: 10px; padding: 7px 2px; font-size: 15px; cursor: pointer; }
.menu-item input { width: 20px; height: 20px; accent-color: var(--accent); }
.menu-note { margin: 6px 0 0; font-size: 12px; color: var(--muted); }
.menu-group + .menu-group { border-top: 1px solid var(--hair); }
.menu-group { display: flex; align-items: center; gap: 6px; }
.menu-group .menu-item { flex: 1; }
.split-btn { flex: none; width: 34px; height: 34px; display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--hair); border-radius: 9px; background: none; color: var(--muted); cursor: pointer; }
.split-btn svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.6; }
.split-btn:hover { color: var(--ink); background: var(--plane); }
.split-btn.on { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 55%, transparent); background: color-mix(in srgb, var(--accent) 14%, transparent); }
.split-btn.on svg { fill: color-mix(in srgb, var(--accent) 30%, transparent); }
.menu-group:has([data-group-toggle]:not(:checked)) .split-btn { opacity: .4; pointer-events: none; }
.is-split .view-btn:not(.on) { display: none; }
.is-split .view-btn.on { cursor: default; } /* one card per view: the caption looks like a lone tab, as on Landet */
.view-btn:disabled { color: var(--muted); }
:fullscreen .top .nav, :fullscreen .logout { display: none; }

/* ---------- Groups on the graphs page ---------- */
.alert-bar { display: flex; align-items: center; gap: 10px; margin: 0 0 20px; padding: 12px 16px; border-radius: var(--radius);
  background: var(--surface); border: 1px solid color-mix(in srgb, var(--warning) 40%, var(--hair)); text-decoration: none; }
.alert-bar .ico { color: var(--warning); width: 18px; height: 18px; }
.group { margin: 0 0 40px; animation: rise .45s cubic-bezier(.2,.7,.2,1) both; }
@keyframes rise { from { opacity: 0; transform: translateY(6px); } }
.group-head { display: flex; align-items: baseline; gap: 14px; margin: 0 0 14px; }
.group-title { margin: 0; font-size: clamp(22px, 2.6vw, 28px); font-weight: 650; letter-spacing: -0.02em; }
.values { list-style: none; margin: 0 0 14px; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px; }
.value { display: flex; flex-direction: column; gap: 2px; padding: 12px 14px; border-radius: 12px; background: var(--surface); border: 1px solid var(--hair); min-width: 0; }
.value-name { font-size: 13.5px; color: var(--ink-2); font-weight: 550; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.value-name .key { width: 12px; margin-right: 8px; vertical-align: middle; }
.key-s0 { background: var(--s1); } .key-s1 { background: var(--s2); } .key-s2 { background: var(--s3); } .key-s3 { background: var(--s4); }
.key-s4 { background: var(--s5); } .key-s5 { background: var(--s6); } .key-s6 { background: var(--s7); } .key-s7 { background: var(--s8); }
.value-num { font-size: 30px; font-weight: 600; letter-spacing: -0.03em; line-height: 1.1; }
.value.is-stale .value-num { color: var(--muted); }
.value-label { font-size: 12px; color: var(--muted); }

/* Plots inside a group: the first is the main plot, the rest strips under it. */
.group-body { padding: 14px 16px 12px; border-radius: var(--radius); background: var(--surface); border: 1px solid var(--hair); }
.plots { position: relative; display: flex; flex-direction: column; gap: 4px; }
[data-view][hidden] { display: none !important; }
.view-switch { display: flex; gap: 2px; margin: 0 0 2px; }
.view-btn { border: 0; background: none; padding: 2px 6px; border-radius: 6px; cursor: pointer; font-size: 11px; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.view-btn:hover { color: var(--ink); background: var(--surface-2); }
.view-btn.on { color: var(--ink); box-shadow: inset 0 -2px 0 var(--accent); border-radius: 6px 6px 0 0; }
.plot { position: relative; display: flex; flex-direction: column; min-width: 0; }
.plot .chart-plot { position: relative; }
.plot-unit { font-size: 11px; color: var(--muted); letter-spacing: .04em; text-transform: uppercase; font-weight: 600; margin: 0 0 2px 2px; }
/* A card with only one view shows its caption like the chosen tab elsewhere. */
.plots > .plot:first-child > .plot-unit { align-self: flex-start; padding: 2px 6px; color: var(--ink); box-shadow: inset 0 -2px 0 var(--accent); border-radius: 6px 6px 0 0; }
.plot .chart-empty { padding: 24px 0; }
.plot .chart-table { margin: 2px 0 0; font-size: 12px; }

/* The legend with live values, under the plots. */
.group-body .legends .values + .values { margin-top: 0; }
.group-body .values { margin: 10px 0 0; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 2px 14px; }
.group-body .value { flex-direction: row; align-items: baseline; gap: 7px; padding: 4px 6px; border: 0; background: none; border-radius: 8px; cursor: pointer; user-select: none; }
.group-body .value:hover { background: var(--surface-2); }
.group-body .value.off { opacity: .38; }
.group-body .value-name { font-size: 13px; font-weight: 600; color: var(--ink-2); flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.group-body .value-name .value-label { font-size: inherit; color: var(--muted); }
/* No key: each name is in its line's color, mixed with the ink so small
   text stays readable (at least 5:1 in both themes). */
.group-body .value .key { display: none; }
.group-body .value:has(.key-s0) .value-name { color: color-mix(in srgb, var(--s1) var(--legend-tint), var(--ink)); }
.group-body .value:has(.key-s1) .value-name { color: color-mix(in srgb, var(--s2) var(--legend-tint), var(--ink)); }
.group-body .value:has(.key-s2) .value-name { color: color-mix(in srgb, var(--s3) var(--legend-tint), var(--ink)); }
.group-body .value:has(.key-s3) .value-name { color: color-mix(in srgb, var(--s4) var(--legend-tint), var(--ink)); }
.group-body .value:has(.key-s4) .value-name { color: color-mix(in srgb, var(--s5) var(--legend-tint), var(--ink)); }
.group-body .value:has(.key-s5) .value-name { color: color-mix(in srgb, var(--s6) var(--legend-tint), var(--ink)); }
.group-body .value:has(.key-s6) .value-name { color: color-mix(in srgb, var(--s7) var(--legend-tint), var(--ink)); }
.group-body .value:has(.key-s7) .value-name { color: color-mix(in srgb, var(--s8) var(--legend-tint), var(--ink)); }
.group-body .value-nums { display: inline-flex; gap: 8px; align-items: baseline; flex: none; }
.group-body .value-num { font-size: 15px; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
.group-body .value-sub { color: var(--ink-2); font-weight: 500; font-size: 13px; }
.group-body .value-sub .u, .group-body .value-num .u { font-size: 0.8em; }
.value-stale { display: inline-flex; align-items: center; gap: 3px; font-size: 11px; color: var(--muted); flex: none; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.value-stale .ico { width: 12px; height: 12px; color: var(--warning); }

/* Landscape tablet and desktop: every group side by side, filling the screen. */
@media (min-width: 1000px) and (orientation: landscape) {
  html[data-page="home"], html[data-page="home"] body { height: 100%; }
  html[data-page="home"] body { display: flex; flex-direction: column; overflow: hidden; }
  html[data-page="home"] .top { position: static; padding-top: max(8px, env(safe-area-inset-top)); padding-bottom: 8px; gap: 16px; }
  html[data-page="home"] .brand { font-size: 15px; }
  html[data-page="home"] .nav a { padding: 4px 10px; font-size: 14px; }
  html[data-page="home"] .main { flex: 1; min-height: 0; max-width: none; width: 100%; padding: 8px max(8px, env(safe-area-inset-right)) 8px max(8px, env(safe-area-inset-left)); display: flex; flex-direction: column; } /* the bottom matches the sides; the home indicator may overlap the last card's edge */
  html[data-page="home"] .alert-bar { margin: 0 0 8px; padding: 6px 12px; font-size: 14px; }
  /* Groups stacked, each a full-width band: plots on the left, the group's
     name and legend in a column on the right. */
  /* The legend column is as wide as the widest legend (at most 300px), the
     same in every group so the charts line up. */
  .groups { flex: 1; min-height: 0; display: grid; grid-auto-flow: row; grid-auto-rows: minmax(0, 1fr); grid-template-columns: minmax(0, 1fr) fit-content(300px); gap: 8px 16px; }
  .groups .group { margin: 0; min-height: 0; min-width: 0; display: grid; grid-column: 1 / -1; grid-template-columns: subgrid;
    grid-template-rows: auto minmax(0, 1fr); grid-template-areas: "plots head" "plots legend"; gap: 2px 16px;
    padding: 6px 10px 2px 2px; border-radius: var(--radius); background: var(--surface); border: 1px solid var(--hair); animation: none; }
  .groups .group-head { grid-area: head; margin: 0 0 4px; align-items: baseline; gap: 8px; }
  .groups .group-title { font-size: 16px; white-space: nowrap; }
  .groups .group-body { display: contents; }
  .groups .plots { grid-area: plots; min-height: 0; display: flex; flex-direction: column; gap: 0; }
  .groups .group > .empty { grid-area: plots; align-self: center; margin: 0; }
  .groups .plot { flex: 3 1 0; min-height: 0; }
  .groups .plot-strip { flex: 2 1 0; min-height: 64px; }
  .groups .plot .chart-plot { flex: 1 1 0; min-height: 0; overflow: hidden; }
  .groups .plot .chart-plot > .uplot { position: absolute; inset: 0; }
  .groups .plot .chart-table { display: none; }
  .groups .plot-unit { position: absolute; top: 0; left: 40px; z-index: 1; margin: 0; line-height: 14px; }
  .groups .plots > .plot:first-child > .plot-unit { top: -2px; left: 34px; line-height: normal; } /* where the tabs sit */
  .groups .legends { grid-area: legend; min-height: 0; overflow-y: auto; scrollbar-width: none; }
  .groups .values { margin: 0; grid-template-columns: 1fr; align-content: start; gap: 0; }
  .groups .view-switch { position: absolute; top: -2px; left: 34px; z-index: 2; margin: 0; }
  .groups .value { padding: 1px 4px; line-height: 1.3; }
  .groups .value-name { font-size: 12.5px; }
  .groups .value-num { font-size: 14px; }
}

/* ---------- Groups editor ---------- */
.group-tabs { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 0 0 18px; }
.group-tabs .chip { text-decoration: none; }
.count { font-size: 12px; opacity: .65; font-variant-numeric: tabular-nums; }
.inline-form { display: inline-flex; gap: 6px; margin: 0 0 0 8px; }
.inline-form input { min-height: 36px; width: 160px; }
.picker { display: grid; gap: 10px; min-width: 0; }
.picker .device { min-width: 0; }
.picker .gone { margin-top: 10px; }
.picker .gone > summary { color: var(--muted); font-weight: 600; }
.picker .gone .device { margin-top: 8px; opacity: .85; }
.picker summary .chip.danger { margin-left: auto; min-height: 30px; padding: 3px 12px; font-size: 13px; }
.hint { margin: 0 0 4px; color: var(--ink-2); font-size: 14px; }
.saved { display: flex; gap: 8px; align-items: center; margin: 0; color: var(--ink-2); }
.saved .ico { color: var(--good); }
.picker .device { border: 1px solid var(--hair); border-radius: var(--radius); background: var(--surface); padding: 0 16px; }
.picker .device[open] { padding-bottom: 14px; }
.picker summary { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; cursor: pointer; padding: 14px 0; list-style: none; }
.picker summary::-webkit-details-marker { display: none; }
.picker summary::before { content: ""; width: 7px; height: 7px; border-right: 1.5px solid var(--muted); border-bottom: 1.5px solid var(--muted); transform: rotate(-45deg); transition: transform .15s; flex: none; }
.picker .device[open] summary::before { transform: rotate(45deg); }
.device-name { font-weight: 600; }
.device-vendor { color: var(--muted); font-size: 13px; }
.alias { display: grid; gap: 6px; font-size: 13px; color: var(--muted); max-width: 360px; margin-bottom: 12px; }
.series-table { width: 100%; border-collapse: collapse; font-size: 14px; table-layout: fixed; }
.series-table th:first-child, .series-table td:first-child { width: 48px; }
.series-table th:nth-child(3) { width: 64px; }
.series-table th:nth-child(4), .series-table th:nth-child(5) { width: 96px; }
.series-table th { text-align: left; font-size: 12px; font-weight: 600; color: var(--muted); padding: 6px 8px; border-bottom: 1px solid var(--hair); }
.series-table td { padding: 6px 8px; border-bottom: 1px solid var(--hair); }
.series-table tr:last-child td { border-bottom: 0; }
.series-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.series-table input[type="checkbox"] { width: 20px; height: 20px; accent-color: var(--accent); }
.w-limit { width: 78px; text-align: right; min-height: 34px !important; }
.save-bar { position: sticky; bottom: 0; padding: 14px 0 max(14px, env(safe-area-inset-bottom)); background: linear-gradient(transparent, var(--plane) 30%); }
.save-bar .primary { width: 100%; max-width: 360px; }
.new-group { display: block; }
.new-group > summary { list-style: none; width: 36px; padding: 0; justify-content: center; font-size: 20px; line-height: 1; }
.new-group > summary::-webkit-details-marker { display: none; }
.new-group[open] > summary { display: none; }
.new-group .inline-form { margin: 0; }
.new-group:not([open]) .inline-form { display: none; } /* a styled form would otherwise show through */
.group-settings { margin: 0 0 16px; }
.group-settings > summary { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; list-style: none; font-size: 14px; color: var(--muted); padding: 4px 0; }
.group-settings > summary::-webkit-details-marker { display: none; }
.group-settings > summary::before { content: ""; width: 6px; height: 6px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(-45deg); transition: transform .15s; }
.group-settings[open] > summary::before { transform: rotate(45deg); }
.group-settings .row-form { margin: 10px 0 0; }
.series-table .short { display: none; }
.series-table td label { cursor: pointer; }
.series-table tr:has(input[type="checkbox"]:not(:checked)) td:nth-child(2) { color: var(--muted); }
/* A sensor this group shows has an accent border. */
.picker .device:has(input[type="checkbox"]:checked) { border-color: color-mix(in srgb, var(--accent) 45%, var(--hair)); }

/* ---------- Filters ---------- */
.filters { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0 0 18px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px; min-height: 36px; padding: 6px 14px;
  border-radius: 999px; border: 1px solid var(--hair); background: transparent; color: var(--ink-2);
  cursor: pointer; font-size: 14px; font-weight: 500; transition: background .15s, color .15s, border-color .15s;
  font-variant-numeric: tabular-nums;
}
.chip:hover { background: var(--surface-2); color: var(--ink); }
.chip.on { background: var(--ink); color: var(--plane); border-color: var(--ink); }
.chip.danger:hover { border-color: var(--critical); color: var(--ink); }
.chip.check input { position: absolute; opacity: 0; pointer-events: none; }
.chip.check { position: relative; }
.chip.check:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
input[type="text"], input[type="password"], input[type="number"], select {
  min-height: 38px; padding: 6px 12px; border-radius: 10px; border: 1px solid var(--hair);
  background: var(--surface-2); color: var(--ink);
}
input:focus, select:focus { outline: none; border-color: var(--accent); }
.ghost { background: none; border: 1px solid var(--hair); border-radius: 999px; padding: 6px 14px; color: var(--ink-2); cursor: pointer; }
.ghost:hover { color: var(--ink); background: var(--surface-2); }
.primary {
  min-height: 46px; border: 0; border-radius: 12px; background: var(--accent); color: var(--accent-ink);
  font-weight: 650; cursor: pointer; font-size: 16px; transition: filter .15s;
}
.primary:hover { filter: brightness(1.06); }

/* ---------- Charts ---------- */
.charts { display: grid; gap: var(--gap); }
.plot.loading .chart-plot { opacity: .45; }
.key { display: inline-block; width: 14px; height: 2px; border-radius: 2px; }
.chart-plot { position: relative; }
.chart-plot:empty { min-height: 260px; }
.chart-empty { padding: 60px 0; text-align: center; color: var(--muted); }
.chart-table { margin-top: 6px; font-size: 13px; }
.chart-table summary { cursor: pointer; color: var(--muted); padding: 6px 0; width: fit-content; }
.chart-table .table-wrap { max-height: 320px; overflow: auto; }
.tip {
  position: absolute; z-index: 5; pointer-events: none; min-width: 96px;
  padding: 10px 12px; border-radius: 10px; background: var(--surface-2);
  border: 1px solid var(--hair); box-shadow: 0 8px 28px rgba(0,0,0,.35);
  font-size: 13px; display: none;
}
.tip-time { color: var(--muted); margin-bottom: 6px; font-variant-numeric: tabular-nums; }
.tip-row { display: grid; grid-template-columns: 14px auto; align-items: center; gap: 8px; }
.tip-row b { font-weight: 650; font-variant-numeric: tabular-nums; }
.tip-when { font-weight: 400; color: var(--muted); }
.tip-row span:last-child { color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.uplot { font-family: var(--font); }
.u-cursor-x { border-right: 1px solid var(--axis) !important; }
.u-select { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.u-axis { font-variant-numeric: tabular-nums; }

/* ---------- Tables & panels ---------- */
.panel { margin-bottom: 8px; }
.panel .section-title { margin-top: 28px; }
.table-wrap { overflow-x: auto; border: 1px solid var(--hair); border-radius: var(--radius); background: var(--surface); }
.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table th { text-align: left; font-weight: 600; font-size: 12px; color: var(--muted); padding: 10px 14px; border-bottom: 1px solid var(--hair); white-space: nowrap; position: sticky; top: 0; background: var(--surface); }
.table td { padding: 10px 14px; border-bottom: 1px solid var(--hair); vertical-align: top; }
.table tr:last-child td { border-bottom: 0; }
.table .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.table .err { color: var(--ink-2); max-width: 520px; overflow-wrap: anywhere; }
.row-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 10px; }
.row-form input[type="text"] { flex: 1 1 200px; min-width: 0; }
.inline-label { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); }
.alert-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 8px; }
.alert-item { display: flex; gap: 12px; align-items: flex-start; padding: 14px 16px; border-radius: var(--radius);
  background: var(--surface); border: 1px solid color-mix(in srgb, var(--warning) 35%, var(--hair)); }
.alert-item > .ico { color: var(--warning); width: 18px; height: 18px; margin-top: 2px; }
.alert-item div { display: grid; gap: 2px; }
.alert-item span { color: var(--ink-2); font-size: 14px; }
.alert-item .muted { font-size: 12.5px; color: var(--muted); }

/* ---------- Login ---------- */
.solo { min-height: 100dvh; display: grid; }
.login { display: grid; place-items: center; padding: 24px; background:
  radial-gradient(60% 50% at 50% 0%, color-mix(in srgb, var(--accent) 12%, transparent), transparent 70%), var(--plane); }
.login-card { width: min(380px, 100%); display: grid; gap: 28px; justify-items: center; }
.login-card > * { width: 100%; }
.login-card > .brand { width: auto; }
.stack { display: grid; gap: 14px; }
.stack > *, .field input { width: 100%; min-width: 0; }
.field { display: grid; gap: 6px; font-size: 13px; color: var(--muted); }
.field-help { margin: -8px 0 0; font-size: 12.5px; color: var(--muted); }
.pin { font-size: 28px; letter-spacing: 0.5em; text-align: center; font-variant-numeric: tabular-nums; min-height: 56px; padding-left: 0.5em; }
.pin-box { position: relative; }
.pin-cells { display: none; }
/* With app.js: eight boxes, the real input invisible on top of them, so a tap
   anywhere focuses it and paste and password autofill still work. */
.pin-on .pin-cells { display: grid; grid-template-columns: repeat(8, 1fr); gap: 8px; }
.pin-on .pin { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; z-index: 1; cursor: text;
  font-size: 16px; letter-spacing: 0; caret-color: transparent; }
.pin-on .pin-submit { display: none; }
.pin-cell { position: relative; height: 54px; border-radius: 12px; background: var(--surface); border: 1px solid var(--hair);
  transition: border-color .15s, background .15s; }
.pin-cell.filled::after { content: ""; position: absolute; inset: 0; margin: auto; width: 12px; height: 12px; border-radius: 50%; background: var(--ink); }
.pin-on:has(.pin:focus) .pin-cell.next { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
.pin-busy .pin-cell { border-color: color-mix(in srgb, var(--accent) 55%, var(--hair)); }
.pin-busy .pin-cell.filled::after { background: var(--accent); }
.pin-wrong .pin-cells { animation: pin-shake .4s; }
.pin-wrong .pin-cell { border-color: color-mix(in srgb, var(--critical) 70%, var(--hair)); }
@keyframes pin-shake { 0%, 100% { transform: none; } 20%, 60% { transform: translateX(-7px); } 40%, 80% { transform: translateX(7px); } }
@media (prefers-reduced-motion: reduce) { .pin-wrong .pin-cells { animation: none; } }
@media (max-width: 360px) { .pin-on .pin-cells { gap: 5px; } .pin-cell { height: 46px; } }
.form-error, .notice { display: flex; gap: 8px; align-items: center; margin: 0; color: var(--ink-2); }
.form-error .ico { color: var(--critical); }
.notice .ico { color: var(--warning); }

/* ---------- Phone ---------- */
@media (max-width: 900px) {
  .top { flex-wrap: wrap; }
  .top .ranges { order: 5; flex-basis: 100%; overflow-x: auto; scrollbar-width: none; }
}
@media (max-width: 640px) {
  /* One row: logo, range, eye. The pages are tabs at the bottom. */
  .top { gap: 8px; padding: max(8px, env(safe-area-inset-top)) max(10px, env(safe-area-inset-right)) 8px max(10px, env(safe-area-inset-left)); flex-wrap: nowrap; }
  .top .nav, .top > .logout, .top [data-fullscreen] { display: none; }
  .top .brand { margin-right: auto; }
  .top .view-menu .menu { left: auto; right: 0; max-width: calc(100vw - 32px); }
  .top .ranges { order: 0; flex-basis: auto; overflow: visible; }
  .top .ranges .chip { display: none; }
  .range-select { display: block; height: 36px; padding: 0 28px 0 12px; border-radius: 999px; font-size: 14px; font-weight: 600; }

  /* Each group is one card: its name at the top, the tabs on the same row. */
  .groups .group { position: relative; margin: 0 0 8px; padding: 8px 8px 6px; border-radius: 10px; background: var(--surface); border: 1px solid var(--hair); }
  .groups .group-head { margin: 0 0 4px; min-height: 24px; align-items: center; }
  .groups .group-title { font-size: 17px; }
  .groups .group-body { padding: 0; border: 0; background: none; }
  .groups .plots { position: static; }
  .groups .view-switch { position: absolute; top: 8px; right: 6px; margin: 0; }
  .groups .group-head:has(+ .group-body .view-switch) { padding-right: 190px; }

  /* The chart's caption sits on the group name's row. */
  .groups .plots > .plot:first-child { position: static; }
  .groups .plots > .plot:first-child > .plot-unit { position: absolute; top: 8px; right: 6px; margin: 0; }

  /* The legend in two columns, one line per sensor: the colored name and the
     value beside it. */
  .groups .group-body .values { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 10px; margin-top: 4px; }
  .groups .group-body .value { display: flex; align-items: baseline; gap: 4px; padding: 2px 0; }
  .groups .group-body .value-name { flex: 1 1 auto; min-width: 0; font-size: 12.5px; font-weight: 600; }
  .groups .group-body .value-num { font-size: 14px; }
  .groups .group-body .value-sub { font-size: 12px; }

  /* Tabs at the bottom, above the home indicator. */
  .tabbar { position: fixed; z-index: 15; left: 0; right: 0; bottom: 0; display: grid; grid-template-columns: repeat(3, 1fr);
    padding: 6px max(8px, env(safe-area-inset-right)) max(6px, env(safe-area-inset-bottom)) max(8px, env(safe-area-inset-left));
    background: color-mix(in srgb, var(--plane) 90%, transparent); backdrop-filter: blur(14px) saturate(1.2);
    -webkit-backdrop-filter: blur(14px) saturate(1.2); border-top: 1px solid var(--hair); }
  .tabbar a { display: grid; justify-items: center; gap: 2px; padding: 6px 0 4px; border-radius: 10px; font-size: 11px; font-weight: 600;
    color: var(--muted); text-decoration: none; }
  .tabbar .ico { width: 22px; height: 22px; }
  .tabbar a[aria-current="page"] { color: var(--accent); }
  body .main { padding-bottom: calc(76px + env(safe-area-inset-bottom)); } /* room for the tabs, over the general phone padding */
  .logout-bottom { display: block; margin: 24px 0 0; }
  .logout-bottom button { width: 100%; }

  /* The groups are slides: swipe sideways, one group per screen. */
  .groups { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; gap: 8px;
    margin: 0 calc(-1 * max(6px, env(safe-area-inset-left))); padding: 0 max(6px, env(safe-area-inset-left)); scroll-padding: 0 max(6px, env(safe-area-inset-left)); }
  .groups::-webkit-scrollbar { display: none; }
  .groups > .group { flex: 0 0 100%; scroll-snap-align: start; scroll-snap-stop: always; margin: 0; }
  .groups > .empty { flex: 0 0 100%; }
  .group-dots { display: flex; justify-content: center; gap: 8px; margin: 6px 0 0; }
  .group-dots button { width: 8px; height: 8px; padding: 0; border: 0; border-radius: 50%; background: var(--hair); cursor: pointer; }
  .group-dots button.on { background: var(--ink); }
  .group-dots:has(button:only-child) { display: none; }

  /* The home page fills the screen between the bars; each slide fills it and
     its chart takes what the name and legend leave. */
  html[data-page="home"] .main { height: calc(100dvh - 55px); display: flex; flex-direction: column; }
  html[data-page="home"] .groups { flex: 1; min-height: 0; }
  .groups > .group { display: flex; flex-direction: column; min-height: 0; }
  .groups .group-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  .groups .plots { flex: 1; min-height: 0; }
  .groups .plot { flex: 3 1 0; min-height: 0; }
  .groups .plot-strip { flex: 2 1 0; min-height: 64px; }
  .groups .plot .chart-plot { flex: 1 1 0; min-height: 0; overflow: hidden; }
  .groups .plot .chart-plot > .uplot { position: absolute; inset: 0; }

  /* The table twin stays for screen readers only. */
  .groups .plot .chart-table { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; margin: 0; }
  .values { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .value-num { font-size: 24px; }
  /* Groups: one scrolling row of tabs, tight cards, the save button above the tabs. */
  html[data-page="groups"] .page-head { margin: 0 0 14px; }
  html[data-page="groups"] .page-title { font-size: 26px; }
  html[data-page="groups"] .page-sub { font-size: 14px; }
  .group-tabs { margin: 0 0 10px; }
  .new-group[open] { flex-basis: 100%; }
  .new-group[open] .inline-form { display: flex; }
  .new-group .inline-form input { flex: 1; width: auto; min-width: 0; }
  .hint { font-size: 13px; color: var(--muted); }
  .picker { gap: 8px; }
  .picker .device { padding: 0 12px; border-radius: 10px; }
  .picker .device[open] { padding-bottom: 8px; }
  .picker summary { padding: 11px 0; gap: 8px; }
  .alias { max-width: none; margin-bottom: 6px; gap: 4px; font-size: 12px; }
  .alias input { min-height: 38px; }
  .series-table { font-size: 15px; }
  .series-table thead th:nth-child(-n+2) { color: transparent; }
  .series-table th:nth-child(3), .series-table td:nth-child(3) { display: none; }
  .series-table th:first-child, .series-table td:first-child { width: 34px; }
  .series-table th:nth-child(4), .series-table th:nth-child(5) { width: 66px; }
  .series-table th { font-size: 11px; padding: 4px; }
  .series-table .long { display: none; }
  .series-table .short { display: inline; }
  .series-table td { padding: 4px; vertical-align: middle; }
  .w-limit { width: 60px; }
  .save-bar { bottom: calc(62px + env(safe-area-inset-bottom)); padding: 10px 0; }
  .save-bar .primary { max-width: none; }
  .main { padding: 16px max(16px, env(safe-area-inset-right)) 48px max(16px, env(safe-area-inset-left)); }
  html[data-page="home"] .main { padding-top: 6px; padding-left: max(6px, env(safe-area-inset-left)); padding-right: max(6px, env(safe-area-inset-right)); }
  .chart-plot:empty { min-height: 210px; }

  /* Health: each table row is a small card, so nothing scrolls sideways. */
  html[data-page="health"] .page-sub { font-size: 14px; }
  html[data-page="health"] .section-title { margin: 22px 0 8px; }
  .int-table, .stale-table, .fail-table { display: block; }
  .int-table thead, .stale-table thead, .fail-table thead { display: none; }
  .int-table tbody, .stale-table tbody, .fail-table tbody { display: block; }
  .int-table tr, .stale-table tr, .fail-table tr { display: grid; padding: 10px 12px; border-bottom: 1px solid var(--hair); }
  .int-table tr:last-child, .stale-table tr:last-child, .fail-table tr:last-child { border-bottom: 0; }
  .table.int-table td, .table.stale-table td, .table.fail-table td { display: block; padding: 0; border: 0; max-width: none; text-align: left; }
  .int-table tr { grid-template-columns: 1.4fr repeat(4, minmax(0, 1fr)); gap: 6px 8px; }
  .int-table td:nth-child(1) { grid-column: 1 / 3; font-size: 16px; }
  .int-table td:nth-child(2) { grid-column: 3 / -1; justify-self: end; }
  .int-table td.err-none { display: none; }
  .int-table td:nth-child(5) .muted { display: none; } /* the count is beside the polls */
  .int-table td[data-label] { font-size: 14px; }
  .int-table td[data-label]::before { content: attr(data-label); display: block; font-size: 11px; font-weight: 600; color: var(--muted); }
  .int-table td.err { grid-column: 1 / -1; font-size: 13px; }
  .stale-table tr { grid-template-columns: minmax(0, 1fr) auto; gap: 1px 12px; font-size: 14px; }
  .stale-table td:nth-child(2) { grid-row: 2; font-size: 12px; color: var(--muted); }
  .table.stale-table td:nth-child(3) { grid-row: 1; grid-column: 2; text-align: right; }
  .table.stale-table td:nth-child(4) { grid-row: 2; grid-column: 2; text-align: right; font-size: 12px; }
  .fail-table tr { grid-template-columns: auto minmax(0, 1fr) auto auto; gap: 2px 10px; font-size: 13px; }
  .fail-table td:nth-child(1) { grid-row: 1; grid-column: 2; color: var(--muted); }
  .fail-table td:nth-child(2) { grid-row: 1; grid-column: 1; font-weight: 600; }
  .fail-table td:nth-child(3), .fail-table td:nth-child(4) { grid-row: 1; color: var(--muted); }
  .fail-table td.err { grid-column: 1 / -1; }
}

/* The Home Screen app on a tablet is a wall screen, like full screen in
   Safari: no page links or Log out. Phones keep their tabs. */
@media (display-mode: standalone) and (min-width: 641px) {
  .top .nav, .top > .logout { display: none; }
}
/* iOS 26/27 blurs the top of a Home Screen app unless a real element (not a
   pseudo-element) with a solid background is fixed within 4px of the top and
   is at least 6px high; iOS also colors the status bar from it. */
.status-plate { display: none; }
@media (display-mode: standalone) {
  .status-plate { display: block; position: fixed; z-index: 50; top: 0; left: 0; right: 0; height: 6px; background: var(--plane); pointer-events: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
@media (forced-colors: active) {
  .key { background: CanvasText !important; }
}
