:root {
  /* Ekas huisstijl — blauw primair, rood accent, met diepte */
  --bg: #eef2f8;
  --bg-2: #f7f9fc;
  --card: #ffffff;
  --ink: #132338;
  --ink-soft: #5c6b82;
  --ink-faint: #8a97ab;
  --line: #e3e9f2;
  --line-2: #d3dbe8;
  --brand: #1b52a0;
  --brand-2: #2e6bc4;
  --brand-dark: #0f3a78;
  --brand-soft: #e7eefb;
  --accent: #d81f2a;
  --accent-soft: #fdeaeb;
  --ok: #14a05a;
  --ok-soft: #e2f6ec;
  --off: #97a4b6;
  --off-soft: #eef1f6;
  /* --warn = rood/foutkleur: storing-status, maar ook algemeen hergebruikt
     voor verwijderknoppen en foutmeldingen — niet hetzelfde als "waarschuwing". */
  --warn: #c9432b;
  --warn-soft: #fbe8e3;
  /* --amber = waarschuwing-status (bewakingsgrens genaderd). */
  --amber: #b26a00;
  --amber-soft: #fff3e0;
  /* --manual = handmatige modus (Hand i.p.v. Auto) — bewuste operatorkeuze,
     geen storing of waarschuwing, dus een eigen neutrale kleur. */
  --manual: #2f7fd0;
  --manual-soft: #e4eefb;
  /* --cool = geleverde koeling in de grafieken. Bewust turkoois en niet het
     huisstijlblauw: warmte staat al in --brand, en naast elkaar moeten die twee
     zonder nadenken uit elkaar te houden zijn. */
  --cool: #0d8f9e;
  --cool-2: #2ab6c4;
  --cool-soft: #e2f5f8;
  --shadow-sm: 0 1px 2px rgba(19, 35, 56, .06), 0 2px 8px rgba(19, 35, 56, .05);
  --shadow: 0 2px 6px rgba(19, 35, 56, .07), 0 12px 30px rgba(19, 35, 56, .08);
  --shadow-lg: 0 10px 24px rgba(19, 35, 56, .12), 0 30px 70px rgba(19, 35, 56, .16);
  --radius: 16px;
  --radius-sm: 10px;
  --ease: cubic-bezier(.22, .61, .36, 1);
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: radial-gradient(1200px 500px at 50% -200px, #ffffff 0%, var(--bg) 60%);
  min-height: 100vh;
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  /* Niets mag de pagina breder maken dan de viewport (mobiel uitzoomen). */
  overflow-x: hidden;
}
h1, h2, h3 { margin: 0; font-weight: 700; letter-spacing: -.01em; }
button { font-family: inherit; }

/* ---------- Topbar ---------- */
.topbar {
  display: flex; align-items: center; justify-content: space-between; gap: 14px 20px;
  padding: 14px 26px;
  background: rgba(255, 255, 255, .82);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 600;
  /* Nooit horizontaal overlopen: bij een drukke balk (superuser met
     voorbeeldweergave + modus-schakelaar) wrapt de rechter cluster netjes naar
     een tweede regel i.p.v. de pagina breder te maken. Zolang alles past blijft
     het één regel met de bestaande spreiding. */
  flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: 14px; }
.brand .logo-img { height: 38px; width: auto; display: block; }
.brand .brand-txt { padding-left: 14px; border-left: 1px solid var(--line-2); }
.brand h1 { font-size: 18px; }
.brand .sub { margin: 2px 0 0; color: var(--accent); font-size: 12px; font-weight: 600; }

.tabs { display: flex; gap: 4px; }
.tab {
  border: none; background: transparent; color: var(--ink-soft);
  padding: 9px 16px; border-radius: 10px; cursor: pointer; font-size: 14px; font-weight: 600;
  transition: background .16s var(--ease), color .16s var(--ease);
  display: inline-flex; align-items: center; gap: 7px;
}
.tab .tab-icon { width: 16px; height: 16px; opacity: .7; transition: opacity .16s; }
.tab:hover { background: var(--bg-2); color: var(--ink); }
.tab.active { background: var(--brand); color: #fff; box-shadow: 0 4px 12px rgba(27, 82, 160, .3); }
.tab.active .tab-icon { opacity: 1; stroke: #fff; }

/* ---------- Voorbeeldweergave (superuser "bekijk als") ---------- */
.preview-switch { display: flex; align-items: center; gap: 8px; }
.preview-switch-label { font-size: 11px; font-weight: 600; color: var(--ink-faint); }
.preview-roles { display: flex; gap: 2px; padding: 3px; background: var(--bg-2); border: 1px solid var(--line-2); border-radius: 999px; }
.prole {
  border: none; background: transparent; color: var(--ink-soft);
  padding: 5px 12px; border-radius: 999px; cursor: pointer; font-size: 12px; font-weight: 600;
  transition: background .16s var(--ease), color .16s var(--ease);
}
.prole:hover { color: var(--ink); }
.prole.active { background: var(--brand); color: #fff; }
.preview-banner {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  padding: 8px 20px; background: var(--amber-soft); color: var(--amber);
  border-bottom: 1px solid var(--line); font-size: 13px; font-weight: 600;
  position: sticky; top: 0; z-index: 599;
}
.preview-user-select {
  border: 1px solid var(--amber); border-radius: 999px; background: transparent; color: var(--amber);
  padding: 4px 10px; font-size: 12px; font-weight: 700; font-family: inherit; cursor: pointer;
}
.preview-user-select:hover { background: var(--amber-soft); }
.preview-stop-btn {
  border: 1px solid var(--amber); background: transparent; color: var(--amber);
  padding: 4px 12px; border-radius: 999px; cursor: pointer; font-size: 12px; font-weight: 700;
  transition: all .16s var(--ease);
}
.preview-stop-btn:hover { background: var(--amber); color: #fff; }
@media (max-width: 760px) {
  .preview-switch { display: none; }
  .preview-banner { font-size: 12px; padding: 8px 12px; }
}

.topbar-user { display: flex; align-items: center; gap: 12px; }
.user-chip { text-align: right; line-height: 1.2; }
.user-chip .user-name { display: block; font-weight: 700; font-size: 14px; }
.user-chip .user-role { display: block; font-size: 11px; color: var(--accent); font-weight: 600; }
.logout-btn {
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line-2); background: var(--card); color: var(--ink);
  padding: 8px; border-radius: 9px; cursor: pointer; font-size: 13px; font-weight: 600;
  transition: all .16s var(--ease); width: 36px; height: 36px;
}
.logout-btn svg { width: 18px; height: 18px; }
.logout-btn:hover { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }

/* ---------- Layout ---------- */
main { max-width: 1240px; margin: 0 auto; padding: 26px 26px 80px; }
.tab-panel { animation: fadeUp .28s var(--ease); }
@keyframes fadeUp { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ---------- Map ---------- */
.map-wrap {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; box-shadow: var(--shadow); margin-bottom: 30px; position: relative;
}
#map { height: 350px; width: 100%; z-index: 1; }
#map.map-focused { outline: 2px solid var(--brand); }
.sys-marker {
  width: 22px; height: 22px; border-radius: 50%; border: 3px solid #fff;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .35);
  position: relative;
}
/* Aantal installaties dat op dezelfde coördinaat ligt. */
.sys-marker-count {
  position: absolute; top: -7px; right: -7px;
  min-width: 16px; height: 16px; padding: 0 3px;
  border-radius: 8px; border: 2px solid #fff; background: var(--ink);
  color: var(--card); font-size: 10px; font-weight: 700; line-height: 12px;
  text-align: center; box-sizing: border-box;
}
.sys-marker.online { background: var(--ok); animation: pulse 2.4s infinite; }
.sys-marker.offline { background: var(--off); }
.sys-marker.manual { background: var(--manual); }
.sys-marker.warning { background: var(--amber); animation: pulse-amber 2.4s infinite; }
.sys-marker.error { background: var(--warn); animation: pulse-warn 2.4s infinite; }
@keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(20, 160, 90, .45); } 70% { box-shadow: 0 0 0 10px rgba(20, 160, 90, 0); } 100% { box-shadow: 0 0 0 0 rgba(20, 160, 90, 0); } }
@keyframes pulse-amber { 0% { box-shadow: 0 0 0 0 rgba(178, 106, 0, .45); } 70% { box-shadow: 0 0 0 10px rgba(178, 106, 0, 0); } 100% { box-shadow: 0 0 0 0 rgba(178, 106, 0, 0); } }
@keyframes pulse-warn { 0% { box-shadow: 0 0 0 0 rgba(201, 67, 43, .45); } 70% { box-shadow: 0 0 0 10px rgba(201, 67, 43, 0); } 100% { box-shadow: 0 0 0 0 rgba(201, 67, 43, 0); } }

.map-tooltip { background: transparent; border: none; box-shadow: none; padding: 0; }
.map-tooltip::before { display: none; }
/* Eén popupvorm voor één én meerdere installaties: een locatieregel met
   daaronder klikbare installatiekaarten. De kaart zelf is de actie, dus geen
   losse knop die per installatie een regel kost. */
.map-pop {
  background: var(--card); border: 1px solid var(--line); border-radius: 12px;
  /* max-width, anders rekt een lange systeemnaam de popup op in plaats van
     af te kappen — bij een cluster wordt hij dan zomaar 330px breed. */
  padding: 5px; min-width: 190px; max-width: 250px; box-shadow: var(--shadow); color: var(--ink);
}
.map-pop .mp-loc {
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--ink-soft); padding: 4px 8px 5px;
}
.map-pop .mp-count {
  margin-left: auto; padding: 0 6px; border-radius: 999px;
  background: var(--line); color: var(--ink-soft); font-size: 11px; font-weight: 600;
}
/* 272px = precies vier kaarten. Scrollen in een hoverpopup is onhandig, dus
   pas vanaf vijf installaties; grotere clusters komen vrijwel niet voor. */
.map-pop .mp-list { display: flex; flex-direction: column; max-height: 272px; overflow-y: auto; }
/* Hairlines in plaats van een rand per kaart: rustiger, en het scheelt de
   ruimte die anders in randen en tussenruimte gaat zitten. */
.map-pop .mp-item + .mp-item { border-top: 1px solid var(--line); }
.map-pop .mp-item {
  display: block; width: 100%; margin: 0; padding: 7px 8px; text-align: left; cursor: pointer;
  background: transparent; color: inherit; font: inherit; border: 0; border-radius: 8px;
}
.map-pop .mp-item:hover, .map-pop .mp-item:focus-visible { background: var(--brand-soft); }
.map-pop .mp-item:hover + .mp-item, .map-pop .mp-item:focus-visible + .mp-item { border-top-color: transparent; }
.map-pop .mp-head { display: flex; align-items: center; gap: 6px; font-size: 13px; }
.map-pop .mp-head strong { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.map-pop .mp-go { margin-left: auto; color: var(--ink-soft); font-size: 15px; line-height: 1; }
.map-pop .mp-item:hover .mp-go { color: var(--brand); }
.map-pop .mp-dot { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; }
.map-pop .mp-dot.online { background: var(--ok); } .map-pop .mp-dot.offline { background: var(--off); }
.map-pop .mp-dot.manual { background: var(--manual); }
.map-pop .mp-dot.warning { background: var(--amber); } .map-pop .mp-dot.error { background: var(--warn); }
.map-pop .mp-row { display: flex; justify-content: space-between; gap: 16px; font-size: 12px; padding-top: 2px; }
.map-pop .mp-row span { color: var(--ink-soft); }

.map-click-popup .leaflet-popup-content-wrapper { background: transparent; box-shadow: none; padding: 0; border-radius: 12px; }
.map-click-popup .leaflet-popup-content { margin: 0; }
.map-click-popup .leaflet-popup-tip { background: var(--card); box-shadow: none; }
.map-click-popup .leaflet-popup-close-button { color: var(--ink-soft); }

/* Custom zoom buttons on map */
.map-zoom-custom {
  position: absolute; bottom: 20px; right: 20px; z-index: 10;
  display: flex; flex-direction: column; gap: 6px;
}
.map-zoom-btn, .map-reset-btn {
  width: 38px; height: 38px; border-radius: 10px; border: 1px solid var(--line);
  background: var(--card); color: var(--ink); box-shadow: var(--shadow-sm);
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  transition: all .16s var(--ease); z-index: 10;
}
.map-zoom-btn svg, .map-reset-btn svg { width: 18px; height: 18px; }
.map-zoom-btn:hover, .map-reset-btn:hover { background: var(--bg-2); border-color: var(--brand); color: var(--brand); }

.map-reset-btn {
  position: absolute; top: 20px; right: 20px;
}
.map-reset-btn[hidden] { display: none; }

/* Scroll guard overlay */
.map-scroll-guard {
  position: absolute; inset: 0; background: rgba(19, 35, 56, 0.72); z-index: 100;
  display: flex; align-items: center; justify-content: center; color: #fff;
  font-size: 15px; font-weight: 600; pointer-events: none; transition: opacity .2s;
  backdrop-filter: blur(2px); text-align: center; padding: 20px;
}
.map-scroll-guard .msg-desktop { display: inline; }
.map-scroll-guard .msg-mobile { display: none; }

/* ---------- Section head + tools ---------- */
.section-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 16px; flex-wrap: wrap; }
.section-head h2 { font-size: 18px; }
.section-tools { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.search-box { position: relative; margin-bottom: 22px; width: 100%; }
.search-box .search-ico { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--ink-faint); font-size: 16px; width: 16px; height: 16px; }
.search-box input {
  padding: 12px 14px 12px 38px; border: 1px solid var(--line-2); border-radius: 12px;
  font-size: 14px; background: var(--card); width: 100%; transition: all .16s var(--ease);
  box-shadow: var(--shadow-sm);
}
.search-box input:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
/* wrap: zonder dit liep de chip-rij op mobiel buiten de viewport, waardoor de
   hele pagina horizontaal breder werd dan het scherm. */
.filter-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chip {
  border: 1px solid var(--line-2); background: var(--card); color: var(--ink-soft);
  padding: 9px 16px; border-radius: 999px; cursor: pointer; font-size: 13px; font-weight: 600;
  transition: all .16s var(--ease);
}
.chip:hover { border-color: var(--brand); color: var(--brand); }
.chip.active { background: var(--brand); border-color: var(--brand); color: #fff; }
.empty-state { text-align: center; color: var(--ink-soft); padding: 44px; }

/* ---------- Laadtoestanden (universeel) ----------------------------------
   Deze stylesheet wordt op élke pagina geladen (vloot, installatiepagina,
   login), dus dit is de plek voor één set laadindicatoren. Drie vormen, elk
   met een eigen taak:

   .spinner       — er gebeurt iets, we weten niet hoe lang. In knoppen en
                    naast korte statusteksten.
   .skeleton      — we weten wélke vorm er komt (kaarten, tabelrijen). Dat
                    leest rustiger dan een spinner: de pagina springt niet
                    van leeg naar vol.
   .loading-block — een leeg vlak dat nog gevuld moet worden en waar geen
                    duidelijke vorm voor is.

   Kleuren komen uit de tokens, niet uit vaste waarden: de spinner gebruikt
   currentColor en werkt daarmee zowel op een donkere knop als op een lichte
   kaart. Bewegingen zijn kort en subtiel; wie systeembreed minder beweging
   heeft ingesteld krijgt onderaan een rustige variant. */

@keyframes ui-spin { to { transform: rotate(360deg); } }
@keyframes ui-shimmer { to { transform: translateX(100%); } }
@keyframes ui-fade-in { from { opacity: 0; } to { opacity: 1; } }

.spinner {
  display: inline-block; width: 16px; height: 16px; flex: none;
  border: 2.5px solid currentColor; border-top-color: transparent;
  border-radius: 50%; opacity: .8; vertical-align: middle;
  animation: ui-spin .6s linear infinite;
}
.spinner.sm { width: 12px; height: 12px; border-width: 2px; }
.spinner.lg { width: 26px; height: 26px; border-width: 3px; }
/* Op een neutrale ondergrond mag hij de merkkleur pakken. */
.spinner.brand { color: var(--brand); }

/* Korte statusregel: "Laden…" met een spinnertje ervoor. Vervangt losse
   "Laden…"-teksten die niets lieten zien tot de data er was. */
.loading-inline {
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--ink-soft); font-size: 13px;
}
/* In een knop of gekleurde balk: kleur en formaat van de omgeving overnemen,
   zodat de spinner op een donkere knop wit is en op een lichte donker. */
.loading-inline.inherit { color: inherit; font-size: inherit; }

.loading-block {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; padding: 40px 20px; color: var(--ink-soft); font-size: 13.5px;
  animation: ui-fade-in .18s var(--ease);
}

.skeleton {
  position: relative; overflow: hidden;
  background: var(--line); border-radius: var(--radius-sm);
}
/* De glans loopt van links naar rechts over het blok. Halftransparant wit,
   zodat hetzelfde blok werkt op een kaart (wit) en op de pagina (--bg). */
.skeleton::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .75), transparent);
  animation: ui-shimmer 1.35s var(--ease) infinite;
}
.skeleton-text { height: 11px; border-radius: 999px; }
.skeleton-text + .skeleton-text { margin-top: 9px; }
.skeleton-text.w40 { width: 40%; }
.skeleton-text.w60 { width: 60%; }
.skeleton-text.w80 { width: 80%; }
/* Iets donkerder blok voor een "cijfer" of knop binnen een skeletkaart. */
.skeleton.strong { background: var(--line-2); }

