/*
|-----------------------------------------------------------------------------
| EAGER NINJA — thema
|-----------------------------------------------------------------------------
| De complete opmaak van de site: kleuren, typografie, knoppen, kaarten, het
| commandopalet, de popups en de nagebouwde Notula-mockup.
|
| Dit bestand is het sjabloon. Wil een volgende app er hetzelfde uitzien, dan
| neem je dit over samen met public/fonts/ — er zit geen bouwstap tussen.
|
| Wat je moet weten voordat je hier iets verandert:
|
|   * Poppins en Material Symbols staan zelf gehost in public/fonts/. Bewust
|     niet bij Google: een merk dat privacy-first heet hoort zijn bezoekers
|     niet langs een derde partij te sturen.
|   * Iconen zijn tekst, geen SVG. Grootte gaat dus via font-size en niet via
|     breedte en hoogte — dat is de val bij het aanpassen.
|   * De pagina is met opzet één donkere wereld. Er is geen lichte stand; elke
|     kleur wordt daarom expliciet gezet, zodat de pagina ook standhoudt op een
|     lichte ondergrond.
|   * Nergens staat een kleur alleen binnen een @media-blok. Doe dat ook niet:
|     dan valt hij weg in de stand die je niet getest hebt.
|
| Naast dit bestand hoort public/css/tailwind.css: de klassen die de opmaak van
| de landingspagina dragen, één keer gegenereerd. Verander je de HTML van die
| pagina, dan moet dat bestand opnieuw gemaakt worden — zie LEESMIJ.md.
*/

