/* NinjaPortal (ninjastic2008.com) - één stylesheet, geen framework.
   Donker omdat de suite de hele dag naast een terminal staat; teal is het
   aan-lampje, ember is wat er beweegt. Zie ../NinjaWebsite/DESIGN.md. */

/* Zelf gehost, latin-subset, variabel 400-900. Geen extern verzoek: de CSP
   staat alleen 'self' toe en dat is precies de bedoeling. */
@font-face {
  font-family: 'Archivo';
  src: url('/assets/fonts/archivo-latin.woff2?v=2026-08-16') format('woff2');
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --bg: oklch(0.16 0.008 250);
  --bg-deep: oklch(0.13 0.008 250);
  --bg-soft: oklch(0.19 0.008 250);
  --panel: oklch(0.20 0.010 250);
  --panel-2: oklch(0.24 0.012 250);
  --border: oklch(0.31 0.012 250);
  --border-soft: oklch(0.26 0.010 250);
  --text: oklch(0.95 0.004 250);
  --muted: oklch(0.76 0.008 250);
  --faint: oklch(0.62 0.008 250);
  --accent: oklch(0.80 0.14 180);
  --accent-dim: oklch(0.42 0.07 180);
  --accent-soft: oklch(0.80 0.14 180 / 0.12);
  --ember: oklch(0.74 0.16 45);
  --ok: oklch(0.82 0.15 150);
  --warn: oklch(0.83 0.14 85);
  --bad: oklch(0.70 0.17 25);

  --mono: ui-monospace, "SF Mono", "Cascadia Code", Consolas, monospace;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --display: 'Archivo', system-ui, sans-serif;

  --radius: 12px;
  --shadow: 0 1px 2px oklch(0 0 0 / .4), 0 10px 30px oklch(0 0 0 / .3);
  --ease: cubic-bezier(0.16, 1, 0.3, 1);

  /* benoemde z-schaal, geen 9999 */
  --z-bg: 0;
  --z-content: 1;
  --z-head: 20;
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: oklch(0.97 0.003 250); --bg-deep: oklch(0.94 0.004 250); --bg-soft: oklch(0.93 0.004 250);
    --panel: oklch(1 0 0); --panel-2: oklch(0.95 0.004 250);
    --border: oklch(0.87 0.006 250); --border-soft: oklch(0.91 0.005 250);
    --text: oklch(0.22 0.010 250); --muted: oklch(0.44 0.010 250); --faint: oklch(0.56 0.010 250);
    --accent: oklch(0.55 0.12 180); --accent-dim: oklch(0.86 0.06 180); --accent-soft: oklch(0.55 0.12 180 / 0.10);
    --ember: oklch(0.58 0.16 45);
    --shadow: 0 1px 2px oklch(0 0 0 / .06), 0 10px 26px oklch(0 0 0 / .07);
  }
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 15.5px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
img { max-width: 100%; }
code, .mono { font-family: var(--mono); font-size: .88em; }
h1, h2, h3 {
  font-family: var(--display);
  letter-spacing: -.025em; line-height: 1.08;
  text-wrap: balance;
}
p { text-wrap: pretty; }
.brand { font-family: var(--display); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

.wrap { max-width: 1060px; margin: 0 auto; padding: 0 22px; }
.narrow { max-width: 460px; }

/* ---------- header ---------- */
.site-head {
  position: sticky; top: 0; z-index: 20;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border-soft);
}
.site-head .wrap { display: flex; align-items: center; gap: 26px; height: 60px; }
.brand {
  font-weight: 650; font-size: 16.5px; letter-spacing: -.02em; color: var(--text);
}
.brand:hover { text-decoration: none; color: var(--accent); }
.site-nav { display: flex; gap: 20px; margin-left: auto; align-items: center; font-size: 14.5px; }
.site-nav a { color: var(--muted); }
.site-nav a:hover, .site-nav a.active { color: var(--text); text-decoration: none; }
.site-nav .btn { padding: 6px 14px; font-size: 14px; }

/* ---------- knoppen ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 18px; border-radius: 9px; border: 1px solid var(--border);
  background: var(--panel-2); color: var(--text); font: inherit; font-size: 14.5px;
  font-weight: 550; cursor: pointer; transition: background .14s, border-color .14s, opacity .14s;
}
.btn:hover { background: var(--panel); border-color: var(--faint); text-decoration: none; }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn-primary {
  background: var(--accent); border-color: var(--accent); color: #04211e;
}
.btn-primary:hover { background: color-mix(in srgb, var(--accent) 88%, #fff); border-color: var(--accent); }
.btn-ghost { background: transparent; }
.btn-danger { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 35%, transparent); background: transparent; }
.btn-danger:hover { background: color-mix(in srgb, var(--bad) 10%, transparent); }
.btn-block { width: 100%; }
.btn-row { display: flex; gap: 10px; flex-wrap: wrap; }

/* ---------- hero ---------- */
.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: clamp(64px, 11vw, 128px) 0 clamp(56px, 9vw, 104px);
  background: radial-gradient(120% 90% at 50% 0%, var(--bg-deep), var(--bg) 70%);
  border-bottom: 1px solid var(--border-soft);
}
.hero-inner { position: relative; z-index: var(--z-content); }
.hero h1 {
  font-size: clamp(38px, 6.6vw, 76px);
  font-weight: 800;
  margin: 0 0 22px;
  max-width: 16ch;
}
.hero h1 .hero-accent { color: var(--accent); }
.hero p.lead {
  font-size: clamp(16.5px, 1.5vw, 19px);
  line-height: 1.65;
  color: var(--muted);
  max-width: 62ch;
  margin: 0 0 30px;
}
.hero .btn-row { margin-bottom: 16px; }
.hero .note { font-family: var(--mono); font-size: 12.5px; color: var(--faint); margin: 0; }
.eyebrow {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--accent);
}