/* Skeletversie van een systeemkaart op het vlootoverzicht. */
.sys-card.is-skeleton { pointer-events: none; }
.sys-card.is-skeleton .sk-hero { height: 30px; width: 55%; margin: 14px 0 8px; }

/* Container die ververst terwijl de oude inhoud blijft staan: dimmen leest
   rustiger dan wegblanken en terugspringen. */
.is-loading { opacity: .55; transition: opacity .12s; pointer-events: none; }

/* Sluier mét spinner over een kaart die ververst. Alleen dimmen was te
   subtiel om op te merken — zeker nu een periodewissel vaak uit de cache
   komt. Dit is een overlay en geen opacity op de kaart zelf, want dan zou de
   spinner mee vervagen. */
.panel-card { position: relative; }
.card-loading {
  position: absolute; inset: 0; z-index: 2; border-radius: inherit;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, .66);
  animation: ui-fade-in .12s var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  /* Niet stilzetten maar verzachten: een indicator die niets doet lijkt
     vastgelopen. De spinner draait langzamer, de glans verdwijnt en het
     skelet ademt rustig. */
  .spinner { animation-duration: 1.4s; }
  .skeleton::after { animation: none; }
  .skeleton { animation: ui-fade-in .2s var(--ease); }
  .loading-block { animation: none; }
}

/* ---------- Instellingen-tab: losse instelkaarten ---------- */
.settings-panel-card {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 18px 20px; margin-bottom: 30px;
}
.settings-panel-card > .muted { margin-bottom: 14px; line-height: 1.5; }
.settings-panel-card .table-wrap { margin-top: 16px; }
/* Schijfvulling: één balk met het aandeel meetdata apart gekleurd. */
.disk-gauge { margin-bottom: 16px; }
.disk-gauge-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.disk-gauge-pct { font-size: 26px; font-weight: 700; letter-spacing: -.02em; }
.disk-gauge-caption { font-size: 13px; color: var(--ink-soft); }
.disk-bar {
  display: flex; height: 12px; border-radius: 999px; overflow: hidden;
  background: var(--off-soft); border: 1px solid var(--line);
}
.disk-bar-fill { display: block; height: 100%; transition: width .35s var(--ease); }
.disk-bar-db { background: linear-gradient(90deg, var(--brand), var(--brand-2)); }
.disk-bar-other { background: var(--line-2); }
.disk-legend { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 8px; font-size: 12px; color: var(--ink-soft); }
.disk-legend span { display: inline-flex; align-items: center; gap: 6px; }
.disk-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; flex: none; }
.disk-dot-db { background: var(--brand); }
.disk-dot-other { background: var(--line-2); }
.disk-dot-free { background: var(--off-soft); border: 1px solid var(--line); }
/* Bijna vol: de balk moet dat zelf al laten zien, niet pas de tekst. */
.disk-gauge.is-warn .disk-gauge-pct { color: var(--amber); }
.disk-gauge.is-warn .disk-bar-other { background: var(--amber); }
.disk-gauge.is-critical .disk-gauge-pct { color: var(--warn); }
.disk-gauge.is-critical .disk-bar-other { background: var(--warn); }

