/**
 * affiche-basis.css — de gedeelde laag van het affiche (sessie 252, TASKS #85)
 *
 * Wat elke pagina deelt: de letter van het woordmerk, de affichetokens, en de chrome die op
 * elke pagina staat (navbar, footer, consentbanner). Elke pagina met die componenten laadt
 * dit bestand als laatste stylesheet. affiche.css (alleen index.html) bouwt erop voort met de
 * pagina zelf; de andere pagina's staan met hun inhoud nog in de oude wereld en gaan één per
 * sessie over (PLANNING.md, Design System).
 *
 * Twee regels die de grens tussen die werelden bewaken:
 * - Hertokenen gebeurt op de wortel van een component, nooit op :root. De oude wereld leest
 *   dezelfde tokens ook in pagina-inhoud (--color-bg-footer in .blog-post-footer,
 *   --color-cta-dark-frame in iconen van blog en landing); op :root zou die inhoud
 *   meeveranderen. Op de wortel erven alleen de kinderen van de component.
 * - De pagina's die al in het affiche staan (nu body.home) staan in dezelfde lijst: een
 *   gemigreerde pagina is voor de tokens gewoon één wortel meer.
 *
 * Elke kleurwaarde is gemeten (WCAG 2.x, ratio's in de comments).
 */

/* ==================== Letter ==================== */
/* Archivo: neo-grotesk, geïnstantieerd op wdth 100 en wght 700–800, gesubset op dezelfde
   219 codepoints als Atkinson Hyperlegible Next. 20.688 B; sinds sessie 252 op elke pagina,
   want het woordmerk in navbar en footer staat erin (Archivo 800). Sessie 240: koppen 700,
   labels 800; 900 had geen gebruiker en is eruit. */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 700 800;
  font-display: swap;
  src: url('/styles/fonts/archivo-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ==================== Tokens ==================== */
:root {
  /* Papier en inkt. Neutraal-koel gebroken wit, bewust geen crème: crème + rood is een
     van de looks waar gegenereerde ontwerpen standaard op landen (new-work.md §4). */
  --af-papier: #efefec;
  --af-papier-2: #e2e2de;      /* banden; inkt erop 14,54:1 */
  --af-inkt: #111111;          /* 16,39:1 op papier */
  --af-inkt-2: #444440;        /* gedempte tekst: 8,49 op papier, 7,53 op papier-2 */
  --af-lijn: #c9c9c4;          /* rasterlijnen: decoratief, draagt geen informatie */
  --af-lijn-sterk: #7a7a75;    /* randen van bedieningselementen: 3,74 / 3,32 (≥3 niet-tekst) */

  /* Het signaal. Alleen als vlak met een witte letter op groot formaat (lat 4,5) of als
     niet-tekstig merkteken (lat 3). Wit op rood 5,79; rood op papier 5,02. */
  --af-rood: #cc0a1e;
  --af-op-rood: #ffffff;
  /* De focusring. In licht het signaalrood; in donker iets lichter, zie daar. */
  --af-focus: var(--af-rood);

  /* De footer is in beide thema's een inktvlak. Een eigen token en geen var(--af-inkt):
     in de footer draaien papier en inkt om, dus daar ís --af-inkt papier. */
  --af-footer: #111111;

  --af-breed: 1400px;
  --af-rand: clamp(16px, 3vw, 32px);
  --af-kop: 'Archivo', 'Atkinson Hyperlegible Next', -apple-system, 'Segoe UI', sans-serif;
  --af-tekst: var(--font-body);
  --af-mono: var(--font-terminal);

  /* Maat en ritme van de inhoud (sessie 254 uit affiche.css); nieuwe namen, dus :root mag. */
  --af-cel: clamp(12px, 1.4vw, 20px);
  --af-sectie: clamp(72px, 9vw, 136px);
  /* Korte secties: regel lucht <= inhoud. Met één maat voor alles hadden sample en
     nieuwsbrief meer lucht dan inhoud (259 tegen 184 en 155 @1440, sessie 242). */
  --af-sectie-kort: clamp(48px, 5vw, 72px);
  /* Afficheschaal: het plafond is de rasterbreedte, niet de viewport. 4.9rem = 88,2px past
     in twee regels op 1336px tekstbreedte; onder ~570px wint 2.2rem (35,2px op 375). */
  --af-affiche: clamp(2.2rem, 6.2vw, 4.9rem);
  --af-h2: clamp(1.75rem, 3.3vw, 2.85rem);      /* max 51,3px */
  --af-h3: 1.22rem;                              /* 22px */
  --af-klein: 0.83rem;                           /* 15px: labels, glos, microcopy */
  --af-ease: cubic-bezier(0.16, 1, 0.3, 1);
}

/* Het donkere thema: het geïnverteerde affiche. Inkt wordt grond, papier wordt letter.
   Gemeten op #111111: papier 16,39 · dim 8,67 (7,79 op grond-2) · rand 3,74 / 3,38.
   Het rood blijft; als merkteken 3,26 op de grond. De footer wordt zwart (#000), zodat
   hij zich van de grond scheidt en zijn gemeten tekstkleuren houdt. */
:root[data-theme="dark"] {
  --af-papier: #111111;
  --af-papier-2: #1c1c1b;
  --af-inkt: #efefec;
  --af-inkt-2: #b0b0ab;
  --af-lijn: #2e2e2c;
  --af-lijn-sterk: #6f6f6a;
  --af-footer: #000000;
  /* #cc0a1e haalde als ring op de band (#1c1c1b) 2,95:1, onder de 3:1 van WCAG 1.4.11
     (critique s257). #d70b20: band 3,21, grond 3,56, zwarte footer 3,96. Alleen de ring;
     het signaalrood als vlak blijft #cc0a1e. */
  --af-focus: #d70b20;
}

/* ==================== Hertokenen op de wortel ==================== */
/* De gedeelde regels in main.css en landing.css lezen custom properties; hier krijgen die
   op de wortel van elke component de waarden van het affiche, en de dichtstbijzijnde
   declaratie wint. Het groen en de accenttekst van de vorige wereld worden inkt: hier is
   elke interactieve tekst inkt en spreekt een toestand via inversie. */
body.home,
body.gidsen,
body.sample,
body.blog,
body.naslag,
body.info,
body.legal,
body.terminal,
.landing-nav-wrapper,
#landing-mobile-menu,
#navbar,
.landing-footer,
.cookie-banner {
  --color-bg: var(--af-papier);
  --color-text: var(--af-inkt);
  --color-text-dim: var(--af-inkt-2);
  --color-text-secondary: var(--af-inkt-2);
  --color-border: var(--af-lijn-sterk);
  --color-link: var(--af-inkt);
  --color-link-hover: var(--af-inkt);
  --color-accent-text: var(--af-inkt);
  --color-ui-primary: var(--af-inkt);
  --color-ui-hover: var(--af-inkt);
  --font-heading: var(--af-kop);

  --color-bg-navbar: var(--af-papier);
  --color-bg-navbar-mobile: var(--af-papier);
  --color-navbar-link: var(--af-inkt);
  --color-navbar-link-hover: var(--af-inkt);
  --color-border-dark-frame: var(--af-inkt);
  --color-toggle-text-inactive: var(--af-inkt-2);
  --color-toggle-hover: var(--af-papier-2);
  --color-cta-dark-frame: var(--af-inkt);
  --color-cta-dark-frame-hover: var(--af-inkt);
  --color-navbar-action: var(--af-inkt);
  --color-navbar-dropdown-icon: var(--af-inkt-2);
  --color-bg-dropdown: var(--af-papier);
  --color-bg-dropdown-hover: var(--af-inkt);
  --color-bg-footer: var(--af-footer);

  --color-cta-primary: var(--af-rood);
  --color-cta-primary-hover: var(--af-inkt);
  --color-cta-text: var(--af-op-rood);

  --border-radius-button: 0;
  --border-radius-small: 0;
  --border-radius-modal: 0;
  --border-radius-cta-nav: 0;
}

/* ==================== Focus in de chrome ==================== */
/* Focus = hier ben jij: het enige andere rood. Binnen de chrome op elke pagina; de focus
   van de pagina-inhoud hoort bij de pagina en gaat mee als die migreert. De schakelaar staat
   er apart in: landing.css geeft hem een blauwe ring op (0,3,0), en op gelijke stand wint
   dit bestand op volgorde. De navlinks ook: .nav-links a:focus-visible (0,2,1) gaf ze een
   blauwe ring met radius 4px (finish review s252). */
.landing-nav-wrapper :focus-visible,
#landing-mobile-menu :focus-visible,
#navbar :focus-visible,
.landing-footer :focus-visible,
.landing-footer .footer-column a:focus-visible,
.landing-footer a.footer-donate:focus-visible,
.cookie-banner :focus-visible,
.theme-toggle:focus-visible,
.landing-nav .theme-toggle:focus-visible,
.landing-nav .nav-links a:focus-visible {
  outline: 2px solid var(--af-focus);
  outline-offset: 2px;
  border-radius: 0;
}

/* ==================== Navbar ==================== */
/* Papier met een inktlijn eronder; de kleuren komen uit de tokens hierboven. De letter zet
   de wortel zelf: hij erfde die van de pagina, en op een pagina in de oude wereld is dat de
   oude tekstkleur (gemeten sessie 252 via de schakelaar, die currentColor leest). */
.landing-nav-wrapper,
#landing-mobile-menu,
#navbar {
  color: var(--af-inkt);
}

