/* ============================================================
   Source Sans 3 -- zelf gehost sinds 31/08/2026.
   Stond hiervoor als <link> naar fonts.googleapis.com in shell()
   (render.mjs). Dat kostte twee extra verbindingen (googleapis +
   gstatic) en, erger, een geketend verzoek: de browser moest eerst
   Googles CSS ophalen voordat hij wist welk lettertypebestand hij
   nodig had -- render-blokkerend, ~230 ms op de kritieke lijn.
   Nu staat @font-face in dit bestand, dat toch al opgehaald wordt,
   dus het woff2 vertrekt meteen mee.

   Even groot als voorheen: Google serveerde voor 400/600/700/900 al
   hetzelfde variabele bestand (één woff2, gewichten 200-900), dus dit
   verandert niets aan het aantal bytes -- enkel aan wie ze levert en
   hoe snel ze op gang komen. Meteen ook geen bezoekersgegevens meer
   naar Google, wat op een site van een jeugdbeweging niet onbelangrijk
   is.

   Variabel lettertype: font-weight is een BEREIK (200-900), zodat ook
   de font-weight: 800 die de CSS hieronder een tiental keer gebruikt
   een echte 800 is i.p.v. een door de browser nagebootste.
   ============================================================ */
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url('../fonts/source-sans-3-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url('../fonts/source-sans-3-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ============================================================
   Chiro Sint-Martinus Westmalle -- design-system mockup
   Huisstijl source: chiro.be huisstijlgids.pdf (official colours)
   ============================================================ */

:root {
  /* Official Chiro Vlaanderen huisstijl */
  --chiro-red: #E1143C;
  --chiro-red-dark: #B10E30;
  --chiro-red-light: #FCE3E9;
  --chiro-blue: #00124D;
  --chiro-beige: #E4D096;

  /* Afdeling colours (confirmed with Stan, age-ascending) */
  --c-sloebers: #8904C0;
  --c-speelclub: #f0d41f;
  --c-rakkers: #008303;
  --c-toppers: #E1143C;
  --c-ketis: #2900FF;
  --c-aspis: #FF8900;
  --c-vb: #6E6E73;

  /* Neutrals */
  --ink: #1C1C1E;
  --ink-soft: #4B4B52;
  --muted: #6E6E76;
  --paper: #FFFFFF;
  --paper-soft: #FAF8F4;
  --paper-warm: #F6F0E4;
  --border: rgba(28, 28, 30, 0.10);
  --border-strong: rgba(28, 28, 30, 0.18);

  /* Type */
  --font-body: "Source Sans 3", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  /* Spacing scale */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 3rem;
  --sp-8: 4.5rem;
  --sp-9: 6.5rem;

  /* Shape -- kept modest on purpose: large, uniform corner-rounding on
     every card/section reads as generic "AI-generated" template design. */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(28,28,30,0.06), 0 1px 1px rgba(28,28,30,0.04);
  --shadow-md: 0 8px 24px rgba(28,28,30,0.10), 0 2px 6px rgba(28,28,30,0.06);
  --shadow-lg: 0 20px 48px rgba(28,28,30,0.16), 0 6px 16px rgba(28,28,30,0.08);

  /* Bar height only -- the logo (.brand .logo-mark, 68px) and the nav type
     (.nav-link, 1rem) are deliberately untouched; the bar was slimmed by
     tightening the padding around them, not by shrinking them. */
  --header-h: 78px;
  --container-w: 1180px;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
}
body {
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--paper);
  line-height: 1.55;
  font-size: 17px;
  -webkit-font-smoothing: antialiased;
  /* Sticky footer: on a short page the footer should sit flush against
     the bottom of the browser window, not float wherever the content
     happens to end. main grows to fill any leftover space; header/footer
     keep their natural size either way. */
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
#main { flex: 1 0 auto; }
img, svg { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; padding: 0; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
input, textarea, select { font: inherit; color: inherit; }
h1, h2, h3, h4 { line-height: 1.15; font-weight: 800; letter-spacing: -0.01em; }
h1 { font-size: clamp(2.1rem, 1.6rem + 2.2vw, 3.4rem); }
h2 { font-size: clamp(1.6rem, 1.35rem + 1.2vw, 2.35rem); }
h3 { font-size: 1.2rem; font-weight: 700; }
p { color: var(--ink-soft); }
.muted { color: var(--muted); }
.small { font-size: 0.875rem; }

/* ---------- Layout primitives ---------- */
.container { max-width: var(--container-w); margin-inline: auto; padding-inline: var(--sp-5); }
.section { padding-block: var(--sp-8); }
.section-tight { padding-block: var(--sp-6); }
.section-head { max-width: 640px; margin-bottom: var(--sp-6); }
.section-head.center { margin-inline: auto; text-align: center; }
/* Homepage section titles: just the short red label (Nieuws, Afdelingen,
   Groepsleiding) at heading size, no separate descriptive sentence. */
.section-title-accent { color: var(--chiro-red); font-size: 2.1rem; margin: 0; }
.section-title-accent a { color: inherit; transition: opacity 0.15s ease; }
.section-title-accent a:hover { opacity: 0.7; }
/* Small red label above a title. Deliberately NOT uppercase with wide
   letter-spacing any more: that treatment turned dates into "21 MEI 2026" and
   ages into "1STE EN 2DE LEERJAAR", which is the single most template-looking
   detail on a page. Same role, read like normal writing. */
.eyebrow {
  display: inline-block;
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--chiro-red);
  margin-bottom: var(--sp-2);
}
/* Reading-column widths. Three named tiers instead of a different inline
   max-width per page: col-read for running text (nieuws, contact), col-doc for
   long documents with tables (privacyverklaring), col-wide for the embedded
   inschrijvingsformulier. .text-col is the bare centring, for elements that
   set their own width. */
.text-col, .col-read, .col-doc, .col-wide { margin-inline: auto; }
.col-read { max-width: 760px; }
.col-doc { max-width: 900px; }
.col-wide { max-width: 1040px; }

.grid { display: grid; gap: var(--sp-5); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
.grid-6 { grid-template-columns: repeat(6, 1fr); }
@media (max-width: 980px) {
  .grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .grid-6 { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 620px) {
  .grid-2, .grid-3, .grid-4, .grid-6 { grid-template-columns: 1fr; }
}
.flex { display: flex; }
.flex-between { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); }
.flex-between.section-head { align-items: flex-end; margin-bottom: var(--sp-6); }
.flex-between.section-head > *:last-child { flex-shrink: 0; padding-bottom: 2px; }
.flex-wrap { flex-wrap: wrap; }
.stack { display: flex; flex-direction: column; gap: var(--sp-2); }
.gap-3 { gap: var(--sp-3); }
/* Text column beside a portrait image: the two sit top-aligned rather than
   stretching the text to the photo's height. */
.split-top { align-items: start; margin-bottom: var(--sp-7); }
/* The second story row mirrors the first: photo hard against the left edge,
   text on the right, so the two photos sit diagonally from one another instead
   of stacking in a column. On one column the text leads and the photo follows,
   because a screen that opens on an image with no heading tells you nothing. */
.split-omgekeerd .prose { grid-row: 1; grid-column: 2; }
.split-omgekeerd > img { grid-row: 1; grid-column: 1; }
@media (max-width: 620px) {
  .split-omgekeerd .prose, .split-omgekeerd > img { grid-row: auto; grid-column: auto; }
  .split-omgekeerd .prose { order: 1; }
  .split-omgekeerd > img { order: 2; }
}
/* Any element that carries an afdeling colour as --accent (page heads, leiding
   profiles) can tint its text with this instead of an inline style. */
.afdeling-accent { color: var(--accent, var(--chiro-red)); }

/* ---------- Skip link ---------- */
.skip-link {
  position: absolute; left: 0; top: -60px;
  background: var(--chiro-red); color: #fff;
  padding: var(--sp-3) var(--sp-5);
  z-index: 1000; border-radius: 0 0 var(--radius-sm) 0;
  transition: top 0.15s ease;
  font-weight: 700;
}
.skip-link:focus { top: 0; }

/* ---------- Focus states ---------- */
a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible {
  outline: 3px solid var(--chiro-blue);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------- Header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: var(--chiro-red);
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s ease;
}
.site-header.is-scrolled { border-bottom-color: rgba(0,0,0,0.15); }
.header-inner {
  min-height: var(--header-h);
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--sp-6);
}
.brand {
  display: flex; align-items: center;
  font-size: 0.98rem; white-space: nowrap; color: #fff;
  padding-block: var(--sp-1);
}
.brand .logo-mark { max-height: 68px; width: auto; }
.logo-mark { filter: brightness(0) invert(1) drop-shadow(0 1px 1px rgba(0,0,0,0.2)); object-fit: contain; }
.main-nav { justify-self: center; min-width: 0; }
.main-nav > ul { display: flex; align-items: center; gap: 4px; }
.nav-item { position: relative; }
.nav-link {
  display: flex; align-items: center; gap: 5px;
  padding: var(--sp-3) 0.75rem;
  font-weight: 600; font-size: 1rem;
  white-space: nowrap;
  border-radius: var(--radius-sm);
  /* Vol wit i.p.v. 92%: wit-op-chirorood haalt 4.81:1, ruim boven de 4.5
     die WCAG voor gewone tekst vraagt -- maar op 92% zakt dat naar 4.22 en
     valt het eronder. Puur de doorzichtigheid weghalen lost dat op zonder
     één letter groter of vetter te maken en zonder aan het rood te raken. */
  color: #fff;
}
/* Label and chevron are one link, so the whole thing highlights as a single
   control and the chevron turns when the menu drops down. */
.nav-parent svg { transition: transform 0.18s ease; }
.nav-item.has-children:hover .nav-parent svg,
.nav-item.has-children:focus-within .nav-parent svg { transform: rotate(180deg); }
/* Hover and the current page share one treatment: a rounded block of
   translucent white behind the label, lighter on hover than on the page you
   are actually on. Nothing changes weight, so the menu never reflows. */
/* Het accent maakt het rood DONKERDER en niet lichter. Met een witte waas
   erover (voorheen 14%/22%) werd de achtergrond juist lichter, en zakte wit
   op wit-op-rood naar 3.78:1 -- onder de 4.5 die WCAG vraagt. Dat was de
   laatste contrastklacht, en ze viel enkel op desktop op: op een telefoon
   zit de navigatie achter het hamburgermenu, dus die labels staan er niet.
   Zwart in plaats van wit geeft precies hetzelfde "opgelichte pil"-effect en
   tilt het contrast naar 6.9:1. */
.nav-link:hover { color: #fff; background: rgba(0,0,0,0.12); }
.nav-link[aria-current="page"] { color: #fff; background: rgba(0,0,0,0.20); }
.submenu {
  position: absolute; top: 100%; left: 0;
  background: var(--paper); border: 1px solid var(--border);
  border-radius: var(--radius-md); box-shadow: 0 6px 16px rgba(28,28,30,0.12);
  min-width: 200px; padding: var(--sp-2);
  opacity: 0; visibility: hidden; transform: translateY(6px);
  transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;
}
.nav-item.has-children:hover .submenu,
.nav-item.has-children:focus-within .submenu {
  opacity: 1; visibility: visible; transform: translateY(0);
}
.submenu li a {
  display: block; padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-sm); font-weight: 600; font-size: 0.92rem;
  color: var(--ink);
}
.submenu li a:hover { background: var(--paper-soft); color: var(--chiro-red); font-weight: 800; }
/* Empty on desktop now that the Inschrijven button is gone -- kept as a
   reserved-width column (roughly matching the logo's width) purely so the
   centred nav balances visually against the logo on the left, instead of
   the empty right edge pulling the optical centre off. */
.header-actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-3); min-width: 52px; }
.hamburger { display: none; flex-direction: column; gap: 5px; padding: var(--sp-2); }
.hamburger span { width: 22px; height: 2px; background: #fff; border-radius: 2px; transition: transform 0.2s ease, opacity 0.2s ease; }
.hamburger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.hamburger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.hamburger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.mobile-nav { display: none; }
@media (max-width: 900px) {
  .main-nav { display: none; }
  .hamburger { display: flex; }
  .mobile-nav {
    display: block;
    border-top: 1px solid var(--border);
    background: var(--paper);
    max-height: calc(100vh - var(--header-h));
    overflow-y: auto;
  }
  .mobile-nav[hidden] { display: none; }
  .mobile-nav > ul { padding: var(--sp-3) var(--sp-5) var(--sp-6); }
  .mobile-nav > ul > li > a { display: block; padding: var(--sp-3) 0; font-weight: 700; font-size: 1.05rem; border-bottom: 1px solid var(--border); }
  .mobile-submenu { padding-left: var(--sp-4); }
  .mobile-submenu a { display: block; padding: var(--sp-2) 0; color: var(--ink-soft); font-weight: 600; }
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  padding: 0.85em 1.5em;
  border-radius: var(--radius-pill);
  font-weight: 700; font-size: 0.95rem;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
  border: 2px solid transparent;
}
.btn-primary { background: var(--chiro-red); color: #fff; }
.btn-primary:hover { background: var(--chiro-red-dark); }
.btn-outline { border-color: var(--chiro-red); color: var(--chiro-red); }
.btn-outline:hover { background: var(--chiro-red-light); }
/* Een <label> die een verborgen bestandsveld draagt was met het toetsenbord
   onbereikbaar zolang dat veld display:none had (helemaal uit de
   focusvolgorde) -- .sr-only laat het veld staan, focusbaar en bedienbaar
   met Enter/spatie zoals elk ander bestandsveld, enkel onzichtbaar. De
   outline moet dan wel op het zichtbare label komen, want de focusring op
   het 1px-veld zelf zou nergens te zien zijn. */
.upload-label { position: relative; }
.upload-label:focus-within { outline: 3px solid var(--chiro-blue); outline-offset: 2px; }
.btn-ghost { color: var(--ink); }
.btn-ghost:hover { background: var(--paper-soft); }
.btn-block { width: 100%; }
.btn-sm { padding: 0.6em 1.15em; font-size: 0.85rem; }
.btn-lg { padding: 1em 2em; font-size: 1.02rem; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* ---------- Badges ---------- */
.badge {
  display: inline-flex; align-items: center;
  padding: 0.3em 0.75em; border-radius: var(--radius-pill);
  font-size: 0.72rem; font-weight: 800; letter-spacing: 0.03em; text-transform: uppercase;
}

/* ---------- Hero ---------- */
/* Full-bleed photo hero with a dark overlay for text contrast -- matches
   the real site's actual homepage (a camp photo with the title on top),
   not an invented gradient. Stan swaps the placeholder for a real photo
   via the Foto's panel in the beheerpaneel. */
.hero {
  position: relative;
  color: #fff;
  overflow: hidden;
  min-height: 650px;
  display: flex;
  align-items: flex-end;
}
.hero-photo {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: 0;
}
.hero::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(20,10,10,0.05) 0%, rgba(15,8,8,0.45) 70%, rgba(10,5,5,0.7) 100%);
  z-index: 1;
}
.hero-inner {
  position: relative; z-index: 2;
  width: 100%;
  padding-block: var(--sp-7);
}
.hero h1 {
  color: #fff;
  text-shadow: 0 2px 12px rgba(0,0,0,0.35);
  margin: 0;
}
.btn-row { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
@media (max-width: 900px) {
  .hero { min-height: 500px; }
  .hero-inner { padding-block: var(--sp-6); }
}
@media (max-width: 480px) {
  .hero { min-height: 400px; }
}

/* ---------- Cards ---------- */
.card {
  display: block; background: var(--paper);
  border: 1px solid var(--border);
  overflow: hidden; transition: border-color 0.15s ease;
  height: 100%;
}
a.card:hover { border-color: var(--border-strong); }
.card-img { width: 100%; aspect-ratio: 16/10; object-fit: cover; background: var(--paper-soft); }
.card-img-square { aspect-ratio: 1/1; }
/* Voor foto's die los op een pagina staan (niet in een .card), zoals de
   sfeerfoto's naast "Wat is Chiro"/"Wie doet mee" en op de afdelingspagina's --
   zelfde lichte afronding als .faq-photo ("Waar komen we samen"). */
.foto-vrijstaand { border-radius: var(--radius-sm); }
.card-body { padding: var(--sp-5); display: flex; flex-direction: column; gap: var(--sp-2); }
.card-body .card-title { font-size: 1.05rem; font-weight: 700; }
.card-link { font-weight: 700; color: var(--chiro-red); font-size: 0.88rem; margin-top: var(--sp-2); }
/* No colour edge and no coloured age text: the afdeling's own page carries
   its colour, the card stays neutral. (The age is muted grey rather than the
   afdeling colour for a second reason -- speelclub's gold and aspi's orange
   are both well under the contrast minimum as text on white.) */
.card-afdeling .eyebrow { color: var(--muted); font-weight: 600; }

/* Homepage nieuws teaser: given more visual weight -- taller photo, bigger
   title, room for the excerpt -- since it's one of only a few sections
   left on the homepage now. */
.card-news .card-img { aspect-ratio: 1/1; }
/* The full post page and its beheerpaneel preview -- same 1:1 as the card
   above and as the crop the beheerpaneel already applies on upload
   (slotConfig() for nieuws-* in admin.js), so the photo isn't cropped once
   at upload time and cropped again, differently, by the page. */
[data-post-body-wrap] .card-img, #preview-photo { aspect-ratio: 1/1; }
.nieuws-grid-home .card-body { padding: var(--sp-6); gap: var(--sp-3); }
.nieuws-grid-home .card-body .card-title { font-size: 1.25rem; }
.nieuws-grid-home .card-body .eyebrow { font-size: 0.8rem; }
.nieuws-grid-home .card-body p { font-size: 0.96rem; }
.nieuws-grid-home .card-link { display: none; }

/* Leiding portraits: circular avatar + name, no card chrome -- matches the
   simple, centered team-directory look of the original site rather than a
   boxed card grid. */
.card-leiding {
  background: transparent; border: none;
}
a.card-leiding:hover { border-color: transparent; }
.card-leiding .card-img { border-radius: 50%; }
.card-leiding .card-body { align-items: center; text-align: center; padding: var(--sp-3) 0 0; }
.card-leiding .card-title { display: flex; flex-direction: column; align-items: center; gap: var(--sp-2); font-size: 0.98rem; }
.card-leiding:hover .card-title { color: var(--chiro-red); }

/* Self-wrapping, centered grid for leiding/groepsleiding avatars -- so a
   half-empty last row centers instead of stretching across the full
   container like the plain card grids do. */
.grid-people {
  grid-template-columns: repeat(auto-fit, minmax(128px, 148px));
  justify-content: center;
  gap: var(--sp-6) var(--sp-5);
}
/* Bigger avatars for the De Leiding overview -- now that the page no
   longer splits attention with an intro paragraph and a separate
   groepsleiding section, the per-afdeling groups can take up more room. */
.grid-people--lg {
  grid-template-columns: repeat(auto-fit, minmax(168px, 200px));
  gap: var(--sp-7) var(--sp-6);
  /* De Leiding overview's heading above this grid is left-aligned, not
     centered -- so the photos should start from that same left edge
     instead of centering as a block whenever a row isn't completely full. */
  justify-content: start;
}

/* De leiding: the whole ploeg as one grid, five to a row. Fifteen people
   divide into rows of five and of three exactly, which is the point of the
   fixed column counts here -- with auto-fit the count drifts with the window
   and the last row ends up half empty again, which is what grouping the
   photos per afdeling did wrong in the first place. */
.grid-ploeg {
  grid-template-columns: repeat(5, minmax(0, 1fr));
  justify-content: stretch;
  /* More air between the rows than between the columns, so the wall reads as
     rows of people and a name never looks attached to the face below it. */
  gap: var(--sp-7) var(--sp-5);
}
/* Name and group belong together, tighter than the card's default gap. */
.grid-ploeg .card-title { gap: var(--sp-1); }
@media (max-width: 900px) { .grid-ploeg { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 440px) { .grid-ploeg { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* The afdeling under the name, in that afdeling's colour -- with no headings
   left on the page it is the only thing that says who belongs together, so it
   carries the colour and the name above it stays plain. */
.card-afdeling-label {
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.01em;
}

/* ---------- Homepage: Over Ons ----------
   Reworked from three equal text tiles into three layers that answer a parent's
   questions in the order they ask them: a facts strip for the four things they
   came for, the story for the ones who want it, and a question list for the
   detail. Same palette and card language as the rest of the page -- the change
   is the reading order, not a new visual style. */

/* Question list. <details> rather than a JS accordion: it works with no
   script, is keyboard- and screen-reader-native, and prints expanded. The
   first one starts open so the block never reads as an empty stack of bars. */
.praktisch-title { margin-top: var(--sp-8); margin-bottom: var(--sp-5); font-size: 1.35rem; }
.faq { border-top: 1px solid var(--border); }
.faq-item { border-bottom: 1px solid var(--border); }
.faq-item summary {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-5) 0;
  font-weight: 700; font-size: 1.08rem; color: var(--ink);
  cursor: pointer; list-style: none;
}
.faq-item summary::-webkit-details-marker { display: none; }
/* Chevron drawn in CSS so there is no icon font or inline SVG per row. */
.faq-item summary::before {
  content: ""; flex: none;
  width: 9px; height: 9px;
  border-right: 2.5px solid var(--chiro-red);
  border-bottom: 2.5px solid var(--chiro-red);
  transform: rotate(-45deg);
  margin-left: 3px; margin-right: var(--sp-2);
  transition: transform 0.18s ease;
}
.faq-item[open] summary::before { transform: rotate(45deg); }
.faq-item summary:hover { color: var(--chiro-red); }
.faq-item summary:focus-visible { outline: 3px solid var(--chiro-blue); outline-offset: 2px; border-radius: 4px; }
.faq-body { padding: 0 0 var(--sp-6) calc(9px + var(--sp-2) + 3px); max-width: 78ch; }
.faq-body p { margin-bottom: var(--sp-3); }
.faq-body p:last-child { margin-bottom: 0; }
.faq-body h3 {
  font-size: 1rem; font-weight: 700; color: var(--ink);
  margin-top: var(--sp-5); margin-bottom: var(--sp-2);
}
.faq-body h3.mt-0 { margin-top: 0; }
/* The lokalen question is the one with a photo -- text and image side by side
   so the answer stays short instead of pushing the next question off-screen. */
.faq-split { display: grid; grid-template-columns: 1fr 320px; gap: var(--sp-6); align-items: start; }
.faq-photo { border-radius: var(--radius-sm); aspect-ratio: 4/3; object-fit: cover; }
@media (max-width: 700px) {
  .faq-split { grid-template-columns: 1fr; }
  .faq-body { padding-left: 0; }
}

/* ---------- Homepage: Inschrijvingen CTA (right under the hero) ---------- */
.cta-band { background: var(--paper); }
.cta-band-inner {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-6);
  padding-block: var(--sp-8); flex-wrap: wrap;
}
.cta-band h2 { font-size: 1.6rem; }
.cta-band p { margin: 0; }
.cta-band .btn { font-size: 1.15rem; padding: 1.05em 2.75em; }
@media (max-width: 700px) {
  .cta-band-inner { flex-direction: column; align-items: flex-start; padding-block: var(--sp-7); }
  .cta-band .btn { width: 100%; }
}

/* ---------- Carousel ----------
   Native scroll-snap rather than a hand-rolled transform: each slide is
   narrower than the viewport so its neighbours peek in on either side
   whenever there's room (desktop/tablet); on narrow phones the slide
   widens to fill the viewport since there's no space left to peek into. */
.carousel-section { padding-block: var(--sp-7); }
.carousel { position: relative; padding-block: var(--sp-2); }
.carousel-viewport {
  position: relative; /* so slide.offsetLeft is relative to the viewport itself, not some other positioned ancestor */
  display: flex;
  gap: var(--sp-4);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding-inline: 19%;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  cursor: grab;
}
.carousel-viewport::-webkit-scrollbar { display: none; }
.carousel-viewport:focus-visible { outline: 3px solid var(--chiro-blue); outline-offset: 3px; }
.carousel-viewport.is-dragging {
  cursor: grabbing;
  scroll-snap-type: none;
  scroll-behavior: auto;
  user-select: none;
}
.carousel-viewport.is-dragging .carousel-img { pointer-events: none; }
.carousel-slide {
  flex: 0 0 62%;
  scroll-snap-align: center;
  scroll-snap-stop: always;
  aspect-ratio: 16/9;
  overflow: hidden;
  opacity: 0.45;
  transform: scale(0.94);
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.carousel-slide.is-active { opacity: 1; transform: scale(1); }
.carousel-img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  -webkit-user-drag: none; user-select: none;
}
.carousel-btn {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 42px; height: 42px; border-radius: 50%;
  background: rgba(20,20,22,0.6); color: #fff;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.15s ease;
  z-index: 2;
}
.carousel-btn:hover { background: rgba(20,20,22,0.8); }
.carousel-btn svg { width: 20px; height: 20px; }
.carousel-prev { left: var(--sp-3); }
.carousel-next { right: var(--sp-3); }
.carousel-dots {
  display: flex; justify-content: center; gap: 0;
  /* Kleiner dan de sp-5 van voorheen omdat de knop zelf nu 32px hoog is:
     de stip komt daardoor optisch op dezelfde plek te staan als vroeger. */
  margin-top: var(--sp-3);
}
/* De knop is de trefzone (24x32), de zichtbare stip wordt in ::before
   getekend. Zo blijft de stip precies even klein en licht als altijd,
   terwijl er met een vinger wel iets te raken valt: 9x9 px lag ver onder de
   24x24 die WCAG 2.5.8 (en Lighthouse) als ondergrens aanhoudt, en de
   stippen lagen bovendien zo dicht op elkaar dat je makkelijk de verkeerde
   foto opende. gap: 0 want de trefzones dragen nu zelf de tussenruimte. */
.carousel-dot {
  width: 24px; height: 32px;
  padding: 0; margin: 0; flex-shrink: 0;
  display: grid; place-items: center;
  background: none; border: none;
  appearance: none; -webkit-appearance: none;
}
.carousel-dot::before {
  content: "";
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--border-strong);
  transition: background 0.15s ease, transform 0.15s ease;
}
.carousel-dot.is-active::before { background: var(--chiro-red); transform: scale(1.25); }
@media (max-width: 900px) {
  .carousel-slide { flex: 0 0 78%; }
  .carousel-viewport { padding-inline: 11%; }
}
@media (max-width: 700px) {
  /* Geen eigen aspect-ratio meer hier: 4/5 (portret) op foto's die zo goed
     als altijd landschap zijn (kampfoto's, groepsfoto's) betekende samen met
     object-fit: cover fors bijsnijden aan beide zijkanten -- precies wat
     opviel op de homepage-carrousel op een telefoon. Nu dezelfde 16/9 als op
     desktop, die met diezelfde foto's al goed werkte. */
  .carousel-slide { flex-basis: 100%; }
  .carousel-viewport { padding-inline: 0; gap: 0; }
  .carousel-btn { width: 36px; height: 36px; }
}
@media (prefers-reduced-motion: reduce) {
  .carousel-viewport { scroll-behavior: auto; }
}

/* ---------- Prose (long-form text pages) ---------- */
/* overflow-wrap guards the privacyverklaring: it contains long unbroken tokens
   ("gegevensbeschermingsautoriteit.be/verzoek-klacht-indienen") that would
   otherwise force the column wider than its container and push the whole
   page sideways instead of wrapping. */
.prose { max-width: 72ch; overflow-wrap: break-word; }
.prose p { margin-bottom: var(--sp-4); font-size: 1.03rem; }
/* Long documents (the privacyverklaring) run h1 -> h2 -> h3 like every other
   page now, so prose only needs those two levels. The h2 is toned down from
   the page-title scale -- a privacy policy's section headings shouldn't shout
   as loudly as the page's own <h1>. */
.prose h2 { font-size: 1.5rem; margin-top: var(--sp-7); margin-bottom: var(--sp-3); }
.prose h3 { font-size: 1.15rem; margin-top: var(--sp-6); margin-bottom: var(--sp-2); }
.prose h2:first-child, .prose h3:first-child { margin-top: 0; }
/* Wide tables need the full column, so the privacyverklaring opts out of the
   72ch reading cap that suits running text. */
.prose-full { max-width: none; }
.prose strong { color: var(--ink); }
.prose hr { border: none; border-top: 1px solid var(--border); margin-block: var(--sp-7); }
.prose ul { list-style: disc; padding-left: 1.3em; margin-bottom: var(--sp-4); }
.prose ul li { margin-bottom: var(--sp-2); font-size: 1.03rem; color: var(--ink-soft); }
.prose ol { list-style: decimal; padding-left: 1.3em; margin-bottom: var(--sp-4); }
.prose ol li { margin-bottom: var(--sp-2); font-size: 1.03rem; color: var(--ink-soft); }
/* Links inside body text otherwise read as inherit-coloured, undecorated text
   -- indistinguishable from a link until you happen to click it. */
.text-link { color: var(--chiro-red); }
.text-link:hover { color: var(--chiro-red-dark); text-decoration: underline; }
.prose table { width: 100%; border-collapse: collapse; margin-bottom: var(--sp-5); font-size: 0.95rem; }
.prose table td, .prose table th { border: 1px solid var(--border); padding: var(--sp-3) var(--sp-4); vertical-align: top; }
/* Column headers used to be an <h6> inside a plain <td>, which read as a
   heading to a screen reader but told it nothing about the column. Real <th
   scope="col"> cells announce the column each cell belongs to instead. */
.prose table th { text-align: left; background: var(--paper-soft); font-weight: 800; color: var(--ink); }
.page-head { padding-block: var(--sp-7) var(--sp-5); }
.page-head h1 { margin-bottom: var(--sp-3); }

/* ---------- Contact blocks ---------- */
.contact-people { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-4); margin-block: var(--sp-5); }
.person-card { background: var(--paper-soft); border-radius: var(--radius-md); padding: var(--sp-5); display: flex; gap: var(--sp-4); align-items: center; }
/* Vaste maat, niet de width:100% die .card-img standaard meegeeft. Als
   flex-item betekent die 100% namelijk "de volle breedte van de kaart", en
   of hij daarna nog terugkrimpt naast de tekst verschilt per browser: Chrome
   deed dat wel, Safari en Firefox niet -- daar vulde de foto de hele kaart en
   liep hij over de namen heen. Met een expliciete maat is er niets meer om
   over te onderhandelen. 88px is ook de maat waarop personCard() de foto
   uitlevert (zie lib/render.mjs), dus dit is geen verkleining van het origineel. */
.person-card .card-img {
  width: 88px; height: 88px; flex-shrink: 0;
  border-radius: 50%;
}
.person-card .person-name { font-size: 1rem; font-weight: 700; margin-bottom: 2px; }
.person-card a { color: var(--chiro-red); font-weight: 600; font-size: 0.9rem; }
/* Homepage groepsleiding: two distinct cards (white, bordered, shadowed --
   pops against the section's off-white background) at a slightly smaller
   size than the Contact page's full version. */
@media (max-width: 700px) { .contact-people { grid-template-columns: 1fr; } }



/* ---------- Contact ---------- */
.lead { font-size: 1.12rem; color: var(--ink-soft); margin-bottom: var(--sp-6); }

/* The answer nearly every visitor came for, given the room it deserves: a big
   plain address between two rules, not a button. An e-mail address is
   something you read and copy, so it is set as text rather than dressed up as
   a call to action. */
.mail-cta { display: block; padding-block: var(--sp-2); }

/* "Terug naar nieuws": a way back, not an action -- so a plain red text link
   under a hairline instead of an outlined pill competing with the article. */
.terug-link {
  margin-top: var(--sp-8); padding-top: var(--sp-5);
  border-top: 1px solid var(--border);
}
.terug-link a {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  color: var(--chiro-red); font-weight: 700; font-size: 0.96rem;
}
.terug-link a span { transition: transform 0.15s ease; }
.terug-link a:hover span { transform: translateX(-3px); }
/* Zelfde streepje-plus-tekstlink onderaan een pagina, maar vooruit in plaats
   van terug (de link naar /oud-leiding/): enkel de pijlrichting verschilt. */
.terug-link--vooruit a:hover span { transform: translateX(3px); }
.mail-cta-label { display: block; font-size: 0.92rem; color: var(--muted); margin-bottom: 4px; }
.mail-cta-address {
  display: block;
  font-size: clamp(1.3rem, 0.95rem + 1.6vw, 1.85rem);
  font-weight: 800; color: var(--chiro-red); line-height: 1.2;
  overflow-wrap: break-word;
}

.contact-h2 { font-size: 1.45rem; margin-top: var(--sp-8); margin-bottom: var(--sp-5); }
.contact-h3 { font-size: 1.02rem; color: var(--muted); font-weight: 700; margin-bottom: var(--sp-3); }
.contact-people + .contact-h3 { margin-top: var(--sp-6); }
.contact-note { margin-top: var(--sp-5); font-size: 0.96rem; }
.contact-note a { color: var(--chiro-red); font-weight: 700; }
.contact-outro {
  margin-top: var(--sp-8); padding-top: var(--sp-5);
  border-top: 1px solid var(--border); color: var(--muted); font-size: 0.96rem;
}

/* Practical details as label/value rows. This replaces the beige bordered box,
   which was the one thing on the page that looked like a component instead of
   like information -- and it matches the hairline rhythm used elsewhere. */
.detail-list { display: grid; gap: var(--sp-4); }
.detail-list > div {
  display: grid; grid-template-columns: 200px 1fr; gap: var(--sp-4);
  align-items: baseline;
}
.detail-list dt { color: var(--muted); font-weight: 600; }
.detail-list dd { margin: 0; font-weight: 700; color: var(--ink); }
@media (max-width: 560px) {
  .detail-list > div { grid-template-columns: 1fr; gap: 2px; }
}

/* Short line under a homepage section title. */
.section-lead { margin-top: var(--sp-3); }
/* Age line under an afdeling card's name -- reads as a caption, not a label. */
.card-age { margin-bottom: 0; color: var(--muted); font-weight: 600; font-size: 0.92rem; }

/* ---------- Agenda ----------
   One row shape for every kind of entry, weighted by how much attention it
   deserves. An ordinary Sunday is the quietest thing on the page -- there are
   43 of them and they all say the same -- while a cancelled Sunday, an event, a
   weekend and camp get progressively more emphasis. No cards, no shadows: the
   left-hand date chips give the list its structure. */
.ag-locatie { font-size: 0.95rem; margin-top: calc(var(--sp-4) * -1); margin-bottom: var(--sp-6); }

/* Cancelled Sundays, lifted to the top of the page. Missing one of these is
   the most costly thing a parent can miss on the whole site. */
.ag-uitzonderingen {
  border: 1px solid var(--chiro-red);
  padding: var(--sp-5);
  margin-bottom: var(--sp-8);
}
.ag-uitzonderingen h2 { font-size: 1.1rem; color: var(--chiro-red); margin-bottom: var(--sp-3); }
.ag-uitzonderingen ul { display: grid; gap: var(--sp-3); }
.ag-uitzonderingen li { display: grid; gap: 2px; font-size: 0.96rem; }
.ag-uitzonderingen strong { color: var(--ink); }
.ag-uitzonderingen span { color: var(--muted); }

.ag-maand + .ag-maand { margin-top: var(--sp-7); }
.ag-maand-titel {
  font-size: 1.05rem; color: var(--chiro-red);
  padding-bottom: var(--sp-2); margin-bottom: var(--sp-2);
  border-bottom: 2px solid var(--chiro-red);
}
.ag-lijst { display: grid; }

.ag-rij {
  display: grid;
  grid-template-columns: 62px 1fr;
  gap: var(--sp-4);
  padding-block: var(--sp-3);
  border-bottom: 1px solid var(--border);
  align-items: baseline;
}
.ag-datum { text-align: center; line-height: 1.1; }
/* Grid children refuse to shrink below their content by default, so a long
   address would push the row wider than the column instead of wrapping. */
.ag-inhoud { min-width: 0; overflow-wrap: break-word; }
.ag-dag { display: block; font-size: 0.74rem; color: var(--muted); text-transform: lowercase; }
.ag-nr { display: block; font-size: 1.25rem; font-weight: 800; color: var(--ink); }
.ag-reeks { display: block; font-size: 0.8rem; font-weight: 700; color: var(--ink); }
.ag-titel { margin: 0; font-weight: 700; color: var(--ink); }
.ag-meta { margin: 2px 0 0; font-size: 0.92rem; color: var(--muted); }
.ag-omschrijving { margin: var(--sp-2) 0 0; font-size: 0.92rem; color: var(--ink-soft); }
/* Small grey word after a title saying what kind of thing this is. */
.ag-soort {
  margin-left: var(--sp-3); font-size: 0.78rem; font-weight: 600;
  color: var(--muted);
}

/* An ordinary Sunday: present, checkable, but not competing for attention. */
.ag-rij.is-standaard .ag-nr { font-weight: 600; color: var(--ink-soft); }
.ag-rij.is-standaard .ag-titel { font-weight: 600; color: var(--ink-soft); }

/* A Sunday that does not run. */
.ag-geen-chiro .ag-titel { color: var(--chiro-red); }
.ag-geen-chiro .ag-nr { color: var(--chiro-red); }

/* Away-from-home entries carry their location, so they read heavier anyway. */
.ag-weekend .ag-titel, .ag-kamp .ag-titel, .ag-activiteit .ag-titel { font-weight: 800; }
.ag-kamp .ag-nr, .ag-weekend .ag-nr { font-size: 1.05rem; }

/* A stretch of time rather than a day. */
.ag-periode { background: var(--paper-warm); }
.ag-periode .ag-titel { color: var(--ink); }

/* Marked by assets/js/main.js once the page loads -- a date that has passed
   stays visible (the whole year is useful context) but steps back. */
.ag-rij.is-voorbij { opacity: 0.45; }
.ag-rij.is-volgende { background: var(--chiro-red-light); }
.ag-rij.is-volgende .ag-titel::after {
  content: "eerstvolgende";
  margin-left: var(--sp-3); font-size: 0.72rem; font-weight: 700;
  color: var(--chiro-red);
}
@media (max-width: 520px) {
  .ag-rij { grid-template-columns: 52px 1fr; gap: var(--sp-3); }
  .ag-soort { display: block; margin-left: 0; }
}

/* ---------- Vriendenboekje ---------- */
.vb-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-4); margin-top: var(--sp-6); }
.vb-item { padding: var(--sp-4); background: var(--paper-soft); border-radius: var(--radius-md); }
.vb-item dt { font-size: 0.82rem; font-weight: 700; color: var(--chiro-red); margin-bottom: 4px; }
.vb-item dd { font-weight: 600; }
.profile-head { display: flex; align-items: center; gap: var(--sp-5); }
/* Zelfde reden als bij .person-card hierboven: dit is óók een flex-rij, dus
   naast een vaste breedte hoort hier flex-shrink: 0, anders mag de browser
   de foto alsnog smaller maken als de naam ernaast lang is. */