.settings-inline-form { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
/* Twee formulierregels onder elkaar (Dataopslag) plakken anders aan elkaar. */
.settings-inline-form + .settings-inline-form { margin-top: 14px; }
.settings-inline-form .field { margin-bottom: 0; flex: 1 1 260px; min-width: 0; }
.settings-inline-form .btn-primary, .settings-inline-form .btn-ghost { flex: none; }

/* ---------- Buttons ---------- */
.btn-primary {
  border: none; background: linear-gradient(135deg, var(--brand), var(--brand-2)); color: #fff; font-weight: 700;
  padding: 10px 18px; border-radius: 10px; cursor: pointer; font-size: 14px;
  box-shadow: 0 4px 12px rgba(27, 82, 160, .28); transition: transform .12s var(--ease), box-shadow .16s;
}
.btn-primary:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(27, 82, 160, .36); }
.btn-ghost {
  border: 1px solid var(--line-2); background: var(--card); color: var(--ink); text-decoration: none;
  padding: 9px 15px; border-radius: 9px; cursor: pointer; font-size: 13px; font-weight: 600;
  display: inline-flex; align-items: center; gap: 6px; transition: all .16s var(--ease);
}
.btn-ghost:hover { background: var(--bg-2); border-color: var(--brand); }
.btn-ghost.danger { color: var(--warn); border-color: var(--warn-soft); }
.btn-ghost.danger:hover { background: var(--warn-soft); }
.mini-btn {
  border: 1px solid var(--line-2); background: var(--card); color: var(--brand);
  padding: 6px 13px; border-radius: 8px; cursor: pointer; font-size: 13px; font-weight: 600; transition: all .14s var(--ease);
  display: inline-flex; align-items: center; gap: 6px;
}
.mini-btn:hover { background: var(--brand-soft); }
.mini-btn.danger { color: var(--warn); border-color: var(--warn-soft); }
.mini-btn.danger:hover { background: var(--warn-soft); }
.mini-btn.icon-only { padding: 6px; }

/* ---------- System cards ---------- */
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); gap: 16px; }
.sys-card {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 18px 20px; cursor: pointer; box-shadow: var(--shadow-sm);
  transition: transform .14s var(--ease), box-shadow .14s var(--ease), border-color .14s;
  position: relative; overflow: hidden;
}
/* Accentbalk als échte linkerrand op een afgeronde vorm, niet als recht
   blokje: zo loopt hij boven en onder mee met de afronding van de kaart —
   hetzelfde beeld als .ov-meldingen en .collapse-section. Een absoluut
   gepositioneerd balkje van 4px bleef daar recht doorheen lopen en werd door
   de overflow:hidden botweg afgekapt. inset:0 valt samen met de binnenkant
   van de 1px kaartrand, vandaar de radius er ook 1px kleiner. */
.sys-card::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  border-radius: calc(var(--radius) - 1px);
  border-left: 4px solid var(--brand);
  opacity: 0; transition: opacity .16s;
}
.sys-card:hover { transform: translateY(-3px); border-color: var(--line-2); box-shadow: var(--shadow); }
.sys-card:hover::before { opacity: 1; }
.sys-card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.sys-card-top h3 { font-size: 16px; }
.sys-place { color: var(--ink-soft); font-size: 13px; margin-top: 2px; }
.sys-hero { margin: 16px 0 4px; }
.sys-hero .hero-num { font-size: 28px; font-weight: 800; color: var(--brand); letter-spacing: -.02em; }
.sys-hero .hero-lbl { font-size: 12px; color: var(--ink-soft); }
.sys-foot { display: flex; justify-content: space-between; font-size: 12px; color: var(--ink-faint); margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line); }

.status-pill { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; padding: 4px 10px; border-radius: 999px; white-space: nowrap; }
.status-pill .dot { width: 8px; height: 8px; border-radius: 50%; }
.status-pill.online { background: var(--ok-soft); color: var(--ok); } .status-pill.online .dot { background: var(--ok); }
.status-pill.offline { background: var(--off-soft); color: var(--off); } .status-pill.offline .dot { background: var(--off); }
.status-pill.manual { background: var(--manual-soft); color: var(--manual); } .status-pill.manual .dot { background: var(--manual); }
.status-pill.warning { background: var(--amber-soft); color: var(--amber); } .status-pill.warning .dot { background: var(--amber); }
.status-pill.error { background: var(--warn-soft); color: var(--warn); } .status-pill.error .dot { background: var(--warn); }