.landing-nav-wrapper {
  border-bottom-width: 1px;
}

/* Een woordmerk is geen actie (sessie 236): geen onderstreping en geen kleurwissel, in rust
   noch bij hover, en dat geldt ook voor het merk in de footer (besluit eigenaar, sessie
   245). main.css kleurt bij hover élke span in het merk (.nav-brand:hover span); de naam
   zelf is een klasseloze span, dus die regel staat hier op span en niet op .brand-accent
   alleen (gemeten sessie 245). */
.landing-nav a.nav-brand,
.landing-nav a.nav-brand:hover,
#navbar a.nav-brand,
#navbar a.nav-brand:hover,
.landing-footer a.footer-logo[href],
.landing-footer a.footer-logo[href]:hover {
  text-decoration: none;
}

.nav-brand {
  font-family: var(--af-kop);
  font-weight: 800;
}

/* 200% tekstzoom op 375: het merk (335px, één woord) duwde de menuknop buiten beeld
   (WCAG 1.4.4, s255). Het mag krimpen en breken; op gewone maat verandert niets. */
.nav-brand,
.nav-brand > span {
  min-width: 0;
  overflow-wrap: anywhere;
}

.nav-brand:hover,
.nav-brand:hover span,
.nav-brand:hover .brand-icon {
  color: var(--af-inkt);
}

.landing-nav .nav-links a,
#navbar .navbar-links a {
  text-decoration: none;
}

.landing-nav .nav-links a:hover,
#navbar .navbar-links a:hover,
#navbar .navbar-action:hover {
  background: var(--af-inkt);
  color: var(--af-papier);
}

/* Het zoekicoon in de app-navbar tilde bij hover 2px op: niets zweeft. */
#navbar .navbar-action:hover {
  transform: none;
}

/* Het Help-menu van de app-navbar: papier met een inkten kader, en een regel inverteert. Het
   pijltje voor elke regel staat gedempt en gaat in het blok mee met de letter. Zonder
   animatie, zoals de FAQ. */
#navbar .dropdown-menu {
  border-color: var(--af-inkt);
  box-shadow: none;
  animation: none;
}

/* Geen glyphs als icoon (craft floor): de "+" op de trigger werd een SVG-chevron in navbar.js,
   die draait als het menu open is; de pijl "→" die bij hover "►" werd, vervalt: de inversie is
   al de hoverfeedback. */
#navbar .dropdown-trigger::after,
#navbar .dropdown-menu a::before,
#navbar .dropdown-menu a:hover::before {
  content: none;
}

#navbar .dropdown-chevron {
  flex-shrink: 0;
}

/* "Help" is een navlink zoals de rest. Tot 768 gaf mobile.css .navbar-links a (0,1,1) hem
   17,6px/400 tegen 16px/500 voor de andere links: hun regel in main.css is sterker dan de
   basisregel van de trigger (0,1,0). Dezelfde tokens, op elke breedte. */
#navbar .navbar-links .dropdown-trigger {
  padding: var(--spacing-sm) var(--spacing-md);
  font-size: var(--navbar-link-size);
  font-weight: var(--navbar-link-weight);
}

#navbar .dropdown-trigger[aria-expanded="true"] .dropdown-chevron {
  transform: rotate(180deg);
}

/* De nav-CTA is een inkten kader, op elke pagina. Rood is per scherm één drager, de
   primaire actie van de pagina zelf; en waar die nog in de oude wereld staat, mag de nav er
   niet met een tweede kleur naast gaan staan. */
.landing-nav .btn-cta-nav {
  background: transparent;
  color: var(--af-inkt);
  border: 1px solid var(--af-inkt);
  border-radius: 0;
  box-shadow: none;
  text-decoration: none;
}

.landing-nav .btn-cta-nav:hover {
  background: var(--af-inkt);
  color: var(--af-papier);
  border-color: var(--af-inkt);
  box-shadow: none;
  transform: none;
}

#landing-mobile-menu .navbar-links a {
  color: var(--af-inkt);
  text-decoration: none;
}

/* De pagina waar je bent: een onderstreping van 2px, de taal van een tekstlink. Waar je bent
   is oriëntatie, geen toestand, dus niet de inversie: die is voor hover (sessie 252, met de
   eigenaar; eerst als inktblok gebouwd, maar dan waren 'hier ben je' en 'hier wijs je'
   hetzelfde gebaar, en het zwaarste vlak van de navbar wees naar waar je al was). Elke
   navbestemming krijgt hem (init-components.js leidt de pagina af uit het pad). Hij las
   --color-prompt, het lime van de terminalprompt; de rand van 2px uit landing.css wordt
   doorzichtig, zodat de link niet verspringt. */
