/* Self-hosted so the app keeps its face offline and asks Google for nothing.
   Both are variable (one file per subset covers every weight used here) and
   SIL OFL 1.1 — see static/fonts/README.md. */
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/static/fonts/archivo-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/static/fonts/archivo-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;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/static/fonts/jetbrains-mono-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/static/fonts/jetbrains-mono-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;
}

/* Heating — warm paper, two accents.
   Ember is "this room is asking for heat", blue is anything scheduled, switched
   off or merely informative, ochre belongs to the watchdog and appears nowhere
   else. No green: the two states people confuse most differ in lightness as
   well as hue. Every figure is set in the mono face so eight rooms line up as
   a column of numbers. */
:root {
  color-scheme: light;
  --font-ui: Archivo, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-num: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --surface-0: #efede8;
  --surface-1: #ffffff;
  --surface-2: #f3f1ec;
  --border: #e4e0d8;
  --text-primary: #1a1b1e;
  --text-secondary: #4a4d52;
  --text-muted: #5c5f64;

  --ember: #b8471a;
  --ember-tint: #f3ded3;
  --ember-ink: #8f3511;
  --blue: #2c6aa8;
  --blue-tint: #dce7f2;
  --blue-ink: #1f4f80;
  --ochre: #8a5a08;
  --ochre-tint: #f6e7c8;
  --ochre-ink: #6b4406;
  --neutral: #9a9d9f;
  --neutral-bar: #b6b2a8;

  /* chart + legacy roles, pointed at the same two accents */
  --series-actual: var(--ember);   /* measured */
  --series-target: var(--blue);    /* target */
  --series-heat: #6e7175;          /* valve, its own panel */
  --good: var(--blue);
  --warning: var(--ochre);
  --critical: var(--ochre);
  --accent: var(--ember);
  --accent-ink: #ffffff;

  --radius: 16px;
  --shadow: 0 1px 2px rgba(26, 27, 30, 0.055);
  --shadow-lift: 0 6px 20px rgba(26, 27, 30, 0.09), 0 1px 2px rgba(26, 27, 30, 0.06);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --surface-0: #131315;
    --surface-1: #1c1d20;
    --surface-2: #24252a;
    --border: #2c2d31;
    --text-primary: #eceae4;
    --text-secondary: #c9c7c1;
    --text-muted: #9a9c9f;
    --ember: #e8794a;
    --ember-tint: #3a2117;
    --ember-ink: #f0a47e;
    --blue: #7fb0e0;
    --blue-tint: #17242e;
    --blue-ink: #9bc4e8;
    --ochre: #e0b04a;
    --ochre-tint: #2a2412;
    --ochre-ink: #e0b04a;
    --neutral: #6e7175;
    --neutral-bar: #4a4c50;
    --series-heat: #8f918f;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-lift: 0 6px 20px rgba(0, 0, 0, 0.45), 0 1px 2px rgba(0, 0, 0, 0.4);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --surface-0: #131315;
  --surface-1: #1c1d20;
  --surface-2: #24252a;
  --border: #2c2d31;
  --text-primary: #eceae4;
  --text-secondary: #c9c7c1;
  --text-muted: #9a9c9f;
  --ember: #e8794a;
  --ember-tint: #3a2117;
  --ember-ink: #f0a47e;
  --blue: #7fb0e0;
  --blue-tint: #17242e;
  --blue-ink: #9bc4e8;
  --ochre: #e0b04a;
  --ochre-tint: #2a2412;
  --ochre-ink: #e0b04a;
  --neutral: #6e7175;
  --neutral-bar: #4a4c50;
  --series-heat: #8f918f;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-lift: 0 6px 20px rgba(0, 0, 0, 0.45), 0 1px 2px rgba(0, 0, 0, 0.4);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
[hidden] { display: none !important; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--surface-0);
  color: var(--text-primary);
  font: 16px/1.45 var(--font-ui);
  -webkit-font-smoothing: antialiased;
  padding-bottom: calc(24px + var(--safe-bottom));
  overscroll-behavior-y: contain;
}
.wrap { max-width: 720px; margin: 0 auto; padding: 0 16px; }