.profile-head .card-img { width: 140px; height: 140px; flex-shrink: 0; border-radius: 50%; }
@media (max-width: 700px) {
  .vb-grid { grid-template-columns: 1fr; }
  .profile-head { flex-direction: column; text-align: center; }
}

/* The old dranklijst mock (tabs, .drank-*, colour picker) was removed here
   -- /dranklijst/ is now Stan's real standalone tool, served as-is with
   its own inline CSS/JS (no shared header/footer/assets). */

/* ---------- Footer ----------
   One slim bar -- matches the real site, not an invented multi-column
   layout: copyright left, social icons centre, a few links right. */
/* Vol wit, zelfde reden als bij .nav-link hierboven: op dit rood haalt
   alleen 100% wit de contrastdrempel. */
.site-footer { background: var(--chiro-red); color: #fff; margin-top: var(--sp-8); }
.footer-bar {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap;
  gap: var(--sp-3); padding-block: var(--sp-4); font-size: 0.85rem;
}
.footer-copy { margin: 0; color: #fff; }
.social-row { display: flex; gap: var(--sp-2); }
/* Bare icons, no chip behind them -- three small circles in a row read as
   buttons that do not look clickable. The icon itself carries the hover. */
.social-dot {
  width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  color: #fff;
  transition: color 0.15s ease, transform 0.15s ease;
}
.social-dot svg { width: 19px; height: 19px; }
.social-dot:hover { color: #fff; transform: translateY(-1px); }
.footer-links { display: flex; gap: var(--sp-4); flex-wrap: wrap; }
.footer-links a { color: #fff; font-weight: 600; }
.footer-links a:hover { color: #fff; }
/* Cleaner on small screens: the header's hamburger menu already covers
   navigation, so the footer's link row is redundant there -- keep just
   the copyright + social icons, the two things worth repeating. */
@media (max-width: 700px) {
  .footer-bar { justify-content: center; text-align: center; }
  .footer-links { display: none; }
}

/* ---------- Forms ---------- */
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--sp-4); }
.field label { font-weight: 700; font-size: 0.9rem; }
.veld-hint { font-weight: 400; color: var(--muted); font-size: 0.82rem; }
.veld-hint code { background: var(--paper-soft); border-radius: 4px; padding: 1px 5px; font-size: 0.8em; }
.field input, .field textarea {
  padding: var(--sp-3) var(--sp-4); border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--paper);
}
.field input:focus, .field textarea:focus { border-color: var(--chiro-blue); }

/* Datumveld + kalenderknopje (zie datumVeld() in build.mjs). Het echte
   <input type="date"> blijft onzichtbaar en dient enkel om showPicker() op
   aan te roepen -- niet display:none, want een niet-getekend element kan
   in de meeste browsers geen kalender openen. */
.datum-invoer { display: flex; gap: var(--sp-2); position: relative; }
.datum-invoer input[type="text"] { flex: 1 1 auto; min-width: 0; }
.datum-kalender-btn {
  flex-shrink: 0; width: 44px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--paper); color: var(--muted); cursor: pointer;
}
.datum-kalender-btn:hover { background: var(--paper-soft); color: var(--chiro-red); }
.datum-kalender-btn svg { width: 18px; height: 18px; }
.datum-kalender-verborgen { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; border: 0; padding: 0; }

/* ---------- 404 ---------- */
.error-page { text-align: center; padding-block: var(--sp-9); }
.error-page .code { font-size: 5rem; font-weight: 900; color: var(--chiro-red-light); line-height: 1; }

/* ---------- Beheerpaneel (admin) ----------
   Admin-only classes below (admin-*, .field, .stat, .photo-*, .btn-danger)
   never appear on the public site -- safe to design freely without any
   risk of bleeding into the real pages. */
/* Eén balk in dezelfde stijl als de site-header (rood, sticky), zonder logo:
   terugknop links, tabbladen in het midden, serverstatus rechts. Voorheen
   een witte kopbalk met daaronder een aparte tabbalk -- twee keer een rij
   hoogte voor wat één balk kan dragen, en een stijlbreuk met de site zelf. */
.admin-header {
  position: sticky; top: 0; z-index: 100;
  background: var(--chiro-red);
  border-bottom: 1px solid transparent;
}
.admin-header-inner {
  min-height: var(--header-h);
  display: flex; align-items: center; gap: var(--sp-4);
}
.admin-back { flex-shrink: 0; }
.admin-header .btn-ghost { color: #fff; }
.admin-header .btn-ghost:hover { background: rgba(255,255,255,0.16); }
/* Minimalistische verbindingsindicator: een kleur zegt genoeg, geen badge
   met achtergrond en rand die om aandacht vraagt. */
.admin-status { display: inline-flex; align-items: center; gap: 7px; font-size: 0.82rem; font-weight: 600; color: #fff; flex-shrink: 0; }
.admin-status-dot { width: 7px; height: 7px; border-radius: 50%; background: rgba(255,255,255,0.45); flex-shrink: 0; }
.admin-status.is-verbonden .admin-status-dot { background: var(--c-rakkers); box-shadow: 0 0 0 2px rgba(255,255,255,0.35); }
.admin-status.is-lokaal .admin-status-dot { background: rgba(255,255,255,0.45); }
@media (max-width: 560px) {
  /* De statustekst zelf is er nog altijd via het title-attribuut (hover/
     tik-en-houd); op smal scherm blijft enkel het stipje, anders knijpt
     "Verbonden met de server" de andere balk-inhoud af. */
  .admin-status-tekst { display: none; }
}

/* Hamburgermenu voor de tabbladen op smalle schermen -- vervangt de
   horizontale scroll-balk (die bleef op zich werken, maar verstopt de
   meeste tabbladen buiten beeld tot je zijwaarts veegt). Hergebruikt
   .hamburger/.mobile-nav van de site zelf: zelfde knop, zelfde openklap-
   gedrag, enkel de tabblad-links zelf (.admin-tab) hebben hier een eigen
   kleurregel nodig omdat die voor de rode kopbalk getekend zijn, niet voor
   het witte uitklappaneel eronder. */
.admin-hamburger { flex-shrink: 0; }
@media (max-width: 720px) {
  .admin-tabs { display: none; }
  .admin-hamburger { display: flex; }
  /* .admin-tabs (flex: 1 1 auto) was wat de statusbol en de terugknop uit
     elkaar duwde -- verdwijnt die op smal scherm, dan klit de rest zonder
     dit links samen i.p.v. rechts te blijven staan zoals het hamburgericoon
     op de publieke site (.header-actions, justify-content: flex-end). */
  .admin-status { margin-left: auto; }
  .admin-mobile-nav > ul > li > a.admin-tab {
    display: flex; align-items: center; gap: 7px;
    color: var(--ink); border-bottom: none; padding: var(--sp-3) 0;
    font-weight: 700; font-size: 1.05rem;
  }
  .admin-mobile-nav > ul > li { border-bottom: 1px solid var(--border); }
  .admin-mobile-nav > ul > li:last-child { border-bottom: none; }
  .admin-mobile-nav .admin-tab:hover,
  .admin-mobile-nav .admin-tab.is-active { color: var(--chiro-red); }
  .admin-mobile-nav .admin-tab-icon { opacity: 0.75; }
  .admin-mobile-nav .admin-tab.is-active .admin-tab-icon { opacity: 1; }
}
/* Getoond wanneer Store.ready() geen verbinding met api.php kreeg -- los van
   de kleine statusbol hierboven (die je makkelijk mist, en op smal scherm
   zelfs zonder tekst staat): dit is de "je bewerkt nu enkel lokaal"-
   waarschuwing die niet over het hoofd te zien is. Amber i.p.v. het
   sitebrede rood: dat rood is hier al overal (kopbalk, knoppen), een
   banner in diezelfde kleur zou niet als iets aparts opvallen. */
.admin-server-banner {
  background: #FFF4E5; color: #8A5300; border-bottom: 1px solid #F5C97B;
  padding: var(--sp-3) var(--sp-5); text-align: center; font-weight: 700; font-size: 0.9rem;
}
.admin-server-banner[hidden] { display: none; }

/* Skeleton -- getoond tussen paginalaad en Store.ready, i.p.v. een lege
   witte main terwijl er op api.php gewacht wordt. */
.admin-skeleton { padding-block: var(--sp-6); }
.admin-skeleton[hidden] { display: none; }
.skeleton-line, .skeleton-block {
  background: linear-gradient(90deg, var(--paper-soft) 25%, var(--border) 37%, var(--paper-soft) 63%);
  background-size: 400% 100%;
  animation: skeleton-shimmer 1.4s ease infinite;
  border-radius: var(--radius-sm);
}
.skeleton-line { height: 14px; width: 60%; margin-bottom: var(--sp-3); }
.skeleton-line--title { height: 26px; width: 30%; margin-bottom: var(--sp-5); }
.skeleton-block { height: 120px; margin-bottom: var(--sp-4); }
@keyframes skeleton-shimmer {
  0% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton-line, .skeleton-block { animation: none; }
}

.admin-tabs { flex: 1 1 auto; min-width: 0; overflow-x: auto; }
.admin-tabs ul { display: flex; gap: var(--sp-1); list-style: none; margin: 0; padding: 0; }
.admin-tabs li { flex-shrink: 0; }
.admin-tab {
  display: flex; align-items: center; gap: 7px;
  padding: var(--sp-3) 0.75rem; font-weight: 700; font-size: 0.9rem; color: #fff;
  border-radius: var(--radius-sm); white-space: nowrap;
  transition: color 0.15s ease, background 0.15s ease;
}
.admin-tab-icon { width: 17px; height: 17px; flex-shrink: 0; opacity: 0.85; }
.admin-tab:hover { color: #fff; background: rgba(0,0,0,0.12); }
.admin-tab.is-active { color: #fff; background: rgba(0,0,0,0.20); }
.admin-tab.is-active .admin-tab-icon { opacity: 1; }

/* Subtabs: kleiner, geen sticky, geen icoon -- voor binnen een tabblad. */
.subtabs { display: flex; gap: var(--sp-1); flex-wrap: wrap; border-bottom: 1px solid var(--border); margin-bottom: var(--sp-6); }
.subtab-btn {
  padding: var(--sp-2) var(--sp-4); font-weight: 700; font-size: 0.85rem; color: var(--muted);
  border-bottom: 3px solid transparent; white-space: nowrap; background: none; border-left: none; border-right: none; border-top: none;
  cursor: pointer; transition: color 0.15s ease;
}
.subtab-btn:hover { color: var(--ink); }
.subtab-btn.is-active { color: var(--chiro-red); border-bottom-color: var(--chiro-red); }
.subtab-panel[hidden] { display: none; }

.admin-section-block { margin-top: var(--sp-8); }
.admin-section-block h2 { font-size: 1.15rem; margin-bottom: var(--sp-4); }

/* ---- Startscherm (/beheer/) ----
   Hairlines en witruimte, in dezelfde toon als de rest van de site. Geen
   kaders om elk item, want dan gaat het ding eruitzien als een verzameling
   widgets terwijl het een lijst is die je in een paar tellen overziet. */
.dash-overzicht { margin-top: var(--sp-6); border-top: 1px solid var(--border); }
.dash-overzicht-rij {
  display: flex; align-items: baseline; gap: var(--sp-4);
  padding: var(--sp-4) 0; border-bottom: 1px solid var(--border);
  color: inherit;
}
.dash-overzicht-rij:hover { background: var(--paper-soft); margin-inline: calc(var(--sp-4) * -1); padding-inline: var(--sp-4); }
.dash-overzicht-rij:hover .dash-overzicht-label { color: var(--chiro-red); }
.dash-overzicht-label { font-weight: 700; min-width: 150px; transition: color 0.15s ease; }
.dash-overzicht-info { flex: 1 1 auto; text-align: right; }
.dash-overzicht-stat { color: var(--muted); font-size: 0.92rem; }
.dash-overzicht-notities { margin-top: 2px; }
.dash-overzicht-notitie { display: block; color: var(--chiro-red); font-size: 0.85rem; font-weight: 700; }

.admin-dash-blok { margin-top: var(--sp-7); }
.admin-dash-blok > h2 {
  font-size: 1.05rem; margin-bottom: 0;
  padding-bottom: var(--sp-2); border-bottom: 1px solid var(--border);
}
.dash-rij {
  display: flex; gap: var(--sp-4);
  padding: var(--sp-3) 0; border-bottom: 1px solid var(--border);
}
.dash-rij:last-child { border-bottom: none; }
/* Vaste kolom voor de datum zodat de titels onder elkaar uitlijnen. */
.dash-datum-cel { color: var(--muted); font-size: 0.92rem; min-width: 150px; flex-shrink: 0; }
.dash-leeg { color: var(--muted); padding: var(--sp-4) 0; }
.admin-dash-acties { display: flex; gap: var(--sp-3); flex-wrap: wrap; margin-top: var(--sp-8); }
@media (max-width: 560px) {
  .dash-overzicht-rij { flex-wrap: wrap; }
  .dash-overzicht-info { flex-basis: 100%; text-align: left; }
  .dash-rij { flex-direction: column; gap: 2px; }
  .dash-datum-cel { min-width: 0; }
  .admin-dash-acties .btn { width: 100%; }
}

.table-scroll { overflow-x: auto; border-radius: var(--radius-md); }
.admin-table { width: 100%; min-width: 480px; border-collapse: collapse; background: var(--paper); border: 1px solid var(--border); border-radius: var(--radius-md); overflow: hidden; }
.admin-table th, .admin-table td { text-align: left; padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border); font-size: 0.9rem; vertical-align: middle; }
.admin-table th { background: var(--paper-soft); font-weight: 700; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); }
.admin-table tbody tr:hover { background: var(--paper-soft); }
.admin-table tr:last-child td { border-bottom: none; }
.admin-table .actions { display: flex; gap: var(--sp-2); justify-content: flex-end; }
.admin-table select { padding: 4px 8px; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); font-size: 0.85rem; }
.admin-empty { padding: var(--sp-6) var(--sp-4); text-align: center; color: var(--muted); }
.admin-empty a { color: var(--chiro-red); font-weight: 700; }

/* Op een smal scherm wordt elke rij een kaartje in plaats van een rij in een
   tabel die je horizontaal moet wegschuiven. Eén en dezelfde HTML: de
   kolomkop van elke cel staat als data-label op de <td> en verschijnt hier
   ervoor, zodat er geen tweede opmaak (en dus geen tweede plek om te
   vergeten bijwerken) nodig is. Cellen zonder data-label -- de knoppenrij,
   de "nog niets"-melding -- krijgen bewust geen kopje. */
@media (max-width: 720px) {
  .table-scroll { overflow-x: visible; }
  .admin-table { display: block; min-width: 0; border: none; background: none; border-radius: 0; }
  .admin-table thead { display: none; }
  .admin-table tbody, .admin-table tr, .admin-table td { display: block; }
  .admin-table tr {
    background: var(--paper); border: 1px solid var(--border); border-radius: var(--radius-md);
    padding: var(--sp-2) var(--sp-4); margin-bottom: var(--sp-4);
  }
  .admin-table tr:last-child { margin-bottom: 0; }
  .admin-table tbody tr:hover { background: var(--paper); }
  .admin-table td {
    border-bottom: none; padding: var(--sp-2) 0;
    display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4);
  }
  .admin-table td[data-label]::before {
    content: attr(data-label);
    font-weight: 700; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em;
    color: var(--muted); flex-shrink: 0;
  }
  .admin-table .actions {
    justify-content: flex-end;
    border-top: 1px solid var(--border); margin-top: var(--sp-2); padding-top: var(--sp-3);
  }
  /* De "nog niets in deze lijst"-cel vult een hele tabel, geen kaartje. */
  .admin-table td[colspan] { display: block; }
}

.admin-panel { background: var(--paper); border: 1px solid var(--border); border-radius: var(--radius-md); padding: var(--sp-6); margin-top: var(--sp-5); box-shadow: var(--shadow-sm); }
.admin-panel[hidden] { display: none; }
.admin-editor-split { display: flex; gap: var(--sp-6); flex-wrap: wrap; align-items: flex-start; }
.admin-editor-fields { flex: 1 1 380px; min-width: 0; }
.admin-editor-preview { flex: 1 1 320px; min-width: 0; position: sticky; top: var(--sp-4); }
.admin-preview-label { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); margin: 0 0 var(--sp-3); }
.admin-preview-frame { border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--paper-soft); padding: var(--sp-5) 0; overflow: hidden; }
.admin-preview-frame .page-head { padding-top: 0; }
.admin-preview-frame #preview-photo[hidden] { display: none; }
.admin-form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--sp-4); }
.admin-form-grid .field-wide { grid-column: 1 / -1; }
@media (max-width: 700px) { .admin-form-grid { grid-template-columns: 1fr; } }
.field textarea { min-height: 90px; resize: vertical; font-family: inherit; }
.field .required { color: var(--chiro-red); }
.admin-form-actions { display: flex; align-items: center; gap: var(--sp-3); margin-top: var(--sp-5); padding-top: var(--sp-5); border-top: 1px solid var(--border); }
.admin-vb-group { grid-column: 1 / -1; }
.admin-vb-group-title {
  font-size: 0.78rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--chiro-red); margin: var(--sp-5) 0 var(--sp-2);
}
.admin-vb-group:first-of-type .admin-vb-group-title { margin-top: 0; }
.admin-photo-field { display: flex; align-items: center; gap: var(--sp-4); }
.admin-photo-preview {
  width: 64px; height: 64px; border-radius: var(--radius-sm); object-fit: cover;
  background: var(--paper-soft); border: 1px solid var(--border); flex-shrink: 0;
  cursor: pointer;
}
.admin-photo-preview:focus-visible { outline: 3px solid var(--chiro-blue); outline-offset: 2px; }