/* ---------- sfeer: korrel en lichtveeg ----------
   Geen vormen, geen tekst. Een fijne korrellaag met daaronder twee brede
   lichtvegen die er heel traag schuin overheen trekken, als stof in een
   lichtbundel. De korrel is één keer gerasterde ruis in een data-URI: geen
   extern verzoek, en de browser tekent hem één keer. De vegen zijn verlopen die
   alleen verschuiven, dus het is compositing zonder herberekening. */
.atmosphere {
  position: absolute; inset: 0;
  z-index: var(--z-bg);
  overflow: hidden;
  pointer-events: none;
}

.sweep {
  position: absolute;
  top: -60%; bottom: -60%;
  width: 46%;
  /* Zachte randen uit het verloop zelf; een blur-filter op dit formaat zou de
     compositor elke frame laten werken. */
  background: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in srgb, var(--accent) 42%, transparent) 34%,
    color-mix(in srgb, var(--accent) 58%, transparent) 50%,
    color-mix(in srgb, var(--accent) 42%, transparent) 66%,
    transparent 100%
  );
  filter: saturate(.85);
  opacity: .42;
  transform: rotate(-16deg) translate3d(-40vw, 0, 0);
  animation: sweepAcross 125s linear infinite;
  will-change: transform;
}

/* De tweede is warmer, breder en nog trager: dat geeft diepte zonder dat je
   twee losse balken ziet lopen. */
.sweep-2 {
  width: 62%;
  background: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in srgb, var(--ember) 34%, transparent) 40%,
    color-mix(in srgb, var(--ember) 46%, transparent) 50%,
    color-mix(in srgb, var(--ember) 34%, transparent) 60%,
    transparent 100%
  );
  opacity: .24;
  animation-duration: 195s;
  animation-delay: -70s;
}

@keyframes sweepAcross {
  from { transform: rotate(-16deg) translate3d(-70vw, 0, 0); }
  to   { transform: rotate(-16deg) translate3d(170vw, 0, 0); }
}

.grain {
  position: absolute; inset: -10%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
  background-repeat: repeat;
  opacity: .09;
}

/* De kop moet vrij staan: naar links en naar onderen loopt alles uit. */
.atmosphere {
  -webkit-mask-image: radial-gradient(135% 115% at 70% 40%, #000 34%, transparent 92%);
  mask-image: radial-gradient(135% 115% at 70% 40%, #000 34%, transparent 92%);
}

@media (prefers-color-scheme: light) {
  .sweep { opacity: .22; }
  .sweep-2 { opacity: .12; }
  .grain { opacity: .05; mix-blend-mode: multiply; }
}

/* ---------- carrousel ---------- */
.suite { padding-bottom: clamp(44px, 6vw, 72px); }
.suite-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 20px; margin-bottom: 24px;
}
.suite-head h2 { font-size: clamp(24px, 3.2vw, 34px); margin: 0; }
.suite-controls { display: flex; gap: 8px; }
.ctl {
  width: 40px; height: 40px; border-radius: 10px;
  border: 1px solid var(--border); background: var(--panel);
  color: var(--text); font-size: 20px; line-height: 1; cursor: pointer;
  transition: background .14s var(--ease), border-color .14s var(--ease);
}
.ctl:hover { background: var(--panel-2); border-color: var(--faint); }
.ctl[disabled] { opacity: .4; cursor: not-allowed; }

.carousel { position: relative; }
.track {
  display: flex; gap: 18px;
  margin: 0; padding: 10px max(22px, calc(50vw - 530px)) 22px;
  list-style: none;
  overflow-x: auto;
  /* `proximity` in plaats van `mandatory`: bij mandatory vecht de snap met een
     lopende scroll-animatie en krijg je die kleine ruk aan het eind. Zo glijdt
     hij netjes uit en klikt hij alleen vast als je vlakbij bent. */
  scroll-snap-type: x proximity;
  scroll-behavior: smooth;
  scroll-padding-inline: 50%;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}
.track::-webkit-scrollbar { display: none; }
.track:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--radius); }