/* --- header ------------------------------------------------------------- */
header {
  position: sticky; top: 0; z-index: 10;
  background: color-mix(in srgb, var(--surface-0) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
  padding: calc(8px + env(safe-area-inset-top, 0px)) 0 8px;
}
.header-row { display: flex; align-items: center; gap: 10px; }
h1 { font-size: 19px; font-weight: 700; margin: 0; letter-spacing: -0.015em; }
.clock { font-family: var(--font-num); font-size: 12px; color: var(--text-muted); flex: 1; }
.status { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-muted); }
.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--good); flex: none; }
.dot.warn { background: var(--ochre); }
.dot.bad { background: var(--ochre); }
.icon-btn {
  appearance: none; border: 0; background: none;
  color: var(--text-muted); width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer;
}
.icon-btn:active { background: var(--surface-2); }
.icon-btn svg { width: 19px; height: 19px; }

/* the sentence at the top of the list: what the house is doing, in words */
.headline { margin: 12px 0 0; font-size: 21px; line-height: 1.2; font-weight: 600; letter-spacing: -0.02em; }
.subline { margin: 5px 0 0; font-size: 13px; line-height: 1.4; color: var(--text-muted); }
.header-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.head-chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--surface-1); border-radius: 999px; padding: 6px 11px;
  font-size: 12px; color: var(--text-secondary);
}
.head-chip svg { width: 13px; height: 13px; }
.head-chip .pip { width: 7px; height: 7px; border-radius: 50%; background: var(--blue); }

.banner {
  margin-top: 10px; padding: 12px 14px; border-radius: 14px; font-size: 13px;
  line-height: 1.45; background: var(--surface-1); color: var(--text-secondary);
  display: flex; gap: 10px; align-items: flex-start;
}
.banner svg { width: 18px; height: 18px; flex: none; margin-top: 1px; }
.banner .grow { flex: 1; min-width: 0; }
.banner b { color: var(--text-primary); font-weight: 600; }
.banner.eco { background: var(--blue-tint); color: var(--blue-ink); }
.banner.eco b, .banner.eco svg { color: var(--blue-ink); }
.banner.bad { background: var(--ochre-tint); color: var(--ochre-ink); }
.banner.bad b, .banner.bad svg { color: var(--ochre-ink); }

/* --- room rows ---------------------------------------------------------
   Eight rooms have to fit on a phone without scrolling, so each room is one
   compact row. The row itself is the control: drag it left/right like a dial,
   tap it to slide the rest of the controls open.

   The bar along the bottom is absolute, not progress: 14° sits at the left and
   24° at the right in every row, so the attic reads as colder than the hall at
   a glance. The tick is the target. */
.room-group { margin-top: 16px; }
.room-group:first-child { margin-top: 10px; }
.group-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; padding: 0 6px 8px;
}
.group-head h2 {
  margin: 0; font-size: 11px; font-weight: 600; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--text-muted);
}
.group-head .avg { font-family: var(--font-num); font-size: 11px; color: var(--text-muted); }

.rooms { display: grid; gap: 8px; margin: 8px 0 0; }
.row {
  background: var(--surface-1); border-radius: var(--radius);
  overflow: hidden; box-shadow: var(--shadow);
  display: grid; grid-template-rows: auto 0fr;
  transition: grid-template-rows 0.22s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.2s;
}
.row.open { grid-template-rows: auto 1fr; box-shadow: var(--shadow-lift); }
.row.dragging { box-shadow: var(--shadow-lift); }

.row-main {
  /* a grid item's automatic minimum is its content: without this a long name
     next to a running timer pushes the figures off the card */
  min-width: 0;
  position: relative; display: flex; align-items: flex-start; gap: 12px;
  padding: 12px 15px 15px; min-height: 64px; cursor: ew-resize;
  touch-action: pan-y; user-select: none; -webkit-user-select: none;
}
.row.dragging .row-main { background-color: color-mix(in srgb, var(--ember) 7%, transparent); }

