@font-face{font-family:"Saira Condensed";font-style:normal;font-weight:500;font-display:swap;src:url("/fonts/saira-condensed-500.woff2") format("woff2")}
@font-face{font-family:"Saira Condensed";font-style:normal;font-weight:700;font-display:swap;src:url("/fonts/saira-condensed-700.woff2") format("woff2")}
@font-face{font-family:"Atkinson Hyperlegible";font-style:normal;font-weight:400;font-display:swap;src:url("/fonts/atkinson-hyperlegible-400.woff2") format("woff2")}
@font-face{font-family:"Atkinson Hyperlegible";font-style:normal;font-weight:700;font-display:swap;src:url("/fonts/atkinson-hyperlegible-700.woff2") format("woff2")}
@font-face{font-family:"JetBrains Mono";font-style:normal;font-weight:400 600;font-display:swap;src:url("/fonts/jetbrains-mono.woff2") format("woff2")}

/* One narrow column, mobile first. The LED board is the main thing on the page. */
:root{
  --bg:#eef1f4; --panel:#ffffff; --ink:#18212b; --muted:#5d6b78; --line:#d5dce3; --field:#f6f8fa;
  --board:#1b2a24; --board-edge:#2c3f36; --board-ink:#b9cbbf; --off:#2e3b35; --socket:#101a16;
  --accent:#2d6fb3; --accent-ink:#ffffff; --danger:#c0352a; --ok:#15803d; --warn:#e8b100;
  --f-display:"Saira Condensed","Arial Narrow",sans-serif;
  --f-body:"Atkinson Hyperlegible",system-ui,sans-serif;
  --f-data:"JetBrains Mono",ui-monospace,Menlo,monospace;
}
@media (prefers-color-scheme: dark){:root:not([data-theme="light"]){
  --bg:#0f1418; --panel:#161d23; --ink:#e7edf2; --muted:#93a1ad; --line:#26313a; --field:#0f1418;
  --board:#0b1612; --board-edge:#1f3229; --board-ink:#8fa797; --off:#1d2924; --socket:#050a08;
  --accent:#6aa5e3; --accent-ink:#0f1418; --danger:#ef6a5e; --ok:#4ade80; --warn:#f5c518; color-scheme:dark}}
:root[data-theme="dark"]{
  --bg:#0f1418; --panel:#161d23; --ink:#e7edf2; --muted:#93a1ad; --line:#26313a; --field:#0f1418;
  --board:#0b1612; --board-edge:#1f3229; --board-ink:#8fa797; --off:#1d2924; --socket:#050a08;
  --accent:#6aa5e3; --accent-ink:#0f1418; --danger:#ef6a5e; --ok:#4ade80; --warn:#f5c518; color-scheme:dark}

*{box-sizing:border-box}
[hidden]{display:none!important}
/* Read by a screen reader, not shown: the spoken text in place of shown text hidden from it (aria-hidden, G34). */
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}
body{background:var(--bg);color:var(--ink);font:16px/1.5 var(--f-body);margin:0}
.wrap{max-width:760px;margin:0 auto;padding-block:20px 48px;
  padding-left:max(16px,env(safe-area-inset-left,0px));padding-right:max(16px,env(safe-area-inset-right,0px))}
main{display:flex;flex-direction:column;gap:20px}
header{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:20px}
.brand{font:700 1.5rem/1 var(--f-display);letter-spacing:.04em;text-transform:uppercase;color:var(--ink);text-decoration:none}
.meta{display:flex;align-items:center;gap:12px;color:var(--muted);font-size:.85rem;flex-wrap:wrap}
.meta #session:empty{display:none}
button{font:inherit;color:var(--ink)}
a{color:var(--accent)}
p{margin:0}
.btn{display:inline-flex;align-items:center;gap:6px;background:var(--panel);border:1px solid var(--line);border-radius:8px;
  padding:7px 14px;min-height:40px;cursor:pointer;text-decoration:none;color:var(--ink);font-size:.9rem;white-space:nowrap}
.btn:hover{border-color:var(--muted)}
.btn:disabled{opacity:.5;cursor:default}
.btn-primary{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);font-weight:700}
.btn:focus-visible,.seg button:focus-visible,.brand:focus-visible,a:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

.banner{background:color-mix(in srgb,var(--warn) 18%,var(--panel));border:1px solid color-mix(in srgb,var(--warn) 50%,var(--line));
  padding:10px 14px;border-radius:8px;font-size:.9rem}

.status h1{font:700 clamp(2.2rem,8vw,3.6rem)/1 var(--f-display);margin:0;text-wrap:balance;letter-spacing:.01em}
.status .now{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;margin-top:8px}
.status .price{font:600 1.35rem var(--f-data);font-variant-numeric:tabular-nums}
/* An extreme price («100.000.000,0 øre/kWh · …») wraps at 320px, never clipped or scrolled sideways (J34-1). */
.status .now>*{min-width:0;overflow-wrap:anywhere}
.status .sub{color:var(--muted)}
.status .note{color:var(--muted);font-size:.85rem;margin-top:4px}
.status #show-area-prices{margin-top:6px}
.dot{display:inline-block;width:.55em;height:.55em;border-radius:50%;vertical-align:.18em;margin-right:.3em;
  box-shadow:0 0 0 1px color-mix(in srgb,var(--ink) 25%,transparent)}
.dot.off{background:var(--off)}

/* LED board */
.board{background:var(--board);border:2px solid var(--board-edge);border-radius:14px;padding:18px 14px 12px;
  box-shadow:inset 0 2px 0 rgba(255,255,255,.04)}
.board-head{display:flex;justify-content:space-between;gap:8px;flex-wrap:wrap;color:var(--board-ink);font:500 .78rem var(--f-data);
  text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px}
.leds{display:grid;grid-template-columns:repeat(12,1fr);gap:14px clamp(4px,1.4vw,10px);list-style:none;margin:0;padding:0}
.led{display:flex;flex-direction:column;align-items:center;gap:8px;min-width:0;padding:6px 0 0}
.bulb{--c:var(--off);--glow:transparent;--ring:transparent;position:relative;
  width:min(30px,calc(100% - 8px));aspect-ratio:1;border-radius:50%;background:var(--off);
  box-shadow:0 0 0 3px var(--socket),0 0 0 5px var(--ring),0 0 12px 1px var(--glow),inset 0 2px 4px rgba(0,0,0,.55)}
.bulb::after{content:"";position:absolute;left:24%;top:13%;width:34%;height:22%;border-radius:50%;background:rgba(255,255,255,.08)}
.bulb.lit{--glow:color-mix(in srgb,var(--c) 45%,transparent);
  background:radial-gradient(circle at 50% 38%,color-mix(in srgb,var(--c) 55%,#fff) 0%,var(--c) 48%,color-mix(in srgb,var(--c) 72%,#000) 100%)}
.bulb.lit::after{background:rgba(255,255,255,.55)}
.led.now .bulb{--ring:rgba(255,255,255,.9)}
.led .h{font:600 .72rem var(--f-data);color:var(--board-ink);font-variant-numeric:tabular-nums}
.led .p{font:400 .62rem var(--f-data);color:var(--board-ink);opacity:.75;font-variant-numeric:tabular-nums;
  max-width:100%;white-space:nowrap;text-align:center}
/* The digits are kr/kWh with two decimals (STROMLYS-PRIS-MASKINE: «5,84», «−12,50»). They never break and are never
   clipped, so «10,00» can never read as «10» and «,00» (S1). The column is ~17.2px at 320px, ~21.7px apart. By length
   (app.js ledDigitsClass; the comma and a minus count): 4 («5,84», the usual price) and 5 («12,50», «−0,05») fit it at
   ~7.5 and ~5.9px, 6 («−12,50», «100,66») at 5.6px; 7 («1270,00», near the ±1e6 DKK/MWh clamp) at .325rem and -.12em
   is ~17.5px, a hair into the gap; 8 and more («−1250,00») would only fit far smaller, so they get .285rem at -.12em,
   ~17.5px: every realistic neighbour keeps at least 4px clear. The long classes drop the column's max-width, so .led's
   align-items:center spills a wider one equally on both sides, never only towards the next column. From 360px the column
   is at least ~20px, and every class is bigger (the media rule below). */
.led .p.is-4{font-size:.47rem;letter-spacing:-.03em;white-space:nowrap;overflow:visible;max-width:none}
.led .p.is-5{font-size:.37rem;letter-spacing:-.03em;white-space:nowrap;overflow:visible;max-width:none}
.led .p.is-6{font-size:.35rem;letter-spacing:-.1em;white-space:nowrap;overflow:visible;max-width:none}
.led .p.is-7{font-size:.325rem;letter-spacing:-.12em;white-space:nowrap;overflow:visible;max-width:none}
.led .p.is-8{font-size:.285rem;letter-spacing:-.12em;white-space:nowrap;overflow:visible;max-width:none}
@media (min-width:360px){
.led .p.is-4{font-size:.54rem}
.led .p.is-5{font-size:.43rem}
.led .p.is-6{font-size:.41rem}
.led .p.is-7{font-size:.37rem}
.led .p.is-8{font-size:.34rem}
}
.led.now .h{color:#fff}
/* The machine calculator's start (krav K5): a tap on an LED or a chart bar picks it, and it is marked on both. */
.leds .led{cursor:pointer}
.led.picked{outline:2px solid var(--accent);outline-offset:1px;border-radius:8px}
.led.picked .h{background:var(--accent);color:var(--accent-ink);border-radius:4px;padding:0 2px}
.legend{display:flex;gap:6px 16px;flex-wrap:wrap;margin-top:14px;color:var(--board-ink);font-size:.78rem}
.legend>span{min-width:0;overflow-wrap:anywhere}
.legend .dot{box-shadow:none}
.legend .dot.off{box-shadow:0 0 0 1.5px var(--board-ink)}

section.card{background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:16px}
h2{font:700 1.15rem/1.2 var(--f-display);text-transform:uppercase;letter-spacing:.05em;margin:0 0 10px}
.card h2 + * + h2{margin-top:18px}
.seg{display:flex;flex-wrap:wrap;gap:8px}
.seg button{background:transparent;border:1px solid var(--line);border-radius:8px;padding:8px 12px;min-height:40px;cursor:pointer;
  font:600 .85rem var(--f-data);display:inline-flex;align-items:baseline;gap:8px}
.seg button:hover{border-color:var(--muted)}
.seg button[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:var(--panel)}
/* Gang S1 (PR #51): .seg button is more specific than .btn-primary / .btn-danger, so Tilslut, Gem and
   confirm-Fjern lampe were white text on a transparent background in the light theme (~1:1). These
   keep the filled backgrounds inside .seg in both themes (contrast ≥ 4,5:1: light primary 5,20, light
   danger 5,55, dark primary 7,15, dark danger 5,59). */
.seg button.btn-primary{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);font-weight:700}
.seg button.btn-danger{background:var(--danger);border-color:var(--danger);color:var(--panel);font-weight:700}
.seg button.btn-primary:hover{border-color:var(--accent)}
.seg button.btn-danger:hover{border-color:var(--danger)}
.muted{color:var(--muted);font-size:.88rem}
.seg + .muted{margin-top:10px}
/* SL-TEMA: the colour theme picker in the header, a compact .seg: three joined radios on panel, the picked one filled as
   .seg's pressed one. Lys and Mørk set data-theme on <html> (the selectors above), System sets none. */
.seg.theme{gap:0;flex-wrap:nowrap}
.theme button{background:var(--panel);border-radius:0;padding:7px 10px;font-size:.78rem;min-height:44px}
.theme button + button{margin-left:-1px}
.theme button:first-child{border-radius:8px 0 0 8px}
.theme button:last-child{border-radius:0 8px 8px 0}
.theme button[aria-checked="true"]{background:var(--ink);border-color:var(--ink);color:var(--panel)}
.theme button:focus-visible{position:relative;z-index:1}

/* The chart of every known hour (SL-GRAF): kr/kWh up, time along, one bar (a button) per hour in its step's color,
   graded by its price (app.js barRgb).
   The axis stays at the left while the bars scroll sideways when they do not fit: 22px a bar on a phone (a finger's
   width), 16px from 600px, so a whole today-and-tomorrow (up to 49 hours) usually fits a desktop card. */
.chart{overflow-x:auto;overscroll-behavior-x:contain;padding-bottom:4px}
.chart-plot{--plot-h:180px;--col:22px;--axis:max(44px,calc(var(--axis-ch,4) * .4rem + 12px));display:flex;align-items:flex-start;padding-top:18px;
  min-width:calc(var(--axis) + var(--n,24) * var(--col))}
.chart-y{position:sticky;left:0;z-index:3;flex:0 0 var(--axis);height:var(--plot-h);background:var(--panel)}
/* The axis also covers the label strip over the bars and the time row under them, so nothing scrolled under it shows. */
.chart-y::before,.chart-y::after{content:"";position:absolute;left:0;right:0;background:var(--panel)}
.chart-y::before{bottom:100%;height:18px}
.chart-y::after{top:100%;height:1.4rem}
.chart-tick{position:absolute;z-index:1;right:6px;transform:translateY(50%);font:400 .66rem var(--f-data);color:var(--muted);
  font-variant-numeric:tabular-nums;white-space:nowrap}
.chart-cols{position:relative;flex:1 1 auto;display:flex;min-width:0}
.chart-grid{position:absolute;left:0;right:0;top:0;height:var(--plot-h);pointer-events:none}
.chart-line{position:absolute;left:0;right:0;height:1px;background:var(--line)}
.chart-line.is-zero{background:var(--muted)}
.bar{position:relative;z-index:1;flex:1 0 var(--col);min-width:0;display:flex;flex-direction:column;background:transparent;
  border:0;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}
.bar.is-empty{cursor:default}
.bar-plot{position:relative;display:block;height:var(--plot-h)}
.bar-fill{position:absolute;left:3px;right:3px;border-radius:3px 3px 1px 1px;transition:opacity .15s;
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ink) 16%,transparent)}
.bar-fill.is-missing{background:repeating-linear-gradient(45deg,var(--line),var(--line) 3px,transparent 3px,transparent 6px)}
.bar.is-dimmed .bar-fill{opacity:.25}
.bar-value{position:absolute;left:50%;transform:translateX(-50%);margin-bottom:3px;z-index:2;padding:0 3px;border-radius:3px;
  background:var(--panel);color:var(--ink);font:600 .72rem var(--f-data);font-variant-numeric:tabular-nums;white-space:nowrap}
.chart-x{display:block;height:1.4rem;line-height:1.4rem;text-align:center;white-space:nowrap;font:400 .66rem/1.4rem var(--f-data);
  color:var(--muted);font-variant-numeric:tabular-nums}
.bar.is-now .chart-x{color:var(--ink);font-weight:600}
/* Tomorrow starts after a dashed line, named over it. */
.bar.is-midnight .bar-plot::before{content:"";position:absolute;left:0;top:-16px;bottom:0;border-left:1px dashed var(--muted)}
.chart-day{position:absolute;left:4px;top:-17px;font:400 .62rem var(--f-data);color:var(--muted);white-space:nowrap}
/* An hour without a price before the last one with a price: a gap, hatched at the base. */
.bar.is-empty .bar-plot::after{content:"";position:absolute;left:3px;right:3px;bottom:0;height:4px;
  background:repeating-linear-gradient(90deg,var(--line),var(--line) 3px,transparent 3px,transparent 5px)}
/* The calculator's start (krav K5) as on the board: an accent mark under its bar. */
.bar.picked .bar-plot::after{content:"";position:absolute;left:2px;right:2px;bottom:-4px;height:3px;border-radius:2px;background:var(--accent)}
.bar:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;border-radius:4px}
.chart-readout{margin-top:10px;font:400 .85rem/1.5 var(--f-data);overflow-wrap:anywhere}
.chart-readout:empty{display:none}
#chart-note{margin-top:6px}
@media (min-width:600px){.chart-plot{--col:16px}}

/* SL-GRAF: a step's light while logged in (the account's own scale): it breathes, or blinks slowly or fast, on the LED,
   its legend dot and a tapped chart bar. Never with reduced motion: then it stays steady. */
@keyframes led-breathe{0%,100%{opacity:1}50%{opacity:.35}}
@keyframes led-blink{0%,49%{opacity:1}50%,100%{opacity:.15}}
[data-effect="pulse"]{animation:led-breathe 3s ease-in-out infinite}
[data-effect="blink-slow"]{animation:led-blink 2s linear infinite}
[data-effect="blink-fast"]{animation:led-blink .6s linear infinite}
@media (prefers-reduced-motion: reduce){[data-effect]{animation:none}}

#devices{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:10px}
#devices li{background:var(--field);border:1px solid var(--line);border-radius:8px;padding:10px 12px}
#devices li p{display:flex;justify-content:space-between;gap:12px;font-size:.9rem}
#devices li p span:first-child{color:var(--muted)}
#devices li p span:last-child{font-family:var(--f-data);text-align:right}
#devices li .seg{margin-top:8px}
/* A lamp's own tariffs (SL24): labels over full-width inputs, stacked. */
#devices li .tariffs{margin-top:10px}
#devices li .tariffs summary{cursor:pointer;font:700 .95rem var(--f-display);text-transform:uppercase;letter-spacing:.05em;min-height:40px;
  display:flex;align-items:center}
