/* SiteWatch · donkere NOC-stijl, overgenomen uit het ontwerp (Industry design system).

   De kleuren, de letters en de schaal staan NIET hier maar in basis.css, samen met
   het beheer. Dit bestand gaat over de onderdelen van het dashboard; wat voorkant en
   beheer delen hoort maar op één plek te staan, anders lopen ze op een dag uit elkaar.
   basis.css wordt vóór dit bestand geladen (zie layout.php). */

*, *::before, *::after { box-sizing: border-box; }

html {
  margin: 0;
  padding: 0;
  background: var(--ground);
  color: var(--ink);
  /* GEEN `overscroll-behavior-y: none` hier. Dat stond er vanaf de eerste opzet en het zette op
     een telefoon de trek-om-te-verversen van de browser uit. Juist op deze site is dat de knop
     die je nodig hebt: staat het tabblad een nacht open en heeft Android hem bevroren, dan zie je
     de meldingen van vannacht en is trekken de enige manier om erachter te komen dat er allang
     nieuwe zijn. Dat overkwam ons ook echt. De stuiter die je ervoor terugkrijgt is een veel
     kleinere prijs. */
}

body {
  margin: 0;
  padding: 0;
  color: var(--ink);
  /* GEEN achtergrond hier. Die van html schildert het doek al, en een
     ondoorzichtige achtergrond op body dekt alles af wat met z-index -1
     erachter ligt (de stuiterballen). Dat kostte een ronde: de ballen liepen
     wel, maar je zag ze niet. */
  background: transparent;
}

body {
  font-family: var(--font-body);
  font-size: calc(13px * var(--sw-zoom));
  line-height: 1.35;
  -webkit-text-size-adjust: 100%;
}

a { color: var(--acc); text-decoration: none; }
a:hover { text-decoration: underline; }
:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }

/* Rijlinks behouden de tekstkleur; toetsenbordfocus blijft de rand hierboven gebruiken. */
a.sw-112tekst, a.sw-112tekst:hover,
.sw-row a[href^="/domein/"], .sw-row a[href^="/domein/"]:hover {
  color: inherit;
  text-decoration: none;
}

::-webkit-scrollbar { width: calc(10px * var(--sw-zoom)); height: calc(10px * var(--sw-zoom)); }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--ink) 28%, transparent); }

@keyframes sw-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

/* ── Raamwerk ─────────────────────────────────────────────────────────────── */

.sw-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6) var(--space-4);
}

.sw-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-6);
  border-bottom: 1px solid var(--line);
  padding-bottom: var(--space-3);
  flex-wrap: wrap;
}

.sw-brand { display: flex; align-items: center; gap: var(--space-3); }
.sw-brand-naam { display: flex; flex-direction: column; gap: 3px; }

/* Het beeldmerk staat als achtergrond en niet als <img>, zodat het per thema kan wisselen zonder
   dat er een tweede plaatje in de pagina staat. Het logo is getekend voor wit papier; voor het
   donkere scherm is er een variant waarin alleen de grijstinten zijn omgekeerd en het groen
   hetzelfde is gebleven. */
.sw-merk {
  flex: 0 0 auto;
  width: calc(46px * var(--sw-zoom));
  height: calc(46px * var(--sw-zoom));
  background: url('/assets/merk-licht.png') center / contain no-repeat;
}
html[data-sw-theme="dag"] .sw-merk { background-image: url('/assets/merk-donker.png'); }

.sw-brand b {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: calc(27px * var(--sw-zoom));
  line-height: 1;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.sw-brand [data-sw="subtitle"] {
  font-size: calc(9.5px * var(--sw-zoom));
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--t4);
}

.sw-head-left { display: flex; align-items: flex-end; gap: var(--space-6); flex-wrap: wrap; }
.sw-head-right { display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap; }

.sw-tabs { display: flex; flex-wrap: wrap; gap: var(--space-2); }
/* In de kop staat de volledige naam; de korte versie is voor de onderbalk op een telefoon. */
.sw-tab-kort { display: none; }
/* De knop Meer hoort bij de onderbalk op een telefoon; op een breed scherm staat alles gewoon in
   de kop en zou hij een tweede menu zijn. */
.sw-tabs .sw-tab--meer { display: none; }
/* Alle knoppen in de kop houden dezelfde hoogte, anders staat de rij te dansen.
   Achtendertig in plaats van vierenveertig: nog ruim genoeg om aan te tikken, en het
   scheelt genoeg hoogte om de hele kop op een regel te houden. */
.sw-tab {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: calc(11px * var(--sw-zoom));
  letter-spacing: .08em;
  text-transform: uppercase;
  padding: 0 calc(var(--space-3) * .8);
  min-height: calc(34px * var(--sw-zoom));
  display: flex;
  align-items: center;
  border: 1px solid var(--t5);
  background: transparent;
  color: var(--t2);
  cursor: pointer;
}
.sw-tab:hover { background: color-mix(in srgb, var(--ink) 9%, transparent); }
/* Openprovider en Spam zijn links naar een eigen pagina; een link onderstreept bij hover, een tabblad niet. */
.sw-head a.sw-tab:hover { text-decoration: none; }
.sw-head a.sw-tab[aria-current="page"] { background: var(--t5); color: var(--ground); }
/* Alleen in het blad op een telefoon (zie de 760px-regels). Met .sw-head ervoor, anders wint de
   latere .sw-linkbtn-regel (zelfde gewicht) en staan Openprovider en Spam op een breed scherm dubbel. */
.sw-head .sw-alleen-mobiel { display: none; }
/* Op een smal scherm brak "← Dashboard" over twee regels; de knoppen in de kop blijven één regel. */
.sw-head .sw-linkbtn, .sw-head .sw-themebtn { white-space: nowrap; }
.sw-tab[aria-selected="true"] { background: var(--t5); color: var(--ground); }

.sw-live { display: flex; align-items: center; gap: var(--space-2); }
.sw-head .sw-live { align-items: flex-start; }
.sw-head .sw-live i { margin-top: calc(5px * var(--sw-zoom)); }
.sw-live i {
  /* GEEN background hier: de kleur komt van de bg-*-klasse die het script
     zet. Een achtergrond op deze regel is specifieker (0,1,1) dan .bg-crit
     (0,1,0) en zou de stip groen houden terwijl de checker stilstaat. */
  width: calc(8px * var(--sw-zoom)); height: calc(8px * var(--sw-zoom)); display: block;
  animation: sw-pulse 2.2s ease-in-out infinite;
}
.sw-live span {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: calc(13px * var(--sw-zoom));
  letter-spacing: .14em;
  text-transform: uppercase;
}

/* De tijden waarop gemeten wordt staan in dezelfde kolom als "live" en "3 s geleden": het is
   dezelfde mededeling. Ze zitten daarom in .sw-livetekst zelf, zodat ze vanzelf op dezelfde
   lijn beginnen en er geen marge staat die bij een andere schaal weer scheef loopt. */
.sw-intervals { font-size: calc(10.5px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase; color: var(--t4); }

/* ── de hartslag als klokje ─────────────────────────────────────────────────── */
.sw-hartslag { position: relative; }
.sw-hbknop {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: 4px 6px; margin: -4px -6px;
  background: transparent; border: 0; color: inherit; cursor: pointer; border-radius: 999px;
  transition: background .18s ease;
}
.sw-hbknop:hover, .sw-hbknop[aria-expanded="true"] { background: color-mix(in srgb, var(--ink) 9%, transparent); }
.sw-hbknop:focus-visible { outline: 2px solid var(--info); outline-offset: 2px; }
.sw-head .sw-hartslag .sw-hbknop i { margin-top: 0; }
.sw-hbklok {
  width: calc(30px * var(--sw-zoom)); height: calc(30px * var(--sw-zoom));
  display: block; overflow: visible;
  transition: transform .5s cubic-bezier(.34, 1.56, .64, 1);
}
.sw-hbknop:hover .sw-hbklok { transform: scale(1.1); }

/* De zandloper. Het glas draait als geheel (transform-attribuut rotate(hoek 16 16) uit
   sitewatch.js, met deze overgang); het zand zijn twee driehoeken die met een CSS-animatie
   krimpen en groeien. De animatie duurt vijf seconden: even lang als één ronde van het scherm
   (POLL_MS). Verander je de één, verander dan de ander.
   GEEN transform-origin op de groep zelf: het middelpunt zit al in de draaiing. */
/* Het glas draait om zijn eigen midden: transform-box maakt het midden van de groep het draaipunt,
   de draaiing zelf doet sitewatch.js met de Web Animations API (geen inline stijl). */
.sw-zg { transform-box: fill-box; transform-origin: center; }
.sw-zg-glas { fill: color-mix(in srgb, var(--ink) 5%, transparent); stroke: currentColor; stroke-width: 1.2; stroke-linejoin: round; opacity: .9; }
.sw-zg-kap { stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; }
.sw-zg-boven, .sw-zg-onder { fill: var(--info); transform-box: fill-box; }
.sw-zg-boven { transform-origin: 50% 100%; }
.sw-zg-onder { transform-origin: 50% 100%; transform: scale(0); }
.sw-zg-straal { stroke: var(--info); stroke-width: 1; stroke-linecap: round; stroke-dasharray: 1.2 1.7; opacity: 0; }
.sw-zg.is-loop .sw-zg-boven { animation: sw-zg-leeg 5s linear forwards; }
.sw-zg.is-loop .sw-zg-onder { animation: sw-zg-vol 5s linear forwards; }
.sw-zg.is-loop .sw-zg-straal--neer { animation: sw-zg-straal 5s linear forwards; }
/* Na een oneven aantal halve slagen staat het glas op zijn kop: dan wisselen de rollen en de
   draaipunten, en valt het zand langs de andere straal. */
.sw-zg.is-om .sw-zg-boven { transform-origin: 50% 0%; transform: scale(0); }
.sw-zg.is-om .sw-zg-onder { transform-origin: 50% 0%; transform: scale(1); }
.sw-zg.is-om.is-loop .sw-zg-boven { animation-name: sw-zg-vol; }
.sw-zg.is-om.is-loop .sw-zg-onder { animation-name: sw-zg-leeg; }
.sw-zg.is-om.is-loop .sw-zg-straal--neer { animation: none; }
.sw-zg.is-om.is-loop .sw-zg-straal--op { animation: sw-zg-straal 5s linear forwards; }
/* Geen verse cijfers: het zand staat stil. */
.sw-zg.is-stil .sw-zg-boven, .sw-zg.is-stil .sw-zg-onder, .sw-zg.is-stil .sw-zg-straal { animation-play-state: paused; }
@keyframes sw-zg-leeg { from { transform: scale(1); } to { transform: scale(0); } }
@keyframes sw-zg-vol { from { transform: scale(0); } to { transform: scale(1); } }
@keyframes sw-zg-straal {
  0% { opacity: .9; stroke-dashoffset: 0; }
  94% { opacity: .9; stroke-dashoffset: -29; }
  100% { opacity: 0; stroke-dashoffset: -29; }
}
@media (prefers-reduced-motion: reduce) {
  .sw-hbklok { transition: none; }
  .sw-hbknop:hover .sw-hbklok { transform: none; }
  .sw-zg .sw-zg-boven, .sw-zg .sw-zg-onder, .sw-zg .sw-zg-straal { animation: none; }
}

.sw-hbpop {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 40;
  min-width: 230px;
  padding: var(--space-3) var(--space-4);
  background: var(--ground); border: 1px solid var(--line);
  box-shadow: 0 12px 32px rgb(0 0 0 / 35%);
  display: flex; flex-direction: column; gap: var(--space-2);
  transform-origin: top right;
  animation: sw-hbin .32s cubic-bezier(.2, 1.4, .4, 1) both;
}
.sw-hbpop[hidden] { display: none; }
.sw-hbpop::before {
  content: ""; position: absolute; top: -6px; right: 14px; width: 10px; height: 10px;
  background: var(--ground); border-left: 1px solid var(--line); border-top: 1px solid var(--line);
  transform: rotate(45deg);
}
@keyframes sw-hbin {
  from { opacity: 0; transform: translateY(-6px) scale(.92); }
  to { opacity: 1; transform: none; }
}
.sw-hbpop .sw-livetekst { display: flex; align-items: baseline; gap: var(--space-2); }
.sw-hbpop .sw-livetekst b { font-family: var(--font-heading); font-weight: 600; font-size: calc(13px * var(--sw-zoom)); letter-spacing: .14em; text-transform: uppercase; }
.sw-hbpop .sw-livetekst em { font-style: normal; font-size: calc(11px * var(--sw-zoom)); color: var(--t3); font-variant-numeric: tabular-nums; }
.sw-hbrijen { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 3px var(--space-3); }
.sw-hbrijen div { display: contents; }
.sw-hbrijen dt { font-size: calc(10.5px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase; color: var(--t4); }
.sw-hbrijen dd { margin: 0; font-size: calc(12px * var(--sw-zoom)); color: var(--t2); font-variant-numeric: tabular-nums; }
/* display: block staat er met opzet: de mobiele regel `.sw-live span { display: none }` zou
   anders de tekstregels in het kaartje meenemen. */
.sw-hbpop .sw-hbvoet { display: block; font-size: calc(10.5px * var(--sw-zoom)); color: var(--t4); line-height: 1.5; border-top: 1px solid color-mix(in srgb, var(--ink) 12%, transparent); padding-top: var(--space-2); }
.sw-hbpop .sw-livetekst em { display: inline; }
/* Op een telefoon hangt het kaartje onder de kop, over de volle breedte, net als het
   uitklapblad: onderin staat de tabbalk en die hoort niets te bedekken. De kophoogte komt uit
   dezelfde --sw-kop die het blad al zet. */
@media (max-width: 760px) {
  .sw-hbpop {
    position: fixed; top: calc(var(--sw-kop, 60px) + 10px); bottom: auto; left: 12px; right: 12px;
    min-width: 0; transform-origin: top center;
  }
  .sw-hbpop::before { display: none; }
}

.sw-clock { text-align: right; }
.sw-clock b {
  display: block;
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: calc(24px * var(--sw-zoom));
  line-height: 1;
  letter-spacing: .04em;
  font-variant-numeric: tabular-nums;
}
.sw-clock span { font-size: calc(10px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase; color: var(--t4); }

.sw-themeswitch { display: flex; }
.sw-themeswitch button {
  display: flex; align-items: center; gap: 6px;
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(11.5px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase;
  padding: 0 calc(var(--space-3) * .8); min-height: calc(34px * var(--sw-zoom));
  border: 1px solid var(--t5); background: transparent; color: var(--t3);
  cursor: pointer;
}
.sw-themeswitch button:hover { background: color-mix(in srgb, var(--ink) 10%, transparent); }
.sw-themeswitch button[aria-pressed="true"] { background: var(--t5); color: var(--ground); }
.sw-themeswitch svg { width: calc(14px * var(--sw-zoom)); height: calc(14px * var(--sw-zoom)); }

.sw-linkbtn {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(10.5px * var(--sw-zoom)); letter-spacing: .08em; text-transform: uppercase;
  padding: 0 calc(var(--space-3) * .8); min-height: calc(34px * var(--sw-zoom));
  border: 1px solid var(--t5); color: var(--t2); background: transparent;
  cursor: pointer;
}
.sw-linkbtn:hover { background: color-mix(in srgb, var(--ink) 9%, transparent); text-decoration: none; color: var(--ink); }

/* ── Kaart met hoekmarkeringen ────────────────────────────────────────────── */

.sw-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4) var(--space-4);
  border: 1px solid var(--line);
  background: transparent;
}
.sw-card > .corner {
  position: absolute; width: calc(11px * var(--sw-zoom)); height: calc(11px * var(--sw-zoom));
  color: color-mix(in srgb, var(--ink) 55%, transparent);
  pointer-events: none;
}
.sw-card > .corner::before,
.sw-card > .corner::after { content: ""; position: absolute; background: currentColor; }
.sw-card > .corner::before { left: 5px; top: 0; width: calc(1px * var(--sw-zoom)); height: 100%; }
.sw-card > .corner::after { top: 5px; left: 0; width: 100%; height: calc(1px * var(--sw-zoom)); }
.sw-card > .corner.tl { top: -6px; left: -6px; }
.sw-card > .corner.tr { top: -6px; right: -6px; }
.sw-card > .corner.bl { bottom: -6px; left: -6px; }
.sw-card > .corner.br { bottom: -6px; right: -6px; }

.sw-card-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3);
}
.sw-card-head h2 {
  margin: 0;
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(16px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase;
}
.sw-card-head .meta {
  font-size: calc(10.5px * var(--sw-zoom)); letter-spacing: .1em; text-transform: uppercase; color: var(--t4);
  text-align: right;
}

/* ── Bovenste balk: oordeel, tellingen en kengetallen ─────────────────────
   Eén balk in plaats van twee. Op een breed scherm staat alles naast elkaar;
   wordt het krap, dan zakken de kengetallen naar een tweede regel binnen
   dezelfde balk, zodat het er nog steeds als één blok uitziet. */

.sw-topbar {
  display: grid;
  /* De oordeelzin krimpt (en breekt) als het krap wordt; de tellers houden altijd hun eigen breedte.
     Met `auto` als eerste kolom nam een lange zin alle ruimte en schoven de tellers rechts uit beeld. */
  grid-template-columns: minmax(0, max-content) auto minmax(0, 1fr);
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-2) var(--space-4);
}

/* DE RUIMTE VOOR DE OORDEELBALK, ZOLANG HIJ LEEG IS.
 *
 * Deze balk staat leeg in de HTML en wordt door sitewatch.js getekend uit de payload. Dat is met
 * opzet zo: één renderer, zodat het scherm nooit iets anders kan zeggen dan de API. De prijs was
 * een sprong: de browser tekende de pagina zonder balk, en zodra het script hem vulde schoof alles
 * eronder omlaag. Gemeten op de voorpagina, vier rondes achter elkaar dezelfde uitkomst: een layout
 * shift van 0,65 waar 0,1 de grens is.
 *
 * De hoogte van de balk is per breedte vast -- zes tellers en vijf kengetallen, die vouwen op
 * dezelfde punten als de regels hieronder. Deze vier waarden zijn gemeten, niet geschat.
 *
 * `:empty` is de kern van de truc: zodra het script de balk vult telt deze regel niet meer mee, en
 * bepaalt de inhoud zelf de hoogte. Zit er ooit een teller bij en klopt het gereserveerde getal
 * niet meer, dan kost dat een klein sprongetje en nooit een gat. */
.sw-topbar:empty { min-height: 75px; }

/* En de ruimte voor de domeinrijen, op dezelfde manier en om dezelfde reden.
 *
 * Hier kan geen vast getal staan: de lijst is negen domeinen lang voor een voorbijganger en
 * honderdzesenzeventig voor een beheerder. Het aantal komt daarom van de server mee als
 * `--sw-rijen` (zie dashboard.php); de hoogte van één rij hoort bij de opmaak en staat hier. Zo
 * klopt de reservering vanzelf als er een domein bij komt.
 *
 * De getallen zijn gemeten op de echte pagina: 50 px per rij op een breed scherm, 45 onder de
 * 1180, en op een telefoon vouwt een rij over meerdere regels. Ze zijn bewust iets aan de lage
 * kant: te weinig reserveren kost een klein sprongetje, te veel laat een gat vallen. */
[data-sw="sites"]:empty { min-height: calc(var(--sw-rijen, 0) * var(--sw-rijhoogte, 48px)); }
@media (max-width: 1180px) { [data-sw="sites"]:empty { --sw-rijhoogte: 45px; } }
@media (max-width: 760px) { [data-sw="sites"]:empty { --sw-rijhoogte: 105px; } }
@media (max-width: 500px) { [data-sw="sites"]:empty { --sw-rijhoogte: 114px; } }
@media (max-width: 440px) { [data-sw="sites"]:empty { --sw-rijhoogte: 132px; } }
@media (max-width: 1600px) { .sw-topbar:empty { min-height: 133px; } }
@media (max-width: 1180px) { .sw-topbar:empty { min-height: 204px; } }
@media (max-width: 760px) { .sw-topbar:empty { min-height: 196px; } }

.sw-topbar.tone-ok { border-color: color-mix(in srgb, var(--ok) 60%, transparent); background: color-mix(in srgb, var(--ok) 10%, transparent); }
.sw-topbar.tone-warn { border-color: color-mix(in srgb, var(--warn) 70%, transparent); background: color-mix(in srgb, var(--warn) 11%, transparent); }
.sw-topbar.tone-crit { border-color: var(--crit); background: color-mix(in srgb, var(--crit) 16%, transparent); }
.sw-topbar.tone-dim { border-color: var(--line); }