.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--sp-4); }
.photo-slot-card { background: var(--paper); border: 1px solid var(--border); border-radius: var(--radius-md); overflow: hidden; }
.photo-slot-card .psc-body { padding: var(--sp-3) var(--sp-4); }
/* Het fotokader is een <button> zodra er een foto staat (zie fotoKaartHtml
   in admin.js), dus de knop-standaardopmaak moet eraf -- de focusring uit
   "Focus states" hierboven blijft wel gewoon werken. */
.psc-frame { display: block; width: 100%; padding: 0; background: none; border: none; font: inherit; color: inherit; }
button.psc-frame { cursor: pointer; }
.psc-frame img { width: 100%; aspect-ratio: 4/3; object-fit: cover; display: block; }
.psc-frame--cirkel { width: 55%; margin: var(--sp-4) auto 0; border-radius: 50%; overflow: hidden; border: 2px solid var(--border); }
.psc-frame--cirkel img { aspect-ratio: 1/1; }

/* ---- Dialoogvensters ----
   Eén basis voor élk venster dat over de pagina komt (de bevestigingsvraag
   bij verwijderen, de crop-popup). Stonden hiervoor als twee losse, bijna
   identieke blokken in dit bestand, wat ze langzaam uit elkaar liet lopen --
   andere achtergrondkleur, andere z-index, ander toetsenbordgedrag. Wat per
   venster écht verschilt (het crop-kader hieronder) staat apart; de rest
   niet meer. Het gedrag hoort bij openDialoog() in admin.js. */