#devices li .tariffs summary:focus-visible,#devices li .tariffs input:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
#devices li .tariffs form{display:flex;flex-direction:column;gap:10px;margin-top:6px}
#devices li .tariffs p{display:block;font-size:.88rem}
#devices li .tariffs p:empty{display:none}
#devices li .tariff{display:flex;flex-direction:column;gap:4px}
#devices li .tariff label{font-size:.9rem}
#devices li .tariff input{width:100%;min-height:40px;padding:7px 10px;font:400 1rem var(--f-data);color:var(--ink);
  background:var(--panel);border:1px solid var(--line);border-radius:8px}
#devices li .tariffs [role="status"]{margin-top:8px}
#devices li .tariff .error{font-weight:700}

/* The machine calculator (STROMLYS-PRIS-MASKINE; SL-APPARAT-UX): tiles to pick an apparat, then a card under them with
   a window on a strip of the known hours. Every text wraps at 320px; two tiles a row on a phone, all five on a desktop. */
.tiles{list-style:none;padding:0;margin:14px 0 0;display:grid;grid-template-columns:repeat(auto-fill,minmax(116px,1fr));gap:8px}
.tile-item{display:flex;flex-direction:column;gap:6px;min-width:0}
.tile{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;flex:1 1 auto;width:100%;min-height:118px;
  padding:14px 4px 12px;background:var(--field);border:1px solid var(--line);border-radius:12px;cursor:pointer;text-align:center;
  font:inherit;color:var(--ink);-webkit-tap-highlight-color:transparent;transition:border-color .15s,background-color .15s}
