/* ---------------------------------------------------------------------------
   Omnivan – kundportalen (app.omnivan.se)

   Laddas ovanpå omnivan.css och bara när sidan är portalen. Admin styrs av
   omnivan.css; att hålla dem isär i två filer är billigare än att hålla isär
   dem med selektorer som måste vinna över varandra.

   Färgerna står här, inte i omnivan.css: sedan handoffen för värmen
   (docs/design_handoff_omnivan_varme/runda-1-2026-10-29, avsnitt 8, Johans
   beslut 2026-10-29) har portalen en egen, grön palett, medan admin och
   hemsidan behåller havsblått. Paletten skriver över de delade namnen
   (--bg, --sea ...), så att allt i omnivan.css också följer med. --sea heter
   som förut men är portalens accent: grön, "igång" och "valt".

   Målgruppen är husbilsägare, de flesta över 60. Det är därför bastexten är
   18px och ingenting klickbart är under 44px - inte en stilfråga utan skälet
   till att den här designen finns.

   Tema och textstorlek (layout.html, look.go): <html data-theme> är system,
   light eller dark, och <html data-text> är larger eller largest, sparat per
   användare. Admin får inget av attributen, så inget nedan når admin.
   Textstorlekarna är rem, så att data-text skalar all text i portalen, inte
   bara brödtexten.

   Ordning:
     1. Tokens        2. Bas och typografi     3. Ram: header, nav, footer
     4. Kort och rutor                         5. Formulär, knappar, reglage
     6. Sidspecifikt
   --------------------------------------------------------------------------- */

/* --- 1. Tokens ------------------------------------------------------------ */

/* Inter, samma fil som admin och omnivan.se. SIL OFL 1.1, fonts/LICENSE.txt. */
@font-face {
  font-family: "Omnivan Inter";
  src: url("fonts/inter-latin-wght-normal.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* Ljust. Kontrasten för varje par text och yta prövas i look_test.go, i
   båda temana: minst 4,5:1 för text, 3:1 för fokusringen. */
html[data-theme] {
  color-scheme: light;
  --font: "Omnivan Inter", system-ui, -apple-system, "Segoe UI", sans-serif;

  --bg:          #e8eee9;
  --card:        #ffffff;
  --raised:      #e0e8e2; /* upphöjd yta: ett val som inte är valt, en bricka */
  --line:        #c5d1c8;
  --line-strong: #a3b3a8;
  --line-soft:   #dde6df;
  --head:        #f1f5f2;
  --ink:         #16211b;
  --mute:        #4a5a50;
  --sea:         #2f6b4f; /* accenten: igång, valt */
  --sea-dk:      #23523c; /* text på den mjuka accenten, länkar */
  --sea-tint:    #dcebe1; /* den mjuka accenten */
  --on-accent:   #ffffff;
  --warm:        #d8872c; /* loggans signal */
  --warm-lt:     #f0a54e;
  --warm-tint:   #fbefd5; /* varning: yta, text, kant */
  --warm-ink:    #7a4f00;
  --warm-line:   #e2c27a;
  --cold:        #245a80; /* kallt, sommar */
  --cold-tint:   #e0ecf5;
  --ok:          #2f6b4f;
  --ok-tint:     #dcebe1;
  --bad:         #a3182a; /* fel: text, yta, kant */
  --bad-tint:    #fbe7ea;
  --bad-line:    #e8a3ac;
  --bad-row:     #fff8f9;
  --on-bad:      #ffffff;
  --focus:       #c46a22;
  --switch-off:  #7a8a80;
  --knob:        #ffffff;
  --logo-body:   #15283a;
  --logo-signal: #d8872c;
  --shade:       21, 40, 58; /* skuggornas färg, som rgb-tal */
}

/* Mörkt: när användaren valt Mörkt, eller Som telefonen och telefonen är
   mörk. Samma värden två gånger, eftersom CSS inte kan dela ett block mellan
   ett attribut och en mediefråga; look_test.go kontrollerar att de är lika. */
html[data-theme="dark"] {
  color-scheme: dark;
  --bg:          #0f1513;
  --card:        #171f1c;
  --raised:      #202a26;
  --line:        #2e3a35;
  --line-strong: #46554e;
  --line-soft:   #24302b;
  --head:        #1b2420;
  --ink:         #ecf2ee;
  --mute:        #a6b4ac;
  --sea:         #6ccb9a;
  --sea-dk:      #93e0b6;
  --sea-tint:    #183527;
  --on-accent:   #06200f;
  --warm:        #f0a54e;
  --warm-lt:     #f0a54e;
  --warm-tint:   #33280f;
  --warm-ink:    #f2c46b;
  --warm-line:   #6b5420;
  --cold:        #8cc4ee;
  --cold-tint:   #16293a;
  --ok:          #6ccb9a;
  --ok-tint:     #183527;
  --bad:         #ff8a8a;
  --bad-tint:    #3a1a1d;
  --bad-line:    #7a3038;
  --bad-row:     #1e1517;
  --on-bad:      #2a0a0d;
  --focus:       #f0a54e;
  --switch-off:  #6f8076;
  --knob:        #ecf2ee;
  --logo-body:   #ecf2ee;
  --logo-signal: #f0a54e;
  --shade:       0, 0, 0;
}
@media (prefers-color-scheme: dark) {
  html[data-theme="system"] {
    color-scheme: dark;
    --bg:          #0f1513;
    --card:        #171f1c;
    --raised:      #202a26;
    --line:        #2e3a35;
    --line-strong: #46554e;
    --line-soft:   #24302b;
    --head:        #1b2420;
    --ink:         #ecf2ee;
    --mute:        #a6b4ac;
    --sea:         #6ccb9a;
    --sea-dk:      #93e0b6;
    --sea-tint:    #183527;
    --on-accent:   #06200f;
    --warm:        #f0a54e;
    --warm-lt:     #f0a54e;
    --warm-tint:   #33280f;
    --warm-ink:    #f2c46b;
    --warm-line:   #6b5420;
    --cold:        #8cc4ee;
    --cold-tint:   #16293a;
    --ok:          #6ccb9a;
    --ok-tint:     #183527;
    --bad:         #ff8a8a;
    --bad-tint:    #3a1a1d;
    --bad-line:    #7a3038;
    --bad-row:     #1e1517;
    --on-bad:      #2a0a0d;
    --focus:       #f0a54e;
    --switch-off:  #6f8076;
    --knob:        #ecf2ee;
    --logo-body:   #ecf2ee;
    --logo-signal: #f0a54e;
    --shade:       0, 0, 0;
  }
}

/* Textstorleken: Normal, Större och Störst (1, 1,15 och 1,3 i prototypen). */
html[data-text="larger"]  { font-size: 115%; }
html[data-text="largest"] { font-size: 130%; }

.portal {
  --p-bg:        var(--bg);
  --p-card:      var(--card);
  --p-raised:    var(--raised);
  --p-ink:       var(--ink);
  --p-mute:      var(--mute);
  --p-line:      var(--line);
  --p-line-strong: var(--line-strong);
  --p-sea:       var(--sea);
  --p-sea-dk:    var(--sea-dk);
  --p-sea-tint:  var(--sea-tint);
  --p-on-accent: var(--on-accent);
  --p-warm:      var(--warm);
  --p-warm-tint: var(--warm-tint);
  --p-warm-ink:  var(--warm-ink);
  --p-warm-line: var(--warm-line);
  --p-cold:      var(--cold);
  --p-cold-tint: var(--cold-tint);
  --p-focus:     var(--focus);
  --p-ok:        var(--ok);
  --p-ok-tint:   var(--ok-tint);
  --p-bad:       var(--bad);
  --p-bad-tint:  var(--bad-tint);
  --p-bad-line:  var(--bad-line);
  --p-on-bad:    var(--on-bad);
  --p-switch-off:var(--switch-off);
  --p-knob:      var(--knob);

  --p-radius-sm: 10px;
  --p-radius:    12px;
  --p-radius-lg: 16px;
  --p-radius-xl: 18px;

  --p-shadow-card:  0 1px 2px rgba(var(--shade), .04);
  --p-shadow-hover: 0 6px 20px rgba(var(--shade), .08);
  --p-shadow-panel: 0 1px 2px rgba(var(--shade), .06), 0 8px 28px rgba(var(--shade), .08);

  --p-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
}

/* --- 2. Bas och typografi -------------------------------------------------- */
body.portal {
  background: var(--p-bg);
  color: var(--p-ink);
  font-size: 1.125rem;
  line-height: 1.55;
}

.portal a { color: var(--p-sea-dk); }
.portal a:hover { color: var(--p-sea); }

.portal p { margin: 0; }
.portal h1 {
  font-size: clamp(1.75rem, 4.6vw, 2.25rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin: 0;
}
.portal h2 { font-size: 1.3125rem; font-weight: 600; margin: 0; }
.portal h3 { font-size: 1.1875rem; font-weight: 600; margin: 0; }

.portal .lede { font-size: 1.125rem; color: var(--p-mute); margin: 8px 0 0; }
.portal .muted { color: var(--p-mute); }
.portal .bad-text { color: var(--p-bad); font-weight: 600; }
.portal .small { font-size: 1rem; color: var(--p-mute); }
.portal .mono { font-family: var(--p-mono); }

/* Mätvärden och koder sätts med samma breda siffror, så att en kolumn med tal
   inte hoppar i sidled när värdet ändras. */
.portal .figure {
  font-size: 2.25rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

/* Fokusringen är bärnsten, inte havsblå: den ska synas mot både vitt och de
   blå ytorna, och mot en knapp som redan ÄR havsblå. Logotypens mörkare
   bärnsten (--focus), så att den når 3:1 mot alla ljusa ytor. */
.portal :is(button, input, a, summary):focus-visible {
  outline: 3px solid var(--p-focus);
  outline-offset: 2px;
}

/* --- 3. Ram ---------------------------------------------------------------- */
/* Från sida till sida: den nya sidan tonar in över den gamla i stället för att
   blinka vitt, och sidhuvudet står still (samma namn på varje sida). Bara CSS:
   webbläsare utan stöd (Firefox i dag) byter sida som förut. */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .15s; }
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}
.portal .top {
  background: var(--p-card);
  border-bottom: 1px solid var(--p-line);
  view-transition-name: portal-top;
}
.portal .top-inner {
  max-width: 1080px;
  margin: 0 auto;
  padding: 10px clamp(16px, 4vw, 32px);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 20px;
}
.portal .brand {
  display: flex;
  align-items: center;
  min-height: 44px;
  gap: 10px;
  color: var(--p-ink);
  font-size: 1.375rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  text-decoration: none;
}
/* Bilen i bläck, signalen i bärnsten - samma märke som hemsidan, men
   portalens färger. */
:is(.portal .brand, .portal .entry-brand) .logo-body { stroke: var(--logo-body); }
:is(.portal .brand, .portal .entry-brand) .logo-signal { stroke: var(--logo-signal); }
:is(.portal .brand, .portal .entry-brand) .logo-dot { fill: var(--logo-signal); }

.portal nav { display: flex; flex-wrap: wrap; gap: 8px; }
.portal nav a {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  padding: 0 16px;
  border-radius: var(--p-radius-sm);
  font-size: 1.0625rem;
  color: var(--p-ink);
  text-decoration: none;
}
.portal nav a:hover { background: var(--p-bg); }
.portal nav a.on {
  background: var(--p-sea-tint);
  color: var(--p-sea-dk);
  font-weight: 600;
}
.portal .spacer { flex: 1 1 auto; }
/* Profilikonen leder till kontot. Rund, och lika hög som menyns poster. */
.portal .whoami {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--p-line);
  border-radius: 50%;
  color: var(--p-mute);
  text-decoration: none;
}
.portal .whoami:hover { background: var(--p-bg); color: var(--p-ink); }
.portal .whoami[aria-current] { background: var(--p-sea-tint); border-color: transparent; color: var(--p-sea-dk); }
/* "Mitt konto" i ord där det finns plats; på en smal skärm bara ikonen, och
   orden kvar för skärmläsaren (docs/plan/begriplig-portal.md). */
.portal .whoami-text {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
@media (min-width: 900px) {
  .portal .whoami { width: auto; gap: 8px; padding: 0 16px 0 12px; border-radius: 22px; font-size: 1.0625rem; }
  .portal .whoami-text { position: static; width: auto; height: auto; overflow: visible; clip: auto; }
}

.portal main {
  max-width: 1080px;
  margin: 0 auto;
  padding: clamp(24px, 4vw, 44px) clamp(16px, 4vw, 32px) 56px;
}
.portal main.narrow { max-width: 640px; }
.portal main.mid { max-width: 760px; }

.portal footer {
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 clamp(16px, 4vw, 32px) 40px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  font-size: 0.875rem;
  color: var(--p-mute);
}
/* Sidfotens länkar är tryckytor som alla andra: 44 px höga (H10). */
.portal footer a { display: inline-flex; align-items: center; min-height: 44px; }

/* Besked. Samma form för bra och dåliga nyheter, olika färg - en som inte
   läser texten ska ändå se vilket det är. */
.portal .msg {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  border: 0;
  border-radius: var(--p-radius);
  padding: 14px 18px;
  margin: 0 0 24px;
  font-weight: 500;
}
/* En plats för ett meddelande som ett skript fyller (elcentralens panel):
   tom är den dold, också fast .msg är flex. */
.portal .msg[hidden] { display: none; }
.portal .msg.ok  { background: var(--p-ok-tint);  color: var(--p-ok); }
.portal .msg.bad { background: var(--p-bad-tint); color: var(--p-bad); }
.portal .msg svg { flex: none; margin-top: 2px; }

/* --- 4. Kort och rutor ----------------------------------------------------- */
.portal .card {
  background: var(--p-card);
  border: 1px solid var(--p-line);
  border-radius: var(--p-radius-lg);
  padding: 20px;
  box-shadow: var(--p-shadow-card);
}
.portal a.card { display: block; color: inherit; text-decoration: none; }
.portal a.card:hover { border-color: var(--p-sea); box-shadow: var(--p-shadow-hover); }

/* Formulärkort: mjukare hörn och en tydligare skugga, för de sidor som är en
   enda uppgift och inget annat. */
.portal .panel {
  background: var(--p-card);
  border-radius: var(--p-radius-xl);
  padding: clamp(24px, 5vw, 36px);
  box-shadow: var(--p-shadow-panel);
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.portal .stack { display: flex; flex-direction: column; gap: 24px; }
.portal .row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }

.portal .grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  gap: 16px;
}

/* --- 5. Formulär, knappar, reglage ----------------------------------------- */
.portal label { display: block; font-size: 1.125rem; font-weight: 500; color: var(--p-ink); margin-bottom: 6px; }
.portal .field { display: flex; flex-direction: column; }
.portal .hint { font-size: 1rem; color: var(--p-mute); margin: 8px 0 0; }

.portal :is(input[type="text"], input[type="email"], input[type="password"], input[type="number"], input[type="tel"]) {
  width: 100%;
  min-height: 56px;
  padding: 0 16px;
  border: 1.5px solid var(--p-line);
  border-radius: var(--p-radius);
  background: var(--p-card);
  color: var(--p-ink);
  font: inherit;
}
.portal :is(textarea, select) {
  width: 100%;
  min-height: 56px;
  padding: 14px 16px;
  border: 1.5px solid var(--p-line);
  border-radius: var(--p-radius);
  background: var(--p-card);
  color: var(--p-ink);
  font: inherit;
}
.portal textarea { resize: vertical; line-height: 1.5; }
.portal :is(input, textarea, select):hover { border-color: var(--p-line-strong); }
/* The contact form's honeypot: out of sight and out of the tab order, but in
   the page, where a bot filling every field finds it. */
.portal .trap { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.portal input.code {
  min-height: 60px;
  font-family: var(--p-mono);
  font-size: 1.375rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.portal .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 56px;
  padding: 0 24px;
  border: 0;
  border-radius: var(--p-radius);
  background: var(--p-sea);
  color: var(--p-on-accent);
  font: inherit;
  font-size: 1.1875rem;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
}
.portal .btn:hover { background: var(--p-sea-dk); color: var(--p-on-accent); }
.portal .btn.wide { width: 100%; }

.portal .btn.outline {
  min-height: 52px;
  font-size: 1.125rem;
  background: transparent;
  border: 1.5px solid var(--p-sea);
  color: var(--p-sea-dk);
}
.portal .btn.outline:hover { background: var(--p-sea-tint); color: var(--p-sea-dk); }

.portal .btn.quiet {
  min-height: 44px;
  padding: 0 16px;
  font-size: 1rem;
  font-weight: 500;
  background: var(--p-card);
  border: 1.5px solid var(--p-line);
  color: var(--p-ink);
}
.portal .btn.quiet:hover { border-color: var(--p-sea); background: var(--p-card); color: var(--p-ink); }

.portal .btn.danger {
  background: var(--p-card);
  border: 1.5px solid var(--p-bad);
  color: var(--p-bad);
}
.portal .btn.danger:hover { background: var(--p-bad); color: var(--p-on-bad); }
.portal .btn.danger.filled { background: var(--p-bad); color: var(--p-on-bad); }

.portal .back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  font-size: 1.0625rem;
  color: var(--p-sea-dk);
  text-decoration: none;
}
.portal .back:hover { text-decoration: underline; }

/* Reglaget är en vanlig kryssruta.
   Den postar med formuläret som vilken kryssruta som helst, behåller
   tangentbord och skärmläsare, och kräver inget JavaScript - vilket CSP:n
   ändå inte hade tillåtit inline. */
.portal .switch {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  width: 68px;
  height: 40px;
  padding: 4px;
  border: 0;
  border-radius: 20px;
  background: var(--p-switch-off);
  cursor: pointer;
  transition: background .2s;
  position: relative;
  min-height: 0;
  margin: 0;
}
.portal .switch::before {
  content: "";
  position: absolute;
  top: 4px;
  left: 4px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--p-knob);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .2);
  transition: transform .2s;
}
.portal .switch:checked { background: var(--p-sea); }
.portal .switch:checked::before { transform: translateX(28px); }
/* På eller Av framför reglaget (partials.html, switch-word): läget i ord, inte
   bara i färg. Ordet följer kryssrutan, utan skript. */
.portal .switch-word {
  flex: none; min-width: 2em; text-align: right; font-size: 1rem; font-weight: 600; line-height: 40px; color: var(--p-mute);
}
.portal .switch-word:has(+ .switch:checked) { color: var(--p-sea-dk); }
.portal .switch-word:has(+ .switch:checked) .off,
.portal .switch-word:not(:has(+ .switch:checked)) .on { display: none; }

/* Val av tystnadsgräns. Radioknappar som ser ut som knappar, så att träffytan
   är hela rutan och inte en prick på 16px. */
.portal .choices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 8px;
}
.portal .choice {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  border: 1.5px solid var(--p-line);
  border-radius: var(--p-radius);
  background: var(--p-card);
  font-size: 1.0625rem;
  cursor: pointer;
}
.portal .choice input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.portal .choice:has(input:checked) {
  border: 2px solid var(--p-sea);
  background: var(--p-sea-tint);
  color: var(--p-sea-dk);
  font-weight: 600;
}
.portal .choice:has(input:focus-visible) { outline: 3px solid var(--p-focus); outline-offset: 2px; }

/* Utseende och text (konto-utseende.html): bocken på det valda, så att valet
   inte bara syns i färg, och varje textstorlek skriven i sin egen storlek. */
/* En rad per val, så att Som telefonen och Störst får plats med bocken. */
.portal .look-choices { grid-template-columns: 1fr; }
.portal .look-choices .choice { justify-content: flex-start; gap: 10px; padding: 8px 16px; }
.portal .look-tick { display: inline-flex; flex: none; visibility: hidden; }
.portal .choice:has(input:checked) .look-tick { visibility: visible; }
.portal .look-size-normal  { font-size: 1rem; }
.portal .look-size-larger  { font-size: 1.15rem; }
.portal .look-size-largest { font-size: 1.3rem; }