.sw-verdict-main { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.sw-verdict-main svg { width: calc(30px * var(--sw-zoom)); height: calc(30px * var(--sw-zoom)); flex: none; }
.sw-verdict-main b {
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(24px * var(--sw-zoom)); line-height: 1;
  letter-spacing: .06em; text-transform: uppercase;
  /* Een korte zin blijft op één regel; een lange (zoals "al 23 minuten geen geslaagde ophaalronde")
     breekt af in plaats van de tellers rechts uit de balk te duwen. */
  white-space: normal; text-wrap: balance;
}

.sw-counts { display: flex; gap: var(--space-4); align-items: center; }
.sw-counts div { text-align: center; min-width: calc(56px * var(--sw-zoom)); }
.sw-counts b {
  display: block;
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(22px * var(--sw-zoom)); line-height: 1; font-variant-numeric: tabular-nums;
}
.sw-counts span {
  display: block;
  font-size: calc(9px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase;
  color: var(--t4); margin-top: 3px;
}

.sw-topbar .sw-kpis {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--space-4);
  border-left: 1px solid color-mix(in srgb, var(--ink) 16%, transparent);
  padding-left: var(--space-6);
}
.sw-topbar .sw-kpi { padding: 0; gap: 0; border: 0; background: transparent; }
.sw-topbar .sw-kpi .value { font-size: calc(22px * var(--sw-zoom)); }

@media (max-width: 1600px) {
  /* Onder de domeinnaam alleen nog wat er echt toe doet. Interval en drempel
     lieten de regel over twee regels breken en maakten elke rij een slag
     hoger; ze staan toch al op het detailscherm. */
  .sw-domain .sw-sub-detail { display: none; }
  .sw-domain .sw-sub > span:first-child::before { content: none; }

  /* Te krap voor één regel: de kengetallen zakken naar een tweede regel,
     maar blijven binnen dezelfde balk staan. */
  .sw-topbar { grid-template-columns: minmax(0, max-content) minmax(min-content, 1fr); row-gap: var(--space-3); }
  .sw-topbar .sw-kpis {
    grid-column: 1 / -1;
    border-left: 0; padding-left: 0;
    border-top: 1px solid color-mix(in srgb, var(--ink) 14%, transparent);
    padding-top: var(--space-3);
  }
}

/* Fixi heeft drie rijen kengetallen en een toelichting; die passen ook op een breed scherm nooit naast de
   oordeelzin. Daar staan ze dus op elke breedte op een eigen regel, zoals onder 1600 px bij elk paneel. */
@media (min-width: 1601px) {
  .sw-topbar[data-sw-fixikop] { grid-template-columns: minmax(0, max-content) minmax(min-content, 1fr); row-gap: var(--space-3); }
  .sw-topbar[data-sw-fixikop] .sw-kpis {
    grid-column: 1 / -1;
    border-left: 0; padding-left: 0;
    border-top: 1px solid color-mix(in srgb, var(--ink) 14%, transparent);
    padding-top: var(--space-3);
  }
}

/* De vier weergaven (overzicht, uptime, bezoekers, detail) stapelen hun
   blokken met dezelfde tussenruimte als de rest van het scherm. */
[data-sw-panel] { display: flex; flex-direction: column; gap: var(--space-3); }
[data-sw-panel].sw-hidden { display: none; }

/* ── Stale-banner ─────────────────────────────────────────────────────────── */

.sw-stale {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 2px solid var(--crit);
  background: color-mix(in srgb, var(--crit) 20%, transparent);
}
.sw-stale svg { width: calc(28px * var(--sw-zoom)); height: calc(28px * var(--sw-zoom)); flex: none; color: var(--crit); }
.sw-stale b {
  display: block;
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(20px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase; color: var(--crit);
}
.sw-stale span { display: block; font-size: calc(12px * var(--sw-zoom)); color: var(--t2); margin-top: 3px; }

/* ── Meldingen, in de kolom naast de domeinentabel ────────────────────────
   Ze stonden eerst als brede balken boven de tabel. Bij vijf meldingen duwde
   dat de domeinen onder de vouw, en juist die lijst is waar je naar kijkt. */

.sw-main {
  display: grid;
  grid-template-columns: minmax(0, 1fr) calc(320px * var(--sw-zoom));
  gap: var(--space-3);
  align-items: start;
}
.sw-main.geen-meldingen { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 1181px) and (max-width: 1500px) {
  .sw-main { grid-template-columns: minmax(0, 1fr); }
}
.sw-mainleft { display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }

.sw-alertpanel {
  /* Geen maximumhoogte en geen scrollbalk: die stond lelijk dwars door het
     scherm. De kolom groeit gewoon mee met wat er open staat, en verbergt
     dus ook nooit een melding. */
  align-self: start;
}

/* Dezelfde banner, maar dan als mededeling in plaats van alarm. */
.sw-stale.sw-stale-mild {
  border-color: color-mix(in srgb, var(--warn) 70%, transparent);
  background: color-mix(in srgb, var(--warn) 10%, transparent);
}
.sw-stale.sw-stale-mild b { color: var(--warn); }
.sw-staleknop { margin-left: auto; align-self: center; }
.sw-staleknop button {
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(11px * var(--sw-zoom)); letter-spacing: .08em; text-transform: uppercase;
  padding: 0 var(--space-3); min-height: calc(34px * var(--sw-zoom));
  border: 1px solid var(--warn); background: transparent; color: var(--warn);
  cursor: pointer; white-space: nowrap;
}
.sw-staleknop button:hover { background: color-mix(in srgb, var(--warn) 16%, transparent); }

.sw-alerts { display: flex; flex-direction: column; gap: var(--space-2); }

.sw-alert {
  display: flex; flex-direction: column; gap: 3px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--line);
  background: transparent;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  width: 100%;
}
.sw-alert:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.sw-alert.tone-crit { border-color: var(--crit); background: color-mix(in srgb, var(--crit) 14%, transparent); }
.sw-alert.tone-warn { border-color: color-mix(in srgb, var(--warn) 70%, transparent); background: color-mix(in srgb, var(--warn) 10%, transparent); }

.sw-alert .kop { display: flex; align-items: center; gap: 6px; }
.sw-alert .kop svg { flex: none; }
.sw-alert .kop b {
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(15px * var(--sw-zoom)); letter-spacing: .03em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sw-alert .meting {
  margin-left: auto; flex: none;
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(13px * var(--sw-zoom)); font-variant-numeric: tabular-nums;
}
.sw-alert .wat { font-size: calc(11.5px * var(--sw-zoom)); color: var(--t2); }
.sw-alert .voet {
  display: flex; gap: var(--space-2); align-items: baseline;
  font-size: calc(9.5px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase;
}
.sw-alert .voet .tag { font-family: var(--font-heading); font-weight: 600; }
.sw-alert .voet .sinds { color: var(--t4); font-variant-numeric: tabular-nums; }
.sw-alert .advies {
  font-size: calc(11px * var(--sw-zoom)); color: var(--t3);
  border-top: 1px solid color-mix(in srgb, var(--ink) 10%, transparent);
  padding-top: 3px; margin-top: 2px;
}
.sw-alert .advies .deur {
  /* Een blokje op een eigen regel: naast de zin gaat hij midden in een woord afbreken. */
  display: block; width: max-content; max-width: 100%;
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(10px * var(--sw-zoom)); letter-spacing: .1em; text-transform: uppercase;
  padding: 2px 8px; margin-top: 4px;
  border: 1px solid currentColor; color: var(--t2);
  text-decoration: none; white-space: nowrap;
}
.sw-alert .advies .deur:hover,
.sw-alert .advies .deur:focus-visible { color: var(--ink); background: color-mix(in srgb, var(--ink) 10%, transparent); }

/* ── KPI-tegels ───────────────────────────────────────────────────────────── */

.sw-kpis { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--space-3); }
.sw-kpis.of4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.sw-kpi { padding: var(--space-2) var(--space-3); gap: 1px; }
.sw-kpi .label { font-size: calc(9.5px * var(--sw-zoom)); letter-spacing: .14em; text-transform: uppercase; color: var(--t4); }
.sw-kpi .row { display: flex; align-items: baseline; gap: 5px; }
.sw-kpi .value {
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(26px * var(--sw-zoom)); line-height: 1.02; font-variant-numeric: tabular-nums;
}
.sw-kpi .unit { font-size: calc(11px * var(--sw-zoom)); color: var(--t3); }
.sw-kpi .sub { font-size: calc(10.5px * var(--sw-zoom)); color: var(--t3); }

/* ── Domeinentabel ────────────────────────────────────────────────────────── */

.sw-table { display: flex; flex-direction: column; }
.sw-row {
  display: grid;
  /* Negen kolommen: domein, status, http, respons, uptime, bezoekers, nu
     online, laatste check en het pijltje. Dit getal moet gelijk lopen met wat
     renderSites() in de rij zet, anders breekt de rij doormidden. */
  grid-template-columns:
    minmax(calc(150px * var(--sw-zoom)), 1.25fr)
    calc(126px * var(--sw-zoom))
    calc(46px * var(--sw-zoom))
    calc(74px * var(--sw-zoom))
    minmax(calc(140px * var(--sw-zoom)), 1.4fr)
    calc(54px * var(--sw-zoom))
    calc(86px * var(--sw-zoom))
    calc(60px * var(--sw-zoom))
    calc(78px * var(--sw-zoom))
    calc(44px * var(--sw-zoom))
    calc(74px * var(--sw-zoom))
    calc(18px * var(--sw-zoom));
  gap: var(--space-3);
  align-items: center;
  padding: 6px var(--space-2) 6px var(--space-3);
  border-bottom: 1px solid var(--line-soft);
}
.sw-row.head {
  border-left: 3px solid transparent; /* Dezelfde statusrand als de inhoudsrijen. */
  border-bottom: 1px solid var(--line);
  padding-bottom: 6px;
  font-size: calc(9.5px * var(--sw-zoom)); letter-spacing: .14em; text-transform: uppercase; color: var(--t4);
}
.sw-row.head .first { font-family: var(--font-heading); font-weight: 600; font-size: calc(15px * var(--sw-zoom)); letter-spacing: .12em; }
.sw-row.item { cursor: pointer; background: transparent; text-align: left; border-left: 3px solid transparent; }
.sw-row.item:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); }
.sw-row.item.tone-crit { background: color-mix(in srgb, var(--crit) 12%, transparent); border-left-color: var(--crit); }
.sw-row.item.tone-warn { background: color-mix(in srgb, var(--warn) 10%, transparent); border-left-color: var(--warn); }
.sw-row .num { text-align: right; font-variant-numeric: tabular-nums; }

/* Het pijltje aan het eind van een rij. Een SVG zonder maat groeit uit tot
   de hele cel, dus die maat staat hier hard. */
.sw-row .sw-chevron { width: calc(14px * var(--sw-zoom)); height: calc(14px * var(--sw-zoom)); flex: none; justify-self: end; }

/* De samenvattingsregel is er alleen voor mobiel: daar vallen de losse
   kolommen weg. Op een breed scherm zou hij een achtste item in een
   zevenkoloms raster zijn en de rij dus doormidden breken. */
.sw-row.item .col-meta { display: none; }

.sw-domain b {
  display: block;
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(16px * var(--sw-zoom)); line-height: 1.05; letter-spacing: .03em;
}
.sw-domain .sw-sub, .sw-detail-title .sw-sub {
  display: block;
  font-size: calc(9.5px * var(--sw-zoom)); line-height: 1.2; letter-spacing: .08em; text-transform: uppercase; color: var(--t5);
}
.sw-sub > span + span::before { content: " " attr(data-sep) " "; }

/* De rijen zijn knoppen; die rekken in een flex-kolom niet vanzelf mee. */
.sw-row.item { width: 100%; font: inherit; color: inherit; }