.landing-nav .nav-links a.active,
#landing-mobile-menu .navbar-links a.active {
  color: var(--af-inkt);
  /* landing.css gaf de actieve link in het blad ook 600: twee markeringen voor één ding. */
  font-weight: var(--navbar-link-weight);
  border-bottom-color: transparent;
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.2em;
}

.landing-nav .nav-links a.active:hover {
  background: var(--af-inkt);
  color: var(--af-papier);
}

.navbar-toggle span {
  background-color: var(--af-inkt);
}

/* De app-navbar (terminal) op dezelfde rail als de marketing-navbar, en dus als het raster
   van het affiche: gemeten stond zijn woordmerk op 56px tegen 52 (1440) en 56 tegen 32
   (1280), omdat #navbar zijn eigen 24px padding óm de rail van 32 zette, en de links
   stonden 24px uit elkaar in plaats van 16. */
/* De rail zelf (32px) zet main.css al op .navbar-content; de 24px die #navbar eromheen zette
   moest eraf (een mutant die de rail hier opnieuw zette, veranderde niets: sessie 252). */
#navbar {
  padding-inline: 0;
}

/* Tot 768 zet landing.css de marketing-nav op --landing-padding-mobile (20px); dat token
   staat in landing.css, dat de terminal niet laadt, vandaar de terugval. */
@media (max-width: 768px) {
  #navbar .navbar-content {
    padding-inline: var(--landing-padding-mobile, 20px);
  }
}

@media (min-width: 769px) {
  #navbar .navbar-links {
    gap: var(--spacing-md);
  }
}

/* Woordmerk en hamburger op de rail, links en rechts even ver van de rand. mobile.css gaf de
   hamburger 8px marge rechts (tot 768), en de terminal had daar nog 12px padding om de rail:
   op 375 stond het merk op 20 tegen 32, en de hamburger 28 en 40 van de rand. */
.landing-nav-wrapper .navbar-toggle,
#navbar .navbar-toggle {
  margin-right: 0;
}

/* Een tikdoel van 44px, zoals in de marketing-navbar (landing.css); hier was hij 30. */
#navbar .theme-toggle {
  min-height: 44px;
}

/* De schakelaar is in elke navbar dezelfde: twee tekens, de labels alleen voor
   schermlezers. landing.css verbergt ze in de marketing-navbar; de app-navbar (terminal)
   toonde "DONKER" en "LICHT". In het ingeklapte menu (tot 768) staan ze in beide navbars
   zichtbaar, daar is ruimte. */
@media (min-width: 769px) {
  html:not(.nav-ingeklapt) #navbar .toggle-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* ==================== Inklappen op wat past (TASKS #88) ==================== */
/* navbar.js zet html.nav-ingeklapt zodra de uitgeklapte nav niet in de balk past. Dat werkt
   alleen als een link die niet past ook echt uitloopt: tot sessie 252 viel hij stil over twee
   regels (sessie 213: "past" volgens scrollWidth, maar een balk van 70px). */
.landing-nav .nav-links a,
.landing-nav .btn-cta-nav,
#navbar .navbar-links > li > a {
  white-space: nowrap;
}

/* De app-navbar (terminal) ingeklapt vanaf 769px. Tot 768 doet mobile.css dit, maar dat
   bestand laadt alleen tot 768; daarboven klapte hij nooit in en liep hij tot 266px buiten
   beeld. De waarden zijn die van mobile.css, zodat het menu op elke breedte hetzelfde is. */
@media (min-width: 769px) {
  html.nav-ingeklapt #navbar .navbar-toggle {
    display: flex;
    width: 44px;
    height: 44px;
    padding: 14px 0;
  }

  html.nav-ingeklapt #navbar .navbar-menu {
    position: fixed;
    top: var(--navbar-height);
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 999;
    display: none;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: var(--spacing-lg);
    background-color: var(--color-bg-navbar-mobile);
    overflow-y: auto;
  }

  html.nav-ingeklapt #navbar .navbar-menu.active {
    display: flex;
  }

  html.nav-ingeklapt #navbar .navbar-links {
    flex-direction: column;
    gap: 0;
    width: 100%;
    margin-bottom: var(--spacing-lg);
  }

  html.nav-ingeklapt #navbar .navbar-links li {
    width: 100%;
    border-bottom: 1px solid var(--color-border-dark-frame);
  }

  /* Alleen de vorm; maat, gewicht en binnenruimte komen uit main.css, zoals in het marketing-
     blad (de waarden uit mobile.css gaven hier 19,8px/400 en rijen van 63px tegen 18/500/45). */
  html.nav-ingeklapt #navbar .navbar-links a {
    display: block;
    width: 100%;
    min-height: 44px;
    text-align: left;
  }

  html.nav-ingeklapt #navbar .dropdown-menu {
    position: static;
    min-width: 100%;
    padding: var(--spacing-xs) 0;
    border: 0;
    border-top: 1px solid var(--color-border-dark-frame);
  }

  html.nav-ingeklapt #navbar .dropdown-menu a {
    padding-left: calc(var(--spacing-xl) + var(--spacing-md));
    padding-right: var(--spacing-xl);
  }

  html.nav-ingeklapt #navbar .navbar-actions {
    flex-direction: column;
    gap: var(--spacing-md);
    width: 100%;
    margin-top: var(--spacing-lg);
    padding-top: var(--spacing-lg);
    border-top: 1px solid var(--color-border-dark-frame);
  }

  html.nav-ingeklapt #navbar .navbar-action,
  html.nav-ingeklapt #navbar .theme-toggle {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    width: 100%;
    min-height: 44px;
    border: 1px solid var(--color-border-dark-frame);
    border-radius: 0;
    background-color: transparent;
    color: var(--color-navbar-link);
  }

  html.nav-ingeklapt #navbar .navbar-action {
    gap: var(--spacing-md);
    padding: var(--spacing-md) var(--spacing-lg);
    font-size: 1.1rem;
  }

  html.nav-ingeklapt #navbar .navbar-action svg {
    width: 24px;
    height: 24px;
  }

  html.nav-ingeklapt #navbar .theme-toggle {
    gap: 2px;
    padding: 0 4px;
    font-size: 11px;
  }

  html.nav-ingeklapt body.mobile-menu-open {
    overflow: hidden;
  }
}

/* Het label naast het zoekicoon in het ingeklapte terminalblad, op elke breedte (tot 768 zette
   mobile.css ze). Ze stonden in de terminalletter met Title Case en met margin-left: auto,
   op 900 zo'n 640px van hun icoon (finish review s252): mono als kostuum, en een label dat
   niet bij zijn icoon staat. Nu de letter van het blad, zinskapitaal, naast het icoon. */
html.nav-ingeklapt #navbar .navbar-action[aria-label="Zoek commands"]::after {
  content: "Zoek commands";
  margin-left: 0;
  font-family: inherit;
}

