/* WattBridge.nl – gedeelde stijl van het beheerdashboard (cloud), het setup-portal (hub) en de
   webinterfaces van de modules (OCPP- en Modbus-proxy). Dit bestand staat op vier plekken en
   moet overal gelijk zijn (cloud/tests/test_frontend.py controleert dat):
     cloud/esh_cloud/static/style.css            edge/esh_agent/static/style.css
     edge/modules/ocpp-proxy/ocpp_proxy/static/   edge/modules/modbus-proxy/modbus_proxy/static/

   Uitgangspunten (zie docs/HUISSTIJL.md):
   - kleur alleen voor status (groen/oranje/rood) en één accentkleur (tenant mag die zetten);
   - weinig kaders: vlakken met een dunne rand, geen zware schaduwen;
   - koppen in gewone schrijfwijze, knoppen zo breed als hun tekst;
   - vaste maten: 4/8/12/16/24/32 px. */
:root {
  --nacht: #0B1F33; --stroom: #1F6FB2; --licht: #E8F1FA;
  --zon: #F5A623; --zon-bg: #FDF3E1; --zon-ink: #8A5A00; --groen: #1E9E5E; --groen-ink: #157A47; --groen-bg: #E5F6ED;
  --rood: #B42318; --rood-bg: #FDECEA; --grijs: #F2F4F7; --steen: #5B6573;
  --paars: #6941C6; --paars-ink: #6941C6;

  --bg: #F6F8FA; --surface: #ffffff; --surface-alt: var(--grijs); --text: var(--nacht);
  --muted: var(--steen); --border: rgba(11, 31, 51, 0.08); --border-strong: rgba(11, 31, 51, 0.16);
  --accent: var(--stroom); --accent-bg: var(--licht);
  /* Knoppen: in beide modi donker genoeg voor witte tekst (contrast >= 4,5; cloud/tests/test_frontend.py). */
  --button: var(--stroom); --button-danger: #B42318;
  --radius: 10px; --mono: ui-monospace, SFMono-Regular, Menlo, monospace;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0A141F; --surface: #0F1D2C; --surface-alt: #162839; --text: #E7EEF5; --muted: #94A3B3;
    --border: rgba(232, 241, 250, 0.09); --border-strong: rgba(232, 241, 250, 0.18);
    --licht: #15304A; --accent-bg: #15304A; --groen-bg: #12301F; --rood-bg: #3A1C1A; --zon-bg: #3A2C12;
    --zon-ink: #F5C46B; --accent: #5AA6E6; --rood: #F07167; --groen: #4CC38A; --groen-ink: #4CC38A;
    --paars: #9E77ED; --paars-ink: #B692F6;
  }
  .logo .ink { fill: var(--text); }
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif; font-size: 15px;
  background: var(--bg); color: var(--text); line-height: 1.5; min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}