.sw-status { display: flex; align-items: center; gap: 7px; min-width: 0; }
.sw-status svg { width: calc(15px * var(--sw-zoom)); height: calc(15px * var(--sw-zoom)); flex: none; }
.sw-status b {
  display: block;
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(12.5px * var(--sw-zoom)); letter-spacing: .1em; text-transform: uppercase;
}
.sw-status span {
  display: block;
  font-size: calc(10px * var(--sw-zoom)); color: var(--t4);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.sw-mono {
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(15px * var(--sw-zoom)); font-variant-numeric: tabular-nums;
}
.sw-unit { font-size: calc(10.5px * var(--sw-zoom)); color: var(--t4); }

.sw-uptime { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }

/* ── Grafieken ────────────────────────────────────────────────────────────── */

.sw-axis {
  display: flex; justify-content: space-between;
  font-size: calc(9.5px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase; color: var(--t5);
}

/* ── Checklog ─────────────────────────────────────────────────────────────── */

.sw-log { display: flex; flex-direction: column; }
.sw-logline {
  display: grid;
  grid-template-columns: calc(78px * var(--sw-zoom)) calc(62px * var(--sw-zoom)) calc(220px * var(--sw-zoom)) calc(60px * var(--sw-zoom)) calc(88px * var(--sw-zoom)) minmax(0, 1fr);
  gap: var(--space-3);
  align-items: baseline;
  padding: 3px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 6%, transparent);
  font-variant-numeric: tabular-nums;
  font-size: calc(12px * var(--sw-zoom));
}
.sw-logline .time { font-size: calc(11.5px * var(--sw-zoom)); color: var(--t4); }
.sw-logline .level {
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(12px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase;
}
.sw-logline .target { color: var(--t1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sw-logline .measure { text-align: right; }
.sw-logline .note { color: var(--t3); }
.sw-logline.warn, .sw-logline.fail { background: color-mix(in srgb, var(--warn) 8%, transparent); }

/* ── Storingenlijst ───────────────────────────────────────────────────────── */

.sw-incidents { display: flex; flex-direction: column; }
.sw-incident {
  display: grid;
  grid-template-columns: calc(132px * var(--sw-zoom)) calc(8px * var(--sw-zoom)) minmax(150px, 1fr) calc(96px * var(--sw-zoom)) minmax(0, 2fr) calc(96px * var(--sw-zoom));
  gap: var(--space-3);
  align-items: baseline;
  padding: 8px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 8%, transparent);
}
.sw-incident .when { font-size: calc(11.5px * var(--sw-zoom)); font-variant-numeric: tabular-nums; color: var(--t3); }
.sw-incident .dot { width: calc(7px * var(--sw-zoom)); height: calc(7px * var(--sw-zoom)); display: block; align-self: center; }
.sw-incident .domain { font-family: var(--font-heading); font-weight: 600; font-size: calc(15px * var(--sw-zoom)); letter-spacing: .03em; }
.sw-incident .dur { font-family: var(--font-heading); font-weight: 600; font-size: calc(14px * var(--sw-zoom)); font-variant-numeric: tabular-nums; }
.sw-incident .reason { font-size: calc(12px * var(--sw-zoom)); }
.sw-incident .state { font-size: calc(10.5px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase; text-align: right; color: var(--t4); }

/* ── Detailscherm ─────────────────────────────────────────────────────────── */

.sw-detail-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-6); flex-wrap: wrap; }
.sw-detail-title { display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap; }
.sw-detail-title svg.glyph { width: calc(26px * var(--sw-zoom)); height: calc(26px * var(--sw-zoom)); flex: none; }
.sw-detail-title b {
  display: block;
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(27px * var(--sw-zoom)); line-height: 1; letter-spacing: .05em;
}
.sw-detail-title span {
  display: block;
  font-size: calc(10.5px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase; color: var(--t4); margin-top: 3px;
}
.sw-detail-badge {
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(15px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase;
  padding: 6px var(--space-4); border: 1px solid currentColor;
}
.sw-detail-grid { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: var(--space-3); align-items: start; }
.sw-detail-col { display: flex; flex-direction: column; gap: var(--space-3); }

.sw-facts { display: flex; flex-direction: column; }
.sw-fact {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-3);
  align-items: baseline;
  padding: 9px 0; border-bottom: 1px solid color-mix(in srgb, var(--ink) 8%, transparent);
}
.sw-fact dt { font-size: calc(12px * var(--sw-zoom)); letter-spacing: .04em; text-transform: uppercase; color: var(--t3); }
.sw-fact dd {
  margin: 0; text-align: right;
  font-family: var(--font-heading); font-weight: 600; font-size: calc(14px * var(--sw-zoom)); letter-spacing: .03em;
}

/* ── Lege staat ───────────────────────────────────────────────────────────── */

.sw-empty { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-8) var(--space-4); text-align: center; }
.sw-empty b {
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(20px * var(--sw-zoom)); letter-spacing: .1em; text-transform: uppercase; color: var(--t3);
}
.sw-empty p { margin: 0 auto; max-width: 62ch; font-size: calc(12.5px * var(--sw-zoom)); color: var(--t4); }

/* ── Voet ─────────────────────────────────────────────────────────────────── */

.sw-foot {
  display: flex; justify-content: space-between; gap: var(--space-6);
  font-size: calc(10px * var(--sw-zoom)); letter-spacing: .14em; text-transform: uppercase; color: var(--t5);
  border-top: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
  padding-top: var(--space-2);
  flex-wrap: wrap;
}

/* ── Kleurrollen ──────────────────────────────────────────────────────────── */

.c-ok { color: var(--ok); }
.c-warn { color: var(--warn); }
.c-crit { color: var(--crit); }
.c-acc { color: var(--acc); }
/* Voor tekens die geen eigen kleur verdienen maar wel leesbaar moeten blijven. */
.c-t3 { color: var(--t3); }
.c-dim { color: var(--t5); }
.c-ink { color: var(--ink); }
.bg-ok { background: var(--ok); }
.bg-warn { background: var(--warn); }
.bg-crit { background: var(--crit); }
.bg-acc { background: var(--acc); }
.bg-dim { background: var(--t5); }
.bg-ink { background: var(--ink); }

.sw-hidden { display: none !important; }

/* De knop "Installeren" en de uitleg erachter. De uitleg hangt onder de knop
   en duwt niets opzij; op een smal scherm gaat hij over de volle breedte. */
.sw-install { position: relative; display: inline-flex; }
.sw-installtip {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 40;
  width: min(320px, calc(100vw - 32px));
  padding: var(--space-3) var(--space-4);
  background: var(--ground); border: 1px solid var(--line);
  box-shadow: 0 12px 32px rgb(0 0 0 / 35%);
  font-size: 12.5px; line-height: 1.6; color: var(--t2);
  display: flex; flex-direction: column; gap: 6px;
}
.sw-notify { display: flex; flex-direction: column; gap: 6px; }
.sw-notifystatus { font-size: 12px; color: var(--t4); line-height: 1.5; }

/* In de kop staat die uitleg in de weg: hij duwt de knoppenrij scheef en zegt iets
   wat je aan de knop zelf al ziet. In het blad op een telefoon en in het beheer
   blijft hij wél staan, want daar is ruimte en daar lees je hem ook echt. */
.sw-head .sw-notifystatus { display: none; }

.sw-installtip b { font-size: 13px; color: var(--t1); }
.sw-installtip p { margin: 0; }

/* Op een telefoon staat de knop links in beeld en zou de uitleg er links naast
   uit lopen. Daar wordt het een blokje onderin, altijd volledig zichtbaar. */
@media (max-width: 700px) {
  /* De regel met de intervallen staat op een telefoon in de weg: hij kost een
     hele regel kop terwijl exact dezelfde tekst boven het checklog staat. */
  .sw-head .sw-intervals { display: none; }

  .sw-installtip {
    position: fixed;
    top: auto; bottom: 12px; left: 12px; right: 12px;
    width: auto;
  }
}
.sw-visually-hidden {
  position: absolute; width: calc(1px * var(--sw-zoom)); height: calc(1px * var(--sw-zoom)); overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ── Tablet ───────────────────────────────────────────────────────────────── */

@media (max-width: 1180px) {
  .sw-main, .sw-main.geen-meldingen { grid-template-columns: minmax(0, 1fr); }
  .sw-topbar .sw-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .sw-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .sw-kpis.of4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sw-detail-grid { grid-template-columns: minmax(0, 1fr); }
  .sw-row { grid-template-columns: minmax(150px, 1.4fr) calc(140px * var(--sw-zoom)) calc(56px * var(--sw-zoom)) calc(84px * var(--sw-zoom)) minmax(140px, 1.2fr) calc(24px * var(--sw-zoom)); }
  .sw-row .col-lastcheck { display: none; }
  .sw-alert { grid-template-columns: calc(130px * var(--sw-zoom)) minmax(160px, 1fr) calc(110px * var(--sw-zoom)) calc(140px * var(--sw-zoom)); }
  .sw-alert .col-advice { grid-column: 1 / -1; }
  .sw-logline { grid-template-columns: calc(70px * var(--sw-zoom)) calc(54px * var(--sw-zoom)) minmax(120px, 1fr) calc(52px * var(--sw-zoom)) calc(76px * var(--sw-zoom)); }
  .sw-logline .note { grid-column: 1 / -1; padding-left: 70px; }
}

/* ── Mobiel ───────────────────────────────────────────────────────────────── */

/* ─────────────────────────────────────────────────────────────────────────
   Twee bewuste regels in plaats van een toevallige afbreking, van 940 tot 761

   In die band paste de tabbladenrij links niet meer naast de knoppen rechts. Het
   rechterblok viel er dan onder, rechts uitgelijnd, en de balk werd van 54 naar
   116 pixels hoog met een lege strook ernaast: dat leest als een kapotte kop.

   Onder de 760 gebeurde dit al lang niet meer, want daar krijgen beide blokken de
   volle breedte en staan ze netjes onder elkaar (61 pixels). Diezelfde twee regels
   gelden nu vanaf 940, zodat de overgang van breed naar smal in één keer gaat in
   plaats van via een tussenstand die niemand zo bedoeld heeft.

   Dit stond er al vóór de roulette; gevonden bij het nameten van de kop.
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width: 940px) {
  .sw-head { align-items: flex-start; }
  .sw-head-left, .sw-head-right { width: 100%; }
  .sw-head-right { justify-content: space-between; }
}

@media (max-width: 760px) {
  .sw-shell { padding: var(--space-3) var(--space-3) var(--space-4); gap: var(--space-3); }

  .sw-head { align-items: flex-start; gap: var(--space-3); }
  .sw-head-left, .sw-head-right { gap: var(--space-3); width: 100%; }
  .sw-head-right { justify-content: space-between; }
  .sw-brand b { font-size: calc(22px * var(--sw-zoom)); }
  .sw-clock b { font-size: calc(20px * var(--sw-zoom)); }
  .sw-tabs { width: 100%; }
  .sw-tab { flex: 1; justify-content: center; padding: 0 var(--space-2); font-size: calc(11.5px * var(--sw-zoom)); }
  .sw-intervals { order: 10; width: 100%; }

  /* Het oordeelblok vulde het hele eerste scherm van een telefoon: je moest scrollen om
     ook maar één domein te zien, terwijl daar het antwoord staat. Alles staat er nog, maar
     kleiner en dichter op elkaar: getal en label naast elkaar in plaats van onder elkaar,
     en de tegels eronder in dezelfde compacte maat. */
  .sw-topbar { grid-template-columns: minmax(0, 1fr); gap: var(--space-2); padding: var(--space-2) var(--space-3); }
  .sw-verdict-main { gap: var(--space-2); }
  .sw-verdict-main svg { width: calc(22px * var(--sw-zoom)); height: calc(22px * var(--sw-zoom)); }
  .sw-verdict-main b { font-size: calc(17px * var(--sw-zoom)); white-space: normal; }

  /* Zes tellingen naast elkaar lopen op 375px over elkaar heen; twee rijen van drie houdt
     elk label leesbaar. Getal en label op één regel scheelt de halve hoogte. */
  .sw-counts {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 4px var(--space-2); width: 100%;
  }
  .sw-counts div { min-width: 0; display: flex; align-items: baseline; gap: 5px; text-align: left; }
  .sw-counts b { font-size: calc(15px * var(--sw-zoom)); }
  .sw-counts span { font-size: calc(8px * var(--sw-zoom)); letter-spacing: .06em; margin-top: 0; }

  /* Op een smal scherm alleen wat er echt toe doet onder de domeinnaam. */
  .sw-domain .sw-sub-detail { display: none; }
  .sw-domain .sw-sub > span:first-child::before { content: none; }

  .sw-kpis, .sw-kpis.of4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sw-kpi .value { font-size: calc(21px * var(--sw-zoom)); }

  /* De tegels ín het oordeelblok mogen kleiner dan de losse tegels elders: ze staan hier
     als samenvatting, niet als kop van een scherm. */
  .sw-topbar .sw-kpis { gap: var(--space-2) var(--space-3); border-left: 0; padding-left: 0; }
  /* Het cijfer en de toelichting naast elkaar in plaats van onder elkaar: dat scheelt per
     tegel een regel, en zes tegels keer een regel is een halve telefoon. */
  .sw-topbar .sw-kpi {
    display: grid; grid-template-columns: auto minmax(0, 1fr);
    column-gap: 6px; align-items: baseline;
  }
  .sw-topbar .sw-kpi .label { grid-column: 1 / -1; font-size: calc(8px * var(--sw-zoom)); letter-spacing: .06em; }
  .sw-topbar .sw-kpi .value { font-size: calc(16px * var(--sw-zoom)); }
  .sw-topbar .sw-kpi .sub { font-size: calc(9px * var(--sw-zoom)); }

  /* De tabel wordt een lijst met kaartjes: kolommen passen hier niet. */
  .sw-row.head { display: none; }
  .sw-row.item {
    /* Niet "auto" voor de statuskolom: die eiste alle ruimte op waardoor de
       domeinkolom naar 0 px kroop en de domeinnaam over de status heen viel.
       Twee kolommen met een vaste verhouding houdt allebei leesbaar. */
    grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
    grid-template-areas:
      "domain status"
      "meta   meta"
      "uptime uptime";
    row-gap: var(--space-2);
    padding: var(--space-3);
    border: 1px solid var(--line);
    border-left-width: calc(3px * var(--sw-zoom));
    margin-bottom: var(--space-2);
  }
  .sw-row.item .sw-domain { grid-area: domain; }
  .sw-row.item .sw-status { grid-area: status; justify-content: flex-end; text-align: right; min-width: 0; }
  /* Hoogstens twee regels toelichting: anders wordt elk kaartje vier regels
     hoog en scroll je je suf. De volledige tekst staat in de meldingenkolom
     en op het detailscherm. */
  .sw-row.item .sw-status span {
    text-align: right; white-space: normal;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .sw-row.item .sw-domain b { overflow-wrap: anywhere; }

  /* De kengetallen in de bovenste balk: .sw-topbar .sw-kpis is specifieker dan
     .sw-kpis, dus die moet hier apart genoemd worden. Anders blijven het vijf
     kolommen van 54 px en loopt de tekst over elkaar heen. */
  .sw-topbar .sw-kpis {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-2) var(--space-3);
  }
  .sw-topbar .sw-counts { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .sw-row.item .col-meta { grid-area: meta; display: flex; gap: var(--space-4); flex-wrap: wrap; }
  .sw-row.item .col-meta .sw-unit { white-space: nowrap; }
  .sw-row.item .col-http, .sw-row.item .col-ms, .sw-row.item .col-lastcheck,
  .sw-row.item .col-ssl, .sw-row.item .col-dnssec { display: none; }
  .sw-row.item .sw-uptime { grid-area: uptime; }
  .sw-row.item .sw-chevron { display: none; }


  .sw-logline { grid-template-columns: calc(62px * var(--sw-zoom)) calc(46px * var(--sw-zoom)) minmax(0, 1fr) calc(44px * var(--sw-zoom)); row-gap: 2px; }
  .sw-logline .measure { display: none; }
  .sw-logline .note { grid-column: 1 / -1; padding-left: 62px; }

  .sw-incident {
    grid-template-columns: calc(8px * var(--sw-zoom)) minmax(0, 1fr) auto;
    grid-template-areas: "dot domain dur" "x when when" "y reason reason" "z state state";
    row-gap: 2px;
  }
  .sw-incident .dot { grid-area: dot; }
  .sw-incident .domain { grid-area: domain; }
  .sw-incident .dur { grid-area: dur; }
  .sw-incident .when { grid-area: when; }
  .sw-incident .reason { grid-area: reason; }
  .sw-incident .state { grid-area: state; text-align: left; }

  .sw-foot { flex-direction: column; gap: var(--space-1); }
  .sw-card-head { flex-direction: column; align-items: flex-start; gap: 2px; }
  .sw-card-head .meta { text-align: left; }
}

@media (prefers-reduced-motion: reduce) {
  .sw-live i { animation: none; }
}

/* ── Hulpklassen ──────────────────────────────────────────────────────────
   Deze staan hier en niet als style="" in de HTML, omdat het
   Content-Security-Policy geen inline stijlen toestaat, ook niet die
   JavaScript zelf zet. Eén regel CSS is bovendien beter te vinden. */

.sw-plainlink { text-decoration: none; color: inherit; }
.sw-plainlink:hover { text-decoration: none; color: inherit; }
.sw-gap-top { margin-top: var(--space-3); }
[data-sw-panel] > .sw-gap-top { margin-top: 0; }
.sw-nomargin { margin: 0; }
.sw-minw0 { min-width: 0; }
.sw-tail { font-size: calc(10px * var(--sw-zoom)); letter-spacing: .14em; color: var(--t3); }
.sw-loghead-live { margin-left: var(--space-3); }

.sw-glyph-15 { width: calc(15px * var(--sw-zoom)); height: calc(15px * var(--sw-zoom)); }
.sw-glyph-17 { width: calc(17px * var(--sw-zoom)); height: calc(17px * var(--sw-zoom)); }
.sw-glyph-14 { width: calc(14px * var(--sw-zoom)); height: calc(14px * var(--sw-zoom)); }
.sw-glyph-26 { width: calc(26px * var(--sw-zoom)); height: calc(26px * var(--sw-zoom)); }
.sw-glyph-28 { width: calc(28px * var(--sw-zoom)); height: calc(28px * var(--sw-zoom)); }
.sw-glyph-32 { width: calc(32px * var(--sw-zoom)); height: calc(32px * var(--sw-zoom)); }

.sw-uptime-pct { width: calc(58px * var(--sw-zoom)); text-align: right; }

/* De uptime-tabel heeft een eigen kolomindeling. */
.sw-row.uptimerow {
  grid-template-columns: minmax(170px, 1fr) minmax(220px, 2.4fr) calc(78px * var(--sw-zoom)) calc(78px * var(--sw-zoom)) calc(78px * var(--sw-zoom));
}

/* De regels onder "Laatste checks" op het detailscherm. */
.sw-logline.checkline { grid-template-columns: calc(62px * var(--sw-zoom)) calc(8px * var(--sw-zoom)) minmax(0, 1fr) calc(84px * var(--sw-zoom)); }
.sw-logline.checkline .dot { align-self: center; }

/* De balkgrafieken zijn SVG: de hoogtes zitten in attributen, niet in stijl. */
.sw-svgbars { display: block; width: 100%; }
.sw-svgbars.h16 { height: calc(16px * var(--sw-zoom)); }
.sw-uptime .sw-svgbars { flex: 1; min-width: 0; }
.sw-svgbars.h20 { height: calc(20px * var(--sw-zoom)); }
.sw-svgbars.h40 { height: calc(40px * var(--sw-zoom)); }
.sw-svgbars.h104 { height: calc(104px * var(--sw-zoom)); }
.sw-svgbars .ok { fill: color-mix(in srgb, var(--ok) 62%, transparent); }
.sw-svgbars .warn { fill: var(--warn); }
.sw-svgbars .crit { fill: var(--crit); }
.sw-svgbars .now { fill: var(--acc); }
.sw-svgbars .none { fill: color-mix(in srgb, var(--ink) 12%, transparent); }
.sw-svgbars .plain { fill: var(--t5); }

@media (max-width: 1180px) {
  .sw-row.uptimerow { grid-template-columns: minmax(140px, 1fr) minmax(160px, 2fr) calc(66px * var(--sw-zoom)) calc(66px * var(--sw-zoom)) calc(66px * var(--sw-zoom)); }
}
@media (max-width: 760px) {
  .sw-row.item.uptimerow {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "domain pct" "bars bars";
    row-gap: var(--space-2);
  }
  .sw-row.item.uptimerow > :nth-child(1) { grid-area: domain; }
  .sw-row.item.uptimerow > :nth-child(2) { grid-area: bars; }
  .sw-row.item.uptimerow > :nth-child(3),
  .sw-row.item.uptimerow > :nth-child(4) { display: none; }
  .sw-row.item.uptimerow > :nth-child(5) { grid-area: pct; }
  .sw-logline.checkline { grid-template-columns: calc(56px * var(--sw-zoom)) calc(8px * var(--sw-zoom)) minmax(0, 1fr) calc(66px * var(--sw-zoom)); }
}


/* ── Groot scherm ──────────────────────────────────────────────────────────
   Het ontwerp is getekend op 1440 px van dichtbij. Hangt het scherm aan de
   muur, dan kijk je er van verder af naar en moet alles groter. Deze trappen
   doen dat vanzelf; de knop "groot scherm" in de kop zet er nog een slag
   bovenop voor wie er echt met de neus vanaf staat. */

/* De intervallenregel is de langste tekst in de kop, en hij staat woordelijk ook boven
   het checklog. Onder de 1700 pixels moet de kop het zonder doen: dan passen de knoppen
   op één regel, en dat is wat je de hele dag ziet. */
@media (max-width: 1699px) {
  .sw-head .sw-intervals { display: none; }
}




/* ── Bezoekerskolommen in de domeinentabel ─────────────────────────────── */

.sw-delta { font-size: calc(10px * var(--sw-zoom)); font-variant-numeric: tabular-nums; }
.sw-domain-name { font-family: var(--font-heading); font-weight: 600; font-size: calc(16px * var(--sw-zoom)); letter-spacing: .03em; }

/* ── Staafgrafiek bezoekers ────────────────────────────────────────────── */

.sw-vcol.leeg { opacity: .35; }
.sw-vchart { display: flex; align-items: flex-end; gap: calc(6px * var(--sw-zoom)); }
.sw-vchart-empty { margin: 0; font-size: calc(12px * var(--sw-zoom)); color: var(--t4); }
.sw-vcol {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: calc(4px * var(--sw-zoom));
  /* Een gemeten dag is een knop: die opent het venster met de verdeling per domein. De
     knop moet er niet uitzien als een knop -- de grafiek blijft een grafiek -- maar wel
     aanvoelen als iets waar je op kunt drukken. */
  font: inherit; color: inherit; background: none; border: 0; padding: 0;
  -webkit-appearance: none; appearance: none;
}
button.sw-vcol { cursor: pointer; }
button.sw-vcol:hover svg.sw-vbar rect,
button.sw-vcol:focus-visible svg.sw-vbar rect { fill: var(--acc); }
button.sw-vcol:hover .sw-vval,
button.sw-vcol:focus-visible .sw-vval { color: var(--t1); }
button.sw-vcol:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
/* Op een aanraakscherm bestaat hover niet; daar mag de aanwijzing weg. */
@media (hover: none) {
  button.sw-vcol:hover svg.sw-vbar rect { fill: color-mix(in srgb, var(--acc) 45%, transparent); }
}
.sw-vval { font-size: calc(10px * var(--sw-zoom)); font-variant-numeric: tabular-nums; color: var(--t3); }
.sw-vday {
  font-size: calc(9.5px * var(--sw-zoom)); letter-spacing: .08em; text-transform: uppercase;
  color: var(--t5); white-space: nowrap;
}
svg.sw-vbar {
  display: block; width: 100%; height: calc(56px * var(--sw-zoom));
}
svg.sw-vbar rect { fill: color-mix(in srgb, var(--acc) 45%, transparent); }
svg.sw-vbar.now rect { fill: var(--acc); }

.sw-vstats {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-3);
  border-top: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
  padding-top: var(--space-3);
}
.sw-vstats .label { font-size: calc(9.5px * var(--sw-zoom)); letter-spacing: .14em; text-transform: uppercase; color: var(--t4); }
.sw-vstats .value { font-family: var(--font-heading); font-weight: 600; font-size: calc(19px * var(--sw-zoom)); font-variant-numeric: tabular-nums; }

/* ── Bezoekers per domein ──────────────────────────────────────────────── */

.sw-row.vrow {
  grid-template-columns:
    minmax(calc(150px * var(--sw-zoom)), 1.3fr)
    calc(90px * var(--sw-zoom)) calc(90px * var(--sw-zoom)) calc(72px * var(--sw-zoom))
    minmax(calc(150px * var(--sw-zoom)), 1.4fr)
    calc(64px * var(--sw-zoom))
    minmax(calc(90px * var(--sw-zoom)), 1fr)
    calc(64px * var(--sw-zoom));
}
.sw-share { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
svg.sw-share-svg { flex: 1; min-width: 0; height: calc(8px * var(--sw-zoom)); display: block; }
svg.sw-share-svg .track { fill: color-mix(in srgb, var(--ink) 12%, transparent); }
svg.sw-share-svg .fill { fill: var(--acc); }
.sw-share-label {
  font-size: calc(11px * var(--sw-zoom)); font-variant-numeric: tabular-nums;
  width: calc(38px * var(--sw-zoom)); text-align: right; color: var(--t3);
}
.c-t2 { color: var(--t2); }

/* ── CMS-gezondheid ────────────────────────────────────────────────────── */

.sw-fact.health {
  grid-template-columns: calc(16px * var(--sw-zoom)) minmax(0, 1fr) auto;
  align-items: center;
}
.sw-fact.health dt { text-transform: none; letter-spacing: .02em; }
.sw-fact.health dd { white-space: normal; text-align: right; }

@media (max-width: 1180px) {
  /* Krap: bezoekers, nu online en het domein vallen weg; ssl blijft, want
     dat is de kolom waar je een storing in wording aan ziet aankomen. */
  .sw-row .col-visitors, .sw-row .col-online, .sw-row .col-domein { display: none; }
  .sw-row {
    grid-template-columns:
      minmax(100px, 1.3fr) 100px 40px 60px minmax(80px, 1.4fr) 46px 86px 18px;
  }
  .sw-row.vrow {
    grid-template-columns: minmax(120px, 1.2fr) 80px 72px minmax(90px, 1fr) 56px;
  }
  .sw-row.vrow > :nth-child(3), .sw-row.vrow > :nth-child(7), .sw-row.vrow > :nth-child(8) { display: none; }
}

@media (max-width: 760px) {
  .sw-vchart { gap: 2px; }
  .sw-vval { display: none; }
  /* Veertien datums naast elkaar passen niet op 375 px en lopen in elkaar.
     Alleen elke derde tonen; de rest houdt zijn ruimte, zodat de staafjes
     even breed blijven. */
  .sw-vday { font-size: 8px; letter-spacing: 0; }
  .sw-vcol .sw-vday { visibility: hidden; }
  .sw-vcol:nth-child(3n + 1) .sw-vday,
  .sw-vcol:last-child .sw-vday { visibility: visible; }
  .sw-row.vrow {
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas: "domein vandaag nu";
    padding: var(--space-3);
    border: 1px solid var(--line);
    margin-bottom: var(--space-2);
  }
  .sw-row.vrow > :nth-child(1) { grid-area: domein; }
  .sw-row.vrow > :nth-child(2) { grid-area: vandaag; }
  .sw-row.vrow > :nth-child(6) { grid-area: nu; }
  .sw-row.vrow > :nth-child(3),
  .sw-row.vrow > :nth-child(4),
  .sw-row.vrow > :nth-child(5),
  .sw-row.vrow > :nth-child(7),
  .sw-row.vrow > :nth-child(8) { display: none; }
  .sw-vstats { gap: var(--space-2); }
}


/* Zes tegels op het detailscherm (ontwerp), en de ondertitel op één regel. */
.sw-kpis.of6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }

.sw-detail-title .sw-sub {
  display: flex; flex-wrap: wrap; gap: 0 calc(4px * var(--sw-zoom));
  max-width: calc(560px * var(--sw-zoom));
}
.sw-detail-title .sw-sub > span { white-space: nowrap; }

/* Het checklog mag op een smal scherm nooit de pagina breed maken. */
.sw-logline .target,
.sw-logline .note { min-width: 0; overflow: hidden; text-overflow: ellipsis; }

@media (max-width: 1180px) {
  .sw-kpis.of6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .sw-kpis.of6 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sw-logline { grid-template-columns: 58px 42px minmax(0, 1fr) 40px; }
  .sw-logline .target { white-space: nowrap; }
}


/* ── Stuiterballen tegen de schermbeveiliging ─────────────────────────────
   De beveiliging van een Samsung kijkt naar een stilstaand beeld. Wake lock
   hielp niet (dat gaat over een slapend scherm) en een filmpje afspelen ook
   niet (het beeld zelf bleef stilstaan). Wat wel telt is dat er echt pixels
   veranderen, over het hele scherm.

   Dus: de oude stuiterbal van vroeger. Elke bal heeft een eigen tempo voor
   links-rechts en voor boven-onder, en die twee zijn geen veelvoud van elkaar,
   dus de baan herhaalt zich praktisch nooit. Ze liggen achter de inhoud en de
   kaarten zijn doorzichtig, dus je kijkt er dwars doorheen.

   Alleen transform wordt geanimeerd; de tv hoeft de pagina dus niet bij elke
   stap opnieuw door te rekenen. */

.sw-wakker {
  position: fixed; inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}
.sw-wakker .bol {
  position: absolute; top: 0; left: 0;
  border-radius: 50%;
  will-change: transform;
}

/* Een echte bal in plaats van een wolk: een lichte kern linksboven, een
   volle kleur en een duidelijke rand. Anders zie je op een tv van drie meter
   afstand niets bewegen, en dat is nu juist het hele doel. */
.sw-wakker .bol::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 30%,
    color-mix(in srgb, var(--bal) 15%, #fff) 0%,
    var(--bal) 34%,
    color-mix(in srgb, var(--bal) 78%, #000) 82%,
    color-mix(in srgb, var(--bal) 55%, #000) 100%);
  box-shadow: inset 0 0 calc(30px * var(--sw-zoom)) color-mix(in srgb, #000 45%, transparent);
}

/* Twee animaties per bal: een voor de breedte, een voor de hoogte. De
   verhouding tussen die twee bepaalt de baan; oneven getallen zorgen dat hij
   nooit hetzelfde rondje blijft draaien. */
.sw-wakker .b1 {
  --bal: var(--acc); width: 20vmax; height: 20vmax; opacity: .22;
  animation: sw-x 37s linear infinite alternate, sw-y 23s linear infinite alternate;
}
.sw-wakker .b2 {
  --bal: var(--ok); width: 13vmax; height: 13vmax; opacity: .34;
  animation: sw-x 29s linear infinite alternate, sw-y 41s linear infinite alternate;
  animation-delay: -8s, -14s;
}
.sw-wakker .b3 {
  --bal: var(--acc); width: 26vmax; height: 26vmax; opacity: .15;
  animation: sw-x 53s linear infinite alternate, sw-y 31s linear infinite alternate;
  animation-delay: -21s, -5s;
}
.sw-wakker .b4 {
  --bal: var(--warn); width: 9vmax; height: 9vmax; opacity: .38;
  animation: sw-x 19s linear infinite alternate, sw-y 43s linear infinite alternate;
  animation-delay: -3s, -27s;
}
.sw-wakker .b5 {
  --bal: var(--ok); width: 16vmax; height: 16vmax; opacity: .26;
  animation: sw-x 47s linear infinite alternate, sw-y 17s linear infinite alternate;
  animation-delay: -33s, -9s;
}
.sw-wakker .b6 {
  --bal: var(--crit); width: 11vmax; height: 11vmax; opacity: .26;
  animation: sw-x 61s linear infinite alternate, sw-y 29s linear infinite alternate;
  animation-delay: -12s, -19s;
}

/* Van rand tot rand. calc met 100% houdt rekening met de eigen grootte, dus
   de bal loopt niet half het scherm uit. */
@keyframes sw-x {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(100vw - 100%)); }
}
@keyframes sw-y {
  from { translate: 0 0; }
  to   { translate: 0 calc(100vh - 100%); }
}


/* In de dagstand is het doek licht. Dezelfde dekking geeft daar harde vlekken
   op wit, dus de ballen worden er wat ingetogener. */
html[data-sw-theme="dag"] .sw-wakker .bol { opacity: .12; }
html[data-sw-theme="dag"] .sw-wakker .b4,
html[data-sw-theme="dag"] .sw-wakker .b2 { opacity: .16; }

/* ─────────────────────────────────────────────────────────────────────────
   Als app op een telefoon

   Op een breed scherm bestaat hier niets van: de menuknop is verborgen en
   .sw-extra is display:contents, dus de knoppen staan gewoon in de kop.
   Onder de 760 pixels wordt het een app: een smalle balk bovenin die blijft
   staan, de drie weergaven als tabbalk onderin met je duim erbij, en de rest
   achter één knop in een blad dat omhoogkomt.
   ───────────────────────────────────────────────────────────────────────── */

.sw-menubtn { display: none; }

.sw-extra, .sw-menugroep, .sw-menulijst { display: contents; }
.sw-sheetkop, .sw-menutitel, .sw-menuchevron { display: none; }
.sw-install button > svg, .sw-notify button > svg { display: none; }
.sw-sheetgreep, .sw-sheetdim { display: none; }

/* ─────────────────────────────────────────────────────────────────────────
   Het uitklapblad, al vanaf 1600 pixels

   Onder deze breedte paste de kop niet meer op één regel: de knoppen rechts
   vielen eronder en de balk werd twee keer zo hoog (54 naar 116 pixels), met
   een lege strook ernaast. Dat is precies de breedte van een halfgeschoven
   venster, dus je liep er zo tegenaan.

   De grens stond op 1150 en dat was gemeten aan de kop van een BEZOEKER. Wie
   is ingelogd heeft er twee knoppen bij (meldingen, beheer), en die kop brak
   al bij 1300; de grens van 1400 liet bij extra bedieningen nog uitloop zien.
   Met Spraak houden we 1600 aan. Eén grens voor iedereen, en die
   volgt de breedste stand, want een kop die halverwege omklapt is erger dan een
   kop die iets eerder compact wordt: de knoppen zitten dan achter de hamburger
   in plaats van dat ze eronder vallen.

   Verandert er iets aan de kop, meet dit dan opnieuw en niet op gevoel: zet het
   venster ingelogd op 1600 en kijk of `.sw-head` 54 pixels hoog blijft.

   Alleen de knoppen rechts gaan hier achter de hamburger; de rest van het
   scherm blijft de gewone weergave. Onder de 760 neemt de echte mobiele
   opmaak het over (tabbalk onderin, kaartjes in plaats van een tabel).
   ───────────────────────────────────────────────────────────────────────── */
@media (max-width: 1600px) {
  .sw-menubtn {
    display: inline-flex; align-items: center; justify-content: center;
    width: calc(34px * var(--sw-zoom)); height: calc(34px * var(--sw-zoom)); flex: none;
    border: 1px solid var(--t5); background: transparent; color: var(--t2);
    cursor: pointer; padding: 0;
  }
  .sw-menubtn svg { width: 18px; height: 18px; }
  .sw-menubtn[aria-expanded="true"] { background: var(--t5); color: var(--ground); }

  .sw-extra {
    display: flex; flex-direction: column; align-items: stretch;
    gap: var(--space-3);
    /* HET BLAD KOMT VAN ONDEREN, ACHTER DE TABBALK VANDAAN, en gaat daar ook weer heen (Theo,
       18 september 2026: "menu moet eigenlijk vanuit onder achter het pwa menu en ook weer daar
       sluiten; hij komt nu plotseling vanuit rechtsboven"). De knop Meer staat onderin, dus daar
       hoort het blad ook vandaan te komen -- dat is de beweging die je in elke app kent. Het stond
       eerst onder de kop, uit de tijd dat de hamburger daar zat. */
    position: fixed; left: 0; right: 0;
    bottom: var(--sw-voet, 0px);
    z-index: 29;
    padding: var(--space-3) var(--space-4) var(--space-4);
    background: var(--ground);
    border-top: 1px solid var(--line);
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -14px 34px rgb(0 0 0 / 40%);
    transform: translateY(110%);
    opacity: 0; visibility: hidden; pointer-events: none;
    transition: transform .3s cubic-bezier(.22, 1, .36, 1), opacity .24s ease, visibility 0s .3s;
    /* Het blad paste niet: de onderste knoppen vielen achter de tabbalk en waren niet te raken
       (Theo, 18 september 2026: "menu past niet helemaal, ik kan nooit bij onderste"). Nu loopt hij
       tot onder de kop en scrolt hij zelf als er meer in staat dan er past. */
    max-height: calc(100dvh - var(--sw-kop, 58px) - var(--sw-voet, 0px) - var(--space-3));
    /* `fit-content` en niet de vanzelfsprekende `auto`: een vastgezet blok in een flexcontainer
       wordt door de browser alsnog uitgerekt tot zijn maximum, en dan staat er een half scherm leegte
       onder de laatste knop. */
    height: fit-content; align-self: flex-start;
    overflow-y: auto; overscroll-behavior: contain;
    padding-bottom: var(--space-4);
  }
  .sw-extra.is-slepen { transition: none; }
  .sw-extra.open { transform: translateY(0); opacity: 1; visibility: visible; pointer-events: auto; transition-delay: 0s; }
  @media (prefers-reduced-motion: reduce) {
    .sw-extra { transition: none; }
  }

  .sw-sheetgreep {
    display: block; width: 42px; height: 4px; border-radius: 2px;
    background: var(--t5); margin: 0 auto var(--space-2);
    order: -1;
  }
  .sw-extra .sw-themeswitch { width: 100%; }
  .sw-extra .sw-themeswitch button { flex: 1; justify-content: center; min-height: 46px; }
  .sw-extra .sw-install { display: block; }
  .sw-extra .sw-linkbtn,
  .sw-extra .sw-roulettebtn,
  .sw-extra .sw-themebtn { display: flex; justify-content: center; width: 100%; min-height: 46px; }
  /* Behalve de knop in het profielblok: die staat naast de naam en niet eronder. Zonder deze regel
     duwt hij de naam tot één letter per regel. */
  .sw-extra .sw-profiel .sw-linkbtn { width: auto; flex: none; padding-inline: var(--space-3); }

  .sw-sheetdim {
    display: block; position: fixed; inset: 0; z-index: 28;
    background: rgb(0 0 0 / 45%);
  }
  .sw-sheetdim { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .24s ease, visibility 0s .3s; }
  .sw-sheetdim.open { opacity: 1; visibility: visible; pointer-events: auto; transition-delay: 0s; }
  .sw-sheetdim[hidden] { display: none; }
  .sw-sheetkop { display: flex; align-items: center; justify-content: space-between; }
  .sw-sheetkop h2 { margin: 0; font: 600 24px/1.3 var(--font-body); }
  .sw-menugroep { display: block; }
  /* Platformbestemmingen staan boven 760px al in de tabbalk. */
  .sw-extra .sw-menugroep--platform { display: none; }
  .sw-extra .sw-menulijst > .sw-alleen-mobiel { display: none; }
  .sw-menutitel { display: block; margin: 0 0 9px 3px; color: var(--t3); font: 500 14px/1.4 var(--font-body); }
  .sw-menulijst { display: flex; flex-direction: column; overflow: hidden; border: 1px solid var(--line); border-radius: 16px; background: color-mix(in srgb, var(--ink) 4%, var(--ground)); }
  .sw-menulijst > * + * { box-shadow: inset 0 1px var(--line); }
  .sw-extra .sw-menulijst button, .sw-extra .sw-menulijst > a {
    justify-content: flex-start; gap: 14px; min-height: 54px; padding: 12px 16px; margin: 0;
    border: 0; border-radius: 0; background: transparent; color: var(--ink);
    font: 400 16px/1.4 var(--font-body); text-transform: none; letter-spacing: normal; text-align: left;
  }
  .sw-extra .sw-menulijst button:hover, .sw-extra .sw-menulijst > a:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); text-decoration: none; }
  .sw-extra .sw-menulijst button[aria-pressed="true"] { color: var(--acc); background: color-mix(in srgb, var(--acc) 9%, transparent); }
  .sw-extra .sw-menulijst svg { display: block; width: 22px; height: 22px; flex: none; color: var(--t3); }
  .sw-menuchevron { display: block; margin-left: auto; color: var(--t5); font-size: 24px; }
  .sw-extra .sw-menulijst .sw-install { width: 100%; }
  .sw-extra .sw-menulijst .sw-install button { width: 100%; }
  .sw-extra .sw-installtip { position: static; width: auto; margin: 0 12px 12px; box-shadow: none; }
  @media (prefers-reduced-motion: reduce) { .sw-extra, .sw-sheetdim { transition: none; } }
}
.sw-tab svg { display: none; }

@media (max-width: 760px) {
  /* DE BOVENBALK STAAT VAST, NIET PLAKKEND (verzoek Theo, 18 september 2026: "header en footer zit
     niet vast, moet echt een pwa dingetje zijn net als bij cms"). Met `sticky` schuift hij in een
     geïnstalleerde app toch mee zodra je met een zwiep scrolt; `fixed` blijft echt staan, net als de
     balk onderin. De schil houdt er ruimte voor vrij met dezelfde maat die het script meet. */
  .sw-head {
    position: fixed; top: 0; left: 0; right: 0; z-index: 30;
    align-items: center;
    flex-wrap: nowrap;
    gap: var(--space-3);
    margin: 0;
    padding: max(var(--space-3), env(safe-area-inset-top)) var(--space-3) var(--space-3);
    background: var(--ground);
    border-bottom: 1px solid var(--line);
  }
  .sw-head-left { width: auto; flex: 1 1 auto; min-width: 0; gap: var(--space-3); }
  .sw-head-right { width: auto; flex: 0 0 auto; justify-content: flex-end; gap: var(--space-3); flex-wrap: nowrap; }
  .sw-brand [data-sw="subtitle"] { display: none; }
  .sw-brand b { font-size: 19px; }
  .sw-merk { width: 34px; height: 34px; }
  .sw-live span { display: none; }
  .sw-live i { width: 9px; height: 9px; }
  .sw-clock { text-align: right; }
  .sw-clock b { font-size: 16px; }
  .sw-clock span { display: none; }

  .sw-menubtn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; flex: none;
    border: 1px solid var(--t5); background: transparent; color: var(--t2);
    cursor: pointer; padding: 0;
  }
  .sw-menubtn svg { width: 20px; height: 20px; }
  .sw-menubtn[aria-expanded="true"] { background: var(--t5); color: var(--ground); }

  /* De drie weergaven onderin, waar je duim al is. */
  .sw-head-left .sw-tabs {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 35;
    width: auto; gap: 0;
    background: var(--ground);
    border-top: 1px solid var(--line);
    /* Minstens vier pixels onder de labels, en meer op een toestel met een veeggebied. Met alleen
       `env()` staat de tekst op een Android-telefoon (waar die waarde nul is) tegen de onderrand en
       snijdt hij af (Theo, 18 september 2026: "pwa footer is niet goed te zien"). */
    padding-bottom: max(4px, env(safe-area-inset-bottom));
  }
  .sw-tabs .sw-tab {
    flex: 1 1 0; flex-direction: column; gap: 3px;
    min-height: 64px; padding: 9px 4px 8px;
    border: 0; background: transparent; color: var(--t4);
    font-size: 11px; letter-spacing: .03em;
  }
  /* Het label krijgt zijn eigen regelhoogte. Zonder dit valt de onderkant van de letters weg zodra
     de knop krap staat: de tekst wordt afgekapt door de `overflow: hidden` die de lange namen op
     één regel houdt. */
  .sw-tabs .sw-tab span { line-height: 1.3; padding-bottom: 1px; }
  .sw-tab svg { display: block; width: 21px; height: 21px; }
  /* WAT ER OP EEN TELEFOON IN DE ONDERBALK STAAT (verzoek Theo, 18 september 2026): CMS sites,
     Uptime, Bezoekers, 112-meldingen, Nieuws en Meer. Dat is waar je op een telefoon voor komt; de
     serverknoppen, Spam, Openprovider en Geparkeerd staan achter Meer. Zes is het maximum: bij zeven
     wordt een label zo smal dat het afkapt. */
  .sw-tabs .sw-tab--pagina { display: none; }
  .sw-tabs .sw-tab--pagina[data-sw-view="112"],
  .sw-tabs .sw-tab--pagina[data-sw-view="nieuws"] { display: inline-flex; }
  /* "112-meldingen" en "CMS sites" breken over twee regels en duwen de balk scheef. Onderin staat
     daarom de korte naam; het icoon staat erbij en je weet waar je op drukt.

     Twee losse spannen en geen `font-size: 0` met een `::after`: bij die truc valt de regelhoogte
     van het label weg (die rekent met de lettergrootte) en zakt het woord een paar pixels ten
     opzichte van de labels ernaast. Dat was precies te zien bij 112. */
  .sw-tabs .sw-tab span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
  .sw-tabs .sw-tab .sw-tab-lang { display: none; }
  .sw-tabs .sw-tab .sw-tab-kort { display: inline; }
  /* De serverknoppen zijn er op een telefoon niet: die gaan over één machine en passen niet bij de
     vijf schermen die over het platform gaan. Ze staan in het blad achter Meer. */
  .sw-servertabs { display: none; }
  .sw-tabs .sw-tab--meer { display: inline-flex; }
  /* De hamburger in de kop is weg; Meer staat onderin bij de rest. */
  .sw-head-right .sw-menubtn { display: none; }
  .sw-extra .sw-alleen-mobiel { display: flex; }
  .sw-tab[aria-selected="true"] { background: transparent; color: var(--acc); }
  .sw-tab:hover { background: transparent; }

  /* Ruimte boven voor de vaste kop en onder voor de tabbalk; `--sw-kop` is de gemeten hoogte van
     die kop (zie zetBlad in sitewatch.js), met een terugval voor het eerste moment. */
  .sw-shell {
    padding-top: calc(var(--sw-kop, 58px) + var(--space-3));
    padding-bottom: calc(82px + env(safe-area-inset-bottom));
  }

  .sw-extra {
    top: 0; bottom: var(--sw-voet, 74px);
    height: calc(100dvh - var(--sw-voet, 74px)); max-height: none; gap: 22px;
    padding: max(20px, env(safe-area-inset-top)) max(16px, env(safe-area-inset-right)) 24px max(16px, env(safe-area-inset-left));
    scrollbar-width: none;
    border-radius: 0; border: 0; box-shadow: none;
  }
  .sw-extra::-webkit-scrollbar { display: none; }
  .sw-sheetgreep { display: none; }
  .sw-extra .sw-menugroep--platform { display: block; }
  .sw-extra .sw-menulijst > .sw-alleen-mobiel { display: flex; }
  .sw-tabs .sw-tab--meer[aria-expanded="true"] { color: var(--acc); }
  .sw-tab--meer svg { box-sizing: content-box; padding: 3px 14px; margin: -3px -14px; border-radius: 18px; transition: background .2s ease; }
  .sw-tab--meer[aria-expanded="true"] svg { background: color-mix(in srgb, var(--acc) 18%, transparent); }

}