/* ── Poppins, identiek aan Notula ──────────────────────────────
           Zelfde bestanden, zelfde unicode-range-splitsing: de browser haalt
           de "latinext"-variant alleen op als er tekens in staan die daarin
           zitten. Scheelt op deze pagina ruim de helft van het fontverkeer. */
        @font-face{font-family:'Poppins';font-style:normal;font-weight:400;font-display:swap;
          src:url('/fonts/poppins-400-latin.woff2') format('woff2');
          unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
        @font-face{font-family:'Poppins';font-style:normal;font-weight:400;font-display:swap;
          src:url('/fonts/poppins-400-latinext.woff2') format('woff2');
          unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}
        @font-face{font-family:'Poppins';font-style:normal;font-weight:500;font-display:swap;
          src:url('/fonts/poppins-500-latin.woff2') format('woff2');
          unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
        @font-face{font-family:'Poppins';font-style:normal;font-weight:500;font-display:swap;
          src:url('/fonts/poppins-500-latinext.woff2') format('woff2');
          unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}
        @font-face{font-family:'Poppins';font-style:normal;font-weight:600;font-display:swap;
          src:url('/fonts/poppins-600-latin.woff2') format('woff2');
          unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
        @font-face{font-family:'Poppins';font-style:normal;font-weight:600;font-display:swap;
          src:url('/fonts/poppins-600-latinext.woff2') format('woff2');
          unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}
        @font-face{font-family:'Poppins';font-style:normal;font-weight:700;font-display:swap;
          src:url('/fonts/poppins-700-latin.woff2') format('woff2');
          unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
        @font-face{font-family:'Poppins';font-style:normal;font-weight:700;font-display:swap;
          src:url('/fonts/poppins-700-latinext.woff2') format('woff2');
          unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}

        :root {
            /* Exact de twee regels uit Notula's app.css, zodat de landing en de
               app dezelfde letter tonen — ook als het woff2 nog niet binnen is. */
            --font:      'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, Roboto, sans-serif;
            --font-mono: 'SF Mono', 'Cascadia Code', 'Consolas', ui-monospace, monospace;

            --bg:      #070709;
            --bg-soft: #0b0c10;
            --bg-card: rgba(255, 255, 255, 0.024);
            --line:    rgba(255, 255, 255, 0.08);
            --line-hi: rgba(255, 255, 255, 0.16);
            --txt:     #f6f7f8;
            --muted:   #8b90a0;
            /* 3,58:1 was te weinig: deze kleur draagt de trust badges en
               de privacyregel, dus gewone tekst. Nu ~4,8:1 op #070709. */
            --dim:     #767c8e;
            --a1:      #7c5cff;
            --a2:      #22d3ee;
            --ok:      #34d97b;
            --shadow:  0 24px 64px -24px rgba(0, 0, 0, 0.9);
            color-scheme: dark;
        }

        /* Padding en rand tellen mee ín de breedte, niet erbovenop.

   Op de landingspagina regelt Tailwind dit, maar de poort en het beheer laden
   Tailwind bewust niet — en zonder deze regel wordt een blok met width:100%
   en padding breder dan zijn ouder. Dat leverde een toegangsvlak van 794 px op
   naast een preview van 736 px, plus horizontale overloop. */
*, *::before, *::after { box-sizing: border-box; }

* { border-color: var(--line); }

        html {
            background: var(--bg);
            scroll-behavior: smooth;
            scroll-padding-top: 6.75rem;
            -webkit-text-size-adjust: 100%;
        }

        body {
            background: var(--bg);
            color: var(--txt);
            font-family: var(--font);
            -webkit-font-smoothing: antialiased;
            text-rendering: optimizeLegibility;
            margin: 0;
            overflow-x: hidden;
        }

        /* Hero-typografie vóór Tailwind, zodat de LCP-tekst meteen goed staat.
           Poppins is geometrisch en rond: de strakke -0.045em die Linear op
           Inter gebruikt laat de o's en e's hier tegen elkaar aan lopen. Op
           -0.02em blijft het scherp én leesbaar. Regelhoogte iets ruimer, want
           Poppins heeft een lagere x-hoogte dan Inter. */
        .h-display {
            font-size: clamp(2.625rem, 7.4vw, 5.25rem);
            line-height: 1.04;
            letter-spacing: -0.02em;
            font-weight: 600;
            margin: 0;
            text-wrap: balance;
        }

        .h-section {
            font-size: clamp(1.875rem, 4vw, 2.875rem);
            line-height: 1.14;
            letter-spacing: -0.018em;
            font-weight: 600;
            text-wrap: balance;
        }

        /* Losse woorden in kapitalen hebben bij Poppins juist ruimte nodig. */
        h1, h2, h3 { font-family: var(--font); }

        .mono { font-family: var(--font-mono); }

        /* ── Achtergrond: aurora + raster + grain ─────────────────────── */
        .bg-stage {
            position: fixed;
            inset: 0;
            z-index: 0;
            pointer-events: none;
            overflow: hidden;
        }

        .bg-stage::before {
            content: '';
            position: absolute;
            top: -34rem;
            left: 50%;
            width: min(120rem, 190vw);
            height: 68rem;
            transform: translateX(-50%);
            background:
                radial-gradient(46% 44% at 50% 52%, rgba(124, 92, 255, 0.28), transparent 68%),
                radial-gradient(34% 38% at 24% 44%, rgba(34, 211, 238, 0.16), transparent 70%),
                radial-gradient(30% 34% at 76% 40%, rgba(236, 72, 153, 0.11), transparent 72%);
            filter: blur(28px);
        }

        /* Honingraat in plaats van ruitjes.
           Eén SVG-tegel van 34,64 × 60 met vijf zeshoeken: de middelste past
           er helemaal in, de vier op de hoeken lopen door in de buurtegels.
           Daardoor sluit het patroon naadloos aan bij herhaling.
           34,64 = √3 × 20, de breedte van een spitse zeshoek met zijde 20 —
           die verhouding moet kloppen, anders staan de raten scheef.

           De lijnen staan op vol wit in de tegel en de dekking regelt de
           laag zelf: gedeelde randen worden twee keer getekend, en met een
           half doorzichtige lijnkleur zouden die dubbel zo hard oplichten. */
        .bg-stage::after {
            content: '';
            position: absolute;
            inset: 0;
            opacity: 0.06;
            background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='34.64' height='60' viewBox='0 0 34.64 60'%3E%3Cg fill='none' stroke='%23fff' stroke-width='0.65'%3E%3Cpath d='M17.32 10L34.64 20L34.64 40L17.32 50L0 40L0 20Z'/%3E%3Cpath d='M0 -20L17.32 -10L17.32 10L0 20L-17.32 10L-17.32 -10Z'/%3E%3Cpath d='M34.64 -20L51.96 -10L51.96 10L34.64 20L17.32 10L17.32 -10Z'/%3E%3Cpath d='M0 40L17.32 50L17.32 70L0 80L-17.32 70L-17.32 50Z'/%3E%3Cpath d='M34.64 40L51.96 50L51.96 70L34.64 80L17.32 70L17.32 50Z'/%3E%3C/g%3E%3C/svg%3E");
            background-size: 51.96px 90px;
            mask-image: radial-gradient(115% 70% at 50% 0%, #000 8%, transparent 62%);
            -webkit-mask-image: radial-gradient(115% 70% at 50% 0%, #000 8%, transparent 62%);
        }

        .grain {
            position: fixed;
            inset: 0;
            z-index: 1;
            pointer-events: none;
            opacity: 0.032;
            mix-blend-mode: overlay;
            background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
        }

        /* ── Glas & randen ────────────────────────────────────────────── */
        .glass {
            background: var(--bg-card);
            border: 1px solid var(--line);
            backdrop-filter: blur(14px) saturate(150%);
            -webkit-backdrop-filter: blur(14px) saturate(150%);
        }

        /* Linear-truc: gradient-hairline aan de bovenkant van een kaart. */
        .edge-top {
            position: relative;
        }
        .edge-top::before {
            content: '';
            position: absolute;
            inset-inline: 12%;
            /* top: 0, niet -1px: vier van de vijf kaarten hebben
               overflow:hidden en knipten de lijn anders volledig weg. */
            top: 0;
            height: 1px;
            background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.45), transparent);
            opacity: 0.55;
        }

        /* Cursor-spotlight op de bento-kaarten. */
        .spot {
            position: relative;
            isolation: isolate;
            transition: border-color 0.35s ease, transform 0.35s ease;
        }
        .spot::after {
            content: '';
            position: absolute;
            inset: 0;
            border-radius: inherit;
            opacity: 0;
            transition: opacity 0.35s ease;
            background: radial-gradient(
                24rem 24rem at var(--mx, 50%) var(--my, 0%),
                rgba(124, 92, 255, 0.16),
                transparent 62%
            );
            z-index: -1;
        }
        .spot:hover { border-color: var(--line-hi); }
        .spot:hover::after { opacity: 1; }

        /* ── Woordmerk ────────────────────────────────────────────────────
           EAGER zwaar, NINJA licht, met de metaalglans uit het logo: een band
           die van wit via grijs terug naar wit loopt. Bewust in CSS en niet als
           afbeelding — zo blijft het scherp op elk scherm, is het selecteerbaar
           en leesbaar voor zoekmachines, en kost het nul kilobytes.

           Valt de gradiënt weg (oudere browser, geforceerde kleuren), dan
           zorgt de `color` eronder dat er gewoon witte tekst staat. */
        .wordmark {
            color: #f4f6f8;
            letter-spacing: -0.015em;
            line-height: 1;
            white-space: nowrap;
        }
        /* Dezelfde gradiënt als de <h1>: wit → lavendel → lichtblauw. Zo is de
           titel in de hero geen los kunstje maar een vergroting van het logo. */
        @supports (-webkit-background-clip: text) or (background-clip: text) {
            .wordmark {
                background: linear-gradient(100deg, #ffffff 4%, #cfc6ff 52%, #8fe6f5 98%);
                -webkit-background-clip: text;
                background-clip: text;
                color: transparent;
            }
        }
        /* In hoog-contrastmodus wint leesbaarheid van de glans. */
        @media (forced-colors: active) {
            .wordmark { background: none; color: CanvasText; }
        }

        /* Het woordmerk als één geheel.

   Eén maat op .merk stuurt allebei de regels. Schaal je ze los, dan wordt de
   payoff bij een kleiner woordmerk breder dan de naam erboven en lijkt het
   logo scheef — die 0,385 is precies de verhouding waarbij de "e" van Simple
   onder de "A" van NINJA eindigt. */
/* Zeshoek links, naam en payoff rechts. Eén font-size op .merk stuurt alle
   drie: schaal je ze los, dan wordt de payoff bij een kleiner logo breder dan
   de naam erboven en lijkt het merk scheef. */
.merk {
    display: inline-flex;
    /* center, geen stretch: .merk wordt op sommige plekken door zijn ouder
       uitgerekt (op de poort tot 260 px), en met stretch groeit de zeshoek dan
       mee tot buiten het logo. De hoogte van de zeshoek staat daarom vast in
       em hieronder. */
    align-items: center;
    /* Dicht op de naam: de zeshoek en het woordmerk horen als één merk te
       lezen, niet als een plaatje met tekst ernaast. */
    gap: 0.26em;
    line-height: 1;
    /* align-self en width: als flex-kind in een kolom rekt dit blok anders mee
       tot de volle breedte van zijn ouder, en dan lijnt de payoff uit op die
       rand in plaats van op de naam erboven. */
    align-self: flex-start;
    width: fit-content;
}

.merk-teken {
    /* De hoogte loopt van de kaplijn van EAGER tot de basislijn van de payoff.
       Dat is geen willekeurige maat: het zijn de twee lijnen waar het oog het
       logo aan ophangt. Gemeten, met de bovenkant van het tekstblok als
       nulpunt:
           kaplijn EAGER      0,1500 em
           basislijn payoff   1,3925 em
           hoogte             1,2425 em

       Op kaphoogte alleen (0,7031 em) werd de EN erin 5 px in de kopbalk en
       4 px op mobiel: textuur in plaats van tekst. Zo wordt hij 9 tot 14 px.

       Let op het verschil tussen de tekening en zijn doos: het pad loopt van
       y=1 tot y=23 in een viewBox van 24, dus 22/24 van de doos. Voor 1,2425 em
       zichtbaar moet de doos 1,2425 x 24/22 = 1,3555 em zijn. */
    height: 1.3555em;
    width: 1.3555em;
    flex: none;
    display: block;

    /* Het middelpunt is de E van EAGER, niet het midden van het tekstblok.
       Die twee liggen niet op dezelfde hoogte, want de payoff hangt onder het
       blok en trekt het midden daarvan omlaag. align-items op .merk is center,
       dus zonder correctie zou de zeshoek dat lagere midden volgen. Gemeten,
       met de bovenkant van het tekstblok als nulpunt:
           de E loopt van 0,150 em tot 0,853 em   -> midden 0,5016 em
           het blok is 1,585 em hoog              -> midden 0,7925 em
       De zeshoek gaat dus 0,2909 em omhoog.

       Daardoor steekt hij 0,12 em boven de bovenkant van het woordmerk uit.
       Dat is de bedoeling en het duwt niets opzij: `top` verschuift alleen wat
       je ziet, niet wat de opmaak berekent. */
    position: relative;
    top: -0.2909em;
}

.merk-tekst {
    display: inline-flex;
    flex-direction: column;
    gap: 0.2em;
    min-width: 0;
}

.merk .wordmark { font-size: 1em; }
/* 0,385 is de maat van het logo zelf. Hij heeft even op 0,44 gestaan omdat een
   doorlichting meldde dat de payoff nergens boven de 12 px uitkwam — 8,5 px in
   de kopbalk, 10,8 px in de voet. Dat was een regel voor LOPENDE TEKST die hier
   niet hoort: een payoff in een logo is merkmeubilair, geen leesstof, en die is
   in elk logo klein. Groter maken haalde de verhoudingen uit het merk.

   Waar de kleine maat wél knelt is de kopbalk op een smal scherm; daar valt de
   payoff daarom weg (zie de media query onderaan dit bestand). Dat is een
   opmaakbeslissing op één plek, en niet iets om het hele merk voor te
   verbouwen. */
.merk .payoff   { font-size: 0.385em; }

.wordmark-eager { font-weight: 700; }
        .wordmark-ninja { font-weight: 400; margin-left: 0.14em; }

        /* De payoff staat in het logo op de volle breedte van het woordmerk;
           de letterspatiëring hieronder benadert dat zonder trucs. */
        /* De payoff eindigt rechts precies onder de A van NINJA.
           Twee dingen zijn daarvoor nodig:

           1. text-align:right — de regel is smaller dan het woordmerk, en
              stond dus links uitgelijnd twintig pixels te ver naar binnen.
           2. géén margin-correctie. Dat leek nodig — letter-spacing zet die
              ruimte immers ook áchter de laatste letter — maar gemeten blijkt
              de browser die spatie bij rechts uitlijnen zelf al weg te laten.
              Mét correctie stond de e er 0,55 px vóórbij in plaats van erop.

           Gemeten: rechterrand van de A op 294,46 px, rechterrand van de e op
           294,46 px. Verander je de letterspatiëring, meet dan opnieuw met een
           Range over het laatste teken — de doosbreedte zegt het je niet. */
        .payoff {
            color: var(--muted);
            letter-spacing: 0.055em;
            line-height: 1;
            white-space: nowrap;
            text-align: right;
        }
        .payoff b { color: #e9ebef; font-weight: 600; }

        .grad-text {
            /* Zelfde reden als bij .poort-kop: buiten de doos van het element
               krijgt de tekst geen gradiënt en verdwijnt hij. Dit is een inline
               element, dus verticale padding duwt de regels NIET uit elkaar —
               hij vergroot alleen het vlak waarop geschilderd wordt. Gratis
               verzekering voor staartletters als de p van "simpler". */
            padding-bottom: 0.08em;
            background: linear-gradient(100deg, #ffffff 6%, #cfc6ff 46%, #8fe6f5 96%);
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
        }

        /* ── Knoppen ──────────────────────────────────────────────────── */
        .btn {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 0.5rem;
            border-radius: 0.625rem;
            font-weight: 500;
            font-size: 0.9375rem;
            line-height: 1;
            padding: 0.8125rem 1.25rem;
            white-space: nowrap;
            text-decoration: none;
            cursor: pointer;
            transition: transform 0.18s ease, box-shadow 0.25s ease,
                        background-color 0.25s ease, border-color 0.25s ease;
        }
        .btn:active { transform: translateY(1px) scale(0.99); }

        .btn-primary {
            color: #0a0a12;
            background: linear-gradient(180deg, #ffffff, #ddd9f5);
            border: 1px solid rgba(255, 255, 255, 0.9);
            box-shadow: 0 0 0 1px rgba(124, 92, 255, 0.22),
                        0 12px 36px -12px rgba(124, 92, 255, 0.65);
        }
        .btn-primary:hover {
            box-shadow: 0 0 0 1px rgba(124, 92, 255, 0.4),
                        0 18px 46px -12px rgba(124, 92, 255, 0.85);
        }

        .btn-ghost {
            color: var(--txt);
            background: rgba(255, 255, 255, 0.035);
            border: 1px solid var(--line);
        }
        .btn-ghost:hover {
            background: rgba(255, 255, 255, 0.07);
            border-color: var(--line-hi);
        }

        /* Toetsenbord-focus zichtbaar, muisklik niet. */
        :where(a, button, input, summary, [tabindex]):focus-visible {
            outline: 2px solid var(--a2);
            outline-offset: 3px;
            border-radius: 0.4rem;
        }

        kbd {
            font-family: var(--font-mono);
            font-size: 0.6875rem;
            line-height: 1;
            padding: 0.25rem 0.375rem;
            border-radius: 0.3125rem;
            border: 1px solid var(--line);
            background: rgba(255, 255, 255, 0.05);
            color: var(--muted);
        }

        /* ── Iconen: Material Symbols Rounded ─────────────────────────────
           Hetzelfde icoonlettertype als Notula, uitgedund tot precies de iconen
           die dit portal gebruikt: 9 kB, tegenover 419 kB voor de bibliotheek
           die er hiervoor stond.

           LET OP — dit bestand is een SUBSET. Er zitten alleen de iconen in die
           op dat moment gebruikt werden. Zet je ergens een nieuwe icoonnaam
           neer, dan is die er niet, en dan valt de ligatuur terug op de tekst
           zelf: je ziet een losse letter staan (een "D" voor `database`, een
           "C" voor `cell_tower`). Het lijkt op een stukke stijl maar het is een
           ontbrekend teken.

           Nieuwe subset maken — de lijst met namen komt uit de broncode:

             grep -rhoE 'class="ms[^"]*">[a-z_0-9]+' resources/views \
               | sed 's/.*>//' | sort -u | paste -sd,

             curl -A "<een echte browser-UA>" \
               "https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded&icon_names=<lijst>"

           en dan het woff2-adres uit dat antwoord ophalen. Bewust ZONDER het
           asbereik achter de familienaam: dan krijg je één vaste snit van 9 kB
           in plaats van een variabel lettertype van 102 kB. De regel
           font-variation-settings hieronder doet op een vaste snit niets, en
           dat is prima — de standaardsnit is precies wat we tonen.

           Een icoon is hier tekst: de naam staat in het element en het
           lettertype maakt er een tekening van. Grootte dus via font-size,
           niet via breedte en hoogte — dat is de val bij het overstappen.

           font-display: block is met opzet. Tot het lettertype er is, is de
           inhoud de ligatuurnaam ("keyboard_return"); die mag je niet even
           zien staan. */
        @font-face {
            font-family: 'Material Symbols';
            font-style: normal;
            font-weight: 400;
            font-display: block;
            /* Het versienummer moet mee omhoog zodra je een nieuwe subset maakt.

               De helper middel() zet een hash achter stylesheets en scripts,
               maar niet achter een adres dát ín een stylesheet staat — dit
               adres dus. Zonder ?v= houdt de browser het oude bestand vast, en
               de service worker helemaal: die geeft alles onder /fonts/ eerst
               uit zijn cache. Je krijgt dan losse letters te zien op de plek
               van je nieuwe iconen en gaat in de CSS zoeken naar een fout die
               er niet is. Eén keer op gestruikeld. */
            src: url('/fonts/material-symbols.woff2?v=2') format('woff2');
        }

        .ms {
            font-family: 'Material Symbols';
            font-weight: 400;
            font-style: normal;
            line-height: 1;
            display: inline-block;
            flex-shrink: 0;
            width: 1em;
            height: 1em;
            overflow: hidden;
            letter-spacing: normal;
            text-transform: none;
            white-space: nowrap;
            word-wrap: normal;
            direction: ltr;
            -webkit-font-feature-settings: 'liga';
            -webkit-font-smoothing: antialiased;
            font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
        }

        .ico {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 1.125rem;
            height: 1.125rem;
            font-size: 1.125rem;
            flex: none;
        }
        .ico-lg { width: 1.375rem; height: 1.375rem; font-size: 1.375rem; }

        /* ── Statuslamp ───────────────────────────────────────────────── */
        .led {
            position: relative;
            width: 0.5rem;
            height: 0.5rem;
            border-radius: 999px;
            background: var(--ok);
            box-shadow: 0 0 0 3px rgba(52, 217, 123, 0.14);
            flex: none;
        }
        .led::after {
            content: '';
            position: absolute;
            inset: 0;
            border-radius: inherit;
            background: var(--ok);
            animation: ping 2.4s cubic-bezier(0, 0, 0.2, 1) infinite;
        }
        @keyframes ping {
            0%   { transform: scale(1);   opacity: 0.7; }
            70%  { transform: scale(3.2); opacity: 0; }
            100% { transform: scale(3.2); opacity: 0; }
        }
        .led-down { background: #f5a524; box-shadow: 0 0 0 3px rgba(245, 165, 36, 0.16); }
        .led-down::after { background: #f5a524; }

        /* ── Scroll-reveal ────────────────────────────────────────────────
           Let op de .js-voorwaarde. Zonder JavaScript — CDN eruit, script-fout,
           oude browser, tekstbrowser — blijft alles gewoon zichtbaar. Zou de
           opacity: 0 onvoorwaardelijk zijn, dan toont deze pagina bij de
           kleinste JS-storing een lege zwarte vlakte. */
        .js .reveal {
            opacity: 0;
            transform: translateY(14px);
            transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1),
                        transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
            will-change: opacity, transform;
        }
        /* will-change loslaten zodra de overgang klaar is: anders houdt de
           browser voor 31 elementen een aparte laag aan die nooit meer
           verandert. */
        .js .reveal.in { opacity: 1; transform: none; will-change: auto; }

        /* ── Typemachine in de kop ───────────────────────────────────────
           Het wisselende woord staat in de bron, dus zonder JavaScript leest
           er gewoon "life simpler." en zien crawlers de volledige kop.

           Bewust GEEN vaste breedte. Dat was de eerste opzet — een doos zo
           breed als het langste woord, om layout shift te vermijden — maar
           dan staat er een gat van veertig pixels tussen "life" en
           "simpler." en leest het als een fout in plaats van als een effect.

           De rekensom erachter: het bewegende gebied is ruwweg 300×80 px in
           een venster van 1440×900 (impact ≈ 0,019) en schuift zo'n 12 px per
           beeldje (afstand ≈ 0,013). Dat is 0,00025 per verschuiving, en met
           een stuk of zestien verschuivingen binnen één meetvenster ongeveer
           0,004 — tegen een CLS-budget van 0,1. Niet de moeite waard om een
           zichtbaar gat voor te accepteren. */
        .tw { display: inline-block; }
        .tw-caret {
            display: none;
            width: 0.06em;
            height: 0.82em;
            margin-left: 0.045em;
            vertical-align: -0.06em;
            border-radius: 1px;
            /* Vaste kleur: de ouder heeft color:transparent voor de
               gradiënt, dus currentColor zou hier onzichtbaar zijn. */
            background: #8fe6f5;
        }
        /* Twee wegen naar hetzelfde: .js zet de cursor neer zodra JavaScript
           aan staat, .tw-actief zodra de typemachine daadwerkelijk begint. Dat
           tweede is wat de poort gebruikt — die zet geen .js op <html>, en een
           knipperende cursor achter een zin die niet beweegt is een belofte die
           niet wordt ingelost. */
        .js .tw-caret,
        .tw-actief .tw-caret { display: inline-block; }
        .tw-caret.rest { animation: blink 1.05s steps(1) infinite; }
        @keyframes blink { 50% { opacity: 0; } }

        /* ── Productmockup ────────────────────────────────────────────── */
        .mock {
            border-radius: 0.875rem;
            border: 1px solid var(--line);
            background: #23262f;
            box-shadow: var(--shadow), 0 0 0 1px rgba(255, 255, 255, 0.03) inset;
            overflow: hidden;
        }

        /* ── Het Notula-dashboard, nagebouwd ──────────────────────────────
           Geen schermafdruk maar opmaak. Blijft scherp op elk scherm, weegt
           nul kilobyte, en de datum in de kop klopt altijd — een afdruk van
           vorig jaar valt meteen op. Kleuren, indeling en cijfers komen uit
           de donkere stand van notula.eager.ninja.

           ⚠ Verandert het dashboard, pas dit dan aan. Een productfoto die
             niet meer klopt is erger dan geen productfoto. Wil je liever een
             echte opname: zet $heroShot in het configuratieblok, dan komt er
             een <img> in plaats van dit blok.

           Alles hierbinnen staat in em, dus die ene font-size schaalt de
           complete mockup mee met het venster. */
        .nt {
            --nt-side:   #23262f;
            --nt-bg:     #2b2f3a;
            --nt-panel:  #303442;
            --nt-card:   #272b36;
            --nt-line:   rgba(255, 255, 255, 0.07);
            --nt-txt:    #e9ebf1;
            --nt-mut:    #9aa0b0;
            --nt-soft:   #6f7585;
            --nt-acc:    #7b7bf0;
            --nt-cyan:   #35c6e0;
            --nt-pink:   #ef4d8b;
            --nt-orange: #f97b34;
            --nt-gray:   #868c9c;
            --nt-gold:   #e3c04a;
            --nt-teal:   #4fd1c5;

            /* De vloer stond op 8 px en 0,95vw haalde die pas bij 842 px in.
               Tussen 640 px (waar de zijbalk erbij komt) en 1053 px werd de
               mockup dus KLEINER naarmate het scherm groter werd: op een
               telefoon 10 px, op een tablet 8 px. Met 10 px en 1,2vw sluit hij
               aan op de telefoonmaat en staat hij vanaf 958 px op zijn
               maximum. */
            font-size: clamp(10px, 1.2vw, 11.5px);
            line-height: 1.35;
            color: var(--nt-txt);
            background: var(--nt-side);
        }

        /* Browserlijst met adres */
        .nt-chrome {
            display: flex;
            align-items: center;
            gap: 0.7em;
            padding: 0.75em 1em;
            background: rgba(255, 255, 255, 0.02);
            border-bottom: 1px solid var(--nt-line);
        }
        .nt-dot { width: 0.62em; height: 0.62em; border-radius: 999px; background: rgba(255,255,255,.12); flex: none; }
        .nt-url {
            margin: 0 auto;
            font-family: var(--font-mono);
            font-size: 0.86em;
            color: var(--nt-soft);
        }

        .nt-app { display: grid; grid-template-columns: 16.5em 1fr; }

        /* ── Zijbalk ────────────────────────────────────────────────── */
        .nt-side {
            padding: 1em 0.85em;
            /* De zijbalk is hoger dan het hoofdgebied; zonder deze regel
               blijft er een dode band onder het dashboardvlak staan. */
            height: 100%;
            border-right: 1px solid var(--nt-line);
            display: flex;
            flex-direction: column;
            gap: 0.75em;
            min-width: 0;
        }
        .nt-brand { display: flex; align-items: center; gap: 0.5em; padding: 0 0.2em; }
        /* Het merkteken van Notula: de onderbroken ring met het potlood.
           Eén op één het bestand dat de app zelf gebruikt
           (notula/public/img/notula-merk-64.png), en op dezelfde manier: als
           masker, niet als plaatje. Zo neemt hij de kleur van de tekst ernaast
           over en is er geen aparte lichte versie nodig.

           Verandert het logo, dan opnieuw coderen:
             base64 -w0 notula/public/img/notula-merk-64.png */
        .nt-merk {
            width: 1.85em;
            height: 1.85em;
            flex: none;
            background: currentColor;
            -webkit-mask: url("data:image/png;base64,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") center/contain no-repeat;
            mask: url("data:image/png;base64,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") center/contain no-repeat;
        }
        .nt-brand b { font-size: 1.55em; font-weight: 700; letter-spacing: -0.01em; line-height: 1; }
        .nt-brand i {
            display: block;
            font-style: normal;
            font-size: 0.62em;
            letter-spacing: 0.16em;
            color: var(--nt-gold);
            margin-top: 0.25em;
        }
        .nt-search, .nt-new {
            display: flex; align-items: center; gap: 0.55em;
            padding: 0.62em 0.75em;
            border-radius: 0.6em;
            font-size: 0.95em;
        }
        .nt-search { background: rgba(255,255,255,.035); color: var(--nt-soft); }
        .nt-new { background: rgba(255,255,255,.055); color: var(--nt-txt); font-weight: 500; }

        .nt-nav, .nt-list { list-style: none; margin: 0; padding: 0; }
        .nt-nav li, .nt-list li {
            display: flex; align-items: center; gap: 0.65em;
            padding: 0.52em 0.7em;
            border-radius: 0.55em;
            color: var(--nt-mut);
            font-size: 0.98em;
            min-width: 0;
        }
        .nt-nav li span, .nt-list li span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        .nt-nav li.on { background: rgba(255,255,255,.06); color: var(--nt-txt); font-weight: 500; }
        .nt-nav li b, .nt-list li b { margin-left: auto; font-weight: 400; color: var(--nt-soft); font-size: 0.92em; }

        .nt-sec {
            display: flex; align-items: center; gap: 0.5em;
            padding: 0.5em 0.7em 0.2em;
            color: var(--nt-soft);
            font-size: 0.95em;
        }
        .nt-sec b { margin-left: auto; font-weight: 400; }
        .nt-sec b.\!ml-0 { margin-left: 0.5em; }

        /* Persoonlijke inhoud in de mockup staat onscherp. Dat past bij het
           verhaal van de pagina — je laat het dashboard zien zonder iemands
           notities te tonen — en het scheelt de vraag wie "John" is.

           Wat wél scherp blijft: de navigatie, de getallen en de kaarttitels.
           Dat is het product. Wat je vervaagt zijn de gegevens.

           Let op: dit is een gordijn, geen slot. De tekst staat gewoon in de
           HTML. Voor deze mockup maakt dat niets uit — het zijn verzonnen
           namen — maar gebruik deze klasse nooit om échte gegevens af te
           schermen. Notula maakt datzelfde onderscheid met zijn privacy-stand. */
        .nt-wazig {
            filter: blur(0.32em);
            user-select: none;
            -webkit-user-select: none;
        }
        @media (prefers-reduced-motion: no-preference) {
            .nt-wazig { transition: filter 0.3s ease; }
        }

        .nt-i { display: inline-flex; font-size: 1.05em; width: 1em; height: 1em; flex: none; }

        .nt-foot { margin-top: auto; padding-top: 0.9em; border-top: 1px solid var(--nt-line); }
        .nt-who { display: flex; align-items: center; gap: 0.55em; }
        .nt-av {
            width: 1.7em; height: 1.7em; border-radius: 999px; flex: none;
            display: grid; place-items: center;
            font-size: 0.82em; font-weight: 600; color: #fff;
            background: var(--nt-pink);
        }
        .nt-track { display: block; height: 0.3em; border-radius: 999px; background: rgba(255,255,255,.08); overflow: hidden; }
        .nt-track i { display: block; height: 100%; border-radius: 999px; background: var(--nt-acc); }
        .nt-ult {
            display: inline-flex; align-items: center; gap: 0.3em;
            padding: 0.25em 0.55em; border-radius: 0.35em;
            background: var(--nt-gold); color: #2a2210;
            font-size: 0.72em; font-weight: 700; letter-spacing: 0.06em;
        }

        /* ── Hoofdgebied ────────────────────────────────────────────── */
        /* max-height + overflow: de tweede rij kaarten loopt bewust onderuit
           beeld, zodat de fade iets te verbergen heeft en de mockup niet
           torenhoog wordt. */
        .nt-main { background: var(--nt-bg); padding: 0.9em; position: relative; min-width: 0; }
        .nt-panel { background: var(--nt-panel); border-radius: 0.85em; padding: 1.1em; }

        .nt-top { display: flex; align-items: center; gap: 0.6em; margin-bottom: 1em; }
        .nt-h { margin: 0; font-size: 1.45em; font-weight: 600; letter-spacing: -0.015em; }
        .nt-count { margin-left: auto; color: var(--nt-soft); font-size: 0.92em; white-space: nowrap; }
        .nt-seg { display: flex; gap: 0.15em; padding: 0.2em; border-radius: 0.55em; background: rgba(255,255,255,.05); }
        .nt-seg span { padding: 0.35em 0.7em; border-radius: 0.4em; font-size: 0.92em; color: var(--nt-mut); white-space: nowrap; }
        .nt-seg span.on { background: rgba(123,123,240,.28); color: #fff; }

        .nt-day { border: 1px solid rgba(123,123,240,.55); border-radius: 0.7em; padding: 0.8em 0.9em; margin-bottom: 1em; }
        .nt-day-h { display: flex; align-items: center; gap: 0.6em; margin-bottom: 0.7em; }
        .nt-day-h strong { font-size: 1em; font-weight: 600; }
        .nt-btn {
            margin-left: auto; display: inline-flex; align-items: center; gap: 0.35em;
            padding: 0.4em 0.7em; border-radius: 0.5em;
            border: 1px solid var(--nt-line); background: rgba(255,255,255,.04);
            color: var(--nt-txt); font-size: 0.9em; white-space: nowrap;
        }
        .nt-row { display: flex; align-items: center; gap: 0.6em; font-size: 0.98em; min-width: 0; }
        .nt-bullet { width: 0.5em; height: 0.5em; border-radius: 999px; background: var(--nt-cyan); flex: none; }
        /* Niet :first-of-type — élk kind van .nt-row is een span, dus dat
           selecteerde het bolletje en niet de titel. min-width:0 is nodig
           omdat een flex-item anders weigert te krimpen en de tekst
           doorloopt in plaats van af te kappen. */
        .nt-row > .nt-title {
            font-weight: 500; min-width: 0;
            overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
        }
        .nt-meta { margin-left: auto; display: inline-flex; align-items: center; gap: 0.3em; color: var(--nt-soft); font-size: 0.9em; white-space: nowrap; }
        .nt-tag { color: var(--nt-cyan); font-size: 0.9em; white-space: nowrap; }

        .nt-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.7em; }
        .nt-card { background: var(--nt-card); border: 1px solid var(--nt-line); border-radius: 0.7em; padding: 0.9em; min-width: 0; }
        .nt-ct {
            display: flex; align-items: center; gap: 0.45em;
            margin: 0 0 0.8em; color: var(--nt-mut);
            font-size: 0.8em; font-weight: 600; letter-spacing: 0.09em;
        }
        .nt-big { margin: 0; display: flex; align-items: baseline; gap: 0.4em; }
        .nt-big b { font-size: 2.4em; font-weight: 600; line-height: 1; color: var(--nt-acc); }
        .nt-big span { color: var(--nt-mut); font-size: 0.95em; }
        .nt-sub { margin: 0.7em 0 0; color: var(--nt-soft); font-size: 0.9em; }
        .nt-kv { margin: 0.7em 0 0; display: flex; gap: 0.5em; color: var(--nt-soft); font-size: 0.9em; }
        .nt-kv b { margin-left: auto; color: var(--nt-txt); font-weight: 600; }

        .nt-chart { display: flex; align-items: center; gap: 0.9em; }
        .nt-chart svg { width: 6em; height: 6em; flex: none; }
        .nt-chart text { fill: var(--nt-txt); }
        /* Los nodig: een fill="…"-attribuut op het element zelf verliest
           het van elke class-selector, dus zonder deze regel kleurt het
           bijschrift onder het getal net zo wit als het getal. */
        .nt-chart text.nt-mini { fill: var(--nt-mut); }
        .nt-legend { list-style: none; margin: 0; padding: 0; flex: 1; min-width: 0; }
        .nt-legend li { display: flex; align-items: center; gap: 0.45em; padding: 0.16em 0; font-size: 0.92em; color: var(--nt-mut); }
        .nt-legend i { width: 0.5em; height: 0.5em; border-radius: 999px; flex: none; }
        .nt-legend b { margin-left: auto; color: var(--nt-txt); font-weight: 600; }

        /* Op een telefoon verbergt Notula zelf ook de zijbalk. */
        @media (max-width: 639px) {
            .nt { font-size: 10px; }
            .nt-app { grid-template-columns: 1fr; }
            .nt-side { display: none; }
            .nt-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
            .nt-chart { flex-direction: column; align-items: flex-start; gap: 0.6em; }
            .nt-chart svg { width: 5em; height: 5em; }

            /* Het woordje onder het getal in de ring zou hier op 3,5 px
               uitkomen: dat rendert als vuil, niet als tekst. Het getal
               en de legenda vertellen het verhaal ook zonder. */
            .nt-mini { display: none; }
        }

        .locked { filter: blur(0.35px); color: var(--a2); }

        /* Honeypot: uit beeld, uit de tabvolgorde, maar wél in het formulier. */
        .hp {
            position: absolute;
            width: 1px;
            height: 1px;
            padding: 0;
            margin: -1px;
            overflow: hidden;
            clip-path: inset(50%);
            white-space: nowrap;
            border: 0;
        }

        /* ── EAGER LABS: geblurde concepten ───────────────────────────── */
        .veil {
            filter: blur(7px);
            opacity: 0.5;
            user-select: none;
        }

        /* ── Ninja-mark ───────────────────────────────────────────────── */
        .mark {
            transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
        }
        a:hover .mark { transform: rotate(90deg); }

        /* ── FAQ ──────────────────────────────────────────────────────── */
        details > summary { list-style: none; cursor: pointer; }
        details > summary::-webkit-details-marker { display: none; }
        details[open] .faq-chev { transform: rotate(45deg); }
        .faq-chev { transition: transform 0.25s ease; }

        /* ── Juridische documenten in een popup ────────────────────────────
           Het dialog-element in plaats van een zelfgebouwde modal: de browser regelt
           dan de focus-val, Escape, de achtergrondlaag en het teruggeven van
           de focus aan de knop waarop geklikt is. Dat zijn precies de vier
           dingen waar zelfbouw op sneuvelt. */
        dialog.doc {
            width: min(46rem, calc(100vw - 2rem));
            max-height: min(82vh, 52rem);
            padding: 0;
            border: 1px solid var(--line-hi);
            border-radius: 1rem;
            background: #0d0e14;
            color: var(--txt);
            box-shadow: 0 40px 90px -24px rgba(0, 0, 0, 0.95);
            overflow: hidden;
        }
        dialog.doc::backdrop {
            background: rgba(0, 0, 0, 0.72);
            backdrop-filter: blur(4px);
            -webkit-backdrop-filter: blur(4px);
        }
        dialog.doc[open] {
            display: flex;
            flex-direction: column;
            animation: popIn 0.22s cubic-bezier(0.16, 1, 0.3, 1) both;
        }

        .doc-head {
            display: flex;
            align-items: flex-start;
            gap: 1rem;
            padding: 1.5rem 1.5rem 1rem;
            border-bottom: 1px solid var(--line);
            flex: none;
        }
        .doc-head h2 {
            margin: 0;
            font-size: 1.375rem;
            font-weight: 600;
            letter-spacing: -0.018em;
        }
        .doc-head p {
            margin: 0.35rem 0 0;
            font-size: 0.8125rem;
            color: var(--dim);
        }
        .doc-close {
            margin-left: auto;
            display: grid;
            place-items: center;
            width: 2.25rem;
            height: 2.25rem;
            flex: none;
            border-radius: 0.5rem;
            border: 1px solid var(--line);
            background: rgba(255, 255, 255, 0.03);
            color: var(--muted);
            cursor: pointer;
            transition: color 0.2s ease, border-color 0.2s ease;
        }
        .doc-close:hover { color: #fff; border-color: var(--line-hi); }

        /* De inhoud scrolt, de kop en de voet blijven staan. */
        .doc-body {
            overflow-y: auto;
            overscroll-behavior: contain;
            padding: 1.25rem 1.5rem 1.75rem;
        }
        .doc-body h3 {
            margin: 1.75rem 0 0.6rem;
            font-size: 0.9375rem;
            font-weight: 600;
            letter-spacing: -0.01em;
        }
        .doc-body h3:first-child { margin-top: 0; }
        .doc-body p, .doc-body li {
            margin: 0 0 0.7rem;
            font-size: 0.875rem;
            line-height: 1.65;
            color: var(--muted);
            max-width: 62ch;
        }
        .doc-body ul { margin: 0 0 0.7rem; padding-left: 1.15rem; }
        .doc-body li { margin-bottom: 0.35rem; }
        .doc-body li::marker { color: var(--a1); }
        .doc-intro { color: var(--txt) !important; }

        .doc-foot {
            flex: none;
            display: flex;
            align-items: center;
            gap: 0.75rem;
            flex-wrap: wrap;
            padding: 0.9rem 1.5rem;
            border-top: 1px solid var(--line);
            font-size: 0.75rem;
            color: var(--dim);
        }

        /* Onderdelen die nog ingevuld moeten worden vallen op. Zichtbaar
           gemarkeerd met opzet: zo kan dit niet per ongeluk live gaan
           terwijl het er af uitziet. */
        .doc-todo {
            color: #f5a524;
            border-bottom: 1px dotted rgba(245, 165, 36, 0.5);
        }

        @media (max-width: 480px) {
            /* dvh en niet vh: vh rekent met de viewport zonder adresbalk, dus
               met adresbalk in beeld werd de popup hoger dan het scherm en viel
               hij boven én onder net buiten beeld. De vh-regel blijft staan als
               terugval voor browsers die dvh niet kennen. */
            dialog.doc { max-height: 88vh; max-height: 88dvh; border-radius: 0.85rem; }
            .doc-head, .doc-body, .doc-foot { padding-left: 1.1rem; padding-right: 1.1rem; }
        }
        /* ── Commandopalet ───────────────────────────────────────────── */
        #palette[hidden] { display: none; }
        .palette-item[aria-selected='true'] {
            background: rgba(255, 255, 255, 0.06);
            border-color: var(--line-hi);
        }
        .palette-item[aria-selected='true'] .palette-hint { opacity: 1; }

        .fade-in { animation: fadeIn 0.16s ease-out both; }
        .pop-in  { animation: popIn 0.2s cubic-bezier(0.16, 1, 0.3, 1) both; }
        @keyframes fadeIn { from { opacity: 0; } }
        @keyframes popIn  { from { opacity: 0; transform: translateY(-8px) scale(0.985); } }

        /* Alles wat beweegt, staat uit voor wie dat instelt. */
        @media (prefers-reduced-motion: reduce) {
            html { scroll-behavior: auto; }
            *, *::before, *::after {
                animation-duration: 0.001ms !important;
                animation-iteration-count: 1 !important;
                transition-duration: 0.001ms !important;
            }
            .js .reveal { opacity: 1; transform: none; }
        }

        /* Print: donker papier is zonde van de toner. */
        @media print {
            .bg-stage, .grain, #palette, header { display: none !important; }
            html, body { background: #fff !important; color: #000 !important; }
            /* Zonder deze regel is elke kop én het woordmerk blanco op
               papier: de letters zijn transparant en de gradiënt eronder
               is een achtergrond, en die drukt een browser standaard niet af. */
            .grad-text, .wordmark {
                background: none !important;
                -webkit-text-fill-color: #000 !important;
                color: #000 !important;
            }
            .payoff, .payoff b { color: #333 !important; }
            .mock { border-color: #ccc !important; }
        }

/* ── Maten van het merk per plek ──────────────────────────────────────
   Alleen een font-size; de verhoudingen komen uit .merk hierboven. */
.merk-kop  { font-size: 1.375rem; }
@media (min-width: 640px) { .merk-kop { font-size: 1.625rem; } }
.merk-voet { font-size: 1.75rem; }

/* Onder de 400 px is er geen ruimte voor de payoff naast de knoppen in de
   balk; de naam en de zeshoek blijven staan. */
@media (max-width: 399px) {
    .merk-kop .payoff { display: none; }
    /* Zonder de payoff is er geen basislijn om op te mikken en is het tekstblok
       nog maar 1 em hoog. De zeshoek wordt dan even hoog als dat blok:
       1 x 24/22 = 1,0909 em, netjes in het midden. */
    .merk-kop .merk-teken { height: 1.0909em; width: 1.0909em; top: 0; }
}

/* ── Smalle schermen ───────────────────────────────────────────────────────
   Deze regels staan hier en niet als Tailwind-klasse in de opmaak, omdat
   public/css/tailwind.css een bevroren bouwresultaat is: een utility-klasse
   die daar niet in staat doet niets. Handgeschreven CSS werkt overal, ook op
   de poort en in het beheer, die Tailwind bewust niet laden. */

/* De kopbalk van de landingspagina heeft 411 px nodig: merk 163, zoekknop 40,
   "Try Notula" 96, inlogknop 40, plus de tussenruimtes en 40 px padding. Op een
   telefoon van 375 px viel de inlogknop daardoor half buiten beeld — niet
   zichtbaar, niet aan te tikken, en zonder horizontale schuifbalk om het te
   verraden, want de body klemt de overloop af.

   Onder 430 px verdwijnt daarom de knop "Try Notula" uit de balk. Dat is de
   minste schade: diezelfde knop staat groot in de hero, twee vingerbreedtes
   lager, terwijl zoeken en inloggen nergens anders staan. Zonder de knop heeft
   de balk nog 307 px nodig en past hij tot 320 px. */
@media (max-width: 429px) {
    .kop-cta { display: none; }
}

/* iOS zoomt in zodra je een invoerveld aantikt met een font-size onder 16 px,
   en zoomt daarna niet vanzelf terug: je zit met een pagina die 30% te groot
   staat en moet zelf terugknijpen. De velden stonden op 15 px en 13 px.

   De :not()-staarten staan er voor de specificiteit: een Tailwind-klasse als
   text-sm weegt (0,1,0) en zou een kale `input` overrulen. */
@media (max-width: 640px) {
    input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]),
    textarea:not([hidden]),
    select:not([hidden]) {
        font-size: 1rem;
    }
}

/* Een vinger is geen muisaanwijzer. Op een aanraakscherm krijgen knoppen die
   te klein zijn uitgetekend alsnog 44 px hoogte mee — de maat die zowel Apple
   als de WCAG aanhouden. Alleen op pointer:coarse, zodat de knoppen op een
   desktop hun compacte vorm houden. */
@media (pointer: coarse) {
    .btn,
    .kijk-knop,
    button:not([class*="h-10"]):not([class*="h-9"]),
    a.btn {
        min-height: 2.75rem;
    }
    .kijk-knop { padding-block: 0.625rem; }

    /* De icoonknoppen in de kopbalk staan op h-10 (40 px) en vallen daarom
       buiten de regel hierboven. Op een aanraakscherm is dat net te klein.
       Handgeschreven en niet met h-11/w-11, want die klassen staan niet in het
       bevroren tailwind.css. */
    header[data-header] .h-10 { min-height: 2.75rem; min-width: 2.75rem; }

    /* De navigatie: vier doelen van 36 px met 4 px ertussen. */
    header[data-header] nav a {
        display: inline-flex;
        align-items: center;
        min-height: 2.75rem;
    }

    /* Het kruisje van de juridische popup was 36 breed en 44 hoog geworden —
       te smal om te raken, en niet langer vierkant. */
    .doc-close { min-width: 2.75rem; }

    /* De links in de voettekst bleven 32 px terwijl de knoppen ernaast in
       dezelfde kolom al 44 px waren. */
    footer nav a,
    footer nav button { min-height: 2.75rem; display: inline-flex; align-items: center; }

    /* "Open Notula" op de LABS-kaart: de enige doorklik naar het live product. */
    #labs article a { min-height: 2.75rem; }
}

/* De navigatie klapte aan op 768 px maar past pas vanaf 803: merk 200 + nav 264
   + acties 243 + tussenruimte 32 + padding 64. Het tekort werd opgevangen door
   te krimpen, dus "Why us" brak binnen zijn eigen link naar twee regels en de
   hint "Ctrl K" brak af achter "Ctrl". Nu pas vanaf 1024 px; tot dan is het
   commandopalet de navigatie, precies zoals op een telefoon.

   Handgeschreven, want lg:flex staat niet in het bevroren tailwind.css. De
   selector weegt (0,1,2) en wint daarmee van .md:flex (0,1,0). */
@media (max-width: 1023px) {
    header[data-header] nav[aria-label="Main navigation"] { display: none; }
}

/* Het commandopalet wordt met vh gepositioneerd en begrensd (pt-[12vh] op de
   doos, max-h-[52vh] op de lijst). Op een telefoon is 1vh de hoogte MET de
   adresbalk weggeschoven, dus met de adresbalk in beeld is er minder ruimte dan
   het palet denkt: op een scherm van 568 px begint de lijst 68 px van boven en
   mag hij 295 px worden, terwijl er maar 480 px zichtbaar is. Met het
   toetsenbord open blijft er nauwelijks een resultaat over.

   Handgeschreven, want pt-[8dvh] en max-h-[52dvh] staan niet in het bevroren
   tailwind.css. De Tailwind-waarden blijven als terugval eronder staan voor
   browsers zonder dvh. */
@supports (height: 100dvh) {
    @media (max-width: 639px) {
        #palette { padding-top: 8dvh; }
        #palette-list { max-height: 52dvh; }
    }
}