.tile:hover{border-color:var(--muted)}
.tile[aria-pressed="true"]{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 16%,var(--field));
  box-shadow:inset 0 0 0 1px var(--accent)}
.tile:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.tile-icon{width:34px;height:34px;margin-bottom:4px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.tile-name{font-weight:700;font-size:.95rem;line-height:1.25;max-width:100%;overflow-wrap:anywhere}
.tile-facts{font:400 .76rem var(--f-data);color:var(--muted);font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
.tile-item .machine-actions{justify-content:center}
.tiles-empty{grid-column:1/-1;display:flex;flex-direction:column;align-items:flex-start;gap:10px;padding:14px 16px;
  background:var(--field);border:1px dashed var(--muted);border-radius:12px}
.machine-card{margin-top:14px;background:var(--field);border:1px solid var(--line);border-radius:12px;padding:16px;min-width:0}
.machine-card h3{font:700 1.2rem/1.3 var(--f-body);margin:0;overflow-wrap:anywhere}
.machine-facts{font:400 .85rem var(--f-data);color:var(--muted);margin-top:2px}
/* The strip: one cell per known hour in its step's color (app.js sets it from the answer, as the chart), tomorrow after a
   dashed line. The window over it is --d hours wide from hour --i of --n (the gap counted), snapped to whole hours. It
   is dragged by itself or its handle (no page scroll while dragging: touch-action), and moved with the arrow keys. */
.strip{--gap:2px;--h:56px;position:relative;margin-top:30px;user-select:none;-webkit-user-select:none}
.strip-track{display:grid;grid-template-columns:repeat(var(--n),minmax(0,1fr));gap:var(--gap);height:var(--h);cursor:pointer;
  -webkit-tap-highlight-color:transparent}
.strip-cell{position:relative;border-radius:3px;background:var(--off);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ink) 12%,transparent)}
.strip-cell.is-empty{background:repeating-linear-gradient(45deg,var(--line),var(--line) 3px,transparent 3px,transparent 6px)}
.strip-cell.is-missing{background:var(--muted)}
.strip-cell.is-now{box-shadow:inset 0 0 0 2px color-mix(in srgb,var(--ink) 75%,transparent)}
.strip-cell.is-midnight::before{content:"";position:absolute;left:calc(var(--gap) / -2 - 1px);top:-8px;bottom:-8px;border-left:1px dashed var(--muted)}
.strip-window{--i:0;--d:1;position:absolute;top:-6px;height:calc(var(--h) + 12px);left:calc((100% + var(--gap)) * var(--i) / var(--n) - 5px);
  width:calc((100% + var(--gap)) * var(--d) / var(--n) - var(--gap) + 10px);border:3px solid var(--ink);border-radius:9px;
  box-shadow:0 0 0 2px var(--field),0 0 0 4px color-mix(in srgb,var(--accent) 60%,transparent);cursor:grab;touch-action:none;
  transition:left .15s ease-out,width .15s ease-out}