/* Geïnstalleerd als app: geen adresbalk, dus de balk bovenin mag iets ruimer
   zodat hij niet tegen de statusbalk van de telefoon aan plakt. */
@media (max-width: 760px) and (display-mode: standalone) {
  .sw-head { padding-top: max(var(--space-4), env(safe-area-inset-top)); }
}

/* ─────────────────────────────────────────────────────────────────────────
   De opgeruimde kop

   Het woordmerk draagt het domein, dus de regel eronder hoeft dat niet te
   herhalen. Het live-lampje staat op twee regels in plaats van naast elkaar,
   en dag/nacht/schema zit achter één knop. Alles bij elkaar scheelt dat een
   flinke hap breedte, en die gaat naar de cijfers.
   ───────────────────────────────────────────────────────────────────────── */

/* "LIVE" en de teller staan naast elkaar op één regel; de meettijden vallen daaronder,
   want die horen er wel bij maar zijn een ander soort mededeling. `flex-basis: 100%` is wat
   die derde regel afdwingt: zonder dat schuift hij achter de teller aan. */
.sw-livetekst {
  display: flex; flex-wrap: wrap; align-items: baseline;
  column-gap: var(--space-2); row-gap: 1px;
  line-height: 1.15;
}
.sw-livetekst .sw-intervals { flex-basis: 100%; }
.sw-livetekst b {
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(13px * var(--sw-zoom));
  letter-spacing: .14em; text-transform: uppercase;
}
.sw-livetekst em {
  font-style: normal;
  font-size: calc(10px * var(--sw-zoom));
  letter-spacing: .08em; text-transform: uppercase; color: var(--t4);
  font-variant-numeric: tabular-nums;
}

.sw-themebtn {
  display: inline-flex; align-items: center; gap: calc(var(--space-2) * .7);
  min-height: calc(34px * var(--sw-zoom));
  padding: 0 calc(var(--space-3) * .8);
  border: 1px solid var(--t5); background: transparent; color: var(--t2);
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(10.5px * var(--sw-zoom));
  letter-spacing: .1em; text-transform: uppercase;
  cursor: pointer; white-space: nowrap;
}
.sw-themebtn:hover { background: color-mix(in srgb, var(--ink) 9%, transparent); color: var(--ink); }
.sw-themebtn[data-stand="schema"] { border-color: var(--acc); color: var(--acc); }
/* Even breed in alle drie de standen. De knop draait rond tussen Dag, Nacht en Schema, en met een
   opschrift dat meegroeit verspringt de hele rij knoppen ernaast elke keer dat je hem indrukt.
   Het getal is de breedte van het langste woord (Schema) in deze letter; de knop mag groeien als
   een vertaling langer is, maar nooit krimpen. Zelfde reden als bij de roulette ernaast. */
.sw-themebtn [data-sw="theme-label"] { display: inline-block; min-width: calc(46px * var(--sw-zoom)); text-align: center; }
.sw-roulettebtn [data-sw="roulette-label"] { display: inline-block; text-align: center; }
.sw-themeicon { display: inline-flex; }
.sw-themeicon svg { width: calc(16px * var(--sw-zoom)); height: calc(16px * var(--sw-zoom)); }

/* ── Roulette ─────────────────────────────────────────────────────────────────
   De knop die het scherm vanzelf langs de weergaven laat lopen. Zelfde maat en
   rand als de dag/nacht-knop ernaast: het is dezelfde soort schakelaar, en twee
   knoppen naast elkaar die net niet even hoog zijn valt meteen op.

   Draait hij, dan draait het icoon mee en licht de rand op in de accentkleur.
   Dat is met opzet het enige verschil: een tv aan de muur moet je van vijf meter
   afstand kunnen zien of hij loopt. */
.sw-roulettebtn {
  display: inline-flex; align-items: center; gap: calc(var(--space-2) * .7);
  min-height: calc(34px * var(--sw-zoom));
  padding: 0 calc(var(--space-3) * .8);
  border: 1px solid var(--t5); background: transparent; color: var(--t2);
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(10.5px * var(--sw-zoom));
  letter-spacing: .1em; text-transform: uppercase;
  cursor: pointer; white-space: nowrap;
}
.sw-roulettebtn:hover { background: color-mix(in srgb, var(--ink) 9%, transparent); color: var(--ink); }
.sw-roulettebtn[aria-pressed="true"] { border-color: var(--acc); color: var(--acc); }
.sw-rouletteicon { display: inline-flex; }
.sw-rouletteicon svg {
  width: calc(16px * var(--sw-zoom)); height: calc(16px * var(--sw-zoom));
  transform-origin: 50% 50%;
}
.sw-roulettebtn[aria-pressed="true"] .sw-rouletteicon svg { animation: sw-rouletteDraai 2.6s linear infinite; }

@keyframes sw-rouletteDraai { to { transform: rotate(360deg); } }

/* De overgang tussen twee weergaven. Het paneel dooft, wisselt, en komt terug:
   zonder die adempauze klapt het beeld om en lijkt het scherm te haperen.
   De duur staat ook in sitewatch.js (ROULETTE_FADE_MS); houd ze gelijk. */
.sw-shell.is-rouletting [data-sw-panel] { transition: opacity .28s ease; }
.sw-shell.is-rouletting.is-vervagen [data-sw-panel] { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  .sw-roulettebtn[aria-pressed="true"] .sw-rouletteicon svg { animation: none; }
  .sw-shell.is-rouletting [data-sw-panel] { transition: none; }
  .sw-shell.is-rouletting.is-vervagen [data-sw-panel] { opacity: 1; }
}

/* De serverknoppen staan in dezelfde rij als de drie vaste weergaven, maar
   krijgen een streepje ervoor: het zijn andere domeinen, geen andere kijk op
   dezelfde. */
.sw-servertabs { display: inline-flex; gap: var(--space-2); align-items: stretch; }
.sw-servertabs::before {
  content: ""; align-self: center;
  width: 1px; height: calc(24px * var(--sw-zoom));
  background: var(--line); margin: 0 var(--space-2) 0 var(--space-1);
}

@media (max-width: 760px) {
  /* De serverknoppen stonden hier vroeger gewoon in de onderbalk. Sinds 18 september 2026 staan daar
     de vijf schermen die over het hele platform gaan plus Meer; een serverknop gaat over één machine
     en hoort in het blad achter Meer. Zeven knoppen naast elkaar op 390 pixels betekende bovendien
     dat elk label over twee regels brak. */
  .sw-servertabs { display: none; }
  .sw-servertabs::before { content: none; }
  .sw-themebtn { width: 100%; justify-content: center; min-height: 46px; }
}

/* ─────────────────────────────────────────────────────────────────────────
   Inzoomen op één moment

   Klik op een balkje en dit venster laat zien wat er op dat moment werkelijk
   gemeten is. Bewust een venster en geen aparte pagina: je bent aan het kijken
   naar een grafiek en wilt daar meteen weer in terug.
   ───────────────────────────────────────────────────────────────────────── */

.sw-svgbars.klikbaar rect { cursor: pointer; }
.sw-svgbars.klikbaar rect:hover { opacity: .72; }

.sw-momentlaag {
  position: fixed; inset: 0; z-index: 60;
  background: rgb(0 0 0 / 55%);
  display: flex; align-items: flex-start; justify-content: center;
  padding: var(--space-6) var(--space-4);
  overflow-y: auto;
}

.sw-momentkaart {
  width: min(920px, 100%);
  background: var(--ground);
  border: 1px solid var(--line);
  box-shadow: 0 24px 64px rgb(0 0 0 / 45%);
  display: flex; flex-direction: column;
}

.sw-momentkop {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4);
  padding: var(--space-4);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; background: var(--ground); z-index: 1;
}
.sw-momenttitel { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.sw-momenttitel b {
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(17px * var(--sw-zoom)); letter-spacing: .04em;
}
.sw-momenttitel .meta {
  font-size: calc(11px * var(--sw-zoom)); letter-spacing: .1em;
  text-transform: uppercase; color: var(--t4);
}
.sw-momentdicht {
  flex: none; width: 34px; height: 34px; line-height: 1;
  border: 1px solid var(--t5); background: transparent; color: var(--t2);
  font-size: 20px; cursor: pointer;
}
.sw-momentdicht:hover { background: color-mix(in srgb, var(--ink) 10%, transparent); color: var(--ink); }

.sw-momentbody { padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-4); }

.sw-momentcijfers {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: var(--space-3);
}
.sw-momentcijfer {
  border: 1px solid var(--line-soft); padding: var(--space-3);
  display: flex; flex-direction: column; gap: 2px; min-width: 0;
}
.sw-momentcijfer .label {
  font-size: calc(9.5px * var(--sw-zoom)); letter-spacing: .12em;
  text-transform: uppercase; color: var(--t4);
}
.sw-momentcijfer b {
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(21px * var(--sw-zoom)); line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.sw-momentcijfer .sub { font-size: calc(10.5px * var(--sw-zoom)); color: var(--t4); }

.sw-momentnote {
  margin: 0; padding: var(--space-3);
  border-left: 3px solid var(--warn);
  background: color-mix(in srgb, var(--warn) 10%, transparent);
  font-size: calc(12.5px * var(--sw-zoom)); color: var(--t2); line-height: 1.6;
}

.sw-momentblok { display: flex; flex-direction: column; }
.sw-momentblok-kop {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3);
  padding-bottom: var(--space-2); border-bottom: 1px solid var(--line);
  margin-bottom: var(--space-2);
}
.sw-momentblok-kop b {
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(12px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase;
}
.sw-momentblok-kop .meta {
  font-size: calc(10.5px * var(--sw-zoom)); letter-spacing: .08em;
  text-transform: uppercase; color: var(--t4);
}

.sw-momentrow {
  display: grid;
  grid-template-columns: calc(72px * var(--sw-zoom)) calc(64px * var(--sw-zoom)) calc(74px * var(--sw-zoom)) minmax(0, 1fr);
  gap: var(--space-3);
  padding: 5px 0;
  font-size: calc(12px * var(--sw-zoom));
  border-bottom: 1px solid var(--line-soft);
}
.sw-momentrow:last-child { border-bottom: 0; }
.sw-momentrow .tijd { color: var(--t4); font-variant-numeric: tabular-nums; }
.sw-momentrow .code { font-variant-numeric: tabular-nums; }
.sw-momentrow .ms { text-align: right; font-variant-numeric: tabular-nums; color: var(--t3); }
.sw-momentrow .tekst { color: var(--t2); overflow-wrap: anywhere; }
.sw-momentrow.fout { background: color-mix(in srgb, var(--crit) 8%, transparent); }
.sw-momentrow.klikbaar { cursor: pointer; }
.sw-momentrow.klikbaar:hover { background: color-mix(in srgb, var(--ink) 7%, transparent); }

/* De rijen in het bezoekersvenster hebben een andere indeling dan die van een meetmoment:
   daar is het tijd-code-duur-tekst, hier domein-aantal-aandeel. De vaste kolommen hierboven
   zijn 72 pixels breed en een domeinnaam past daar niet in -- die liep over het getal heen. */
.sw-momentrow.sw-dagrij {
  grid-template-columns: minmax(0, 1fr) auto calc(46px * var(--sw-zoom));
  align-items: baseline;
}
.sw-momentrow.sw-dagrij .sw-domain-name { overflow-wrap: anywhere; }
.sw-momentrow.sw-dagrij .num { text-align: right; font-variant-numeric: tabular-nums; }

/* Honderden metingen achter elkaar: die krijgen hun eigen schuifgebied, anders
   duwt één dag het hele venster kilometers lang. */
.sw-momentmetingen { max-height: calc(340px * var(--sw-zoom)); overflow-y: auto; }

.sw-momentleeg {
  margin: 0; padding: var(--space-3) 0;
  font-size: calc(12.5px * var(--sw-zoom)); color: var(--t4); line-height: 1.6;
}

@media (max-width: 760px) {
  /* `flex-start` en niet `stretch`: met `stretch` wordt de kaart precies zo hoog als het scherm,
     terwijl de inhoud langer is. Die inhoud liep dan buiten de kaart door en daar houdt de witte
     achtergrond op -- je keek dwars door het venster heen op de pagina eronder (Theo, 18 september
     2026: "modal is niet helemaal wit van achtergrond als je scrolt"). Nu bepaalt de inhoud de
     hoogte, met het scherm als ondergrens. */
  .sw-momentlaag { padding: 0; align-items: flex-start; }
  .sw-momentkaart { width: 100%; min-height: 100%; border: 0; }
  /* Het venster van een meetmoment vult het scherm, want daar staan honderden metingen in.
     Het bezoekersvenster is een lijstje van negen domeinen; dat over een heel telefoonscherm
     uitrekken geeft een halve pagina leegte onder de laatste regel. */
  .sw-momentkaart.kort { min-height: 0; align-self: flex-start; }
  .sw-momentrow {
    grid-template-columns: calc(66px * var(--sw-zoom)) calc(52px * var(--sw-zoom)) calc(62px * var(--sw-zoom));
    row-gap: 2px;
  }
  .sw-momentrow .tekst { grid-column: 1 / -1; }
}

/* ── De schil om de kop in het beheer ─────────────────────────────────────────
   Het beheer zet de kop in dezelfde .sw-shell als de website, zodat elke maat (rand, marge,
   plakkende balk op een telefoon) uit dezelfde regels komt. Alleen de hoogte en de ruimte
   eronder horen bij een schil met inhoud, en die is hier leeg. Staat na alle mediaregels, zodat
   dit ook de padding-bottom van de telefoonregels overneemt. */
.sw-shell.sw-shell--kop { min-height: 0; padding-bottom: 0; gap: 0; }
/* Een gesloten weergave: in het overzichtspaneel blijven alleen de oordeelbalk en het kaartje. */
[data-sw-panel="overzicht"].is-gesloten > :not([data-sw="verdict"]):not([data-sw="gesloten"]) { display: none; }

/* ── Panelen met inhoud van de server (Spam, Openprovider) ─────────────────────
   Dezelfde kaarten en kleuren als de rest van het dashboard; dit zijn alleen de bouwstenen die
   die panelen extra nodig hebben: een tabel, een lijst met knoppen, een badge, een formulier. */
.sw-kaarttekst { margin: 0; max-width: 84ch; font-size: calc(13px * var(--sw-zoom)); line-height: 1.5; color: var(--t2); }
.sw-kaarttekst + .sw-kaarttekst { margin-top: var(--space-2); }
ul.sw-kaarttekst { padding-left: 1.2em; }
.sw-fijn { font-size: calc(11px * var(--sw-zoom)); letter-spacing: .06em; color: var(--t4); margin-top: 3px; }
.sw-tabelwrap { overflow-x: auto; }
.sw-tabel { width: 100%; border-collapse: collapse; font-size: calc(12.5px * var(--sw-zoom)); }
.sw-tabel th {
  text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--line);
  font-family: var(--font-heading); font-weight: 600; font-size: calc(10.5px * var(--sw-zoom));
  letter-spacing: .12em; text-transform: uppercase; color: var(--t4);
}
.sw-tabel td { padding: 7px 8px; border-bottom: 1px solid color-mix(in srgb, var(--line) 60%, transparent); vertical-align: top; }
.sw-tabel .num { text-align: right; font-variant-numeric: tabular-nums; }

/* De regel onder een cel: het waarom bij een oordeel, of de datum bij een domein. Kleiner en rustiger
   dan de cel zelf, zodat de tabel leesbaar blijft met twee regels per rij. */
.sw-tabelsub { margin-top: 2px; font-size: calc(11.5px * var(--sw-zoom)); color: var(--t2); line-height: 1.35; }
/* De rij die je hebt opengeklapt: een streep aan de kop, geen vlak. De tabel staat vol
   kleurbetekenis (groen is goed, rood is stuk) en een gekleurde achtergrond zou daar dwars
   doorheen praten. */