[hidden], .role-hidden { display: none !important; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* --- opbouw van de pagina ------------------------------------------------------------------ */
.wrap { max-width: 720px; margin: 0 auto; padding: 16px; }
.wrap.wide { max-width: 1200px; padding: 24px 24px 16px; }
/* Gecentreerde kop: setup-portal, eerste beheerder, account instellen. */
header { text-align: center; padding: 16px 0 24px; }
.logo { height: 32px; width: auto; display: block; }
header .logo { margin: 0 auto; }
.brand-name { font-size: 20px; font-weight: 700; color: var(--accent); letter-spacing: -0.01em; }
.brand-logo { height: 30px; width: auto; max-width: 220px; display: block; }
header h1 { margin-top: 12px; }
.subtitle { color: var(--muted); font-size: 14px; margin: 2px 0 0; }

/* Bovenbalk van het dashboard: logo links, menu, gebruiker rechts. */
.topbar { background: var(--surface); border-bottom: 1px solid var(--border); }
.topbar-inner {
  max-width: 1200px; margin: 0 auto; padding: 0 24px; min-height: 56px;
  display: flex; align-items: center; gap: 24px; flex-wrap: wrap;
}
.topbar .brand { display: flex; align-items: center; gap: 10px; }
.topbar .logo { height: 26px; }
.topbar .brand-logo { height: 28px; }
.topbar .who { margin-left: auto; display: flex; align-items: center; gap: 12px; font-size: 14px; color: var(--muted); }

h1 { font-size: 22px; margin: 0; font-weight: 650; letter-spacing: -0.015em; }
h2 { font-size: 16px; margin: 32px 0 12px; font-weight: 650; display: flex; gap: 8px; align-items: center; }
h2:first-child { margin-top: 0; }
h3 { font-size: 15px; margin: 0 0 8px; font-weight: 650; }
.page-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 0 0 20px; }
.page-head .sub { color: var(--muted); font-size: 14px; margin: 2px 0 0; }
.page-head .tools { margin-left: auto; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.page-head .tools input:not([type="checkbox"]) { width: 240px; }
.page-head .tools button { margin: 0; }
.back { display: inline-block; font-size: 14px; color: var(--muted); margin-bottom: 8px; }
footer { text-align: center; color: var(--muted); font-size: 12px; margin: 40px 0 8px; }

/* --- menu en tabbladen -------------------------------------------------------------------- */
nav { display: flex; gap: 2px; flex-wrap: wrap; align-items: center; }
nav button {
  background: none; color: var(--muted); padding: 6px 12px; font-weight: 550; border-radius: 8px; margin: 0;
}
nav button:hover { color: var(--text); background: var(--surface-alt); }
nav button.active { color: var(--text); background: var(--surface-alt); }
/* Menu van de hub (setup-portal en modulepagina's) bestaat uit links. */
nav a { color: var(--muted); padding: 6px 12px; font-weight: 550; font-size: 14px; border-radius: 8px; text-decoration: none; }
nav a:hover { color: var(--text); background: var(--surface-alt); text-decoration: none; }
nav a.active { color: var(--text); background: var(--surface-alt); }
.portal #tab-wizard, .portal #tab-account, .portal #login { max-width: 760px; margin-left: auto; margin-right: auto; }
/* Menu in een gecentreerde kop (setup-portal). */
header nav {
  justify-content: center; margin: 16px auto 0; padding: 4px; background: var(--surface-alt);
  border-radius: 10px; width: fit-content; max-width: 100%;
}
header nav button.active { background: var(--surface); box-shadow: 0 1px 2px rgba(11, 31, 51, 0.08); }
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin: 0 0 20px; overflow-x: auto; }
.tabs button {
  background: none; color: var(--muted); border-radius: 0; padding: 10px 12px; margin: 0 0 -1px;
  border-bottom: 2px solid transparent; font-weight: 550; white-space: nowrap;
}
.tabs button:hover { color: var(--text); }
.tabs button.active { color: var(--text); border-bottom-color: var(--accent); }

/* --- vlakken ------------------------------------------------------------------------------ */
.card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 20px; margin-bottom: 16px;
}
.card > :last-child { margin-bottom: 0; }
.card > p.muted:first-child { margin-top: 0; font-size: 14px; }
.card.narrow { max-width: 400px; margin: 40px auto; }
.card.danger { border-color: color-mix(in srgb, var(--rood) 35%, transparent); }
.grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.tile { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px 16px; }
.tile .label { color: var(--muted); font-size: 13px; }
.tile .value { font-size: 22px; font-weight: 650; }
.notice {
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap; padding: 12px 16px; margin: 0 0 16px;
  border-radius: var(--radius); background: var(--accent-bg); font-size: 14px;
}
.notice.warn { background: var(--zon-bg); }
.notice.bad { background: var(--rood-bg); }
.notice.ok { background: var(--groen-bg); }
.notice .grow { flex: 1; min-width: 200px; }
.notice button, .notice .button { margin: 0; }
details.more { margin-top: 12px; font-size: 14px; }
details.more > summary { cursor: pointer; color: var(--muted); list-style: none; }
details.more > summary::before { content: "▸ "; }
details.more[open] > summary::before { content: "▾ "; }
details.more > summary::-webkit-details-marker { display: none; }
details.more[open] > summary { margin-bottom: 8px; }