.admin-overlay {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(20,10,10,0.45); backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center; padding: var(--sp-5);
}
.admin-overlay[hidden] { display: none; }
.admin-dialog {
  background: var(--paper); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  padding: var(--sp-6); max-width: 420px; width: 100%;
}
/* Titel van een venster: een <h2> zodat de koppenstructuur van de pagina
   klopt, maar op de grootte van de tekst eromheen i.p.v. van een paginakop. */
.admin-dialog-title { font-size: 1.2rem; font-weight: 700; }
.admin-dialog-actions { display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-5); }
.admin-dialog-actions--eind { justify-content: flex-end; gap: var(--sp-3); margin-top: var(--sp-6); }
.admin-dialog-spacer { flex: 1 1 auto; }

/* Inlogscherm -- zelfde look als de dranklijst (lichte, volle achtergrond en
   een groot afgerond kaartje in het midden, geen donker overlay-gevoel zoals
   de bevestig-/crop-vensters hierboven): dit blokkeert niet iets waar je al
   mee bezig was, dit IS het eerste scherm. Eigen kleuren/lettertype van deze
   site (Chiro-rood, Source Sans 3) i.p.v. de letterlijke dranklijst-CSS, die
   een eigen, oudere rode tint en systeemlettertype gebruikt. */
.login-overlay {
  position: fixed; inset: 0; z-index: 300;
  background: var(--paper);
  display: flex; align-items: center; justify-content: center; padding: var(--sp-5);
}
.login-overlay[hidden] { display: none; }
.login-card {
  background: var(--paper); width: 100%; max-width: 360px;
  padding: var(--sp-7) var(--sp-6); border-radius: 28px; box-shadow: var(--shadow-lg);
  border: 1px solid var(--border);
  text-align: center;
}
.login-titel { color: var(--chiro-red); font-weight: 800; font-size: 1.5rem; letter-spacing: -0.02em; margin: 0 0 4px; }
.login-sub { color: var(--muted); font-size: 0.9rem; margin: 0 0 var(--sp-5); }
.login-input {
  width: 100%; padding: var(--sp-4); background: rgba(28,28,30,0.035);
  border: 1.5px solid transparent; border-radius: 16px; margin-bottom: var(--sp-4);
  box-sizing: border-box; font-size: 1rem; font-family: inherit; color: var(--ink);
}
.login-input:focus-visible { border-color: var(--border-strong); background: var(--paper); outline: none; }
.login-fout { color: var(--chiro-red-dark); font-size: 0.85rem; font-weight: 600; margin: var(--sp-4) 0 0; }