/* ---------- Insight tab ---------- */
.insight-hero { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 22px; }
.insight-hero .ih-item {
  background: linear-gradient(135deg, var(--brand), var(--brand-dark)); color: #fff;
  border-radius: var(--radius); padding: 22px; box-shadow: var(--shadow);
}
.insight-hero .ih-item.green { background: linear-gradient(135deg, #16824a, #0e5f36); }
.insight-hero .ih-item.amber { background: linear-gradient(135deg, #b26a00, #7a4200); }
.insight-hero .ih-num { font-size: 32px; font-weight: 800; letter-spacing: -.02em; line-height: 1; }
.insight-hero .ih-lbl { font-size: 12px; opacity: .88; margin-top: 6px; }
.insight-lead { font-size: 15px; color: var(--ink); margin: 4px 0 24px; padding: 12px 16px; background: var(--brand-soft); border-radius: 12px; border-left: 4px solid var(--brand); }

/* Samenvattende zin in gewone taal (§12.2 p.1): één regel die vertelt hoe de
   vloot ervoor staat, met het periodeverschil erin verweven. */
.insight-summary {
  font-size: 16px; line-height: 1.5; color: var(--ink); margin: 4px 0 18px;
  padding: 14px 18px; background: var(--brand-soft); border-radius: 12px;
  border-left: 4px solid var(--brand);
}
.insight-summary strong { color: var(--brand-dark); }

/* KPI-strip: 4 vaste, benoemde kaarten met groot afgerond getal, delta t.o.v.
   de vorige periode en een sparkline (§12.2 p.2). Licht van kleur zodat de
   accenten (getal, delta, sparkline) het werk doen — één ding kleur. */
.kpi-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 16px; margin-bottom: 14px; }
.kpi-card {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 18px 18px 16px; box-shadow: var(--shadow-sm);
  display: flex; flex-direction: column; gap: 6px; min-height: 108px;
  border-top: 3px solid var(--brand);
}
/* Zonder sparkline pinnen we de delta onderaan, zodat de secundaire regel
   (delta of context) op alle kaarten op dezelfde hoogte staat. */
.kpi-card > .delta { margin-top: auto; }
.kpi-card.kpi-clickable { cursor: pointer; text-align: left; font: inherit; transition: border-color .15s var(--ease), box-shadow .15s var(--ease); }
.kpi-card.kpi-clickable:hover { border-color: var(--line-2); box-shadow: var(--shadow); }
.kpi-card.kpi-clickable:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.kpi-label { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-soft); }
.kpi-value { font-size: 32px; font-weight: 800; letter-spacing: -.02em; line-height: 1; color: var(--brand-dark); }
.kpi-value.ok { color: var(--ok); }
.kpi-value.warn { color: var(--amber); }
.kpi-value.bad { color: var(--warn); }
.kpi-unit { font-size: 15px; font-weight: 700; color: var(--ink-faint); margin-left: 5px; }
.kpi-context { font-size: 12px; color: var(--ink-soft); margin-top: auto; }

/* Delta-chip: pijl + één afgerond verschil. Groen = beter, rood = slechter,
   grijs = neutraal/geen richting. Kleur is nooit het enige signaal (de pijl
   codeert de richting ook). */
.delta { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 700; }
.delta.up { color: var(--ok); }
.delta.down { color: var(--warn); }
.delta.neutral { color: var(--ink-soft); }
.delta.flat, .delta.none { color: var(--ink-faint); font-weight: 600; }
.delta-ref { font-weight: 500; color: var(--ink-faint); }
.sales-stat-row .delta { font-size: 12px; margin-left: 8px; }

/* Sparkline: huidige periode in accentkleur, vorige periode grijs gestippeld. */
.spark { width: 100%; height: 34px; margin-top: auto; overflow: visible; }
.spark .spark-cur { fill: none; stroke: var(--brand); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.spark .spark-prev { fill: none; stroke: var(--off); stroke-width: 1.5; stroke-dasharray: 3 3; opacity: .8; }

/* All-time verkoopregel: het totale verhaal sinds de start, klein onder de
   periode-KPI's zodat de kaarten zelf over de gekozen periode blijven gaan. */
.insight-alltime { font-size: 13px; color: var(--ink-soft); margin: 0 0 22px; }
.insight-alltime strong { color: var(--brand-dark); font-weight: 700; }

/* "Bijgewerkt om HH:MM" — refresh-eerlijkheid, geen realtime-belofte (§12.3). */
.chart-updated { font-size: 12px; color: var(--ink-faint); margin: 12px 0 0; }

/* Per-systeem overzicht op de devicepagina — hergebruikt de insight-opmaak
   hierboven (fleet.css wordt daar óók geladen). Alleen een paar extra's: een
   tekstuele Status-KPI, een drill-down-link en een laadstaat. */
.kpi-value.kpi-text { font-size: 19px; line-height: 1.2; }
.ov-card { margin-bottom: 18px; }
.ov-loading { padding: 40px 8px; text-align: center; }
.ov-link { border: none; background: none; color: var(--brand); font: inherit; font-weight: 600; cursor: pointer; padding: 0; }
.ov-link:hover { text-decoration: underline; }

.insight-grid-info { display: grid; grid-template-columns: 1.6fr 1fr; gap: 20px; align-items: start; margin-bottom: 20px; }
.panel-card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 22px; box-shadow: var(--shadow-sm); }
.pc-title { font-size: 15px; margin-bottom: 16px; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-soft); font-weight: 700; }

.bar-chart { display: flex; flex-direction: column; gap: 12px; }
.bar-row { display: grid; grid-template-columns: 150px 1fr 90px; align-items: center; gap: 12px; }
.bar-name { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-track { background: var(--bg); border-radius: 999px; height: 12px; overflow: hidden; }
.bar-fill { height: 100%; background: linear-gradient(90deg, var(--brand-2), var(--brand)); border-radius: 999px; animation: grow 1s var(--ease); }
@keyframes grow { from { width: 0 !important; } }
.bar-val { font-size: 14px; font-weight: 700; color: var(--brand); text-align: right; }

.sales-stats { display: flex; flex-direction: column; gap: 14px; }
.sales-stat-row { display: flex; justify-content: space-between; border-bottom: 1px solid var(--line); padding-bottom: 10px; font-size: 14px; }
.sales-stat-row:last-child { border-bottom: none; padding-bottom: 0; }
.sales-stat-row .lbl { color: var(--ink-soft); font-weight: 500; }
.sales-stat-row .val { font-weight: 700; color: var(--ink); }

.assumption-note { font-size: 12px; color: var(--ink-faint); margin-top: 14px; line-height: 1.4; }

/* Kolomgrafiek geleverde warmte. Bewust geen grafiekbibliotheek: het is een
   reeks staafjes, en flexbox met hoogte-percentages doet dat zonder 200 kB
   extra en met dezelfde huisstijlkleuren als de rest. */
.chart-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.chart-head .pc-title { margin-bottom: 0; }
.period-filter { display: flex; gap: 8px; flex-wrap: wrap; }
/* Grafiekraam: y-aslabels links, plotvlak rechts. De x-as staat eronder en
   krijgt per staaf een even breed vakje, zodat de labels precies onder hun
   staaf uitkomen ook als er maar een paar getoond worden. */
.chart-frame { display: grid; grid-template-columns: auto 1fr; gap: 10px; align-items: stretch; }
.y-unit { font-size: 11px; color: var(--ink-faint); margin-bottom: 6px; font-weight: 600; }
.y-axis {
  display: flex; flex-direction: column; justify-content: space-between;
  /* min-height i.p.v. height: de as rekt mee met het plotvlak (dat bij koeling
     hoger is), zodat de labels altijd op hun rasterlijn blijven staan. */
  min-height: 180px; font-size: 11px; color: var(--ink-faint); text-align: right;
  /* De labels horen op de lijn te staan, niet eronder. */
  transform: translateY(-.5em);
}
.plot { position: relative; height: 180px; }
/* Met koeling erbij moet er twee kanten op ruimte zijn; iets meer hoogte houdt
   de staafjes leesbaar zonder de kaart op te blazen. */
.plot.is-split { height: 220px; }
.plot .grid { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: space-between; }
.plot .grid i { display: block; border-top: 1px dashed var(--line); }
/* De nullijn: doorgetrokken. Zonder koeling is dat gewoon de onderste lijn. */
.plot .grid i.zero { border-top-style: solid; border-top-color: var(--line-2); }
.col-chart { position: absolute; inset: 0; display: flex; align-items: stretch; gap: 3px; }
/* Eén staafkolom = de warmte-helft boven de nullijn en de koeling-helft
   eronder. De hoogte van de bovenhelft komt uit de data (inline style), zodat
   beide helften dezelfde kWh-schaal delen. */
.col-pair {
  flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;
  background: none; border: none; padding: 0; font: inherit;
}
.col-pair .col-up { display: flex; align-items: flex-end; }
.col-pair .col-dn { flex: 1 1 auto; display: flex; align-items: flex-start; }
.col-chart .col {
  width: 100%; border-radius: 4px 4px 0 0; position: relative;
  background: linear-gradient(180deg, var(--brand-2), var(--brand));
  animation: rise .6s var(--ease); transition: opacity .15s, filter .15s;
  border: none; padding: 0; font: inherit;
}
/* Koeling groeit naar beneden: ronding en kleurverloop gespiegeld, en een
   eigen (koele) kleur zodat kleur én richting hetzelfde vertellen. */
.col-chart .col-cool {
  border-radius: 0 0 4px 4px;
  background: linear-gradient(0deg, var(--cool-2), var(--cool));
}
.col-chart .col.is-empty { background: var(--line); }
.col-chart button.col-pair { cursor: pointer; }
.col-chart button.col-pair:hover .col { filter: brightness(1.15); opacity: .9; }
.col-chart button.col-pair:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
@keyframes rise { from { height: 0 !important; } }

/* Legenda naast het kWh-labeltje; alleen zichtbaar als er koeling in beeld is. */
.chart-legend { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 6px; }
.chart-legend .y-unit { margin-bottom: 0; }
.chart-legend .lg { font-size: 11.5px; color: var(--ink-soft); display: flex; align-items: center; gap: 6px; }
.chart-legend .lg::before { content: ""; width: 11px; height: 11px; border-radius: 3px; display: block; }
.chart-legend .lg-heat::before { background: var(--brand); }
.chart-legend .lg-cool::before { background: var(--cool); }

.x-axis { display: flex; gap: 3px; margin-top: 7px; }
.x-axis .tick {
  flex: 1 1 0; min-width: 0; font-size: 10.5px; color: var(--ink-faint);
  text-align: center; white-space: nowrap; overflow: visible;
}
/* Onderschrift van de grafiek: één regel — uitschieters, daarachter gedempt de
   inzoom-uitleg. Geen aparte alinea's meer, dat kostte alleen maar hoogte. */
.chart-peak { font-size: 12px; color: var(--ink-soft); margin-top: 10px; }
.chart-hint { font-size: 12px; color: var(--ink-faint); }

/* Ingezoomd: kruimelpad met terug-/resetknop. */
.chart-zoom { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.chart-zoom .zoom-label { font-size: 13px; font-weight: 700; color: var(--brand); }
.btn-zoom {
  display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--line-2);
  background: var(--card); color: var(--ink-soft); border-radius: 999px;
  padding: 6px 13px; font-size: 12.5px; font-weight: 600; cursor: pointer;
  transition: border-color .15s, color .15s, background .15s;
}
.btn-zoom:hover { border-color: var(--brand); color: var(--brand); background: var(--brand-soft); }

/* Terwijl er geladen wordt blijft de oude grafiek staan, maar gedimd — zie
   .is-loading bij de laadtoestanden bovenaan. */

/* "Aandacht nodig" — alleen installaties met een signaal; staat er niets,
   dan de geruststellende lege staat. */
.attention-list { display: flex; flex-direction: column; gap: 10px; }
.attention-row {
  display: grid; grid-template-columns: 10px 1fr auto; align-items: start; gap: 12px;
  padding: 13px 15px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg-2);
  cursor: pointer; text-align: left; width: 100%; font: inherit; transition: border-color .15s, background .15s;
}
.attention-row:hover { border-color: var(--line-2); background: var(--card); }
.attention-row .att-dot { width: 10px; height: 10px; border-radius: 50%; margin-top: 5px; }
.attention-row.error .att-dot { background: var(--warn); }
.attention-row.warning .att-dot { background: var(--amber); }
.attention-row .att-name { font-weight: 700; font-size: 14px; }
.attention-row .att-title { font-weight: 600; font-size: 13px; }
.attention-row.error .att-title { color: var(--warn); }
.attention-row.warning .att-title { color: var(--amber); }
.attention-row .att-detail { font-size: 13px; color: var(--ink-soft); margin-top: 3px; line-height: 1.45; }
.attention-row .att-go { color: var(--ink-faint); font-size: 18px; line-height: 1; align-self: center; }
.attention-ok { display: flex; align-items: center; gap: 10px; font-size: 14px; color: var(--ok); font-weight: 600; }
.attention-ok .dot { width: 10px; height: 10px; border-radius: 50%; background: var(--ok); }
/* Meldingen op het per-systeem Overzicht: titel + uitleg netjes gestapeld
   (niet meer tegen elkaar geplakt), met eventueel een oplossings-knop eronder.
   .att-static = geen doorklik (je bent al op de installatie). */
.attention-row .att-body { display: flex; flex-direction: column; gap: 5px; align-items: flex-start; min-width: 0; }
.attention-row .att-body .att-detail { margin-top: 0; }
.attention-row.att-static { cursor: default; }
.attention-row.att-static:hover { border-color: var(--line); background: var(--bg-2); }
.ov-melding-btn { margin-top: 5px; }

/* Meldingenpaneel op het Overzicht: het staat pal onder de KPI's (meteen in
   beeld) met een linker accentbalk naar ernst, plus een korte highlight als je
   er via de Status-/Meldingen-kaart naartoe klikt — zo leidt "Controleer dit"
   zichtbaar naar het antwoord. */
.ov-meldingen { border-left: 4px solid var(--amber); }
.ov-meldingen.has-error { border-left-color: var(--warn); }
.ov-meldingen.flash { animation: ovFlash 1.1s var(--ease); }
@keyframes ovFlash {
  0%, 35% { box-shadow: 0 0 0 4px rgba(27, 82, 160, .20); }
  100% { box-shadow: var(--shadow-sm); }
}
@media (prefers-reduced-motion: reduce) { .ov-meldingen.flash { animation: none; } }

/* Inklapbare sectie op <details>/<summary>: native, dus met toetsenbord en
   schermlezer bruikbaar zonder eigen JS. De kop leent de typografie van
   .section-head en de teller is een gewone .status-pill, zodat de kleuren
   dezelfde betekenis houden als op de systeemkaarten. */
/* De sectie krijgt dezelfde kaartvorm als de blokken erboven (.panel-card),
   anders hangt hij als losse regel op de paginaachtergrond onder een rij
   witte vlakken en leest hij als een restje in plaats van als een eigen
   onderdeel. Iets minder padding dan een gewone kaart, want ingeklapt is het
   maar één regel. */
.collapse-section { margin-top: 26px; padding: 16px 22px; }
.collapse-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  cursor: pointer; list-style: none; user-select: none;
  border-radius: var(--radius-sm);
}
/* Is er iets aan de hand, dan mag de kaart dat ook ingeklapt uitstralen —
   dezelfde kleuren als de statusbolletjes op de systeemkaarten. */