/* --- formulieren -------------------------------------------------------------------------- */
label { display: block; font-size: 14px; font-weight: 550; margin: 12px 0 4px; }
label.check { display: flex; gap: 8px; align-items: center; }
label.check input { width: auto; margin: 0; }
.hint { color: var(--muted); font-size: 13px; margin: 4px 0 0; font-weight: 400; }
input, select, textarea {
  width: 100%; padding: 8px 10px; font: inherit; color: var(--text); background: var(--surface);
  border: 1px solid var(--border-strong); border-radius: 8px;
}
input[type="file"] { padding: 6px; }
input:focus, select:focus, textarea:focus, button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
button, .button {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 8px 14px; font: inherit; font-weight: 600; font-size: 14px; border: 0; border-radius: 8px;
  background: var(--button); color: #fff; cursor: pointer; margin-top: 16px; text-decoration: none;
}
button:hover { filter: brightness(1.06); }
button.secondary, .button.secondary {
  background: var(--surface); color: var(--text); box-shadow: inset 0 0 0 1px var(--border-strong);
}
button.secondary:hover, .button.secondary:hover { background: var(--surface-alt); filter: none; text-decoration: none; }
button.danger { background: var(--button-danger); }
button.small { padding: 4px 10px; font-size: 13px; margin: 0; }
button.link { background: none; color: var(--accent); padding: 2px 4px; margin: 0; font-weight: 550; }
button.link:hover { text-decoration: underline; filter: none; }
button:disabled { opacity: 0.55; cursor: default; }
/* Smalle formulieren (inloggen, account): de hoofdknop over de volle breedte. */
.card.narrow button[type="submit"], button.block { width: 100%; }
.row { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; }
.row > * { flex: 1; min-width: 160px; }
.row > .auto, .row > button, .row.auto > * { flex: 0 0 auto; min-width: 0; }
.row > h3 { margin: 0; }
.row > .push { margin-left: auto; }
h3.section { margin: 24px 0 4px; }
.block-gap { margin-bottom: 24px; }
/* Bewerkbare lijsten (backends, clients, live-waarden): invoervelden in een compacte tabel. */
.edit-table { margin: 8px 0; }
.edit-table th, .edit-table td { padding: 6px 8px; }
.edit-table td input:not([type="checkbox"]):not([type="radio"]), .edit-table td select { padding: 6px 8px; }
.edit-table td input + input, .edit-table td select + input { margin-top: 6px; }
.edit-table .w-name { width: 170px; } .edit-table .w-ip { width: 170px; } .edit-table .w-num { width: 100px; }
.edit-table .c { text-align: center; width: 70px; }
.edit-table input[type="checkbox"], .edit-table input[type="radio"] { width: auto; }
details.more.inline { margin: 0; }
details.more.inline > summary { font-size: 13px; }
.module-head { margin: 4px 0 16px; align-items: center; }
/* Live gegevens (alleen platform): totalenregel boven de hubtabel, kolom "Nu", live-kaart. */
.fleet-line { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin: 0 0 16px; }
.fleet-item { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 16px; }
.fleet-item .label { color: var(--muted); font-size: 13px; }
.fleet-item .value { font-size: 20px; font-weight: 650; }
.fleet-item .sub { color: var(--muted); font-size: 13px; }
th.live-col, td.live-col { white-space: nowrap; width: 1%; }
td.hub-cell { min-width: 160px; }
/* Lange meldingen breken af in plaats van de tabel te breed te maken. */
td.attn-cell { min-width: 140px; }
td.attn-cell .badge { white-space: normal; margin: 2px 4px 2px 0; border-radius: 8px; }
td.attn-cell .badge + .badge { margin-left: 0; }
td.live-col { font-variant-numeric: tabular-nums; }
td.live-col .live-value { font-weight: 600; line-height: 20px; }
td.live-col .sub { font-size: 12px; line-height: 16px; }
/* Vaste kleur per stroom: laadpaal paars, zon geel, net blauw, batterij groen (stip in de kop).
   De statusregel kleurt mee met de richting; "stil" en "in balans" blijven grijs. */
.flow-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; vertical-align: 1px; }
.flow-ev { background: var(--paars); } .flow-zon { background: var(--zon); }
.flow-net { background: var(--stroom); } .flow-bat { background: var(--groen); }
/* Specifieker dan "td .sub" en ".live-tiles .sub" (grijs). */
.live-tiles .sub[class*="tone-"], td .sub[class*="tone-"] { font-weight: 550; }
.live-tiles .sub.tone-ev, td .sub.tone-ev { color: var(--paars-ink); }
.live-tiles .sub.tone-zon, td .sub.tone-zon { color: var(--zon-ink); }
.live-tiles .sub.tone-in, td .sub.tone-in, .live-tiles .sub.tone-bad, td .sub.tone-bad { color: var(--rood); }
.live-tiles .sub.tone-out, td .sub.tone-out, .live-tiles .sub.tone-charge, td .sub.tone-charge { color: var(--groen-ink); }
.live-tiles .sub.tone-discharge, td .sub.tone-discharge { color: var(--accent); }
.live-tiles { border-top: 0; padding-top: 0; }
.live-tiles .sub { color: var(--muted); font-size: 13px; }
.row label { margin-bottom: 4px; }
/* Wizardknoppen: "Vorige" links, "Volgende"/opslaan rechts. */
.actions { display: flex; gap: 12px; margin-top: 8px; align-items: center; }
.actions button { margin-top: 8px; }
.actions button[type="submit"], .actions [data-next] { margin-left: auto; }
.actions button[type="submit"] + [data-next] { margin-left: 0; }
.form-foot { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 16px; }
.form-foot button, .form-foot .button { margin: 0; }
.form-foot p.error, .form-foot p.ok { margin: 0; }
/* Alleen meldingen (<p>): de klassen ok/bad/error komen ook voor op stippen en labels. */
p.error { color: var(--rood); font-size: 14px; margin: 8px 0 0; white-space: pre-wrap; }
p.error:empty, p.ok:empty { display: none; }
p.ok { color: var(--groen-ink); font-size: 14px; margin: 8px 0 0; }
fieldset { border: 0; padding: 0; margin: 0 0 8px; }
legend { font-weight: 650; padding: 0; margin: 0 0 4px; }