/* ---- Crop-popup: verschuiven + zoomen, zoals de iOS-fotobewerker ---- */
.crop-frame {
  position: relative; overflow: hidden; width: 100%; background: #111;
  border-radius: var(--radius-md); touch-action: none; cursor: grab; margin-top: var(--sp-4);
}
.crop-frame:active { cursor: grabbing; }
.crop-frame.is-cirkel { border-radius: 50%; }
/* Naar binnen i.p.v. de gewone outline-offset: overflow:hidden hierboven
   snijdt een naar buiten geplaatste outline anders gedeeltelijk weg. */
.crop-frame:focus-visible { outline: 3px solid var(--chiro-blue); outline-offset: -3px; }
.crop-frame img { position: absolute; max-width: none; pointer-events: none; user-select: none; }
.crop-zoom-label { display: block; font-size: 0.85rem; font-weight: 700; margin-top: var(--sp-5); }
#crop-zoom { width: 100%; margin-top: var(--sp-2); }
.photo-slot-card .psc-label { font-weight: 700; font-size: 0.85rem; display: block; margin-bottom: var(--sp-3); }
.photo-slot-card .psc-actions { display: flex; gap: var(--sp-2); }
.photo-slot-card .psc-badge { font-size: 0.7rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; font-weight: 700; }
.photo-slot-card.is-customised .psc-badge { color: var(--chiro-red); }
.admin-fotos-toolbar { display: flex; gap: var(--sp-3); flex-wrap: wrap; align-items: center; margin-bottom: var(--sp-6); }
.admin-fotos-search {
  flex: 1; min-width: 200px; padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--paper);
}
.admin-fotos-group { margin-bottom: var(--sp-7); }
.admin-fotos-group:last-child { margin-bottom: 0; }
.admin-fotos-group-title {
  font-size: 0.95rem; font-weight: 800; margin-bottom: var(--sp-4);
  padding-bottom: var(--sp-2); border-bottom: 2px solid var(--border);
  display: flex; align-items: center; gap: var(--sp-2);
}
.admin-fotos-group-count { font-weight: 600; color: var(--muted); font-size: 0.82rem; }
.admin-fotos-empty { color: var(--muted); padding: var(--sp-6) 0; text-align: center; }