.collapse-section.has-error { border-left: 4px solid var(--warn); }
.collapse-section.has-warning { border-left: 4px solid var(--amber); }
/* Het standaard driehoekje weg in alle browsers; we tonen een eigen chevron. */
.collapse-head::-webkit-details-marker { display: none; }
.collapse-head::marker { content: ""; }
.collapse-head h2 { font-size: 18px; }
.collapse-head:hover h2 { color: var(--brand); }
.collapse-head:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
.collapse-chevron {
  margin-left: auto; color: var(--ink-faint); font-size: 13px; font-weight: 700;
  display: inline-flex; align-items: center; gap: 6px;
}
.collapse-chevron svg { width: 16px; height: 16px; transition: transform .18s var(--ease); }
.collapse-section[open] .collapse-chevron svg { transform: rotate(180deg); }
/* Scheidingslijn tussen kop en inhoud zodra hij openstaat, zodat de kaart
   niet één ongedeeld blok wordt. */
.collapse-body {
  margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--line);
  animation: ui-fade-in .18s var(--ease);
}

@media (prefers-reduced-motion: reduce) {
  .collapse-chevron svg { transition: none; }
  .collapse-body { animation: none; }
}

/* ---------- Drawer ---------- */
.drawer-backdrop { position: fixed; inset: 0; background: rgba(15, 25, 40, .4); z-index: 900; backdrop-filter: blur(2px); animation: fade .2s; }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
.drawer {
  position: fixed; top: 0; right: 0; height: 100%; width: min(470px, 95vw);
  background: var(--bg); z-index: 1000; box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column; animation: slideIn .26s var(--ease);
}
@keyframes slideIn { from { transform: translateX(40px); opacity: .3; } to { transform: none; opacity: 1; } }
.drawer-head { display: flex; align-items: flex-start; justify-content: space-between; padding: 20px 22px; background: var(--card); border-bottom: 1px solid var(--line); }
.drawer-head h2 { font-size: 19px; }
.drawer-place { margin: 3px 0 0; color: var(--ink-soft); font-size: 13px; }
.close-btn { border: none; background: var(--bg); color: var(--ink-soft); width: 34px; height: 34px; border-radius: 10px; font-size: 15px; cursor: pointer; transition: all .14s; }
.close-btn:hover { background: var(--line); color: var(--ink); }
.drawer-body { padding: 20px 22px; overflow-y: auto; }
.section-title { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-faint); margin: 22px 0 10px; font-weight: 700; }
.section-title:first-child { margin-top: 0; }
.tile-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.tile { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 12px; }
.tile .t-icon { font-size: 15px; }
.tile .t-val { font-size: 19px; font-weight: 800; margin-top: 4px; letter-spacing: -.01em; }
.tile .t-val .t-unit { font-size: 12px; font-weight: 600; color: var(--ink-soft); margin-left: 2px; }
.tile .t-lbl { font-size: 11px; color: var(--ink-soft); margin-top: 1px; }
.tile.is-fault { border-color: var(--warn); background: var(--warn-soft); }
.tile.is-fault .t-val, .tile.is-fault .t-lbl { color: var(--warn); }
.value-banner { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; background: linear-gradient(135deg, var(--brand), var(--brand-dark)); color: #fff; border-radius: 14px; padding: 16px; }
.value-banner.two { grid-template-columns: repeat(2, 1fr); }
.value-banner .vb-num { font-size: 22px; font-weight: 800; }
.value-banner .vb-lbl { font-size: 11px; opacity: .86; margin-top: 2px; }
.muted { color: var(--ink-soft); font-size: 13px; }
.drawer-admin { display: flex; gap: 8px; flex-wrap: wrap; }

.mode-toggle { display: inline-flex; background: var(--off-soft); border-radius: 10px; padding: 3px; gap: 3px; margin-bottom: 12px; }
.mode-toggle button { border: none; background: transparent; color: var(--ink-soft); padding: 7px 16px; border-radius: 8px; cursor: pointer; font-size: 13px; font-weight: 600; transition: all .16s var(--ease); }
.mode-toggle button.active { background: var(--card); color: var(--brand); box-shadow: var(--shadow-sm); }
.controls-wrap { transition: opacity .2s, filter .2s; }
.controls-wrap.locked { opacity: .5; pointer-events: none; filter: grayscale(.3); }
.controls-wrap.locked::before { content: "In automatische modus regelt de installatie zelf. Zet op ‘Handmatig’ om aan te passen."; display: block; font-size: 12px; color: var(--ink-soft); background: var(--brand-soft); border-radius: 8px; padding: 8px 10px; margin-bottom: 10px; }
.control-row { background: var(--card); border: 1px solid var(--line); border-radius: 12px; padding: 14px; margin-bottom: 10px; }
.control-row .c-lbl { font-weight: 600; font-size: 14px; margin-bottom: 10px; }
.control-line { display: flex; gap: 10px; align-items: center; }
.control-line input[type=range] { flex: 1; accent-color: var(--brand); }
.rangeval { min-width: 60px; text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; color: var(--brand); }
.btn-apply { border: none; background: var(--brand); color: #fff; font-weight: 600; padding: 8px 16px; border-radius: 8px; cursor: pointer; font-size: 13px; }
.btn-apply:hover { background: var(--brand-dark); }
.seg { display: flex; gap: 6px; flex-wrap: wrap; }
.seg button { border: 1px solid var(--line-2); background: var(--card); color: var(--ink); padding: 8px 15px; border-radius: 8px; cursor: pointer; font-size: 13px; font-weight: 600; transition: all .14s var(--ease); }
.seg button.active { background: var(--brand); border-color: var(--brand); color: #fff; }

/* ---------- Data table ---------- */
.table-wrap { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); overflow-x: auto; box-shadow: var(--shadow-sm); -webkit-overflow-scrolling: touch; }
.data-table { width: 100%; min-width: 640px; border-collapse: collapse; }
.data-table th { text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: .03em; color: var(--ink-soft); padding: 14px 16px; border-bottom: 1px solid var(--line); font-weight: 700; }
.data-table td { padding: 13px 16px; border-bottom: 1px solid var(--line); font-size: 14px; vertical-align: middle; }
.data-table tr:last-child td { border-bottom: none; }
.data-table tbody tr { transition: background .12s; }
.data-table tbody tr:hover td { background: var(--bg-2); }
.role-badge { font-size: 12px; font-weight: 700; padding: 3px 10px; border-radius: 999px; }
.role-badge.user { background: var(--brand-soft); color: var(--brand); }
.role-badge.admin { background: var(--amber-soft); color: var(--amber); }
.role-badge.superuser { background: var(--accent-soft); color: var(--accent); }
.status-badge { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; }
.status-badge .dot { width: 8px; height: 8px; border-radius: 50%; }
.status-badge.active { color: var(--ok); } .status-badge.active .dot { background: var(--ok); }
.status-badge.inactive { color: var(--off); } .status-badge.inactive .dot { background: var(--off); }
.badge-otp { font-size: 11px; background: var(--amber-soft); color: var(--amber); border-radius: 4px; padding: 2px 5px; font-weight: 700; margin-left: 4px; }
.row-actions { text-align: right; white-space: nowrap; }
.row-actions .mini-btn + .mini-btn { margin-left: 8px; }

/* ---------- Modal ---------- */
.modal-backdrop { position: fixed; inset: 0; background: rgba(15, 25, 40, .45); z-index: 1100; display: flex; align-items: center; justify-content: center; padding: 20px; animation: fade .2s; }
.modal { background: var(--bg); border-radius: 18px; width: min(500px, 96vw); max-height: min(720px, calc(100dvh - 40px)); overflow: hidden; display: flex; flex-direction: column; box-shadow: var(--shadow-lg); animation: pop .24s var(--ease); }
@keyframes pop { from { transform: scale(.94) translateY(10px); opacity: 0; } to { transform: none; opacity: 1; } }
.modal-head { display: flex; align-items: center; justify-content: space-between; padding: 18px 22px; background: var(--card); border-bottom: 1px solid var(--line); }
.modal-head h2 { font-size: 18px; }
.modal-body { min-height: 0; padding: 20px 22px; overflow-y: auto; overscroll-behavior: contain; }
.field { margin-bottom: 14px; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.field > label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 6px; }
.field input { width: 100%; padding: 10px 12px; border: 1px solid var(--line-2); border-radius: 9px; font-size: 14px; background: var(--card); transition: all .14s var(--ease); }
.field input:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.field input:disabled { background: var(--off-soft); color: var(--ink-soft); }
.field .muted { margin-top: 4px; font-size: 12px; }

/* ---------- Gedeelde formuliercontrols ----------
   .ctl geeft een los <input>/<select>/<textarea> dezelfde look als .field input
   en .cselect-btn, zodat velden buiten een modal (instellingenpanelen, de
   IJsvorming-tab) niet terugvallen op de browserstandaard. */
.ctl {
  width: 100%; box-sizing: border-box; padding: 10px 12px; border: 1px solid var(--line-2);
  border-radius: 9px; font: inherit; font-size: 14px; color: var(--ink);
  background: var(--card); transition: all .14s var(--ease);
}
.ctl:hover:not(:disabled) { border-color: var(--brand); }
.ctl:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft); }
.ctl:disabled { background: var(--off-soft); color: var(--ink-soft); }
/* Datum-/tijdvelden willen anders zo breed als hun tekst; in een kolom zetten
   we ze net als de rest op de volle breedte. */
.ctl[type="time"], .ctl[type="date"], .ctl[type="datetime-local"], .ctl[type="number"] { min-width: 0; }
/* Vaste waarde die je niet zelf invult (bv. een naam die de koppeling ophaalt),
   in dezelfde vorm als de invulvelden ernaast zodat de rij uitlijnt. */