.slide {
  scroll-snap-align: center;
  flex: 0 0 clamp(260px, 78vw, 340px);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 22px;
  display: flex; flex-direction: column; gap: 12px;
  /* De kaart die in het midden staat komt een tikje naar voren. Dat maakt het
     schuiven leesbaar: je ziet wáár je bent zonder dat er iets springt. */
  transform: scale(.965);
  opacity: .72;
  transition: transform .55s var(--ease), opacity .55s var(--ease), border-color .35s var(--ease);
  will-change: transform;
}
.slide[data-current="true"] { transform: scale(1); opacity: 1; }
.slide h3 { font-size: 19px; margin: 0; }
.slide .tag { font-family: var(--mono); font-size: 12px; color: var(--faint); margin: 0; }
.slide p.body { margin: 0; color: var(--muted); font-size: 14.5px; flex: 1; }
.slide .meta {
  display: flex; gap: 12px; flex-wrap: wrap;
  font-family: var(--mono); font-size: 12px; color: var(--faint);
  border-top: 1px solid var(--border-soft); padding-top: 12px; margin-top: 4px;
}
.slide .meta b { color: var(--muted); font-weight: 600; }
.slide[data-current="true"] { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); }
/* Zonder JavaScript staat er niets gedimd: dan zijn alle kaarten gewoon vol. */
.no-js .slide { transform: none; opacity: 1; }

.dots { display: flex; gap: 8px; justify-content: center; padding-top: 4px; }
.dots button {
  width: 26px; height: 4px; padding: 0; border: 0; border-radius: 999px;
  background: var(--border); cursor: pointer;
  transition: background .2s var(--ease), width .2s var(--ease);
}
.dots button[aria-selected="true"] { background: var(--accent); width: 40px; }

/* ---------- hoe het samenhangt ---------- */
.wiring h2, .account-cta h2 { font-size: clamp(24px, 3.2vw, 34px); margin: 0 0 26px; }
.wiring-grid { display: grid; gap: 26px 34px; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.wiring-item h3 { font-size: 16.5px; margin: 0 0 8px; }
.wiring-item p { margin: 0; color: var(--muted); font-size: 14.5px; max-width: 46ch; }
.account-cta p.lead { color: var(--muted); font-size: 16.5px; max-width: 62ch; margin: 0 0 26px; }

/* ---------- secties ---------- */
section { padding: 56px 0; }
section + section { border-top: 1px solid var(--border-soft); }
.section-head { margin-bottom: 28px; }
.section-head h2 { font-size: 24px; margin: 8px 0 8px; }
.section-head p { color: var(--muted); max-width: 66ch; margin: 0; }

/* ---------- app-kaarten ---------- */
.grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.card {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 20px; display: flex; flex-direction: column; gap: 10px;
}
.card-head { display: flex; align-items: center; gap: 12px; }
.appmark {
  width: 38px; height: 38px; flex: none; border-radius: 10px;
  display: grid; place-items: center; border: 1px solid var(--border);
  font-family: var(--mono); font-size: 13px; font-weight: 700; letter-spacing: -.02em;
}
.card-head .t { font-weight: 600; font-size: 16px; }
.card-head .s { font-size: 12.5px; color: var(--faint); font-family: var(--mono); }
.card p { margin: 0; color: var(--muted); font-size: 14.5px; flex: 1; }
.card .meta {
  display: flex; gap: 14px; flex-wrap: wrap; font-family: var(--mono);
  font-size: 12px; color: var(--faint); border-top: 1px solid var(--border-soft); padding-top: 12px;
}
.card .meta b { color: var(--muted); font-weight: 600; }

.pill {
  display: inline-flex; align-items: center; gap: 6px; font-family: var(--mono);
  font-size: 11px; font-weight: 600; padding: 2px 9px; border-radius: 999px;
  border: 1px solid var(--border); color: var(--muted);
}
.pill.accent { color: var(--accent); border-color: var(--accent-dim); background: var(--accent-soft); }
.pill.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
.pill.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }

/* ---------- kenmerken ---------- */
.features { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.feature .g {
  font-family: var(--mono); font-size: 13px; color: var(--accent);
  border: 1px solid var(--accent-dim); background: var(--accent-soft);
  width: 30px; height: 30px; display: grid; place-items: center; border-radius: 8px; margin-bottom: 12px;
}
.feature h3 { font-size: 15.5px; margin: 0 0 6px; }
.feature p { margin: 0; color: var(--muted); font-size: 14.5px; }

/* ---------- formulieren ---------- */
.auth-page { padding: 56px 0 80px; }
.panel {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 14px; padding: 30px 28px; box-shadow: var(--shadow);
}
.panel h1 { font-size: 23px; margin: 0 0 6px; }
.panel .sub { color: var(--muted); font-size: 14.5px; margin: 0 0 22px; }

.field { margin-bottom: 15px; }
.field label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 6px; color: var(--muted); }
.field input, .field select {
  width: 100%; padding: 10px 12px; border-radius: 9px;
  border: 1px solid var(--border); background: var(--bg-soft); color: var(--text);
  font: inherit; font-size: 15px;
}
.field input:focus { border-color: var(--accent); outline: none; }
.field .hint { font-size: 12.5px; color: var(--faint); margin-top: 5px; }
.field .hint.bad { color: var(--bad); }
.field .hint.ok { color: var(--ok); }
.field.code input { font-family: var(--mono); font-size: 22px; letter-spacing: .34em; text-align: center; }

/* honeypot: onzichtbaar voor mensen, aanwezig voor formulierinvullers */
.trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.meter { height: 4px; border-radius: 2px; background: var(--panel-2); margin-top: 8px; overflow: hidden; }
.meter i { display: block; height: 100%; width: 0; background: var(--bad); transition: width .2s, background .2s; }
.meter.ok i { background: var(--ok); }
.meter.mid i { background: var(--warn); }