/* Danger button -- distinct from .btn-primary (also red): darker shade,
   and always sits inside a clearly-labelled "Gevarenzone" card so context
   makes the difference obvious even though both are red-based. */
.btn-danger { background: var(--chiro-red-dark); color: #fff; }
.btn-danger:hover { background: #8a0a24; box-shadow: var(--shadow-md); }

/* The season panel sits above the exception table and is visually a settings
   block, not another record in the list. */
.admin-seizoen { margin-top: var(--sp-6); background: var(--paper-soft); }
.admin-seizoen h2 { font-size: 1.15rem; }
.admin-hint { font-weight: 400; color: var(--muted); font-size: 0.85rem; }

/* Toast -- brief, non-blocking confirmation after a save/upload/delete. */
.admin-toast {
  position: fixed; left: 50%; bottom: var(--sp-6); z-index: 300;
  transform: translate(-50%, 0);
  background: var(--ink); color: #fff;
  padding: var(--sp-3) var(--sp-5); border-radius: var(--radius-pill);
  box-shadow: var(--shadow-lg); font-weight: 600; font-size: 0.9rem;
  display: flex; align-items: center; gap: var(--sp-2);
  opacity: 0; transition: opacity 0.2s ease, transform 0.2s ease;
  pointer-events: none;
}
.admin-toast[hidden] { display: none; }
.admin-toast.is-visible { opacity: 1; transform: translate(-50%, -6px); }
.admin-toast svg { width: 16px; height: 16px; color: #7CD98A; flex-shrink: 0; }
/* "Opslaan…" (bezig) en een mislukte opslag blijven staan i.p.v. na 2,6s te
   verdwijnen (zie showToast() in admin.js) -- een kleur zegt genoeg om de
   drie toestanden (bezig/gelukt/mislukt) uit elkaar te houden. */
.admin-toast.is-besig svg { color: rgba(255,255,255,0.6); }
.admin-toast.is-fout { background: var(--chiro-red-dark); }
.admin-toast.is-fout svg { color: #fff; }
.admin-toast-spin { transform-origin: center; animation: toast-spin 0.9s linear infinite; }
@keyframes toast-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .admin-toast-spin { animation: none; }
}
@media (max-width: 560px) {
  .admin-toast { left: var(--sp-4); right: var(--sp-4); transform: none; bottom: var(--sp-4); }
  .admin-toast.is-visible { transform: translateY(-4px); }
}

/* ---------- Print ---------- */
/* Vooral voor de Agenda: de maandtabs tonen normaal maar één maand
   tegelijk ([hidden] via JS), wat op papier een pagina met bijna niets erop
   zou geven. Alle maanden tonen en de tabs zelf (zinloos op papier) weg,
   samen met de rode kopbalk/voettekst/menu -- die drinken vooral inkt op
   zonder iets bij te dragen aan een afdruk. */
@media print {
  .site-header, .site-footer, .skip-link, .hamburger, .mobile-nav,
  .admin-header, .admin-hamburger, .admin-mobile-nav,
  .ag-maand-tabs, .subtabs { display: none !important; }
  [data-subtab-panel] { display: block !important; }
  .ag-maand { break-inside: avoid; }
}

/* ---------- Utility ---------- */
.mt-0 { margin-top: 0; }
.mt-6 { margin-top: var(--sp-6); }
.mt-7 { margin-top: var(--sp-7); }
.mb-6 { margin-bottom: var(--sp-6); }
.text-center { text-align: center; }
.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;
}