/* --- 6. Sidspecifikt ------------------------------------------------------- */

/* Inloggning och registrering: en uppgift, mitt på sidan. */
.portal main.entry {
  max-width: 440px;
  display: flex;
  flex-direction: column;
  gap: 28px;
  padding-top: clamp(32px, 8vh, 72px);
}
.portal .entry-brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  font-size: 1.875rem;
  font-weight: 600;
  letter-spacing: -0.03em;
}

/* Statusraden under lådans namn. */
.portal .status {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 10px;
  margin-top: 10px;
  font-size: 1.1875rem;
  font-weight: 500;
}
.portal .status .since { font-size: 1rem; font-weight: 400; color: var(--p-mute); }
.portal .dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  align-self: center;
}
.portal .status.up   { color: var(--p-ok); }
.portal .status.up   .dot { background: var(--p-ok);   box-shadow: 0 0 0 5px var(--p-ok-tint); }
.portal .status.down { color: var(--p-bad); }
.portal .status.down .dot { background: var(--p-bad);  box-shadow: 0 0 0 5px var(--p-bad-tint); }
.portal .status.idle { color: var(--p-mute); }
.portal .status.idle .dot { background: var(--p-mute); box-shadow: 0 0 0 5px var(--p-line); }

/* Lådbannern på översikten. */
.portal .banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 20px;
  background: var(--p-sea-tint);
  border-radius: var(--p-radius-lg);
  padding: 18px 22px;
}
.portal .banner .tile {
  flex: none;
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 14px;
  background: var(--p-card);
  color: var(--p-sea);
}
.portal .banner .what { flex: 1 1 260px; }
.portal .banner .what strong { font-weight: 600; }
.portal .banner .what .meta { font-size: 1rem; color: var(--p-mute); }

/* Mätvärden. */
.portal .reading .label { font-size: 1rem; color: var(--p-mute); }
.portal .reading .age { font-size: 1rem; color: var(--p-mute); margin-top: 4px; }
.portal .reading.stale .figure { color: var(--p-mute); }
.portal .reading.stale .age { color: var(--p-warm-ink); font-weight: 600; }

/* Tystnadsvakten får en bärnstensram. Den är produktens kärna, och den ska
   se ut som något annat än en rad i en lista. */
.portal .watchcard {
  background: var(--p-card);
  border: 2px solid var(--p-warm);
  border-radius: var(--p-radius-lg);
  padding: 22px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.portal .watchcard .head { display: flex; align-items: flex-start; gap: 16px; }
.portal .watchcard .tile {
  flex: none;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 14px;
  background: var(--p-warm-tint);
  color: var(--p-warm-ink);
}
.portal .watchcard .head .what { flex: 1 1 auto; }
/* Larmkortet på en telefon: rubriken behåller raden, och ordet och reglaget
   går ned under den, till höger. */
@media (max-width: 520px) {
  .portal .watchcard .head { flex-wrap: wrap; }
  .portal .watchcard .head .what { flex: 1 1 calc(100% - 80px); }
  .portal .watchcard .head .switch-word { margin-left: auto; }
}
.portal hr.rule { border: 0; border-top: 1px solid var(--p-line); margin: 0; }

/* Frikoppling. Röd ruta, för det är den enda handlingen på sidan som inte går
   att ångra utan att koden på lådan byts. */
.portal .danger-zone {
  background: var(--p-bad-tint);
  border-radius: var(--p-radius-lg);
  padding: 22px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.portal .danger-zone h2 { color: var(--p-bad); }

/* Numrerade steg på inkopplingssidan. */
.portal .steps { display: flex; flex-direction: column; gap: 18px; margin: 0; padding: 0; list-style: none; }
.portal .steps li { display: flex; align-items: flex-start; gap: 14px; }
.portal .steps .n {
  flex: none;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--p-sea);
  color: var(--p-on-accent);
  font-weight: 600;
  font-size: 1.0625rem;
}

/* --- Detaljer som kom med vyerna ------------------------------------------ */

/* Ett kort som staplar sitt innehåll står tätare än sidans egen stapel: 24px
   mellan två kort är en paus, 24px inuti ett kort ser ut som ett misstag. */
.portal .card.stack { gap: 14px; }
.portal .card h2 + .muted { margin-top: -4px; }

/* Mätvärdeskortet: etikett, siffra, ålder - i den ordningen och tätt ihop. */
.portal .reading .figure { margin-top: 6px; }

/* Rubriken över en radiogrupp är ingen <label>, eftersom den inte pekar på ett
   enskilt fält. Den ska ändå se ut som en. */
.portal .field > .label {
  display: block;
  font-size: 1.125rem;
  font-weight: 500;
  color: var(--p-ink);
  margin-bottom: 6px;
}

/* Raden under "Omnivan-lådan" är flera <span> i en <span>. */
.portal .banner .what .meta { display: block; margin-top: 4px; }
.portal .watchcard .head .what .muted { margin-top: 6px; }

/* Punktlistan i frikopplingsrutan. */
.portal .danger-zone ul { margin: 0; padding-left: 22px; display: flex; flex-direction: column; gap: 6px; }
.portal .danger-zone li { font-size: 1.0625rem; }

/* Ikonen framför e-postadressen ska inte tryckas ihop av flexraden. */
.portal .row > svg { flex: none; color: var(--p-mute); }

/* --- Prylar (fas 3) ---------------------------------------------------------- */

/* Rubrikraden på översikten: namnet till vänster, "Lägg till pryl" till höger,
   och under varandra när det inte får plats. */
.portal .titlerow {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px 24px;
}
.portal .row.between { justify-content: space-between; }
.portal .stack.tight { gap: 12px; }
.portal .found { font-size: 1.1875rem; font-weight: 500; }

/* Ikonplattan. Bärnstenstonad, som i designen: prylarna är det varma på sidan,
   lådan det blå. */
.portal .gadget .tile,
.portal .hit .tile,
.portal .gadget-head .tile {
  flex: none;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 14px;
  background: var(--p-warm-tint);
  color: var(--p-warm-ink);
}
.portal .gadget-head .tile.big { width: 64px; height: 64px; border-radius: 18px; }

/* Prylkortet. */
.portal .card.gadget { display: flex; flex-direction: column; gap: 10px; }
.portal .gadget .head { display: flex; align-items: center; gap: 14px; }
.portal .gadget .what { display: flex; flex-direction: column; min-width: 0; }
.portal .gadget .name { font-size: 1.1875rem; font-weight: 600; }
.portal .gadget .maker { font-size: 1rem; color: var(--p-mute); }
.portal .gadget .figure { font-size: 2.125rem; margin-top: 4px; }
.portal .gadget .figure.stale,
.portal .gadget .figure.none { color: var(--p-mute); }
.portal .gadget .sub { font-size: 1rem; color: var(--p-mute); }
.portal .gadget .foot {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  padding-top: 12px;
  border-top: 1px solid var(--p-line);
  font-size: 1rem;
  color: var(--p-mute);
}
.portal .gadget .foot .dot { width: 8px; height: 8px; }
.portal .dot.ok  { background: var(--p-ok); }
.portal .dot.bad { background: var(--p-bad); }
.portal .card.gadget.lost { border-color: var(--p-bad); }

/* Sista rutan i rutnätet: streckad, och hela rutan är länken. */
.portal a.card.add {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 180px;
  border: 2px dashed var(--p-line);
  background: transparent;
  box-shadow: none;
  color: var(--p-sea-dk);
  font-weight: 600;
}
.portal a.card.add:hover { border-color: var(--p-sea); background: var(--p-sea-tint); }

/* Ett skanningsresultat: ikon, vad det är, knapp. */
.portal .card.hit {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 16px;
}
.portal .hit .what { flex: 1 1 220px; display: flex; flex-direction: column; }
.portal .hit .maker { font-size: 1rem; color: var(--p-mute); }
.portal .card.hit.done { background: var(--p-bg); }
/* En pryl som lådan hittade men som inte är upplåst (catalog/plugins.go):
   ingen knapp, och läget i ord med ett hänglås. */
.portal .card.hit.locked { background: var(--p-bg); border-style: dashed; }
.portal .lock-note { display: inline-flex; align-items: center; gap: 8px; margin: 0; font-size: 1rem; font-weight: 600; color: var(--p-mute); }

/* Medan lådan letar. Snurran är ren CSS; den som inte vill ha rörelse får en
   stilla ring. */
.portal .card.searching {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 1.1875rem;
  font-weight: 500;
}
.portal .spinner {
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 3px solid var(--p-sea-tint);
  border-top-color: var(--p-sea);
  animation: p-spin 1s linear infinite;
}
@keyframes p-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .portal .spinner { animation: none; }
}

/* Tips och "syns inte din pryl?": gul ruta, som i designen. */
.portal .tip {
  background: var(--p-warm-tint);
  border-radius: var(--p-radius-lg);
  padding: 18px 22px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}

/* Förloppet i parningsguiden: fyra segment, 6px. */
.portal .progress {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.portal .progress li { height: 6px; border-radius: 3px; background: var(--p-line); }
.portal .progress li.on { background: var(--p-sea); }

/* Pryldetaljen. */
.portal .gadget-head { display: flex; align-items: flex-start; gap: 18px; }
/* Ett långt namn, "Luftkonditioneringen", bryts vid större text i stället
   för att skjuta sidan i sidled (H10). */
.portal .gadget-head > div { min-width: 0; }
.portal .gadget-head h1 { overflow-wrap: anywhere; hyphens: auto; }
.portal .gadget-head .lede { margin-top: 4px; }

.portal .control {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 20px;
  padding-top: 14px;
  border-top: 1px solid var(--p-line);
}
.portal .control:first-of-type { border-top: 0; padding-top: 0; }
.portal .control .what { display: flex; flex-direction: column; }
.portal .control .hint { flex-basis: 100%; margin: 0; }
.portal input.setpoint { width: 110px; min-height: 52px; text-align: center; font-size: 1.25rem; }

/* Grafen. Linjen och ytan färgas här, inte i SVG:n, så att CSP:n kan stå
   kvar utan inline-stilar. */
/* The day's chart, drawn by frontend/src/charts.ts with uPlot. The box keeps its
   height before the script runs, so the page does not jump. */
.portal .chart { width: 100%; min-height: 220px; }
.portal .chart-pick { display: flex; flex-wrap: wrap; gap: 8px; }
.portal .chart-pick:empty { display: none; }
.portal .chart-pick .btn { min-height: 44px; padding: 0 16px; font-size: 1rem; }
.portal .chart-pick button[aria-pressed="true"] { background: var(--p-sea); border-color: var(--p-sea); color: var(--p-on-accent); }
.portal .chart-readout { min-height: 1.4em; margin: 0; color: var(--p-mute); }
.portal .chart-range { margin: 0; padding-left: 1.1em; color: var(--p-mute); }
.portal .chart .u-over { cursor: crosshair; }

/* Synlig bara för skärmläsare: fältet har en rubrik ovanför sig i kortet. */
.portal .sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* --- Energi just nu (enhet.html) ------------------------------------------
   The battery large on the left, sun and charger beside it; one column on a
   phone. Big type: this is the number people come for. */
.portal .hero {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: 16px 28px;
  padding: 24px 28px;
  border-radius: var(--p-radius-lg);
  background: var(--p-card);
  box-shadow: var(--p-shadow-panel);
}
.portal .hero.stale { opacity: .7; }
.portal .hero .label { margin: 0; color: var(--p-mute); font-size: 1rem; font-weight: 600; }
.portal .hero-soc { margin: 2px 0 8px; font-size: 4rem; line-height: 1; font-weight: 700; font-variant-numeric: tabular-nums; }
.portal .hero meter { width: 100%; height: 14px; }
.portal .hero-flow { margin: 12px 0 0; font-size: 1.25rem; font-weight: 600; }
.portal .hero-flow.charging { color: var(--p-ok); }
.portal .hero-lasts { margin: 4px 0 0; font-size: 1.125rem; color: var(--p-ink); }
.portal .hero-side { display: grid; gap: 14px; align-content: start; }
.portal .hero-item .figure { margin: 2px 0 0; font-size: 1.75rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.portal .hero-item .small { margin: 2px 0 0; color: var(--p-mute); }
.portal .hero-age { grid-column: 1 / -1; margin: 0; color: var(--p-mute); }
@media (max-width: 640px) {
  .portal .hero { grid-template-columns: 1fr; padding: 20px; }
  .portal .hero-soc { font-size: 3.25rem; }
}

/* What became of the last control command (enhet-pryl.html). */
.portal .command-result p { margin: 0; }
.portal .command-result p + p { margin-top: 4px; }
.portal .command-result.ok { border-left: 4px solid var(--p-ok); }
.portal .command-result.bad { border-left: 4px solid var(--p-bad); }
.portal .control .note { margin: 8px 0 0; padding: 10px 12px; border-radius: var(--p-radius-sm);
  background: var(--p-warm-tint); color: var(--p-warm-ink); font-weight: 600; }

/* --- Märkesbrickan (designrunda 2) ------------------------------------------
   The manufacturer's monogram on a colour of the portal's own - a placeholder
   within "no manufacturer logos". Radius 30 % and text 40 % of the side. The
   classes come from web/icons.go (brandChip); the colour from the catalogue. */
.portal .pi { display: block; flex: none; }
.portal .brand-chip {
  display: inline-grid; place-items: center; flex: none;
  color: #fff; font-weight: 700; letter-spacing: -0.02em; line-height: 1;
}
.portal .brand-chip.bs-22 { width: 22px; height: 22px; border-radius: 7px; font-size: 0.5625rem; }
.portal .brand-chip.bs-24 { width: 24px; height: 24px; border-radius: 7px; font-size: 0.625rem; }
.portal .brand-chip.bs-26 { width: 26px; height: 26px; border-radius: 8px; font-size: 0.625rem; }
.portal .brand-chip.bs-28 { width: 28px; height: 28px; border-radius: 8px; font-size: 0.6875rem; }
.portal .brand-chip.bs-32 { width: 32px; height: 32px; border-radius: 10px; font-size: 0.8125rem; }
.portal .brand-chip.bs-36 { width: 36px; height: 36px; border-radius: 11px; font-size: 0.875rem; }
/* The manufacturer's own symbol, on white, where its logo has one (static/
   brands/README.md). The monogram is still in the markup for the brands that
   have none, and for those that do it is hidden rather than removed. */
.portal .brand-chip.brand-victron, .portal .brand-chip.brand-dometic,
.portal .brand-chip.brand-truma, .portal .brand-chip.brand-ruuvi, .portal .brand-chip.brand-wattcycle,
.portal .brand-chip.brand-oria, .portal .brand-chip.brand-sargent {
  background-color: #fff; background-repeat: no-repeat; background-position: center;
  box-shadow: inset 0 0 0 1px var(--p-line); color: transparent; font-size: 0;
}
.portal .brand-chip.brand-victron { background-image: url("brands/victron-mark.svg"); background-size: 78% auto; }
.portal .brand-chip.brand-dometic { background-image: url("brands/dometic-mark.png"); background-size: 62% auto; }
.portal .brand-chip.brand-truma   { background-image: url("brands/truma-mark.svg"); background-size: 74% auto; }
.portal .brand-chip.brand-ruuvi   { background-image: url("brands/ruuvi-mark.png"); background-size: 70% auto; }
.portal .brand-chip.brand-wattcycle { background-image: url("brands/wattcycle-mark.png"); background-size: 76% auto; }
.portal .brand-chip.brand-sargent { background-image: url("brands/sargent-mark.svg"); background-size: 80% auto; }
/* Not ORIA's logo - none was found - but our drawing of the puck itself. */
.portal .brand-chip.brand-oria { background-image: url("brands/oria-mark.svg"); background-size: 88% auto; }
/* No symbol of their own: the monogram, in the colour of their logo. */
.portal .brand-epever  { background: #0462ce; }
.portal .brand-mopeka  { background: #3ab047; }
.portal .brand-omnivan { background: var(--warm); }
.portal .brand-unknown { background: var(--mute); }
.portal .gadget .maker { display: inline-flex; align-items: center; gap: 7px; }

/* --- Översikten (designrunda 2, vy 1) --------------------------------------- */
.portal .ov { gap: 24px; }
.portal .ov-head h1 { margin: 0; }
.portal .ov-summary { margin: 10px 0 0; font-size: 1.375rem; line-height: 1.4; max-width: 34em; text-wrap: pretty; }
.portal .ov-summary strong { font-weight: 700; }
.portal .ov-summary .bad { color: var(--p-bad); font-weight: 600; }
.portal .ov-statusrow { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 20px; margin-top: 12px; }
.portal .ov-statusrow .status { margin: 0; }
.portal .ov-settings { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; font-size: 1.0625rem; font-weight: 600; }

.portal .brandrow {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px 28px;
  padding: 18px 22px; border-radius: var(--p-radius-lg); background: var(--p-sea-tint);
}
.portal .brandrow-title { flex: 0 1 260px; }
.portal .brandrow-title .t { font-size: 1.1875rem; font-weight: 600; }
.portal .brandrow-title .s { font-size: 1rem; color: var(--p-mute); }
.portal .brandrow-items { flex: 1 1 480px; display: flex; flex-wrap: wrap; gap: 8px; }
.portal .brandrow-item {
  display: inline-flex; align-items: center; gap: 10px; min-height: 48px; padding: 0 14px 0 8px;
  border-radius: var(--p-radius); background: var(--p-card); font-size: 1rem;
}
.portal .brandrow-item .n { font-weight: 600; }
.portal .brandrow-item .c { color: var(--p-mute); }

.portal .ov-gadgets { display: flex; flex-direction: column; gap: 12px; }
.portal .ov-gadgets-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; }
.portal .ov-gadgets-head h2 { margin: 0; }
.portal .ov-gadgets-head h2 .muted { font-weight: 400; }
.portal .fgroups { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); gap: 16px; }
.portal .fgroup {
  display: flex; flex-direction: column; padding: 16px 18px;
  border-radius: var(--p-radius-lg); border: 1px solid var(--p-line); background: var(--p-card);
}
.portal .fgroup-head { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; font-size: 1rem; font-weight: 600; color: var(--p-mute); }
.portal .frow {
  display: flex; align-items: center; gap: 12px; min-height: 48px;
  border-top: 1px solid var(--line-soft); color: var(--p-ink); text-decoration: none; font-size: 1.0625rem;
}
.portal .fgroup-head + .frow { border-top: 0; }
.portal .frow:hover { color: var(--p-sea-dk); }
.portal .frow .name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.portal .frow .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--p-ok); flex: none; }
.portal .frow .value { font-size: 1.125rem; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.portal .frow.quiet, .portal .frow.quiet:hover { color: var(--p-bad); }
.portal .frow.quiet .dot { background: var(--p-bad); }

/* <details> as a card: the collapsed parts of design round 2. */
.portal details.card > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 64px; margin: -4px 0; cursor: pointer; list-style: none; font-size: 1.3125rem; font-weight: 600;
}
.portal details.card > summary::-webkit-details-marker { display: none; }
.portal details.card > summary .muted { font-size: 1rem; font-weight: 400; }
.portal .detail-rows { display: flex; flex-direction: column; margin-top: 8px; }
.portal .detail-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 16px; align-items: baseline;
  min-height: 48px; padding: 8px 0; border-top: 1px solid var(--line-soft);
}
.portal .detail-row .v { font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
.portal .detail-row .a { grid-column: 1 / -1; font-size: 0.875rem; color: var(--p-mute); }
.portal .detail-row.stale .v { color: var(--p-warm-ink); }

/* --- En pryl (designrunda 2, vy 2) ------------------------------------------ */
.portal .gp { gap: 24px; }
.portal .gp-maker { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin: 6px 0 0; color: var(--p-mute); }
.portal .gp-maker strong { color: var(--p-ink); font-weight: 600; }
.portal .gp-panel {
  display: flex; flex-direction: column; gap: 18px; padding: 28px;
  border-radius: var(--p-radius-xl); background: var(--p-card); box-shadow: var(--p-shadow-panel);
}
.portal .gp-panel.stale .gp-big { color: var(--p-mute); }
.portal .gp-state { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 16px 24px; }
.portal .gp-label { margin: 0; color: var(--p-mute); font-size: 1rem; font-weight: 600; }
.portal .gp-big { margin: 2px 0 0; font-size: 3.25rem; line-height: 1.05; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.portal .gp-sub { margin: 6px 0 0; font-size: 1.1875rem; font-weight: 500; }
.portal .gp-toggle { margin: 0; }
.portal .btn.big { min-height: 60px; padding: 0 28px; font-size: 1.25rem; gap: 10px; }
.portal .gp-panel .msg { display: flex; align-items: center; gap: 10px; margin: 0; padding: 12px 16px; border-radius: var(--p-radius); background: var(--p-bg); font-weight: 500; }
.portal .gp-panel .msg.ok { background: var(--p-ok-tint); color: var(--p-ok); }
.portal .gp-panel .msg.bad { background: var(--p-bad-tint); color: var(--p-bad); }
.portal .gp-notice { border-radius: var(--p-radius); background: var(--p-warm-tint); color: var(--p-warm-ink); }
.portal .gp-notice summary { display: flex; align-items: center; gap: 10px; min-height: 52px; padding: 0 16px; font-weight: 600; cursor: pointer; list-style: none; }
.portal .gp-notice summary::-webkit-details-marker { display: none; }
.portal .gp-notice summary span { flex: 1; }
.portal .gp-notice p { margin: 0; padding: 0 16px 16px 46px; font-size: 1.0625rem; color: var(--p-ink); }
/* What admin has written about the model (gadgetinfo.go): the info icon under
   the heading, folded like the notice above but in the sea's colour. */
.portal .gp-info { border-radius: var(--p-radius); background: var(--p-sea-tint); color: var(--p-sea-dk); }
.portal .gp-info summary { display: flex; align-items: center; gap: 10px; min-height: 52px; padding: 0 16px; font-weight: 600; cursor: pointer; list-style: none; }
.portal .gp-info summary::-webkit-details-marker { display: none; }
.portal .gp-info summary span { flex: 1; }
.portal .gp-info[open] summary > svg:last-child { transform: rotate(180deg); }
.portal .gp-info-body { padding: 0 16px 16px 48px; font-size: 1.0625rem; color: var(--p-ink); }
.portal .gp-info-body p, .portal .gp-info-body ul { margin: 0 0 10px; }
.portal .gp-info-body > :last-child { margin-bottom: 0; }
.portal .gp-info-body ul { padding-left: 20px; }
.portal .gp-setter { display: flex; flex-direction: column; gap: 6px; }
/* Ett val bland några lägen (luftkonditioneringens): läget i ord, och en knapp per läge. */
.portal .gp-choice { display: flex; flex-direction: column; gap: 6px; }
.portal .gp-choice-head { display: flex; justify-content: space-between; gap: 12px; margin: 0; }
.portal .gp-choice-label { font-weight: 600; }
.portal .gp-choice-state { color: var(--p-mute); text-align: right; }
.portal .gp-choice-picks {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 4px; padding: 4px;
  border-radius: 14px; background: var(--line-soft);
}
.portal .gp-keys { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr)); gap: 12px; }
.portal .gp-key { padding: 16px 18px; border-radius: var(--p-radius-lg); border: 1px solid var(--p-line); background: var(--p-card); }
.portal .gp-key .k { margin: 0; font-size: 1rem; color: var(--p-mute); }
.portal .gp-key .v { margin: 0; font-size: 1.75rem; font-weight: 700; line-height: 1.2; font-variant-numeric: tabular-nums; }
.portal .gp-key.stale .v { color: var(--p-mute); }
.portal .gp-name { margin-top: 12px; }
@media (max-width: 640px) {
  .portal .gp-toggle, .portal .gp-toggle .btn { width: 100%; }
  .portal .gp-big { font-size: 2.75rem; }
}