.ctl-static { background: var(--off-soft); color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctl-static:hover { border-color: var(--line-2); }
.ctl-static.is-set { color: var(--ink); font-weight: 600; }

/* Label + control + uitleg als één blok, zodat losse velden onder elkaar of in
   een raster altijd op dezelfde hoogte uitlijnen. */
.field-stack { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px 16px; align-items: start; }
.field-item { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.field-label { font-size: 13px; font-weight: 600; color: var(--ink); }
.field-note { font-size: 12px; line-height: 1.45; color: var(--ink-soft); }
.field-note.danger-text { color: var(--warn); font-weight: 600; }

/* Afgebakend blok met kop + uitleg binnen een groter formulier. */
.settings-block { margin: 4px 0 18px; padding: 14px 16px; border: 1px solid var(--line); border-radius: 12px; background: var(--bg-2); }
.settings-block-head h3 { font-size: 13px; font-weight: 600; color: var(--ink); }
.settings-block-head .muted { margin: 6px 0 0; font-size: 12px; line-height: 1.5; }
.settings-block-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 12px 0 14px; }
.settings-block-actions .field-note { flex: 1 1 200px; }
.settings-advanced { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 12px; }
.settings-advanced > summary { cursor: pointer; font-size: 12px; font-weight: 600; color: var(--ink-soft); list-style: none; display: flex; align-items: center; gap: 6px; }
.settings-advanced > summary::-webkit-details-marker { display: none; }
.settings-advanced > summary::before { content: "›"; display: inline-block; transition: transform .16s var(--ease); font-size: 15px; line-height: 1; }
.settings-advanced[open] > summary::before { transform: rotate(90deg); }
.settings-advanced > summary:hover { color: var(--brand); }
.settings-advanced > .field-stack { margin-top: 12px; }

.section-divider { font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-faint); font-weight: 700; margin: 18px 0 12px; padding-top: 14px; border-top: 1px solid var(--line); }
.info-box { background: var(--brand-soft); color: var(--brand-dark); font-size: 13px; padding: 11px 13px; border-radius: 10px; margin-bottom: 14px; }
.modal-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; margin-top: 18px; }
.modal-actions .btn-primary { margin-left: auto; }
.user-form { min-height: 0; }
.user-form .assign-list { max-height: min(210px, 29dvh); }
.user-actions {
  position: sticky;
  bottom: -20px;
  z-index: 2;
  margin: 18px -22px -20px;
  padding: 14px 22px;
  background: var(--bg);
  border-top: 1px solid var(--line);
}

/* ---------- Confirm dialog ---------- */
.confirm-backdrop { position: fixed; inset: 0; background: rgba(15, 25, 40, .55); z-index: 1300; display: flex; align-items: center; justify-content: center; padding: 20px; animation: fade .2s; }
.confirm-dialog { background: var(--bg); border-radius: 18px; width: min(400px, 96vw); padding: 22px 24px; box-shadow: var(--shadow-lg); animation: pop .24s var(--ease); }
.confirm-dialog h3 { font-size: 17px; margin-bottom: 10px; }
.confirm-dialog p { font-size: 14px; color: var(--ink-soft); line-height: 1.5; }
.confirm-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 20px; }
.confirm-dialog.danger .confirm-actions .btn-primary { background: var(--warn); box-shadow: none; }
.confirm-dialog.danger .confirm-actions .btn-primary:hover { background: var(--warn); filter: brightness(.92); transform: translateY(-1px); }

/* Geocode Status Styling */
.geocode-status { font-size: 12px; margin-top: -6px; margin-bottom: 12px; font-weight: 600; transition: color 0.15s; }
.geocode-status.loading { color: var(--ink-soft); }
.geocode-status.success { color: var(--ok); }
.geocode-status.error { color: var(--warn); }
.location-field { position: relative; }
.location-field > .muted { margin-top: 6px; font-size: 11px; }
.location-suggestions { position: absolute; z-index: 1003; left: 0; right: 0; top: calc(100% - 20px); padding: 5px; border: 1px solid var(--line-2); border-radius: 10px; background: var(--card); box-shadow: var(--shadow); }
.location-suggestion { display: block; width: 100%; padding: 9px 10px; border: 0; border-radius: 7px; background: transparent; color: var(--ink); text-align: left; cursor: pointer; font: inherit; font-size: 13px; }
.location-suggestion:hover, .location-suggestion:focus, .location-suggestion.active { background: var(--brand-soft); color: var(--brand); outline: 0; }
.location-suggestions { max-height: 260px; overflow-y: auto; }

/* ---------- Custom select ---------- */
.cselect { position: relative; user-select: none; }
.cselect-btn { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 12px; border: 1px solid var(--line-2); border-radius: 9px; background: var(--card); font-size: 14px; font-weight: 500; color: var(--ink); cursor: pointer; transition: all .14s var(--ease); text-align: left; }
/* Een lang optielabel mag de knop niet hoger maken dan de velden ernaast. */
.cselect-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cselect.open .cselect-btn, .cselect-btn:hover { border-color: var(--brand); }
.cselect.open .cselect-btn { box-shadow: 0 0 0 3px var(--brand-soft); }
.cselect-arrow { display: inline-flex; width: 16px; height: 16px; color: var(--ink-faint); flex-shrink: 0; transition: transform .2s var(--ease); }
.cselect-arrow svg { width: 100%; height: 100%; }
.cselect.open .cselect-arrow { transform: rotate(180deg); }
.cselect-menu { position: absolute; top: calc(100% + 6px); left: 0; right: 0; background: var(--card); border: 1px solid var(--line); border-radius: 10px; box-shadow: var(--shadow); padding: 5px; z-index: 1002; opacity: 0; transform: translateY(-6px); pointer-events: none; transition: opacity .16s var(--ease), transform .16s var(--ease); max-height: 280px; overflow-y: auto; overscroll-behavior: contain; }
/* Een .card klipt standaard (overflow: hidden), waardoor een uitgeklapte lijst
   onderaan de kaart werd afgesneden. Deze panelen bevatten keuzelijsten. */
.installation-card, #panel-ijsvorming .card { overflow: visible; }
.cselect.open .cselect-menu { opacity: 1; transform: none; pointer-events: auto; }
.cselect-opt { padding: 9px 11px; border-radius: 7px; font-size: 14px; cursor: pointer; transition: background .12s; }
.cselect-opt:hover { background: var(--bg-2); }
.cselect-opt.sel { background: var(--brand-soft); color: var(--brand); font-weight: 600; }
/* Toetsenbordfocus binnen het menu (pijltjes). */
.cselect-opt.active { background: var(--bg-2); box-shadow: inset 0 0 0 2px var(--brand); }

/* ---------- Custom checkbox / assign list ---------- */
.assign-list { max-height: 210px; overflow-y: auto; border: 1px solid var(--line); border-radius: 12px; padding: 6px; background: var(--card); }
/* Filterveld boven de systeemlijst in de gebruikerspopup. */
.assign-search { margin-bottom: 8px; }

/* Formulierfout die blijft staan zolang de modal openstaat. */
.form-error { margin: 12px 0 0; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--warn); background: var(--warn-soft); color: var(--warn); font-size: 13.5px; }

/* Knop met spinner terwijl de bijbehorende call loopt. */
button.is-busy { display: inline-flex; align-items: center; gap: 8px; opacity: .75; cursor: progress; }

/* Aantal zichtbare resultaten naast een sectiekop. */
.count-pill { display: inline-block; margin-left: 8px; padding: 2px 9px; border-radius: 99px; background: var(--brand-soft); color: var(--brand); font-size: 12px; font-weight: 700; vertical-align: middle; }

/* Foutstaat in plaats van een eeuwig draaiend skelet. */
.load-error { display: flex; align-items: center; justify-content: center; gap: 12px; flex-wrap: wrap; padding: 14px 12px; color: var(--ink-soft); font-size: 14px; text-align: center; }
.btn-ghost.sm { padding: 5px 10px; font-size: 13px; }

.assign-group { position: sticky; top: -6px; z-index: 1; margin: 0 0 4px; padding: 6px 10px 4px; background: var(--card); font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-soft); }
.assign-group ~ .assign-group { margin-top: 8px; border-top: 1px solid var(--line); padding-top: 10px; }
.assign-row { display: flex; align-items: center; gap: 8px; border-radius: 99px; padding: 4px; transition: background .12s; margin-bottom: 4px; }
.assign-row:last-child { margin-bottom: 0; }
.assign-row.on { background: var(--brand-soft); }
.check { display: flex; align-items: center; gap: 10px; padding: 7px 8px; cursor: pointer; font-size: 14px; flex: 1; min-width: 0; }
.check input { position: absolute; opacity: 0; width: 0; height: 0; }
.check-box { width: 20px; height: 20px; border: 2px solid var(--line-2); border-radius: 6px; flex: none; position: relative; transition: all .16s var(--ease); background: var(--card); }
.check-box::after { content: ""; position: absolute; inset: 0; margin: auto; width: 5px; height: 10px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg) scale(0); transition: transform .16s var(--ease); }
.check input:checked ~ .check-box { background: var(--brand); border-color: var(--brand); }
.check input:checked ~ .check-box::after { transform: rotate(45deg) scale(1); }
.check input:focus-visible ~ .check-box { box-shadow: 0 0 0 3px var(--brand-soft); }
.check-txt { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- Permission toggle (inline switch) ---------- */
.perm-toggle { display: flex; align-items: center; gap: 6px; padding: 4px 8px; cursor: pointer; flex: none; }
.perm-toggle-label { font-size: 12px; font-weight: 600; color: var(--ink-soft); }
.perm-toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.perm-switch-track { position: relative; width: 34px; height: 20px; border-radius: 99px; background: var(--line-2); flex: none; transition: background .16s var(--ease); }
.perm-switch-thumb { position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.25); transition: transform .16s var(--ease); }
.perm-toggle input:checked ~ .perm-switch-track { background: var(--brand); }
.perm-toggle input:checked ~ .perm-switch-track .perm-switch-thumb { transform: translateX(14px); }
.perm-toggle input:focus-visible ~ .perm-switch-track { box-shadow: 0 0 0 3px var(--brand-soft); }