.strip-window.is-dragging{cursor:grabbing;transition:none}
/* The run goes on past the last known price: the window is cut there, its open end dashed. */
.strip-window.is-cut{border-right-style:dashed;border-top-right-radius:2px;border-bottom-right-radius:2px}
.strip-window:focus-visible{outline:2px solid var(--accent);outline-offset:5px}
.strip-handle{position:absolute;left:50%;top:-14px;width:48px;height:28px;transform:translateX(-50%);display:flex;align-items:center;
  justify-content:center}
.strip-handle::before{content:"";width:30px;height:10px;border-radius:5px;background:var(--accent);box-shadow:0 0 0 2px var(--field)}
@media (pointer:coarse){.strip-handle{top:-18px;width:56px;height:36px}.strip-handle::before{width:38px;height:12px}}
.strip-x{display:grid;grid-template-columns:repeat(var(--n),minmax(0,1fr));gap:var(--gap);margin-top:12px;
  font:400 .66rem/1.3 var(--f-data);color:var(--muted);font-variant-numeric:tabular-nums}
.strip-x>span{display:flex;flex-direction:column;align-items:center;min-width:0;white-space:nowrap}
.strip-x>span:first-child{color:var(--ink);font-weight:600}
.strip-day{align-self:flex-start;margin-top:2px}
.strip-help{font-size:.8rem}
.machine-result{display:flex;align-items:baseline;justify-content:space-between;flex-wrap:wrap;gap:2px 16px;margin-top:14px;overflow-wrap:anywhere}
.machine-cost{font:600 1.6rem var(--f-data);font-variant-numeric:tabular-nums}
.machine-when{color:var(--muted)}
.machine-more{display:flex;flex-direction:column;gap:10px;margin-top:12px;overflow-wrap:anywhere}
/* The cheapest start: a button that moves the window there, or a line when the window is on it already. */
.machine-cheapest,.machine-cheapest-here{background:color-mix(in srgb,var(--ok) 14%,var(--field));
  border:1px solid color-mix(in srgb,var(--ok) 40%,var(--line));border-radius:10px;padding:12px 14px;font:700 .95rem/1.45 var(--f-body)}