.sw-tabel tr.is-gekozen > td { background: color-mix(in srgb, var(--ink) 4%, transparent); }
.sw-tabel tr.is-gekozen > td:first-child { box-shadow: inset 2px 0 0 var(--acc); }
.sw-tabel b { font-weight: 600; }
.sw-lijst { display: flex; flex-direction: column; }
.sw-lijstrij {
  display: flex; gap: var(--space-3); justify-content: space-between; align-items: flex-start;
  padding: var(--space-3) 0; border-top: 1px solid color-mix(in srgb, var(--line) 60%, transparent);
}
.sw-lijstrij:first-child { border-top: 0; padding-top: 0; }
.sw-lijstrij > div:first-child { min-width: 0; flex: 1 1 auto; }
.sw-lijstrij > div:first-child > b { font-family: var(--font-heading); font-size: calc(14px * var(--sw-zoom)); letter-spacing: .04em; }
.sw-lijstrij p { margin: 4px 0 0; font-size: calc(12.5px * var(--sw-zoom)); color: var(--t2); overflow-wrap: anywhere; }
.sw-badge {
  display: inline-block; margin-left: 6px; padding: 1px 6px; border: 1px solid var(--t5); vertical-align: middle;
  font-family: var(--font-heading); font-weight: 600; font-size: calc(9.5px * var(--sw-zoom)); letter-spacing: .1em; text-transform: uppercase; color: var(--t3);
}
.sw-badge.c-crit, .sw-badge.c-warn, .sw-badge.c-ok { border-color: currentColor; }
.sw-bericht { margin-top: 6px; }
.sw-bericht summary { cursor: pointer; font-size: calc(12px * var(--sw-zoom)); color: var(--t2); }
.sw-bericht pre {
  margin: 6px 0 0; padding: var(--space-3); max-height: 18em; overflow: auto;
  white-space: pre-wrap; overflow-wrap: anywhere; font: inherit; font-size: calc(12px * var(--sw-zoom)); color: var(--t2);
  background: color-mix(in srgb, var(--ink) 5%, transparent);
}
.sw-acties { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin-top: var(--space-2); }
.sw-lijstrij .sw-acties { margin-top: 0; flex: none; justify-content: flex-end; }
.sw-linkbtn.c-crit { border-color: var(--crit); }
.sw-linkbtn:disabled { opacity: .4; cursor: not-allowed; }
.sw-linkbtn:disabled:hover { background: transparent; color: var(--t2); }
/* Het automatisch geblokkeerde deel van een dag in de spamgrafiek: donkerder op dezelfde staaf. */
svg.sw-vbar rect.auto { fill: var(--crit); }
.sw-melding { padding: var(--space-3) var(--space-4); font-size: calc(12.5px * var(--sw-zoom)); border-left: 3px solid var(--ok); }
.sw-melding--fout { border-left-color: var(--crit); }
.sw-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--space-3); }
.sw-form label {
  display: flex; flex-direction: column; gap: 4px;
  font-family: var(--font-heading); font-size: calc(10.5px * var(--sw-zoom)); letter-spacing: .1em; text-transform: uppercase; color: var(--t4);
}
.sw-form input {
  font: inherit; font-size: calc(13px * var(--sw-zoom)); color: var(--ink);
  background: color-mix(in srgb, var(--ink) 5%, transparent); border: 1px solid var(--t5); padding: 8px 10px; min-height: 36px;
}
.sw-form input:disabled { opacity: .5; }
@media (max-width: 760px) {
  .sw-lijstrij { flex-direction: column; }
  .sw-lijstrij .sw-acties { justify-content: flex-start; }
}

/* ── Het paneel 112 · P2000-meldingen van 112radar.nl ────────────────────────
   Dezelfde kaarten en dezelfde kleuren als de rest; alleen de meldingregel is nieuw. Links een
   vast blokje met de prioriteitscode, zodat het oog langs één kolom kan lopen in plaats van in
   elke regel te moeten zoeken. Rechts de tijd, want dat is het tweede waar je naar kijkt. */
/* Eén regel per melding: tijd, prioriteit, discipline, de tekst en de plaats. Vaste kolommen voor
   alles wat kort is, zodat het oog langs één lijn kan lopen; de tekst krijgt wat overblijft en de
   plaats staat rechts. Zo passen er ruim twee keer zoveel meldingen in beeld als toen elke melding
   drie regels innam, en dat was precies het punt: dit is een overzicht. */
.sw-112rij {
  display: grid; align-items: center; gap: var(--space-3);
  grid-template-columns:
    calc(56px * var(--sw-zoom))
    calc(46px * var(--sw-zoom))
    calc(20px * var(--sw-zoom))
    minmax(0, 1fr)
    minmax(0, calc(190px * var(--sw-zoom)));
  padding: calc(7px * var(--sw-zoom)) 0;
}
.sw-112prio {
  min-width: 0;
  font-family: var(--font-heading); font-weight: 600; font-size: calc(11.5px * var(--sw-zoom));
  letter-spacing: .06em; text-align: center;
  padding: 2px 4px; border: 1px solid currentColor;
  background: color-mix(in srgb, currentColor 12%, transparent);
}
.sw-112tijd {
  min-width: 0;
  font-variant-numeric: tabular-nums; font-size: calc(12px * var(--sw-zoom)); color: var(--t3);
}
/* De datum staat alleen bij een melding die niet van vandaag is; zie de regelpartial. Onder de tijd
   en niet ernaast: naast elkaar zou de kolom voor elke rij breder moeten worden, ook op een scherm
   waar alles van vandaag is. */
.sw-112tijd .dag { display: block; font-size: calc(10.5px * var(--sw-zoom)); color: var(--t4); }
.sw-112merk { display: inline-flex; align-items: center; }
/* De tekst blijft op één regel. Een melding die niet past wordt afgekapt met een echte ellips; het
   hele verhaal staat in het venster dat opengaat als je erop klikt. */
.sw-112tekst {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: calc(13px * var(--sw-zoom));
}
.sw-112plaats {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  text-align: right; font-size: calc(12px * var(--sw-zoom)); color: var(--t3);
}
/* Weggefilterd door de balk erboven. Een klasse en geen `style.display`: de CSP van InfraOps staat
   geen inline stijl toe, ook niet vanuit JavaScript. */
.sw-112rij.is-weg { display: none; }

/* De filterbalk boven de lijst. */
.sw-112filterbalk {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3);
}
.sw-112chips { display: flex; flex-wrap: wrap; gap: calc(6px * var(--sw-zoom)); }
.sw-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: calc(5px * var(--sw-zoom)) calc(10px * var(--sw-zoom));
  border: 1px solid var(--line); background: transparent; color: var(--t2);
  font: inherit; font-size: calc(12.5px * var(--sw-zoom)); cursor: pointer;
}
.sw-chip:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); }
.sw-chip:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
.sw-chip[aria-pressed="true"] {
  border-color: var(--acc); color: var(--ink);
  background: color-mix(in srgb, var(--acc) 14%, transparent);
}
/* Het zoekveld staat naast "In de buurt" en niet op een regel eronder: het is één balk. Het neemt
   de ruimte die overblijft, met een ondergrens zodat er altijd een half zinnetje in past. */
.sw-112zoek { display: flex; align-items: center; gap: 6px; flex: 1 1 calc(200px * var(--sw-zoom)); min-width: calc(150px * var(--sw-zoom)); }
.sw-112zoek .teken { flex: none; font-size: calc(12.5px * var(--sw-zoom)); }
.sw-112zoek input {
  flex: 1 1 auto; min-width: 0;
  padding: calc(5px * var(--sw-zoom)) calc(8px * var(--sw-zoom));
  border: 1px solid var(--line); background: transparent; color: var(--ink);
  font: inherit; font-size: calc(12.5px * var(--sw-zoom));
}
.sw-112zoek input:focus-visible { outline: 2px solid var(--acc); outline-offset: 1px; }

/* De filterbalk en de lijst in één kaart, gescheiden door een lijn in plaats van door ruimte.
   De kaart zelf heeft daarom geen padding meer: die zit per deel, anders telt hij dubbel. */