/* Senaste dygnet på översikten: sparklines drawn on the server (daychart.go). */
.portal .ov-cards { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-start; }
.portal .ov-day {
  flex: 2 1 540px; min-width: 0; display: flex; flex-direction: column; gap: 14px; padding: 24px;
  border-radius: var(--p-radius-lg); background: var(--p-card); box-shadow: var(--p-shadow-panel);
}
.portal .ov-day-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 8px 16px; }
.portal .ov-day-head h2 { margin: 0; }
.portal .ov-day-head .muted { font-size: 1rem; }
.portal .spark-row {
  display: grid; grid-template-columns: minmax(110px, 150px) minmax(0, 1fr); gap: 16px; align-items: center;
  padding-top: 12px; border-top: 1px solid var(--line-soft);
}
.portal .spark-axis { border-top: 0; padding-top: 0; }
.portal .spark-name { display: flex; align-items: center; gap: 8px; font-size: 1rem; color: var(--p-mute); }
.portal .spark-now { font-size: 1.625rem; font-weight: 700; line-height: 1.15; font-variant-numeric: tabular-nums; }
.portal .spark-range { font-size: 0.875rem; color: var(--p-mute); }
.portal .spark { width: 100%; height: 80px; display: block; overflow: visible; }
.portal .spark .line { fill: none; stroke-width: 2.5; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.portal .spark-sea .line { stroke: var(--p-sea); }  .portal .spark-sea .area { fill: var(--p-sea-tint); }
.portal .spark-warm .line { stroke: var(--p-warm); } .portal .spark-warm .area { fill: var(--p-warm-tint); }
.portal .spark-ok .line { stroke: var(--p-ok); }    .portal .spark-ok .area { fill: var(--p-ok-tint); }
.portal .spark-axis .ticks { display: flex; justify-content: space-between; font-size: 0.875rem; color: var(--p-mute); }
.portal .chart-pick .btn.compare { gap: 8px; border-style: dashed; border-color: var(--p-line); color: var(--p-ink); background: transparent; font-weight: 500; }
.portal .chart-pick .btn.compare[aria-pressed="true"] { border-color: var(--p-warm); background: var(--p-warm-tint); color: var(--p-ink); }

/* Det här har hänt (happened.go): tid i en smal kolumn, text bredvid. */
.portal .ov-log {
  flex: 1 1 300px; min-width: 0; display: flex; flex-direction: column; gap: 4px; padding: 24px;
  border-radius: var(--p-radius-lg); border: 1px solid var(--p-line); background: var(--p-card);
}
.portal .ov-log h2 { margin: 0 0 8px; }
.portal .happened { list-style: none; margin: 0; padding: 0; }
.portal .happened li {
  display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 12px; padding: 10px 0;
  border-top: 1px solid var(--line-soft); font-size: 1.0625rem;
}
.portal .happened time { font-size: 1rem; color: var(--p-mute); font-variant-numeric: tabular-nums; }
.portal .happened a { color: inherit; text-decoration: none; }
.portal .happened a:hover { text-decoration: underline; }
.portal .happened li.bad span, .portal .happened li.bad a { color: var(--p-bad); font-weight: 600; }
.portal .ov-log-all { margin-top: 6px; display: inline-flex; align-items: center; min-height: 44px; font-size: 1.0625rem; font-weight: 600; }
.portal .ov-log-page .happened li { grid-template-columns: 110px minmax(0, 1fr); }
.portal .spark-axis .ticks span { white-space: nowrap; }
@media (max-width: 520px) {
  .portal .ov-day { padding: 20px 16px; }
  .portal .spark-row { grid-template-columns: 110px minmax(0, 1fr); gap: 12px; }
  .portal .spark-now { font-size: 1.375rem; }
  .portal .spark-range { font-size: 0.8125rem; }
  .portal .spark-axis .ticks span:nth-child(2), .portal .spark-axis .ticks span:nth-child(4) { display: none; }
}

/* A manufacturer's logo in full (icons.go, brandLogo). The height is set in
   the markup; the width follows. */
.portal .brand-logo { display: block; max-width: 100%; height: auto; }
/* Tillverkarnas ordmärken är ritade för en ljus botten. I mörkt läge får de
   en vit platta, som märkesbrickorna har. */
html[data-theme="dark"] .portal .brand-logo { padding: 3px 6px; border-radius: 6px; background: #fff; }
@media (prefers-color-scheme: dark) {
  html[data-theme="system"] .portal .brand-logo { padding: 3px 6px; border-radius: 6px; background: #fff; }
}
.portal footer .trademarks { flex-basis: 100%; font-size: 0.875rem; }

/* Larmsidan (alarms.go): Just nu, och reglerna per funktion. */
.portal .nowcard {
  display: flex; align-items: flex-start; gap: 16px; padding: 20px;
  border-radius: var(--p-radius-lg); background: var(--p-bad-tint);
}
.portal .nowcard.seen { background: var(--p-card); border: 1px solid var(--p-line); }
.portal .nowtile {
  position: relative; flex: none; width: 48px; height: 48px; border-radius: 14px;
  display: grid; place-items: center; background: var(--p-card); color: var(--p-bad);
}
.portal .nowtile .corner { position: absolute; right: -6px; bottom: -6px; border-radius: 9px; box-shadow: 0 0 0 3px var(--p-bad-tint); }
.portal .nowcard.seen .nowtile .corner { box-shadow: 0 0 0 3px var(--p-card); }
.portal .nowtext { flex: 1 1 auto; min-width: 0; }
.portal .nowtext h3 { margin: 0; font-size: 1.25rem; font-weight: 600; color: var(--p-bad); }
.portal .nowcard.seen .nowtext h3 { color: var(--p-ink); }
.portal .nowtext p { margin: 4px 0 0; font-size: 1.0625rem; }
.portal .nowactions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-top: 12px; }
.portal .nowactions form { margin: 0; }
.portal .btn.outline.bad { border-color: var(--p-bad); color: var(--p-bad); background: var(--p-card); }
.portal .btn.text { background: transparent; border-color: transparent; color: var(--p-ink); padding: 0 8px; }
.portal .btn.text:hover { background: transparent; color: var(--p-ink); text-decoration: underline; }
.portal .rulecard { padding: 20px 24px; }
.portal .rulerow {
  display: flex; align-items: center; gap: 14px; min-height: 76px; padding: 10px 0;
  border-top: 1px solid var(--line-soft); cursor: pointer;
}
.portal .rulecard .fgroup-head + .rulerow { border-top: 0; }
.portal .watchcard .rulerow { border-top: 0; min-height: 0; padding: 0; }
.portal .ruletext { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.portal .ruletext .t { font-size: 1.125rem; font-weight: 500; }
.portal .ruletext .s { font-size: 1rem; color: var(--p-mute); }
.portal .rulerow .switch { flex: none; }
/* The same alarm from two gadgets (alarms.go, markTwins): the note the
   server writes under each, and the question alarms.ts puts under the row
   just turned on. */
.portal .rule-also {
  display: flex; align-items: flex-start; gap: 8px; margin: 0 0 12px; font-size: 1rem; color: var(--p-warm-ink);
}
.portal .rule-also .pi { flex: none; margin-top: 3px; }
.portal .rulecard .dup-ask { margin: 0 0 12px; }
.portal .dup-ask p { margin: 0; font-size: 1rem; color: var(--p-warm-ink); font-weight: 500; }

/* Lägg till pryl, designrunda 2 (vy 4). */
.portal .hit .tile { position: relative; }
.portal .hit .tile .corner { position: absolute; right: -6px; bottom: -6px; border-radius: 9px; box-shadow: 0 0 0 3px var(--p-card); }
.portal .hit .what strong { font-size: 1.1875rem; font-weight: 600; }
.portal .hit .lands { display: inline-flex; align-items: center; gap: 6px; margin-top: 4px; font-size: 1rem; color: var(--p-sea-dk); }
.portal .hit .btn { min-height: 56px; }
.portal .found { display: inline-flex; align-items: center; gap: 8px; }
.portal .found .pi { color: var(--p-ok); }
.portal .talks { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
.portal .talk {
  display: flex; flex-direction: column; justify-content: center; gap: 8px; min-height: 96px; padding: 16px 18px;
  border-radius: var(--p-radius-lg); border: 1px solid var(--p-line); background: var(--p-card);
}
.portal .talk .brand-logo { max-height: 36px; }
.portal .talk-name { display: flex; align-items: center; gap: 10px; }
.portal .talk-what { font-size: 0.875rem; color: var(--p-mute); }
.portal .talk.soon { background: transparent; border-style: dashed; }
.portal .talk.soon .brand-logo { filter: grayscale(1); opacity: .6; }
.portal .talk-what em { font-style: normal; font-weight: 600; }
.portal .ftags { display: flex; flex-wrap: wrap; gap: 8px; }
.portal .ftag {
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 14px;
  border-radius: 999px; background: var(--p-card); border: 1px solid var(--p-line);
  color: var(--p-ink); text-decoration: none; font-weight: 500;
}
.portal .ftag:hover { border-color: var(--p-sea); }
.portal .detail-row .k .note { display: block; margin-top: 2px; font-size: 0.875rem; font-weight: 400; color: var(--p-mute); }

/* --- Batteriet med egen BMS (designrunda 3, enhet-pryl.html) ---------------
   docs/design_handoff_kundportal/runda-3-2026-10-01. The widths and heights
   come from classes in steps of 5 % (battery.go, step5), so the CSP holds
   without a style attribute. */
.portal .gp.bat { gap: 20px; }
.portal .bat-panel { gap: 20px; padding: 26px; }
.portal .bat-panel .gp-state { gap: 12px 24px; }
.portal .bat-panel .gp-big { font-size: 3.5rem; }
.portal .bat-left { margin: 0 0 6px; font-size: 1.1875rem; font-weight: 500; font-variant-numeric: tabular-nums; }
.portal .bat-meter {
  height: 18px; border-radius: 9px; overflow: hidden;
  background: var(--line-soft); box-shadow: inset 0 0 0 1px var(--p-line);
}
.portal .bat-fill { display: block; height: 100%; border-radius: 9px; background: var(--p-ok); }
.portal .bat-fill.sea { background: var(--p-sea); }
.portal .bat-fill.warm { background: var(--p-warm); }
.portal .bat-panel.stale .bat-fill { opacity: .45; }
.portal .bat-fill.w-0 { width: 0; }       .portal .bat-fill.w-5 { width: 5%; }    .portal .bat-fill.w-10 { width: 10%; }  .portal .bat-fill.w-15 { width: 15%; }
.portal .bat-fill.w-20 { width: 20%; }    .portal .bat-fill.w-25 { width: 25%; }  .portal .bat-fill.w-30 { width: 30%; }  .portal .bat-fill.w-35 { width: 35%; }
.portal .bat-fill.w-40 { width: 40%; }    .portal .bat-fill.w-45 { width: 45%; }  .portal .bat-fill.w-50 { width: 50%; }  .portal .bat-fill.w-55 { width: 55%; }
.portal .bat-fill.w-60 { width: 60%; }    .portal .bat-fill.w-65 { width: 65%; }  .portal .bat-fill.w-70 { width: 70%; }  .portal .bat-fill.w-75 { width: 75%; }
.portal .bat-fill.w-80 { width: 80%; }    .portal .bat-fill.w-85 { width: 85%; }  .portal .bat-fill.w-90 { width: 90%; }  .portal .bat-fill.w-95 { width: 95%; }
.portal .bat-fill.w-100 { width: 100%; }

/* Lägesraden: the four states, and "vet inte" when the values are old. */
.portal .bat-state {
  display: flex; align-items: center; gap: 14px; padding: 14px 16px;
  border-radius: var(--p-radius); background: var(--p-bg); color: var(--p-ink);
}
.portal .bat-state.charge  { background: var(--p-ok-tint);  color: var(--p-ok); }
.portal .bat-state.drain   { background: var(--p-sea-tint); color: var(--p-sea-dk); }
.portal .bat-state.protect { background: var(--p-bad-tint); color: var(--p-bad); }
.portal .bat-state.old     { color: var(--p-mute); }
.portal .bat-state-icon {
  flex: none; width: 44px; height: 44px; border-radius: var(--p-radius);
  display: grid; place-items: center; background: var(--p-card);
}
.portal .bat-state-text { flex: 1; min-width: 0; }
.portal .bat-state-text strong { display: block; font-size: 1.25rem; font-weight: 600; line-height: 1.3; }
.portal .bat-state-text span { display: block; font-size: 1rem; color: var(--p-ink); }
.portal .bat-readonly { display: flex; align-items: center; gap: 8px; margin: 0; font-size: 1rem; color: var(--p-mute); }

/* Så mår batteriet. */
.portal .bat-health { display: flex; flex-direction: column; gap: 12px; }
.portal .bat-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap: 12px; }
.portal .bat-card {
  display: flex; flex-direction: column; gap: 12px; padding: 18px;
  border-radius: var(--p-radius-lg); border: 1px solid var(--p-line); background: var(--p-card);
}
.portal .bat-card.bad { border-color: var(--p-bad); }
.portal .bat-card-head { display: flex; align-items: center; gap: 8px; margin: 0; font-size: 1rem; font-weight: 600; color: var(--p-mute); }
.portal .bat-answer { margin: 0; font-size: 1.375rem; font-weight: 700; line-height: 1.2; font-variant-numeric: tabular-nums; }
.portal .bat-card.bad .bat-answer { color: var(--p-bad); }
.portal .bat-card.stale .bat-answer { color: var(--p-mute); }
.portal .bat-why { margin: 0; font-size: 1rem; color: var(--p-mute); }
.portal .bat-cells { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; margin: 0; padding: 0; list-style: none; }
.portal .bat-cells li { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.portal .bat-cell {
  position: relative; display: block; width: 100%; height: 56px; border-radius: 8px; overflow: hidden;
  background: var(--line-soft); box-shadow: inset 0 0 0 1px var(--p-line);
}
.portal .bat-cell-fill { position: absolute; left: 0; right: 0; bottom: 0; background: var(--p-ok); }
.portal .bat-cells li.bad .bat-cell-fill { background: var(--p-bad); }
.portal .bat-cells li.bad .bat-cell-v { color: var(--p-bad); font-weight: 600; }
.portal .bat-card.stale .bat-cell-fill { opacity: .45; }
.portal .bat-cell-v { font-size: 0.8125rem; color: var(--p-mute); font-variant-numeric: tabular-nums; }
.portal .bat-cell-fill.h-0 { height: 0; }       .portal .bat-cell-fill.h-5 { height: 5%; }    .portal .bat-cell-fill.h-10 { height: 10%; }  .portal .bat-cell-fill.h-15 { height: 15%; }
.portal .bat-cell-fill.h-20 { height: 20%; }    .portal .bat-cell-fill.h-25 { height: 25%; }  .portal .bat-cell-fill.h-30 { height: 30%; }  .portal .bat-cell-fill.h-35 { height: 35%; }
.portal .bat-cell-fill.h-40 { height: 40%; }    .portal .bat-cell-fill.h-45 { height: 45%; }  .portal .bat-cell-fill.h-50 { height: 50%; }  .portal .bat-cell-fill.h-55 { height: 55%; }
.portal .bat-cell-fill.h-60 { height: 60%; }    .portal .bat-cell-fill.h-65 { height: 65%; }  .portal .bat-cell-fill.h-70 { height: 70%; }  .portal .bat-cell-fill.h-75 { height: 75%; }
.portal .bat-cell-fill.h-80 { height: 80%; }    .portal .bat-cell-fill.h-85 { height: 85%; }  .portal .bat-cell-fill.h-90 { height: 90%; }  .portal .bat-cell-fill.h-95 { height: 95%; }
.portal .bat-cell-fill.h-100 { height: 100%; }
.portal .bat-rows { display: flex; flex-direction: column; }
.portal .bat-line {
  display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 30px;
  border-top: 1px solid var(--line-soft); font-size: 1rem;
}
.portal .bat-line span { color: var(--p-mute); }
.portal .bat-line strong { font-weight: 600; font-variant-numeric: tabular-nums; }
.portal .bat-line.bad strong { color: var(--p-bad); }

/* Senaste dygnet, the battery's: the range beside the heading, a legend,
   and the comparisons in a row of their own (frontend/src/charts.ts). */
.portal .bat-day { gap: 14px; padding: 22px; }
.portal .bat-day-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 16px; }
.portal .bat-day-head .muted { font-size: 1rem; font-variant-numeric: tabular-nums; }
.portal .chart-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 1rem; }
.portal .chart-legend:empty { display: none; }
.portal .chart-legend .item { display: inline-flex; align-items: center; gap: 8px; }
.portal .chart-legend .sw { flex: none; width: 18px; height: 3px; border-radius: 2px; background: var(--p-sea); }
.portal .chart-legend .sw-1 { background: var(--p-sea-dk); }
.portal .chart-legend .sw-2 { background: var(--p-warm); }
.portal .chart-legend .sw-3 { background: var(--p-ok); }
.portal .chart-legend .sw-cmp { height: 0; border-radius: 0; background: none; border-top: 3px dashed var(--p-warm); }
.portal .chart-compare {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding-top: 12px; border-top: 1px solid var(--line-soft);
}
.portal .chart-compare:empty { display: none; }
.portal .chart-compare .label { margin-right: 4px; font-size: 1rem; color: var(--p-mute); }
.portal .chart-compare .btn.compare {
  min-height: 44px; padding: 0 14px 0 8px; gap: 8px; font-size: 1rem; font-weight: 500; white-space: nowrap;
  border: 1.5px dashed var(--p-line); background: transparent; color: var(--p-ink);
}
.portal .chart-compare .btn.compare:hover { border-color: var(--p-warm); background: transparent; color: var(--p-ink); }
.portal .chart-compare .btn.compare[aria-pressed="true"] { border-color: var(--p-warm); background: var(--p-warm-tint); }

/* Alla värden, Felsökning: the summary's own text and a chevron. */
.portal details.bat-more > summary { justify-content: flex-start; }
.portal details.bat-more > summary > span:first-child { flex: 1 0 auto; }
.portal details.bat-more > summary > .muted { min-width: 0; text-align: right; line-height: 1.3; }
.portal details.bat-more > summary .chev { display: grid; place-items: center; color: var(--p-mute); }
.portal details.bat-more[open] > summary .chev { transform: rotate(180deg); }
.portal .bat-groups { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); gap: 4px 32px; margin-top: 4px; }
.portal .bat-group { display: flex; flex-direction: column; padding-top: 10px; }
.portal .bat-group-name { margin: 0; padding-bottom: 4px; font-size: 1rem; font-weight: 600; color: var(--p-mute); }
.portal .bat-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 44px;
  border-top: 1px solid var(--line-soft); font-size: 1.0625rem;
}
.portal .bat-row strong { font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; overflow-wrap: anywhere; }
.portal .bat-row.stale strong { color: var(--p-warm-ink); }
.portal .bat-row.bad strong { color: var(--p-bad); }
.portal .bat-diag-lede { margin: 4px 0 8px; font-size: 1rem; }
@media (max-width: 640px) {
  .portal .bat-panel { padding: 20px; }
  .portal .bat-panel .gp-big { font-size: 2.75rem; }
}
@media (max-width: 520px) {
  .portal .chart-compare .label { flex-basis: 100%; }
  .portal .chart-compare .btn.compare { width: 100%; justify-content: flex-start; }
}