.machine-cheapest{display:flex;flex-direction:column;align-items:flex-start;gap:6px;width:100%;text-align:left;cursor:pointer;color:var(--ink)}
.machine-cheapest:hover{border-color:var(--ok)}
.machine-cheapest:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.machine-cheapest-go{font:600 .82rem var(--f-data);color:var(--ok);text-decoration:underline;text-underline-offset:3px}
.machine-missing{background:color-mix(in srgb,var(--warn) 18%,var(--panel));border:1px solid color-mix(in srgb,var(--warn) 50%,var(--line));
  padding:8px 12px;border-radius:8px;font-size:.9rem}
.machine-how summary{cursor:pointer;color:var(--muted);font-size:.88rem;min-height:36px;display:flex;align-items:center}
.machine-how summary::before{content:"";margin-right:8px;border-left:6px solid currentColor;border-block:4px solid transparent;transition:transform .15s}
.machine-how[open] summary::before{transform:rotate(90deg)}
.machine-how summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.machine-parts{margin:6px 0 0;padding-left:1.2rem;font:400 .85rem var(--f-data)}
@media (prefers-reduced-motion: reduce){.tile,.strip-window,.machine-how summary::before{transition:none}}
.field{display:flex;flex-direction:column;gap:4px;min-width:0}
.field label{font-size:.9rem}
.field input,.field select{width:100%;max-width:100%;min-height:40px;padding:7px 10px;font:400 1rem var(--f-data);color:var(--ink);
  background:var(--panel);border:1px solid var(--line);border-radius:8px}