/* Eén lijn tussen de links en de acties, niet twee met een lege strook ertussen: de onderrand
   van de laatste link sluit de lijst al af (finish review s252, beide bladen). In het Help-blok
   droeg elk item ook de rand van de lijstregels: onder "Shortcuts" stonden er twee. */
html.nav-ingeklapt #landing-mobile-menu .navbar-actions,
html.nav-ingeklapt #navbar .navbar-actions {
  margin-top: 0;
  border-top: 0;
}

html.nav-ingeklapt #navbar .dropdown-menu li {
  border-bottom: 0;
}

/* De themaschakelaar in het blad: de enige plek op mobiel om van thema te wisselen. De labels
   stonden op 11px in kapitalen, links in een kader van volle breedte. Nu twee gelijke helften
   in de letter van het blad, elk minstens 44px hoog (de rand telt mee). */
html.nav-ingeklapt #landing-mobile-menu .theme-toggle,
html.nav-ingeklapt #navbar .theme-toggle {
  gap: 0;
  padding: 0;
  font-size: 1rem;
}

html.nav-ingeklapt #landing-mobile-menu .toggle-option,
html.nav-ingeklapt #navbar .toggle-option {
  flex: 1;
  justify-content: center;
  gap: var(--spacing-sm);
  min-height: 42px;
  padding: 0;
  font-size: inherit;
}

html.nav-ingeklapt #landing-mobile-menu .toggle-label,
html.nav-ingeklapt #navbar .toggle-label {
  font-size: inherit;
  font-weight: 500;
  letter-spacing: 0;
}

/* ==================== Footer ==================== */
/* De pagina eindigt op een inktvlak: het omgekeerde affiche als slot. In de footer draaien
   papier en inkt om: hier is inkt de grond. Dan lezen de linkregels en de schakelaars
   vanzelf papier, en de lime tokens waar footer.js-markup op leunt (kolomkoppen, hovers)
   worden papier. Papier op #111: 16,39; gedempt #b0b0ab: 8,67. Op #000 (donker) hoger. */
.landing-footer {
  background: var(--color-bg-footer);
  --af-inkt: #efefec;
  --af-inkt-2: #b0b0ab;
  --af-papier: #111111;
  --color-cta-dark-frame: #efefec;
  --color-navbar-link-hover: #efefec;
  --color-footer-text: #efefec;
  --color-footer-text-dim: #b0b0ab;
  --color-footer-text-strong: #efefec;
  --color-footer-link: #efefec;
  --color-footer-link-hover: #efefec;
  border-top: 0;
  /* De footer op de rail van het raster: zelfde rand, zelfde contentbreedte. Hij had 32px
     padding en een eigen max-width van 1400px, dus zijn inhoud begon 13px naast de rail. */
  padding-inline: var(--af-rand);
}

.landing-footer .footer-content,
.landing-footer .footer-bottom {
  max-width: calc(var(--af-breed) - 2 * var(--af-rand));
  margin-inline: auto;
}

/* Met [href]: affiche.css laadt hierna en geeft body.home a (0,1,2) een onderstreping. Een
   gelijke stand wint die op volgorde, dus deze regel is (0,2,1). */
.landing-footer a[href] {
  color: var(--af-inkt);
  text-decoration: none;
}

.landing-footer a[href]:hover {
  text-decoration: underline;
  text-decoration-thickness: 2px;
}

/* De Ko-fi-link droeg een lime waas. Hier een papieren kader, en bij hover de inversie zoals
   elke knop; de onderstreping van de footerlinks stond anders als tweede lijn in het kader. */
.landing-footer a.footer-donate,
.landing-footer a.footer-donate:hover {
  background-color: transparent;
  border: 1px solid var(--af-inkt);
  border-radius: 0;
  color: var(--af-inkt);
  box-shadow: none;
  transform: none;
}

.landing-footer a.footer-donate:hover {
  background-color: var(--af-inkt);
  color: var(--af-papier);
  text-decoration: none;
}

/* Een link in de footer-social (nu alleen Ko-fi): een onderstreping als hover past niet bij een blok. */
.landing-footer .footer-social a:hover {
  background-color: var(--af-inkt);
  color: var(--af-papier);
  transform: none;
}

/* ==================== Consentbanner ==================== */
/* Het eerste wat elke nieuwe bezoeker ziet. Papier, een inktlijn boven, knoppen met een
   inkten kader die inverteren. Beide knoppen blijven gelijkwaardig: weigeren mag niet
   zwakker ogen dan accepteren (geen dark pattern). */
.cookie-banner {
  background-color: var(--af-papier);
  color: var(--af-inkt);
  border-top: 1px solid var(--af-inkt);
  /* Op de rail, zoals navbar en footer: main.css gaf .cookie-content de terminalbreedte, dus
     stond de inhoud op 120-1319 tegen 52-1388 (finish review s252). */
  padding-inline: var(--af-rand);
}

.cookie-banner .cookie-content {
  max-width: calc(var(--af-breed) - 2 * var(--af-rand));
}

/* "Meer info" is een link en moet er een zijn: in de inkt van de lopende tekst, zonder
   onderstreping en zonder hover, was hij niet te herkennen. De taal van een tekstlink. */
.cookie-banner a[href] {
  color: var(--af-inkt);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

.cookie-banner a[href]:hover {
  text-decoration-thickness: 2px;
}

.cookie-banner .btn-small.btn-secondary {
  min-height: 44px;
  background-color: transparent;
  color: var(--af-inkt);
  border: 1px solid var(--af-inkt);
  border-radius: 0;
  font-family: var(--af-tekst);
  font-weight: 700;
  box-shadow: none;
  transform: none;
}

.cookie-banner .btn-small.btn-secondary:hover,
.cookie-banner .btn-small.btn-secondary:focus-visible {
  background-color: var(--af-inkt);
  color: var(--af-papier);
  border-color: var(--af-inkt);
  box-shadow: none;
  transform: none;
}

/* ==================== De pagina-inhoud: gedeelde primitieven ==================== */
/* Sessie 254: uit affiche.css (extract-regel). Element-brede regels onder :is() van de
   gemigreerde wortels (zelfde specificiteit als body.home); achteraan, zoals op de homepage. */
/* ==================== Browseroppervlakken ==================== */
:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info, body.legal, body.terminal) ::selection {
  background: var(--af-inkt);
  color: var(--af-papier);
}

:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info, body.legal, body.terminal) :focus-visible {
  outline: 2px solid var(--af-focus);   /* focus = hier ben jij: het enige andere rood */
  outline-offset: 2px;
}

/* De skiplink heeft een kader; :is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info, body.legal, body.terminal) a zette er een onderstreping bij. */
:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info, body.legal, body.terminal) .skip-link {
  text-decoration: none;
}

:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info, body.legal, body.terminal) a {
  color: var(--af-inkt);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info, body.legal, body.terminal) a:hover {
  text-decoration-thickness: 2px;
}

:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info, body.legal, body.terminal) code {
  font-family: var(--af-mono);
  font-size: 0.9em;
  background: none;
  color: inherit;
  padding: 0;
}