/* --- tekst en labels ---------------------------------------------------------------------- */
.code {
  font-family: var(--mono); font-size: 24px; letter-spacing: 0.08em; text-align: center;
  padding: 12px; background: var(--accent-bg); border-radius: 8px; margin: 8px 0; word-break: break-all;
}
.mono { font-family: var(--mono); font-size: 13px; word-break: break-all; }
.muted { color: var(--muted); }
.nowrap { white-space: nowrap; word-break: normal; }
.small-text { font-size: 13px; }
.badge {
  display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: 12px; font-weight: 600;
  background: var(--surface-alt); color: var(--muted); white-space: nowrap; line-height: 1.6;
}
.badge + .badge { margin-left: 4px; }
.badge.ok { background: var(--groen-bg); color: var(--groen-ink); }
.badge.warn { background: var(--zon-bg); color: var(--zon-ink); }
.badge.bad { background: var(--rood-bg); color: var(--rood); }
.badge.info { background: var(--accent-bg); color: var(--accent); }
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; background: var(--muted); vertical-align: 1px; }
.dot.info { background: var(--accent); } .dot.ok { background: var(--groen); } .dot.warn { background: var(--zon); } .dot.bad { background: var(--rood); }
.swatch { display: inline-block; width: 12px; height: 12px; border-radius: 3px; vertical-align: -1px; margin-right: 8px; border: 1px solid var(--border-strong); }
dl.kv { display: grid; align-items: baseline; grid-template-columns: minmax(120px, max-content) 1fr; gap: 6px 20px; margin: 0; font-size: 14px; }
dl.kv dt { color: var(--muted); }
dl.kv dd { margin: 0; word-break: break-word; }
.status-line { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin: 0 0 16px; }
.chip {
  display: inline-flex; align-items: center; padding: 4px 12px; border-radius: 999px; font-size: 13px;
  font-weight: 550; background: var(--surface); color: var(--text); margin: 0;
  box-shadow: inset 0 0 0 1px var(--border-strong);
}
.chip:hover { background: var(--surface-alt); filter: none; }
.chip.active { background: var(--text); color: var(--bg); box-shadow: none; }
.chip.active .dot { box-shadow: 0 0 0 2px var(--bg); }

/* --- tabellen ----------------------------------------------------------------------------- */
.table-wrap { overflow-x: auto; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: 16px; }
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th { text-align: left; color: var(--muted); font-weight: 550; font-size: 13px; background: var(--surface); }
th, td { padding: 10px 14px; border-bottom: 1px solid var(--border); vertical-align: middle; }
tbody tr:last-child td { border-bottom: 0; }
td .sub { color: var(--muted); font-size: 13px; }
td.num, th.num { text-align: right; }
td.actions-cell { text-align: right; white-space: nowrap; }
tr.clickable { cursor: pointer; }
tr.clickable:hover td { background: var(--surface-alt); }
td.empty { color: var(--muted); text-align: center; padding: 24px; }

/* --- setup-portal (hub) ------------------------------------------------------------------- */
.steps { display: flex; gap: 6px; justify-content: center; flex-wrap: wrap; margin: 16px 0; padding: 0; list-style: none; }
.steps li { font-size: 13px; color: var(--muted); padding: 4px 10px; border-radius: 999px; background: var(--surface-alt); }
.steps li.active { background: var(--button); color: #fff; }
.steps li.done { background: var(--groen-bg); color: var(--groen-ink); }
.module-fields[hidden] { display: none; }

/* --- webinterfaces van de modules ------------------------------------------------------- */
.topbar .module-name { font-weight: 650; padding-left: 10px; border-left: 1px solid var(--border-strong); }
.card.live .label, .tiles .label { color: var(--muted); font-size: 13px; }
.big-value { font-size: 40px; font-weight: 650; letter-spacing: -0.02em; line-height: 1.15; margin: 2px 0 12px; }
.big-value.active { color: var(--groen-ink); }
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(90px, 1fr)); gap: 12px; margin: 0 0 16px;
  padding: 12px 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.tiles .value { font-size: 18px; font-weight: 600; }