.msg {
  border-radius: 9px; padding: 11px 13px; font-size: 14px; margin-bottom: 16px;
  border: 1px solid var(--border); background: var(--panel-2); color: var(--muted);
}
.msg.bad { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, transparent); background: color-mix(in srgb, var(--bad) 8%, transparent); }
.msg.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, transparent); background: color-mix(in srgb, var(--ok) 8%, transparent); }
.msg.busy { color: var(--muted); }
.msg[hidden] { display: none; }

.alt.fineprint { color: var(--faint); font-size: 13px; }
.alt { margin-top: 20px; font-size: 14px; color: var(--muted); text-align: center; }
.form-foot { margin-top: 6px; display: flex; justify-content: space-between; align-items: center; font-size: 13.5px; }

/* ---------- account ---------- */
/* De `min(...)` is niet overbodig: op een scherm van 320px is er na de marge van
   de wrapper minder dan 320px over, en dan duwt een kale minmax(320px) de hele
   pagina breder dan het toestel. */
/* Panelen strekken mee tot de hoogte van hun rij. Met `align-items: start`
   hield elk kort paneel op waar zijn inhoud ophield, terwijl de rij pas eindigde
   bij het langste paneel - dat gaf gaten van honderden pixels tussen de rijen en
   randen die nergens uitkwamen. Nu is de tussenruimte overal exact de gap. */
.acct-grid { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); align-items: stretch; }
.acct-grid > .panel { display: flex; flex-direction: column; }
.acct-head { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-bottom: 26px; }
.acct-head .who { font-size: 22px; font-weight: 620; }
.acct-head .spacer { margin-left: auto; }
.acct-head .sub { color: var(--faint); font-family: var(--mono); font-size: 13px; }
.panel h2 { font-size: 16px; margin: 0 0 4px; }
.panel .panel-sub { color: var(--muted); font-size: 13.5px; margin: 0 0 18px; }
.kv { display: grid; grid-template-columns: auto 1fr; gap: 8px 16px; font-size: 14px; margin-bottom: 18px; }
.kv dt { color: var(--faint); font-family: var(--mono); font-size: 12.5px; }
.kv dd { margin: 0; }
.codes { font-family: var(--mono); font-size: 14px; background: var(--bg-soft); border: 1px solid var(--border);
  border-radius: 9px; padding: 14px; columns: 2; column-gap: 20px; margin: 14px 0; }

/* QR bij het instellen van 2FA. Het witte vlak en de stille zone zitten in de
   SVG zelf (zonder allebei leest geen scanner een code op een donkere pagina);
   hier staat alleen hoe groot hij mag worden. Nooit breder dan het scherm: dit
   is bij uitstek iets wat je op een telefoon doet. */
.qr { margin: 14px 0; }
.qr svg { display: block; width: min(236px, 100%); height: auto; border-radius: 10px; }