/* ==================== Het raster ==================== */
.af-raster {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 0;
  max-width: var(--af-breed);
  margin-inline: auto;
  padding-inline: var(--af-rand);
  box-sizing: border-box;
  width: 100%;
}

.af-raster > * {
  grid-column: 1 / -1;
  min-width: 0;
}

/* Onder 768 vier kolommen. */
@media (max-width: 767px) {
  .af-raster {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* ==================== De actie ==================== */
/* Het enige rood-als-vlak. Geen icoon, geen lift, geen schaduw: bij hover inverteert hij
   naar inkt. (0,3,1) wint van .btn-cta:hover en [data-theme] .btn-cta (0,2,0). */
:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info) .btn-cta.af-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 56px;
  padding: 14px 28px;
  box-sizing: border-box;
  background: var(--af-rood);
  color: var(--af-op-rood);
  font-family: var(--af-tekst);
  /* Grote tekst (≥18,66px bold, lat 4,5) op élke breedte: onder 768px zakt de basis naar
     16px en werd 1.15rem 18,4px — normale tekst, lat 7, en wit op rood haalt 5,79. */
  font-size: max(1.15rem, 19px);
  font-weight: 700;
  letter-spacing: 0;
  text-decoration: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  transform: none;
  transition: background-color 160ms var(--af-ease), color 160ms var(--af-ease);
}

:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info) .btn-cta.af-cta:hover,
:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info) .btn-cta.af-cta:focus-visible {
  background: var(--af-inkt);
  color: var(--af-papier);
  transform: none;
}

.af-actie {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 20px;
}

.af-microcopy {
  margin: 0;
  font-size: var(--af-klein);
  color: var(--af-inkt-2);
}

/* Secundaire knop: inkten kader, inversie bij hover. */
.af-knop {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 10px 18px;
  box-sizing: border-box;
  border: 1px solid var(--af-inkt);
  font-family: var(--af-tekst);
  font-size: 0.9rem;
  font-weight: 700;
  line-height: 1.2;
}

:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info) a.af-knop {
  color: var(--af-inkt);
  text-decoration: none;
}

/* Focus = hover (DESIGN.md, Buttons), plus de rode ring (s255). */
:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info) a.af-knop:hover,
:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info) a.af-knop:focus-visible,
:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info) a.af-knop--vol {
  background: var(--af-inkt);
  color: var(--af-papier);
}

:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info) a.af-knop--vol:hover,
:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info) a.af-knop--vol:focus-visible {
  background: transparent;
  color: var(--af-inkt);
}

.af-leeslink {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 0.9rem;
}

/* ==================== Koppen en tekst ==================== */
.af h1,
.af h2,
.af h3 {
  font-family: var(--af-kop);
  color: var(--af-inkt);
  margin: 0;
  text-wrap: balance;
}

.af h2 {
  font-size: var(--af-h2);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.02em;
}

.af h3 {
  font-size: var(--af-h3);
  font-weight: 700;
  line-height: 1.2;
}

/* Eén maat voor lopende tekst. `ch` is de breedte van een "0"; in Atkinson zijn de
   meeste letters smaller. Gemeten s255: 62ch gaf op gidsen 86 tekens per regel, niet de
   ~75 die hier stond (craft floor: 65–75). Open voor de homepage: TASKS #85 fase D. */
.af p {
  margin: 0;
  line-height: 1.55;
  max-width: 62ch;
}

.af-kop {
  display: grid;
  grid-template-columns: subgrid;
  row-gap: 16px;
  padding-bottom: clamp(28px, 4vw, 56px);
}

.af-kop h2 {
  grid-column: 1 / 8;
}

/* De inleiding hoort bij de kop, niet bij de glos-kolom: die is op deze pagina voor
   uitleg naast iets links. Tot sessie 242 stond hij rechtsboven en hing nergens aan. */
.af-kop p {
  grid-column: 1 / 8;
  font-size: 1.1rem;
  color: var(--af-inkt-2);
  max-width: 52ch;
}

/* ==================== Secties en banden ==================== */
.af-sectie,
.af-band {
  padding-block: var(--af-sectie);
}

.af-band {
  background: var(--af-papier-2);
}


/* ==================== De kantlijn: bloglinks op de naad ==================== */
/* Sessie 254: uit affiche.css; ook naast elke gids. */
/* De kop van een kolom op de naad: "In gewoon Nederlands" boven de glos, "Verder lezen
   op de blog" boven de kantlijn. Eén vorm voor één functie (proef P0-P2 sessie 246, P1):
   Atkinson 700 in gedempte inkt. Het gewicht maakt het een kop, de kleur zet hem achter
   wat hij aankondigt (glos en links in inkt). Tot sessie 246 twee vormen: 600 gedempt, en
   vette mono in inkt, terwijl mono alleen voor wat je kunt nalopen is (de paden eronder). */
.af-lees-label {
  font-family: var(--af-tekst);
  font-size: var(--af-klein);
  font-weight: 700;
  color: var(--af-inkt-2);
}

.af-lees-lijst {
  display: grid;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.af-lees-pad {
  display: block;
  margin-top: -6px;             /* in de onderpadding van de link: het pad hoort bij zijn titel */
  pointer-events: none;         /* en houdt het tikdoel van de link heel */
  font-family: var(--af-mono);
  font-size: 0.75rem;
  color: var(--af-inkt-2);
}

/* Het tikdoel (≥44px) komt uit een vaste padding, niet uit min-height: die zette de
   restruimte ónder een titel van één regel, zodat de afstanden in de lijst verschilden. */
/* Zijpadding met een even grote negatieve marge: de tekst blijft op zijn plek (op de
   naad), en het geïnverteerde blok bij hover krijgt 8px lucht naast de letters. Zonder
   stond de laatste letter tegen de rand van het zwarte vlak (gemeten sessie 245). */
:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info) .af-lees-lijst .blog-link {
  display: inline-block;
  padding: 10px 8px;
  margin-inline: -8px;
  font-family: var(--af-tekst);
  font-size: 1.05rem;
  font-weight: 400;
  line-height: 1.35;
  color: var(--af-inkt);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;   /* de gedeelde .blog-link draagt 0 1px 3px; deze wereld heeft geen schaduw */
}

:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info) .af-lees-lijst .blog-link:hover,
:is(body.home, body.gidsen, body.sample, body.blog, body.naslag, body.info) .af-lees-lijst .blog-link:focus-visible {
  background: var(--af-inkt);
  color: var(--af-papier);
  text-decoration: none;
}

.af-lees-meer {
  font-size: var(--af-klein);
}


/* ==================== De gids: kopgroep, de gids op de naad, de hoofdstukken ==================== */
/* Sessie 256: uit gidsen.css, want de samples gebruiken dezelfde component (vier pagina's,
   de extract-regel). De klassen houden hun gi-naam: gidsen.html, check 6f en
   gidsen-layout.spec.js lezen ze zo. */