.field input[type="color"]{padding:2px;width:4rem}
.field input:focus-visible,.field select:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.field .error{font-weight:700;font-size:.85rem}
.own-machines{margin-top:16px;border-top:1px solid var(--line);padding-top:12px}
.own-machines h3,.scale summary{font:700 .95rem var(--f-display);text-transform:uppercase;letter-spacing:.05em;margin:0 0 8px}
.own-machines form,.scale form{display:flex;flex-direction:column;gap:10px}
.own-machines [role="status"],.scale [role="status"]{margin-top:8px}
.scale summary{cursor:pointer;min-height:40px;display:flex;align-items:center}
.scale summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.scale-steps{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:10px}
.scale-step{background:var(--field);border:1px solid var(--line);border-radius:8px;padding:8px 12px;display:flex;flex-direction:column;gap:8px}
.scale-step-title{font-weight:700}

/* SL-PAIR: «Tilslut lampe» with the lamp's code, a lamp's own settings («Lampen»), its status with the ring's error codes
   and «Fjern lampe». Every control a finger uses is at least 44px. */
.pair{margin:4px 0 12px}
.pair .btn,.lamp .btn,.lamp-remove .btn{min-height:44px}
.pair-form{display:flex;flex-direction:column;gap:10px;margin-top:12px}
.pair-form label{font-weight:700}
.pair-code{width:100%;max-width:17rem;min-height:56px;padding:8px 12px;font:600 1.6rem var(--f-data);letter-spacing:.12em;
  text-transform:uppercase;color:var(--ink);background:var(--panel);border:1px solid var(--line);border-radius:8px}