/* ---------- tabel / lijst ---------- */
.list { border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.list .row { display: flex; justify-content: space-between; gap: 12px; padding: 11px 14px; font-size: 14px; }
.list .row + .row { border-top: 1px solid var(--border-soft); }
.list .row .sub { color: var(--faint); font-family: var(--mono); font-size: 12px; }

/* ---------- footer ---------- */
.site-foot {
  border-top: 1px solid var(--border-soft); margin-top: 40px; padding: 34px 0 50px;
  color: var(--faint); font-size: 13.5px;
}
.site-foot .wrap { display: flex; gap: 18px; flex-wrap: wrap; align-items: center; }
.site-foot a { color: var(--muted); }
.site-foot .spacer { margin-left: auto; }

/* ---------- prose (legal) ---------- */
.prose { max-width: 72ch; padding: 46px 0 60px; }
.prose h1 { font-size: 28px; margin: 0 0 10px; }
.prose h2 { font-size: 17px; margin: 32px 0 8px; }
.prose p, .prose li { color: var(--muted); }
.prose .updated { font-family: var(--mono); font-size: 12.5px; color: var(--faint); }

@media (max-width: 760px) {
  /* Op een smal scherm loopt de tekst over de volle breedte; dan is de
     constellatie geen achtergrond meer maar ruis. Alleen de gloed blijft. */
  /* Op smal beeld staat de tekst over de volle breedte: dan mag de sfeer
     zachter, anders leest het als vuil op het scherm. */
  .sweep { opacity: .2; }
  .sweep-2 { opacity: .1; }
  .grain { opacity: .04; }
  .suite-head { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 620px) {
  .site-nav { gap: 14px; font-size: 14px; }
  .site-nav .hide-sm { display: none; }
  .hero { padding: 52px 0 40px; }
  .codes { columns: 1; }
}

/* ---------- minder beweging ----------
   Niet optioneel: wie dit aan heeft staan krijgt dezelfde pagina, stil. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .sweep { animation: none; transform: rotate(-16deg) translate3d(38vw, 0, 0); }
  .sweep-2 { transform: rotate(-16deg) translate3d(64vw, 0, 0); }
  .track { scroll-behavior: auto; }
  .slide { transform: none; opacity: 1; }
  * { transition-duration: .01ms !important; }
}

/* ---------- beheerpagina ----------
   Eén scherm waarop alles staat: wie er is, wie erin mag, wat er draait en wat
   de update-server uitdeelt. Een tabel en niet nóg een raster kaartjes: dit is
   een lijst die je scant en waarin je iets aanklikt. */
.admin-head { margin-bottom: 26px; }
.admin-head h1 { font-size: clamp(28px, 4vw, 40px); margin: 0 0 10px; }
.admin-head .lead { color: var(--muted); max-width: 62ch; margin: 0; }

.stats {
  display: grid; gap: 14px; margin-bottom: 26px;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.stat {
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--panel); padding: 16px 18px;
}
.stat b {
  display: block; font-family: var(--display); font-size: 30px;
  font-weight: 700; line-height: 1; letter-spacing: -.03em; margin-bottom: 6px;
}
.stat span { font-size: 13px; color: var(--muted); }
.stat.accent b { color: var(--accent); }

.admin-panel { margin-bottom: 22px; }
.table-wrap { overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; font-size: 14px; min-width: 720px; }
.table th {
  text-align: left; font-weight: 600; font-size: 12px; color: var(--faint);
  text-transform: uppercase; letter-spacing: .06em;
  padding: 0 12px 10px 0; border-bottom: 1px solid var(--border);
}
.table td { padding: 12px 12px 12px 0; border-bottom: 1px solid var(--border-soft); vertical-align: middle; }
.table tr:last-child td { border-bottom: 0; }
.table .who b { display: block; }
.table .who span { color: var(--faint); font-family: var(--mono); font-size: 12px; }
.table select {
  background: var(--panel-2); color: var(--text); border: 1px solid var(--border);
  border-radius: 8px; padding: 5px 8px; font: inherit; font-size: 13px;
}
.table .row-actions { text-align: right; white-space: nowrap; }
/* Niet meer aan `.table` gebonden: deze knopjes staan inmiddels ook in de
   inhoudsbeheerder, en daar kreeg je zonder deze regels de knoppen van de
   browser - lichte blokjes in een donkere pagina. */
.mini {
  border: 1px solid var(--border); background: transparent; color: var(--muted);
  border-radius: 8px; padding: 5px 10px; font: inherit; font-size: 12.5px; cursor: pointer;
  transition: color .14s var(--ease), border-color .14s var(--ease);
}
.mini:hover { color: var(--text); border-color: var(--faint); }
.mini.danger { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 35%, transparent); }
.mini.danger:hover { background: color-mix(in srgb, var(--bad) 10%, transparent); }
.mini[disabled] { opacity: .35; cursor: not-allowed; }

.switch { display: flex; gap: 10px; align-items: flex-start; font-size: 14px; color: var(--muted); margin-bottom: 16px; }
.switch input { margin-top: 3px; accent-color: var(--accent); }
.policy-actions { margin-top: 4px; }

@media (max-width: 620px) {
  .stat b { font-size: 24px; }
}

/* ==========================================================================
   Hoofdsite (ninjastic2008.com): dashboard, productkaarten en rechten.
   Gebruikt dezelfde tokens als de rest; alleen wat er hier bij komt staat hier.
   ========================================================================== */

.linkish {
  border: 0; background: none; padding: 0; cursor: pointer;
  font: inherit; font-size: 11px; color: var(--accent);
  text-decoration: underline; text-underline-offset: 2px;
}
.linkish:disabled { opacity: .5; cursor: not-allowed; }
.dash-lead { margin: 6px 0 0; color: var(--muted); font-size: 14px; max-width: 60ch; }

/* ==========================================================================
   Voorpagina: het werk. Rustig, weinig kleur, veel lucht - de projecten zijn
   de inhoud, de opmaak hoort niet mee te praten.
   ========================================================================== */

/* De hero is hier lager dan op een productpagina: er staat één zin, en die
   hoeft geen heel scherm te vullen. */
.hero-lead { padding: clamp(72px, 12vw, 132px) 0 clamp(56px, 8vw, 96px); }
.hero-lead .eyebrow { display: block; margin-bottom: 18px; }
.hero-lead h1 {
  font-size: clamp(36px, 6vw, 68px);
  font-weight: 800; margin: 0 0 24px; max-width: 18ch;
}
.hero-lead .lead { max-width: 56ch; }

/* ---------- projecten ---------- */
.work { padding: clamp(48px, 7vw, 88px) 0; border-top: 1px solid var(--border-soft); }
.work-head { max-width: 62ch; margin-bottom: clamp(28px, 4vw, 44px); }
.work-head h2 { font-size: clamp(26px, 3.4vw, 38px); margin: 0 0 10px; }
.work-head p { margin: 0; color: var(--muted); }

.work-list { list-style: none; margin: 0; padding: 0; }

/* Eén rij per project. Geen kaarten met randen: een lijst leest als een
   inhoudsopgave van het werk, en dat is precies wat het is. */
.work-item {
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr) auto;
  gap: 20px;
  align-items: start;
  padding: clamp(20px, 2.6vw, 30px) 0;
  border-top: 1px solid var(--border-soft);
}
.work-item:last-child { border-bottom: 1px solid var(--border-soft); }

.work-no {
  font-size: 12px; color: var(--faint); padding-top: 6px;
  font-variant-numeric: tabular-nums;
}
.work-body h3 { font-size: clamp(19px, 2.2vw, 25px); margin: 0 0 8px; }
.work-body h3 a { color: var(--text); }
/* Het onderstrepen gebeurt hier met een lijn die groeit, niet met de standaard
   onderstreping: die springt en trekt de aandacht naar de link in plaats van
   naar de naam. */