/* De grond komt via de wortellijst hierboven, niet hier (mutant M7, s254). */
:is(body.gidsen, body.sample) {
  /* Productpagina, geen affiche: koppen onder de afficheschaal (proef s254). */
  --gi-h1: var(--af-h2);
  --gi-h2: clamp(1.5rem, 2.4vw, 2.1rem);
}

/* "stap-voor-stap" breekt niet op een koppelteken; U+2011 zou uit een terugvalletter komen. */
.gi-heel {
  white-space: nowrap;
}

/* Lopende tekst op hoogstens ±75 tekens: 1ch is in Atkinson ±1,45 teken, dus de 62ch van .af p gaf
   op gidsen 83-93 tekens per regel (per regel geteld, s255). */
:is(body.gidsen, body.sample) .af p {
  max-width: 48ch;
  text-wrap: pretty;
}

/* Kopgroep dicht, de stap naar de tabel is de grote. */
.gi-aanbod {
  padding-block: clamp(24px, 2.5vw, 44px) var(--af-sectie-kort);
}

.af .gi-aanbod h1 {
  grid-column: 1 / -1;     /* over het hele raster, zoals de h1 van de homepage */
  font-size: var(--gi-h1);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.02em;
}

.af .gi-sub {
  grid-column: 1 / 9;
  padding-top: 20px;
  font-size: 1.1rem;
}

/* ==================== De gidsen op de naad ==================== */
/* Eén band, geen metronoom van vier banden (homepage s248). */
.gi-gidsen {
  padding-block: var(--af-sectie-kort);
}

.gi-gids {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  padding-block: clamp(36px, 4vw, 64px);   /* anker: scroll-padding in landing.css */
}

.gi-gids:first-child {
  padding-top: 0;
}

.gi-gids:last-child {
  padding-bottom: 0;
}

.gi-gids + .gi-gids {
  border-top: 1px solid var(--af-inkt);
}

.gi-gids-tekst {
  grid-column: 1 / 8;
  display: grid;
  align-content: start;
  gap: 14px;
  padding-right: var(--af-cel);
}

.af .gi-gids h2 {
  font-size: var(--gi-h2);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.015em;
}

.af .gi-meta {
  margin-top: -6px;
  font-family: var(--af-mono);
  font-size: var(--af-klein);
  color: var(--af-inkt-2);
}

.gi-acties {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 24px;
  padding-top: 6px;
}

/* Rechts van de naad de inhoud van de pdf (s255), als de sample-inhoud van de homepage.
   Geen verticale rand: de tabel trekt zelf de lijn. */
.gi-kantlijn {
  grid-column: 8 / -1;
  align-content: start;
  display: grid;
  gap: 10px;
  padding-left: var(--af-cel);
}

.af .gi-kantlijn p {
  margin: 0;
}

.gi-inhoud {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 2px solid var(--af-inkt);
}

.gi-inhoud li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: var(--af-cel);
  align-items: baseline;
  padding: 8px 0;
  border-bottom: 1px solid var(--af-lijn-sterk);
}

.gi-inhoud-titel {
  font-size: 0.95rem;
  line-height: 1.35;
}

.gi-inhoud-p {
  font-family: var(--af-mono);
  font-size: var(--af-klein);
  white-space: nowrap;
}

/* Onder 1024: kolom 8-12 te smal voor de kantlijn; alles onder elkaar. */
@media (max-width: 1023px) {
  .af .gi-aanbod h1,
  .af .gi-sub,
  .gi-gids-tekst {
    grid-column: 1 / -1;
  }

  .gi-gids-tekst {
    padding-right: 0;
  }

  .gi-kantlijn {
    grid-column: 1 / -1;
    margin-top: 32px;
    padding-left: 0;
  }
}

/* ==================== De inhoud van een sample ==================== */
/* Sessie 256: uit affiche.css; de homepage en de twee samplepagina's. */
/* De inhoud als tabel op het raster, in de grammatica van de cijfertabel: index in kolom
   1, titel 2-10, paginaverwijzing 11-12 rechts; bovenlijn 2px inkt, rijen in de
   bedieningslijn. Eén regel voor beide tabellen (open punt "twee tabellen, twee regels",
   sessie 248): een cel op een rasterlijn draagt vanaf 768 zelf de celmaat, links en rechts
   gelijk; onder 768 staan index en getal op de lijn. */
.af-sample-inhoud {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  margin: 0;
  padding: 0;
  list-style: none;
}

.af-sample-inhoud li {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  align-items: baseline;
  padding: 10px 0;
  border-bottom: 1px solid var(--af-lijn-sterk);
}

.af-inhoud-nr { grid-column: 1; padding-left: var(--af-cel); }
.af-inhoud-titel { grid-column: 2 / 11; padding-left: var(--af-cel); }
.af-inhoud-p { grid-column: 11 / -1; justify-self: end; padding-right: var(--af-cel); }

.af-sample-inhoud li:first-child {
  border-top: 2px solid var(--af-inkt);
}

.af-inhoud-nr,
.af-inhoud-p {
  font-family: var(--af-mono);
  font-size: var(--af-klein);
}

.af-inhoud-nr {
  font-weight: 700;
}

.af-inhoud-p {
  white-space: nowrap;
}

@media (max-width: 767px) {
  /* Vier kolommen zijn te grof voor index, titel en pagina: de rij houdt een eigen raster,
     met de index op de lijn (zoals het getal in de cijfertabel onder 768). */
  .af-sample-inhoud {
    display: block;
  }

  .af-sample-inhoud li {
    grid-template-columns: 3.2em minmax(0, 1fr) auto;
    column-gap: var(--af-cel);
  }

  .af-inhoud-nr,
  .af-inhoud-titel,
  .af-inhoud-p {
    grid-column: auto;
    padding-inline: 0;
  }
}

/* ==================== Het formulier (Brevo) ==================== */
/* Sessie 256: uit affiche.css; de nieuwsbrief op de homepage en het sampleformulier. De
   markup is die van Brevo en blijft gelijk: brevo-submit.js zoekt .homepage-newsletter op,
   dus die klasse is de wortel. Zelfde specificiteit als het oude body.home .af-news. */
:is(body.home, body.sample, body.blog) .homepage-newsletter .sib-form,
:is(body.home, body.sample, body.blog) .homepage-newsletter .sib-form-container,
:is(body.home, body.sample, body.blog) .homepage-newsletter #sib-form-container {
  max-width: none;   /* main.css: .sib-form 540px; de rasterkolom is de maat */
  padding: 0;
  margin: 0;
  background: none;
  text-align: left;
}

:is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-form {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;   /* de gedeelde regel centreert: veld 70px naast de naad */
  gap: 0;
  max-width: none;
  margin: 0;
}

/* De wrapper groeit tot de rasterrand (kolom 8-12), met een basis van 220: vanaf 1024
   passen veld en knop (150) naast elkaar (381px op 1024). Selector met .newsletter-form:
   main.css zet (0,4,0) `flex: 0 1 auto`, en die won van de vorige (0,3,1) op elke breedte,
   dus het veld had zijn eigen 247px en de knop brak op 768-1032 onder een veld zonder
   rechterrand (gemeten sessie 245). Onder 1024 staan ze bewust onder elkaar. */