/* Senaste dygnet: each row is the link to its gadget, and its value is live
   (frontend/src/overview-live.ts). */
.portal a.spark-link { color: inherit; text-decoration: none; border-radius: 10px; }
.portal a.spark-link:hover .spark-name, .portal a.spark-link:focus-visible .spark-name { color: var(--p-sea-dk); text-decoration: underline; }
.portal a.spark-link:focus-visible { outline: 2px solid var(--p-sea); outline-offset: 4px; }
@keyframes spark-fresh { from { color: var(--p-sea); } to { color: inherit; } }
.portal [data-e].fresh { animation: spark-fresh 1.2s ease-out; }

/* A battery's direction beside its value (overview.go, batteryFlow), the
   same rule as the battery in the "Just nu" card: green and down, into the
   battery, while it charges; red and up, out of it, while it drains; none at
   rest or when not known (Johan, 2026-10-02). Both arrows are in the page;
   the class shows one (frontend/src/overview-live.ts). */
.portal .flow { display: inline-flex; align-items: center; vertical-align: middle; margin-right: 4px; }
.portal .flow .up, .portal .flow .down { display: none; }
.portal .flow-charge .down { display: inline-flex; color: var(--p-ok); }
.portal .flow-drain .up { display: inline-flex; color: var(--p-bad); }
.portal .flow .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.portal .spark-now .flow { margin: 0 0 0 6px; }
.portal .spark-now .flow .pi { width: 20px; height: 20px; }

/* "Just nu" (design round 4, energyflow.go): built from what the box can
   measure - full, sol or batteri - and its day chart under it. Only the
   tokens of omnivan.css. A battery that gives power is red, with its
   arrows rising; one that charges green, arrows falling (Johan,
   2026-10-02, over round 4's "sea, not red"). The BMS's protection is red
   too, and says so in words. */
.portal .ef {
  --ef-text: var(--p-ink); --ef-mute: var(--p-mute); --ef-help: var(--p-mute);
  --ef-use: var(--p-sea-dk); --ef-use-bg: var(--p-sea-tint);
  container-type: inline-size; gap: 18px; padding: 24px; border-radius: var(--p-radius-xl);
  box-shadow: var(--p-shadow-panel); color: var(--p-ink); font-size: 1.0625rem; line-height: 1.5;
}
.portal .ej { --ej-ink: var(--p-sea-dk); --ej-tint: var(--p-bg); }
.portal .ej-charge { --ej-ink: var(--p-ok); --ej-tint: var(--p-ok-tint); }
.portal .ej-drain { --ej-ink: var(--p-bad); --ej-tint: var(--p-bad-tint); }
.portal .ej-protect { --ej-ink: var(--p-bad); --ej-tint: var(--p-bad-tint); }
.portal .ej-old, .portal .ej-unknown, .portal .ej-rest { --ej-ink: var(--p-mute); }
.portal .ej [hidden] { display: none; }

.portal .ej-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 8px 16px; }
.portal .ej-titles { min-width: 0; }
.portal .ej-titles h2 { margin: 0; font-size: 1.75rem; font-weight: 700; letter-spacing: -0.02em; line-height: 1.15; }
.portal .ej-src { margin: 4px 0 0; font-size: 1rem; color: var(--p-mute); }
.portal .ej-pill {
  display: inline-flex; align-items: center; min-height: 34px; padding: 0 14px; border-radius: 999px;
  font-size: 1rem; font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums;
  background: var(--p-bg); color: var(--p-mute);
}
.portal .ej-charge .ej-pill { background: var(--p-ok-tint); color: var(--p-ok); }
.portal .ej-drain .ej-pill { background: var(--p-bad-tint); color: var(--p-bad); }
.portal .ej-protect .ej-pill { background: var(--p-bad-tint); color: var(--p-bad); }
.portal .ej-sol.ej-lit .ej-pill { background: var(--p-warm-tint); color: var(--p-warm-ink); }

/* The sun's icon by day, the moon's without sun: both in the page, the
   class shows one (frontend/src/energyflow.ts changes it live). */
.portal .ej-sunico, .portal .ej-moonico { display: inline-flex; }
.portal .ej-lit .ej-moonico, .portal .ej:not(.ej-lit) .ej-sunico { display: none; }

/* The battery: a cell with a pole, filled as high as the charge in the
   colour of its edge. The height is a class in steps of 5 %. */
.portal .ej-cell {
  position: relative; display: flex; align-items: flex-end; flex: none; box-sizing: border-box;
  width: 34px; height: 52px; padding: 3px; border: 3px solid var(--ej-ink); border-radius: 7px; margin-top: 8px;
}
.portal .ej-cell::before {
  content: ""; position: absolute; top: -8px; left: 50%; width: 14px; height: 5px; margin-left: -7px;
  border-radius: 2px 2px 0 0; background: var(--ej-ink);
}
.portal .ej-fill { display: block; width: 100%; border-radius: 3px; background: var(--ej-ink); }
.portal .ej-cell-lg { width: 46px; height: 72px; padding: 4px; border-radius: 9px; margin-top: 9px; }
.portal .ej-cell-lg::before { top: -9px; width: 18px; height: 6px; margin-left: -9px; }
.portal .ej-cell-lg .ej-fill { border-radius: 4px; }
.portal .ej-fill.h-0 { height: 0%; } .portal .ej-fill.h-5 { height: 5%; } .portal .ej-fill.h-10 { height: 10%; } .portal .ej-fill.h-15 { height: 15%; } .portal .ej-fill.h-20 { height: 20%; }
.portal .ej-fill.h-25 { height: 25%; } .portal .ej-fill.h-30 { height: 30%; } .portal .ej-fill.h-35 { height: 35%; } .portal .ej-fill.h-40 { height: 40%; } .portal .ej-fill.h-45 { height: 45%; }
.portal .ej-fill.h-50 { height: 50%; } .portal .ej-fill.h-55 { height: 55%; } .portal .ej-fill.h-60 { height: 60%; } .portal .ej-fill.h-65 { height: 65%; } .portal .ej-fill.h-70 { height: 70%; }
.portal .ej-fill.h-75 { height: 75%; } .portal .ej-fill.h-80 { height: 80%; } .portal .ej-fill.h-85 { height: 85%; } .portal .ej-fill.h-90 { height: 90%; } .portal .ej-fill.h-95 { height: 95%; }
.portal .ej-fill.h-100 { height: 100%; }

/* The arrows in the battery run the way the energy goes through the pole
   on top: falling into a battery that charges, rising out of one that gives
   power (Johan, 2026-10-02: a draining battery with falling arrows looked
   like it was charging). Over a fill that glows a little; white on the
   fill, inside the cell's padding box; the card's class shows one
   direction. At rest, old or stopped by the BMS: none, and no glow. */
.portal .ej-chevs { position: absolute; inset: 3px; width: calc(100% - 6px); height: calc(100% - 6px); }
.portal .ej-cell-lg .ej-chevs { inset: 4px; width: calc(100% - 8px); height: calc(100% - 8px); }
.portal .ej-chev { fill: none; stroke: var(--p-on-accent); stroke-width: 2.7; stroke-linecap: round; stroke-linejoin: round; opacity: 0; }
.portal .ej-up, .portal .ej-down { display: none; }
.portal .ej-charge .ej-down, .portal .ej-drain .ej-up { display: inline; }
.portal .ej-charge .ej-down .ej-chev { animation: ej-down 1.8s linear infinite; }
.portal .ej-drain .ej-up .ej-chev { animation: ej-up 1.8s linear infinite; }
.portal .ej .ej-chev.ej-d2 { animation-delay: .6s; }
.portal .ej .ej-chev.ej-d3 { animation-delay: 1.2s; }
.portal .ej-charge .ej-fill, .portal .ej-drain .ej-fill { animation: ej-glow 2.4s ease-in-out infinite; }
@keyframes ej-up   { from { transform: translateY(14px); opacity: 0; } 30% { opacity: 1; } to { transform: translateY(-20px); opacity: 0; } }
@keyframes ej-down { from { transform: translateY(-20px); opacity: 0; } 30% { opacity: 1; } to { transform: translateY(14px); opacity: 0; } }
@keyframes ej-glow { 0%, 100% { filter: brightness(1); } 50% { filter: brightness(1.18); } }
/* Nothing moves for whoever has asked for that; one arrow stands still, so
   the direction is still drawn. */
@media (prefers-reduced-motion: reduce) {
  .portal .ej .ej-chev, .portal .ej .ej-fill { animation: none; }
  .portal .ej-charge .ej-down .ej-chev.ej-d2, .portal .ej-drain .ej-up .ej-chev.ej-d2 { opacity: 1; }
}

/* 4a, full: three tiles, and the two lines of what goes where in the
   gaps between them. */
.portal .ej-grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 10px; }
.portal .ej-tile {
  grid-column: span 2; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  min-width: 0; min-height: clamp(150px, 30cqi, 180px); padding: 16px 8px; border-radius: var(--p-radius-lg); text-align: center;
}
.portal .ej-sun { background: var(--p-warm-tint); color: var(--p-warm-ink); }
.portal .ej-batt { background: var(--ej-tint); gap: 6px; }
.portal .ej-load { background: var(--p-sea-tint); color: var(--p-sea-dk); }
.portal .ej-val { font-size: clamp(1.375rem, 5cqi, 1.875rem); font-weight: 700; line-height: 1.2; color: var(--p-ink); font-variant-numeric: tabular-nums; }
.portal .ej-cap { font-size: 1rem; font-weight: 500; }
.portal .ej-sub { font-size: 0.875rem; font-weight: 600; color: var(--ej-ink); font-variant-numeric: tabular-nums; }
.portal .ej-note { font-size: 0.8125rem; color: var(--p-mute); line-height: 1.3; }
.portal .ej-flow {
  display: flex; flex-direction: column; align-items: center; margin: 0; font-size: 0.875rem; font-weight: 600;
  line-height: 1.3; text-align: center; min-width: 0;
}
.portal .ej-flow-a { grid-column: 2 / span 2; }
.portal .ej-flow-b { grid-column: 4 / span 2; }
.portal .ej-flow.tone-warm { color: var(--p-warm-ink); }
.portal .ej-flow.tone-ok { color: var(--p-ok); }
.portal .ej-flow.tone-sea { color: var(--p-sea-dk); }
.portal .ej-flow.tone-off { color: var(--p-mute); }

/* 4b and 4c: one large box that wraps, the icon on top on a phone. */
.portal .ej-hero { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 24px; padding: 22px; border-radius: var(--p-radius-lg); }
.portal .ej-hero-sun { background: var(--p-warm-tint); }
.portal .ej-hero-batt { background: var(--ej-tint); }
.portal .ej-disc {
  display: grid; place-items: center; flex: none; width: 64px; height: 64px; border-radius: 50%;
  background: var(--p-card); color: var(--p-warm-ink);
}
.portal .ej-hero-text { flex: 1 1 160px; min-width: 0; }
.portal .ej-hero-sun .ej-hero-text { flex-basis: 200px; }
.portal .ej-label { font-size: 1rem; font-weight: 600; color: var(--ej-ink); }
.portal .ej-hero-sun .ej-label { color: var(--p-warm-ink); }
.portal .ej-huge { font-size: clamp(2.5rem, 10cqi, 3.5rem); font-weight: 700; letter-spacing: -0.02em; line-height: 1.05; font-variant-numeric: tabular-nums; }
.portal .ej-line { font-size: 1rem; margin-top: 4px; }
.portal .ej-subline { font-size: 1rem; color: var(--p-mute); font-variant-numeric: tabular-nums; }
.portal .ej-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr)); gap: 10px; }
.portal .ej-fact { padding: 12px 16px; border-radius: var(--p-radius); background: var(--p-bg); }
.portal .ej-fact .k { font-size: 0.875rem; color: var(--p-mute); }
.portal .ej-fact .v { font-size: 1.25rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.portal .ej-net {
  flex: 1 1 200px; display: flex; align-items: center; gap: 12px; padding: 14px 16px;
  border-radius: var(--p-radius); background: var(--p-card); color: var(--ej-ink);
}
.portal .ej-netin, .portal .ej-netout { display: inline-flex; flex: none; }
.portal .ej-net.in .ej-netout, .portal .ej-net:not(.in) .ej-netin { display: none; }
.portal .ej-net-text { display: flex; flex-direction: column; min-width: 0; font-size: 1rem; font-weight: 600; }
.portal .ej-net-text strong { font-size: 1.375rem; font-weight: 700; line-height: 1.2; color: var(--p-ink); font-variant-numeric: tabular-nums; }

.portal .ej-time { margin: 0; font-size: 1.125rem; }
.portal .ej-time strong { font-weight: 700; }
.portal .ej-time[title] { cursor: help; }

/* Varifrån kommer siffrorna? - closed, in place of the formula that was
   always shown. */
.portal .ej-how { border-radius: var(--p-radius); background: var(--p-bg); }
.portal .ej-how summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 10px; min-height: 48px; padding: 0 14px;
  font-size: 1rem; font-weight: 600; color: var(--p-mute);
}
.portal .ej-how summary::-webkit-details-marker { display: none; }
.portal .ej-how summary span { flex: 1; }
.portal .ej-how[open] summary .pi:last-child { transform: rotate(180deg); }
.portal .ej-how p { margin: 0; padding: 0 14px 14px 42px; font-size: 1rem; }

.portal .ef-alert, .portal .ef-old-line {
  display: flex; align-items: flex-start; gap: 8px; margin: 0; padding: 10px 12px; border-radius: 14px;
  font-size: 1rem; font-weight: 600; line-height: 1.4;
}
.portal .ef-alert { background: var(--p-bad-tint); color: var(--p-bad); }
.portal .ef-old-line { background: var(--p-raised); color: var(--p-mute); }
.portal .ef-alert .pi, .portal .ef-old-line .pi { flex: none; margin-top: 2px; }