.work-body h3 a {
  background-image: linear-gradient(var(--accent), var(--accent));
  background-size: 0% 1px; background-position: 0 100%; background-repeat: no-repeat;
  transition: background-size .35s var(--ease), color .2s var(--ease);
  text-decoration: none;
}
.work-body h3 a:hover, .work-body h3 a:focus-visible {
  color: var(--accent); background-size: 100% 1px; text-decoration: none;
}
.work-body p { margin: 0; color: var(--muted); font-size: 15px; max-width: 62ch; }

.work-meta {
  display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
  text-align: right; padding-top: 4px;
}
.work-meta .mono { font-size: 11.5px; color: var(--faint); white-space: nowrap; }

@media (max-width: 640px) {
  /* Op een telefoon staat het nummer boven de naam in plaats van ernaast, en
     de stand eronder - anders wordt de middenkolom een woord breed. */
  .work-item { grid-template-columns: 1fr; gap: 10px; }
  .work-no { padding-top: 0; }
  .work-meta { flex-direction: row; align-items: center; text-align: left; }
}

/* ---------- infrastructuur ---------- */
.infra {
  padding: clamp(48px, 7vw, 88px) 0;
  background: var(--bg-soft);
  border-top: 1px solid var(--border-soft);
  border-bottom: 1px solid var(--border-soft);
}
.infra-grid {
  display: grid; gap: clamp(24px, 4vw, 48px);
  grid-template-columns: minmax(0, 1.4fr) minmax(240px, 1fr);
  align-items: start;
}
@media (max-width: 760px) { .infra-grid { grid-template-columns: 1fr; } }
.infra-lead h2 { font-size: clamp(24px, 3vw, 32px); margin: 0 0 14px; }
.infra-lead p { color: var(--muted); margin: 0 0 14px; max-width: 58ch; }
.infra-lead .btn { margin-top: 6px; }

.infra-figures {
  display: grid; gap: 1px; margin: 0;
  background: var(--border-soft); border: 1px solid var(--border-soft);
  border-radius: var(--radius); overflow: hidden;
}
.infra-figures > div { background: var(--panel); padding: 18px 20px; }
.infra-figures dt { font-size: 12.5px; color: var(--faint); margin-bottom: 4px; }
.infra-figures dd { margin: 0; }

/* ---------- toegang (op de accountpagina) ---------- */
.access {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--panel); padding: 16px 18px;
  display: flex; flex-direction: column; gap: 8px;
}
/* Alleen wat je hébt krijgt een accentrand. "Je hebt dit niet" is geen fout en
   hoort dus geen waarschuwingskleur te krijgen. */
.access.has { border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); }
.access-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.access-head b { font-size: 15.5px; }
.access-note { font-size: 11.5px; color: var(--faint); margin: 0; min-height: 1.2em; }
.access-ask { font-size: 13px; color: var(--muted); margin: 4px 0 0; }
.access .btn { margin-top: auto; align-self: flex-start; }
.grid-products {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}

.figure { font-family: var(--mono); font-size: clamp(19px, 2.4vw, 25px); font-weight: 600; letter-spacing: -.02em; color: var(--text); font-variant-numeric: tabular-nums; }
.figure .dec { color: var(--muted); }
.figure .unit { font-size: .62em; color: var(--faint); margin-left: 1px; }

/* Een klasse met `display` verslaat de browserregel voor [hidden]; zonder dit
   staat een verborgen knop gewoon in beeld. Geldt voor elk element dat hier een
   eigen display-waarde krijgt, dus generiek opgelost. */
[hidden] { display: none !important; }

/* ==========================================================================
   Detailpagina van een item, en de bewerker in het beheerscherm.
   ========================================================================== */