.sw-112hoofd { padding: 0; gap: 0; }
.sw-112deel { padding: var(--space-3) var(--space-4) var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.sw-112deel + .sw-112deel { border-top: 1px solid var(--line); }
/* EEN VAST GETAL EN GEEN `flex` MET `height: auto`. Dat laatste lijkt netter (dan volgt de grafiek
   de kaart eromheen precies), maar deze staaf is een SVG met een viewBox van 10 bij 100: zonder
   opgegeven hoogte pakt hij zijn eigen verhouding en wordt hij tien keer zo hoog als breed. Op een
   breed scherm is dat een grafiek van een halve meter. */
.sw-vchart--kort .sw-vbar { height: calc(84px * var(--sw-zoom)); }
.sw-112disckaart .sw-staafrij { padding: calc(2px * var(--sw-zoom)) 0; }
/* De uurgrafiek staat in de rechterkolom, dus vierentwintig staafjes op de smalle helft. Ze raken
   elkaar bijna: de tussenruimte gaat omlaag, de cijfers boven de staafjes gaan eruit (die stonden
   in elkaar), en van de uren blijft elk derde staan. De rest houdt zijn ruimte, zodat de staafjes
   even breed blijven. */
.sw-112uurkaart .sw-card-head .meta { white-space: nowrap; }
.sw-112uurkaart .sw-vchart { gap: calc(2px * var(--sw-zoom)); }
.sw-112uurkaart .sw-vval { display: none; }
.sw-112uurkaart .sw-vday { letter-spacing: 0; }
.sw-112uurkaart .sw-vcol .sw-vday { visibility: hidden; }
.sw-112uurkaart .sw-vcol:nth-child(3n + 1) .sw-vday,
.sw-112uurkaart .sw-vcol:last-child .sw-vday { visibility: visible; }

/* Elke kaart in die rij is zo hoog als zijn inhoud. Ze allebei op de hoogte van de langste zetten
   gaf een uurgrafiek met een handbreed niets eronder; dit is juist de kaart die korter moest. */
/* De filterkaart is een balk en geen kaart met inhoud: minder lucht dan de rest. */
/* De filterbalk is een balk en geen kaart met inhoud: minder lucht boven en onder. */
.sw-112deel.sw-112filter { padding-top: var(--space-3); padding-bottom: var(--space-3); }
.sw-112filter .sw-fijn { margin: var(--space-2) 0 0; }
/* Staat er niets te melden, dan neemt de regel ook geen hoogte in. */
.sw-112filter .sw-fijn.is-leeg { display: none; }
/* Wachten op je locatie: de knop staat aan maar er is nog geen punt. */
.sw-112buurt[aria-pressed="true"] { border-color: var(--acc); }
/* De bronvermelding is een afspraak met 112radar, geen voetnoot: hij mag opvallen en de link
   hoort als link te lezen. Op de pagina staat hij op één regel: de bron links, waar je hem voor
   moet houden rechts. */
.sw-112bronkaart { padding-top: var(--space-3); padding-bottom: var(--space-3); }
.sw-112bronregel {
  margin: 0; display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: space-between; gap: var(--space-2) var(--space-3);
  font-size: calc(13px * var(--sw-zoom)); color: var(--t2);
}
.sw-112bronregel a { color: var(--acc); text-decoration: underline; text-underline-offset: 2px; }
.sw-112bron { margin-top: var(--space-3); }
.sw-112bron a { color: var(--acc); text-decoration: underline; text-underline-offset: 2px; }
/* Op een telefoon past de regel niet meer op één lijn: het prioriteitsblokje en de tijd zouden dan
   met de tekst gaan wisselen van plek. Daar staan ze samen op de bovenste regel (code links, tijd
   rechts) en heeft de tekst de volle breedte eronder. `.sw-lijstrij` zet daar flex-direction op
   column; een raster negeert dat, dus de volgorde blijft staan zoals hij hoort. */
@media (max-width: 980px) {
  /* Onder de duizend pixels passen twee kaarten niet meer naast elkaar zonder dat de staafjes
     van de uurgrafiek strepen worden. */
}

@media (max-width: 760px) {
  /* OP EEN TELEFOON IS ELKE MELDING EEN KAARTJE (verzoek Theo, 18 september 2026: "echt app
     gevoel"). Bovenaan de meldingtekst zelf -- dat is waar je naar kijkt -- met de prioriteit als
     gekleurd blokje ervoor, en eronder de tijd, de dienst en de plaats als rustige regel. Een lijst
     met streepjes ertussen leest op 390 pixels als een spreadsheet; een kaartje per melding leest
     als een app, en je raakt hem makkelijker met je duim. */
  .sw-lijst .sw-112rij {
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: calc(8px * var(--sw-zoom)); row-gap: calc(6px * var(--sw-zoom));
    border: 0; border-radius: 14px;
    background: color-mix(in srgb, var(--ink) 6%, transparent);
    padding: calc(11px * var(--sw-zoom)) calc(12px * var(--sw-zoom));
    margin-bottom: calc(8px * var(--sw-zoom));
    align-items: start;
  }
  .sw-112prio {
    grid-column: 1; grid-row: 1;
    padding: 2px 7px; border-radius: 6px; font-weight: 600;
    background: color-mix(in srgb, currentColor 18%, transparent);
  }
  .sw-112tekst {
    grid-column: 2; grid-row: 1; white-space: normal;
    font-size: calc(13.5px * var(--sw-zoom)); line-height: 1.35; color: var(--ink);
  }
  /* Tijd, dienst en plaats staan als één rustige regel onder de tekst. */
  .sw-112tijd { grid-column: 1 / -1; grid-row: 2; color: var(--t4); }
  .sw-112merk { grid-column: 1 / -1; grid-row: 2; justify-self: start; margin-left: calc(52px * var(--sw-zoom)); }
  .sw-112plaats { grid-column: 1 / -1; grid-row: 2; justify-self: end; color: var(--t3); }
  .sw-112zoek { flex-basis: 100%; }
  /* De zes knoppen even breed in drie kolommen: zo staan ze in twee nette rijen in plaats van in
     drie rafelige, en is elke knop een fatsoenlijk raakvlak. Ze stonden eerst naast elkaar te
     vloeien op hun eigen tekstbreedte, en dan valt "In de buurt" als enige op een derde regel. */
  .sw-112chips {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: calc(6px * var(--sw-zoom)); width: 100%;
  }
  .sw-chip {
    justify-content: center; gap: 4px; min-height: 40px; padding: 4px 6px;
    font-size: calc(11.5px * var(--sw-zoom)); text-align: center; line-height: 1.15;
  }
}

/* ── Eén 112-melding uitgeklapt ──────────────────────────────────────────────
   Hetzelfde venster als de momentkaart, alleen wat breder: er staan twee kolommen in (links de
   kaart en de tijdlijn, rechts de eenheden en de rest). Op een telefoon vallen die onder elkaar. */
/* Het meldingvenster is het breedste dat dit scherm heeft: er staan twee kolommen in, en in de
   rechterkolom een tabel met eenheden die op 1120 pixels ging afbreken op "1 m 30 s". */
.sw-momentkaart--breed { width: min(1440px, 96vw); }
.sw-m112 { display: flex; flex-direction: column; gap: var(--space-4); }
.sw-m112-kop { display: flex; align-items: flex-start; gap: var(--space-3); }
.sw-m112-kop b { font-family: var(--font-heading); font-size: calc(17px * var(--sw-zoom)); letter-spacing: .04em; }
.sw-m112-body {
  margin: 0; padding: var(--space-3);
  background: color-mix(in srgb, var(--ink) 5%, transparent);
  border-left: 2px solid var(--acc);
  font-size: calc(13.5px * var(--sw-zoom)); line-height: 1.55;
}
.sw-m112-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-4); align-items: start; }
.sw-m112-kolom { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.sw-m112-blok > h2 {
  font-family: var(--font-heading); font-weight: 600; font-size: calc(12px * var(--sw-zoom));
  letter-spacing: .14em; text-transform: uppercase; color: var(--t3);
  margin: 0 0 var(--space-2); display: flex; align-items: baseline; gap: var(--space-2);
}
.sw-m112-blok > h2 .meta { font-family: var(--font-body); font-size: calc(11px * var(--sw-zoom)); letter-spacing: .06em; text-transform: none; color: var(--t4); }

/* De tijdlijn: tijd links in een vaste kolom, zodat je verticaal kunt lezen wanneer wat uitging. */
.sw-tijdlijn { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.sw-tijdlijn li { display: flex; gap: var(--space-3); padding: var(--space-2) 0; border-top: 1px solid color-mix(in srgb, var(--line) 60%, transparent); }
.sw-tijdlijn li:first-child { border-top: 0; }
.sw-tijdlijn .tijd { flex: 0 0 auto; font-variant-numeric: tabular-nums; font-size: calc(12.5px * var(--sw-zoom)); color: var(--t3); }
.sw-tijdlijn .tekst { min-width: 0; font-size: calc(12.5px * var(--sw-zoom)); line-height: 1.5; }
.sw-tijdlijn .tekst .sw-fijn { display: block; }

.sw-m112-sites { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.sw-m112-sites li { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.sw-m112-sites b { font-family: var(--font-heading); letter-spacing: .04em; }
.sw-m112-koppel { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.sw-m112-koppel li { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }

/* Het kaartje: één afbeelding die de server uit de tegels heeft samengesteld, met de speld er al in
   getekend. Daardoor is er hier niets te positioneren en staat er geen stijl in de HTML. */
.sw-kaart {
  display: block; width: 100%; max-width: 420px; height: auto; aspect-ratio: 420 / 240;
  border: 1px solid var(--line); background: color-mix(in srgb, var(--ink) 6%, transparent);
}

/* Een meldingregel is aanklikbaar; dat mag je ook zien en met het toetsenbord kunnen. */
.sw-112rij[data-sw-melding] { cursor: pointer; }
.sw-112rij[data-sw-melding]:hover { background: color-mix(in srgb, var(--ink) 5%, transparent); }
.sw-112rij[data-sw-melding]:focus-visible { outline: 2px solid var(--acc); outline-offset: -2px; }

@media (max-width: 860px) {
  .sw-m112-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ── 112: balken, siteverdeling en feitenblokjes ─────────────────────────────
   De balken zijn SVG en geen CSS-breedte: de CSP van InfraOps staat geen inline
   stijl toe, ook niet vanuit JavaScript, en een `width` op een rechthoek is een
   attribuut. Hetzelfde patroon als de staafgrafiek per uur. */
.sw-staven { display: flex; flex-direction: column; gap: 7px; }
.sw-staafrij {
  display: grid; grid-template-columns: minmax(0, 106px) minmax(0, 1fr) 46px;
  align-items: center; gap: 10px;
}
.sw-staafrij--site { grid-template-columns: minmax(0, 150px) minmax(0, 1fr) 40px 52px; }
.sw-staafrij .naam {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 13px; color: var(--t2);
}
.sw-staafrij .naam b { display: block; font-size: 13.5px; color: var(--t1); }
.sw-staafrij .naam .sw-fijn { display: block; }
.sw-staafrij .num { font-family: var(--font-heading); font-weight: 700; font-size: 15px; text-align: right; }
.sw-staafrij .nu { font-size: 11px; letter-spacing: .06em; text-align: right; text-transform: uppercase; }
.sw-staaf { display: block; width: 100%; height: 9px; }
.sw-staaf .spoor { fill: color-mix(in srgb, var(--ink) 8%, transparent); }
.sw-staaf .c-acc { fill: var(--acc); }
.sw-staaf .c-crit { fill: var(--crit); }
.sw-staaf .c-warn { fill: var(--warn); }
.sw-staaf .c-ok { fill: var(--ok); }
.sw-staaf .c-t3 { fill: var(--t3); }


/* ── 112-venster: feitenlijst, onbewerkt antwoord en de voet ─────────────────── */
.sw-m112-feiten {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
  gap: 2px 14px; margin: 0 0 14px;
}
.sw-m112-feiten > div {
  display: grid; grid-template-columns: minmax(0, 110px) minmax(0, 1fr); gap: 10px;
  padding: 5px 0; border-bottom: 1px solid var(--line-soft);
}
.sw-m112-feiten dt {
  font-family: var(--font-heading); font-size: 11px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--t3);
}
.sw-m112-feiten dd { margin: 0; font-size: 13.5px; color: var(--t1); overflow-wrap: anywhere; }

.sw-m112-rauw { margin-top: 14px; border-top: 1px solid var(--line); padding-top: 10px; }
.sw-m112-rauw > summary {
  cursor: pointer; font-family: var(--font-heading); font-size: 12px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--t2);
}
.sw-m112-rauw pre {
  margin: 8px 0 0; padding: 10px; max-height: 250px; overflow: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px; line-height: 1.5; white-space: pre;
  background: color-mix(in srgb, var(--ink) 4%, transparent);
}

/* De voet met vorige, volgende en sluiten. Raakvlakken van 44px, zodat het op een
   aanraakscherm ook werkt. */
.sw-m112-voet {
  display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end;
  margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--line);
}
.sw-m112-voet .sw-linkbtn { min-height: 44px; padding: 0 14px; }
.sw-linkbtn--pri { background: var(--ink); border-color: var(--ink); color: var(--ground); }
.sw-linkbtn--pri:hover { background: var(--ink); color: var(--ground); opacity: .88; }

/* ── 112: de meldinglijst loopt door tot onderaan het scherm ─────────────────
   Op een breed scherm mag de linkerkolom precies zo lang zijn als het beeld:
   dan blijven de kop, de statusstrip en de rechterkolom staan waar ze staan,
   en scrollt alleen de lijst. Zonder zichtbare balk, want die zou in dit
   ontwerp het enige zijn dat opvalt.

   Op smalle schermen doet dit niets: daar staan de kolommen onder elkaar en
   hoort de pagina gewoon te scrollen. Een lijst met een eigen scrolgebied
   binnen een pagina die zelf ook scrollt is op een telefoon niet te bedienen. */
@media (min-width: 1000px) {
  /* De lijst wordt begrensd door het scherm en niet door de rechterkolom. Meerekenen met
     de rechterkolom leek logisch -- even lang is netjes -- maar die is vier panelen hoog,
     dus de lijst schoot meters omlaag en dat was juist het probleem.

     De 200 pixels is een gekozen getal: de vastgezette kop plus wat lucht. Wordt de kop
     ooit hoger, dan is dit de enige plek waar het staat. */
  .sw-112lijstkaart { display: flex; flex-direction: column; }
  .sw-112lijstkaart > .sw-lijst {
    max-height: calc(100dvh - 200px); min-height: 320px; overflow-y: auto;
    /* Wel scrollen, geen balk: hetzelfde als de andere scrolgebieden hier. */
    scrollbar-width: none;
  }
  .sw-112lijstkaart > .sw-lijst::-webkit-scrollbar { width: 0; height: 0; }

  /* En de kop blijft staan, want daar ging het om: je wilt bij het doorlopen van de lijst
     kunnen zien waar je bent en wat de klok doet. Op smalle schermen deed hij dit al. */
  .sw-head {
    position: sticky; top: 0; z-index: 30;
    background: var(--ground);
    padding-bottom: var(--space-3);
  }
}

/* ── 112: disciplinetekens, kaart en wat afwerking ───────────────────────────── */
.sw-disc { flex: 0 0 auto; width: 15px; height: 15px; }
.sw-discregel { display: inline-flex; align-items: center; gap: 6px; }
.sw-staafrij .naam.sw-discregel { display: flex; }

/* Het vak waar de kaart in staat. De plaatsregel en de bronvermelding liggen eroverheen, dus
   `position: relative`; de hoogte staat hier, want een kaart heeft er zelf geen. */
.sw-osm { position: relative; border: 1px solid var(--line); overflow: hidden; }
/* Leaflet vult dit vak. Vaste verhouding en niet een vaste hoogte: dan blijft de kaart op een
   telefoon een kaart en niet een streep. `saturate` houdt hem rustig onder de rest van het scherm;
   de speld en de lijn houden hun eigen kleur, want die staan er niet ingebakken maar bovenop. */
.sw-osm-kaart {
  position: relative; display: block; width: 100%; aspect-ratio: 760 / 420;
  max-height: calc(420px * var(--sw-zoom)); background: var(--surface, var(--ground));
}
.sw-osm-kaart .leaflet-tile-pane { filter: saturate(.6); }
/* De statische kaart staat meteen klaar en blijft liggen tot de interactieve kaart geladen is. */
.sw-osm-plaatje { display: block; width: 100%; height: auto; border: 0; filter: saturate(.6); }
.sw-osm-kaart > .sw-osm-plaatje { position: absolute; inset: 0; height: 100%; object-fit: cover; z-index: 800; pointer-events: none; }
.sw-osm-kaart.is-interactief > .sw-osm-plaatje { display: none; }
.sw-112eerder { padding: var(--space-4); }
.sw-112eerder h2 { margin: 0 0 var(--space-2); }
.sw-112eerder ul { margin: 0; padding-left: var(--space-4); }
.sw-112eerder li + li { margin-top: var(--space-2); }

/* De twee merkjes op de kaart. Dezelfde kleuren als de legenda eronder (`.sw-ritmerk`), en ze
   staan hier omdat de CSP geen stijlregel vanuit JavaScript toelaat behalve wat Leaflet zelf zet. */
.sw-kaartmerk__stip {
  display: block; width: 12px; height: 12px; margin: 2px;
  border: 2px solid var(--ground); border-radius: 50%;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--ink) 35%, transparent);
}
.sw-kaartmerk__stip--melding { background: #d1495b; }
.sw-kaartmerk__stip--kazerne { background: #5c96c7; }

/* De bronvermelding van OpenStreetMap hoort in beeld te staan, maar hoeft niet te schreeuwen. */
.sw-osm .leaflet-control-attribution {
  background: color-mix(in srgb, var(--ground) 88%, transparent);
  color: var(--t2); font-size: 11px;
}
.sw-osm .leaflet-control-attribution a { color: var(--t2); }
.sw-osm .leaflet-bar a {
  background: color-mix(in srgb, var(--ground) 92%, transparent);
  border-bottom-color: var(--line); color: var(--t1);
}
.sw-osm .leaflet-bar a:hover { background: var(--ground); color: var(--acc); }

/* De regel onder de kaart: welke post, welke eenheid, en hoe lang hij onderweg was. */
.sw-m112-rit { margin: var(--space-2) 0 0; display: flex; align-items: center; flex-wrap: wrap; gap: 6px; font-size: calc(12.5px * var(--sw-zoom)); color: var(--t2); }
.sw-m112-rit b { font-family: var(--font-heading); color: var(--t1); }
.sw-ritmerk { flex: none; width: 11px; height: 11px; border: 2px solid var(--ground); }
.sw-ritmerk--kazerne { background: #5c96c7; }
.sw-osm-speld {
  position: absolute; top: 50%; left: 50%; width: 14px; height: 14px; margin: -7px 0 0 -7px;
  border: 2px solid var(--ground); border-radius: 50%; background: currentColor;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--ink) 35%, transparent);
  pointer-events: none;
}
.sw-osm-speld::after {
  content: ""; position: absolute; inset: -9px; border: 1px solid currentColor; border-radius: 50%;
  opacity: .55; animation: swPuls 2.4s ease-out infinite;
}
@keyframes swPuls {
  0% { transform: scale(.55); opacity: .75; }
  100% { transform: scale(1.35); opacity: 0; }
}
/* De plaatsregel ligt óp de kaart en moet dus boven de kaartlagen staan. Leaflet legt zijn panes
   op z-index 400 en hoger; zonder een eigen waarde verdwijnt dit label erachter en staat er ineens
   geen straatnaam meer bij een melding. Onder de knoppen blijven (die zitten op 800), want die moet
   je kunnen indrukken. */
.sw-osm-plek {
  position: absolute; left: 10px; bottom: 10px; z-index: 500; max-width: calc(100% - 20px); padding: 6px 9px;
  background: color-mix(in srgb, var(--ground) 88%, transparent);
  border: 1px solid var(--line); font-size: 12px; color: var(--t2); pointer-events: none;
}
.sw-osm-plek b { display: block; font-family: var(--font-heading); font-size: 13.5px; color: var(--t1); }

@media (prefers-reduced-motion: reduce) {
  .sw-osm-speld::after { animation: none; }
}

/* Het disciplinemerk: een getint vierkantje met een lijnteken erin, naast de
   prioriteitsbadge. Zo zie je in één oogopslag wie er is gealarmeerd, ook op een
   scherm aan de muur. Geen echte logo's: die van politie, brandweer en
   ambulancezorg zijn beschermde merken, en op een dashboard van derden wekken ze
   bovendien de indruk van een officieel verband. De vormen verschillen genoeg om
   ook zonder kleur uit elkaar te houden. */
.sw-discmerk {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto; width: 22px; height: 22px;
  /* Geen randje en geen tint meer om het teken heen: sinds het teken een emoji is (dezelfde als op
     de filterknoppen erboven) zit de kleur al in het teken zelf, en een vakje eromheen maakt er een
     badge van die met de prioriteitsbadge ernaast gaat concurreren. */
  font-size: 14px; line-height: 1;
  /* DIT VOORKOMT EEN PAGINA VAN DRIE METER. In het merk zit een `sw-visually-hidden`-label met de
     naam van de discipline, voor een schermlezer. Dat label staat op `position: absolute`, en een
     absoluut geplaatst element hangt aan de dichtstbijzijnde ouder die zelf een positie heeft.
     Stond die er niet, dan hing het aan de pagina -- en dan telt het mee voor de hoogte van de
     pagina, ook al zit het in de lijst die op zevenhonderd pixels wordt afgeknipt. Veertig
     meldingen gaven zo veertig labels tot drieduizend pixels diep, en de pagina scrolde door tot
     3695 pixels terwijl de inhoud op 1219 ophield. Theo zag dat op 9 september 2026: "pagina
     scrolt nog wel eindeloos door". Eén regel is genoeg: nu hangt het label aan dit vakje van 22
     bij 22 en komt het nergens meer buiten. */
  position: relative;
}
.sw-discmerk svg { width: 14px; height: 14px; }
.sw-staafrij .sw-discmerk { width: 19px; height: 19px; font-size: 13px; }
.sw-staafrij .sw-discmerk svg { width: 12px; height: 12px; }


/* ── Het meldingvenster naar het ontwerp ────────────────────────────────────── */
/* Iets ruimer dan het standaardvenster: er staan twee kolommen in plus een kaart.

   En een váste hoogte. De ene melding heeft drie alarmeringen, vier eenheden en het weer,
   de andere alleen een regel tekst. Zonder vaste hoogte veranderde het venster bij elke
   pijltjestoets van formaat en sprong de pagina eronder mee -- bij het doorlopen van een
   lijst is dat het ergste wat een venster kan doen. Nu is elk venster even groot en
   scrollt alleen de inhoud, zonder zichtbare balk. */
/* Het meldingvenster is het breedste dat dit scherm heeft: twee kolommen, een kaart en een tabel
   met eenheden. Deze regel staat ná `--breed` en wint dus; ze allebei op 1560 zetten zou twee
   plekken zijn waar dezelfde maat staat, dus hier staat hij en `--breed` is voor de rest. */
.sw-momentkaart--112 { width: min(1560px, 96vw); position: relative; }

@media (min-width: 761px) {
  /* Hoger dan eerst (was 86dvh / 940px). In dat venster staan een kaart, de eenheden, de tijdlijn
     en onderaan de knoppen om naar de vorige of volgende melding te gaan -- en juist die knoppen
     vielen er meestal onder. Nu past het meestal in één beeld. */
  .sw-momentkaart--112 { height: min(94dvh, 1100px); }
  .sw-momentkaart--112 > .sw-momentbody {
    flex: 1 1 auto; min-height: 0; overflow-y: auto; scrollbar-width: none;
  }
  .sw-momentkaart--112 > .sw-momentbody::-webkit-scrollbar { width: 0; height: 0; }
  /* De laag hoeft dan zelf niet te scrollen; het venster staat midden in beeld. De klasse
     komt van het script en niet van `:has()`, want dat is één ding minder om op te
     vertrouwen. Op een telefoon blijft het venster schermvullend zoals het al was. */
  .sw-momentlaag--112 { align-items: center; overflow: hidden; }
}
/* Dezelfde hoekmarkeringen als de panelen eronder, zodat het venster bij de rest hoort. */
.sw-momentkaart--112 > .corner { position: absolute; z-index: 2; }

/* Een korte lift bij het openen. Kort genoeg om niet in de weg te zitten, lang genoeg om te zien
   wáár het venster vandaan komt.

   GEEN FADE OP HET VENSTER ZELF. Dat stond hier wel (`opacity: 0` naar `1`), en op een telefoon
   bleef de kaart halverwege hangen: gemeten op 11 september 2026 stond hij op 0,63 en keek je dwars
   door het venster heen naar de lijst eronder. Een animatie die bepaalt óf je de inhoud kunt lezen
   is er één te veel -- als hij hapert, hapert het scherm. De lift doet hetzelfde werk en kan niets
   kapotmaken: blijft hij halverwege staan, dan staat het venster tien pixels lager en verder niets.

   En het venster is altijd dekkend, ook tijdens de lift: het vult op een telefoon het hele scherm,
   dus alles wat erdoorheen schemert is de pagina eronder. */
@media (prefers-reduced-motion: no-preference) {
  .sw-momentkaart--112 { animation: swVensterOp .22s ease-out both; }
  @keyframes swVensterOp {
    from { transform: translateY(10px); }
    to { transform: none; }
  }
}
.sw-momentkaart { opacity: 1; }

/* De melding zoals hij binnenkwam: de ruwe P2000-regel in monospace op een lichte
   ondergrond. Dat is de tekst die de pieper liet zien, en die hoort er ook uit te
   zien als een pieperregel en niet als lopende tekst. */
.sw-m112-ruw {
  margin: 0 0 14px; padding: 10px 12px;
  background: color-mix(in srgb, var(--ink) 4%, transparent);
  border-left: 2px solid var(--line);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px; line-height: 1.55; overflow-wrap: anywhere;
}

/* De tijdlijn krijgt een lijn aan de linkerkant, zodat je ziet dat het één reeks is. */
.sw-tijdlijn { position: relative; padding-left: 14px; }
.sw-tijdlijn::before {
  content: ""; position: absolute; left: 3px; top: 4px; bottom: 4px;
  border-left: 1px solid var(--line);
}
.sw-tijdlijn > li { position: relative; }
.sw-tijdlijn > li::before {
  content: ""; position: absolute; left: -14px; top: 7px; width: 5px; height: 5px;
  margin-left: 1px; border-radius: 50%; background: var(--t3);
}

/* Roepnummers in monospace: dat zijn codes, geen woorden, en ze lezen alleen goed
   als de cijfers onder elkaar staan. */
.sw-tabel .roep {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12.5px;
}

/* De pagina staat stil zolang er een venster openstaat. `overflow: hidden` op het
   wortelelement en niet op de body: dat werkt ook op iOS, waar de body zelf niet
   de scroller is. */
html.sw-vast { overflow: hidden; }

/* De kop boven de pieperregel, in dezelfde toon als de andere blokkoppen. */
.sw-m112-ruwkop {
  margin: 0 0 6px; font-family: var(--font-heading); font-size: 11.5px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--t3);
}

/* ── Het nieuwspaneel ────────────────────────────────────────────────────────
   Nieuwsblokken met de foto van de uitgever erbij: beeld, bron, tijdstip, kop, twee regels
   samenvatting. Een raster dat meegroeit met de breedte, want deze lijst staat op een telefoon
   onder elkaar en op een breed scherm naast elkaar.

   VASTE VERHOUDINGEN OP HET BEELD. De foto's komen van de servers van de uitgevers en druppelen
   binnen terwijl je al leest; zonder `aspect-ratio` en vaste hoogte springt de hele lijst bij elke
   foto die aankomt. Het vak is er dus al voordat het plaatje er is. */
.sw-nieuwsraster {
  display: grid; gap: var(--space-3);
  grid-template-columns: repeat(auto-fill, minmax(calc(240px * var(--sw-zoom)), 1fr));
}
.sw-nieuwskaart {
  display: flex; flex-direction: column; min-width: 0;
  border: 1px solid var(--line); background: color-mix(in srgb, var(--ink) 2%, transparent);
}
.sw-nieuwskaart.is-weg { display: none; }
.sw-nieuwsbeeld {
  display: grid; place-items: center; aspect-ratio: 16 / 9; overflow: hidden;
  background: color-mix(in srgb, var(--ink) 7%, transparent);
  border-bottom: 1px solid var(--line);
}
/* Een bron zonder foto in zijn feed krijgt zijn naam in datzelfde vak: het raster blijft recht,
   en er staat niets wat er niet is. */
.sw-nieuwsbeeld b {
  padding: 0 var(--space-3); text-align: center;
  font-family: var(--font-heading); font-size: calc(12px * var(--sw-zoom));
  font-weight: 500; color: var(--t4); letter-spacing: .06em; text-transform: uppercase;
}
.sw-nieuwsbeeld img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* Iets gedempt, zodat een felle persfoto niet met het scherm vecht; scherper zodra je hem
     aanwijst, want dan gaat je aandacht erheen. */
  filter: saturate(.85) brightness(.92); transition: filter .18s ease;
}
.sw-nieuwskaart:hover .sw-nieuwsbeeld img { filter: none; }
.sw-nieuwskop { display: flex; flex-direction: column; gap: 4px; padding: var(--space-3); min-width: 0; }
.sw-nieuwsmeta {
  display: flex; justify-content: space-between; gap: var(--space-2);
  font-size: calc(11px * var(--sw-zoom)); color: var(--t4);
}
.sw-nieuwsmeta b { font-weight: 500; color: var(--t3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sw-nieuwsmeta time { white-space: nowrap; font-variant-numeric: tabular-nums; }
.sw-nieuwskop h3 {
  margin: 0; font-family: var(--font-heading); font-size: calc(14px * var(--sw-zoom));
  line-height: 1.3; font-weight: 500;
  /* Drie regels kop: een uitgever met een lange kop mag het blok niet twee keer zo hoog maken. */
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.sw-nieuwskop h3 a { color: var(--ink); text-decoration: none; }
.sw-nieuwskop h3 a:hover { text-decoration: underline; }
.sw-nieuwskop p {
  /* Twee regels samenvatting; wie meer wil klikt door naar de uitgever. Een feed die er vijf
     alinea's in stopt zou anders één blok een half scherm geven. `-webkit-box` is wat elke
     browser hiervoor begrijpt, ook de niet-webkit-browsers. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  margin: 0; font-size: calc(11.5px * var(--sw-zoom)); color: var(--t3); line-height: 1.45;
}

@media (max-width: 760px) {
  /* OP EEN TELEFOON LEEST NIEUWS ALS EEN APP (verzoek Theo, 18 september 2026: "echt app gevoel").
     Bovenaan één grote kaart met de foto en de kop eroverheen -- dat is het bericht waar je mee
     begint -- en daaronder rijen met een miniatuur links en de kop rechts. Dat is de vorm die elke
     nieuwsapp gebruikt, en met een reden: op 390 pixels kost een volle foto per bericht drie
     schermen scrollen voor vier koppen.

     De samenvatting valt weg op deze breedte. Twee regels kop plus bron en tijd is wat je nodig
     hebt om te beslissen of je doorklikt; de rest staat bij de uitgever. */
  .sw-nieuwsraster { grid-template-columns: minmax(0, 1fr); gap: calc(10px * var(--sw-zoom)); }

  .sw-nieuwskaart {
    flex-direction: row; align-items: stretch;
    border: 0; border-radius: 14px; overflow: hidden;
    background: color-mix(in srgb, var(--ink) 6%, transparent);
  }
  .sw-nieuwsbeeld {
    flex: 0 0 calc(96px * var(--sw-zoom)); aspect-ratio: 1 / 1;
    border-bottom: 0; border-radius: 12px; margin: 8px 0 8px 8px;
  }
  .sw-nieuwsbeeld img { filter: none; }
  .sw-nieuwsbeeld b { font-size: calc(10px * var(--sw-zoom)); }
  .sw-nieuwskop { padding: 10px 12px; gap: 5px; justify-content: center; }
  .sw-nieuwskop h3 { font-size: calc(14.5px * var(--sw-zoom)); -webkit-line-clamp: 2; }
  .sw-nieuwskop p { display: none; }
  .sw-nieuwsmeta { font-size: calc(11px * var(--sw-zoom)); }
  .sw-nieuwsmeta b { font-style: italic; }

  /* Het eerste bericht als grote kaart, met de kop over de foto heen. */
  .sw-nieuwsraster > .sw-nieuwskaart:first-child {
    position: relative; flex-direction: column; border-radius: 16px;
  }
  .sw-nieuwsraster > .sw-nieuwskaart:first-child .sw-nieuwsbeeld {
    flex: none; width: 100%; aspect-ratio: 16 / 10; margin: 0; border-radius: 16px;
  }
  .sw-nieuwsraster > .sw-nieuwskaart:first-child .sw-nieuwskop {
    position: absolute; inset: auto 0 0 0; padding: 14px;
    background: linear-gradient(to top, rgb(0 0 0 / 88%), rgb(0 0 0 / 45%) 55%, rgb(0 0 0 / 0%));
  }
  .sw-nieuwsraster > .sw-nieuwskaart:first-child h3 {
    font-size: calc(17px * var(--sw-zoom)); -webkit-line-clamp: 3; color: #fff;
  }
  .sw-nieuwsraster > .sw-nieuwskaart:first-child h3 a { color: #fff; }
  .sw-nieuwsraster > .sw-nieuwskaart:first-child .sw-nieuwsmeta b,
  .sw-nieuwsraster > .sw-nieuwskaart:first-child .sw-nieuwsmeta time { color: rgb(255 255 255 / 82%); }
}

/* De knoppenrij onder een melding: alleen op een telefoon, waar je hem in elke app onderaan
   verwacht. Op een breed scherm staat de kaart al groot in beeld. */
.sw-m112-acties { display: none; }

@media (max-width: 760px) {
  .sw-m112-acties {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: calc(8px * var(--sw-zoom));
    margin-top: var(--space-3); padding-top: var(--space-3);
    border-top: 1px solid var(--line);
  }
  .sw-m112-actie {
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    padding: calc(10px * var(--sw-zoom)) 4px;
    border-radius: 12px; background: color-mix(in srgb, var(--ink) 7%, transparent);
    color: var(--t2); text-decoration: none;
    font-size: calc(11px * var(--sw-zoom)); letter-spacing: .06em;
  }
  .sw-m112-actie span { font-size: calc(17px * var(--sw-zoom)); line-height: 1; }
  .sw-m112-actie:active { background: color-mix(in srgb, var(--acc) 22%, transparent); }

  /* De kaart bovenaan, zoals in elke meldingenapp: dat is het eerste dat je wilt zien. De feiten
     eronder; die lees je pas als je weet waar het is. */
  .sw-m112 { display: flex; flex-direction: column; }
  /* De volgorde staat er helemaal uitgeschreven: zet je er maar een paar, dan belandt alles zonder
     eigen nummer op nul en schuift de kop onder de kaart. */
  .sw-m112-kop { order: 1; }
  .sw-m112-grid { order: 2; }
  .sw-m112-ruwkop { order: 3; }
  .sw-m112-ruw { order: 4; }
  .sw-m112-feiten { order: 5; }
  .sw-m112-acties { order: 6; }
  .sw-m112-pagina { order: 7; }
  .sw-m112-rauw { order: 8; }
}

/* ── De eigen pagina van één melding ─────────────────────────────────────────
   Dezelfde kaarten als het venster, met een kop erboven die zegt waar je bent. Dit is de pagina
   die je deelt en die een zoekmachine leest, dus hij begint met een echte <h1> en een kruimelpad
   in plaats van met een vensterbalk. */
.sw-meldingpagina { padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); }
.sw-meldingpagina h1 {
  margin: 0; font-family: var(--font-heading); font-size: calc(22px * var(--sw-zoom));
  line-height: 1.2; letter-spacing: -.01em; color: var(--ink);
}
.sw-kruimels { font-size: calc(11.5px * var(--sw-zoom)); color: var(--t4); }
.sw-kruimels a { color: var(--t3); }
.sw-kruimels a:hover { color: var(--ink); }

/* De weg naar die pagina, onderaan in het venster. */
.sw-m112-pagina { margin: var(--space-4) 0 0; padding-top: var(--space-3); border-top: 1px solid var(--line); }
.sw-m112-pagina a { color: var(--acc); font-size: calc(13px * var(--sw-zoom)); }

/* ── De filterlijsten rechts op het nieuwsscherm ───────────────────────────────
   Alle bediening staat rechts (verzoek van Theo, 11 september 2026): links alleen
   berichten, rechts drie manieren om erin te kijken -- per bron, per gebied en
   per site -- elk met het aantal erbij en elk klikbaar.

   Een echte `<button>` en geen rij met een klikhandler: dan levert de browser
   Enter, spatie, de focusring en de knoprol zelf. De staaf erin blijft precies de
   staaf die er bij de andere verdelingen ook staat, zodat het scherm één stelsel
   houdt. */
/* Een bredere naamkolom dan bij de gewone verdelingen: hier staan uitgeversnamen en
   domeinen ("Noordhollands Dagblad", "wieringerwerf.nl"), en die moet je kunnen lezen
   voordat je erop klikt. De rechterkolom heeft de ruimte. */
/* DE NAAM KRIJGT DE RUIMTE DIE OVERBLIJFT, NIET DE STAAF.
   De naamkolom stond vast op 168 pixels en de staaf pakte al het andere. Op een breed scherm gaf
   dat een staaf van vijfhonderd pixels naast "Belangen Vereniging Julian...", terwijl zo'n staaf
   niets meer vertelt dan eentje van driehonderd: het gaat om de verhouding, niet om de lengte.
   De bovengrens is de kleinste van 250 pixels en 45% van de regel. Kaal 250 liet op een telefoon
   een staaf van vijftien pixels over; kaal 45% was op een middelbreed paneel weer te weinig voor
   de langste bronnaam. Zo groeit de naam mee tot hij past, neemt hij nooit meer dan de helft, en
   houdt de ondergrens van 168 het smalle scherm precies zoals het was. */
.sw-filterstaven .sw-filterrij {
  display: grid;
  grid-template-columns: minmax(140px, min(210px, 46%)) minmax(0, 1fr) 40px;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: calc(2px * var(--sw-zoom)) calc(4px * var(--sw-zoom));
  margin: 0;
  text-align: left;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: pointer;
  font: inherit;
  color: inherit;
}

.sw-filterstaven .sw-filterrij:hover {
  background: var(--paper2, rgba(128, 128, 128, 0.1));
}

.sw-filterstaven .sw-filterrij:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: -2px;
}

/* Aangeklikt: een rand en een zwaardere naam. Geen vlak in een steunkleur -- de staaf
   erin draagt al kleur, en twee gekleurde vlakken over elkaar wordt onrustig. */
.sw-filterstaven .sw-filterrij.is-aan {
  border-color: var(--ink, currentColor);
  background: var(--paper2, rgba(128, 128, 128, 0.1));
}

.sw-filterstaven .sw-filterrij.is-aan .naam {
  color: var(--ink, currentColor);
  font-weight: 700;
}

.sw-filterstaven .sw-filterrij .naam {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
  color: var(--t2);
}

.sw-filterstaven .sw-filterrij .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-size: 12.5px;
}

/* TWEE KOLOMMEN ZODRA ER RUIMTE IS.
   Deze lijsten worden lang: twintig bronnen en tien gebieden onder elkaar is een halve pagina
   scrollen voor iets wat bedoeld is als overzicht (Theo, 16 september 2026: "maak je ze ook nog
   smaller de stats zo dat het allemaal in beeld past"). Naast elkaar halveert dat zonder dat er
   iets wegvalt.

   De grens ligt op 1500: daaronder staat de rechterkolom er nog wel, maar is hij smal genoeg dat
   twee namen naast elkaar allebei zouden afkappen, en dan lees je niets meer. Onder de 1200 valt
   het raster sowieso terug op één kolom. */
@media (min-width: 1500px) {
  .sw-filterstaven {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 18px;
  }
}

/* Een bron die een fout gaf. Het uitroepteken staat naast de naam, zodat je in de lijst meteen
   ziet wélke bron het is; de reden staat in de kaart erboven en in de tooltip. */
.sw-bronfout {
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 14px; margin-left: 5px;
  border: 1px solid var(--warn, currentColor); border-radius: 50%;
  color: var(--warn, currentColor); font-size: 10px; font-weight: 700; line-height: 1;
}
.sw-filterstaven .sw-filterrij.is-bronfout .naam { color: var(--warn, currentColor); }

/* Of we van deze uitgever toestemming hebben. Zelfde maat en plek als het uitroepteken hierboven,
   zodat de twee merkjes naast elkaar niet gaan schelen. Vier standen, en alle vier zeggen iets: een
   vinkje dat het mag, een vinkje met een uitroepteken dat het mag zonder foto, een kruisje dat het
   niet mag, en drie puntjes dat we het gevraagd hebben maar nog niets hoorden. Staat er niets, dan
   is er ook nog niets gevraagd. */
.sw-toestemming {
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 14px; margin-left: 5px;
  border: 1px solid currentColor; border-radius: 50%;
  font-size: 9px; font-weight: 700; line-height: 1;
}
.sw-toestemming.is-ja { color: var(--ok, currentColor); }
.sw-toestemming.is-nee { color: var(--crit, currentColor); }
.sw-toestemming.is-gevraagd { color: var(--t2, currentColor); border-style: dashed; }
/* Toestemming zonder foto's: het vinkje met een klein oranje uitroepteken rechtsboven. Samen in één
   groep, zodat een afgekapte naam ze samen laat wegvallen: een los uitroepteken is hier al "deze bron
   gaf een fout". Het uitroepteken steekt 2 px boven het vinkje uit; de naamkolom knipt af wat meer
   dan ongeveer 3 px boven de regel komt. De ruimte rechts houdt het foutmerkje erachter los. */
.sw-toestemming-groep { position: relative; display: inline-flex; }
.sw-toestemming-groep.is-zonderfoto { padding-right: 5px; }
.sw-toestemming-let {
  position: absolute; top: -2px; right: 0;
  display: inline-flex; align-items: center; justify-content: center;
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--warn, currentColor); color: var(--panel, #fff);
  font-size: 7px; font-weight: 800; line-height: 1;
}

/* De uitlegballon bij een merkje (`data-sw-uitleg`, zie sitewatch.js): meteen bij de muis, en op een
   telefoon bij een tik. Eén ballon voor de hele pagina, vast in beeld geplaatst, zodat een kolom die
   afknipt (de naamkolom hierboven) hem niet raakt. De eerste regel is de kop. */
.sw-uitleg {
  position: fixed; z-index: 2000; left: 0; top: 0;
  max-width: min(300px, calc(100% - 16px));
  padding: 9px 11px; border-radius: 8px;
  background: var(--panel2); color: var(--ink);
  border: 1px solid var(--line);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .28);
  font-size: 12.5px; font-weight: 400; line-height: 1.45; letter-spacing: normal;
  text-align: left; text-transform: none; white-space: pre-line;
}
.sw-uitleg::first-line { font-weight: 700; }
.sw-uitleg[hidden] { display: none; }
[data-sw-uitleg] { cursor: help; }
/* Op een aanraakscherm: Safari op een iPhone stuurt een tik op een gewone span alleen door als het
   element er klikbaar uitziet. */