.row-scale {
  position: absolute; left: 15px; right: 15px; bottom: 11px; height: 4px;
  border-radius: 2px; background: var(--surface-2); pointer-events: none;
}
.row-fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: 0;
  border-radius: 2px; background: var(--neutral-bar);
  transition: width 0.4s ease-out, background-color 0.3s;
}
.row-tick {
  position: absolute; top: -3px; bottom: -3px; width: 2px; left: 0;
  border-radius: 1px; background: var(--text-primary);
  transition: left 0.18s ease-out;
}
.row.dragging .row-tick { transition: none; width: 3px; top: -5px; bottom: -5px; }
.row.heating .row-fill { background: var(--ember); }
.row.alert .row-fill { background: var(--ochre); }
.row.off .row-fill { background: color-mix(in srgb, var(--blue) 55%, var(--surface-2)); }
.row.off .row-tick { background: color-mix(in srgb, var(--blue) 55%, var(--surface-2)); }
.row.stale { opacity: 0.62; }

.row-text { position: relative; flex: 1; min-width: 0; }
.row-name {
  display: block; font-size: 15.5px; font-weight: 600; letter-spacing: -0.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.row-tags {
  display: flex; gap: 7px; align-items: center; flex-wrap: wrap;
  font-size: 11.5px; color: var(--text-muted); margin-top: 6px;
}
/* the state, said in a word as well as a colour */
.state {
  display: inline-flex; align-items: center; gap: 5px; border-radius: 999px;
  padding: 3px 9px 3px 7px; font-size: 11.5px; font-weight: 500;
  background: var(--surface-2); color: var(--text-secondary);
}
.state::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--neutral);
}
.state.is-heating { background: var(--ember-tint); color: var(--ember-ink); }
.state.is-heating::before { background: var(--ember); }
.state.is-alert { background: var(--ochre-tint); color: var(--ochre-ink); }
.state.is-alert::before { background: var(--ochre); }
.state.is-off { background: var(--blue-tint); color: var(--blue-ink); }
.state.is-off::before { background: var(--blue); }
.row-tags .timer-tag {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--font-num); font-size: 11.5px; color: var(--text-secondary);
}
.row-tags .timer-tag svg { width: 12px; height: 12px; }
.row-tags .meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.row-nums { position: relative; text-align: right; flex: none; }
.row-actual {
  display: flex; align-items: baseline; justify-content: flex-end; gap: 1px;
  font-family: var(--font-num); font-size: 27px; font-weight: 500;
  letter-spacing: -0.035em; line-height: 1;
}
.row-actual .unit { font-size: 15px; font-weight: 400; color: var(--text-muted); }
.row-target {
  margin-top: 6px; font-family: var(--font-num); font-size: 11.5px;
  letter-spacing: -0.01em; white-space: nowrap; color: var(--text-muted);
}
.row.heating .row-target { color: var(--ember-ink); }
.row.alert .row-target { color: var(--ochre-ink); }
.row.off .row-target { color: var(--blue-ink); }
.row.dragging .row-target { font-size: 14px; color: var(--ember-ink); }
.row-target.pending { opacity: 0.6; }
.row-target .eta { margin-left: 5px; color: var(--text-muted); }

/* the drawer that slides open on tap */
.row-panel { overflow: hidden; }
.row-panel-inner {
  padding: 2px 15px 15px; display: flex; flex-direction: column; gap: 10px;
  border-top: 1px solid var(--surface-2); margin-top: 2px;
}
.panel-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.chips { display: flex; gap: 6px; flex: 1; flex-wrap: wrap; }
.chip {
  appearance: none; border: 1px solid var(--border); background: var(--surface-1);
  color: var(--text-primary); padding: 7px 14px; border-radius: 12px;
  font-size: 13px; font-weight: 500; cursor: pointer; min-height: 40px;
}
.chip[aria-pressed="true"] {
  background: var(--text-primary); border-color: var(--text-primary); color: var(--surface-1);
}
.step-btn {
  appearance: none; border: 1px solid var(--border); background: var(--surface-1);
  color: var(--text-primary); width: 46px; height: 46px; border-radius: 14px;
  font-size: 20px; font-weight: 500; cursor: pointer; flex: none;
  display: grid; place-items: center; user-select: none;
}
.step-btn:active { transform: scale(0.96); background: var(--surface-2); }
.step-btn:disabled { opacity: 0.4; }
.bar { flex: 1; height: 4px; border-radius: 2px; background: var(--surface-2); overflow: hidden; }
.bar span { display: block; height: 100%; background: var(--ember); }
.link-btn {
  appearance: none; background: none; border: none; color: var(--blue-ink);
  font: inherit; font-size: 13px; font-weight: 600; padding: 8px 2px; cursor: pointer; min-height: 40px;
}
.hint { font-size: 12px; color: var(--text-muted); }
.time-input {
  font: inherit; font-size: 15px; font-family: var(--font-num);
  padding: 8px 10px; border-radius: 12px; border: 1px solid var(--border);
  background: var(--surface-1); color: var(--text-primary); min-height: 40px;
}
.panel-row.custom { gap: 10px; }
.list-foot { padding: 10px 2px 0; }