:is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-form .sib-input {
  flex: 1 1 220px;
  margin: 0;
  padding: 0;
}

/* Tot 768 zet main.css het formulier in een kolom, en daar is flex-basis de hoogte: de
   220px hierboven maakte het blok om een veld van 56px 220px hoog, 164px lucht tussen veld
   en knop (regressie van sessie 245, gevonden sessie 246). Zelfde grens als main.css. */
@media (max-width: 768px) {
  :is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-form .sib-input {
    flex: none;
  }
}

:is(body.home, body.sample, body.blog) .homepage-newsletter .entry__field {
  margin: 0;
  border: 0;
  background: none;
  border-radius: 0;
}

:is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-form .input {
  width: 100%;
  min-height: 56px;
  padding: 0 16px;
  box-sizing: border-box;
  border: 1px solid var(--af-inkt);
  border-right: 0;
  border-radius: 0;
  background: var(--af-papier);
  color: var(--af-inkt);
  font-family: var(--af-tekst);
  font-size: 1rem;
  box-shadow: none;
}

:is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-form .input::placeholder {
  color: var(--af-inkt-2);
  opacity: 1;
}

:is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-button {
  min-height: 56px;
  padding: 0 24px;
  border: 1px solid var(--af-inkt);
  border-radius: 0;
  background: var(--af-inkt);
  color: var(--af-papier);
  font-family: var(--af-tekst);
  font-size: 1rem;
  font-weight: 700;
  box-shadow: none;
  cursor: pointer;
  transform: none;
}

:is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-button:hover {
  background: var(--af-papier);
  color: var(--af-inkt);
  transform: none;
  box-shadow: none;
}

/* Op één rij bovenkant op bovenkant. main.css reserveert onder beide ruimte voor een
   foutmelding, 1.6em onder de wrapper (16px letter: 25,6) en onder de knop (18px: 28,8);
   gecentreerd stond het veld daardoor 1,6px lager dan de knop. Alleen vanaf 1024: onder
   769 zet main.css de rij in een kolom die moet blijven rekken. */
@media (min-width: 1024px) {
  :is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-form {
    align-items: flex-start;
  }
}

/* Focus zoals elk ander element hier: de rode ring. main.css zet outline: none en
   kleurt alleen de rand. */
:is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-form .input:focus-visible {
  border-color: var(--af-inkt);
  outline: 2px solid var(--af-focus);
  outline-offset: 2px;
}

/* main.css geeft deze link bij hover een rand in --color-cta-primary: het signaalrood,
   als tweede lijn onder de onderstreping. Hier is hij een gewone tekstlink. */
:is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-or-support a,
:is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-or-support a:hover {
  border-bottom: 0;
}

:is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-privacy,
:is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-or-support {
  margin: 12px 0 0;
  font-size: var(--af-klein);
  color: var(--af-inkt-2);
  text-align: left;
}

/* Veld en knop onder elkaar tot 1023 (was: tot 767). Op 768-1032 brak de knop al onder
   het veld, op zijn eigen breedte en met een veld zonder rechterrand. */
@media (max-width: 1023px) {
  :is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-form .input {
    border-right: 1px solid var(--af-inkt);
  }

  :is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-button {
    width: 100%;
  }
}

/* De meldingen na het versturen. main.css tint ze groen en rood (color-mix) met een gekleurd
   icoon; hier is een melding gewoon tekst in inkt, zonder icoon. Geen lijn erboven: Brevo zet
   inline max-width 540px op het paneel, dus een rand liep op de homepage 17px vóór de
   rasterrand dood (gemeten s256). #id-selector: main.css staat op (1,1,0). */
:is(body.home, body.sample, body.blog) .homepage-newsletter #success-message,
:is(body.home, body.sample, body.blog) .homepage-newsletter #error-message {
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--af-inkt);
  font-family: var(--af-tekst);
  font-size: 1rem;
  text-align: left;
}

:is(body.home, body.sample, body.blog) .homepage-newsletter .sib-form-message-panel__text {
  display: block;
  padding: 0;
  text-align: left;
}

:is(body.home, body.sample, body.blog) .homepage-newsletter .sib-form-message-panel .sib-icon {
  display: none;
}

/* De foutmelding (sessie 257, critique cyclus 2): ze stond als gewone 16px-inkt boven het
   label, even zwaar als de intro, en viel niet op. Nu vet, met de [!] van de terminal, en
   ónder de knop, waar je net op drukte. Volgorde via de flexkolom, zodat de DOM van Brevo
   gelijk blijft; brevo-submit.js zet de focus terug op het veld en koppelt de melding eraan
   (aria-describedby). Inkt, geen rood: het rood is de actie. */
:is(body.home, body.sample, body.blog) .homepage-newsletter .sib-form-container {
  display: flex;
  flex-direction: column;
}

:is(body.home, body.sample, body.blog) .homepage-newsletter #error-message {
  order: 1;
  margin-top: 12px;
  font-weight: 700;
}

:is(body.home, body.sample, body.blog) .homepage-newsletter #error-message .sib-form-message-panel__text::before {
  content: '[!] ';
  font-family: var(--af-mono);
}

/* Wachten (brevo-submit.js zet disabled): main.css verbleekt de knop tot 0,7, en wit op dat
   rood leest slecht. Hier zegt de tekst wat er gebeurt ("Bezig met versturen…"); de knop houdt
   zijn rood (wit erop 5,79). (0,4,1) tegen (0,3,0). */
:is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-button:disabled {
  opacity: 1;
  cursor: progress;
}

/* Het tegenstuk van [!]: wat gelukt is, krijgt de [✓] van de terminal (finish review s257). */
:is(body.home, body.sample, body.blog) .homepage-newsletter #success-message .sib-form-message-panel__text::before {
  content: '[✓] ';
  font-family: var(--af-mono);
  font-weight: 700;
}

/* Het veld blijft na een fout aangewezen, ook als de focus weg is: de rand wordt 2px inkt. Als
   inset-lijn bovenop de rand van 1px, zodat er niets verschuift. */
:is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-form .input[aria-invalid="true"] {
  box-shadow: inset 0 0 0 1px var(--af-inkt);
}

/* Een programmatisch focusdoel (tabindex -1), geen bedieningselement: geen ring. */
:is(body.home, body.sample, body.blog) .homepage-newsletter #success-message:focus {
  outline: none;
}

:is(body.home, body.sample, body.blog) .homepage-newsletter .newsletter-verstuurd {
  margin: 8px 0 0;
  font-size: var(--af-klein);
  color: var(--af-inkt-2);
}

/* ==================== Na het versturen: "Ander adres?" ==================== */
/* brevo-submit.js zet onder de bevestiging het adres en deze knop (sessie 257). Ook op de
   blogindex, die de --af-tokens niet heeft: daarom alleen inherit. Een knop die leest als
   link (hij wisselt een toestand, hij navigeert niet), 44px hoog als tikdoel. */