.pair-code:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.pair-form .error,.lamp .error,.lamp-remove .error{font-weight:700;font-size:.85rem}
.pair-form .error:empty,#devices-note:empty{display:none}
#devices-note{margin-bottom:10px}
#devices li .unseen{display:block;margin-top:8px;padding:8px 12px;border-radius:8px;font-size:.88rem;
  background:color-mix(in srgb,var(--warn) 18%,var(--panel));border:1px solid color-mix(in srgb,var(--warn) 50%,var(--line))}
#devices li .lamp,#devices li .lamp-status,#devices li .lamp-remove{margin-top:10px}
#devices li .lamp summary,#devices li .lamp-status summary{cursor:pointer;font:700 .95rem var(--f-display);text-transform:uppercase;
  letter-spacing:.05em;min-height:44px;display:flex;align-items:center}
#devices li .lamp summary:focus-visible,#devices li .lamp-status summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
#devices li .lamp p,#devices li .lamp-status p,#devices li .lamp-remove p{display:block;font-size:.88rem}
#devices li .lamp p:empty,#devices li .lamp-remove p:empty{display:none}
#devices li .lamp form{display:flex;flex-direction:column;gap:12px;margin-top:6px}
.kv{display:flex;justify-content:space-between;gap:12px;font-size:.9rem}
.kv span:first-child{color:var(--muted)}
/* SL-FACTORY (Skærm SL-LYSSTYRKE-UX): a brightness, mobile first. − and + of 56px with a filled background in both
   themes around the value, large as «25 %» (the number is typable: dashed underline), then a full-width slider with a
   28px thumb on a 44px hit area. No transitions, so nothing moves under prefers-reduced-motion either. */
.level{display:flex;flex-direction:column;gap:6px;max-width:30rem}
.level label{font-weight:700;font-size:.95rem}
.level-row{display:flex;align-items:center;justify-content:space-between;gap:12px}
.level-row button{flex:none;width:56px;height:56px;font:700 1.7rem/1 var(--f-data);color:var(--ink);
  background:color-mix(in srgb,var(--accent) 14%,var(--panel));border:1px solid color-mix(in srgb,var(--accent) 45%,var(--line));
  border-radius:12px;cursor:pointer;touch-action:manipulation;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none}