/* --- compact: eight rooms on one phone screen --------------------------
   The list is the whole point of this app, so one room is one line by
   default. Valve and rate step aside — they are in the drawer, and the foot
   of the list turns them back on for good. Anything exceptional (a window
   open, a flat battery, a fault) stays on the row at any density. */
body.compact .headline { font-size: 19px; }
body.compact .subline { font-size: 12.5px; }
body.compact .room-group { margin-top: 12px; }
body.compact .room-group:first-child { margin-top: 10px; }
body.compact .group-head { padding: 0 6px 6px; }
body.compact .rooms { gap: 6px; }
body.compact .row-main { padding: 10px 15px 14px; min-height: 48px; align-items: center; }
body.compact .row-scale { bottom: 9px; }
body.compact .row-text { display: flex; align-items: baseline; gap: 7px; }
body.compact .state { padding: 3px 8px 3px 6px; }
body.compact .row-name { flex: 0 1 auto; min-width: 9ch; }
/* On one line the room name wins the space: the tags give way first, and
   nothing inside them wraps. */
body.compact .row-tags { margin-top: 0; flex: 0 999 auto; flex-wrap: nowrap; overflow: hidden; min-width: 0; }
body.compact .row-tags > * { flex: none; white-space: nowrap; }
/* A running timer is the thing you can act on, so it takes the chip's place
   on a narrow row — the bar still says whether the room is heating. */
body.compact .row-tags:has(.timer-tag) .state { display: none; }
body.compact .row-tags .flags { flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; }
body.compact .row-tags .readings { display: none; }
/* the arrival estimate needs the width the room name wants more */
body.compact .eta { display: none; }
body.compact .row-actual { font-size: 23px; }
/* the target sits beside the reading, not under it: one line per room */
body.compact .row-nums { display: flex; align-items: baseline; gap: 9px; }
body.compact .row-target { margin-top: 0; font-size: 12px; }
body.compact .row-name { overflow: hidden; text-overflow: ellipsis; }
/* a fault is worth the extra line, whatever the density */
body.compact .row.alert .row-text { display: block; }
body.compact .row.alert .row-tags { margin-top: 5px; flex-wrap: wrap; }

/* --- detail sheet ------------------------------------------------------- */
dialog#sheet {
  border: none; padding: 0; margin: 0 auto; width: 100%; max-width: 720px;
  background: var(--surface-1); color: var(--text-primary);
  border-radius: 20px 20px 0 0; position: fixed; inset: auto 0 0 0;
  max-height: 92vh; overflow: auto;
}
dialog#sheet::backdrop { background: rgba(0, 0, 0, 0.45); }
.sheet-pad { padding: 16px 16px calc(24px + var(--safe-bottom)); }
.sheet-head { display: flex; align-items: center; gap: 12px; margin-bottom: 4px; }
.sheet-head h2 { margin: 0; font-size: 18px; flex: 1; }
.summary { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 12px 0; }
.stat { background: var(--surface-2); border-radius: 12px; padding: 10px; }
.stat .n { font-size: 18px; font-weight: 650; font-family: var(--font-num); font-variant-numeric: tabular-nums; }
.stat .k { font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.range { display: flex; gap: 8px; margin-bottom: 8px; }
figure { margin: 0; }
figcaption { font-size: 13px; color: var(--text-secondary); margin-bottom: 8px; }
.legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: 13px; color: var(--text-secondary); margin: 8px 0 0; }
.legend span { display: inline-flex; align-items: center; gap: 6px; }
.legend i { width: 14px; height: 3px; border-radius: 2px; display: inline-block; }
.chart-wrap { position: relative; }
svg.chart { display: block; width: 100%; height: auto; touch-action: pan-y; }
.tip {
  position: absolute; pointer-events: none; background: var(--surface-1);
  border: 1px solid var(--border); border-radius: 10px; padding: 8px 10px;
  font-size: 13px; box-shadow: var(--shadow); min-width: 128px; opacity: 0;
  transition: opacity 0.12s; font-family: var(--font-num); font-variant-numeric: tabular-nums;
}
.tip.on { opacity: 1; }
.tip .t { color: var(--text-muted); font-size: 11px; margin-bottom: 4px; }
.tip .row { display: flex; align-items: center; gap: 6px; }
.tip .row b { margin-left: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: 13px; margin-top: 10px; }
table.data th, table.data td { text-align: left; padding: 6px 4px; border-bottom: 1px solid var(--border); }
table.data td { font-family: var(--font-num); font-variant-numeric: tabular-nums; color: var(--text-secondary); }
details.table-view summary { font-size: 13px; color: var(--blue-ink); cursor: pointer; padding: 8px 0; font-weight: 600; }
.events { list-style: none; padding: 0; margin: 12px 0 0; font-size: 13px; }
.events li { display: flex; gap: 8px; padding: 7px 0; border-bottom: 1px solid var(--border); color: var(--text-secondary); }
.events time { color: var(--text-muted); flex: none; font-family: var(--font-num); font-variant-numeric: tabular-nums; }
.events .k { font-weight: 600; color: var(--text-primary); }