@media (hover: none) {
  [data-sw-uitleg] { cursor: pointer; }
}

/* Een bron die aanstaat maar niets levert. Geen knop: erop klikken zou een lege lijst geven en dat
   leest als een storing. Wat er in plaats van de staaf staat is de maand van het laatste bericht. */
.sw-filterrij.is-stil { opacity: .62; cursor: default; }
.sw-filterrij.is-stil .num { font-variant-numeric: normal; font-size: 11.5px; color: var(--t2); }

.sw-bronfoutlijst { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.sw-bronfoutlijst li { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: 12.5px; color: var(--t2); }
.sw-bronfoutlijst li b { font-family: var(--font-heading); color: var(--t1); }

/* Het zoekveld staat nu in de rechterkolom en vult die helemaal.

   `flex: 0 0 auto` is hier geen franje. `.sw-112zoek` draagt `flex: 1 1 200px`, en dat was de
   BREEDTE zolang hij in de filterbalk stond -- een rij. In de kaart hiernaast is de flexrichting een
   kolom, en dan wordt diezelfde 200px de HOOGTE: een zoekveld van twee centimeter hoog met een
   invoerregel ergens in het midden. Gemeten: kaart 260 px hoog waarvan 200 voor het veld. */
.sw-nieuwszoekveld {
  flex: 0 0 auto;
  width: 100%;
  margin-top: calc(6px * var(--sw-zoom));
}


.sw-tekstknop {
  padding: 0;
  background: none;
  border: 0;
  font: inherit;
  color: inherit;
  text-decoration: underline;
  cursor: pointer;
}

/* ── Het venster van één melding: meelopen ─────────────────────────────────────
   Slepen en zoomen doet Leaflet zelf, inclusief de muisaanwijzer en het aanraakgedrag. Wat hier
   stond regelde dat voor de getekende afbeelding en is daarmee vervallen. */

/* Wisselen van melding terwijl het venster openblijft: kort wegfaden en weer terug.
   Het venster zelf opnieuw opbouwen zou een flits geven -- laag weg, laag terug -- en
   dat elke keer dat er een melding binnenkomt. */
.sw-momentbody { transition: opacity 0.16s ease-out; }
.sw-momentbody.is-wisselt { opacity: 0.28; }

@media (prefers-reduced-motion: reduce) {
  .sw-momentbody,
  .sw-osm .sw-osm-kaart { transition: none; }
}

/* De knoppen "vorige" en "volgende" plakken onderaan het venster.

   Hoger maken was niet genoeg: een melding mét kaart, eenheden en tijdlijn heeft altijd meer
   inhoud dan er past, en dan valt juist de knop waarmee je verder wilt eronder. Nu staat hij er
   altijd, hoeveel er ook boven staat. Een dekkende achtergrond, want de inhoud schuift eronder
   door. */
@media (min-width: 761px) {
  .sw-momentkaart--112 .sw-m112-voet {
    position: sticky;
    bottom: 0;
    z-index: 2;
    margin-top: var(--space-4);
    padding: var(--space-3) 0;
    background: var(--ground);
    border-top: 1px solid var(--line);
  }
}

/* Het knopje naast het kruisje: meelopen met de nieuwste melding. */
.sw-momentvolg {
  display: inline-flex; align-items: center; gap: calc(6px * var(--sw-zoom));
  margin-left: auto; margin-right: calc(8px * var(--sw-zoom));
  padding: calc(4px * var(--sw-zoom)) calc(10px * var(--sw-zoom));
  background: transparent; border: 1px solid var(--line); border-radius: 999px;
  color: var(--t2); font: inherit; font-size: calc(11.5px * var(--sw-zoom));
  letter-spacing: 0.08em; text-transform: uppercase; cursor: pointer;
}

.sw-momentvolg:hover { color: var(--ink); border-color: var(--ink); }
.sw-momentvolg:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }

.sw-momentvolg-stip {
  width: calc(7px * var(--sw-zoom)); height: calc(7px * var(--sw-zoom));
  border-radius: 50%; background: var(--t3); flex: none;
}

.sw-momentvolg.is-aan { color: var(--ok, #2f855a); border-color: currentColor; }
.sw-momentvolg.is-aan .sw-momentvolg-stip {
  background: currentColor;
  animation: sw-volgklop 2s ease-in-out infinite;
}

@keyframes sw-volgklop {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

@media (prefers-reduced-motion: reduce) {
  .sw-momentvolg.is-aan .sw-momentvolg-stip { animation: none; }
}

/* ── Wie er nu op onze websites is ─────────────────────────────────────────────
   Eén regel per bezoeker: wanneer, waar, wie, hoe lang en waar vandaan. Vijf
   kolommen die elk hun eigen vraag beantwoorden, zodat je met je oog langs één
   kolom kunt lopen in plaats van elke regel te moeten lezen. */
.sw-wielijst { display: flex; flex-direction: column; }

/* ÉÉN REGEL IS ÉÉN KNOP, EN HIJ IS BEWUST LAAG (23 september 2026). Op een drukke middag staan hier
   dertig regels; die stonden op drie tekstregels hoog elk, en dan zie je er zeven zonder te
   scrollen. Alles wat je nodig hebt om te scannen staat nu op ten hoogste twee regels per vak, de
   rest zit in het venster dat opengaat als je erop drukt. Een knop hoort er hier niet uit te zien
   als een knop -- vandaar dat alles wat een knop meekrijgt (rand, achtergrond, letter, uitlijning)
   weer wordt teruggezet. */
.sw-wierij {
  display: grid;
  grid-template-columns: 58px minmax(0, 1.5fr) minmax(0, 1.2fr) 86px minmax(0, 1fr);
  align-items: center; gap: calc(10px * var(--sw-zoom));
  width: 100%; margin: 0;
  padding: calc(5px * var(--sw-zoom)) calc(4px * var(--sw-zoom));
  background: none; border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
  -webkit-appearance: none; appearance: none;
}
/* Alleen waar er een muis is: op een aanraakscherm blijft :hover na een tik hangen tot je ergens
   anders tikt, en dan staat er een regel opgelicht die je al lang hebt losgelaten. */
@media (hover: hover) {
  .sw-wierij:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); }
}
.sw-wierij:focus-visible { outline: 2px solid var(--acc); outline-offset: -2px; }

.sw-wierij:last-child { border-bottom: 0; }

/* Een bot is geen bezoeker om iets van te vinden; hij mag stiller staan. */
.sw-wierij.is-bot { opacity: 0.6; }

/* En hij mag helemaal weg. De keuze staat op het hele scherm (sitewatch.js zet de klasse op <html>
   en onthoudt hem), zodat de lijst per domein en die van alle sites samen hetzelfde laten zien --
   twee lijsten die elk hun eigen stand onthouden is precies het soort verschil waar je later naar
   staat te kijken zonder te snappen wat je ziet. */
html.sw-bots-uit .sw-wierij.is-bot { display: none; }

/* De schakelaar zelf is het tweede getal in de kop ("7 bezoekers · 22 robots"): geen extra knop en
   geen extra regel, precies zoals gevraagd. Doorgestreept betekent: deze staan nu niet in de lijst. */
.sw-wiebots {
  padding: 0; border: 0; background: none; font: inherit; color: inherit;
  cursor: pointer; text-decoration: underline; text-decoration-style: dotted;
  text-underline-offset: 3px;
}
.sw-wiebots:hover { color: var(--ink); }
.sw-wiebots:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; }
html.sw-bots-uit .sw-wiebots { text-decoration: line-through; opacity: .75; }

.sw-wietijd {
  font-variant-numeric: tabular-nums; font-size: calc(12px * var(--sw-zoom)); color: var(--t3);
}

.sw-wieplek, .sw-wiewie, .sw-wieduur, .sw-wiebron { min-width: 0; display: flex; flex-direction: column; gap: 1px; }

/* Afkappen en niet afbreken. Een paginatitel of een verwijzende URL is zo lang als hij is; laat je
   hem wikkelen, dan bepaalt de langste regel de hoogte van de hele lijst. Wat niet past staat
   voluit in het venster. */
.sw-wiepad, .sw-wiepadadres, .sw-wiemeta, .sw-wiebronregel, .sw-wiesite {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* De tekeningetjes: apparaat, soort robot, waar hij vandaan kwam. Ze staan vóór de tekst op dezelfde
   regel en krimpen niet mee, zodat de tekst ernaast netjes afkapt in plaats van het tekeningetje
   plat te drukken. */
.sw-wieicoon {
  width: calc(12px * var(--sw-zoom)); height: calc(12px * var(--sw-zoom));
  flex: 0 0 auto; vertical-align: -1px; margin-right: 4px; opacity: .85;
}

/* Het vlaggetje van het land. Op Windows tekent het toestel geen vlag maar de twee letters van de
   landcode; dat is dezelfde informatie, dus het blijft leesbaar. De landnaam staat als tooltip. */
.sw-wielandvlag {
  flex: 0 0 auto; font-family: var(--font-body);
  font-size: calc(12.5px * var(--sw-zoom)); line-height: 1;
}

.sw-wiepad { font-size: calc(12.5px * var(--sw-zoom)); color: var(--ink); }
.sw-wiepadadres { font-size: calc(11px * var(--sw-zoom)); color: var(--t3); }

/* Het adres in een vaste letter: dan staan de punten onder elkaar en lees je een lijst in één blik.
   De vlaggen ("THEO", "ingelogd", "bot") staan ernaast op dezelfde regel.

   Afkappen is hier geen opmaak maar een rem: een IPv6-adres is vijfenveertig tekens en de naam van
   een bekend adres mag er veertig zijn. Zonder deze regels loopt zo'n regel de buurkolom in. Voluit
   staat alles in het venster. */
.sw-wieip {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px 6px;
  min-width: 0; overflow: hidden;
  font-family: var(--font-mono, monospace); font-size: calc(12px * var(--sw-zoom));
}
.sw-wieadres { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sw-wiemeta { font-size: calc(11px * var(--sw-zoom)); color: var(--t3); }

.sw-wieduur b { font-size: calc(12.5px * var(--sw-zoom)); font-variant-numeric: tabular-nums; white-space: nowrap; }
.sw-wieduur span { font-size: calc(11px * var(--sw-zoom)); color: var(--t3); white-space: nowrap; }

.sw-wiebronregel { font-size: calc(11.5px * var(--sw-zoom)); color: var(--t2); }

.sw-wievlag {
  display: inline-block; flex: 0 1 auto;
  max-width: calc(140px * var(--sw-zoom));
  padding: 0 calc(6px * var(--sw-zoom));
  border: 1px solid var(--line); border-radius: 999px;
  font-family: var(--font-body); font-size: calc(10px * var(--sw-zoom));
  letter-spacing: 0.06em; text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Alleen te zien zodra de robots zijn opgevouwen: dan is de lijst leeg terwijl er wel iets is. */
.sw-wiealleenrobots { display: none; }
html.sw-bots-uit .sw-wiealleenrobots { display: block; }

/* Dezelfde rij, maar met de sitenaam ervoor: op /bezoekers staan acht sites door elkaar en dan is
   "op welke site" de eerste vraag. Op de domeinpagina weet je dat al, dus daar blijft de rij vijf
   kolommen breed. */
.sw-wierij.heeft-site {
  grid-template-columns: minmax(0, 96px) 58px minmax(0, 1.4fr) minmax(0, 1.1fr) 86px minmax(0, 1fr);
}

/* De binnenkant van de kaart wordt in één keer gevuld met het fragment. Zonder deze regel is die
   tussen-div geen flexcontainer en valt de tussenruimte weg die `.sw-card` aan zijn kinderen geeft:
   de kop plakt dan tegen de lijst, anders dan op elke andere kaart. */
[data-sw="wie-alles"] { display: flex; flex-direction: column; gap: var(--space-2); }

.sw-wiesite {
  font-size: calc(12px * var(--sw-zoom)); color: var(--ink);
  overflow-wrap: anywhere; font-weight: 600;
}

/* Als er niemand is: per site wanneer er voor het laatst wel iemand was. Zonder dit blok is de
   kaart een doodlopende weg -- je ziet "niemand" en weet niet of dat klopt. */
.sw-wielaatst { display: flex; flex-direction: column; gap: calc(4px * var(--sw-zoom)); margin-top: calc(10px * var(--sw-zoom)); }

.sw-wielaatstrij {
  display: flex; gap: calc(10px * var(--sw-zoom)); align-items: baseline;
  padding: calc(4px * var(--sw-zoom)) 0;
  border-top: 1px solid var(--line);
}

/* ── Alles over één bezoeker ──────────────────────────────────────────────────
   De inhoud van het venster achter een regel in "wie er nu is". Het venster zelf is het gewone
   venster van dit dashboard (maakMomentVenster in sitewatch.js); hier staat alleen hoe de feiten
   erin liggen: naam links, waarde rechts, één per regel. */

.sw-wiefeiten { display: flex; flex-direction: column; }
.sw-wiefeit {
  display: grid; grid-template-columns: minmax(0, 132px) minmax(0, 1fr); gap: var(--space-3);
  padding: 7px 0; border-bottom: 1px solid var(--line-soft);
  font-size: calc(12.5px * var(--sw-zoom));
}
.sw-wiefeit:last-child { border-bottom: 0; }
/* De naam mag afbreken: "Besturingssysteem" past op een telefoon niet in één regel, en zonder deze
   regel schuift hij dwars over de waarde ernaast heen. */
.sw-wiefeitnaam { color: var(--t3); overflow-wrap: anywhere; }
.sw-wiefeitwaarde { overflow-wrap: anywhere; }

@media (max-width: 760px) {
  .sw-wiefeit { grid-template-columns: minmax(0, 104px) minmax(0, 1fr); gap: var(--space-2); }
}

/* Een bezoek is één kaartje: site en tijd bovenaan, pagina en apparaat samen,
   verblijfsduur en herkomst eronder. Alle gegevens blijven leesbaar. */
@media (max-width: 760px) {
  /* Drie regels per bezoeker en niet zeven. Wat er afgaat -- provider, apparaat, waar hij vandaan
     kwam -- staat voluit in het venster dat opengaat als je op het kaartje tikt; op een telefoon is
     dat prettiger te lezen dan een kaartje met acht regels waar je langs moet scrollen. Het pijltje
     achter de tijd zegt dat er iets achter zit. */
  .sw-wielijst { gap: 8px; }
  .sw-wierij, .sw-wierij.heeft-site {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "site duur" "plek plek" "wie wie" "bron bron";
    align-items: center;
    gap: 1px 10px; padding: 9px 11px;
    background: color-mix(in srgb, var(--ink) 4%, var(--ground));
    border: 1px solid var(--line); border-radius: 12px;
  }
  .sw-wierij:last-child { border-bottom: 1px solid var(--line); }
  .sw-wiesite { grid-area: site; font-size: 13px; }
  .sw-wieplek { grid-area: plek; }
  .sw-wiepad { font-size: 14px; font-weight: 600; line-height: 1.35; }
  .sw-wiewie { grid-area: wie; }
  .sw-wieip, .sw-wiemeta { font-size: 11.5px; }
  /* Hoe lang iemand er al is staat rechtsboven en niet "gezien 12 s": daar is de lijst op
     gesorteerd, en wie in deze lijst staat is per definitie van de laatste vijf minuten. Het
     pijltje zegt dat er meer achter zit. */
  .sw-wieduur {
    grid-area: duur; justify-self: end; font-size: 11.5px; color: var(--t3);
    flex-direction: row; align-items: baseline; gap: 4px;
  }
  .sw-wieduur b { font-size: 11.5px; }
  .sw-wieduur::after { content: " \203A"; color: var(--t4); }
  /* Waar hij vandaan kwam en waar hij zit: op een telefoon naast elkaar op één regel in plaats van
     onder elkaar. Wat niet past kapt af; voluit staat het in het venster. */
  .sw-wiebron { grid-area: bron; flex-direction: row; align-items: baseline; gap: 4px 8px; }
  .sw-wiebron .sw-wiemeta { flex: 0 1 auto; }
  /* Het adres van de pagina, het aantal pagina's en wanneer hij voor het laatst iets deed passen er
     op deze breedte niet bij zonder dat het kaartje twee regels hoger wordt. Ze staan alle drie in
     het venster dat opengaat als je op het kaartje tikt. */
  .sw-wiepadadres, .sw-wietijd, .sw-wieduur span { display: none; }
  .sw-wielaatstrij { flex-direction: column; gap: 1px; }
  [data-sw="visitorchart2"] { overflow-x: auto; padding-bottom: 8px; }
  [data-sw="visitorchart2"] .sw-vcol { flex: 0 0 44px; }
  [data-sw="visitorchart2"] .sw-vval { display: block; font-size: 11px; }
  [data-sw="visitorchart2"] .sw-vday { visibility: visible; font-size: 11px; }
  [data-sw="visitors"] .vrow.item { border-radius: 12px; min-height: 60px; }
  [data-sw="visitors"] .vrow.item > :nth-child(2)::before,
  [data-sw="visitors"] .vrow.item > :nth-child(6)::before {
    display: block; font: 11px var(--font-body); color: var(--t3); margin-bottom: 3px;
  }
  [data-sw="visitors"] .vrow.item > :nth-child(2)::before { content: "Vandaag"; }
  [data-sw="visitors"] .vrow.item > :nth-child(6)::before { content: "Nu"; }
}

/* ── Geparkeerde domeinen ─────────────────────────────────────────────────────
   De lijst links, de kolom die meedenkt rechts, en het venster met alles over één domein.
   (18 september 2026; hiervoor stond alles onder elkaar over de volle breedte.) */

.sw-parkbalk { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-3); align-items: center; }
/* De bediening staat rechts en is dus smal: de groepen komen onder elkaar in plaats van naast
   elkaar te worden platgedrukt. Krap op elkaar, want deze kolom moet in zijn geheel op het scherm
   passen zodra je het paneel opent. */
.sw-parkbalk { gap: calc(6px * var(--sw-zoom)) var(--space-3); }
.sw-parkbalk > * { flex: 1 1 100%; }
.sw-parkknoppen { align-items: center; }
/* Het woord ervoor staat op dezelfde hoogte als het midden van de knoppen ernaast; als los
   tekstlabel zakt het anders naar de bovenkant van de regel. */
.sw-parklabel {
  display: inline-flex; align-items: center; align-self: stretch;
  font-size: calc(10px * var(--sw-zoom)); letter-spacing: .14em; text-transform: uppercase; color: var(--t4);
  margin-right: 2px;
}

/* Het venster rechtsboven is een knop en hoort er ook zo uit te zien: dezelfde maat als de kentallen
   ernaast, met een rand die zegt dat er iets gebeurt als je erop drukt. */
.sw-kpi--knop {
  color: inherit; text-decoration: none;
  border: 1px solid var(--line);
  padding: var(--space-2) var(--space-3);
  transition: background-color .15s ease, border-color .15s ease;
}
.sw-kpi--knop:hover, .sw-kpi--knop:focus-visible {
  background: color-mix(in srgb, var(--ink) 8%, transparent);
  border-color: var(--acc);
}
.sw-kpi--knop .sub { color: var(--acc); }

/* De rechterkolom moet in beeld blijven als je door de lijst van achtenzeventig domeinen scrolt, en
   hij moet erop passen zodra je het paneel opent (verzoek Theo, 18 september 2026). Daarom blijft
   hij plakken en krijgt hij een eigen schuifbalk zodra hij toch hoger wordt dan het scherm -- op een
   klein venster met veel kaarten is dat beter dan een kolom die halverwege ophoudt. */
@media (min-width: 981px) {
  /* De kolom mag niet hoger worden dan wat er onder de kop over is. Dat getal is de hoogte van de
     sitekop plus de balk met de kentallen erboven -- dezelfde soort maat als de meldingenlijst op
     het 112-paneel gebruikt. Zo staat de bediening er altijd helemaal op zodra je het paneel opent;
     wat er bij een klein venster toch niet bij past, scrolt binnen de kolom zelf. */
  .sw-detail-grid > .sw-detail-col:last-child {
    position: sticky; top: var(--space-3);
    max-height: calc(100dvh - 340px); min-height: 360px;
    overflow-y: auto; overscroll-behavior: contain;
    scrollbar-width: none;
  }
  .sw-detail-grid > .sw-detail-col:last-child::-webkit-scrollbar { width: 0; height: 0; }

  /* En de lijst zelf scrolt binnen zijn kaart, net als de meldingenlijst op het 112-paneel. Dat is
     wat de rechterkolom in beeld houdt: zonder dit groeit de pagina mee met achtenzeventig regels en
     staat de halve bediening onder de vouw. De kop van de tabel blijft staan, zodat je bij regel
     zestig nog weet welke kolom welke is. */
  .sw-parklist > .sw-tabelwrap {
    max-height: calc(100dvh - 430px); min-height: 320px; overflow-y: auto;
    scrollbar-width: none;
  }
  .sw-parklist > .sw-tabelwrap::-webkit-scrollbar { width: 0; height: 0; }
  .sw-parktabel thead th {
    position: sticky; top: 0; z-index: 1;
    background: var(--ground);
  }
}
.sw-parkknoppen { display: flex; flex-wrap: wrap; gap: 4px; }
/* Het aantal achter een filterknop: hetzelfde gewicht als de knop, maar rustiger, zodat de knop
   zelf het woord blijft en niet het getal. */
.sw-parkaantal { color: var(--t4); font-variant-numeric: tabular-nums; }
.sw-linkbtn--pri .sw-parkaantal { color: inherit; }

/* Een rij van de tabel is helemaal aanklikbaar, niet alleen de domeinnaam. Anders mik je op een
   woord van twaalf pixels hoog terwijl de hele regel over het domein gaat. */
.sw-parktabel tbody tr { cursor: pointer; }
.sw-parktabel tbody tr:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); }
.sw-parktabel tbody tr.is-gekozen { background: color-mix(in srgb, var(--acc) 12%, transparent); }
.sw-parktabel tbody tr[hidden] { display: none; }