.level-value{flex:1;display:flex;align-items:baseline;justify-content:center;gap:.25em;min-width:0}
.level-input{width:3.4ch;min-height:56px;padding:0 2px;text-align:right;font:700 2.5rem/1 var(--f-data);color:var(--ink);
  background:transparent;border:0;border-bottom:2px dashed var(--muted);border-radius:0}
@supports (field-sizing:content){.level-input{width:auto;field-sizing:content;min-width:1.2ch}}
.level-value .unit{font:700 1.7rem var(--f-data);color:var(--ink)}
.level-slider{-webkit-appearance:none;appearance:none;width:100%;height:44px;margin:0;background:transparent;cursor:pointer}
.level-slider::-webkit-slider-runnable-track{height:8px;border-radius:4px;background:color-mix(in srgb,var(--muted) 55%,var(--field))}
.level-slider::-moz-range-track{height:8px;border-radius:4px;background:color-mix(in srgb,var(--muted) 55%,var(--field))}
.level-slider::-moz-range-progress{height:8px;border-radius:4px;background:var(--accent)}
.level-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;box-sizing:border-box;width:28px;height:28px;
  margin-top:-10px;border-radius:50%;background:var(--accent);border:3px solid var(--panel);box-shadow:0 0 0 1px var(--accent)}
.level-slider::-moz-range-thumb{box-sizing:border-box;width:28px;height:28px;border-radius:50%;background:var(--accent);
  border:3px solid var(--panel);box-shadow:0 0 0 1px var(--accent)}
.level-row button:focus-visible,.level-input:focus-visible,.level-slider:focus-visible,.lamp select:focus-visible,
.check input:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.level-input:focus-visible{border-bottom-color:var(--accent)}
.hours{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.lamp .field select{min-height:44px}
.check{display:flex;align-items:flex-start;gap:10px;min-height:44px}
.check input{flex:none;width:22px;height:22px;margin:11px 0 0}
.check label{padding-top:10px;font-size:.9rem}
.lamp fieldset{border:1px solid var(--line);border-radius:8px;padding:6px 12px 10px;margin:0;min-width:0}
.lamp legend{font-weight:700;font-size:.9rem;padding:0 4px}
.confirm{display:flex;flex-direction:column;gap:8px}
.btn-warn{border-color:var(--warn);background:color-mix(in srgb,var(--warn) 18%,var(--panel));font-weight:700}
.btn-danger{background:var(--danger);border-color:var(--danger);color:var(--panel);font-weight:700}
/* Status: the ring's error areas in the demo's colours; the signature is the ring's last four LEDs on a dark socket. */
.err-network{--err:#2563EB}
.err-prices{--err:#F97316}
.err-system{--err:#EAB308}
.err-lamp{--err:#A855F7}
#devices li .lamp-status h3{font:700 .95rem var(--f-body);margin:12px 0 6px}
#devices li .lamp-status h4{font:700 .9rem var(--f-body);margin:12px 0 4px}
.status-now{display:flex;flex-direction:column;gap:8px}
.err-banner{display:block;width:100%;min-height:44px;text-align:left;cursor:pointer;color:var(--ink);font:inherit;font-size:.9rem;
  border-left:6px solid var(--err)}
.status-ok .dot{background:var(--ok)}
.err-group h4 .dot{background:var(--err)}
.err-entry{display:flex;flex-direction:column;gap:4px;padding:8px 0;border-top:1px solid var(--line);overflow-wrap:anywhere}
.err-entry:focus{outline:2px solid var(--accent);outline-offset:2px}
.err-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.sig{display:inline-flex;gap:4px;padding:4px 6px;border-radius:999px;background:var(--board)}
.sig-dot{width:14px;height:14px;border-radius:50%;background:var(--off)}
.sig-area{background:var(--err)}
.sig-on{background:#fff}
.sig-marker{background:#2563EB;animation:err-marker 1s step-end infinite}
@keyframes err-marker{0%{background:#2563EB}25%{background:#F97316}50%{background:#EAB308}75%{background:#A855F7}}
@media (prefers-reduced-motion: reduce){.sig-marker{animation:none;background:conic-gradient(#2563EB 0 25%,#F97316 0 50%,#EAB308 0 75%,#A855F7 0)}}

footer{color:var(--muted);font-size:.8rem;display:flex;flex-direction:column;gap:4px}