/* --- settings sheet ----------------------------------------------------- */
dialog#settings {
  border: none; padding: 0; margin: 0 auto; width: 100%; max-width: 720px;
  background: var(--surface-1); color: var(--text-primary);
  border-radius: 20px 20px 0 0; position: fixed; inset: auto 0 0 0;
  max-height: 92vh; overflow: auto;
}
dialog#settings::backdrop { background: rgba(0, 0, 0, 0.45); }
.panel-block { padding: 14px 0; border-top: 1px solid var(--border); }
.panel-block h3 { font-size: 15px; margin: 0 0 4px; }
.field-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 8px 0; }
.field-row input[type="text"], .field-row input[type="password"], .field-row input[type="date"] {
  font: inherit; font-size: 15px; padding: 9px 10px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--surface-0);
  color: var(--text-primary); min-height: 40px; flex: 1; min-width: 120px;
}
.chip.accent { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
a.chip { text-decoration: none; display: inline-flex; align-items: center; }
.code-card {
  margin: 10px 0; padding: 12px; border-radius: 12px; text-align: center;
  background: var(--blue-tint);
  border: 1px solid color-mix(in srgb, var(--blue) 35%, var(--border));
}
.code-card .code {
  font-size: 34px; font-weight: 700; letter-spacing: 0.22em;
  font-family: var(--font-num); font-variant-numeric: tabular-nums; margin: 2px 0 6px;
}
.code-card .link {
  font-size: 12px; color: var(--text-secondary); word-break: break-all; margin-bottom: 8px;
}
.row-actions { display: flex; gap: 6px; align-items: center; margin-left: auto; }
.events .who { color: var(--blue-ink); font-weight: 600; }
.events li .grow { flex: 1; min-width: 0; }
.tag-pill {
  font-size: 11px; padding: 2px 7px; border-radius: 999px;
  background: var(--surface-2); color: var(--text-secondary);
}

/* --- login -------------------------------------------------------------- */
.login { min-height: 80vh; display: grid; place-items: center; }
.login form { background: var(--surface-1); border: 1px solid var(--border); border-radius: var(--radius); padding: 20px; width: 100%; max-width: 340px; box-shadow: var(--shadow); }
.login h1 { font-size: 18px; margin: 0 0 12px; }
.login input {
  width: 100%; padding: 14px; font-size: 16px; border-radius: 12px;
  border: 1px solid var(--border); background: var(--surface-0); color: var(--text-primary);
}
.login button {
  width: 100%; margin-top: 10px; padding: 14px; font-size: 16px; font-weight: 600;
  border: none; border-radius: 12px; background: var(--accent); color: var(--accent-ink); cursor: pointer;
}
.login .bad { color: var(--critical); font-size: 14px; margin: 8px 0 0; }
.muted { color: var(--text-muted); font-size: 13px; }
.skeleton { height: 96px; border-radius: var(--radius); background: var(--surface-2); animation: pulse 1.4s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