/* The day under the flow: the charge on 0–100 %, the chosen on their own scales. */
.portal .ef-day { display: flex; flex-direction: column; gap: 10px; padding-top: 16px; border-top: 1px solid var(--line-soft); }
/* The gear sits by what it changes: the day, not the flow above it. */
.portal .ef-day-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 12px; }
.portal .ef-day-tools { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.portal .ef-gear {
  display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px;
  border-radius: var(--p-radius); color: var(--p-mute); background: var(--p-bg);
}
.portal .ef-gear:hover { background: var(--ef-use-bg); color: var(--ef-use); }
.portal .ef-day-head h3 { margin: 0; font-size: 1.1875rem; font-weight: 600; }
.portal .ef-range { font-size: 0.875rem; color: var(--p-mute); font-variant-numeric: tabular-nums; }
.portal .ef-chart { display: block; width: 100%; height: 120px; overflow: visible; }
.portal .ef-chart .dl { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.portal .ef-chart .dl-0 { stroke: var(--p-sea); stroke-width: 2.5; }
.portal .ef-chart .dl-area { fill: var(--p-sea-tint); }
.portal .ef-chart .dl-1 { stroke: var(--p-warm); stroke-dasharray: 6 5; }
.portal .ef-chart .dl-2 { stroke: var(--p-ok); }
.portal .ef-chart .dl-3 { stroke: var(--p-mute); stroke-dasharray: 1 3; }
.portal .ef-ticks { display: flex; justify-content: space-between; font-size: 0.8125rem; color: var(--ef-help); }
/* Skalan på y-axeln (designrunda 10, dayaxis.go): en kolumn på 44 px med
   tre etiketter, lodrätt centrerade på stödlinjerna vid 5, 50 och 95 % av
   grafens höjd (y 4, 40 och 76 av 80 i SVG:n). Tidsetiketterna står under
   grafen, inte under skalan. */
.portal .day-chart { display: grid; grid-template-columns: 44px minmax(0, 1fr); column-gap: 8px; row-gap: 6px; }
.portal .day-chart.two { grid-template-columns: 44px minmax(0, 1fr) 44px; }
.portal .day-chart-y { position: relative; height: 120px; font-size: 0.8125rem; color: var(--p-mute); font-variant-numeric: tabular-nums; }
.portal .day-chart-y span { position: absolute; right: 0; transform: translateY(-50%); white-space: nowrap; }
.portal .day-chart-y.right span { right: auto; left: 0; }
.portal .day-chart-y .y-top { top: 5%; }
.portal .day-chart-y .y-mid { top: 50%; }
.portal .day-chart-y .y-bot { top: 95%; }
.portal .day-chart-x { grid-column: 2; }
.portal .ef-chart .dl-grid { fill: none; stroke: var(--line-soft); stroke-width: 1; vector-effect: non-scaling-stroke; }
.portal .ef-chart .dl-grid.zero { stroke: var(--line); }
.portal .ef-ticks span { white-space: nowrap; }
.portal .ef-legend { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0 14px; font-size: 0.875rem; color: var(--ef-mute); }
.portal .ef-legend a { display: inline-flex; align-items: center; gap: 6px; min-height: 36px; color: inherit; text-decoration: none; }
.portal .ef-legend a:hover { color: var(--p-sea-dk); text-decoration: underline; }
.portal .ef-legend [data-e] { color: var(--ef-text); font-weight: 700; font-variant-numeric: tabular-nums; }
.portal .ef-legend .sw { flex: none; width: 14px; height: 3px; border-radius: 2px; }
.portal .ef-legend .sw-dl-0 { background: var(--p-sea); }
.portal .ef-legend .sw-dl-1 { height: 0; border-radius: 0; border-top: 2px dashed var(--p-warm); }
.portal .ef-legend .sw-dl-2 { background: var(--p-ok); }
.portal .ef-legend .sw-dl-3 { height: 0; border-radius: 0; border-top: 2px dotted var(--p-mute); }
.portal .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
@media (max-width: 520px) {
  .portal .ov-day.ef { padding: 20px 16px; }
  .portal .ef-ticks span:nth-child(2), .portal .ef-ticks span:nth-child(4) { display: none; }
}

/* Anpassa Senaste dygnet (design E, daypick.go): a sheet from the bottom
   over the overview, or a page of its own without script. */
.portal dialog.sheet {
  width: 100%; max-width: 560px; max-height: 92vh; margin: auto auto 0; padding: 0; border: 0;
  border-radius: 28px 28px 0 0; background: var(--p-card); color: var(--p-ink); overflow: auto;
}
.portal dialog.sheet::backdrop { background: rgba(27, 37, 53, .45); }
.portal .pick { display: flex; flex-direction: column; gap: 16px; padding: 12px 20px 24px; color: var(--p-ink); }
.portal .pick-page .pick { padding: 22px 20px 24px; border-radius: 28px; background: var(--p-card); box-shadow: var(--p-shadow-panel); }
.portal .pick-grip { width: 40px; height: 4px; border-radius: 2px; background: var(--p-line); align-self: center; }
.portal .pick-page .pick-grip { display: none; }
.portal .pick-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.portal .pick-titles { display: flex; flex-direction: column; gap: 4px; }
.portal .pick-titles h2 { margin: 0; font-size: 1.375rem; font-weight: 800; letter-spacing: -0.3px; line-height: 1.2; }
.portal .pick-titles p { font-size: 1rem; color: var(--p-mute); }
.portal .pick-count { flex: none; padding: 6px 10px; border-radius: 999px; background: var(--p-raised); color: var(--p-mute); font-size: 0.8125rem; font-weight: 800; }
.portal .pick-count.full { background: var(--p-sea-tint); color: var(--p-sea-dk); }
.portal .pick-sec { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0; border: 0; min-width: 0; }
.portal .pick-label { padding: 0; font-size: 0.8125rem; font-weight: 700; color: var(--p-mute); letter-spacing: 0.4px; text-transform: uppercase; }
.portal legend.pick-label { margin-bottom: 8px; }
.portal .pick-chips { display: flex; flex-wrap: wrap; gap: 8px; min-height: 36px; }
.portal .pick-chip { display: inline-flex; align-items: center; padding: 8px 12px; border-radius: 999px; background: var(--p-sea-tint); color: var(--p-sea-dk); font-size: 0.875rem; font-weight: 700; }
.portal .pick-none { font-size: 0.875rem; color: var(--p-mute); padding: 8px 0; }
.portal .pick [hidden] { display: none; }
.portal .pick-row {
  position: relative; display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 10px 12px;
  border: 2px solid var(--p-line); border-radius: 16px; background: var(--p-card); cursor: pointer;
}
.portal .pick-row.on { border-color: var(--p-sea); background: var(--p-sea-tint); }
.portal .pick-row.off { opacity: .45; cursor: not-allowed; }
.portal .pick-row:has(input:focus-visible) { outline: 3px solid var(--p-focus); outline-offset: 2px; }
.portal .pick-what { flex: 1 1 auto; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.portal .pick-name { font-size: 1rem; font-weight: 700; line-height: 1.3; }
.portal .pick-metric { font-size: 0.875rem; color: var(--p-mute); line-height: 1.3; }
/* The real checkbox stays in the page, for the keyboard and a screen reader;
   the box beside it is what is drawn. */
.portal .pick-row input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.portal .pick-box {
  flex: none; display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px;
  border: 2px solid var(--p-line); border-radius: 8px; background: var(--p-card); color: var(--p-on-accent);
}
.portal .pick-box .pi { visibility: hidden; stroke-width: 3.5; }
.portal .pick-row input:checked + .pick-box { border-color: var(--p-sea); background: var(--p-sea); }
.portal .pick-row input:checked + .pick-box .pi { visibility: visible; }
.portal .pick-actions { display: flex; gap: 10px; padding-top: 4px; }
.portal .pick-cancel, .portal .pick-done {
  display: inline-flex; align-items: center; justify-content: center; min-height: 52px; border: 0; border-radius: 16px;
  font: inherit; font-size: 1rem; text-decoration: none; cursor: pointer;
}
.portal .pick-cancel { flex: 1 1 0; background: var(--p-raised); color: var(--p-ink); font-weight: 700; }
.portal .pick-done { flex: 2 1 0; background: var(--p-sea); color: var(--p-on-accent); font-weight: 800; }
.portal .pick-cancel:hover { background: var(--p-raised); color: var(--p-ink); }
.portal .pick-done:hover { background: var(--p-sea-dk); }


/* Lådans wifi (enhet-wifi.html): näten i den ordning lådan provar dem. */
.portal .wifi-list { list-style: none; margin: 0; padding: 0; }
.portal .wifi-list li { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 8px 12px; padding: 12px 0; border-bottom: 1px solid var(--p-line); }
.portal .wifi-list li:last-child { border-bottom: 0; }
.portal .wifi-name { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; overflow-wrap: anywhere; }
.portal .wifi-list form { margin: 0; }
.portal .wifi-name .tag { font-size: 0.8125rem; font-weight: 600; padding: 2px 9px; border-radius: 999px;
  background: var(--p-bg); color: var(--p-mute); border: 1px solid var(--p-line); }
.portal .wifi-name .tag.ok { background: var(--p-ok-tint); color: var(--p-ok); border-color: transparent; }

/* --- Inställnings- och detaljsidor, designrunda 5 --------------------------
   docs/design_handoff_kundportal/runda-5-2026-10-06/README.md, "Mönstret för
   inställningssidor": tillbaka → sidhuvud → lägeskort → rader → stängda
   formulär → hjälp längst ned → det som inte går att ångra sist. Mallarna
   page-head, state-card, row och help i partials.html. Raderna heter .lrow,
   inte .row: .row är redan knappraden överallt i portalen. */
.portal .spage { display: flex; flex-direction: column; gap: 20px; }
.portal .spage > .back { align-self: flex-start; }

.portal .page-head { display: flex; align-items: flex-start; gap: 18px; }
.portal .page-head > div { min-width: 0; }
.portal .page-head h1 { font-size: clamp(1.75rem, 4.6vw, 2.125rem); overflow-wrap: anywhere; }
.portal .page-tile {
  flex: none; display: grid; place-items: center; width: 64px; height: 64px;
  border-radius: 18px; background: var(--p-sea-tint); color: var(--p-sea-dk);
}
.portal .page-lede { margin: 6px 0 0; font-size: 1rem; color: var(--p-mute); text-wrap: pretty; }

/* Lägeskortet. */
.portal .state-card {
  display: flex; flex-direction: column; gap: 18px; padding: 20px 24px;
  border-radius: var(--p-radius-xl); background: var(--p-card); box-shadow: var(--p-shadow-panel);
}
.portal .state-head { display: flex; align-items: center; gap: 14px; }
.portal .state-head > div { min-width: 0; }
.portal .state-tile {
  flex: none; display: grid; place-items: center; width: 48px; height: 48px;
  border-radius: 14px; background: var(--p-bg); color: var(--p-mute);
}
.portal .state-ok   .state-tile { background: var(--p-ok-tint);   color: var(--p-ok); }
.portal .state-warn .state-tile { background: var(--p-warm-tint); color: var(--p-warm-ink); }
.portal .state-bad  .state-tile { background: var(--p-bad-tint);  color: var(--p-bad); }
.portal .state-title { font-size: 1.375rem; font-weight: 700; line-height: 1.25; text-wrap: pretty; }
.portal .state-text { margin-top: 2px; font-size: 1rem; color: var(--p-mute); text-wrap: pretty; }
.portal .state-note { font-size: 1rem; color: var(--p-mute); }
.portal .facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin: 0; }
.portal .fact { padding: 14px 16px; border-radius: 14px; background: var(--line-soft); }
.portal .fact dt { font-size: 1rem; color: var(--p-mute); }
.portal .fact dd { margin: 2px 0 0; font-size: 1.1875rem; font-weight: 600; line-height: 1.3; }
.portal .fact.warn { background: var(--p-warm-tint); }
.portal .fact.warn :is(dt, dd) { color: var(--p-warm-ink); }

/* Listan med rader. Hela raden är länken, knappen eller <summary>. */
.portal .rows {
  border-radius: var(--p-radius-xl); background: var(--p-card);
  box-shadow: var(--p-shadow-panel); overflow: hidden;
}
.portal .rows > * + * { border-top: 1px solid var(--line-soft); }
.portal .lrow {
  display: flex; align-items: center; gap: 14px; min-height: 72px; padding: 12px 18px;
  color: var(--p-ink); text-decoration: none; cursor: pointer; list-style: none;
}
.portal .lrow:hover { background: var(--head); color: var(--p-ink); }
.portal summary.lrow::-webkit-details-marker { display: none; }
.portal .lrow-tile {
  flex: none; display: grid; place-items: center; width: 44px; height: 44px;
  border-radius: var(--p-radius); background: var(--p-sea-tint); color: var(--p-sea-dk);
}
.portal .lrow-tile.warm  { background: var(--p-warm-tint); color: var(--p-warm-ink); }
.portal .lrow-tile.plain { background: var(--line-soft); color: var(--p-mute); }
.portal .lrow-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.portal .lrow-title { font-size: 1.125rem; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.portal .lrow-sub { font-size: 1rem; color: var(--p-mute); overflow-wrap: anywhere; }
.portal .lrow-sub.mono { font-family: var(--p-mono); }
/* Läget bryts mellan ord men aldrig inne i ett ("Anslut-en"); bara ett långt
   namn utan mellanrum får brytas, och då först vid halva raden. */
.portal .lrow-value { flex: 0 1 auto; max-width: 50%; font-size: 1rem; font-weight: 500; text-align: right; overflow-wrap: break-word; }
.portal .lrow-value.ok   { color: var(--p-ok); }
.portal .lrow-value.warn { color: var(--p-warm-ink); }
.portal .lrow-value.mute { color: var(--p-mute); }
.portal .lrow-value.sea  { color: var(--p-sea-dk); }
.portal .lrow-chev { flex: none; display: grid; color: var(--p-mute); }
.portal .lrow-fold[open] > summary .lrow-chev { transform: rotate(90deg); }
/* Det som fälls ut: en formulärdel på --head, eller detaljer på vitt. */
.portal .lrow-form {
  display: flex; flex-direction: column; gap: 14px; padding: 18px;
  border-top: 1px solid var(--line-soft); background: var(--head);
}
.portal .lrow-form > p { font-size: 1rem; }
.portal .lrow-open { display: flex; flex-direction: column; gap: 16px; padding: 4px 18px 18px; }

/* Fält och knappar på de här sidorna: 48 px, inte formulärsidornas 56. */
.portal .spage label { font-size: 1rem; font-weight: 600; }
.portal .spage .hint { margin-top: 6px; }
.portal .spage :is(input[type="text"], input[type="password"], input[type="number"]) {
  min-height: 48px; padding: 0 14px; font-size: 1.125rem;
}
.portal .spage input.mono { font-family: var(--p-mono); font-size: 1rem; }
.portal .spage .btn { min-height: 48px; padding: 0 20px; font-size: 1rem; }
.portal .spage .btn.ghost { background: transparent; color: var(--p-mute); font-weight: 500; padding: 0 16px; }
.portal .spage .btn.ghost:hover { background: var(--line-soft); color: var(--p-ink); }
.portal .form-actions { display: flex; flex-wrap: wrap; gap: 10px; }

/* Integritet och trygghet, direkt under det det gäller. */
.portal .lockline { display: flex; align-items: center; gap: 8px; font-size: 1rem; color: var(--p-mute); }

/* Hjälp och teknik längst ned. */
.portal details.help { border-radius: var(--p-radius-xl); background: var(--p-card); border: 1px solid var(--p-line); }
.portal details.help > summary {
  display: flex; align-items: center; gap: 12px; min-height: 64px; padding: 10px 18px;
  cursor: pointer; list-style: none;
}
.portal details.help > summary::-webkit-details-marker { display: none; }
.portal details.help > summary > .pi { color: var(--p-mute); }
.portal .help-text {
  flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: space-between; gap: 2px 16px;
}
.portal .help-title { font-size: 1.125rem; font-weight: 600; }
.portal .help-sub { font-size: 1rem; color: var(--p-mute); line-height: 1.35; }
.portal .help-chev { flex: none; display: grid; color: var(--p-mute); }
.portal details.help[open] .help-chev { transform: rotate(180deg); }
.portal .help-body { display: flex; flex-direction: column; gap: 14px; padding: 0 18px 18px; font-size: 1rem; }
.portal .help-body .steps { gap: 14px; }
.portal .help-body .steps li { gap: 12px; line-height: 1.5; }
.portal .help-body .steps .n { width: 28px; height: 28px; background: var(--p-sea-tint); color: var(--p-sea-dk); font-size: 0.875rem; font-weight: 700; }
.portal .keyvals {
  display: grid; grid-template-columns: auto 1fr; gap: 4px 16px; margin: 0; padding: 14px 16px;
  border-radius: var(--p-radius); background: var(--line-soft);
}
.portal .keyvals dt { color: var(--p-mute); }
.portal .keyvals dd { margin: 0; font-weight: 700; overflow-wrap: anywhere; }

/* Felsökning: de råa värdena, etikett till vänster och värde till höger. */
.portal .tech-rows { display: flex; flex-direction: column; }
.portal .tech-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 16px; align-items: baseline;
  padding: 8px 0; border-top: 1px solid var(--line-soft);
}
.portal .tech-row .k { color: var(--p-mute); }
.portal .tech-row .k .note { display: block; margin-top: 2px; font-size: 0.875rem; }
.portal .tech-row .v { font-weight: 500; font-variant-numeric: tabular-nums; text-align: right; }
.portal .tech-row .a { grid-column: 1 / -1; font-size: 0.875rem; color: var(--p-mute); }
.portal .tech-row.stale .v { color: var(--p-warm-ink); }

/* Det som inte går att ångra, sist och för sig. */
.portal a.danger-row {
  display: flex; align-items: center; gap: 14px; min-height: 64px; padding: 10px 18px;
  border-radius: var(--p-radius-xl); border: 1.5px solid var(--p-bad-tint);
  background: var(--p-card); color: var(--p-bad); text-decoration: none;
}
.portal a.danger-row:hover { background: var(--bad-row); color: var(--p-bad); }
.portal .danger-row .pi { flex: none; }
.portal .danger-row .lrow-sub { color: var(--p-mute); }
@media (max-width: 520px) {
  .portal .state-card { padding: 20px; }
}

/* Wifi, 6a: näten med ordningsnummer, och knappar på raden. */
.portal .list-block { display: flex; flex-direction: column; gap: 10px; }
.portal .lrow.net { cursor: default; }
.portal .lrow.net:hover { background: transparent; }
.portal .lrow.net .lrow-text { flex: 1 1 0; }
.portal .lrow-num {
  flex: none; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%;
  background: var(--line-soft); color: var(--p-mute); font-size: 1rem; font-weight: 700;
}
.portal .lrow-actions { flex: none; display: flex; gap: 2px; margin-right: -8px; }
.portal .lrow-actions form { margin: 0; }
.portal .spage .btn.mini {
  min-height: 44px; padding: 0 12px; border: 0; border-radius: var(--p-radius-sm);
  background: transparent; color: var(--p-mute); font-size: 1rem; font-weight: 500;
}
.portal .spage .btn.mini:hover { background: var(--line-soft); color: var(--p-ink); }
.portal .lrow-empty { padding: 18px; color: var(--p-mute); font-size: 1rem; }
.portal .lrow.add { min-height: 64px; color: var(--p-sea-dk); font-size: 1.0625rem; font-weight: 600; }
.portal .lrow.add:hover { color: var(--p-sea-dk); }
.portal .lrow-plus {
  flex: none; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%;
  background: var(--p-sea-tint);
}
.portal .lrow-fold[open] > summary.lrow.add { background: var(--head); }
/* Svaret på ett kommando, mellan lägeskortet och listan: ett kort, inte en
   lös rad. */
.portal .spage > .msg { margin: 0; border-radius: var(--p-radius-lg); }
.portal .spage > .msg:not(.ok):not(.bad) { background: var(--p-card); box-shadow: var(--p-shadow-card); }

/* Satelliter, 6b: det en satellit fäller ut. */
.portal .lrow-open > p { font-size: 1rem; }
.portal .inline-field { display: flex; flex-wrap: wrap; gap: 10px; }
.portal .inline-field input { flex: 1 1 220px; width: auto; }
.portal .spage .inline-field .btn { min-height: 48px; }
.portal .raw { font-family: var(--p-mono); font-size: 0.875rem; color: var(--p-mute); overflow-wrap: anywhere; }
.portal details.confirm > summary {
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; list-style: none; cursor: pointer;
  font-size: 1rem; font-weight: 600; color: var(--p-bad);
}
.portal details.confirm > summary::-webkit-details-marker { display: none; }
.portal details.confirm > .lrow-form { border: 1.5px solid var(--p-bad-tint); border-radius: var(--p-radius); }
.portal .small-steps { gap: 12px; }
.portal .small-steps li { gap: 12px; font-size: 1rem; line-height: 1.5; }
.portal .small-steps .n { width: 28px; height: 28px; background: var(--p-sea-tint); color: var(--p-sea-dk); font-size: 0.875rem; font-weight: 700; }

/* Home Assistant, 6c: ett reglage på raden, och fälten två och två. */
.portal label.lrow { margin: 0; font-size: inherit; font-weight: inherit; }
.portal .lrow .switch { flex: none; }
.portal .lrow-warn { padding: 0 18px 16px 76px; font-size: 1rem; color: var(--p-warm-ink); text-wrap: pretty; }
.portal .lrow-save { padding: 0 18px 16px 76px; }
.portal [data-autosubmit-save][hidden] { display: none; }
.portal .field-pair { display: grid; grid-template-columns: minmax(0, 1fr) 130px; gap: 12px; }
.portal .field-duo { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; }
.portal .spage .btn.ghost.bad { color: var(--p-bad); }
.portal .spage .btn.ghost.bad:hover { background: var(--p-bad-tint); color: var(--p-bad); }
@media (max-width: 520px) {
  .portal .lrow-warn, .portal .lrow-save { padding-left: 18px; }
}
@media (max-width: 360px) {
  .portal .field-pair { grid-template-columns: 1fr; }
}

/* --- AI-stödet, designrunda 7 (docs/design_handoff_kundportal/runda-7-2026-10-06) ---
   7c: Läget i ord på översikten. 8a-8i: frågesidan (enhet-fraga.html,
   frontend/src/assistant.ts). Modellens text är vanlig brödtext i normal vikt; det
   som är mätt står i rutorna under "Mätt av lådan". */
.portal .ov-laget { margin: 4px 0 0; font-size: 1.1875rem; line-height: 1.55; color: var(--p-ink); max-width: 38em; text-wrap: pretty; }
.portal .ov-laget.old { margin: 0; font-size: 1.125rem; line-height: 1.5; color: var(--p-mute); }
.portal .ov-laget-quiet { margin: 4px 0 0; font-size: 1.1875rem; line-height: 1.5; font-weight: 600; color: var(--p-bad); text-wrap: pretty; }
.portal .ov-laget-by {
  margin: 0; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 0 12px; font-size: 1rem; max-width: 38em;
}
.portal .ov-laget-by .who { display: inline-flex; align-items: center; gap: 6px; color: var(--p-mute); white-space: nowrap; }
.portal .ov-laget-by a {
  display: inline-flex; align-items: center; gap: 2px; min-height: 44px; font-weight: 600;
  color: var(--p-sea-dk); text-decoration: none;
}
.portal .ov-laget-by a:hover { text-decoration: underline; }

.portal .ask-page { max-width: 760px; }
.portal .ask-lede { margin: 6px 0 0; font-size: 1rem; color: var(--p-mute); text-wrap: pretty; }
.portal .ask-thread { display: flex; flex-direction: column; gap: 16px; }
.portal .ask-thread:empty { display: none; }
.portal .visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Fältet och förslagen. */
.portal .ask-more { display: flex; flex-direction: column; gap: 8px; }
.portal .ask-more-label { margin: 0; font-size: 1.0625rem; font-weight: 600; }
.portal .ask { display: flex; flex-wrap: wrap; gap: 10px; margin: 0; }
.portal .ask input[type="text"] {
  flex: 1 1 0; min-width: 0; min-height: 60px; padding: 0 16px; border-radius: 14px;
  border: 1.5px solid var(--p-line); background: var(--p-card); color: var(--p-ink); font: inherit; font-size: 1.125rem;
}
.portal .ask input[type="text"]:disabled { background: var(--line-soft); }
.portal .ask-send {
  width: 60px; height: 60px; flex: none; display: grid; place-items: center; border: none; border-radius: 14px;
  background: var(--p-sea); color: var(--p-on-accent); cursor: pointer;
}
.portal .ask-send:hover { background: var(--p-sea-dk); }
.portal .ask-send:disabled { background: var(--p-switch-off); cursor: default; }
.portal .ask-pills { flex: 1 0 100%; display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.portal .ask-pills:empty { display: none; }
.portal .ask-pills button {
  display: inline-flex; align-items: center; min-height: 48px; padding: 0 16px; border-radius: 24px;
  border: 1.5px solid var(--p-line); background: var(--p-card); color: var(--p-sea-dk);
  font: inherit; font-size: 1.0625rem; font-weight: 500; text-align: left; cursor: pointer;
}
.portal .ask-pills button:hover { border-color: var(--p-sea); background: var(--p-sea-tint); }
.portal .ask-trust { display: flex; flex-direction: column; gap: 8px; }
.portal .ask-trust p { display: flex; align-items: flex-start; gap: 8px; margin: 0; font-size: 1rem; color: var(--p-mute); }
.portal .ask-trust .pi { margin-top: 2px; flex: none; }
.portal .ask-busy .ask-more { display: none; }

/* Svarskortet. */
.portal .answer {
  background: var(--p-card); border-radius: 18px; overflow: hidden; box-shadow: var(--p-shadow-panel);
}
.portal .answer-silent { display: flex; gap: 12px; align-items: flex-start; padding: 14px 18px; background: var(--p-bad-tint); }
.portal .answer-silent > .pi { color: var(--p-bad); margin-top: 2px; flex: none; }
.portal .answer-silent .t { margin: 0; font-size: 1.125rem; font-weight: 700; color: var(--p-bad); line-height: 1.3; }
.portal .answer-silent .s { margin: 2px 0 0; font-size: 1rem; color: var(--p-ink); }
.portal .answer-body { padding: 18px; display: flex; flex-direction: column; gap: 14px; }
.portal .answer-q { margin: 0; font-size: 1.3125rem; font-weight: 600; line-height: 1.3; text-wrap: pretty; }
.portal .answer-from { display: flex; align-items: center; gap: 10px; font-size: 1rem; font-weight: 600; color: var(--p-mute); }
.portal .answer-from .tile, .portal .measured-row .tile, .portal .ask-limit .tile {
  flex: none; display: grid; place-items: center; border-radius: 10px;
}
.portal .answer-from .tile { width: 32px; height: 32px; background: var(--p-sea-tint); color: var(--p-sea-dk); }
.portal .answer-text { margin: 0; font-size: 1.25rem; line-height: 1.5; font-weight: 400; white-space: pre-wrap; text-wrap: pretty; }
.portal .answer-text.writing::after {
  content: ""; display: inline-block; width: 3px; height: 1.05em; margin-left: 3px; vertical-align: -0.15em;
  background: var(--p-sea); animation: ovCaret 1s steps(1) infinite;
}
.portal .answer-thinking { display: flex; flex-direction: column; gap: 6px; padding: 6px 0; }
.portal .answer-thinking .row { display: flex; align-items: center; gap: 12px; font-size: 1.1875rem; }
.portal .answer-thinking .slow { margin: 0; font-size: 1rem; color: var(--p-mute); }
.portal .answer-thinking .dots { display: inline-flex; gap: 5px; flex: none; }
.portal .answer-thinking .dots span {
  width: 9px; height: 9px; border-radius: 50%; background: var(--p-sea); animation: ovDot 1.2s ease-in-out infinite;
}
.portal .answer-thinking .dots span:nth-child(2) { animation-delay: .16s; }
.portal .answer-thinking .dots span:nth-child(3) { animation-delay: .32s; }
@keyframes ovDot { 0%, 80%, 100% { opacity: .25; transform: translateY(0); } 40% { opacity: 1; transform: translateY(-3px); } }
@keyframes ovCaret { 0%, 50% { opacity: 1; } 51%, 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .portal .answer-thinking .dots span, .portal .answer-text.writing::after { animation: none; }
}

/* Mätt av lådan: från databasen, aldrig från modellens text. */
.portal .measured { display: flex; flex-direction: column; gap: 8px; }
.portal .measured-label { font-size: 1rem; font-weight: 600; color: var(--p-mute); }
.portal .measured-row {
  display: flex; align-items: center; gap: 12px; min-height: 60px; padding: 8px 12px; border-radius: 14px;
  background: var(--p-card); border: 1.5px solid var(--p-line); color: var(--p-ink); text-decoration: none;
}
.portal .measured-row:hover { border-color: var(--p-sea); color: var(--p-ink); }
.portal .measured-row .tile { width: 38px; height: 38px; background: var(--p-warm-tint); color: var(--p-warm-ink); }
.portal .measured-row .what { flex: 1 1 auto; min-width: 0; }
.portal .measured-row .name { display: block; font-size: 1rem; font-weight: 500; line-height: 1.3; }
.portal .measured-row .age { display: flex; align-items: center; gap: 6px; font-size: 1rem; color: var(--p-mute); }
.portal .measured-row .age .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--p-ok); flex: none; }
.portal .measured-row .value { font-size: 1.1875rem; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.portal .measured-row > .pi { color: var(--p-mute); flex: none; }
.portal .measured-row.old .age { color: var(--p-warm-ink); font-weight: 600; }
.portal .measured-row.old .age .dot { background: var(--p-warm); }
.portal .measured-row.old .value { color: var(--p-mute); }
.portal .answer-action { min-height: 56px; font-size: 1.125rem; justify-content: center; gap: 8px; }
.portal .answer-foot {
  margin: 0; padding-top: 12px; border-top: 1px solid var(--line-soft); display: flex; align-items: flex-start;
  gap: 8px; font-size: 1rem; line-height: 1.45; color: var(--p-mute);
}
.portal .answer-foot .pi { margin-top: 1px; flex: none; }
.portal .answer-foot.bad { color: var(--p-bad); }
.portal .answer-problem { display: flex; flex-direction: column; gap: 12px; }
.portal .answer-problem p { margin: 0; font-size: 1.1875rem; line-height: 1.5; text-wrap: pretty; }
.portal .answer-problem .btn { align-self: flex-start; }

/* Förra frågan (bara med skript): ihopfälld ovanför kortet. */
.portal details.answer-prev { border-radius: 14px; background: var(--p-card); border: 1px solid var(--p-line); }
.portal details.answer-prev > summary {
  display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 8px 16px; cursor: pointer; list-style: none;
}
.portal details.answer-prev > summary::-webkit-details-marker { display: none; }
.portal details.answer-prev .label { display: block; font-size: 0.875rem; color: var(--p-mute); }
.portal details.answer-prev .prev-q { display: block; font-size: 1.0625rem; font-weight: 600; }
.portal details.answer-prev > summary > span:first-child { flex: 1; min-width: 0; }
.portal details.answer-prev[open] > summary .pi { transform: rotate(180deg); }
.portal details.answer-prev .answer { box-shadow: none; border-top: 1px solid var(--p-line); border-radius: 0 0 14px 14px; }

/* 8i: gränsen är nådd. */
.portal .ask-limit {
  display: flex; gap: 14px; align-items: flex-start; padding: 18px; border-radius: 18px;
  background: var(--p-card); box-shadow: var(--p-shadow-panel);
}
.portal .ask-limit .tile { width: 48px; height: 48px; border-radius: 14px; background: var(--p-warm-tint); color: var(--p-warm-ink); }
.portal .ask-limit .t { margin: 0; font-size: 1.3125rem; font-weight: 700; line-height: 1.3; }
.portal .ask-limit .s { margin: 4px 0 0; font-size: 1rem; color: var(--p-mute); text-wrap: pretty; }

/* Prylsidan: fler brytare (en Elcentral) och nivåreglage. */
.portal .gp-switches { box-shadow: none; border: 1px solid var(--p-line); }
.portal .gp-switch { cursor: default; }
.portal .gp-switch:hover { background: none; }
.portal .gp-switch form { margin: 0; flex: none; }
.portal .gp-slider { align-items: center; gap: 14px; }
.portal .gp-slider .slider { flex: 1 1 auto; min-width: 0; min-height: 44px; accent-color: var(--p-sea-dk); }
.portal .gp-slider .slider-value { flex: none; min-width: 4.5em; font-size: 1.125rem; font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }

/* --- Elcentralen, designrunda 9 (docs/design_handoff_kundportal/runda-9-2026-10-08) ---
   Sammanfattningen, grupperna och raderna. Lägena per rad: known, waiting,
   done, failed, stale, unknown (controlpanel.go). */
.portal .ec-summary {
  scroll-margin-top: 96px; display: flex; flex-direction: column; gap: 14px; padding: 18px;
  border-radius: var(--p-radius-xl); background: var(--p-card); box-shadow: var(--p-shadow-panel);
}
.portal .ec-summary-head { display: flex; align-items: flex-start; gap: 14px; }
.portal .ec-summary-tile {
  flex: none; display: grid; place-items: center; width: 48px; height: 48px; border-radius: 14px;
  background: var(--p-warm-tint); color: var(--p-warm-ink);
}
.portal .ec-summary.bad .ec-summary-tile { background: var(--p-bad-tint); color: var(--p-bad); }
.portal .ec-summary-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.portal .ec-summary-text p { margin: 0; font-size: 1rem; color: var(--p-ink); }
.portal .ec-summary-text .ec-summary-title { font-size: 1.5rem; font-weight: 700; line-height: 1.25; }
.portal .ec-summary.bad .ec-summary-title { color: var(--p-bad); }
.portal .ec-summary form { margin: 0; }
.portal .ec-alloff { width: 100%; min-height: 56px; gap: 10px; }

.portal .ec-group { display: flex; flex-direction: column; gap: 10px; }
.portal .ec-group-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 0 4px; }
.portal .ec-group-head h2 { margin: 0; font-size: 1.25rem; font-weight: 600; }
.portal .ec-rename {
  display: inline-flex; align-items: center; gap: 6px; min-height: 44px;
  font-size: 1rem; font-weight: 500; color: var(--p-sea-dk); text-decoration: none;
}
.portal .ec-rows {
  display: flex; flex-direction: column; gap: 1px; overflow: hidden;
  border: 1px solid var(--p-line); border-radius: var(--p-radius-xl); background: var(--line-soft);
}
.portal .ec-row { display: flex; flex-direction: column; gap: 10px; padding: 10px 14px; background: var(--p-card); scroll-margin-top: 96px; }
.portal .ec-row-main { display: flex; align-items: center; gap: 12px; min-height: 52px; }
.portal .ec-row form { margin: 0; }
.portal .ec-tile {
  flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 12px;
  background: var(--line-soft); color: var(--p-mute);
}
.portal .ec-tile.warm { background: var(--p-warm-tint); color: var(--p-warm-ink); }
.portal .ec-tile.sea  { background: var(--p-sea-tint); color: var(--p-sea-dk); }
.portal .ec-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.portal .ec-name { font-size: 1.125rem; font-weight: 600; line-height: 1.3; overflow-wrap: anywhere; }
.portal .ec-sub { font-size: 1rem; color: var(--p-mute); }
.portal .ec-sub.waiting { font-weight: 500; color: var(--p-sea-dk); }
.portal .ec-sub.done    { font-weight: 600; color: var(--p-ok); }
.portal .ec-sub.failed  { font-weight: 500; color: var(--p-bad); }
.portal .ec-sub.stale   { font-weight: 600; color: var(--p-warm-ink); }
.portal .ec-value { flex: none; font-size: 1.125rem; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Reglaget: en knapp med role="switch" i ett eget formulär. Eget namn:
   .switch är kryssrutan på inställningssidorna. */
/* 68 × 44: ingen tryckyta under 44 px (H10). En större osynlig yta runt
   knappen tar Chromium inte emot tryck på. */
.portal .ec-switch {
  flex: none; position: relative; width: 68px; height: 44px; padding: 3px; border-radius: 22px;
  border: 2px solid var(--p-switch-off); background: var(--p-switch-off); cursor: pointer;
}
/* Knoppen flyttas med transform, så att den kan glida när läget byts på
   sidan (64 px inuti ramen − 2 × 3 px − 34 px knopp = 24 px). */
.portal .ec-switch .knob {
  position: absolute; top: 3px; left: 3px; width: 34px; height: 34px; border-radius: 50%;
  background: var(--p-knob); box-shadow: 0 1px 3px rgba(0, 0, 0, .2);
  transition: transform .15s ease-out;
}
.portal .ec-switch.on { border-color: var(--p-sea); background: var(--p-sea); }
.portal .ec-switch.on .knob { transform: translateX(24px); }
.portal .ec-switch.wait { border: 2px dashed var(--p-sea); background: var(--p-sea-tint); }
.portal .ec-switch.wait .knob { background: var(--p-sea); box-shadow: none; }
.portal .ec-switch:focus-visible { outline: 3px solid var(--p-sea-dk); outline-offset: 2px; }

/* Från trycket tills servern svarat (frontend/src/panel.ts sätter .sending
   på knappen som skickade formuläret): det önskade läget direkt, streckat som
   när servern ritar "Väntar på lådan …". Orden kommer med serverns svar. */
.portal .ec-switch.sending { border: 2px dashed var(--p-sea); background: var(--p-sea-tint); cursor: progress; }
.portal .ec-switch.sending .knob { transform: translateX(24px); background: var(--p-sea); box-shadow: none; }
.portal .ec-switch.on.sending .knob { transform: none; }
.portal .ec-pick.sending { background: var(--p-card); border: 1.5px dashed var(--p-sea); color: var(--p-sea-dk); cursor: progress; }
.portal .ec-choice:has(.sending) .ec-pick.picked:not(.sending) { background: transparent; border-color: transparent; color: var(--p-ink); }
.portal .ec-two .btn.sending,
.portal .ec-alloff.sending { border-style: dashed; border-color: var(--p-sea); color: var(--p-sea-dk); cursor: progress; }
@media (prefers-reduced-motion: reduce) {
  .portal .ec-switch .knob { transition: none; }
}

/* Två knappar när läget inte är känt, och batterivalet. */
.portal .ec-row form.ec-two { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-left: 52px; }
.portal .ec-two .btn { min-height: 48px; border-width: 1.5px; border-color: var(--p-line); color: var(--p-ink); font-size: 1.0625rem; font-weight: 600; }
.portal .ec-row form.ec-choice {
  display: grid; grid-template-columns: 1fr 1fr; gap: 4px; margin-left: 52px; padding: 4px;
  border-radius: 14px; background: var(--line-soft);
}
.portal .ec-pick {
  min-height: 44px; border-radius: 10px; border: 1.5px solid transparent; background: transparent;
  color: var(--p-ink); font: inherit; font-size: 1rem; font-weight: 600; cursor: pointer;
}
.portal .ec-pick.picked { background: var(--p-card); border-color: var(--p-sea); color: var(--p-sea-dk); }
.portal .ec-row.stale .ec-pick, .portal .ec-row.unknown .ec-pick { background: var(--p-card); border-color: var(--p-line); }

/* Val bland flera (AC:ns läge och fläkt): samma knappar som batterivalet,
   en kolumn per val. Klassen säger hur många, eftersom style-attribut inte
   är tillåtna. */
.portal .ec-row form.ec-picks.n-3 { grid-template-columns: repeat(3, 1fr); }
.portal .ec-row form.ec-picks.n-4 { grid-template-columns: repeat(4, 1fr); }
.portal .ec-row form.ec-picks.n-5 { grid-template-columns: repeat(5, 1fr); }
.portal .ec-row form.ec-picks.n-6 { grid-template-columns: repeat(6, 1fr); }

/* − och + kring ett värde (AC:ns temperatur), till höger på raden. */
.portal .ec-row form.ec-step { flex: none; display: flex; align-items: center; gap: 6px; }
.portal .ec-step-btn {
  display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%;
  border: 1.5px solid var(--p-line); background: var(--p-card); color: var(--p-ink);
  font: inherit; font-size: 1.5rem; font-weight: 600; line-height: 1; cursor: pointer;
}
.portal .ec-step-btn:disabled { color: var(--p-line); cursor: default; }
.portal .ec-step-btn:focus-visible { outline: 3px solid var(--p-sea-dk); outline-offset: 2px; }
.portal .ec-step-value {
  min-width: 4.2em; text-align: center; font-size: 1.25rem; font-weight: 600; font-variant-numeric: tabular-nums;
}
.portal .ec-step.sending .ec-step-value { color: var(--p-sea-dk); }
.portal .ec-step.sending .ec-step-btn { border-style: dashed; border-color: var(--p-sea); }

/* Dimmerns nivå under raden, och en tanks stapel. */
.portal .ec-row form.ec-level { display: flex; align-items: center; gap: 12px; margin-left: 52px; }
.portal .ec-level label { font-size: 1rem; font-weight: 400; color: var(--p-mute); }
.portal .ec-level .slider-value { min-width: 3.5em; font-size: 1.0625rem; }
.portal .ec-tank { height: 10px; margin-left: 52px; border-radius: 5px; background: var(--line-soft); overflow: hidden; }
.portal .ec-tank-fill { display: block; height: 100%; border-radius: 5px; background: var(--p-sea); }
.portal .ec-tank-fill.w-0 { width: 0%; }
.portal .ec-tank-fill.w-5 { width: 5%; }
.portal .ec-tank-fill.w-10 { width: 10%; }
.portal .ec-tank-fill.w-15 { width: 15%; }
.portal .ec-tank-fill.w-20 { width: 20%; }
.portal .ec-tank-fill.w-25 { width: 25%; }
.portal .ec-tank-fill.w-30 { width: 30%; }
.portal .ec-tank-fill.w-35 { width: 35%; }
.portal .ec-tank-fill.w-40 { width: 40%; }
.portal .ec-tank-fill.w-45 { width: 45%; }
.portal .ec-tank-fill.w-50 { width: 50%; }
.portal .ec-tank-fill.w-55 { width: 55%; }
.portal .ec-tank-fill.w-60 { width: 60%; }
.portal .ec-tank-fill.w-65 { width: 65%; }
.portal .ec-tank-fill.w-70 { width: 70%; }
.portal .ec-tank-fill.w-75 { width: 75%; }
.portal .ec-tank-fill.w-80 { width: 80%; }
.portal .ec-tank-fill.w-85 { width: 85%; }
.portal .ec-tank-fill.w-90 { width: 90%; }
.portal .ec-tank-fill.w-95 { width: 95%; }
.portal .ec-tank-fill.w-100 { width: 100%; }
@media (max-width: 640px) {
  .portal .ec-row form:is(.ec-two, .ec-choice, .ec-level) { margin-left: 0; }
  .portal .ec-tank { margin-left: 0; }
}

/* --- "Just nu": landström från elcentralen (shore.go) ------------------------ */
.portal .ej-shore {
  display: flex; align-items: flex-start; gap: 8px; margin: 0; padding: 10px 12px; border-radius: 14px;
  font-size: 1rem; font-weight: 600; line-height: 1.4;
}
.portal .ej-shore .pi { flex: none; margin-top: 2px; }
.portal .ej-shore.on  { background: var(--p-ok-tint); color: var(--p-ok); }
.portal .ej-shore.off { background: var(--line-soft); color: var(--p-mute); }
.portal .ej-shore.old { background: var(--p-warm-tint); color: var(--p-warm-ink); }

/* Namn på belysningen, designrunda 9g. */
.portal .ec-names {
  display: flex; flex-direction: column; gap: 18px; padding: 18px;
  border-radius: var(--p-radius-xl); background: var(--p-card); box-shadow: var(--p-shadow-panel);
}
.portal .ec-name-field { display: flex; flex-direction: column; gap: 6px; }
.portal .ec-names input[type="text"] { min-height: 56px; font-size: 1.125rem; }
.portal .ec-name-field .hint { margin: 0; font-size: 1rem; color: var(--p-mute); }
.portal .ec-suggest { display: flex; flex-wrap: wrap; gap: 8px; }
.portal .ec-suggest[hidden] { display: none; }
.portal .ec-chip {
  min-height: 44px; padding: 0 16px; border: 0; border-radius: 22px; background: var(--p-bg);
  color: var(--p-ink); font: inherit; font-size: 1rem; cursor: pointer;
}
.portal .ec-names .btn { width: 100%; }

/* Elcentralen med sitt skript (panel.ts): omslaget följer sidans flöde,
   panelen har stackens avstånd. Med skriptet skickar ett reglage sin nivå när
   det släpps, så knappen Ställ in behövs bara utan. */
.portal .ec-live { display: contents; }
.portal .ec-panel { display: flex; flex-direction: column; gap: 24px; }
.portal .ec-panel.live .slider-set { display: none; }

/* Guiderna på /guider (docs.go): listan efter märke, det som är bra att veta,
   och guidens egen text, skriven i markdown i admin. */
.portal .docs-brand { display: flex; flex-direction: column; gap: 10px; }
.portal .docs-brand h2 { display: flex; align-items: center; gap: 10px; font-size: 1.25rem; }
.portal .lrow.off { cursor: default; }
.portal .lrow.off:hover { background: none; }
.portal .lrow.off .lrow-chev { visibility: hidden; }
.portal .docs-more, .portal .docs-updated { font-size: 1rem; color: var(--p-mute); }
.portal .docs-note { padding: 16px 18px; border-radius: var(--p-radius); background: var(--p-sea-tint); }
.portal .docs-note-title { display: flex; align-items: center; gap: 10px; margin: 0 0 6px; font-weight: 600; color: var(--p-sea-dk); }
.portal .docs-note-body { padding-left: 32px; font-size: 1.0625rem; }
.portal .docs-note-body p, .portal .docs-note-body ul { margin: 0 0 10px; }
.portal .docs-note-body > :last-child { margin-bottom: 0; }
.portal .docs-note-body ul { padding-left: 20px; }
.portal .docs-steps { display: flex; flex-direction: column; gap: 8px; margin: 0; padding-left: 24px; line-height: 1.5; }

/* Länken från prylens sida till dess guide, under infotexten. */
.portal .gp-guide {
  display: flex; align-items: center; gap: 10px; min-height: 52px; padding: 0 16px;
  border-radius: var(--p-radius); border: 1px solid var(--p-line); background: var(--p-card);
  color: var(--p-sea-dk); font-weight: 600; text-decoration: none;
}
.portal .gp-guide span { flex: 1; }
.portal .gp-guide:hover { background: var(--head); }

/* Guidens text. Bara det goldmark skriver: rubriker, stycken, listor,
   bilder, tabeller, kod och citat. */
.portal .doc {
  padding: 22px 26px; border-radius: var(--p-radius-xl); background: var(--p-card);
  box-shadow: var(--p-shadow-panel); font-size: 1.0625rem; line-height: 1.6; overflow-wrap: anywhere;
}
.portal .doc > * { margin: 0 0 14px; }
.portal .doc > :first-child { margin-top: 0; }
.portal .doc > :last-child { margin-bottom: 0; }
.portal .doc h2 { margin-top: 28px; font-size: 1.5rem; line-height: 1.3; }
.portal .doc h3 { margin-top: 22px; font-size: 1.25rem; line-height: 1.3; }
.portal .doc :is(h4, h5, h6) { margin-top: 18px; font-size: 1.0625rem; }
.portal .doc :is(ul, ol) { padding-left: 24px; }
.portal .doc li + li { margin-top: 4px; }
.portal .doc img { display: block; max-width: 100%; height: auto; border-radius: var(--p-radius); border: 1px solid var(--p-line); }
.portal .doc p > img + img { margin-top: 10px; }
.portal .doc code { padding: 1px 5px; border-radius: 6px; background: var(--line-soft); font-family: var(--p-mono); font-size: .9em; }
.portal .doc pre { padding: 14px 16px; overflow-x: auto; border-radius: var(--p-radius); background: var(--line-soft); line-height: 1.45; }
.portal .doc pre code { padding: 0; background: none; }
.portal .doc blockquote { padding: 2px 0 2px 16px; border-left: 4px solid var(--p-sea-tint); color: var(--p-mute); }
.portal .doc table { display: block; max-width: 100%; overflow-x: auto; border-collapse: collapse; font-size: 1rem; }
.portal .doc :is(th, td) { padding: 8px 12px; border-bottom: 1px solid var(--p-line); text-align: left; vertical-align: top; }
.portal .doc th { font-weight: 600; }
.portal .doc hr { margin: 24px 0; border: 0; border-top: 1px solid var(--p-line); }
@media (max-width: 640px) {
  .portal .doc { padding: 18px 16px; }
  .portal .docs-note-body { padding-left: 0; }
}

/* ---------------------------------------------------------------------------
   Firmware som kunden godkänner, designrunda 10 (fwpage.go, enhet-firmware.html):
   notisen på översikten och sidan /enhet/{id}/firmware.
   --------------------------------------------------------------------------- */
.portal .fw-notice {
  display: flex; align-items: center; gap: 14px; min-height: 64px; max-width: 640px; margin-top: 14px;
  padding: 12px 16px; border-radius: 14px; background: var(--p-sea-tint); color: var(--p-ink); text-decoration: none;
}
.portal .fw-notice:hover { box-shadow: inset 0 0 0 1.5px var(--p-sea); color: var(--p-ink); }
.portal .fw-notice-tile {
  flex: none; display: grid; place-items: center; width: 40px; height: 40px;
  border-radius: 12px; background: var(--p-card); color: var(--p-sea-dk);
}
.portal .fw-notice-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.portal .fw-notice-title { font-size: 1.125rem; font-weight: 600; line-height: 1.3; }
.portal .fw-notice-sub { font-size: 1rem; color: var(--p-mute); }
.portal .fw-notice-go { display: inline-flex; align-items: center; gap: 2px; font-size: 1.0625rem; font-weight: 600; color: var(--p-sea-dk); white-space: nowrap; }
.portal .fw-notice.bad { background: var(--p-bad-tint); }
.portal .fw-notice.bad .fw-notice-title,
.portal .fw-notice.bad .fw-notice-tile { color: var(--p-bad); }
.portal .fw-notice.bad:hover { box-shadow: inset 0 0 0 1.5px var(--p-bad); }

.portal .fw { max-width: 680px; }
.portal .fw h1 { font-size: clamp(1.75rem, 4.6vw, 2.125rem); }
.portal .fw-lede { margin-top: 4px; font-size: 1.0625rem; color: var(--p-mute); }
.portal .fw-lede .mono { font-family: var(--p-mono); font-size: 1rem; }

/* Lägeskortet, med designens större platta och fyra toner. */
.portal .fw-card { gap: 16px; padding: 22px; }
.portal .fw-card .state-tile { width: 52px; height: 52px; border-radius: 14px; }
.portal .fw-card .state-title { font-size: 1.5rem; }
.portal .fw-card .state-text { font-size: 1.0625rem; }
.portal .fw-new  .state-tile,
.portal .fw-busy .state-tile { background: var(--p-sea-tint); color: var(--p-sea-dk); }
.portal .fw-done .state-tile { background: var(--p-ok-tint); color: var(--p-ok); }
.portal .fw-bad  .state-tile { background: var(--p-bad-tint); color: var(--p-bad); }
.portal .fw-bad  .state-title { color: var(--p-bad); }
.portal .fw-facts {
  display: flex; flex-direction: column; gap: 10px; margin: 0; padding: 14px 16px; list-style: none;
  border-radius: 12px; background: var(--p-bg);
}
.portal .fw-facts li { display: flex; align-items: flex-start; gap: 10px; font-size: 1rem; }
.portal .fw-facts li > svg { flex: none; margin-top: 2px; color: var(--p-mute); }
/* Stapeln är en <progress>: en bredd i ett style-attribut skulle vara
   enklare, och CSP:n förbjuder det. */
.portal .fw-progress { display: flex; flex-direction: column; gap: 8px; }
.portal .fw-progress progress {
  width: 100%; height: 10px; border: 0; border-radius: 5px; overflow: hidden;
  appearance: none; background: var(--line-soft); color: var(--p-sea);
}
.portal .fw-progress progress::-webkit-progress-bar { background: var(--line-soft); border-radius: 5px; }
.portal .fw-progress progress::-webkit-progress-value { background: var(--p-sea); border-radius: 5px; }
.portal .fw-progress progress::-moz-progress-bar { background: var(--p-sea); border-radius: 5px; }
.portal .fw-progress p { font-size: 1rem; color: var(--p-mute); }
.portal .fw .btn.fw-go { display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: 56px; font-size: 1.125rem; }
.portal .fw-help { font-size: 1rem; color: var(--p-mute); }

/* Stegen: lådan, sedan satelliterna. */
.portal .fw-step { display: flex; flex-direction: column; gap: 12px; }
.portal .fw-step h2 { display: flex; align-items: center; gap: 10px; font-size: 1.3125rem; font-weight: 600; }
.portal .fw-num {
  flex: none; display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%;
  background: var(--p-raised); color: var(--p-mute); font-size: 1rem; font-weight: 700;
}
.portal .fw-num.on   { background: var(--p-sea); color: var(--p-on-accent); }
.portal .fw-num.done { background: var(--p-ok); color: var(--p-on-accent); }
.portal .fw-step-text { font-size: 1rem; color: var(--p-mute); text-wrap: pretty; }

.portal .fw-row { display: flex; align-items: center; gap: 12px; min-height: 72px; padding: 10px 16px; }
.portal .fw-tile {
  flex: none; display: grid; place-items: center; width: 42px; height: 42px;
  border-radius: 12px; background: var(--p-sea-tint); color: var(--p-sea-dk);
}
.portal .fw-tile.plain { background: var(--line-soft); color: var(--p-mute); }
.portal .fw-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.portal .fw-name { font-size: 1.125rem; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.portal .fw-sub { font-size: 1rem; color: var(--p-mute); font-variant-numeric: tabular-nums; }
.portal .fw-sub.warn { color: var(--p-warm-ink); }
.portal .fw-pill {
  flex: none; display: inline-flex; align-items: center; min-height: 32px; padding: 0 12px;
  border-radius: 999px; font-size: 1rem; font-weight: 600; white-space: nowrap;
}
.portal .fw-pill.new  { background: var(--p-sea-tint); color: var(--p-sea-dk); }
.portal .fw-pill.busy { background: var(--p-sea); color: var(--p-on-accent); }
.portal .fw-pill.done { background: var(--p-ok-tint); color: var(--p-ok); }
.portal .fw-pill:is(.wait, .queue) { background: var(--line-soft); color: var(--p-mute); }
.portal .fw-pill:is(.offline, .fail) { background: var(--p-bad-tint); color: var(--p-bad); }
/* Vad är nytt i {v}? (releasenotes.go): en punktlista i hjälpkortet. */
.portal .fw-notes ul { display: flex; flex-direction: column; gap: 8px; margin: 0; padding-left: 22px; }

/* Inkopplingen (enhet-inkoppling, setupgate.go): en låda som inte varit
   online sedan den kopplades. En ruta över sidan som inte går att stänga;
   den går vidare av sig själv när lådan är online. */
.portal .setup-gate {
  position: fixed; inset: 0; z-index: 50; display: flex; align-items: flex-start; justify-content: center;
  padding: 24px 16px; overflow-y: auto; background: rgba(27, 37, 53, .45);
}
.portal .setup-card {
  display: flex; flex-direction: column; gap: 16px; width: 100%; max-width: 560px; margin: auto 0;
  padding: 20px; border-radius: var(--p-radius-xl); background: var(--p-bg); box-shadow: var(--p-shadow-panel);
}
.portal .setup-card .state-card { box-shadow: none; }
.portal .setup-foot { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; font-size: 1rem; }
.portal .setup-foot a { color: var(--p-mute); }

/* The QR reader (frontend/src/scan.ts, Johan 2026-10-14): the buttons the
   script shows where there is a camera, and the camera in a dialog over the
   page. The picture is cropped square; the whole frame is still read. */
.portal [data-scan][hidden] { display: none; }
.portal .ov-links { display: inline-flex; flex-wrap: wrap; gap: 0 20px; }
.portal button.ov-settings {
  padding: 0; border: 0; background: none; font: inherit; font-size: 1.0625rem; font-weight: 600;
  color: var(--p-sea-dk); text-decoration: underline; cursor: pointer;
}
.portal button.ov-settings:hover { color: var(--p-sea); }
.portal dialog.scan {
  width: min(480px, calc(100vw - 32px));
  max-height: calc(100dvh - 32px);
  padding: 16px;
  border: 0;
  border-radius: var(--p-radius-lg);
  background: var(--p-card);
  color: var(--p-ink);
}
.portal dialog.scan::backdrop { background: rgb(0 0 0 / 0.7); }
.portal .scan-video {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--p-radius);
  background: #000;
}
.portal .scan-video[hidden] { display: none; }
.portal .scan-msg { margin: 14px 0; font-size: 1.0625rem; }

/* Victron (victron.go, templates/enhet-victron.html, Johan 2026-10-19): Venus
   OS upplägg i portalens egen form. Batteriet som en ring, systemet som rutor,
   två i bredd på telefonen. En ruta som leder till reglage säger det längst
   ned. Inga Victron-färger: portalens egna. */
.portal .vx-battery {
  display: flex; align-items: center; gap: 22px; margin: 18px 0; padding: 18px 20px;
  border: 1px solid var(--p-line); border-radius: var(--p-radius-lg); background: var(--p-card);
  box-shadow: var(--p-shadow-card); color: var(--p-ink); text-decoration: none;
}
.portal .vx-battery:hover { box-shadow: var(--p-shadow-hover); color: var(--p-ink); }
.portal .vx-ring { position: relative; flex: 0 0 132px; width: 132px; height: 132px; }
.portal .vx-ring svg { width: 100%; height: 100%; }
.portal .vx-ring-bg { fill: none; stroke: var(--p-sea-tint); stroke-width: 9; }
.portal .vx-ring-fill { fill: none; stroke: var(--p-sea); stroke-width: 9; stroke-linecap: round; }
.portal .vx-ring-text {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.portal .vx-soc { font-size: 1.875rem; font-weight: 700; line-height: 1.1; }
.portal .vx-mode { font-size: 1rem; color: var(--p-mute); }
.portal .vx-battery-facts { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 22px; margin: 0; flex: 1; }
.portal .vx-battery-facts dt { font-size: 0.875rem; color: var(--p-mute); }
.portal .vx-battery-facts dd { margin: 0; font-size: 1.1875rem; font-weight: 600; }
.portal .vx-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; margin: 18px 0; }
.portal .vx-tile {
  display: flex; flex-direction: column; gap: 4px; min-height: 120px; padding: 14px 16px;
  border: 1px solid var(--p-line); border-radius: var(--p-radius); background: var(--p-card);
  box-shadow: var(--p-shadow-card); color: var(--p-ink); text-decoration: none;
}
.portal a.vx-tile:hover { box-shadow: var(--p-shadow-hover); color: var(--p-ink); }
.portal .vx-tile.warm { border-color: var(--p-warm); background: var(--p-warm-tint); }
.portal .vx-tile-head { display: flex; align-items: center; gap: 8px; font-size: 1rem; font-weight: 600; color: var(--p-mute); }
.portal .vx-tile.warm .vx-tile-head { color: var(--p-warm-ink); }
.portal .vx-big { font-size: 1.625rem; font-weight: 700; line-height: 1.2; }
.portal .vx-line { font-size: 1rem; }
.portal .vx-line-label { color: var(--p-mute); }
.portal .vx-do { display: inline-flex; align-items: center; gap: 2px; margin-top: auto; padding-top: 6px; font-size: 1rem; font-weight: 600; color: var(--p-sea-dk); }
.portal .vx-h { margin: 26px 0 10px; font-size: 1.25rem; }
.portal .vx-tank { margin: -6px 18px 10px 70px; }
@media (max-width: 520px) {
  .portal .vx-battery { flex-direction: column; align-items: stretch; text-align: left; }
  .portal .vx-ring { align-self: center; }
  .portal .vx-tiles { grid-template-columns: 1fr 1fr; gap: 10px; }
  .portal .vx-tile { min-height: 104px; padding: 12px 12px; }
  .portal .vx-big { font-size: 1.375rem; }
}

/* --- Värmen (heaterview.go, varme.html) -------------------------------------
   docs/design_handoff_omnivan_varme/runda-1-2026-10-29: ett eget huvud,
   ratten och menyn med fem flikar längst ned, fast mot skärmens nederkant
   och över iOS hemindikator (safe area). Mått och rundningar ur prototypen;
   färgerna är portalens tokens. Grönt betyder att något är igång, aldrig
   vilken flik man står på: den är grå och fet. */
body.portal.app { min-height: 100vh; min-height: 100dvh; }
.portal .hv {
  --hv-shadow: 0 1px 2px rgba(var(--shade), .06), 0 6px 20px rgba(var(--shade), .06);
  max-width: 560px; margin: 0 auto; min-height: 100vh; min-height: 100dvh;
  display: flex; flex-direction: column;
  padding-bottom: calc(92px + env(safe-area-inset-bottom, 0px));
}
.portal .hv-head {
  display: flex; align-items: center; gap: 12px;
  padding: calc(14px + env(safe-area-inset-top, 0px)) 18px 10px;
}
.portal .hv-logo {
  width: 48px; height: 48px; border-radius: 16px; flex: none; display: grid; place-items: center;
  background: var(--p-card); border: 1px solid var(--p-line);
}
.portal .hv-logo .logo-body { stroke: var(--logo-body); }
.portal .hv-logo .logo-signal { stroke: var(--logo-signal); }
.portal .hv-logo .logo-dot { fill: var(--logo-signal); }
.portal .hv-who { flex: 1 1 auto; min-width: 0; }
.portal .hv-name { margin: 0; font-size: 1.25rem; font-weight: 800; letter-spacing: -0.02em; line-height: 1.2; }
.portal .hv-conn { display: flex; align-items: center; gap: 7px; margin-top: 2px; font-size: 0.9375rem; font-weight: 700; color: var(--p-mute); }
.portal .hv-conn.weak { color: var(--p-warm-ink); }
.portal .hv-conn.off { color: var(--p-bad); }
.portal .bars { display: inline-flex; align-items: flex-end; gap: 2px; height: 15px; }
.portal .bars i { width: 4px; border-radius: 1px; background: var(--p-line); }
.portal .bars i:nth-child(1) { height: 5px; }
.portal .bars i:nth-child(2) { height: 8px; }
.portal .bars i:nth-child(3) { height: 11px; }
.portal .bars i:nth-child(4) { height: 15px; }
.portal .bars-4 i, .portal .bars-3 i:nth-child(-n+3) { background: var(--p-sea); }
.portal .bars-1 i:first-child { background: var(--warm); }
.portal .hv-pwr {
  width: 64px; height: 64px; border-radius: 50%; flex: none; padding: 0; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  border: 2px solid var(--p-sea); background: var(--p-sea); color: var(--p-on-accent);
  font: inherit; font-size: 0.875rem; font-weight: 800; line-height: 1; box-shadow: var(--hv-shadow);
}
.portal .hv-pwr.off { background: var(--p-card); color: var(--p-ink); border-color: var(--p-line); }
.portal .hv-pwr.wait { border-style: dashed; }
.portal .hv button:disabled { opacity: .42; cursor: default; }

/* margin och max-width: portalens main centrerar sig själv, vilket i en
   flexkolumn krymper den till innehållets bredd. */
.portal .hv-main { flex: 1 1 auto; display: flex; flex-direction: column; gap: 12px; margin: 0; max-width: none; padding: 4px 18px 16px; }
.portal .hv-page-h h1 { margin: 0; font-size: 1.625rem; font-weight: 800; letter-spacing: -0.03em; line-height: 1.15; }
.portal .hv-page-h p { margin: 2px 0 0; color: var(--p-mute); font-size: 1rem; }

/* Ratten: bara ringen tar emot drag (.hit), ett tryck mitt i gör inget. */
.portal .hv-dial { position: relative; width: 300px; max-width: 100%; aspect-ratio: 300 / 252; margin: 0 auto; touch-action: none; user-select: none; -webkit-user-select: none; }
.portal .hv-dial > svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.portal .hv-dial .trk { fill: none; stroke: var(--p-raised); stroke-width: 14; stroke-linecap: round; }
.portal .hv-dial .prg { fill: none; stroke: var(--p-sea); stroke-width: 14; stroke-linecap: round; }
.portal .hv-dial svg * { pointer-events: none; } /* också knoppen: den ligger över ringen */
.portal .hv-dial .hit { fill: none; stroke: transparent; stroke-width: 46; }
.portal .hv-dial[role="slider"] .hit { pointer-events: stroke; cursor: grab; }
.portal .hv-dial.drag .hit { cursor: grabbing; }
.portal .hv-dial .knob { fill: var(--p-card); stroke: var(--p-sea); stroke-width: 6; }
.portal .hv-dial .lim { font-size: 15px; font-weight: 700; fill: var(--p-mute); }
.portal .hv-dial.lock .prg, .portal .hv-dial.lock .knob { stroke: var(--p-line); }
.portal .hv-dial.lock[role="slider"] .hit { cursor: default; pointer-events: none; }
.portal .hv-dial:focus-visible { outline: 3px solid var(--p-focus); outline-offset: 4px; border-radius: 24px; }
.portal .hv-disc {
  position: absolute; left: 50%; top: 53.2%; width: 59.3%; aspect-ratio: 1; transform: translate(-50%, -50%);
  border-radius: 50%; display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; pointer-events: none;
  background: radial-gradient(circle at 35% 28%, var(--p-card), var(--p-raised) 78%);
  box-shadow: 0 14px 34px rgba(var(--shade), .12), inset 0 1px 0 rgba(255, 255, 255, .5);
}
.portal .hv-disc .l { font-size: 0.9375rem; font-weight: 700; color: var(--p-mute); }
.portal .hv-disc .n { font-size: 4rem; line-height: 1; font-weight: 800; letter-spacing: -0.05em; font-variant-numeric: tabular-nums; }
.portal .hv-disc .n small { font-size: 1.375rem; font-weight: 700; letter-spacing: 0; vertical-align: 1.9rem; margin-left: 2px; color: var(--p-mute); }
.portal .hv-disc .in { display: flex; align-items: center; gap: 4px; margin-top: 6px; font-size: 0.9375rem; font-weight: 700; }
.portal .hv-dial.lock .hv-disc .n { color: var(--p-mute); }

/* Statusraden: text, ikon och färg, aldrig bara färg. */
.portal .hv-status {
  display: flex; align-items: center; gap: 10px; min-height: 52px; padding: 10px 16px; border-radius: 18px;
  font-size: 1rem; font-weight: 700; line-height: 1.35; background: var(--p-sea-tint); color: var(--p-sea-dk);
}
.portal .hv-status.neutral { background: var(--p-raised); color: var(--p-ink); }
.portal .hv-status.cool { background: var(--p-cold-tint); color: var(--p-cold); }
.portal .hv-status.warn { background: var(--p-warm-tint); color: var(--p-warm-ink); }
.portal .hv-status.bad { background: var(--p-bad-tint); color: var(--p-bad); }
.portal .hv-status > svg, .portal .hv-status .spin { flex: none; }
.portal .spin { width: 20px; height: 20px; border-radius: 50%; border: 3px solid currentColor; border-right-color: transparent; animation: hv-spin .9s linear infinite; }
@keyframes hv-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .portal .spin { animation: none; border-right-color: currentColor; opacity: .6; } }

/* Kallare och Varmare: 72 px höga. */
.portal .hv-steps { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: 0; }
.portal .hv-step {
  min-height: 72px; border-radius: 20px; border: 1px solid var(--p-line); background: var(--p-card); color: var(--p-ink);
  box-shadow: var(--hv-shadow); display: flex; align-items: center; gap: 12px; padding: 0 14px; text-align: left;
  font: inherit; cursor: pointer;
}
.portal .hv-step.up { justify-content: flex-end; text-align: right; }
.portal .hv-step .pm { width: 46px; height: 46px; border-radius: 50%; flex: none; display: grid; place-items: center; background: var(--p-raised); color: var(--p-ink); }
.portal .hv-step.up .pm { background: var(--p-sea); color: var(--p-on-accent); }
.portal .hv-step b { display: block; font-size: 1.125rem; font-weight: 800; line-height: 1.2; }
.portal .hv-step small { display: block; font-size: 0.9375rem; font-weight: 600; color: var(--p-mute); }
html[data-text="largest"] .portal .hv-steps { grid-template-columns: minmax(0, 1fr); }

.portal .hv-card { display: flex; flex-direction: column; gap: 14px; padding: 18px; border-radius: 22px; background: var(--p-card); border: 1px solid var(--p-line); box-shadow: var(--hv-shadow); }

/* Menyn. Block, inte portalens flexmeny (.portal nav): som flexobjekt
   krympte raden till flikarnas bredd i mitten av skärmen. */
.portal .hv-nav {
  display: block;
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 10;
  background: var(--p-card); border-top: 1px solid var(--p-line);
  padding: 8px 8px max(12px, env(safe-area-inset-bottom, 0px));
}
.portal .hv-nav-in { max-width: 560px; margin: 0 auto; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 2px; }
.portal .hv-nav a {
  min-height: 64px; border-radius: 16px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; padding: 4px 0; color: var(--p-mute); font-size: 0.9375rem; font-weight: 700; text-decoration: none;
}
html[data-text] .portal .hv-nav a { font-size: 0.875rem; }
.portal .hv-nav a[aria-current="page"] { background: var(--p-raised); color: var(--p-ink); font-weight: 800; }
.portal .hv-nav .nav-ico { color: var(--p-mute); }
.portal .hv-nav .nav-ico.run { color: var(--p-sea); }

/* Snabbval (heaterquick.go): 2 × 2, en kolumn vid större text. Det valda
   har tjock ram, mjuk accent och en bock, inte bara färg. */
.portal .hv-row-h { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-top: 4px; }
.portal .hv-row-h h2 { margin: 0; font-size: 1.125rem; font-weight: 800; letter-spacing: -0.01em; }
.portal .hv-row-h span { font-size: 0.9375rem; font-weight: 600; color: var(--p-mute); }
.portal .hv-quick { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: 0; }
html[data-text] .portal .hv-quick { grid-template-columns: minmax(0, 1fr); }
.portal .hv-qk {
  position: relative; min-height: 78px; border-radius: 20px; border: 1px solid var(--p-line);
  background: var(--p-card); color: var(--p-ink); box-shadow: var(--hv-shadow); padding: 10px 12px;
  display: grid; grid-template-columns: 36px minmax(0, 1fr); gap: 9px; align-items: center; text-align: left;
  font: inherit; cursor: pointer;
}
.portal .hv-qk .ic { width: 36px; height: 36px; border-radius: 13px; display: grid; place-items: center; background: var(--p-raised); color: var(--p-ink); }
.portal .hv-qk .t { min-width: 0; }
.portal .hv-qk b { display: block; font-size: 1rem; font-weight: 800; line-height: 1.2; }
.portal .hv-qk small { display: block; margin-top: 1px; font-size: 0.9375rem; line-height: 1.3; color: var(--p-mute); }
.portal .hv-qk[aria-pressed="true"] { border: 3px solid var(--p-sea); background: var(--p-sea-tint); padding: 8px 10px; }
.portal .hv-qk[aria-pressed="true"] .ic { background: var(--p-sea); color: var(--p-on-accent); }
.portal .hv-qk[aria-pressed="true"] small { color: var(--p-sea-dk); }
.portal .hv-qk .tick { position: absolute; top: 7px; right: 7px; width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; background: var(--p-sea); color: var(--p-on-accent); }
.portal .hv-qk.sending { border-style: dashed; }

/* Rutan efter ett snabbval, längst ned över menyn. */
.portal .hv-undo {
  position: fixed; left: 50%; transform: translateX(-50%); z-index: 11;
  bottom: calc(96px + env(safe-area-inset-bottom, 0px)); width: min(524px, calc(100% - 32px));
  display: flex; align-items: center; gap: 10px; padding: 10px 10px 10px 16px; border-radius: 18px;
  background: var(--p-ink); color: var(--p-bg); box-shadow: 0 8px 28px rgba(var(--shade), .25);
  font-weight: 700; line-height: 1.35;
}
.portal .hv-undo-text { flex: 1 1 auto; }
.portal .hv-undo form { margin: 0; flex: none; }
/* Rutan har omvända färger: fokusringen i textens färg syns mot den. */
.portal .hv-undo :focus-visible { outline-color: currentColor; }
.portal .hv-undo-btn {
  min-height: 48px; padding: 0 16px; border-radius: 14px; border: 2px solid currentColor;
  background: transparent; color: inherit; font: inherit; font-weight: 800; cursor: pointer;
}

/* Vatten, Energi och Fläkt (heaterchoices.go): stora valkort med ikon,
   förklaring och en bock på det valda. */
.portal .hv-opts { display: flex; flex-direction: column; gap: 10px; margin: 0; }
.portal .hv-group-h { margin: 6px 0 0; font-size: 1rem; font-weight: 800; color: var(--p-mute); }
.portal .hv-opt {
  display: grid; grid-template-columns: 48px minmax(0, 1fr) 30px; gap: 12px; align-items: center;
  min-height: 72px; padding: 12px 14px; border-radius: 20px; border: 1px solid var(--p-line);
  background: var(--p-card); color: var(--p-ink); box-shadow: var(--hv-shadow); text-align: left; font: inherit; cursor: pointer;
}
.portal .hv-opt .ic { width: 48px; height: 48px; border-radius: 16px; display: grid; place-items: center; background: var(--p-raised); color: var(--p-ink); }
.portal .hv-opt .ic .nav-ico { color: var(--p-mute); }
.portal .hv-opt .ic .nav-ico.run { color: var(--p-sea); }
.portal .hv-opt b { display: block; font-size: 1.125rem; font-weight: 800; line-height: 1.25; }
.portal .hv-opt small { display: block; font-size: 0.9375rem; color: var(--p-mute); line-height: 1.35; }
.portal .hv-opt .fit { display: inline-flex; align-items: center; gap: 5px; margin-top: 4px; font-size: 0.9375rem; font-weight: 700; color: var(--p-sea-dk); }
.portal .hv-opt .fit.bad { color: var(--p-warm-ink); }
.portal .hv-opt .rad { width: 30px; height: 30px; border-radius: 50%; border: 2px solid var(--p-line-strong); display: grid; place-items: center; }
.portal .hv-opt[aria-pressed="true"] { border: 3px solid var(--p-sea); background: var(--p-sea-tint); padding: 10px 12px; }
.portal .hv-opt[aria-pressed="true"] .ic { background: var(--p-card); }
.portal .hv-opt[aria-pressed="true"] .rad { border-color: var(--p-sea); background: var(--p-sea); color: var(--p-on-accent); }
.portal .hv-opt[aria-pressed="true"] small { color: var(--p-sea-dk); }
.portal .hv-opt.sending { border-style: dashed; }

/* Säkringen: tre knappar i rad, och varningen under. */
.portal .hv-fuse { display: flex; flex-direction: column; gap: 12px; margin: 0; }
.portal .hv-fuse h2 { margin: 0; font-size: 1.125rem; font-weight: 800; }
.portal .hv-seg { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px; padding: 4px; border-radius: 18px; background: var(--p-raised); }
.portal .hv-seg button {
  min-height: 52px; border: 0; border-radius: 14px; background: transparent; color: var(--p-ink);
  font: inherit; font-size: 1.0625rem; font-weight: 800; cursor: pointer;
}
.portal .hv-seg button[aria-pressed="true"] { background: var(--p-card); box-shadow: inset 0 0 0 3px var(--p-sea); }
.portal .hv-hint { margin: 0; font-size: 0.9375rem; color: var(--p-mute); }
.portal .hv-box { display: flex; gap: 12px; align-items: flex-start; padding: 14px 16px; border-radius: 18px; line-height: 1.45; }
.portal .hv-box > svg { flex: none; margin-top: 2px; }
.portal .hv-box b { display: block; margin-bottom: 2px; font-size: 1.0625rem; }
.portal .hv-box.warn { background: var(--p-warm-tint); color: var(--p-warm-ink); border: 1px solid var(--p-warm-line); }
.portal .hv-box form { margin: 10px 0 0; }
.portal .hv-act {
  min-height: 48px; padding: 0 16px; border-radius: 14px; border: 2px solid currentColor;
  background: transparent; color: inherit; font: inherit; font-weight: 800; cursor: pointer;
}

/* Tillstånden (heaterBlockOf): offline och fel i rött, avstängd neutral med
   en stor Starta pannan. */
.portal .hv-box.bad { background: var(--p-bad-tint); color: var(--p-bad); border: 1px solid var(--p-bad-line); }
.portal .hv-box.neutral { background: var(--p-raised); color: var(--p-ink); }
.portal .hv-box ul { margin: 6px 0 0; padding-left: 20px; }
.portal .hv-box li { margin: 3px 0; }
.portal .hv-code { display: block; margin-top: 6px; font-size: 0.9375rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.portal .hv-box .hv-start { margin-top: 12px; gap: 8px; }
.portal .hv-conn.winter { color: var(--p-cold); }

/* Vinterförvaring täcker hela vyn. */
.portal .hv-winter { align-items: center; text-align: center; gap: 14px; padding-top: 28px; }
.portal .hv-snow { width: 96px; height: 96px; border-radius: 50%; display: grid; place-items: center; background: var(--p-cold-tint); color: var(--p-cold); }
.portal .hv-winter h1 { margin: 0; font-size: 1.625rem; font-weight: 800; letter-spacing: -0.02em; line-height: 1.2; }
.portal .hv-since { margin: 0; font-size: 1.0625rem; font-weight: 700; color: var(--p-mute); }
.portal .hv-points { list-style: none; margin: 4px 0; padding: 0; display: flex; flex-direction: column; gap: 10px; text-align: left; width: 100%; }
.portal .hv-points li { display: flex; gap: 12px; align-items: flex-start; padding: 12px 14px; border-radius: 16px; background: var(--p-card); border: 1px solid var(--p-line); }
.portal .hv-points li svg { flex: none; color: var(--p-cold); }
.portal .hv-confirm { width: 100%; text-align: left; }
.portal .hv-confirm > summary { list-style: none; cursor: pointer; }
.portal .hv-confirm > summary::-webkit-details-marker { display: none; }
.portal .hv-confirm[open] > summary { display: none; }
.portal .hv-confirm-body { display: flex; flex-direction: column; gap: 12px; padding: 16px; border-radius: 20px; background: var(--p-card); border: 1px solid var(--p-line); margin: 0; }
.portal .hv-confirm-body p { margin: 0; font-weight: 600; }

/* Mer (heatermore.go): veckan, anslutningen, Mina prylar och Mer i bilen. */
.portal .hv-card-h { margin: 0; font-size: 1.125rem; font-weight: 800; display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.portal .hv-card-h span { font-size: 0.9375rem; font-weight: 600; color: var(--p-mute); }
.portal .hv-stats { margin: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 8px; }
.portal .hv-stats div { padding: 10px 12px; border-radius: 14px; background: var(--p-raised); }
.portal .hv-stats dt { font-size: 0.9375rem; color: var(--p-mute); }
.portal .hv-stats dd { margin: 2px 0 0; font-size: 1.25rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.portal .hv-facts { margin: 0; display: flex; flex-direction: column; gap: 10px; }
.portal .hv-facts div { display: flex; justify-content: space-between; gap: 12px; }
.portal .hv-facts dt { color: var(--p-mute); }
.portal .hv-facts dd { margin: 0; font-weight: 700; text-align: right; }
.portal .hv-incar { display: flex; flex-direction: column; gap: 10px; align-items: flex-start; padding: 16px; border-radius: 20px; border: 2px dashed var(--p-line-strong); }
.portal .hv-incar p { margin: 0; color: var(--p-mute); }
.portal .hv-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.portal .hv-chips li { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 999px; background: var(--p-raised); font-size: 0.9375rem; font-weight: 700; }

/* Historik: kurvan, ritad i Go, och händelserna. */
.portal .hv-chart { width: 100%; height: auto; overflow: visible; }
.portal .hv-chart .temp { fill: none; stroke: var(--p-sea); stroke-width: 2.5; stroke-linejoin: round; }
.portal .hv-chart .set { fill: none; stroke: var(--p-mute); stroke-width: 2; stroke-dasharray: 6 5; }
.portal .hv-legend { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; font-size: 0.9375rem; font-weight: 600; }
.portal .hv-legend .sw { display: inline-block; width: 20px; height: 0; border-top: 3px solid var(--p-sea); }
.portal .hv-legend .sw.set { border-top: 2px dashed var(--p-mute); }
.portal .hv-events { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; border-radius: 18px; background: var(--p-card); border: 1px solid var(--p-line); }
.portal .hv-events li { display: grid; grid-template-columns: 6.5em minmax(0, 1fr); gap: 10px; padding: 12px 14px; border-top: 1px solid var(--p-line); }
.portal .hv-events li:first-child { border-top: 0; }
.portal .hv-events .t { color: var(--p-mute); font-variant-numeric: tabular-nums; }

/* Mer i bilen, förhandsvisningen. */
.portal .hv-plugin { flex-direction: row; align-items: center; gap: 12px; padding: 14px; }
.portal .hv-plugin .ic { width: 44px; height: 44px; flex: none; border-radius: 14px; display: grid; place-items: center; background: var(--p-raised); }
.portal .hv-plugin b { display: block; font-size: 1.0625rem; }
.portal .hv-plugin small { display: block; color: var(--p-mute); }