/* De twintig drukste domeinen in twee kolommen van tien: eerst tien links, dan tien rechts
   (verzoek Theo, 18 september 2026: "10 links en 10 rechts"). Met `columns` loopt de lijst kolom
   voor kolom vol; een raster zou hem om en om vullen en dan staat nummer twee rechtsboven. En het
   hangt aan de breedte van de kolom zelf, dus bij een smaller scherm of een groter lettertype valt
   hij vanzelf terug op één kolom in plaats van twee namen die allebei afkappen. */
.sw-parkstaven {
  /* `display: block` moet erbij: `.sw-staven` is een flexcontainer en daarop doet `columns` niets. */
  display: block;
  columns: calc(240px * var(--sw-zoom)) 2;
  column-gap: 18px;
}
.sw-parkstaven > .sw-staafrij { margin-bottom: 7px; }
.sw-parkstaven > * { break-inside: avoid; }
.sw-staafrij--link { color: var(--ink); text-decoration: none; }
.sw-staafrij--link:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); }

/* Per maand, gegroepeerd per jaar: het jaartal als kopje boven zijn eigen rij staafjes. */
.sw-parkjaar + .sw-parkjaar { margin-top: var(--space-3); }
.sw-parkjaar > .sw-parklabel { display: block; margin-bottom: 4px; }

/* ── De indeling van het paneel ───────────────────────────────────────────────
   De lijst links, de geschiedenis rechts. Onder de 1150 px komt de geschiedenis eronder in twee
   kolommen, en op een telefoon onder elkaar. Deze regels stonden tot 21 september 2026 in een eigen
   park.css; één paneel met een eigen stijlblad is precies hoe een scherm uit de pas gaat lopen. */
.sw-parkgrid {
  /* De zijkolom is breed genoeg voor twee kolommen van tien: samen de top twintig naast elkaar,
     zoals het nieuwspaneel zijn bronnen toont. Bij 2,5fr paste er maar één kolom in. */
  display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(calc(420px * var(--sw-zoom)), 1fr);
  gap: var(--space-3); align-items: start;
}
.sw-parklist, .sw-parkhistory { min-width: 0; }
.sw-parkhistory { display: grid; gap: var(--space-3); }

/* De keuzebalk staat over de volle breedte, dus de groepen mogen naast elkaar. In de smalle
   rechterkolom doet `.sw-parkbalk` juist het omgekeerde; vandaar dat dit aan de kaart hangt. */
.sw-parkkiezer .sw-parkbalk > * { flex: 0 1 auto; }
.sw-parkcontrols { gap: var(--space-2); }
.sw-parkcontrols label { display: flex; align-items: center; gap: 6px; }
.sw-parkcontrols select, .sw-parkcontrols input[type="month"] {
  font: inherit; color: inherit; background: var(--ground);
  border: 1px solid var(--line); padding: 0 10px; min-height: 44px; max-width: 100%;
}
.sw-parkcontrols select:focus-visible, .sw-parkcontrols input:focus-visible {
  outline: 2px solid var(--acc); outline-offset: 1px;
}

/* De balk boven de lijst: zoeken, filteren op oordeel, sorteren. */
.sw-parktoolbar {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--space-2) var(--space-3); padding-bottom: var(--space-2);
}
.sw-parktoolbar .sw-112zoek { flex: 1 1 calc(210px * var(--sw-zoom)); }

/* De maanden naast de lijst. Eén regel per maand; de gekozen maand licht op, net als een gekozen
   rij in de tabel -- zelfde kleur, zodat "dit heb je aan" er overal hetzelfde uitziet. */
.sw-parkmonths a {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px var(--space-2);
  padding: calc(8px * var(--sw-zoom)) var(--space-2);
  color: var(--ink); text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 8%, transparent);
}
.sw-parkmonths a:last-child { border-bottom: 0; }
.sw-parkmonths a small { grid-column: 1 / -1; color: var(--t4); }
.sw-parkmonths a:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); }
.sw-parkmonths a.is-actief { background: color-mix(in srgb, var(--acc) 12%, transparent); }

/* De dagtabel scrolt binnen zijn eigen kaart en houdt zijn kop vast, zodat de kolom naast de lijst
   niet meegroeit met een maand van eenendertig dagen. */
.sw-parkdays { max-height: calc(420px * var(--sw-zoom)); overflow: auto; scrollbar-width: none; }
.sw-parkdays::-webkit-scrollbar { width: 0; height: 0; }
.sw-parkdays th { position: sticky; top: 0; z-index: 1; background: var(--ground); }
.sw-parkdays td:first-child { min-width: calc(54px * var(--sw-zoom)); }

.sw-parkdashboard .sw-parktabel td:first-child { overflow-wrap: anywhere; }
.sw-parkdashboard .sw-parktabel th { white-space: normal; }

@media (max-width: 1150px) {
  .sw-parkgrid { grid-template-columns: 1fr; }
  .sw-parkhistory { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 760px) {
  .sw-parkhistory { grid-template-columns: 1fr; }
  /* Zeven kolommen passen niet op een telefoon. Zonder ondergrens perst de tabel de domeinnaam
     letter voor letter onder elkaar ("anwb / ervari / ngen. / nl"); met een ondergrens schuift de
     tabel opzij binnen zijn eigen kader, zoals de tabellen in het CMS. */
  .sw-parkdashboard .sw-parktabel { min-width: calc(640px * var(--sw-zoom)); }
  .sw-parkdashboard .sw-parktabel td:first-child { overflow-wrap: normal; }
  .sw-parkdashboard .sw-parktabel td { white-space: nowrap; }
  .sw-parkcontrols label { width: 100%; }
  .sw-parkcontrols select, .sw-parkcontrols input[type="month"] { width: 100%; min-width: 0; font-size: 16px; }
}

/* ── Het venster over het scherm ───────────────────────────────────────────── */

.sw-modal {
  position: fixed; inset: 0; z-index: 60;
  display: flex; align-items: flex-start; justify-content: center;
  padding: var(--space-4);
  overflow-y: auto; overscroll-behavior: contain;
}
/* De achtergrond is een link naar het adres zonder domein: klikken buiten het venster is dus
   precies hetzelfde als sluiten, zonder een tweede weg door de code. */
.sw-modal-achter {
  position: fixed; inset: 0;
  background: color-mix(in srgb, #000 66%, transparent);
  backdrop-filter: blur(2px);
}
.sw-modal-venster {
  position: relative; z-index: 1;
  width: min(1180px, 100%);
  margin: auto;
  background: var(--ground); border: 1px solid var(--line);
  box-shadow: 0 24px 60px rgb(0 0 0 / 45%);
  display: flex; flex-direction: column;
  animation: sw-modalin .22s ease-out both;
}
@keyframes sw-modalin {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .sw-modal-venster { animation: none; }
}
/* De kop blijft staan tijdens het scrollen: bij een domein met veertig bezoekers is de sluitknop
   anders drie schermen omhoog. */
.sw-modal-kop {
  position: sticky; top: 0; z-index: 2;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-3) var(--space-4);
  background: var(--ground); border-bottom: 1px solid var(--line);
}
.sw-modal-titel b {
  display: block;
  font-family: var(--font-heading); font-weight: 600;
  font-size: calc(22px * var(--sw-zoom)); line-height: 1.1; letter-spacing: .04em;
  overflow-wrap: anywhere;
}
.sw-modal-titel span {
  display: block; margin-top: 2px;
  font-size: calc(10.5px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase; color: var(--t4);
}
.sw-modal-acties { display: flex; gap: 6px; flex-wrap: wrap; }
/* De sluitknop krijgt de aandacht zodra het venster opengaat (zie sitewatch.js), dus hij moet ook
   zichtbaar de knop zijn waar je op staat -- niet alleen een van de twee. */
.sw-modal-sluit { font-weight: 600; }
.sw-modal-inhoud {
  padding: var(--space-4);
  display: flex; flex-direction: column; gap: var(--space-3);
}
/* De kaarten in het venster hebben geen eigen rand en geen hoekjes: de rand van het venster is al
   de begrenzing, en een kader in een kader maakt het onrustig. */
.sw-modal-kaart { border: 0; box-shadow: none; padding: 0; }
.sw-modal-kaart + .sw-modal-kaart { border-top: 1px solid var(--line); padding-top: var(--space-3); }
.sw-modal-feiten {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(calc(150px * var(--sw-zoom)), 1fr));
  gap: var(--space-2) var(--space-3);
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  padding: var(--space-3) 0;
}
.sw-modal-feiten .sw-kpi { padding: 0; border: 0; background: transparent; }
.sw-modal-feiten .value { font-size: calc(15px * var(--sw-zoom)); }
.sw-modal-grid { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: var(--space-4); align-items: start; }
/* Zonder scrollslot scrollt de lijst eronder mee zodra het venster aan zijn eind is. */
body.sw-modal-open { overflow: hidden; }

@media (max-width: 980px) {
  .sw-modal-grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 760px) {
  /* Op een telefoon is een venster met marges eromheen een postzegel: hij vult het scherm. */
  .sw-modal { padding: 0; }
  .sw-modal-venster { width: 100%; min-height: 100%; border: 0; }
  .sw-modal-inhoud { padding: var(--space-3); }
  .sw-modal-kop { padding: var(--space-3); }
  .sw-parkbalk { gap: var(--space-2); }
}

/* Het baken onder de nieuwslijst: zonder JavaScript een gewone knop, met JavaScript het punt waar
   de volgende vierentwintig berichten binnenkomen zodra je in de buurt komt. */
.sw-nieuwsmeer {
  display: block; margin-top: var(--space-3); padding: var(--space-3);
  text-align: center; text-decoration: none;
  border: 1px solid var(--line); color: var(--t3);
  font-size: calc(11px * var(--sw-zoom)); letter-spacing: .12em; text-transform: uppercase;
}
.sw-nieuwsmeer:hover { color: var(--ink); border-color: var(--acc); }
.sw-nieuwsmeer.is-bezig { color: var(--t5); border-style: dashed; }
/* Bij een gefilterde lijst klopt "nog 233 te gaan" niet: dat getal gaat over alles. Weg ermee;
   het paneel haalt de rest dan zelf op. */
.sw-nieuwsmeer.is-weg { display: none; }

/* Het profielblok bovenaan het uitschuifblad: wie er is ingelogd, met de knop naar het beheer of
   naar de inlogpagina. Alleen op een telefoon; op een breed scherm staat die knop in de kop. */
.sw-profiel { display: none; }

@media (max-width: 760px) {
  .sw-profiel {
    display: flex; align-items: center; gap: var(--space-3); flex-shrink: 0;
    padding: calc(10px * var(--sw-zoom)) calc(12px * var(--sw-zoom));
    border: 1px solid var(--line); border-radius: 14px;
    background: color-mix(in srgb, var(--ink) 5%, transparent);
  }
  .sw-profiel-teken {
    display: grid; place-items: center; flex: none;
    width: calc(38px * var(--sw-zoom)); height: calc(38px * var(--sw-zoom));
    border-radius: 50%; background: color-mix(in srgb, var(--acc) 30%, transparent);
    color: var(--ink); font-family: var(--font-heading); font-size: calc(16px * var(--sw-zoom));
  }
  .sw-profiel-tekst { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
  .sw-profiel-tekst b { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sw-profiel-tekst b { font-size: calc(13.5px * var(--sw-zoom)); color: var(--ink); }
  .sw-profiel-tekst small { font-size: calc(11px * var(--sw-zoom)); color: var(--t4); }
  .sw-profiel .sw-linkbtn { flex: none; border: 0; border-radius: 10px; text-transform: none; letter-spacing: normal; font: 500 14px var(--font-body); }
  .sw-extra > .sw-menugroep, .sw-extra > .sw-sheetkop { flex-shrink: 0; }
  /* De losse Beheer-knop verderop in het blad: die staat hierboven al naast je naam. */
  .sw-extra .sw-beheerknop { display: none; }
  /* 112-meldingen en Nieuws staan in de onderbalk; in het blad zouden ze er twee keer staan
     (Theo, 18 september 2026). */
  .sw-extra .sw-alleen-mobiel[data-sw-view="112"],
  .sw-extra .sw-alleen-mobiel[data-sw-view="nieuws"] { display: none; }
}

/* Zolang het uitschuifmenu openstaat veert de pagina eronder niet mee. Op een telefoon is dat wat
   de browser aangrijpt om te herladen zodra je in dat menu omlaag veegt; dan ben je je menu en je
   plek kwijt. */
html.sw-blad-open, body.sw-blad-open { overscroll-behavior: none; }
body.sw-blad-open { overflow: hidden; }

/* Dezelfde bediening op telefoon en tablet; de desktop behoudt zijn compacte overzicht. */
@media (max-width: 1050px) {
  .sw-hbknop { min-height: 44px; min-width: 44px; }
  .sw-linkbtn, .sw-chip, .sw-filterstaven .sw-filterrij { min-height: 48px; border-radius: 10px; }
  .sw-linkbtn { font-size: 14px; letter-spacing: .02em; text-transform: none; }
  .sw-chip { font-size: 13px; }
  .sw-form input, .sw-112zoek input { min-height: 48px; font-size: 16px; border-radius: 10px; }
  .sw-filterstaven .sw-filterrij { padding-block: 8px; }
  .sw-tabs, .sw-head { padding-left: max(12px, env(safe-area-inset-left)); padding-right: max(12px, env(safe-area-inset-right)); }
}

/* Veeg vanaf de kop om te sluiten; de melding en kaart blijven normaal bedienbaar. */
@media (max-width: 1024px) {
  .sw-momentkaart--112 { height: 100dvh; min-height: 0; width: 100%; }
  .sw-momentlaag--112 { overflow: hidden; }
  .sw-momentkaart--112 > .sw-momentbody { min-height: 0; flex: 1; overflow-y: auto; }
  .sw-momentkaart--112 .sw-momentkop { flex-shrink: 0; position: relative; padding-top: 26px; touch-action: none; }
  .sw-momentkaart--112 .sw-momentkop::before {
    content: ""; position: absolute; top: 9px; left: calc(50% - 20px);
    width: 40px; height: 4px; border-radius: 4px; background: currentColor; opacity: .25;
  }
  .sw-momentkaart--112.cms-swipe-dragging { animation: none; }
  .sw-momentkaart--112 .sw-momentbody { touch-action: pan-y pinch-zoom; }
}

.sw-nieuwsbeeld img.sw-bronlogo {
  object-fit: contain;
  background: #fff;
  padding: 12px;
  box-sizing: border-box;
  filter: none;
}
/* De enige spraakknop blijft op alle schermen direct in de kop bereikbaar. */
.sw-themebtn[data-omroep-open] { position: relative; width: calc(34px * var(--sw-zoom)); min-width: calc(34px * var(--sw-zoom)); height: calc(34px * var(--sw-zoom)); min-height: 0; justify-content: center; padding: 0; flex: none; }
.sw-themebtn[data-omroep-open] > svg { width: calc(18px * var(--sw-zoom)); height: calc(18px * var(--sw-zoom)); flex: none; }
.sw-themebtn[data-omroep-open] [data-omroep-status] { display: none; }
.sw-themebtn[data-omroep-open][data-omroep-stand="aan"]::after,
.sw-themebtn[data-omroep-open][data-omroep-stand="klik-nodig"]::after { content: ""; position: absolute; right: calc(3px * var(--sw-zoom)); top: calc(3px * var(--sw-zoom)); width: calc(5px * var(--sw-zoom)); height: calc(5px * var(--sw-zoom)); border-radius: 50%; background: var(--ok); }
.sw-themebtn[data-omroep-open][data-omroep-stand="klik-nodig"]::after { background: var(--warn); }
.sw-omroep-form { display: grid; gap: 14px; }
.sw-omroep-veld { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.sw-omroep-veld input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--acc); }
.sw-omroep-form select { max-width: 100%; min-width: 0; padding: 7px; color: var(--ink); background: var(--bg); border: 1px solid var(--line); font: inherit; }
.sw-omroep-categorieen { margin: 0; padding: 12px; border: 1px solid var(--line); }
.sw-omroep-categorie { display: grid; grid-template-columns: minmax(110px, 1fr) minmax(0, 2fr); gap: 12px; align-items: center; margin: 8px 0; }
.sw-omroep-acties { display: flex; flex-wrap: wrap; gap: 10px; }
.sw-omroep-diagnose { min-width: 0; border-top: 1px solid var(--line); padding-top: 12px; }
.sw-omroep-diagnose summary, .sw-omroep-meer-stemmen summary { cursor: pointer; }
.sw-omroep-meer-stemmen[open] > select { margin-top: 10px; width: 100%; }
.sw-omroep-diagnose ol { max-height: 240px; overflow-y: auto; padding-left: 24px; font-size: 12px; overflow-wrap: anywhere; }
.sw-omroep-diagnose li { margin: 6px 0; }
.sw-omroep-diagnose time { font-variant-numeric: tabular-nums; color: var(--t3); }
.sw-omroep-activatie {
  position: fixed; z-index: 1601;
  left: 50%; transform: translateX(-50%);
  bottom: calc(max(var(--sw-voet, 0px), env(safe-area-inset-bottom)) + var(--space-3));
  width: max-content; max-width: min(calc(100% - 2 * var(--space-3)), calc(760px * var(--sw-zoom)));
  padding: var(--space-3) var(--space-4); border: 1px solid var(--acc); border-radius: 5px;
  background: var(--ground); color: var(--ink); box-shadow: 0 4px 18px #0005;
  font: inherit; cursor: pointer; pointer-events: auto;
}
/* Kaartjes delen de bestaande kaartjas; de ondoorzichtige achtergrond houdt tekst leesbaar. */
.sw-omroep-kaarten {
  position: fixed; z-index: 1600;
  top: calc(var(--sw-kop, 70px) + var(--space-3)); right: max(var(--space-3), env(safe-area-inset-right));
  display: flex; flex-direction: column; gap: var(--space-2);
  width: min(calc(100% - 2 * var(--space-3)), calc(420px * var(--sw-zoom))); pointer-events: none;
}
.sw-omroep-kaarten:empty { display: none; }
.sw-omroep-kaart {
  --omroep-kleur: var(--acc);
  position: relative; min-width: 0; margin: 0; padding: 0;
  background: var(--panel); border: 1px solid var(--line); border-left: calc(3px * var(--sw-zoom)) solid var(--omroep-kleur);
  box-shadow: 0 4px 18px #0005; pointer-events: auto;
  animation: sw-omroep-kaart-in .18s ease-out backwards;
  transition: opacity .18s ease, transform .18s ease;
}
.sw-omroep-kaart[data-omroep-categorie="112"], .sw-omroep-kaart[data-omroep-categorie="spam"] { --omroep-kleur: var(--crit); }
.sw-omroep-kaart[data-omroep-categorie="fixi"], .sw-omroep-kaart[data-omroep-categorie="agenda"] { --omroep-kleur: var(--warn); }
.sw-omroep-kaart[data-omroep-prioriteit="hoog"] { --omroep-kleur: var(--warn); }
.sw-omroep-kaart[data-omroep-prioriteit="kritiek"] { --omroep-kleur: var(--crit); }
.sw-omroep-kaart[data-omroep-toon="herstel"] { --omroep-kleur: var(--ok); }
.sw-omroep-kaart[data-omroep-toon="onderhoud"] { --omroep-kleur: var(--t3); }
.sw-omroep-kaart[data-omroep-categorie="bezoekers"] { --omroep-kleur: var(--info); }
.sw-omroep-kaart-link {
  display: grid; grid-template-columns: calc(22px * var(--sw-zoom)) minmax(0, 1fr);
  gap: var(--space-2) var(--space-3); align-items: start;
  padding: var(--space-3) calc(44px * var(--sw-zoom)) var(--space-3) var(--space-3);
  color: var(--ink); text-decoration: none;
}
.sw-omroep-kaart-link:hover { color: var(--ink); text-decoration: none; background: color-mix(in srgb, var(--ink) 5%, transparent); }
.sw-omroep-kaart-icoon { grid-column: 1; width: calc(22px * var(--sw-zoom)); height: calc(22px * var(--sw-zoom)); color: var(--omroep-kleur); flex: none; }
.sw-omroep-kaart-inhoud { min-width: 0; display: grid; gap: calc(4px * var(--sw-zoom)); }
.sw-omroep-kaart-meta { color: var(--t3); font-size: calc(11px * var(--sw-zoom)); line-height: 1.4; }
.sw-omroep-kaart-titel { margin: 0; min-width: 0; font-size: calc(14px * var(--sw-zoom)); line-height: 1.4; overflow-wrap: anywhere; }
.sw-omroep-kaart-sluit {
  position: absolute; right: 0; top: 0; display: flex; align-items: center; justify-content: center;
  width: calc(40px * var(--sw-zoom)); height: calc(40px * var(--sw-zoom)); padding: 0;
  border: 0; background: transparent; color: var(--t3); font: inherit; font-size: calc(22px * var(--sw-zoom)); cursor: pointer;
}
.sw-omroep-kaart-sluit:hover { color: var(--ink); background: color-mix(in srgb, var(--ink) 8%, transparent); }
.sw-omroep-kaart.is-verdwijnt { animation: none; opacity: 0; transform: translateY(calc(6px * var(--sw-zoom))); pointer-events: none; }
@keyframes sw-omroep-kaart-in { from { opacity: 0; transform: translateY(calc(6px * var(--sw-zoom))); } to { opacity: 1; transform: none; } }
@media (max-width: 760px) {
  .sw-omroep-kaarten { left: max(var(--space-3), env(safe-area-inset-left)); width: auto; }
  .sw-omroep-kaart-link { padding-right: 44px; }
  .sw-omroep-kaart-sluit { width: 44px; height: 44px; }
}
@media (prefers-reduced-motion: reduce) {
  .sw-omroep-kaart { animation-name: sw-omroep-kaart-fade; animation-duration: .1s; transition: opacity .1s; }
  .sw-omroep-kaart.is-verdwijnt { transform: none; }
}
@keyframes sw-omroep-kaart-fade { from { opacity: 0; } to { opacity: 1; } }
.sw-omroep-activatie[hidden] { display: none; }
@media (max-width: 600px) {
  .sw-omroep-categorie { grid-template-columns: minmax(0, 1fr); }
  .sw-omroep-categorie > .sw-omroep-veld { grid-column: 1 / -1; }
  .sw-omroep-categorie > select { width: 100%; }
  .sw-omroep-veld > select { max-width: 65%; }
}

/* Agenda en Fixi hebben op brede schermen al hun eigen tab. */
@media (min-width: 1601px) { .sw-linkbtn--alleen-blad { display: none; } }