.item { padding: clamp(44px, 6vw, 80px) 0 clamp(48px, 7vw, 88px); }
.item h1 { font-size: clamp(30px, 4.6vw, 50px); font-weight: 800; margin: 10px 0 16px; max-width: 20ch; }
.item .lead { color: var(--muted); max-width: 62ch; font-size: clamp(15.5px, 1.4vw, 18px); margin: 0 0 18px; }
.item-meta { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.item-meta .mono { font-size: 12px; color: var(--faint); }

/* De leesbreedte is smaller dan de pagina: lange regels lezen slecht, en dit is
   het enige deel van de site waar echt gelezen wordt. */
.item-body { max-width: 68ch; margin-top: clamp(26px, 4vw, 40px); }
.item-body h2 { font-size: clamp(20px, 2.4vw, 26px); margin: 32px 0 10px; }
.item-body p { color: var(--muted); margin: 0 0 14px; }
.item-body figure { margin: 22px 0; }
.item-body img { display: block; width: 100%; height: auto; border-radius: var(--radius); border: 1px solid var(--border); }
.item-body figcaption { font-size: 12.5px; color: var(--faint); margin-top: 8px; }
.item-back { margin-top: 40px; font-size: 14.5px; }
.work-empty { color: var(--faint); font-family: var(--mono); font-size: 13px; padding: 18px 0; list-style: none; }

/* ---------- bewerker ---------- */
.panel-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.form-grid {
  display: grid; gap: 14px; margin: 18px 0 14px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.form-grid label, label.wide { display: flex; flex-direction: column; gap: 6px; font-size: 13.5px; color: var(--muted); }
label.wide { margin-bottom: 8px; }
.form-grid label.check { flex-direction: row; align-items: center; gap: 8px; }
.form-grid input, .form-grid select, label.wide textarea, .block input, .block textarea {
  font: inherit; font-size: 14.5px; color: var(--text);
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 9px;
  padding: 9px 11px;
}
.form-grid input:focus, .form-grid select:focus, label.wide textarea:focus, .block input:focus, .block textarea:focus {
  outline: 2px solid var(--accent); outline-offset: 1px;
}
.form-grid input[type="checkbox"] { width: auto; accent-color: var(--accent); }

.blocks-head { font-size: 15px; margin: 22px 0 10px; }
.blocks { display: flex; flex-direction: column; gap: 12px; }
.block { border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-soft); padding: 12px 14px; }
.block-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.block-head .mono { font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--faint); }
.block-body { display: flex; flex-direction: column; gap: 10px; }
.block-body label { display: flex; flex-direction: column; gap: 5px; font-size: 12.5px; color: var(--muted); }
.block-preview img { max-width: 220px; border-radius: 8px; border: 1px solid var(--border); margin-top: 6px; }
.blocks-add { margin-top: 14px; }
.blocks-add .btn { font-size: 13px; padding: 7px 12px; }


/* ---------- beheerlijst voor de inhoud ----------
   De inhoudsbeheerder is het werkblad van deze pagina, geen zijpaneel: over de
   volle breedte, met vier kolommen die altijd op hun plek staan. */
.admin-wide { grid-column: 1 / -1; }

.clist { display: flex; flex-direction: column; gap: 8px; margin-top: 18px; }

.citem {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) auto;
  gap: 16px; align-items: center;
  padding: 12px 14px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--bg-soft);
  transition: border-color .14s var(--ease);
}
.citem:hover { border-color: var(--faint); }
/* Een concept staat er wel, maar telt nog niet mee. Dat hoort te zien te zijn
   zonder dat je het label leest. */
.citem.is-draft { opacity: .72; border-style: dashed; }

.citem-move { display: flex; flex-direction: column; gap: 3px; }
.citem-main { min-width: 0; }
.citem-title { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 15px; }
.citem-target {
  display: flex; align-items: baseline; gap: 8px;
  font-size: 12px; color: var(--faint); margin-top: 3px; min-width: 0;
}
.citem-kind {
  flex: none; font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--faint); opacity: .8;
}
.citem-where { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.citem-actions { display: flex; gap: 6px; flex: none; }

/* De pijltjes zijn knoppen zonder tekst; zonder vaste maat worden het blokjes
   van verschillende breedte zodra er één uit staat. */
.mini.icon {
  width: 26px; height: 20px; padding: 0; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}

@media (max-width: 620px) {
  /* Op een smal scherm onder elkaar: drie kolommen van 90 pixels leest niemand. */
  .citem { grid-template-columns: 30px minmax(0, 1fr); }
  .citem-actions { grid-column: 2; justify-content: flex-start; }
}

/* De knop hoort naast de uitleg, niet eronder: zonder een grens op de tekst
   neemt die de hele breedte en wordt de knop naar de volgende regel geduwd. */
.panel-head > div:first-child { max-width: 70ch; }
.panel-head > .btn, .panel-head > .btn-row { flex: none; }
.panel-head .panel-sub { margin-bottom: 0; }

/* ---------- bewerker: bereikbaar blijven ----------
   De pagina heeft een plakkende koptekst. Zonder deze marge schuift
   scrollIntoView de bewerker er precies achter, en dan staat de opslaanknop
   onder de balk waar je hem niet ziet. */
[data-editor] { scroll-margin-top: 76px; }

/* Het formulier is lang; Opslaan hoort niet alleen bovenaan te bestaan. De kop
   blijft daarom binnen het paneel meelopen. */
[data-editor] .panel-head {
  position: sticky; top: 60px; z-index: 2;
  background: var(--panel);
  padding: 12px 0; margin: -12px 0 0;
  border-bottom: 1px solid var(--border-soft);
}

/* Het bestandsveld van de browser is een lichte knop in een donkere pagina.
   Alleen de knop erin is te stylen, en dat is precies genoeg. */
.block input[type="file"] {
  padding: 8px; color: var(--muted); font-size: 13px;
  background: var(--panel); border: 1px dashed var(--border);
}
.block input[type="file"]::file-selector-button {
  font: inherit; font-size: 12.5px; cursor: pointer; margin-right: 10px;
  color: var(--text); background: var(--panel-2);
  border: 1px solid var(--border); border-radius: 8px; padding: 5px 10px;
}
.block input[type="file"]::file-selector-button:hover { border-color: var(--faint); }

/* De knop per project. Staat in de rechterkolom onder de stand, zodat de rij
   rustig blijft maar er onmiskenbaar iets te klikken valt. */
.work-cta {
  font-size: 13px; padding: 7px 13px; margin-top: 4px;
  border-color: color-mix(in srgb, var(--accent) 35%, var(--border));
  color: var(--accent);
}
.work-cta:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}
@media (max-width: 640px) {
  /* Onder elkaar staat de knop links, in de leesrichting. */
  .work-meta { align-items: flex-start; }
  .work-cta { margin-top: 6px; }
}