.newsletter-ander-adres {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-decoration: underline;
  text-underline-offset: 0.2em;
  cursor: pointer;
}

/* ==================== De kopgroep en het slot: naslag en infopagina's ==================== */
/* Sessie 265 uit naslag.css (extract-regel: woordenlijst, commands, over-ons, contact, 404). De
   klassen houden hun nl-naam: naslag.css, term-filter.js en naslag-layout.spec.js lezen ze zo. */
/* Zoals gidsen: h1 op headlineschaal over het raster, de zin in 1-8. Vanaf 1024 staat de rode
   actie rechts in 9-12, naast de zin; daaronder eronder. Geen eyebrow (craft floor). */
.nl-kop {
  display: grid;
  grid-template-columns: subgrid;
  align-items: start;
  padding-block: clamp(24px, 2.5vw, 44px) clamp(28px, 2.8vw, 40px);
}

.nl-kop h1 {
  grid-column: 1 / -1;
  margin: 0;
  font-family: var(--af-kop);
  font-size: var(--af-h2);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--af-inkt);
  text-wrap: balance;
}

.nl-sub {
  grid-column: 1 / 9;
  max-width: 52ch;
  margin: 16px 0 0;
  font-size: 1.1rem;
  line-height: 1.5;
  color: var(--af-inkt-2);
}

.nl-actie {
  grid-column: 1 / -1;
  margin-top: 24px;
}

@media (min-width: 1024px) {
  .nl-actie {
    grid-column: 9 / -1;
    grid-row: 2 / span 2;
    align-self: end;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    margin-top: 16px;
    padding-left: var(--af-cel);
  }
}

/* Een actierij zoals op de blog: kop, één zin, het inkten kader. De rode actie staat bovenaan. */
/* De plaatsing op twee klassen: .nl > * en .af-raster > * (0,1,0) zetten elk kind op 1 / -1, en
   naslag.css laadt ná dit bestand (gemeten s265: het slot liep na de verhuizing over 1-12). */
:is(.nl, .af-raster) > .nl-slot {
  grid-column: 1 / 8;
}

.nl-slot {
  margin-top: var(--af-sectie-kort);
  padding: 16px 0 24px;
  border-top: 2px solid var(--af-inkt);
  border-bottom: 1px solid var(--af-lijn-sterk);
}

@media (max-width: 1023px) {
  :is(.nl, .af-raster) > .nl-slot {
    grid-column: 1 / -1;
  }
}

.nl-slot h2 {
  margin: 0;
  font-family: var(--af-kop);
  font-size: var(--af-h3);
  font-weight: 700;
  line-height: 1.2;
  color: var(--af-inkt);
}

.nl-slot p {
  max-width: 48ch;
  margin: 8px 0 16px;
  line-height: 1.55;
  color: var(--af-inkt-2);
}

/* ==================== De vragen (FAQ): homepage en contact ==================== */
/* Sessie 265 uit affiche.css. Twee pagina's, onder de drempel van drie van de extract-regel, maar
   een kopie kostte 1,4 KB van een budget met 4 KB marge. :is() houdt de specificiteit van body.home. */
:is(body.home, body.info) .af-faq .faq-item {
  margin: 0;
  padding: 0;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--af-lijn-sterk);
  border-radius: 0;
  box-shadow: none;
  opacity: 1;
  transform: none;
  filter: none;
}

:is(body.home, body.info) .af-faq .faq-heading {
  margin: 0;
  font-size: inherit;
}

:is(body.home, body.info) .af-faq .faq-question {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  width: 100%;
  min-height: 60px;
  padding: 14px 0;
  background: none;
  border: 0;
  border-radius: 0;
  color: var(--af-inkt);
  font-family: var(--af-kop);
  font-size: 1.1rem;
  font-weight: 700;
  text-align: left;
  cursor: pointer;
}

:is(body.home, body.info) .af-faq .faq-question:hover {
  background: none;
  color: var(--af-inkt);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

:is(body.home, body.info) .af-faq .faq-icon {
  flex-shrink: 0;
  color: var(--af-inkt);
  transition: transform 200ms var(--af-ease);
}

:is(body.home, body.info) .af-faq .faq-item.open .faq-icon {
  transform: rotate(180deg);
}

/* De gedeelde FAQ animeert max-height en padding: layout-eigenschappen, en hier is de
   enige beweging de registratie. Open en dicht zonder overgang. */
:is(body.home, body.info) .af-faq .faq-answer {
  transition: none;
}

:is(body.home, body.info) .af-faq .faq-answer p {
  max-width: 60ch;
  padding-bottom: 20px;
  color: var(--af-inkt);
}

/* ==================== De module in tekst: blog en naslag ==================== */
/* Sessie 263 uit blog.css (extract-regel): de vijftien posts en commands/ tonen terminaluitvoer
   in dezelfde zwarte module. Prompt papier 700, uitvoer uit de papierfamilie, de info-rol op een
   papieren label, waarschuwing amber, fout zalm. De homepage heeft een eigen module (affiche.css,
   met glos-kolom en registratie) en zet deze tokens zelf op body.home. */
:is(body.blog, body.naslag, body.info) {
  --af-m-grond: #0a0a0a;
  --af-m-tekst: #d6d6d2;        /* 13,58 op de grond */
  --af-m-prompt: #efefec;       /* 17,18, in 700 */
  --af-m-label: #efefec;
  --af-m-label-inkt: #111111;   /* 16,39 op het label */
  --af-m-fout: #fa7c76;         /* 7,74 */
  --af-m-waarsch: #d29922;      /* 7,84 */
  --af-rij: 1.5rem;
}

:root[data-theme="dark"] :is(body.blog, body.naslag, body.info) {
  --af-m-grond: #000000;
}

/* Elke regel is een eigen blok (.r): zonder klapte meerregelige uitvoer in tot één alinea, op de
   blog 41 van 57 blokken (s261), op commands/ 30 van 31 (s263). Een te lange regel slaat om en
   springt in, op de lijn van een harde vervolgregel (Literal Output Rule). */
.terminal-example .prompt {
  color: var(--af-m-prompt);
  font-weight: 700;
  white-space: pre-wrap;
  user-select: none;
}

.terminal-example .output {
  margin: 0;
}

.terminal-example .r {
  display: block;
  min-height: var(--af-rij);
  padding-left: 1.8em;
  text-indent: -1.8em;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* Een regel met een tiplabel springt zes tekens in (3,6em: JetBrains Mono is 0,6em breed), op de
   lijn van zijn harde vervolgregel, die in de bron na "[TIP] " begint (sessie 262: de omgeslagen
   eerste regel stond op drie tekens, de vervolgregel op zes). */
.terminal-example .r:has(> .tip) {
  padding-left: 3.6em;
  text-indent: -3.6em;
}

.terminal-example .tip {
  margin-left: -6px;
  padding: 1px 6px;
  background: var(--af-m-label);
  color: var(--af-m-label-inkt);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

.terminal-example .warn { color: var(--af-m-waarsch); }
.terminal-example .err { color: var(--af-m-fout); }