.tiles:empty { display: none; }
.sub-card { border: 1px solid var(--border); border-radius: 8px; padding: 12px 16px; margin: 0 0 12px; }
.checks { display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 8px; }
.checks label.check { margin: 0; font-weight: 400; }
.page-head .tools label.check { margin: 0; font-weight: 500; }
.section-hint { margin: 0 0 16px; }
button.link.danger-link { color: var(--rood); margin-left: auto; }
pre.result { background: var(--surface-alt); border-radius: 8px; padding: 12px; white-space: pre-wrap; margin: 12px 0 0; }
.result { margin-top: 12px; }
.log { font-family: var(--mono); font-size: 12.5px; max-height: 72vh; overflow: auto; padding: 8px 12px; }
.log .line { display: grid; grid-template-columns: 76px 150px 1fr; gap: 8px; padding: 2px 0; border-bottom: 1px solid var(--border); }
.log .line:last-child { border-bottom: 0; }
.log .time, .log .peer { color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.log .text { word-break: break-all; }
.log .line.err .text, .log .line.err .peer { color: var(--rood); }
.log .line.info .text { color: var(--muted); }
.toast {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); margin: 0; z-index: 10;
  background: var(--text); color: var(--bg); padding: 10px 16px; border-radius: 8px; font-size: 14px;
  box-shadow: 0 4px 16px rgba(11, 31, 51, 0.2);
}

/* --- sticker van de hub (portal, /sticker): label van 70 × 54 mm ------------------------
   Boven: QR-code (34 mm) met daarnaast merk, hub-ID, setupcode en koppelcode.
   Onder over de volle breedte: vingerafdruk en een korte uitleg. */
.sticker-head { margin: 24px 0; }
.sticker {
  width: 70mm; height: 54mm; box-sizing: border-box; padding: 3mm;
  display: grid; grid-template-columns: 34mm 1fr; grid-template-rows: 34mm 1fr; gap: 2mm 2.5mm;
  background: #fff; color: #000; border: 1px dashed var(--border-strong); border-radius: 2mm; overflow: hidden;
}
.sticker-qr { width: 34mm; height: 34mm; }
.sticker-qr svg { width: 100%; height: 100%; display: block; }
.sticker-text { min-width: 0; line-height: 1.15; align-self: center; }
.sticker-brand { font-weight: 700; font-size: 8pt; margin-bottom: 1.5mm; overflow-wrap: anywhere; }
.sticker dl { margin: 0; }
.sticker dt { color: #555; font-size: 6pt; text-transform: uppercase; letter-spacing: 0.04em; }
.sticker dd { margin: 0 0 1.2mm; font-family: var(--mono); font-weight: 700; font-size: 8.5pt; white-space: nowrap; }
.sticker-foot { grid-column: 1 / -1; align-self: end; border-top: 0.2mm solid #000; padding-top: 1.2mm; line-height: 1.2; }
.sticker-foot dd { font-size: 8pt; margin: 0; }
.sticker-foot p { margin: 0.8mm 0 0; font-size: 6pt; color: #333; }
@media print {
  @page { size: 70mm 54mm; margin: 0; }
  body.sticker-page { background: #fff; padding: 0; }
  body.sticker-page .wrap { padding: 0; max-width: none; }
  .no-print { display: none !important; }
  .sticker { border: 0; border-radius: 0; }
}

@media (max-width: 640px) {
  .log .line { grid-template-columns: 1fr; gap: 0; }
  .wrap.wide { padding: 16px; }
  .topbar-inner { padding: 8px 16px; gap: 8px 16px; }
  .topbar nav { order: 3; width: 100%; overflow-x: auto; flex-wrap: nowrap; }
  th, td { padding: 8px 10px; }
  .hide-sm { display: none; }
}
/* Meekijken als tenant: altijd zichtbaar bovenaan, in de vaste platformkleur (niet die van de tenant). */
.acting-bar { background: var(--zon); color: #0B1F33; font-size: 14px; font-weight: 550; }
.acting-inner { max-width: 1200px; margin: 0 auto; padding: 8px 24px; display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.acting-inner span { flex: 1; min-width: 240px; }
.acting-bar button { background: #0B1F33; color: #fff; margin: 0; }