/* ---------- Offline-regeling toggle + toelichting (installatiepagina) ---------- */
.offline-mode-box { margin: 4px 0 18px; padding: 14px 16px; border: 1px solid var(--line); border-radius: 12px; background: var(--bg-2); }
.offline-mode-toggle.perm-toggle { width: 100%; justify-content: space-between; padding: 0; }
.offline-mode-toggle .perm-toggle-label { font-size: 13px; font-weight: 600; color: var(--ink); }
.offline-mode-hint { margin: 8px 0 0; padding: 0; font-size: 12px; line-height: 1.5; color: var(--ink-soft); }

/* ---------- Weergavemodus (eenvoudig / technisch) ---------- */
/* Staat in de gedeelde topbar (fleet.css wordt op beide pagina's geladen). In
   eenvoudige modus verdwijnt alles met .tech-only; de rol blijft leidend voor
   wat je überhaupt mág zien. */
.mode-toggle.perm-toggle { flex: none; margin: 0 6px; }
.mode-toggle .perm-toggle-label { color: var(--ink-soft); white-space: nowrap; }
[data-mode="simple"] .tech-only { display: none !important; }

/* ---------- OTP result ---------- */
.otp-result p { margin: 0 0 10px; font-size: 14px; }
.otp-box { display: flex; align-items: center; gap: 10px; background: var(--bg-2); border: 1px dashed var(--line-2); border-radius: 12px; padding: 14px; margin: 6px 0; }
.otp-box code { font-size: 24px; font-weight: 800; letter-spacing: .12em; color: var(--brand); flex: 1; }

/* ---------- Toast ---------- */
.toast { position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%) translateY(20px); background: var(--ink); color: #fff; padding: 12px 22px; border-radius: 12px; z-index: 1200; font-size: 14px; box-shadow: var(--shadow-lg); opacity: 0; transition: opacity .25s var(--ease), transform .25s var(--ease); }
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast.err { background: var(--warn); }


/* ---------- Mijn account (gedeeld, uit de topbar-partial) ---------- */
.account-backdrop { position: fixed; inset: 0; background: rgba(19, 35, 56, .34); z-index: 1090; }
.account-menu {
  position: fixed; top: 66px; right: 16px; z-index: 1100;
  width: min(340px, calc(100vw - 32px)); max-height: calc(100dvh - 90px); overflow-y: auto;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); padding: 16px 18px 18px;
  animation: account-in .18s var(--ease) both;
}
@keyframes account-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
.account-menu-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 4px; }
.account-menu-head h2 { font-size: 16px; }
.account-menu-sub { margin: 2px 0 0; font-size: 12px; color: var(--ink-soft); }
.account-section { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
.account-section:first-of-type { border-top: none; padding-top: 6px; margin-top: 6px; }
.account-section h3 { font-size: 13px; margin-bottom: 10px; }
.account-langs .chip { padding: 7px 13px; font-size: 12.5px; }
.account-lang-hint { margin-top: 8px; font-size: 12px; }
.account-menu .field { margin-bottom: 12px; }
.account-menu .btn-primary { width: 100%; }
.account-feedback { margin-top: 10px; font-size: 12.5px; font-weight: 600; color: var(--ok); }
.account-feedback.err { color: var(--warn); }
.account-menu[hidden], .account-backdrop[hidden] { display: none !important; }
@media (max-width: 820px) {
  .account-menu { top: auto; bottom: 0; left: 0; right: 0; width: auto;
    border-radius: var(--radius) var(--radius) 0 0; max-height: 82dvh;
    padding-bottom: calc(20px + env(safe-area-inset-bottom, 0px)); }
  @keyframes account-in { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
}

/* ---------- Dev credit ---------- */
.dev-credit {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 500;
  display: flex; align-items: center; justify-content: center;
  padding: 10px 16px;
  font-size: 13px; color: var(--ink-soft);
  background: rgba(255, 255, 255, .85);
  backdrop-filter: saturate(180%) blur(12px);
  border-top: 1px solid var(--line);
}
.dev-credit a { color: var(--brand); font-weight: 600; text-decoration: none; }
.dev-credit a:hover { text-decoration: underline; }

/* Mobile Nav (Bottom Footer) */
.bottom-nav {
  position: fixed; bottom: 0; left: 0; right: 0; height: 60px;
  background: rgba(255, 255, 255, 0.88); border-top: 1px solid var(--line);
  box-shadow: 0 -4px 20px rgba(19, 35, 56, 0.08); z-index: 800;
  display: none; align-items: center; justify-content: space-around;
  backdrop-filter: blur(12px);
}
.bnav-item {
  border: none; background: transparent; padding: 6px 12px; color: var(--ink-soft);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; cursor: pointer; transition: all 0.16s var(--ease); flex: 1; height: 100%;
}
.bnav-item svg { width: 20px; height: 20px; opacity: 0.7; transition: transform 0.16s; }
.bnav-item span { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; }
.bnav-item:hover svg { transform: translateY(-1px); }
.bnav-item.active { color: var(--brand); }
.bnav-item.active svg { stroke: var(--brand); opacity: 1; transform: scale(1.1) translateY(-1px); }

/* ---------- Responsive ---------- */
@media (max-width: 820px) {
  .topbar { padding: 10px 16px; }
  .desktop-tabs { display: none; }
  .bottom-nav { display: flex; }
  /* Alleen boven de bottom-nav tillen als die er ook echt is (device/fleet) —
     op het inlogscherm (geen .bottom-nav in de DOM) hoort de footer gewoon
     onderaan te blijven. */
  .bottom-nav ~ .dev-credit { bottom: 60px; }
  .dev-credit { font-size: 12px; padding: 8px 12px; }
  main { padding: 18px 14px 130px; }
  /* Filterknoppen mogen de viewport nooit oprekken: volle breedte + kleinere
     chips, zodat ze netjes over ~2 rijen breken i.p.v. horizontaal uit beeld. */
  .section-head { align-items: flex-start; }
  .section-tools { width: 100%; }
  .filter-chips { width: 100%; }
  .chip { padding: 8px 13px; font-size: 12.5px; }
  .kpis, .insight-hero { grid-template-columns: 1fr; }
  /* Mobiel: KPI's als compacte 2-koloms subset i.p.v. één lange kolom (§12.5). */
  .kpi-strip { grid-template-columns: 1fr 1fr; gap: 10px; }
  .kpi-card { min-height: 92px; padding: 14px 14px 12px; }
  .kpi-value { font-size: 26px; }
  .delta-ref { display: none; }
  .plot { height: 140px; }
  .plot.is-split { height: 180px; }
  .y-axis { min-height: 140px; }
  .col-chart { gap: 2px; }
  .x-axis .tick { font-size: 9.5px; }
  .attention-row { grid-template-columns: 10px 1fr; }
  .attention-row .att-go { display: none; }
  .insight-grid-info { grid-template-columns: 1fr; }
  .field-row { grid-template-columns: 1fr; }
  .bar-row { grid-template-columns: 110px 1fr 70px; }
  #map { height: 280px; }
  .map-scroll-guard .msg-desktop { display: none; }
  .map-scroll-guard .msg-mobile { display: inline; }
  .brand .brand-txt h1 { font-size: 16px; }
  .brand .brand-txt p.sub { font-size: 11px; }
  .user-chip { display: none; } /* Hide user chip on mobile, keep logo & logout btn */
  /* Op mobiel alleen de schakelaar, zonder label — scheelt breedte in de topbar. */
  .mode-toggle-label { display: none; }
  .modal-backdrop { padding: 12px; }
  .modal { width: 100%; max-height: calc(100dvh - 24px); }
  .user-actions { bottom: -20px; }
}

/* Op telefoon passen er twee systeemkaarten naast elkaar; de auto-fill van
   270px valt anders terug op één kolom en dan wordt de lijst onnodig lang.
   De kaart wordt hiervoor compacter: de status blijft rechtsboven naast de
   naam staan, maar dan alleen als gekleurd bolletje (de tekst past niet naast
   de naam op ~165px breedte), en de voetregel gaat onder elkaar. */
@media (max-width: 560px) {
  .card-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .sys-card { padding: 13px 13px 14px; }
  .sys-card-top { gap: 6px; }
  .sys-card-top h3 { font-size: 14px; overflow-wrap: anywhere; }
  .sys-place { font-size: 12px; overflow-wrap: anywhere; }
  .sys-hero { margin: 12px 0 2px; }
  .sys-hero .hero-num { font-size: 22px; }
  .sys-hero .hero-lbl { font-size: 11px; }
  .sys-foot { flex-direction: column; gap: 3px; margin-top: 10px; padding-top: 10px; font-size: 11.5px; }
  .sys-card .status-pill { background: none; padding: 3px 0 0; gap: 0; flex: none; }
  .sys-card .status-pill .dot { width: 11px; height: 11px; }
  .sys-card .pill-txt { display: none; }
}

/* Password eye visibility toggle */
.pw-wrapper { position: relative; display: flex; align-items: center; width: 100%; }
.pw-wrapper input { padding-right: 42px !important; }
.pw-toggle {
  position: absolute; right: 8px; border: none; background: transparent;
  color: var(--ink-faint); cursor: pointer; display: flex; align-items: center;
  justify-content: center; width: 30px; height: 30px; border-radius: 8px;
  transition: all .16s; padding: 0; z-index: 10;
}
.pw-toggle:hover { color: var(--brand); background: var(--off-soft); }
.pw-toggle svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* ---------- PWA "toevoegen aan startscherm" kaart ---------- */
.pwa-install-banner {
  position: fixed; left: 12px; right: 12px;
  bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  z-index: 1150; max-width: 420px; margin: 0 auto;
  animation: pwa-install-in .3s var(--ease) both;
}
@media (max-width: 820px) {
  /* Alleen boven de bottom-nav tillen als die er ook echt is (device/fleet) —
     op het inlogscherm (geen .bottom-nav in de DOM) hoort de kaart gewoon
     onderaan te blijven, net als de footer hierboven. */
  .bottom-nav ~ .pwa-install-banner { bottom: calc(72px + env(safe-area-inset-bottom, 0px)); }
}
@keyframes pwa-install-in {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: translateY(0); }
}
.pwa-install-card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  padding: 14px 14px 14px 16px;
}
.pwa-install-row { display: flex; align-items: flex-start; gap: 12px; }
.pwa-install-icon { border-radius: 11px; flex-shrink: 0; box-shadow: 0 2px 6px rgba(19, 35, 56, .18); }
.pwa-install-body { flex: 1; min-width: 0; }
.pwa-install-title { font-size: 14px; font-weight: 700; color: var(--ink); margin: 0 0 3px; }
.pwa-install-hint { font-size: 12.5px; color: var(--ink-soft); line-height: 1.45; margin: 0; }
.pwa-install-hint strong { color: var(--ink); }
.pwa-share-ico { display: inline-block; }
.pwa-install-close {
  border: none; background: transparent; color: var(--ink-faint); cursor: pointer;
  font-size: 15px; line-height: 1; width: 26px; height: 26px; border-radius: 8px;
  flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  transition: all .16s var(--ease);
}
.pwa-install-close:hover { background: var(--off-soft); color: var(--ink); }
.pwa-install-btn {
  display: block; width: 100%; margin-top: 10px; border: none; cursor: pointer;
  background: var(--brand); color: #fff; font-weight: 700; font-size: 13.5px;
  padding: 10px; border-radius: 10px; transition: background .16s var(--ease);
}
.pwa-install-btn:hover { background: var(--brand-dark); }
.pwa-install-btn-secondary { background: var(--off-soft); color: var(--ink); }
.pwa-install-btn-secondary:hover { background: var(--line); }