/* De voorpagina toont een selectie; deze regel zegt waar de rest staat. */
.work-more { margin: 26px 0 0; font-size: 14.5px; }
.work-page .work-head h1 { font-size: clamp(30px, 4.4vw, 46px); margin: 8px 0 12px; }
.work-page { padding-top: clamp(36px, 5vw, 64px); border-top: 0; }

/* De knoppenbalk van de bewerker: stand links, knoppen rechts. */
.editor-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.editor-state { font-size: 11.5px; color: var(--faint); margin-right: 4px; }

/* ---------- rechten per product in de beheertabel ----------
   Een regel per product met een niveau ernaast. De losse bevoegdheden staan
   eronder en alleen als iemand "Specific" kiest: anders staat er bij elk
   account een waslijst die niemand leest. */
.grants { display: flex; flex-direction: column; gap: 10px; min-width: 260px; }
.grant { display: flex; flex-direction: column; gap: 6px; }
.grant-head { display: flex; align-items: center; gap: 8px; }
.grant-name { font-size: 13px; color: var(--muted); flex: 1; min-width: 0; }
/* Wat van de rol afwijkt hoort op te vallen: dat is het geval waarin iemand
   zich later afvraagt waarom dit account iets wel of niet kan. */
.grant.explicit .grant-name { color: var(--text); font-weight: 550; }
.grant select {
  font: inherit; font-size: 12.5px; color: var(--text);
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 8px;
  padding: 4px 8px;
}
.grant select:disabled { opacity: .5; }
.pill.tiny { font-size: 9.5px; padding: 2px 6px; }

.grant-caps {
  display: flex; flex-direction: column; gap: 4px;
  margin: 2px 0 4px 10px; padding-left: 10px;
  border-left: 1px solid var(--border-soft);
}
.cap { display: flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--muted); cursor: pointer; }
.cap input { accent-color: var(--accent); margin: 0; }
/* Een bevoegdheid die nog nergens de deur dichthoudt, moet dat zeggen. Anders
   belooft het scherm toegangscontrole die er niet is. */
.cap.soft span:first-of-type { opacity: .8; }
.cap-soft { font-size: 9.5px; color: var(--warn); letter-spacing: .04em; }

/* ---------- GitHub-paneel op de accountpagina ---------- */
.gh-linked { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.gh-avatar { width: 40px; height: 40px; border-radius: 50%; background: var(--panel-2); }
.gh-login { font-weight: 600; font-size: 15px; }
.gh-since { color: var(--faint); font-size: 12.5px; font-family: var(--mono); }


/* ---------- projecten: filteren en bladeren ----------
   De lijst was er een die alleen maar langer werd. Met honderd projecten is
   "alles onder elkaar" geen overzicht meer maar een rol papier, dus staat er nu
   een filter boven en tien per pagina in. */
.work-tools {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
  margin-bottom: 18px;
}
.work-tools[hidden] { display: none; }
.work-search { flex: 1 1 220px; max-width: 320px; display: block; }
.work-search input {
  width: 100%; padding: 9px 13px; border-radius: 9px;
  border: 1px solid var(--border); background: var(--bg-deep); color: var(--text);
  font: inherit; font-size: 14.5px;
}
.work-search input:focus { border-color: var(--accent); outline: none; }

.work-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  padding: 6px 13px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border); background: transparent; color: var(--muted);
  font: inherit; font-size: 13px;
  transition: color .14s var(--ease), border-color .14s var(--ease), background .14s var(--ease);
}
.chip:hover { color: var(--text); border-color: var(--faint); }
.chip.aan { color: var(--accent); border-color: var(--accent-dim); background: var(--accent-soft); }
.chip-scheiding {
  width: 1px; align-self: stretch; margin: 2px 4px;
  background: var(--border-soft);
}

.work-count { margin: 0 0 6px; font-size: 12px; color: var(--faint); min-height: 1.2em; }

/* De bladerbalk. Nummers en niet alleen pijltjes: bij tien pagina's wil je in
   één klik naar de laatste kunnen. */
.work-pager {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin-top: 26px;
}
.work-pager[hidden] { display: none; }
.pager-knop, .pager-nr {
  border: 1px solid var(--border); background: transparent; color: var(--muted);
  border-radius: 9px; font: inherit; font-size: 14px; cursor: pointer;
  padding: 7px 13px;
  transition: color .14s var(--ease), border-color .14s var(--ease), background .14s var(--ease);
}
.pager-nr { min-width: 38px; font-variant-numeric: tabular-nums; }
.pager-knop:hover:not(:disabled), .pager-nr:hover { color: var(--text); border-color: var(--faint); }
.pager-knop:disabled { opacity: .4; cursor: not-allowed; }
.pager-nr.aan { color: var(--accent); border-color: var(--accent-dim); background: var(--accent-soft); }
.pager-gat { color: var(--faint); padding: 0 4px; }

/* Alleen voor schermlezers: het zoekveld heeft een zichtbare suggestie, maar een
   suggestie is geen label. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