/* ---------- Testopstelling (ijsmeting + timelapse) ---------- */
.to-wrap { display: flex; flex-direction: column; gap: 16px; }
.to-status { color: var(--ink-faint); }
/* Inhoud van een kaart lijnt uit met de kop erboven (.card-head: 18px 20px);
   zonder deze marge plakt alles tegen de kaartrand. */
.card-body { padding: 18px 20px; }
.card-body > :first-child { margin-top: 0; }
.card-body > :last-child { margin-bottom: 0; }

/* Periodeknoppen links, afspeelsnelheid rechts, boven de kijker. */
.to-controls { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px 24px; flex-wrap: wrap; margin-bottom: 16px; }
.to-control-block { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.to-speed-block { flex: 0 1 240px; }

.to-hero { display: grid; grid-template-columns: 1.6fr 1fr; gap: 16px; }
/* Foto, afspeelbalk en fotostrook zijn één geheel: de balk loopt over de volle
   kaartbreedte door, zodat je ook bij honderden foto's nauwkeurig kunt slepen. */
.to-viewer { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.to-photo {
  position: relative; background: var(--bg-2); border: 1px solid var(--line);
  border-radius: var(--radius-sm); aspect-ratio: 16 / 10; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
.to-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.to-photo-empty { color: var(--ink-faint); font-size: 14px; }
.to-frame-time {
  position: absolute; left: 10px; bottom: 10px; background: rgba(255,255,255,.92);
  border: 1px solid var(--line); border-radius: 8px; font-size: 12px; padding: 3px 8px; color: var(--ink);
}
/* Sluier tijdens "Nu een foto maken": relais aan, stabiliseren, snapshot. */
.to-photo-busy {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 10px;
  background: rgba(255, 255, 255, .78); color: var(--brand);
  font-size: 13px; font-weight: 600; animation: ui-fade-in .18s var(--ease);
}
/* De meterkaart vult de hoogte naast de foto (waarde in het midden) en de
   knoppen zitten onderaan gelijk met de onderrand van de foto. */
.to-hero-side { display: flex; flex-direction: column; gap: 12px; }
.to-metric {
  flex: 1; display: flex; flex-direction: column; justify-content: center;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 16px;
}
.to-metric-label { display: block; font-size: 13px; color: var(--ink-soft); }
.to-metric-value { display: block; font-size: 34px; font-weight: 700; color: var(--brand); line-height: 1.1; margin-top: 2px; }
.to-metric-sub { display: block; font-size: 12px; color: var(--ink-faint); margin-top: 4px; }
.to-shoot { width: 100%; display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 40px; }

.to-span { margin-bottom: 0; }
/* Van/tot + knop: de knop lijnt uit met de onderrand van de invoervelden, niet
   met de labels erboven. */
.to-custom { display: flex; align-items: flex-end; gap: 12px; margin-bottom: 14px; flex-wrap: wrap; }
.to-custom .field-item { flex: 0 1 230px; }
.to-custom .btn { flex: 0 0 auto; height: 40px; }

.to-player { display: flex; align-items: center; gap: 12px; }
/* Vierkante icoonknoppen (afspelen/pauzeren, downloaden, verwijderen). Ze
   staan op een witte kaart, dus een eigen vlak/rand — anders lezen ze als een
   plaatje in plaats van als knop. */
.to-icon-btn {
  flex: 0 0 auto; width: 38px; height: 38px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--off-soft); color: var(--ink); border: 1px solid var(--line-2);
  box-shadow: 0 1px 2px rgba(19, 35, 56, .06); transition: all .14s var(--ease);
}
.to-icon-btn svg { width: 16px; height: 16px; }
.to-icon-btn:hover:not(:disabled) { background: var(--brand-soft); border-color: var(--brand); color: var(--brand); }
.to-icon-btn:disabled { color: var(--ink-faint); cursor: not-allowed; opacity: .55; box-shadow: none; }
.to-icon-btn.danger { color: var(--warn); }
.to-icon-btn.danger:hover:not(:disabled) { background: var(--warn-soft); border-color: var(--warn); color: var(--warn); }
/* Afspelen is de hoofdactie van de balk. */
.to-play { background: var(--brand); border-color: var(--brand); color: #fff; }
.to-play:hover:not(:disabled) { background: var(--brand-dark); border-color: var(--brand-dark); color: #fff; }
.to-play:disabled { background: var(--off-soft); border-color: var(--line-2); }
.to-play.playing { background: var(--brand-dark); border-color: var(--brand-dark); color: #fff; }
.to-player input[type="range"] { flex: 1; min-width: 0; accent-color: var(--brand); height: 20px; cursor: pointer; }
.to-pos { flex: 0 0 auto; min-width: 104px; text-align: right; color: var(--ink-soft); font-size: 13px; }

.to-thumbs { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; }
.to-thumb {
  flex: 0 0 88px; height: 58px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg-2) center/cover no-repeat; cursor: pointer; padding: 0; position: relative;
}
.to-thumb.active { border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-soft); }
.to-thumb-ph { display: block; width: 100%; height: 100%; }
.to-empty { margin: 0; font-size: 13px; }

/* Per sensor één regel onder het grote getal — blijft leesbaar bij vier stuks. */
.to-sensors { list-style: none; margin: 12px 0 0; padding: 10px 0 0; border-top: 1px solid var(--line); display: flex; flex-direction: column; gap: 2px; }
.to-sensor { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; padding: 3px 0; font-size: 13px; color: var(--ink-soft); }
.to-sensor-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.to-sensor-value { flex: none; font-variant-numeric: tabular-nums; }
.to-sensor.is-top { color: var(--ink); font-weight: 600; }
.to-sensor.is-top .to-sensor-value { color: var(--brand); }

/* Onderbalk van de kijker: afspeelsnelheid links, opruimen rechts. */
.to-footer {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px 24px;
  flex-wrap: wrap; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line);
}
.to-cleanup { align-items: flex-end; text-align: right; }
.to-cleanup-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.btn-ghost.sm { padding: 5px 10px; font-size: 13px; }
.btn-ghost:disabled { opacity: .5; cursor: not-allowed; }

/* Groot weergeven. De foto en de afspeelbalk verhuizen hierheen, dus de
   maatvoering van .to-photo wordt hier overschreven. */
.to-lightbox {
  position: fixed; inset: 0; z-index: 1200; display: flex; flex-direction: column;
  gap: 12px; padding: 14px 18px 20px; background: rgba(12, 22, 36, .93);
  animation: ui-fade-in .16s var(--ease);
}
.to-lightbox-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex: none; }
.to-lightbox-title { color: rgba(255, 255, 255, .82); font-size: 13px; }
.to-lightbox .to-icon-btn { background: rgba(255, 255, 255, .12); border-color: rgba(255, 255, 255, .28); color: #fff; }
.to-lightbox .to-icon-btn:hover:not(:disabled) { background: rgba(255, 255, 255, .22); border-color: #fff; color: #fff; }
.to-lightbox .to-play { background: var(--brand); border-color: var(--brand); }
.to-lightbox-stage { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 12px; }
.to-lightbox .to-photo { flex: 1; min-height: 0; aspect-ratio: auto; background: #000; border-color: rgba(255,255,255,.18); cursor: default; }
.to-lightbox .to-photo img { object-fit: contain; }
.to-lightbox .to-photo-expand { display: none; }
.to-lightbox .to-player { flex: none; }
.to-lightbox .to-pos { color: rgba(255, 255, 255, .8); }
/* Achtergrond niet meescrollen zolang de vergroting openstaat. */
body.to-noscroll { overflow: hidden; }

/* Vergrootknopje rechtsboven in de foto; de hele foto is ook klikbaar. */
.to-photo { cursor: zoom-in; }
.to-photo-expand {
  position: absolute; top: 10px; right: 10px; width: 30px; height: 30px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line); border-radius: 8px; background: rgba(255, 255, 255, .92);
  color: var(--ink); cursor: zoom-in; transition: all .14s var(--ease);
}
.to-photo-expand svg { width: 15px; height: 15px; }
.to-photo-expand:hover { background: #fff; color: var(--brand); border-color: var(--brand); }

/* Uitleg onder een kaartkop, boven de eerste keuze. */
.to-lead { margin: 0 0 14px; font-size: 13px; line-height: 1.5; color: var(--ink-soft); }
.to-settings { margin-top: 14px; }
/* Regel onder de instellingen: wat er nu staat ingesteld, in gewone taal. */
.to-summary { margin: 14px 0 0; padding-top: 12px; border-top: 1px solid var(--line); font-size: 13px; color: var(--ink-soft); }
.to-summary strong { color: var(--ink); font-weight: 600; }

@media (max-width: 720px) {
  .to-hero { grid-template-columns: 1fr; }
}
