/* ═══════════════════════════════════════════════════════════════════════════
   Plannika, de opmaak.

   Eén bestand, geen framework, geen bouwstap. Wat hier staat is het volledige
   ontwerp: kleuren, letters, ritme, beweging, en de twee vormen waarin de app
   verschijnt (een hand en een scherm).

   Drie regels die door alles heen lopen:

   1. LOGISCHE RICHTING. Nergens left of right, altijd inline-start en
      inline-end. Daardoor klapt de hele app om bij dir="rtl" zonder één extra
      regel. Het Arabisch is geen apart thema, het is dezelfde opmaak gespiegeld.

   2. WARME AARDE, GEEN DASHBOARD. De grond is geen zuiver wit maar een warm
      zandwit, en het merk is dennengroen met terracotta ernaast. Een student
      kijkt hier maanden naar, vaak 's avonds en vaak met tegenzin. Koud blauw
      op fel wit maakt dat erger.

   3. GEEN HARDE HOEK. Alles wat een rand heeft is afgerond, en de maten staan
      in de radius-tokens. Een hoek van 0 of 2 px hoort hier niet.

   4. NIETS BEWEEGT ZONDER REDEN. Beweging vertelt waar iets vandaan komt.
      Wie prefers-reduced-motion aan heeft of de knop in Ik omzet, krijgt
      dezelfde app zonder beweging, niet een uitgeklede versie.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Letters, zelf gehost ────────────────────────────────────
   Google Fonts wordt niet aangeroepen: dit is een app die in de bib zonder net
   moet openen, en een externe letter is een extra domein dat kan wegvallen.
   De browser haalt alleen het stuk op dat bij de taal van de student past.

   Montserrat is de huisletter en sinds 09-09-2026 de ENIGE: een familie voor
   de lopende tekst, de koppen, de klok en de cijfers. Daarvoor stonden hier
   Inter voor de tekst en Fraunces voor de koppen; die twee zijn weg, ook uit
   lettertype/. Een variabele snede draagt wght 100 tot 900, dus de 420 van de
   tekst en de 570 van de koppen komen uit hetzelfde bestand en er is geen
   tweede download voor vet.

   Vijf sneden, dezelfde die Google zelf uitknipt: latijn, latijn uitgebreid,
   cyrillisch, cyrillisch uitgebreid en vietnamees. Grieks staat er niet bij en
   dat kost niets: Montserrat snijdt geen Grieks, en geen van de elf talen
   (ar, de, en, es, fr, it, pl, pt, ro, tr, uk) plus het Nederlands vraagt het.
   Arabisch valt terug op de systeemletter, net als vroeger.

   Wat er met de letters meeverdween: font-feature-settings met cv05, cv09 en
   ss03. Dat waren namen uit Inter, Montserrat kent ze niet, en een browser
   negeert ze stil. En de assen opsz, SOFT en WONK van Fraunces: Montserrat
   heeft alleen wght. Ze stonden in twaalf regels en zeiden vanaf nu niets
   meer. */

@font-face{font-family:"Montserrat";font-style:normal;font-weight:100 900;font-display:swap;src:url(lettertype/montserrat-latin.woff2) format("woff2");unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:"Montserrat";font-style:normal;font-weight:100 900;font-display:swap;src:url(lettertype/montserrat-latin-ext.woff2) format("woff2");unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF}
@font-face{font-family:"Montserrat";font-style:normal;font-weight:100 900;font-display:swap;src:url(lettertype/montserrat-cyrillic.woff2) format("woff2");unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116}
@font-face{font-family:"Montserrat";font-style:normal;font-weight:100 900;font-display:swap;src:url(lettertype/montserrat-cyrillic-ext.woff2) format("woff2");unicode-range:U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F}
@font-face{font-family:"Montserrat";font-style:normal;font-weight:100 900;font-display:swap;src:url(lettertype/montserrat-vietnamese.woff2) format("woff2");unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB}

/* ── Tokens: licht ──────────────────────────────────────────
   Elke kleur staat hier één keer. Wie een kleur ergens anders hard intypt,
   breekt het donkere thema, en dat is niet zichtbaar tot iemand 's avonds
   opent. Daarom: nooit hex buiten dit blok.

   Het palet komt uit het kleurbeeld van Alina, op de pixel gemeten: dennengroen
   #1F2D16 als merk, terracotta #B5521B als tweede stem met #8D2A01 en #BE6731
   als diepere en lichtere trap, en olijf #76704C met salie #565E46 als neutrale
   steun. Elk paar hieronder is nagerekend met de WCAG-formule, relatieve
   luminantie en (L1+0,05)/(L2+0,05), en niet geschat: gewone tekst en
   bijschriften halen minstens 4,5, iconen en grote koppen minstens 3,0. */

:root{
  color-scheme: light;

  /* Warm zandwit in plaats van papierwit: de grond hoort bij aardetinten. */
  --grond:#FAF5EB;          /* de pagina */
  --grond-diep:#F0E9DB;     /* achter de kaarten, bv de zijbalk */
  --vlak:#FFFDF8;           /* een kaart */
  --vlak-2:#F5EFE2;         /* zachte vulling in een kaart */
  --vlak-3:#E9E1D0;
  --rand:#E6DECC;
  --rand-2:#D2C8AF;
  /* De rand van iets wat je bedient: een invoerveld, een keuzeknop, het spoor
     van een schakelaar. --rand haalt daar 1,3 en dat is te weinig om het veld
     te zien (WCAG 1.4.11 vraagt 3,0). Deze haalt 4,06 op een kaart, 3,8 op de
     grond en 3,18 op de derde vulling. */
  --rand-veld:#837D64;

  --inkt:#1A1D12;           /* koppen en cijfers, zwart met een groene zweem */
  /* Gewone tekst is salie, exact de kleur uit het beeld: op een kaart 6,7, op
     de zachte vulling 5,9, op vlak-3 nog 5,2. */
  --inkt-2:#565E46;
  /* Bijschrift is olijf, twee tinten donkerder dan de #76704C uit het beeld.
     Nagerekend en niet op het oog gekozen, en op 09-09-2026 nog een tint bij:
     hier stond #6F6A47, dat op een kaart 5,4 haalde en op de zachte vulling
     4,8, maar op --vlak-3 slechts 4,22. Dat is de derde vulling, en daar staat
     onder andere de uurkolom van het weekrooster. Deze waarde haalt 4,69 op
     vlak-3, 5,32 op vlak-2, 6,0 op een kaart en 5,61 op de grond, dus overal
     boven de 4,5 die WCAG AA voor kleine tekst vraagt. Een lichter grijs oogt
     rustiger en is onleesbaar in de zon. */
  --inkt-3:#68633F;

  /* Het merk is dennengroen. #1F2D16 uit het beeld is het anker en draagt de
     diepe trap; de werktint erboven is een tikje lichter, anders is het verloop
     in de vlek en in de hero één zwarte vlek. Merktekst haalt 10,6 op een kaart
     en 9,1 op het merkwasje, en --merk-op haalt 10,6 op --merk. */
  --merk:#2C4420;
  --merk-diep:#1F2D16;
  --merk-op:#FFFDF8;
  --merk-was:#E8EEDF;
  --merk-rand:#C5D2B4;
  /* De zwevende melding staat op --inkt, ook in het lichte thema. Dennengroen
     daarop haalt 1,1 en is dus onleesbaar; deze lichte mos haalt 9,3. */
  --merk-op-inkt:#A8CA88;

  /* Tweede stem: terracotta, met de diepe en de lichte trap uit het beeld. */
  --gloed:#B5521B;          /* nadruk, "nu" */
  --gloed-diep:#8D2A01;     /* terracotta als tekst op een wasje: 7,3 */
  --gloed-licht:#BE6731;    /* een lijn of een rand, nooit kleine tekst */
  --gloed-was:#FBEADF;
  --gloed-op:#FFFDF8;       /* tekst op terracotta: 4,9 */

  --goed:#2C4420;
  --goed-was:#E8EEDF;
  --krap:#6E5D18;           /* olijf die naar oker trekt: op het wasje 5,6 */
  --krap-was:#F6EFD7;
  --fout:#9A2F1A;           /* gebrand roest: op het wasje 6,2 */
  --fout-was:#FAE5DD;

  --sluier:#1B2113;         /* achter een blad of een dialoog */

  /* Diepte. Drie lagen, want één schaduw ziet er altijd goedkoop uit. De
     ondertoon is groenbruin en geen grijs, anders valt ze uit het palet. */
  --op-1:0 1px 2px rgba(31,45,22,.06);
  --op-2:0 1px 2px rgba(31,45,22,.06), 0 4px 14px -4px rgba(31,45,22,.12);
  --op-3:0 2px 4px rgba(31,45,22,.07), 0 16px 40px -12px rgba(31,45,22,.20);
  --op-in:inset 0 1px 0 rgba(255,253,248,.7);

  /* 92 en in donker 88 procent dekking: de labels van de tabbalk staan in
     --inkt-3, en met 82 en 78 zakten ze boven een donkere of lichte plek op
     4,1:1 (axe op 768, StudyTime en de timer). Zo halen ze 4,5:1 boven zwart
     in licht (4,68) en boven wit in donker (4,93), wat er ook achter schuift. */
  --glas:color-mix(in srgb, var(--grond) 92%, transparent);

  /* Beeld. Alina stuurde op 09-09-2026 zestien foto's door met de vraag om de
     achtergronden van de app met dat thema te vullen, "zowel kwa kleur als
     visueel", en er meteen bij: niet te somber. Haar bord is donker, gemeten
     helderheid 0,26 over de zestien beelden. Daarom is het beeld hier de SFEER
     en niet de grond: de foto ligt achter de tekst met een lage dekking, de
     grond blijft zandwit en elke kaart blijft vlak. In het nachtthema mag ze
     wel spreken, daar staat alles bijna dubbel zo hoog.

     Alles hangt aan --beeld. Op 0 verdwijnt elke foto en elk patroon zonder dat
     er één regel geschrapt moet worden, en dat is precies wat de knop in Ik en
     prefers-reduced-data doen. */
  --beeld:1;
  --beeld-band:.46;        /* de sfeerband boven aan een scherm */
  --beeld-kaart:.34;       /* een foto achter een kaart */
  --beeld-varen:.05;       /* het getekende varenpatroon in de grond */
  /* Hoe ver de band naar beneden loopt. Deze maat is geen smaak maar een
     rekensom: de kop is 57 px, de inhoud begint 156 px daaronder, dus op 213 px
     moet er van de foto niets meer over zijn. Op de Why Shelf begint de inhoud
     met een losse zin en niet met een kaart, en die zin stond bij 330 px nog
     leesbaar op een tak. */
  --beeld-hoog:calc(224px + env(safe-area-inset-top,0px));

  /* Maten. Alles zacht: hier stond 10/14/20/26 en dat gaat fors omhoog. --r-m
     werd al gebruikt bij de richtingkiezer maar stond nergens, en een
     border-radius met een onbekende var valt terug op een scherpe hoek. */
  --r-s:14px; --r-m:18px; --r:22px; --r-l:28px; --r-xl:36px;
  --schaal:1;                /* tekstgrootte, instelbaar in Ik */
  --tab:66px;                /* hoogte van de tabbalk op een gsm */
  --zij:248px;               /* breedte van de zijbalk op een scherm */
  --breed:1080px;            /* maximale leesbreedte */

  --snel:140ms; --traag:280ms;
  --veer:cubic-bezier(.32,.72,0,1);
}

/* ── Tokens: donker ─────────────────────────────────────────
   Niet het lichte thema omgekeerd, maar een nachtbos. De grond is warm
   zwartgroen, de kaarten liggen erboven in plaats van eronder, en de merkkleur
   springt naar een licht mosgroen omdat dennengroen op zwart verdwijnt. Ook
   hier is elk paar nagerekend: de zwakste schakel is het bijschrift op de
   zachte vulling met 4,97, en de rest zit hoger. */

@media (prefers-color-scheme: dark){
  :root:not([data-thema="licht"]){ color-scheme: dark;
    --grond:#0D120B; --grond-diep:#0A0E09; --vlak:#161C14; --vlak-2:#1E261B;
    --vlak-3:#273021; --rand:#273021; --rand-2:#3B4634; --rand-veld:#737D67;
    --inkt:#F0EEE2; --inkt-2:#AFB09A; --inkt-3:#9C9C82;
    --merk:#A3C583; --merk-diep:#BBD79E; --merk-op:#121B0C;
    --merk-was:#1C2814; --merk-rand:#32432A; --merk-op-inkt:#1F2D16;
    --gloed:#E08A52; --gloed-diep:#F0A475; --gloed-licht:#E8955F;
    --gloed-was:#2A1A0F; --gloed-op:#24150B;
    --goed:#A3C583; --goed-was:#1C2814;
    --krap:#D7B860; --krap-was:#2A2413;
    --fout:#ED7A5E; --fout-was:#2B1612;
    --op-1:0 1px 2px rgba(3,6,2,.5);
    --op-2:0 1px 2px rgba(3,6,2,.5), 0 6px 18px -6px rgba(3,6,2,.62);
    --op-3:0 2px 6px rgba(3,6,2,.5), 0 22px 48px -14px rgba(3,6,2,.78);
    --op-in:inset 0 1px 0 rgba(240,238,226,.05);
    --glas:color-mix(in srgb, var(--grond) 88%, transparent);
    --beeld-band:.66; --beeld-kaart:.34; --beeld-varen:.08;
  }
}
:root[data-thema="donker"]{ color-scheme: dark;
  --grond:#0D120B; --grond-diep:#0A0E09; --vlak:#161C14; --vlak-2:#1E261B;
  --vlak-3:#273021; --rand:#273021; --rand-2:#3B4634; --rand-veld:#737D67;
  --inkt:#F0EEE2; --inkt-2:#AFB09A; --inkt-3:#9C9C82;
  --merk:#A3C583; --merk-diep:#BBD79E; --merk-op:#121B0C;
  --merk-was:#1C2814; --merk-rand:#32432A; --merk-op-inkt:#1F2D16;
  --gloed:#E08A52; --gloed-diep:#F0A475; --gloed-licht:#E8955F;
  --gloed-was:#2A1A0F; --gloed-op:#24150B;
  --goed:#A3C583; --goed-was:#1C2814;
  --krap:#D7B860; --krap-was:#2A2413;
  --fout:#ED7A5E; --fout-was:#2B1612;
  --op-1:0 1px 2px rgba(3,6,2,.5);
  --op-2:0 1px 2px rgba(3,6,2,.5), 0 6px 18px -6px rgba(3,6,2,.62);
  --op-3:0 2px 6px rgba(3,6,2,.5), 0 22px 48px -14px rgba(3,6,2,.78);
  --op-in:inset 0 1px 0 rgba(240,238,226,.05);
  --glas:color-mix(in srgb, var(--grond) 88%, transparent);
  /* .34 en niet .46: dit blok is "Ik zelf donker" en moet gelijk lopen met het
     auto-donker hierboven. Er stond .46, de waarde van de lichte BAND, en dat
     was een overschrijffout: wie donker koos kreeg de foto achter een Why-kaart
     een derde sterker dan bedoeld, precies de dekking die het bijschrift
     "Geschreven op ..." op 1,79 zette (LEESMIJ: "een tand zachter, 0,34 in
     plaats van 0,46"). Donker is de enige weg naar donker, want de standaard is
     licht, dus elke donkere gebruiker zat op de foute waarde. */
  --beeld-band:.66; --beeld-kaart:.34; --beeld-varen:.08;
}

/* ── Grondslag ──────────────────────────────────────────────── */

*,*::before,*::after{box-sizing:border-box}
html,body{height:100%}
html{-webkit-text-size-adjust:100%}
/* Een knop die de focus krijgt, mag niet onder de kop of de tabbalk liggen
   (WCAG 2.4.11). Gemeten op 390 px: Beginnen op StudyTime lag voor 100 procent
   onder de tabbalk, de dagknoppen in de onboarding voor 99 procent onder de
   voet met Verder. De browser scrolt een gefocuste knop in beeld met deze
   marges erbij. */
html{scroll-padding-block:calc(70px + env(safe-area-inset-top,0px)) calc(var(--tab) + 34px + env(safe-area-inset-bottom,0px))}
html:has(main > .ob){scroll-padding-block:calc(70px + env(safe-area-inset-top,0px)) calc(96px + env(safe-area-inset-bottom,0px))}
.doos{scroll-padding-block:16px}
body{
  margin:0;
  background:var(--grond);
  color:var(--inkt-2);
  font-family:Montserrat,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
  font-size:calc(15px * var(--schaal));
  /* 420 in plaats van 400, zodat het gat met de vette 630 kleiner is en de
     bladzijde minder hard oogt. */
  font-weight:420;
  line-height:1.65;
  /* Montserrat draagt geen cv-varianten; de open a en de echte 1 die hier
     stonden waren namen uit Inter en deden na de wissel niets meer. */
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  overscroll-behavior-y:none;
  text-rendering:optimizeLegibility;
}
h1,h2,h3,h4{margin:0;color:var(--inkt);font-weight:570;line-height:1.26;letter-spacing:-.002em}
h1{font-family:Montserrat,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;font-size:calc(23px * var(--schaal));letter-spacing:.004em}
h2{font-size:calc(16.5px * var(--schaal))}
h3{font-size:calc(14.5px * var(--schaal))}
p{margin:0}
button,input,select,textarea{font:inherit;color:inherit;font-family:inherit}
button{cursor:pointer;background:none;border:0;padding:0;color:inherit;-webkit-tap-highlight-color:transparent}
a{color:var(--merk);text-underline-offset:2px}
ul{margin:0;padding:0;list-style:none}
svg{flex:0 0 auto}
/* Een element met hidden hoort weg te zijn, ook als een klasse er verderop een
   display aan geeft. Zonder deze regel bleven de kop en de zijbalk tijdens de
   onboarding gewoon staan: .kop{display:flex} en .zijbalk{display:flex} wegen
   even zwaar als het attribuut en komen later, dus zij wonnen. Een student zag
   dan een menu naar schermen die er nog niet zijn. */
[hidden]{display:none !important}
::selection{background:color-mix(in srgb,var(--merk) 22%,transparent)}

:focus-visible{outline:2px solid var(--merk);outline-offset:2px;border-radius:11px}
:focus:not(:focus-visible){outline:none}
/* Het scherm na een tabwissel, de kop van een nieuwe stap en een blad krijgen
   de focus enkel zodat een schermlezer daar begint. Het zijn geen knoppen, maar
   na een toets tekende de browser er toch een ring rond: om het hele scherm, na
   elke tabwissel. Tab gaat vanaf daar naar de eerste knop, en die krijgt hem wel. */
:is(main,h1,h2,.doos)[tabindex="-1"]:focus{outline:none}

/* ── Beeld ──────────────────────────────────────────────────
   Twee lagen, allebei versiering. Het zijn pseudo-elementen, dus een
   schermlezer komt ze nooit tegen en ze vangen geen aanwijzer.

   1. HET VARENPATROON, zelf getekend, staat in beeld/varen.svg. Het ligt daar
      als MASKER over een vlak in de merkkleur, niet als gekleurde afbeelding.
      Zo is er één bestand voor allebei de thema's en klopt de kleur vanzelf:
      in het nachtthema is --merk mosgroen in plaats van dennengroen. Een
      gekleurde svg zou twee bestanden vragen en bij elke paletwijziging
      opnieuw getekend moeten worden.

   2. DE SFEERBAND, een foto boven aan elk hoofdscherm, met een masker dat naar
      onder uitdooft. De kop ligt er met matglas overheen, en dat is geen
      toeval: .kop draagt al backdrop-filter, dus het beeld verschijnt daar
      vanzelf vertroebeld en de titel blijft leesbaar.

   De volgorde van schilderen is het hele punt van laag 1. body::after staat op
   z-index -1, en body maakt geen eigen stapelcontext, dus het patroon komt
   achter de inhoud en vóór de achtergrondkleur van body. Met 0 zou het over de
   tekst liggen. Met een gewone div zou het meescrollen; fixed houdt het stil,
   zoals een bodem hoort te liggen. */

body::after{
  content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background-color:var(--merk);
  -webkit-mask-image:url(beeld/varen.svg);mask-image:url(beeld/varen.svg);
  -webkit-mask-size:360px 360px;mask-size:360px 360px;
  -webkit-mask-repeat:repeat;mask-repeat:repeat;
  opacity:calc(var(--beeld-varen) * var(--beeld));
}

/* overflow-x:clip en niet hidden: clip maakt geen schuifvlak, dus de kop blijft
   sticky. Met de tekstafstand van WCAG 1.4.12 (woordafstand 0,16 em) telde
   Chromium de hangende spaties van een gewone alinea op Vandaag als overloop,
   en dan schoof de hele pagina op 390 px 3 px opzij. Er staat niets buiten de
   kolom wat iemand moet zien. */
.kolom{position:relative;overflow-x:clip}
.kolom::before{
  content:"";position:absolute;inset-block-start:0;inset-inline:0;
  height:var(--beeld-hoog);
  background-image:var(--beeld-hier,none);
  background-position:center 30%;background-size:cover;background-repeat:no-repeat;
  opacity:calc(var(--beeld-band) * var(--beeld));
  -webkit-mask-image:linear-gradient(to bottom,rgba(0,0,0,1) 0,rgba(0,0,0,.9) 40%,rgba(0,0,0,.22) 74%,transparent 100%);
  mask-image:linear-gradient(to bottom,rgba(0,0,0,1) 0,rgba(0,0,0,.9) 40%,rgba(0,0,0,.22) 74%,transparent 100%);
  pointer-events:none;
}

/* Welke foto bij welk scherm hoort. app/main.ts zet data-plek op body, en dat
   is het enige wat de code hiervoor moet doen. */
body[data-plek="vandaag"]{--beeld-hier:url(beeld/dag.webp)}
body[data-plek="week"]{--beeld-hier:url(beeld/week.webp)}
body[data-plek="vakken"]{--beeld-hier:url(beeld/vakken.webp)}
body[data-plek="blok"]{--beeld-hier:url(beeld/blok.webp)}
body[data-plek="ik"]{--beeld-hier:url(beeld/ik.webp)}
/* De inhoud begint ONDER de fotostrook, niet erop. Dat is geen smaakkwestie:
   dit project rekent elk kleurenpaar na op WCAG, en donkergroene tekst op een
   foto met lichte en donkere plekken haalt geen enkele norm. Zo staat de foto
   in de strook tussen de kop en de eerste kaart, en staat elke letter weer op
   een effen grond. Op een hand is de strook lager, daar is elke pixel duurder. */
body[data-plek] main{
  padding-top:calc(156px + env(safe-area-inset-top,0px));
  position:relative;
}

body[data-plek="why"]{--beeld-hier:url(beeld/why.webp)}
body[data-plek="gids"]{--beeld-hier:url(beeld/gids.webp)}

/* Op een hand haalt de smalle snede 30 kB per beeld weg. Dat is geen detail:
   dit is een app die in de bib op vier streepjes moet openen. */
@media (max-width:760px){
  body[data-plek="vandaag"]{--beeld-hier:url(beeld/dag-s.webp)}
  body[data-plek="week"]{--beeld-hier:url(beeld/week-s.webp)}
  body[data-plek="vakken"]{--beeld-hier:url(beeld/vakken-s.webp)}
  body[data-plek="blok"]{--beeld-hier:url(beeld/blok-s.webp)}
  body[data-plek="ik"]{--beeld-hier:url(beeld/ik-s.webp)}
  body[data-plek="why"]{--beeld-hier:url(beeld/why-s.webp)}
  body[data-plek="gids"]{--beeld-hier:url(beeld/gids-s.webp)}
  :root{--beeld-hoog:calc(168px + env(safe-area-inset-top,0px))}
  body[data-plek] main{padding-top:calc(104px + env(safe-area-inset-top,0px))}
}

/* DE WHY SHELF. Hier hoort het beeld het sterkst thuis: dit zijn de zinnen
   die een student zelf schreef om door te gaan, en die verdienen meer dan een
   wit vak. Elke kaart krijgt een van de zes foto's, gekozen met nth-child
   zodat de keuze stabiel blijft zonder dat er iets in de opslag bij moet. De
   foto ligt achter een vlak in --vlak, dus de tekst staat nooit op een foto
   maar op een kaart waar een foto doorheen schemert. */
.whykaart{position:relative;overflow:hidden;isolation:isolate}
.whykaart::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:var(--beeld-why,none);
  background-size:cover;background-position:center;
  opacity:calc(var(--beeld-kaart) * var(--beeld));
  /* Hier staat wel een fysieke richting, en dat is geen slordigheid: een
     linear-gradient kent geen inline-start of inline-end, alleen to right of
     een hoek. Met to inline-end wordt de hele mask-image ongeldig verklaard en
     valt het masker stil weg, en dan ligt de foto over de hele kaart. Dus:
     de gewone regel voor links naar rechts, en dezelfde regel gespiegeld voor
     het Arabisch. */
  /* De foto staat vol aan de kant WEG van de tekst, en dooft uit naar de kant
     waar de zin en de datum staan. Andersom was het eerst, en dan haalde de
     regel "Geschreven op ..." in het nachtthema 1,79 tegenover de vereiste 4,5.
     De kaarttekst zelf zat wel goed op 4,97, maar het bijschrift is lichter. */
  -webkit-mask-image:linear-gradient(to right,transparent 0,rgba(0,0,0,.5) 44%,rgba(0,0,0,1) 96%);
  mask-image:linear-gradient(to right,transparent 0,rgba(0,0,0,.5) 44%,rgba(0,0,0,1) 96%);
}
[dir="rtl"] .whykaart::before{
  -webkit-mask-image:linear-gradient(to left,transparent 0,rgba(0,0,0,.5) 44%,rgba(0,0,0,1) 96%);
  mask-image:linear-gradient(to left,transparent 0,rgba(0,0,0,.5) 44%,rgba(0,0,0,1) 96%);
}
.whykaart:nth-of-type(6n+1){--beeld-why:url(beeld/why-1.webp)}
.whykaart:nth-of-type(6n+2){--beeld-why:url(beeld/why-2.webp)}
.whykaart:nth-of-type(6n+3){--beeld-why:url(beeld/why-3.webp)}
.whykaart:nth-of-type(6n+4){--beeld-why:url(beeld/why-4.webp)}
.whykaart:nth-of-type(6n+5){--beeld-why:url(beeld/why-5.webp)}
.whykaart:nth-of-type(6n){--beeld-why:url(beeld/why-6.webp)}

/* DE TIMER KRIJGT GEEN FOTO, en dat is een gemeten keuze en geen vergetelheid.
   Er lag hier een dag een foto achter het canvas van app/bos.ts, eerst mist bij
   daglicht en varens op zwart in het donker. Ze was op het scherm niet te zien,
   ook niet nadat de lucht van het canvas doorschijnend werd gemaakt: een bijna
   zwarte bosfoto op een bijna zwarte grond geeft nu eenmaal niets, en bij
   daglicht viel ze weg tegen het zandwit. Twee bossen over elkaar is bovendien
   een bos te veel. Het getekende bos IS hier het beeld, precies zoals Alina het
   in haar eerste mail beschreef, en dat groeit mee met de sessie. De foto's
   mist.webp en nacht.webp zijn daarom weg, samen 220 kB die niemand zag. */

/* Wie zijn data spaart, krijgt het patroon en geen enkele foto. Het patroon is
   5 kB en staat er al, dus dat kost niets. Let op: geen enkele uitgebrachte
   browser ondersteunt prefers-reduced-data vandaag, dus dit is een belofte voor
   later. Wie nu data wil sparen, zet beeld op zacht in Ik. */
@media (prefers-reduced-data: reduce){
  .kolom::before,.whykaart::before{background-image:none}
  .hero{background-image:linear-gradient(155deg,var(--merk) 0%,var(--merk-diep) 100%)}
}

/* De knop in Ik. Zacht laat het patroon staan en haalt de foto's weg, uit
   haalt alles weg. */
body[data-beeld="zacht"]{--beeld-band:0;--beeld-kaart:0}
body[data-beeld="uit"]{--beeld:0}

/* Tekst die alleen een schermlezer hoort. */
.enkelvoorlezer{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0;
}
/* Een leesteken voor de schermlezer dat aan zijn woord vast moet: inline en nul
   breed, want rond een absoluut vakje zet Chrome een spatie (leesteken() in
   app/ui.ts). */
.enkelteken{font-size:0;line-height:0}

/* Wat enkel met toetsen klopt (sneltoetsen, Ctrl of Cmd plus Enter), op een
   toestel zonder toetsenbord weg, ook voor een schermlezer. app/ui.ts zet de
   klasse toetsenbord op <html> bij een muis of touchpad, of bij de eerste
   echte toets (punt 1m). Wat enkel voor wie tikt bedoeld is (zondertoets),
   verdwijnt dan. */
html:not(.toetsenbord) .enkeltoets,html.toetsenbord .zondertoets{display:none!important}

/* De link "Naar de inhoud": onzichtbaar tot hij de focus krijgt, dan bovenaan
   in merkkleur, boven alles. --merk-op op --merk haalt 10,6. */
.springnaar{
  position:fixed;z-index:1000;inset-inline-start:12px;top:calc(8px + env(safe-area-inset-top));
  padding:10px 16px;border-radius:12px;background:var(--merk);color:var(--merk-op);
  font-weight:600;text-decoration:none;transform:translateY(-200%);
  /* Nooit breder dan het venster, ook niet met grote tekst of op 320 px. */
  max-inline-size:calc(100vw - 24px);
}
.springnaar:focus{transform:none}

/* ═══════════ Raamwerk ═══════════════════════════════════════
   Twee vormen. Onder 900 px: één kolom met een zwevende tabbalk onderaan.
   Vanaf 900 px: een zijbalk naast de inhoud en geen tabbalk meer. Dat is geen
   uitvergrote gsm; het is een andere indeling met dezelfde onderdelen. */

/* De inkeping. index.html zet viewport-fit=cover, dus de bladzijde loopt tot in
   de hoeken van het scherm. Liggend op een iPhone schoven de koptitel en de
   inhoud daardoor half onder de camera-inkeping; nergens in web/ stond
   env(safe-area-inset-left|right). Hier op .raam, want dan erven de kop, de
   inhoud en de zijbalk het in één keer.
   Met opzet padding-left/right en geen padding-inline: env() geeft FYSIEKE
   maten, en met een logische eigenschap zou de linkerinkeping in het Arabisch
   aan de rechterkant terechtkomen. Dit is dus geen inbreuk op regel 1 bovenaan,
   het is de enige manier waarop die maten kloppen. */
.raam{
  min-height:100%;display:flex;flex-direction:column;
  padding-left:env(safe-area-inset-left,0px);
  padding-right:env(safe-area-inset-right,0px);
}

.kolom{flex:1;display:flex;flex-direction:column;min-width:0}

main{
  flex:1;width:100%;max-width:var(--breed);margin-inline:auto;
  padding:14px 16px calc(var(--tab) + 34px + env(safe-area-inset-bottom,0px));
}

/* ── Kop ──────────────────────────────────────────────────── */
.kop{
  position:sticky;top:0;z-index:30;
  display:flex;align-items:center;gap:10px;
  padding:10px 16px 10px;
  padding-top:calc(10px + env(safe-area-inset-top,0px));
  background:var(--glas);
  backdrop-filter:saturate(1.6) blur(14px);
  -webkit-backdrop-filter:saturate(1.6) blur(14px);
  border-bottom:1px solid transparent;
  transition:border-color var(--snel) linear;
}
.kop.gescrold{border-bottom-color:var(--rand)}
.kop .titel{
  font-family:Montserrat,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;font-weight:570;
  font-size:calc(19px * var(--schaal));color:var(--inkt);
  letter-spacing:.004em;min-width:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.kop .rek{flex:1}

.ico{
  width:38px;height:38px;flex:0 0 38px;border-radius:13px;
  display:grid;place-items:center;color:var(--inkt-3);
  transition:background var(--snel),color var(--snel);
}
.ico:hover{background:var(--vlak-2);color:var(--inkt)}
.ico:active{transform:scale(.94)}
.ico.aan{color:var(--merk);background:var(--merk-was)}
.ico .stip{
  position:absolute;margin-block-start:-14px;margin-inline-start:14px;
  width:7px;height:7px;border-radius:99px;background:var(--gloed);
  border:2px solid var(--grond);
}

/* ── Merk ─────────────────────────────────────────────────── */
.merk{
  display:flex;align-items:center;gap:9px;
  font-family:Montserrat,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;font-weight:570;color:var(--inkt);
  font-size:calc(18px * var(--schaal));letter-spacing:-.004em;
}
.merk .vlek{
  width:26px;height:26px;border-radius:10px;flex:0 0 26px;
  background:linear-gradient(150deg,var(--merk) 0%,var(--merk-diep) 100%);
  display:grid;place-items:center;color:var(--merk-op);
  box-shadow:0 2px 6px -1px color-mix(in srgb,var(--merk) 45%,transparent);
}

/* ── Tabbalk, alleen op een gsm ───────────────────────────── */
.tabbalk{
  position:fixed;inset-inline:0;bottom:0;z-index:40;
  /* Deze balk ligt fixed, dus de safe-area-padding op .raam bereikt haar niet:
     ze heeft haar eigen linker- en rechtermarge nodig, anders ligt liggend op
     een iPhone de eerste of de laatste tab onder de inkeping. Weer fysiek, om
     dezelfde reden als daar. */
  padding-block:6px calc(6px + env(safe-area-inset-bottom,0px));
  padding-left:calc(10px + env(safe-area-inset-left,0px));
  padding-right:calc(10px + env(safe-area-inset-right,0px));
  background:var(--glas);
  backdrop-filter:saturate(1.7) blur(18px);
  -webkit-backdrop-filter:saturate(1.7) blur(18px);
  border-top:1px solid var(--rand);
}
/* Het aantal tabs staat NIET meer in deze regel. Er stond repeat(4,1fr)
   terwijl TABS in app/main.ts er sinds StudyTime vijf telt, en dan wikkelde
   de vijfde naar een tweede rij: de balk werd 123 px hoog terwijl main maar
   calc(--tab + 34px) = 100 px onderaan vrijhoudt. Gevolg, gemeten op
   10-09-2026 op 390 px: de laatste knop of zin van elk scherm zat achter de
   balk. Met grid-auto-flow:column blijft elke tab op één rij, hoeveel het er
   ook worden, en klopt --tab weer met wat je ziet. */
/* minmax(0,1fr) en niet 1fr, en dat is het halve verhaal van de fix hierboven.
   1fr betekent minmax(AUTO,1fr): de ondergrens van elke kolom is de
   min-content-breedte van het grid-item, en dat item is de li. In die li zit
   een span met white-space:nowrap, en de min-content-breedte daarvan is het
   VOLLEDIGE label. Wikkelen deed de balk dus niet meer, maar overlopen wel: de
   vijf kolommen samen bleven op hun labelbreedte staan, de ellipsis op de
   span trad nooit op en de vijfde tab viel half van het scherm. Met een
   ondergrens van 0 mag de kolom krimpen, valt de automatische minimummaat van
   de li weg en kapt de span af zoals bedoeld.
   Gemeten met de echte woff2 op wght 570, som van de vijf labels plus 8 px
   gap: op 320 px (300 vrij) liep het over vanaf 110 procent tekstgrootte in
   het Oekraïens en 113 in het Spaans, en zelfs het Nederlands ging stuk bij
   135; op 360 px (340 vrij) vanaf 124 procent. De schuif in Ik loopt tot 140,
   dus dit was geen randgeval: op 140 procent liep elke taal behalve het Turks
   over, en het Spaans, Frans, Duits en Oekraïens ook op 360 px. */
.tabbalk ul{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:2px;max-width:520px;margin-inline:auto}
.tabbalk button{
  width:100%;height:calc(var(--tab) - 12px);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
  color:var(--inkt-3);font-size:calc(12px * var(--schaal));font-weight:570;
  letter-spacing:.004em;border-radius:var(--r-m);position:relative;
  transition:color var(--snel);
}
.tabbalk button .bel{
  position:absolute;inset:2px;border-radius:16px;background:var(--merk-was);
  opacity:0;transform:scale(.8);transition:opacity var(--snel),transform var(--traag) var(--veer);
}
.tabbalk button svg,.tabbalk button span{position:relative}
/* Deze regel blijft staan, maar ze deed NIET wat er stond. De knop is geen
   grid-item, de li is dat; min-width:0 op de knop verlaagt de
   min-content-breedte van de li dus niet en hield in zijn eentje niets tegen.
   Wat de balk smal houdt is de ondergrens van de kolom in .tabbalk ul. Nuttig is
   ze wel: ze laat de knop zelf onder zijn inhoud krimpen zodra de kolom dat
   doet. */
.tabbalk button{min-width:0}
/* 6 px breder dan de knop: met labels van 12 px (punt 1ao) kwam "Asignaturas"
   op 390 px 2 px te kort in een kolom van 72 en kreeg het een ellips. Het label
   staat gecentreerd, dus het steekt hoogstens 3 px aan elke kant in de gap en de
   lege rand naast het buurlabel; gemeten in de 12 talen op 375 en 390 px raakt
   geen label zijn buur. Op 360 px houdt het Spaans zijn ellips, zoals het dat
   op 11 px ook al had. */
.tabbalk button span:not(.bel){max-width:calc(100% + 6px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tabbalk button[aria-current="page"]{color:var(--merk)}
.tabbalk button[aria-current="page"] .bel{opacity:1;transform:scale(1)}
.tabbalk button:active{transform:scale(.95)}

/* ── Zijbalk, alleen op een scherm ────────────────────────── */
.zijbalk{display:none}

@media (min-width:900px){
  .raam{flex-direction:row;height:100%}
  .tabbalk{display:none}
  main{padding:26px 34px 60px;max-width:none}
  .kolom{overflow:auto;height:100vh;height:100dvh;scrollbar-gutter:stable}
  .kolom{scroll-padding-block:90px 24px}
  .kop{padding:18px 34px 14px;background:transparent;backdrop-filter:none}
  .kop.gescrold{background:var(--glas);backdrop-filter:saturate(1.6) blur(14px)}
  /* Ligt er een fotostrook onder de kop, dan blijft dat matglas staan, ook op
     scrollstand 0. Zonder deze regel staan de titel en de drie iconen op een
     breed scherm rechtstreeks op de foto, en dat is gemeten: in het nachtthema
     zakte het zoekicoon op Vakken naar 2,01 tegenover de 3,0 die WCAG voor een
     icoon vraagt, en op Ik naar 2,45. Op een hand ging het altijd goed, want
     daar blijft het glas wel staan. */
  body[data-plek] .kop{
    background:var(--glas);
    backdrop-filter:saturate(1.6) blur(14px);
    -webkit-backdrop-filter:saturate(1.6) blur(14px);
  }
  .zijbalk{
    display:flex;flex-direction:column;gap:4px;
    width:var(--zij);flex:0 0 var(--zij);
    padding:22px 14px 16px;
    background:var(--grond-diep);
    border-inline-end:1px solid var(--rand);
    height:100vh;height:100dvh;position:sticky;top:0;
  }
  .zijbalk .merk{padding-inline:10px;margin-bottom:20px}
  .zijbalk nav{display:flex;flex-direction:column;gap:2px}
  .zijbalk nav button,
  .zijbalk .onderaan button{
    display:flex;align-items:center;gap:11px;width:100%;
    padding:9px 11px;border-radius:14px;color:var(--inkt-2);
    font-size:calc(14px * var(--schaal));font-weight:525;text-align:start;
    transition:background var(--snel),color var(--snel);
  }
  .zijbalk nav button:hover,
  .zijbalk .onderaan button:hover{background:var(--vlak-2);color:var(--inkt)}
  .zijbalk nav button[aria-current="page"],
  .zijbalk .onderaan button[aria-current="page"]{
    background:var(--merk-was);color:var(--merk);font-weight:600;
  }
  .zijbalk .rek{flex:1}
  .zijbalk .onderaan{display:flex;flex-direction:column;gap:2px;border-top:1px solid var(--rand);padding-top:10px}
  /* Op een breed scherm mag de inhoud twee kolommen worden. */
  .duo{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(300px,.85fr);gap:22px;align-items:start}
}
@media (max-width:899px){ .duo{display:contents} .duo-zij{margin-top:14px} }
@media (min-width:1500px){ main{max-width:1340px;margin-inline:auto} }

/* ═══════════ Bouwstenen ════════════════════════════════════ */

.kaart{
  background:var(--vlak);border:1px solid var(--rand);border-radius:var(--r-l);
  padding:16px;box-shadow:var(--op-1);
}
.kaart + .kaart{margin-top:12px}
.kaart.vlak{box-shadow:none;background:var(--vlak-2);border-color:transparent}
.kaart.strak{padding:0;overflow:hidden}
.kaart .kop-rij{display:flex;align-items:center;gap:10px;margin-bottom:12px}

.blad{margin-block:26px 10px;display:flex;align-items:baseline;gap:10px}
.blad h2{flex:0 0 auto}
.blad .lijn{flex:1;height:1px;background:var(--rand)}
.blad .actie{font-size:calc(13px * var(--schaal));font-weight:570;color:var(--merk)}

.rij{display:flex;align-items:center;gap:10px}
.rij .rek{flex:1;min-width:0}
.stapel{display:flex;flex-direction:column;gap:10px}

.stil{color:var(--inkt-3)}
.klein{font-size:calc(13.5px * var(--schaal));line-height:1.6}
.mini{font-size:calc(12px * var(--schaal));line-height:1.55}
.vet{font-weight:600;color:var(--inkt)}
.cijfer{font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}
.afkap{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}

/* Knoppen. Eén hoogte van 46 px, want een duim raakt niets kleiners betrouwbaar. */
.knop{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:46px;padding:0 18px;border-radius:var(--r-m);
  background:var(--merk);color:var(--merk-op);
  font-size:calc(14.5px * var(--schaal));font-weight:570;letter-spacing:.002em;
  box-shadow:0 1px 2px rgba(0,0,0,.10), var(--op-in);
  transition:transform var(--snel) var(--veer),filter var(--snel),background var(--snel);
  white-space:nowrap;
}
.knop:hover{filter:brightness(1.07)}
.knop:active{transform:scale(.97)}
/* Een knop over de volle breedte kan nergens heen als zijn tekst langer is dan
   hij: zonder breken liep "Ich nutze HiSchool schon auf einem anderen Gerät" op
   een gsm 29 px links en rechts buiten zijn rand, en in het Nederlands raakte
   de tekst die rand. Zo'n knop breekt dus, in het midden, met een eigen
   regelafstand en ruimte boven en onder. Op een regel blijft hij 46 px hoog.
   Een knop die naast andere in een rij staat (.breek) doet hetzelfde als hij
   alleen op zijn regel nog te smal is; zijn rij geeft hem eerst zijn hele tekst. */
.knop:is(.vol,.breek){white-space:normal;text-align:center;text-wrap:balance;line-height:1.35;padding-block:10px}
.knop.vol{width:100%}
.knop.zacht{background:var(--vlak-2);color:var(--inkt);box-shadow:none;border:1px solid transparent}
.knop.zacht:hover{background:var(--vlak-3);filter:none}
.knop.rand{background:transparent;border:1px solid var(--rand-2);color:var(--inkt);box-shadow:none}
.knop.rand:hover{background:var(--vlak-2);filter:none}
.knop.gevaar{background:transparent;border:1px solid color-mix(in srgb,var(--fout) 40%,transparent);color:var(--fout);box-shadow:none}
.knop.gevaar:hover{background:var(--fout-was);filter:none}
.knop.klein{min-height:38px;padding:0 13px;font-size:calc(13px * var(--schaal));border-radius:var(--r-s)}
/* Een lange vaknaam met zijn status liep op een gsm rechts uit beeld: hier mag de
   knop breken (Telt niet mee op Vakken). */
.nietmee .knop{white-space:normal;text-align:start;max-width:100%;padding-block:8px}
.knop.gloed{background:var(--gloed);color:var(--gloed-op)}
/* Een knop die uit staat, is effen en dekkend, nooit doorzichtig.

   Hier stond opacity:.42. Op een gsm plakt de voetknop van de onboarding over de
   vaklijst, en bij nul vakken schemerde die lijst door "Je hebt nog geen vakken."
   heen, net als het varenpatroon. Het label haalde zo ook maar 2,26 in het licht
   en 2,59 in het donker. Nu krijgt een knop die uit staat de derde vulling met
   bijschrift erop: 4,69 in het licht en 4,89 in het donker. Hij is zo duidelijk
   geen merkknop meer en blijft toch leesbaar. Een zachte, omrande of gevaarknop
   verliest zijn vulling en houdt een lichte rand. Deze regels staan na de
   soorten hierboven, anders wint de vulling van .knop.gloed of .knop.zacht. */
.knop:disabled{background:var(--vlak-3);color:var(--inkt-3);box-shadow:none;filter:none;pointer-events:none}
.knop:is(.zacht,.rand,.gevaar):disabled{background:transparent;border-color:var(--rand);color:var(--inkt-3)}

.chip{
  display:inline-flex;align-items:center;gap:6px;
  border-radius:999px;padding:5px 11px;
  font-size:calc(12px * var(--schaal));font-weight:570;
  background:var(--vlak-2);color:var(--inkt-2);border:1px solid transparent;
}
.chip.rand{background:transparent;border-color:var(--rand)}
.chip.merk{background:var(--merk-was);color:var(--merk)}
.chip.gloed{background:var(--gloed-was);color:var(--gloed)}
.chip .punt{width:8px;height:8px;border-radius:99px;background:currentColor;flex:0 0 8px}

/* Keuzeknoppen: een rij pillen waarvan er één aan staat. */
.keuzerij{display:flex;gap:6px;flex-wrap:wrap}
.keuzerij button{
  padding:9px 14px;border-radius:var(--r-s);border:1px solid var(--rand-veld);
  background:var(--vlak);font-size:calc(13.5px * var(--schaal));font-weight:570;
  color:var(--inkt-2);min-height:42px;
  /* Enkel de kleuren. Met all liep ook de breedte mee in een overgang, en dan
     mat verdeelKolommen (app/ui.ts) een tussenstand. */
  transition:background-color var(--snel),border-color var(--snel),color var(--snel),box-shadow var(--snel);
}
.keuzerij button:hover{border-color:var(--inkt-3)}
/* De gekozen knop is vol merkgroen. Hij stond op het merkwasje met een lichte
   rand, en dat verschilde 1,17 van een gewone knop: wie kleuren slecht ziet,
   zag niet welke er aan stond (WCAG 1.4.1 en 1.4.11). Nu 10,6 tegen de kaart. */
.keuzerij button[aria-pressed="true"]{
  background:var(--merk);border-color:var(--merk);color:var(--merk-op);
}
/* Een volle rij zet --kol knoppen naast elkaar (app/ui.ts, verdeelKolommen);
   een kortere laatste rij vult de breedte. Zonder --kol (geen script, of een
   rij die enkel op ongelijke breedtes past) is het flex:1 zoals voorheen. */
.keuzerij.vul button{flex:1 1 max(0px, calc((100% - (var(--kol, 99) - 1) * 6px) / var(--kol, 99)));text-wrap:balance}

/* Schuifregelaar */
.schuif{width:100%;-webkit-appearance:none;appearance:none;background:transparent;height:34px;margin:0}
.schuif::-webkit-slider-runnable-track{height:6px;border-radius:99px;background:var(--vlak-3)}
.schuif::-moz-range-track{height:6px;border-radius:99px;background:var(--vlak-3)}
.schuif::-webkit-slider-thumb{
  -webkit-appearance:none;width:24px;height:24px;border-radius:99px;margin-top:-9px;
  background:var(--vlak);border:2px solid var(--merk);box-shadow:var(--op-2);cursor:grab;
}
.schuif::-moz-range-thumb{
  width:24px;height:24px;border-radius:99px;border:2px solid var(--merk);
  background:var(--vlak);box-shadow:var(--op-2);cursor:grab;
}
.schuif:active::-webkit-slider-thumb{cursor:grabbing;transform:scale(1.1)}

/* Invoervelden */
.veld{display:block}
.veld > span,.veld > label{
  display:block;font-size:calc(12.5px * var(--schaal));font-weight:570;
  color:var(--inkt-2);margin-bottom:6px;
}
.veld input,.veld select,.veld textarea,input.invoer,select.invoer{
  width:100%;min-height:46px;padding:11px 13px;border-radius:var(--r-m);
  border:1px solid var(--rand-veld);background:var(--vlak);color:var(--inkt);
  font-size:calc(15px * var(--schaal));transition:border-color var(--snel),box-shadow var(--snel);
}
.veld textarea{min-height:90px;resize:vertical;line-height:1.6}
/* De focus van een veld is een volle ring in merkkleur en geen waas van 16
   procent: die waas haalde nauwelijks 1,2 tegen de grond, en dan zag je met het
   toetsenbord niet in welk veld je stond (WCAG 2.4.7). Ook met :focus-within:
   de laatste Tab-stop van een datum- of tijdveld ligt op het kalendericoon
   binnen het veld, en dan geldt :focus niet meer op het veld zelf. */
.veld input:focus,.veld select:focus,.veld textarea:focus,input.invoer:focus,textarea.invoer:focus,select.invoer:focus,
.veld input:focus-within,input.invoer:focus-within{
  outline:none;border-color:var(--merk);
  box-shadow:0 0 0 2px var(--merk);
}
/* Het wisknopje in een zoekveld. Dat van Chromium is een blauw kruisje (wit in
   donker) van 10 px, buiten het palet. Hier blijft het knopje van de browser
   zelf, dus een klik of tik wist het veld en de app hoort een input-event, en
   Escape wist zoals voorheen; enkel het beeld is eigen: een kruisje in
   --inkt-3 (tegen --vlak 6,0:1 in licht en 6,2:1 in donker, op het dashboard
   5,4:1 in licht), in een vak van 24 px om op te tikken. Met geforceerde
   kleuren in de kleur van de tekst. */
input[type="search"]::-webkit-search-cancel-button{
  -webkit-appearance:none;appearance:none;
  width:24px;height:24px;margin-inline:6px -6px;cursor:pointer;
  background-color:var(--inkt-3);
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 2l8 8M10 2l-8 8' stroke='%23000' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E") center / 12px 12px no-repeat;
          mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 2l8 8M10 2l-8 8' stroke='%23000' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E") center / 12px 12px no-repeat;
}
input[type="search"]::-webkit-search-cancel-button:hover{background-color:var(--inkt-2)}
@media (forced-colors:active){
  input[type="search"]::-webkit-search-cancel-button{forced-color-adjust:none;background-color:CanvasText}
}
.veld .hulp{display:block;margin-top:6px;font-size:calc(12px * var(--schaal));color:var(--inkt-3)}
.veld + .veld{margin-top:14px}

/* Schakelaar */
.schakel{
  display:flex;align-items:center;gap:12px;width:100%;text-align:start;
  padding:12px 2px;min-height:52px;
}
.schakel .rek{flex:1;min-width:0}
/* Een vaknaam van tweehonderd tekens zonder spatie duwde de hele Blok-pagina
   1295 px breed. Elke andere lijst kapte netjes af; deze niet, want een woord
   zonder breekpunt breekt nergens. */
.schakel .rek > span{overflow-wrap:anywhere;word-break:break-word}
/* Het wipje heette .doos, net als de modale doos, en die staat verderop als
   kale klasse in de opmaak. Elke schakelaar in de app erfde daardoor de
   slagschaduw van een dialoog, overflow-y:auto en de animatie "omhoog": bij
   elke hertekening schoof elk schakelaartje 18 px omhoog en kwam het op uit
   het niets. Vandaar een eigen naam. */
.schakel .wip{
  width:46px;height:28px;flex:0 0 46px;border-radius:99px;background:var(--vlak-3);
  /* Het spoor van een schakelaar die uit staat, haalde 1,28 tegen de kaart en
     was dus niet als bediening te zien. */
  box-shadow:inset 0 0 0 1.5px var(--rand-veld);
  position:relative;transition:background var(--traag) var(--veer);
}
.schakel .wip i{
  position:absolute;inset-block-start:3px;inset-inline-start:3px;
  width:22px;height:22px;border-radius:99px;background:var(--vlak);
  box-shadow:var(--op-2);transition:transform var(--traag) var(--veer);
}
.schakel[aria-pressed="true"] .wip{background:var(--merk);box-shadow:none}
.schakel[aria-pressed="true"] .wip i{transform:translateX(18px)}
:root[dir="rtl"] .schakel[aria-pressed="true"] .wip i,
[dir="rtl"] .schakel[aria-pressed="true"] .wip i{transform:translateX(-18px)}

/* Lijstrij die naar iets doorklikt */
.lijst{display:flex;flex-direction:column}
.lijst > button,.lijst > a{
  display:flex;align-items:center;gap:12px;width:100%;text-align:start;
  padding:13px 16px;min-height:56px;color:inherit;text-decoration:none;
  border-bottom:1px solid var(--rand);transition:background var(--snel);
}
.lijst > button:last-child,.lijst > a:last-child{border-bottom:0}
.lijst > button:hover,.lijst > a:hover{background:var(--vlak-2)}
/* De focusring van een rij viel buiten de kaart, en .kaart.strak knipt alles
   wat uitsteekt af: boven, links en rechts was er niets van te zien. Binnen de
   rij getekend blijft hij heel. */
.lijst > button:focus-visible,.lijst > a:focus-visible{outline-offset:-3px}
.dagstrook button:focus-visible{outline-offset:-3px}
/* De gekozen dag staat zelf in --merk, en een ring in --merk erbinnen haalde
   daar 1,0 tegen 1: met het toetsenbord zag je niet dat de focus erop stond.
   --merk-op op --merk haalt 10,6 (WCAG 1.4.11 en 2.4.7). */
.dagstrook button[aria-pressed="true"]:focus-visible{outline-color:var(--merk-op)}
.uitslag button:focus-visible{outline-offset:-3px}
.lijst .rek{flex:1;min-width:0}
.lijst .pijl{color:var(--inkt-3);flex:0 0 auto}
.lijst .waarde{color:var(--inkt-3);font-size:calc(13.5px * var(--schaal));white-space:nowrap}
/* Een rij met een waarde, zoals Je school met de naam van de school. Passen
   titel en waarde samen, dan staan ze op een regel met de waarde rechts. Past
   het niet, dan zakt de waarde onder de titel, en pas als ze ook daar te lang
   is, krijgt ze een beletselteken. Eerst stond de waarde naast de titel en had
   ze voorrang: op 320 px bij een tekstgrootte van 140 procent nam
   "Voorbeelduniversiteit" de rij, brak "Je school" over twee regels en schoof
   de schoolnaam over het woord school (punt 1k, 11-10-2026). */
.kopwaarde{display:flex;flex-wrap:wrap;align-items:baseline;column-gap:12px}
.kopwaarde > .vet{flex:1 0 auto;max-width:100%}
.kopwaarde > .waarde{flex:1 1 auto;text-align:end}

/* Meter */
.meter{height:7px;border-radius:99px;background:var(--vlak-3);overflow:hidden;position:relative;display:flex}
.meter i{display:block;height:100%;border-radius:99px;background:var(--merk);transition:width var(--traag) var(--veer)}
/* 34 procent haalde tegen de baan maar 1,8 en was op een gsm in de zon niet te
   zien. Op 60 en 72 procent haalt de geplande tijd 3,1 en het tekort 3,5, en
   staat de geplande tijd nog altijd 2,7 los van de tijd die al gedaan is. */
.meter i.gepland,.meterleg i.gepland{background:color-mix(in srgb,var(--merk) 60%,transparent)}
.meter i.tekort,.meterleg i.tekort{background:color-mix(in srgb,var(--fout) 72%,transparent)}
.meter b{
  position:absolute;inset-block:-3px;width:2px;border-radius:99px;
  background:var(--inkt);opacity:.34;
}
/* De legende bij de meters per vak (meterLegende in app/ui.ts). */
.meterleg{
  display:flex;flex-wrap:wrap;gap:4px 14px;margin-block:10px 2px;
  font-size:calc(12px * var(--schaal));color:var(--inkt-3);
}
.vakmeters > .meterleg{margin-block:0}
.meterleg span{display:inline-flex;align-items:center;gap:6px}
.meterleg i{width:16px;height:7px;border-radius:99px;background:var(--merk)}
.meterleg b{width:2px;height:13px;border-radius:99px;background:var(--inkt);opacity:.34}

/* ═══════════ Oordeel: de kaart die alles samenvat ══════════
   Dit is het eerste wat een student ziet. Het verloop is bewust heel zacht:
   het moet leesbaar blijven bij fel zonlicht op een gsm. */

.oordeel{
  border-radius:var(--r-xl);padding:20px;position:relative;overflow:hidden;
  border:1px solid var(--rand);background:var(--vlak);box-shadow:var(--op-2);
}
.oordeel::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(120% 90% at 100% 0%, var(--was) 0%, transparent 62%);
}
.oordeel > *{position:relative}
.oordeel .kop2{
  font-family:Montserrat,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;font-weight:570;color:var(--inkt);
  font-size:calc(21px * var(--schaal));line-height:1.3;letter-spacing:0;
}
.oordeel .zin{color:var(--inkt-2);margin-top:7px;font-size:calc(14.5px * var(--schaal))}
.oordeel .voet{display:flex;align-items:center;gap:10px;margin-top:15px;flex-wrap:wrap}
.oordeel.groen{--was:var(--goed-was)}
.oordeel.groen .vinkje{color:var(--goed)}
.oordeel.oranje{--was:var(--krap-was)}
.oordeel.oranje .vinkje{color:var(--krap)}
.oordeel.rood{--was:var(--fout-was)}
.oordeel.rood .vinkje{color:var(--fout)}
.oordeel.neutraal{--was:var(--vlak-2)}
.oordeel .vinkje{
  width:34px;height:34px;border-radius:13px;display:grid;place-items:center;
  background:var(--was);margin-bottom:12px;
}

/* Ring: de dag als een cirkel. */
.ring{position:relative;display:grid;place-items:center;flex:0 0 auto}
.ring svg{transform:rotate(-90deg);overflow:visible}
:root[dir="rtl"] .ring svg,[dir="rtl"] .ring svg{transform:rotate(-90deg) scaleY(-1)}
.ring circle{fill:none;stroke-linecap:round}
.ring .baan{stroke:var(--vlak-3)}
.ring .voor{stroke:var(--merk);transition:stroke-dashoffset var(--traag) var(--veer)}
.ring .binnen{position:absolute;text-align:center;line-height:1.2}
.ring .binnen b{display:block;font-size:calc(17px * var(--schaal));color:var(--inkt);font-weight:600}
.ring .binnen span{display:block;font-size:calc(12px * var(--schaal));color:var(--inkt-3);font-weight:570}

/* ═══════════ Vandaag ═══════════════════════════════════════ */

/* De dagstrook. Zeven dagen, horizontaal, met een puntje per drukte. */
.dagstrook{
  display:flex;gap:7px;overflow-x:auto;scrollbar-width:none;
  margin-inline:-16px;padding:2px 16px 4px;scroll-snap-type:x proximity;
}
@media (min-width:900px){
  /* Daar past de hele strook, dus geen halve knop meer aan de rand. */
  .dagstrook{margin-inline:0;padding-inline:0;justify-content:flex-start}
  .dagstrook button{flex:1 1 0;min-width:44px}
}
.dagstrook::-webkit-scrollbar{display:none}
.dagstrook button{
  flex:0 0 auto;width:52px;padding:9px 0 8px;border-radius:var(--r-m);
  border:1px solid var(--rand);background:var(--vlak);text-align:center;
  scroll-snap-align:center;transition:all var(--snel) var(--veer);position:relative;
}
.dagstrook button:hover{border-color:var(--rand-2)}
.dagstrook button .dg{
  display:block;font-size:calc(12px * var(--schaal));color:var(--inkt-3);
  font-weight:630;text-transform:uppercase;letter-spacing:.06em;
}
.dagstrook button .nr{
  display:block;font-size:calc(17px * var(--schaal));font-weight:600;color:var(--inkt);
  margin-top:1px;font-variant-numeric:tabular-nums;
}
.dagstrook button .stippen{display:flex;gap:2px;justify-content:center;margin-top:5px;height:4px}
.dagstrook button .stippen i{width:4px;height:4px;border-radius:99px;background:var(--inkt-3);opacity:.5}
.dagstrook button[aria-pressed="true"]{
  background:var(--merk);border-color:var(--merk);
  box-shadow:0 4px 12px -3px color-mix(in srgb,var(--merk) 50%,transparent);
}
.dagstrook button[aria-pressed="true"] .dg{color:color-mix(in srgb,var(--merk-op) 76%,transparent)}
.dagstrook button[aria-pressed="true"] .nr{color:var(--merk-op)}
.dagstrook button[aria-pressed="true"] .stippen i{background:var(--merk-op);opacity:.75}
.dagstrook button.vandaag:not([aria-pressed="true"]) .nr{color:var(--merk)}
/* Een rustdag krijgt een zachte vulling, MAAR nooit de dag die je aangetikt
   hebt: die staat al in de merkkleur met lichte tekst erop, en de zachte
   vulling eroverheen maakte donkere tekst op donkergrijs. Gemeten op 1,07
   contrast, dus onleesbaar. */
.dagstrook button.rust:not([aria-pressed="true"]){background:var(--vlak-2);border-color:transparent}
.dagstrook button.examen::after{
  content:"";position:absolute;inset-block-start:6px;inset-inline-end:6px;
  width:6px;height:6px;border-radius:99px;background:var(--fout);
}

/* De tijdlijn van de dag. */
.tijdlijn{margin-top:6px;position:relative}
.tl{display:flex;gap:12px;align-items:stretch;padding-bottom:10px;position:relative}
.tl .uur{
  width:52px;flex:0 0 52px;text-align:end;padding-top:13px;
  color:var(--inkt-3);font-size:calc(12px * var(--schaal));font-weight:570;
  font-variant-numeric:tabular-nums;
}
.tl .as{width:2px;flex:0 0 2px;background:var(--rand);border-radius:99px;margin-block:5px}
.tl .inhoud{flex:1;min-width:0}
.tl.nu .as{background:var(--gloed)}

/* Een blok. De kleur van het vak zit in --vak. */
.blokje{
  --tint:var(--vak,var(--merk));
  border:1px solid var(--rand);border-radius:var(--r);padding:13px 14px;
  background:var(--vlak);position:relative;overflow:hidden;
  box-shadow:var(--op-1);touch-action:pan-y;
  transition:transform var(--snel) var(--veer),box-shadow var(--snel),opacity var(--snel);
}
:root[data-thema="donker"] .blokje{--tint:color-mix(in srgb,var(--vak,var(--merk)) 66%,#fff)}
@media (prefers-color-scheme:dark){
  :root:not([data-thema="licht"]) .blokje{--tint:color-mix(in srgb,var(--vak,var(--merk)) 66%,#fff)}
}
.blokje::before{
  content:"";position:absolute;inset-block:0;inset-inline-start:0;width:4px;
  background:var(--tint);
}
/* Hier gold dezelfde valstrik als bij het masker van .whykaart::before:
   een linear-gradient kent GEEN inline-start of inline-end, alleen to right, to
   left of een hoek. Er stond "to inline-end", en daarmee was de hele waarde
   ongeldig en tekende dit kleurwasje nergens, in geen enkele taal. Dus de
   gewone regel voor links naar rechts, en dezelfde gespiegeld voor het
   Arabisch. */
.blokje::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(to right, color-mix(in srgb,var(--tint) 8%,transparent), transparent 45%);
}
[dir="rtl"] .blokje::after{
  background:linear-gradient(to left, color-mix(in srgb,var(--tint) 8%,transparent), transparent 45%);
}
.blokje > *{position:relative;z-index:1}
/* Een Nederlandse vaknaam is een woord: "Ontwikkelingspsychologie" liep op
   een gsm 12 px uit de rij tegen de duur aan (punt 1ay). Afbreken met een
   koppelteken waar de taal het kent, anders op de rand. */
.blokje .tt{font-weight:600;color:var(--inkt);font-size:calc(15px * var(--schaal));line-height:1.38;overflow-wrap:break-word;-webkit-hyphens:auto;hyphens:auto}
.blokje .on{color:var(--inkt-3);font-size:calc(12.5px * var(--schaal));margin-top:2px;overflow-wrap:anywhere}
.blokje .tb{color:var(--inkt-2);margin-top:4px;line-height:1.4;text-wrap:pretty}
.blokje .du{
  color:var(--inkt-2);font-size:calc(12.5px * var(--schaal));font-weight:600;
  white-space:nowrap;font-variant-numeric:tabular-nums;
}
.blokje .acties{display:flex;gap:7px;margin-top:11px;flex-wrap:wrap}
.blokje .acties button{
  border:1px solid var(--rand);border-radius:var(--r-s);padding:0 12px;min-height:38px;
  font-size:calc(12.5px * var(--schaal));font-weight:570;background:var(--vlak);
  color:var(--inkt-2);transition:all var(--snel);
}
.blokje .acties button:hover{background:var(--vlak-2);color:var(--inkt)}
.blokje .acties button.prim{
  background:var(--tint);border-color:transparent;color:var(--merk-op);
}
.blokje .acties button.rek{flex:1;min-width:96px}
.blokje .acties button.enkelicoon{padding:0;width:38px;flex:0 0 38px;display:grid;place-items:center}
:root[data-thema="donker"] .blokje .acties button.prim{color:var(--grond)}
@media (prefers-color-scheme:dark){
  :root:not([data-thema="licht"]) .blokje .acties button.prim{color:var(--grond)}
}
.blokje.les{--tint:var(--inkt-3);background:var(--vlak-2);box-shadow:none}
.blokje.examen{--tint:var(--fout)}
.blokje.examen .tt{color:var(--fout)}
/* Afgevinkt. Alina schreef: "als je het afvinkt wordt het balkje een lichtere
   kleur van de desbetreffende kleur van het vak". Dat is beter dan doorzichtig
   maken: een blok dat vervaagt leest als iets dat wegvalt, en een blok dat in
   zijn eigen kleur oplicht leest als iets dat af is. De doorstreping blijft,
   want kleur alleen is geen boodschap voor wie tinten slecht onderscheidt. */
.blokje.klaar{
  background:color-mix(in srgb, var(--tint) 11%, var(--vlak));
  border-color:color-mix(in srgb, var(--tint) 28%, var(--rand));
}
.blokje.klaar::before{background:color-mix(in srgb, var(--tint) 45%, var(--vlak))}
.blokje.klaar::after{background:none}
.blokje.klaar .tt{
  text-decoration:line-through;text-decoration-thickness:1.5px;
  color:var(--inkt-2);
}
.blokje.klaar .on, .blokje.klaar .du{color:var(--inkt-3)}
/* De ring om het blok waar je nu op werkt draagt de lichte trap van de
   terracotta: op een kaart haalt die 3,9 en dat is ruim boven de 3,0 die een
   vorm nodig heeft, terwijl de volle terracotta eromheen te hard schreeuwde. */
.blokje.nubezig{
  box-shadow:0 0 0 2px var(--gloed-licht), var(--op-2);
}
.blokje .nu-merk{
  position:absolute;inset-block-start:0;inset-inline-end:0;
  background:var(--gloed);color:var(--gloed-op);font-size:calc(12px * var(--schaal));
  font-weight:630;padding:3px 9px;border-end-start-radius:14px;letter-spacing:.05em;
  text-transform:uppercase;
}

/* De veegwijzers achter een blok. */
.veeglaag{
  position:absolute;inset:0;display:flex;align-items:center;justify-content:space-between;
  padding-inline:16px;font-size:calc(12px * var(--schaal));font-weight:630;
  pointer-events:none;opacity:0;
}
.veeglaag .naarrechts{color:var(--goed)}
.veeglaag .naarlinks{color:var(--krap)}

/* Lege staat, en die mag mooi zijn. */
.leeg{
  text-align:center;padding:40px 20px;display:flex;flex-direction:column;
  align-items:center;gap:12px;
}
.leeg .tekening{
  width:76px;height:76px;border-radius:var(--r-l);display:grid;place-items:center;
  background:linear-gradient(160deg,var(--merk-was),var(--vlak-2));
  color:var(--merk);box-shadow:var(--op-1);
}
.leeg h2{font-family:Montserrat,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;font-size:calc(18px * var(--schaal))}
.leeg p{color:var(--inkt-3);font-size:calc(14px * var(--schaal));max-width:36ch}

/* ═══════════ Timer ═════════════════════════════════════════ */

/* z-index 95, en dat cijfer is geen smaak. Een blad (.laag) staat op 100. Tikte
   je tijdens een blok op "Waarom ook alweer" of op de pomodoroknop, dan opende
   dat blad ONDER de timer en zag je niets; wie dan Escape drukte, annuleerde
   zijn sessie, want de toetsluisteraar van de timer staat eerder geregistreerd
   en riep sluit(false). Veertig minuten weg zonder melding. 95 houdt de timer
   wel boven de kop (30), de tabbalk (40) en de zijbalk, en onder de bladen
   (100) en de meldingen (130). De tweede helft van die fix zit in
   app/vandaag.ts en app/ui.ts. */
.timerlaag{
  position:fixed;inset:0;z-index:95;background:var(--grond);
  /* safe center en schuiven: bij 200 procent zoom op een laptop is de laag maar
     400 px hoog, en dan vielen Annuleren en de regelknoppen onder de rand,
     zonder dat er iets te schuiven viel (WCAG 1.4.4, 1.4.10 en 2.4.11). Met
     gewoon center ging bij te weinig plaats ook de bovenkant weg. */
  display:flex;flex-direction:column;align-items:center;justify-content:safe center;
  overflow-y:auto;overscroll-behavior:contain;
  gap:22px;padding:28px;text-align:center;
  animation:opkomen var(--traag) var(--veer);
}
.timerlaag .klok{
  font-family:Montserrat,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;font-size:clamp(46px,15vw,74px);
  font-weight:570;color:var(--inkt);letter-spacing:-.012em;
  font-variant-numeric:tabular-nums;line-height:1;
}
.timerlaag .vaknaam{font-size:calc(16px * var(--schaal));font-weight:600;color:var(--inkt)}
.timerlaag .watje{color:var(--inkt-3);font-size:calc(13.5px * var(--schaal))}
.timerlaag .terugblik{color:var(--inkt-2);max-width:34ch;text-align:center;line-height:1.45;text-wrap:balance}
/* Het hoofdstuk van het blok (punt 1ay), onder de vaknaam. Een titel uit een
   inhoudstafel kan lang zijn en heeft geen spaties nodig om te breken. */
.timerlaag .hoofdstuk{color:var(--inkt-2);max-width:34ch;margin:3px auto 0;line-height:1.4;overflow-wrap:anywhere;text-wrap:balance}
.timerlaag .knoppen{display:flex;gap:10px;flex-wrap:wrap;justify-content:center}

/* Het bos ligt ONDER de klok en vult de hele laag. Het canvas is decoratie en
   draagt aria-hidden, dus een schermlezer loopt er gewoon overheen. De inhoud
   krijgt een eigen laagje met een zachte doek eronder, want witte cijfers op
   een bos zijn mooi tot er een boom achter staat. */
.timerinhoud{
  position:relative;z-index:1;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:22px;text-align:center;max-width:420px;width:100%;
  padding:26px 22px;border-radius:var(--r-xl);
  background:color-mix(in srgb, var(--grond) 74%, transparent);
  backdrop-filter:blur(14px) saturate(105%);
  -webkit-backdrop-filter:blur(14px) saturate(105%);
}
/* Geen doek als er geen bos is: dan is de laag zelf al de grond. */
.timerlaag:not(:has(> .bos)) .timerinhoud{
  background:transparent;backdrop-filter:none;-webkit-backdrop-filter:none;
}
/* De kleine regelknoppen. Ze mogen niet met de twee grote knoppen concurreren,
   dus ze staan lager in contrast tot je ze aanraakt. */
.timerlaag .regelrij{display:flex;gap:8px;justify-content:center;flex-wrap:wrap}
.timerlaag .regelrij .ico{
  width:42px;height:42px;border-radius:var(--r-l);
  border:1px solid var(--rand);background:var(--vlak);color:var(--inkt-3);
  display:inline-flex;align-items:center;justify-content:center;
  transition:color var(--snel),border-color var(--snel),background var(--snel);
}
.timerlaag .regelrij .ico:hover{color:var(--inkt-2)}
.timerlaag .regelrij .ico.aan{
  color:var(--merk-op);background:var(--merk);border-color:var(--merk);
}
.timerlaag .faseregel{min-height:1.2em;font-weight:600;color:var(--gloed)}
/* De stand en de bediening van de timer (app/vandaag.ts). Rechtop tellen ze
   niet mee; liggend op een gsm en bij 200 procent zoom op een laptop (375 tot
   400 px hoog) staan ze naast elkaar, anders was de laag 830 px hoog en viel
   de vaknaam boven de rand. De ring krimpt daar van 172 naar 112 px, de
   inkeping van een liggende iPhone krijgt zijn marge. Sinds punt 1ay geldt dat
   tot 700 px hoog: een laptop van 1366 bij 768 toont in Chrome maar 657 px, en
   daar vielen Waarom ook alweer, de regelknoppen en Annuleren onder de rand
   zodra er een hoofdstuk en de zin over het blanco blad bij stonden. Vanaf
   512 px hoog groeit de ring weer mee, tot 172 px. */
.timerstand,.timerbediening{display:contents}
@media (orientation:landscape) and (max-height:700px){
  .timerlaag{
    gap:12px;padding-block:8px;
    padding-left:max(16px,env(safe-area-inset-left,0px));
    padding-right:max(16px,env(safe-area-inset-right,0px));
  }
  .timerinhoud{flex-direction:row;align-items:center;max-width:780px;gap:28px;padding:12px 22px}
  .timerstand,.timerbediening{display:flex;flex-direction:column;align-items:center;gap:8px;flex:1 1 0;min-width:0}
  .timerlaag .klok{font-size:clamp(46px,17vh,74px)}
  .timerlaag .ring{width:clamp(112px,100vh - 400px,172px) !important;height:clamp(112px,100vh - 400px,172px) !important}
  .timerlaag .ring svg{width:100%;height:100%}
}
/* Daarboven, tot 900 px hoog (1280 bij 800, 1024 bij 768, 1536 bij 864 met 125
   procent schaal), past de timer onder elkaar, maar met een hoofdstuk en de zin
   over het blanco blad was hij 877 px hoog en lag Annuleren onder de rand
   (punt 1ay). Dan staan de delen dichter en krimpt de ring met de hoogte; een
   timer zonder die regels krijgt enkel onder 780 px de kleinere ruimte. */
@media (orientation:landscape) and (min-height:701px) and (max-height:900px){
  .timerlaag:has(.hoofdstuk, .terugblik){padding-block:16px}
  .timerinhoud:has(.hoofdstuk, .terugblik){gap:16px;padding-block:20px}
  .timerinhoud:has(.hoofdstuk, .terugblik) .ring{width:clamp(104px,100vh - 625px,172px) !important;height:clamp(104px,100vh - 625px,172px) !important}
  .timerinhoud:has(.hoofdstuk, .terugblik) .ring svg{width:100%;height:100%}
}
@media (orientation:landscape) and (min-height:701px) and (max-height:780px){
  .timerlaag{padding-block:16px}
  .timerinhoud{gap:16px;padding-block:20px}
}
/* Een iPhone SE liggend in Safari is 320 px hoog. Met een hoofdstuk en de zin
   over het blanco blad erbij viel de klok daar onder de rand (punt 1ay). De
   klok is wat telt, dus de ring geeft plaats. */
@media (orientation:landscape) and (max-height:360px){
  .timerlaag .ring{width:80px !important;height:80px !important}
  .timerlaag .ring svg{width:80px;height:80px}
}
/* Rechtop op een gsm (664 px hoog) duwde de regel met het hoofdstuk de knop
   Waarom ook alweer 12 px onder de rand (punt 1ay). Dan staan de delen wat
   dichter op elkaar en krimpt de ring met de hoogte, zodat de regelknoppen in
   beeld blijven en enkel Annuleren onder de rand schuift, zoals zonder
   hoofdstuk. dvh volgt de werkbalk van Safari, vh is de terugval. */
@media (orientation:portrait) and (max-height:720px){
  .timerlaag:has(.hoofdstuk, .terugblik){padding-block:16px}
  .timerinhoud:has(.hoofdstuk, .terugblik){gap:16px}
  .timerinhoud:has(.hoofdstuk, .terugblik) .ring{
    width:clamp(120px,100vh - 520px,172px) !important;height:clamp(120px,100vh - 520px,172px) !important;
    width:clamp(120px,100dvh - 520px,172px) !important;height:clamp(120px,100dvh - 520px,172px) !important;
  }
  .timerinhoud:has(.hoofdstuk, .terugblik) .ring svg{width:100%;height:100%}
}
/* In de pauze verschuift de hele laag van merk naar gloed: je ziet in een
   oogopslag dat dit geen werktijd is. */
.timerlaag.pauzefase .klok{color:var(--gloed)}

/* ═══════════ Week ══════════════════════════════════════════ */

/* Op een gsm brak "5 Oct to 11 Oct" over twee regels en stonden Week en Maand
   onder elkaar, omdat de titel zo smal mocht worden als hij wou. Nu neemt de
   titel wat hij nodig heeft naast de pijlen, en gaan Week en Maand eronder als
   het niet past; daar vullen ze de rij (punt 1f, 11-10-2026). */
.weekkop{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:12px}
.weekkop .rek{flex:1 1 auto}
@media (max-width:560px){
  .weekkop .keuzerij{flex:1 1 auto;flex-wrap:nowrap}
  .weekkop .keuzerij button{flex:1}
}
.weekbalk{overflow-x:auto;margin-inline:-16px;padding-inline:16px;scrollbar-width:thin}
/* overflow:clip en niet hidden: hidden maakt van het rooster een scrollvlak, en
   dan blijft de urenkolom niet staan wanneer de week opzij schuift. */
.weekrooster{
  display:grid;grid-template-columns:46px repeat(7,minmax(78px,1fr));
  border:1px solid var(--rand);border-radius:var(--r-l);overflow:hidden;overflow:clip;
  background:var(--vlak);min-width:620px;
}
.weekrooster .dagkop{
  background:var(--vlak-2);padding:9px 4px;text-align:center;
  font-size:calc(12px * var(--schaal));font-weight:630;color:var(--inkt);
  border-bottom:1px solid var(--rand);
}
.weekrooster .dagkop small{display:block;color:var(--inkt-3);font-weight:570;font-size:calc(12px * var(--schaal))}
.weekrooster .dagkop.istoday{color:var(--merk)}
/* De uren en de hoek erboven blijven staan als de week opzij schuift, zodat je
   op een gsm bij vandaag ook ziet hoe laat een blok begint. Ze plakken op -16px:
   de balk heeft 16px binnenrand tot de schermrand, en op 0 schoof de week in die
   strook links van de uren nog zichtbaar door. */
.weekrooster .hoek{background:var(--vlak-2);border-bottom:1px solid var(--rand);position:sticky;inset-inline-start:-16px;z-index:6}
.weekrooster .uurkol{
  background:var(--vlak-2);font-size:calc(12px * var(--schaal));color:var(--inkt-3);
  text-align:end;padding-inline-end:5px;font-weight:570;position:sticky;inset-inline-start:-16px;z-index:6;
  border-inline-end:1px solid var(--rand);
}
.weekrooster .uurkol span{position:absolute;inset-inline-end:5px;transform:translateY(-50%)}
.dagkolom{position:relative;border-inline-start:1px solid var(--rand)}
.dagkolom .lijn{position:absolute;inset-inline:0;height:1px;background:var(--rand);opacity:.6}
.dagkolom.weekend{background:color-mix(in srgb,var(--vlak-2) 55%,transparent)}
.wblok{
  --tint:var(--vak,var(--merk));
  /* Een vinger mag vanaf een blok gewoon scrollen, ook opzij door de week: slepen
     begint pas na 350 ms stil drukken (maakSleepbaar in app/week.ts), en eens het
     blok opgepakt is, houdt een niet-passieve touchmove de scroll tegen. Met
     touch-action:none zette een duimscroll die op een blok begon dat blok vast op
     een ander uur. manipulation en niet pan-x pan-y: zo blijft knijpen om te zoomen
     werken, ook op een blok. user-select en touch-callout, anders opent lang drukken
     op iOS een tekstselectie of een menu boven het blok. */
  touch-action:manipulation;
  -webkit-user-select:none;user-select:none;-webkit-touch-callout:none;
  position:absolute;inset-inline:3px;border-radius:10px;padding:4px 6px;overflow:hidden;
  /* 12 px en niet 10,5: daaronder leest niemand een vaknaam nog, en dat is
     ook de ondergrens die scripts/meet-viewport.mjs meet. De regelhoogte gaat
     omlaag, zodat naam en duur nog altijd in een blok van 34 px passen. */
  font-size:calc(12px * var(--schaal));font-weight:600;line-height:1.15;
  background:var(--tint);color:var(--merk-op);cursor:grab;
  box-shadow:0 1px 3px rgba(0,0,0,.2);
}
:root[data-thema="donker"] .wblok{--tint:color-mix(in srgb,var(--vak,var(--merk)) 62%,#fff);color:var(--grond)}
@media (prefers-color-scheme:dark){
  :root:not([data-thema="licht"]) .wblok{--tint:color-mix(in srgb,var(--vak,var(--merk)) 62%,#fff);color:var(--grond)}
}
/* Geen opacity op de duurregel: wit (--merk-op, #FFFDF8) op een vakkleur haalt minstens 4,72, maar met
   .85 zakte die regel bij 6 van de 16 vakkleuren onder 4,5, de laagste op 3,95. */
.wblok small{display:block;font-weight:500;font-size:calc(12px * var(--schaal))}
/* Twee blokken naast elkaar in een kolom van 78 px laten elk 23 px tekst, en
   "1 h 15" breekt niet meer (harde spaties): smallere rand en spaties, zodat de
   duur heel in het blok staat in plaats van een cijfer af te knippen. */
.wblok.naast{padding-inline:3px}
.wblok.naast small{word-spacing:-.15em}
/* De duur op twee regels als ze op een niet past (pasDuren in app/week.ts). */
.wblok small.twee{white-space:pre-line}
/* De naam op een regel met een beletselteken, of op --nmr regels als er in het
   blok plaats voor is (pasNamen in app/week.ts zet dan .meer), en wat dan niet
   past eindigt op de laatste regel met een beletselteken. Op een regel zonder
   afbreken: met afbreekpunten stond er "Onder-..." waar "Onderzoe..." past.
   .woord is hier inline zoals in de kiezer: als vakje kon een gebroken woord
   twee regels hoog worden binnen een regel, dan knipte de line-clamp het half
   af, en op een regel tekent een beletselteken niet in een vakje. Het vakje
   .staart houdt de laatste drie letters samen. Niet --r: dat is de afronding
   van 22px op :root. */
.wblok .nm{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wblok .nm.meer{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:var(--nmr);line-clamp:var(--nmr);white-space:normal;text-overflow:clip;overflow-wrap:anywhere;-webkit-hyphens:auto;hyphens:auto}
.wblok .nm .woord{display:inline}
.wblok.les{background:var(--inkt-3);cursor:default}
/* Een examen sleep je niet, dus niet de grijphand die het van .wblok erft. */
.wblok.examen{background:var(--fout);color:var(--merk-op);cursor:default}
/* Hetzelfde in het weekrooster: lichter in de eigen kleur, niet doorzichtig.
   De tekst gaat mee van wit naar inkt, want op een lichte vulling verdwijnt wit. */
.wblok.klaar{
  background:color-mix(in srgb, var(--tint) 34%, var(--vlak));
  color:var(--inkt);
}
:root[data-thema="donker"] .wblok.klaar{color:var(--inkt)}
@media (prefers-color-scheme:dark){
  :root:not([data-thema="licht"]) .wblok.klaar{color:var(--inkt)}
}
.wblok.sleept{opacity:.4;cursor:grabbing}
.wblok.vast::after{
  content:"";position:absolute;inset-block-start:3px;inset-inline-end:3px;
  width:5px;height:5px;border-radius:99px;background:currentColor;opacity:.8;
}
.nulijn{position:absolute;inset-inline:0;height:2px;background:var(--gloed);z-index:5;pointer-events:none}
.nulijn::before{
  content:"";position:absolute;inset-inline-start:-4px;top:-3px;
  width:8px;height:8px;border-radius:99px;background:var(--gloed);
}

/* Voortgang per vak, onder het rooster. */
.vakmeters{display:grid;gap:13px;margin-top:16px}
.vakmeter{display:grid;grid-template-columns:1fr auto;gap:5px 10px;align-items:baseline}
/* De volle naam, op zoveel regels als nodig (punt 1bg): in een flexdoos tekende
   text-overflow geen beletselteken, overflow knipte de naam gewoon af. */
.vakmeter .nm{
  font-size:calc(13px * var(--schaal));font-weight:570;color:var(--inkt);line-height:1.3;
  min-width:0;position:relative;padding-inline-start:16px;
  overflow-wrap:break-word;-webkit-hyphens:auto;hyphens:auto;
}
.vakmeter .nm i{position:absolute;inset-inline-start:0;top:calc(.65em - 4.5px);width:9px;height:9px;border-radius:99px;background:var(--vak)}
.vakmeter .cf{font-size:calc(12px * var(--schaal));color:var(--inkt-3);font-variant-numeric:tabular-nums;white-space:nowrap}
.vakmeter .meter{grid-column:1/-1}

/* ═══════════ Vakken ════════════════════════════════════════ */

.vaklijst{display:grid;gap:10px;margin-block-start:12px}
@media (min-width:640px){ .vaklijst{grid-template-columns:repeat(auto-fill,minmax(290px,1fr))} }

.vakkaart{
  background:var(--vlak);border:1px solid var(--rand);border-radius:var(--r-l);
  padding:15px;box-shadow:var(--op-1);text-align:start;width:100%;
  transition:transform var(--snel) var(--veer),box-shadow var(--snel),border-color var(--snel);
  position:relative;overflow:hidden;
}
.vakkaart:hover{box-shadow:var(--op-2);border-color:var(--rand-2)}
.vakkaart:active{transform:scale(.99)}
.vakkaart::before{
  content:"";position:absolute;inset-block-start:0;inset-inline:0;height:3px;background:var(--vak);
}
.vakkaart .naam{
  font-weight:600;color:var(--inkt);font-size:calc(15px * var(--schaal));
  line-height:1.38;letter-spacing:0;
}
.vakkaart .meta{color:var(--inkt-3);font-size:calc(12.5px * var(--schaal));margin-top:3px}
.vakkaart .getal{
  font-family:Montserrat,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;font-size:calc(19px * var(--schaal));font-weight:570;
  color:var(--inkt);font-variant-numeric:tabular-nums;line-height:1;
}
.vakkaart .van{color:var(--inkt-3);font-size:calc(12px * var(--schaal))}
.vakkaart .meter{margin-top:12px}
.vakkaart.klaar::before{background:var(--goed)}

/* ── De vakken als vierkante tegels ──────────────────────────
   Alina vroeg om vierkante tegeltjes naast en onder elkaar, elk in de kleur van
   zijn vak, met de naam, de studiepunten, een doorzichtig balkje dat inkleurt en
   daaronder de tekening die meegroeit. De tegel staat op een heel zachte variant
   van de vakkleur (--vak-zacht, uitgerekend in app/groei.ts), zodat de gewone
   inkt erop blijft werken in plaats van dat er per vak een tekstkleur bij moet.
   De balk loopt vol in --vak-diep, een tint donkerder dan het vak zelf. */
.vaktegels{
  display:grid;gap:12px;margin-block-start:12px;
  grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
}
@media (min-width:900px){ .vaktegels{grid-template-columns:repeat(auto-fill,minmax(180px,1fr))} }

.vaktegel{
  /* GEEN aspect-ratio meer. Hier stond .78, en dan is de hoogte van de tegel
     vast terwijl het beeld erin vierkant is en over de volle breedte loopt:
     alles wat erboven staat ging van de hoogte van het beeld af en
     overflow:hidden knipte de rest weg. Gerekend op 390 px: een tegel is 173 px
     breed en dus 222 px hoog, het beeld heeft 143 px nodig, en er bleef 122 px
     over bij een naam van één regel en 103 px bij twee. Dat is 15 tot 28 procent
     van het beeld weg, 36 procent bij tekstgrootte 1,2, en tegels naast elkaar
     waren elk anders afgesneden. Sinds de tegel ook de dagen tot het examen en
     het tekort kan dragen, ging er in het slechtste geval nog eens 37 px af.
     Nu volgt de tegel zijn inhoud en houdt het beeld zijn eigen vierkant
     (zie .tegelgroei hieronder). */
  display:flex;flex-direction:column;gap:6px;
  padding:14px;text-align:start;width:100%;
  background:var(--vak-zacht,var(--vlak-2));
  border:1px solid var(--rand);border-radius:var(--r-l);
  box-shadow:var(--op-1);position:relative;overflow:hidden;
  transition:transform var(--snel) var(--veer),box-shadow var(--snel),border-color var(--snel);
}
/* In het donkere thema mag de tegel NIET op --vak-zacht staan. Die variabele is
   een lichte pasteltint van de vakkleur, en --inkt is in het donker bijna wit:
   gemeten op 09-09-2026 gaf dat op de vaknaam een contrast van ongeveer 2 op 1,
   ver onder AA, en de tekening erin verdronk mee. In het donker draagt de tegel
   dus een diepe tint van diezelfde vakkleur, zodat de kleur blijft kloppen en
   de inkt weer leest. */
:root[data-thema="donker"] .vaktegel{background:color-mix(in srgb,var(--vak,var(--merk)) 22%,var(--vlak))}
@media (prefers-color-scheme:dark){
  :root:not([data-thema="licht"]) .vaktegel{background:color-mix(in srgb,var(--vak,var(--merk)) 22%,var(--vlak))}
}
.vaktegel:hover{box-shadow:var(--op-2);border-color:var(--rand-2)}
.vaktegel:active{transform:scale(.985)}
/* Klaar, dezelfde drempel als in de lijst (voortgang 0,98). Daar was dat al te
   zien aan de streep bovenaan, op de tegel nog niet. De kleur komt uit het
   token, dus ze klopt in allebei de thema's. */
.vaktegel.klaar{border-color:var(--goed)}
.vaktegel .naam{
  font-weight:600;color:var(--inkt);font-size:calc(14.5px * var(--schaal));
  line-height:1.3;
  /* De volle naam, op zoveel regels als nodig. Hier stond een line-clamp van
     twee regels, en dan was op 320 px of bij 200 procent zoom "Wiskunde met
     (bedrijfs)economische toepassingen" niet meer te lezen, ook niet met
     grotere tekst of meer tekstafstand (WCAG 1.4.10 en 1.4.12). De rij blijft
     toch gelijk: een rasterrij is zo hoog als haar hoogste tegel.
     Een woord dat op zich al breder is dan de tegel ("Computernetwerken" op
     14,5 px tegen 143 px op een scherm van 390 px) breekt af, sinds 11-10-2026
     op een lettergreep met een streepje: zie .woord hieronder. */
  overflow-wrap:anywhere;
}
/* Een lang woord in een naam, gemaakt door woorden() in app/ui.ts (punt 1k).
   Het vakje gaat als geheel naar de volgende regel en breekt pas binnenin af
   als het ook op een volle regel niet past. overflow-wrap:anywhere mag hier
   NIET: daarmee breekt Chromium op de laatste letter die past en komt het
   afbreken nooit aan de beurt. break-word is het vangnet voor een taal zonder
   afbreekwoordenboek, en dan breekt het zoals voorheen. Afbreken volgt lang
   op html, en dat zet pasDocumentAan() in app/i18n.ts op de taal van de app.
   Minstens vier letters voor en na het streepje: anders kwam op een lijstkaart
   van 320 px "Ontwikkelingspsycholo-gie", nu is het "Ontwikkelingspsycho-logie".
   Safari kent hyphenate-limit-chars niet, wel de twee -webkit-regels erachter. */
.woord{display:inline-block;max-width:100%;overflow-wrap:break-word;-webkit-hyphens:auto;hyphens:auto;hyphenate-limit-chars:auto 4 4;-webkit-hyphenate-limit-before:4;-webkit-hyphenate-limit-after:4}
.woord .staart{white-space:nowrap}
.vaktegel .meta{color:var(--inkt);font-weight:500;font-size:calc(12px * var(--schaal))}
/* De twee regeltjes die de tegel er op 10-09-2026 bij kreeg, de dagen tot het
   examen en het tekort, dragen hun kleur zelf mee: --inkt-3 en --fout. Die twee
   zijn gekozen voor tekst op een KAART, en de tegel is geen kaart. In het lichte
   thema staat ze op --vak-zacht, en zacht() klimt maar tot een lichtheid van
   0,66 à 0,75: een middentint, geen pastel. Gemeten op 11-09-2026 om 00u07 met
   scripts/meet-viewport.mjs, op 390 en op 1280 hetzelfde: vijf regels onder AA,
   van 3,00 tot 3,70. Nagerekend met de WCAG-formule over alle zestien tinten uit
   KLEUREN was het erger dan die vijf: de dagenregel haalde 2,44 tot 3,56 en het
   tekort 3,01 tot 4,39, dus alle zestien vakken zakten, niet alleen de vier die
   toevallig in beeld stonden. In het donker haalden ze net wel (4,88 en 4,92).

   De regeltjes blijven staan, de kleur gaat mee met de tegel: allebei een
   color-mix met de inkt, net als de vulling van het balkje hieronder. Omdat
   --inkt in het licht bijna zwart is en in het donker bijna wit, dekt één regel
   allebei de thema's. De dagenregel draagt de tint van het vak zelf, op
   veertig procent, hetzelfde deel als dat balkje; het tekort houdt de foutkleur
   op de helft en blijft dus gebrand rood in plaats van neutrale tekst.
   Nu, over dezelfde zestien tinten: dagen 5,41 tot 7,17 in het licht en 6,72 tot
   7,20 in het donker, tekort 4,88 tot 7,12 en 7,61 tot 8,61. */
.vaktegels{
  /* Op het raster en niet op de tegel: --fout dat naar --fout verwijst is een
     kringverwijzing, en dan valt de kleur helemaal weg. */
  --tegel-fout:color-mix(in srgb,var(--fout) 50%,var(--inkt));
}
.vaktegel{
  --inkt-3:color-mix(in srgb,var(--vak,var(--merk)) 40%,var(--inkt));
  --fout:var(--tegel-fout);
}
.vaktegel .tegelbalk{
  display:block;block-size:7px;border-radius:999px;
  background:color-mix(in srgb, var(--vak) 16%, transparent);
  overflow:hidden;margin-block-start:2px;
}
.vaktegel .tegelbalk i{
  display:block;block-size:100%;border-radius:999px;
  background:var(--vak-diep,var(--vak));
  transition:inline-size var(--traag) var(--veer);
}
/* In het donker is --vak-diep onbruikbaar als vulling. De tegel staat daar op
   color-mix(--vak 22%, --vlak) en de baan op color-mix(--vak 16%, transparent),
   terwijl --vak-diep donkerder(kleur, 0.16) is: nog donkerder dan het vak zelf.
   Drie bijna gelijke donkere tinten over elkaar. Gemeten over alle zestien
   tinten uit KLEUREN ligt het contrast tussen de vulling en de baan tussen 1,00
   en 1,42, tegenover de 3,0 die WCAG 1.4.11 voor een grafisch element vraagt.
   Uitgerekend het element dat de voortgang draagt was dus niet te zien. Met een
   veertig-procentmenging naar --inkt haalt het minstens 6,04. Het lichte thema
   blijft ongemoeid, daar zit het balkje al op 3,66 tot 8,08. Nagerekend op
   10-09-2026 met de echte donkerder() en zacht() uit app/groei-basis.ts:
   oud 1,00 tot 1,42, nieuw 6,04 tot 6,27. */
:root[data-thema="donker"] .vaktegel .tegelbalk i{
  background:color-mix(in srgb,var(--vak) 40%,var(--inkt));
}
@media (prefers-color-scheme:dark){
  :root:not([data-thema="licht"]) .vaktegel .tegelbalk i{
    background:color-mix(in srgb,var(--vak) 40%,var(--inkt));
  }
}
/* Het beeld ligt als een afdruk in de tegel: over de volle breedte, met een
   eigen ronding en een schaduwtje eronder. Tot 09-09-2026 stond hier
   place-items:center en zweefde er een klein vierkantje in het midden van de
   tegel, en dat is precies wat een badge van een beeld maakt. */
.vaktegel .tegelgroei{
  /* Het beeld houdt zijn eigen vierkant in plaats van te krimpen tot wat er
     toevallig overblijft: flex:none zodat het niet meegerekt of geperst wordt,
     aspect-ratio:1 omdat de tekening vierkant is, en margin-block-start:auto om
     het naar de onderkant te duwen. Dat laatste zet de beelden van tegels naast
     elkaar op één lijn, ook als de ene tegel een naam van twee regels heeft en
     de andere niet; het raster rekt de tegels binnen een rij toch al even
     hoog. */
  flex:none;aspect-ratio:1;margin-block-start:auto;
  display:block;min-block-size:0;
  border-radius:calc(var(--r-m) + 2px);overflow:hidden;
  box-shadow:0 1px 2px rgba(20,26,20,.16), 0 6px 14px -8px rgba(20,26,20,.4);
}
/* Het beeld vult de tegel als een afdruk, dus over de volle breedte en niet als
   een plaatje dat in het midden zweeft. Tot 09-09-2026 stond hier block-size:100%
   met een vrije breedte, en dan bleef er links en rechts lucht staan rond een
   rond badge-achtig icoontje. */
.vaktegel .tegelgroei .groei{inline-size:100%;block-size:auto;display:block}

/* De kiezer in het blad van een vak: de twaalf op de voortgang van dat vak. */
.groeikiezer{
  display:grid;gap:8px;grid-template-columns:repeat(auto-fill,minmax(62px,1fr));
}
.groeikeuze{
  display:grid;place-items:center;padding:5px;
  background:var(--vlak);border:1px solid var(--rand);border-radius:var(--r-m);
  transition:border-color var(--snel),box-shadow var(--snel),transform var(--snel) var(--veer);
}
.groeikeuze:hover{border-color:var(--rand-2)}
.groeikeuze:active{transform:scale(.96)}
.groeikeuze.aan{border-color:var(--merk);box-shadow:0 0 0 2px var(--merk-was)}

/* ── StudyTime ───────────────────────────────────────────────
   Een scherm dat het hele tabblad vult en dat rustig moet aanvoelen: brede
   vlakken, veel lucht, weinig randen, en de startknop groot genoeg voor een
   duim. */
.st-kop{
  display:flex;align-items:center;gap:16px;flex-wrap:wrap;
  margin-block-end:14px;
}
.st-cijfers{display:flex;gap:18px;flex-wrap:wrap;margin-block-start:10px}
.st-cijfer{display:flex;flex-direction:column;gap:1px}
.st-cijfer .getal{
  font-size:calc(17px * var(--schaal));font-weight:570;color:var(--inkt);
  font-variant-numeric:tabular-nums;line-height:1.1;
}
.st-start{display:flex;flex-direction:column;gap:8px}
.st-chips{display:flex;flex-wrap:wrap;gap:7px}
.st-chip{
  padding:7px 13px;border-radius:999px;
  border:1px solid var(--rand);background:var(--vlak);
  color:var(--inkt-2);font-size:calc(13px * var(--schaal));font-weight:500;
  transition:border-color var(--snel),background var(--snel),color var(--snel);
}
.st-chip:hover{border-color:var(--rand-2)}
.st-chip.aan{
  border-color:var(--vak);color:var(--inkt);
  background:color-mix(in srgb, var(--vak) 12%, var(--vlak));
}
/* De startknop is het enige wat je op dit scherm echt moet kunnen raken, dus
   hij draagt zijn eigen stijl. De klasse .prim bestaat alleen binnen een blokje
   op Vandaag, en zonder deze regels las de knop hier als platte tekst. */
.st-startknop{
  margin-block-start:14px;min-block-size:54px;
  display:flex;align-items:center;justify-content:center;gap:9px;
  background:var(--merk);color:var(--merk-op);border:none;border-radius:var(--r-m);
  font-size:calc(15.5px * var(--schaal));font-weight:600;
  box-shadow:var(--op-2);
  transition:transform var(--snel) var(--veer),box-shadow var(--snel),filter var(--snel);
}
.st-startknop:hover{filter:brightness(1.06);box-shadow:var(--op-3)}
.st-startknop:active{transform:scale(.99)}
.st-plan{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}
.st-plan li{display:flex;align-items:center;gap:9px;font-size:calc(13.5px * var(--schaal))}
.st-plan li>.mini{white-space:nowrap}
.st-stip{
  inline-size:9px;block-size:9px;border-radius:999px;background:var(--vak);flex:none;
}
.st-samen{background:var(--vlak-2)}

/* De tekening van een groei-icoontje ademt heel traag mee. Het is versiering en
   het mag nooit de aandacht van de tekst wegnemen, dus het is een beweging van
   twee procent over acht seconden. Bij minder beweging staat ze helemaal stil. */
.groei{display:block}
/* De ademende schaal is er op 09-09-2026 uitgehaald. Een beeld dat traag in en
   uit zoomt leest als speelgoed, en dat was precies wat er mis was. Het blok en
   de keyframes blijven staan voor wie hem terug wil. */
.vaktegel .groei{animation:none}
@keyframes groeiadem{
  0%,100%{transform:scale(1)}
  50%{transform:scale(1.02)}
}
@media (prefers-reduced-motion:reduce){
  .vaktegel .groei{animation:none}
}
[data-beweging="uit"] .vaktegel .groei{animation:none}

/* De vakkenkiezer: zoeken over alle opleidingen en jaren. */
.kiezer{display:flex;flex-direction:column;gap:12px;min-height:0;flex:1}
.kiezer .zoekdoos{position:relative}
.kiezer .zoekdoos svg{
  position:absolute;inset-block-start:50%;inset-inline-start:13px;
  transform:translateY(-50%);color:var(--inkt-3);pointer-events:none;
}
.kiezer .zoekdoos input{padding-inline-start:42px}
/* Zoek je richting. Staat boven het zoekveld voor de vakken, want dat is de
   volgorde waarin een student denkt: eerst waar ik zit, dan wat ik volg. */
.kiezer .richtingdoos{display:flex;flex-direction:column;gap:8px}
.kiezer .richtingtreffers{
  display:flex;flex-direction:column;
  border:1px solid var(--rand);border-radius:var(--r-m);
  background:var(--vlak);overflow:hidden;max-height:230px;overflow-y:auto;
}
.kiezer .richtingrij{
  display:flex;align-items:center;gap:10px;width:100%;text-align:start;
  padding:11px 13px;min-height:44px;color:var(--inkt);
  font-size:calc(13.5px * var(--schaal));line-height:1.45;
  transition:background var(--snel);
}
.kiezer .richtingrij + .richtingrij{border-top:1px solid var(--rand)}
.kiezer .richtingrij:hover{background:var(--vlak-2)}
.kiezer .richtingrij .mt{color:var(--inkt-3);font-size:calc(12px * var(--schaal));flex:0 0 auto}
.kiezer .richtingchip{
  display:flex;align-items:center;gap:8px;min-height:44px;
  /* Logisch, niet fysiek: de 13 px hoort aan de tekstkant en de 5 px aan de
     kant van het kruisje. Met padding-left:13px stond in het Arabisch de brede
     marge aan de kruisjeskant en plakte de tekst tegen de rand. */
  padding-block:5px;padding-inline:13px 5px;border-radius:var(--r-m);
  background:var(--merk-was);border:1px solid var(--merk-rand);
  color:var(--merk-diep);font-weight:570;font-size:calc(13.5px * var(--schaal));
}
.kiezer .richtingchip .ico{width:34px;height:34px;flex:0 0 34px;color:var(--merk-diep)}
.kiezer .filters{display:flex;gap:7px;overflow-x:auto;scrollbar-width:none;padding-bottom:2px}
/* De rij scrolt opzij en knipt dus alles af wat uitsteekt, ook de focusring. */
.kiezer .filters select:focus-visible{outline-offset:-3px}
.kiezer .filters::-webkit-scrollbar{display:none}
.kiezer .filters select{
  /* De 30 px is de plek voor het pijltje van de keuzelijst, en dat pijltje
     staat in het Arabisch aan de ANDERE kant. Fysiek stond de ruimte altijd
     rechts, dus in het Arabisch overlapte het pijltje de tekst. */
  min-height:38px;padding-block:0;padding-inline:12px 30px;border-radius:var(--r-s);border:1px solid var(--rand);
  background:var(--vlak);font-size:calc(13px * var(--schaal));font-weight:570;
  color:var(--inkt-2);max-width:190px;
}
.kiezer .uitslag{overflow-y:auto;flex:1;min-height:120px;margin-inline:-4px;padding-inline:4px}
.kiezer .groepkop{
  position:sticky;top:0;background:var(--vlak);z-index:2;
  padding:10px 2px 6px;font-size:calc(12px * var(--schaal));font-weight:630;
  color:var(--inkt-3);text-transform:uppercase;letter-spacing:.07em;
  display:flow-root;line-height:1.35;
}
/* De knop zweeft aan het einde van de regel en de naam loopt eronder door over
   de volle breedte (kiezer.ts, punt 1ah). Een woord breekt naast de knop in
   plaats van eronder te springen en een leeg vak naast de knop te laten: .woord
   is hier inline, het vakje .staart houdt de laatste drie letters samen
   (woorden() in app/ui.ts). Past de naam op een regel, dan zet kiezer.ts
   .een op de kop en staat de naam in het midden van de knop, zoals vroeger met
   align-items:center. */
.kiezer .groepkop .knop{text-transform:none;letter-spacing:0;float:inline-end;margin-inline-start:10px}
.kiezer .groepkop .kopnaam{display:block;overflow-wrap:anywhere;-webkit-hyphens:auto;hyphens:auto}
.kiezer .groepkop .kopnaam .woord{display:inline}
.kiezer .groepkop.een .kopnaam{padding-top:calc((38px - 1lh) / 2)}
/* Over meer regels schuift de knop omhoog tot hij even hoog eindigt als de
   tweede regel, zodat de derde al over de volle breedte loopt. De 38 px is de
   hoogte van .knop.klein, 1.35 * 11.5px de regelhoogte van de kop; de pixel
   extra omdat de browser regels op een 64ste pixel afrondt, en een knop die er
   een fractie onder eindigt, hield de derde regel naast zich. */
.kiezer .groepkop:not(.een) .knop{margin-top:calc(2 * 1.35 * 11.5px * var(--schaal) - 39px)}
.kiezer .groepkop .jaar{white-space:nowrap}
/* Een raster: het vinkje en de studiepunten staan naast de naam en de regel
   eronder, en die twee staan samen in het midden, zoals voorheen met flex. De
   studiepunten komen in de knop voor de regel eronder (kiezer.ts, waarom). */
.vakrij{
  display:grid;grid-template-columns:24px minmax(0,1fr) auto;
  grid-template-areas:"vink nm sp" "vink mt sp";align-content:center;align-items:center;
  column-gap:12px;width:100%;text-align:start;
  padding:11px 12px;border-radius:var(--r-m);transition:background var(--snel);
  min-height:58px;
  /* De studiegids telt meer dan duizend vakken. Zonder dit tekent de browser
     ze allemaal, ook de negenhonderd die niemand ziet, en dan duurt het openen
     van de kiezer op een goedkope Android seconden in plaats van een oogwenk.
     De opgegeven hoogte houdt de schuifbalk toch kloppend. Gemeten op 1277
     rijen als iPhone 13 met zesvoudig vertraagde CPU: alles opnieuw tekenen
     kost zo 23 ms tegen 150 ms zonder. De naam voor een schermlezer staat
     daarom in een aria-label (kiezer.ts): die van de tekst rekent Chrome niet
     uit voor een rij die hij niet tekent. */
  content-visibility:auto;
  contain-intrinsic-size:auto 58px;
}
.vakrij:hover{background:var(--vlak-2)}
.vakrij .vink{
  grid-area:vink;
  width:24px;height:24px;border-radius:9px;border:1.5px solid var(--rand-2);
  display:grid;place-items:center;color:transparent;transition:all var(--snel) var(--veer);
}
.vakrij[aria-pressed="true"] .vink{background:var(--merk);border-color:var(--merk);color:var(--merk-op)}
.vakrij .nm{grid-area:nm;display:block;font-weight:570;color:var(--inkt);font-size:calc(14px * var(--schaal));line-height:1.38}
.vakrij .mt{grid-area:mt;display:block;color:var(--inkt-3);font-size:calc(12px * var(--schaal));margin-top:1px;line-height:1.45}
.vakrij .sp{
  grid-area:sp;
  font-size:calc(12px * var(--schaal));font-weight:600;color:var(--inkt-2);
  font-variant-numeric:tabular-nums;white-space:nowrap;
}

/* De teller onderaan de kiezer. */
.kiezervoet{
  border-top:1px solid var(--rand);padding-top:12px;margin-top:2px;
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
}
.kiezervoet .telling{flex:1;min-width:150px}
.kiezervoet .telling b{display:block;color:var(--inkt);font-weight:600;font-size:calc(14px * var(--schaal))}
.kiezervoet .telling span{display:block;color:var(--inkt-3);font-size:calc(12.5px * var(--schaal));text-wrap:pretty}

/* ═══════════ Bladen, lagen en meldingen ════════════════════ */

.laag{
  position:fixed;inset:0;z-index:100;
  background:color-mix(in srgb,var(--sluier) 45%,transparent);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
  display:flex;align-items:flex-end;justify-content:center;
  animation:vervagen var(--snel) linear;
}
@media (min-width:700px){ .laag{align-items:center;padding:24px} }

.doos{
  background:var(--vlak);width:100%;max-width:560px;
  border-start-start-radius:var(--r-xl);border-start-end-radius:var(--r-xl);
  padding:18px 18px calc(18px + env(safe-area-inset-bottom,0px));
  max-height:92dvh;overflow-y:auto;box-shadow:var(--op-3);
  animation:omhoog var(--traag) var(--veer);
  display:flex;flex-direction:column;
}
@media (min-width:700px){
  .doos{border-radius:var(--r-xl);max-height:86dvh;padding-bottom:18px;animation:opkomen var(--traag) var(--veer)}
}
.doos .greep{
  width:38px;height:4px;border-radius:99px;background:var(--rand-2);
  margin:-6px auto 12px;flex:0 0 auto;
}
@media (min-width:700px){ .doos .greep{display:none} }
.doos .doostitel{display:flex;align-items:center;gap:10px;margin-bottom:14px;flex:0 0 auto}
.doos .doostitel h2{flex:1;font-family:Montserrat,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;font-size:calc(18px * var(--schaal))}
.doos .onderbalk{
  display:flex;gap:10px;margin-top:18px;padding-top:14px;
  border-top:1px solid var(--rand);flex:0 0 auto;
}
.doos .onderbalk .knop{flex:1}

.tostip{
  position:fixed;inset-inline:14px;
  bottom:calc(var(--tab) + 18px + env(safe-area-inset-bottom,0px));
  z-index:130;margin-inline:auto;max-width:460px;
  background:var(--inkt);color:var(--grond);
  padding:13px 16px;border-radius:var(--r-m);box-shadow:var(--op-3);
  font-size:calc(13.5px * var(--schaal));font-weight:525;
  display:flex;align-items:center;gap:12px;
  animation:omhoog var(--traag) var(--veer);
  /* De melding zweeft boven de app en zou anders de knop eronder blokkeren,
     precies op het moment dat iemand doorwerkt. Alleen de knop IN de melding
     vangt kliks; de rest laat ze door. */
  pointer-events:none;
}
/* Staat er een blad open, dan schuift de melding naar boven. Onderaan lag ze
   over de knoppen in de voet van het blad, en dan was Klaar in Mijn week niet
   meer te raken. */
body:has(.laag) .tostip{bottom:auto;top:calc(14px + env(safe-area-inset-top,0px))}
/* Een blad dat opengaat terwijl een melding met Ongedaan maken staat, begint
   onder die melding (14 px marge, 55 px melding met knop, 15 px lucht), ook liggend
   op een gsm waar het blad anders op 24 px begon (punt 1aq, zie blad() in
   app/ui.ts). */
.laag.met-tost{padding-top:calc(84px + env(safe-area-inset-top,0px))}
.laag.met-tost .doos{max-height:min(92dvh,calc(100dvh - 84px - env(safe-area-inset-top,0px)))}
@media (min-width:700px){
  .laag.met-tost .doos{max-height:min(86dvh,calc(100dvh - 108px - env(safe-area-inset-top,0px)))}
}
@media (min-width:900px){ .tostip{bottom:24px;inset-inline-start:auto;inset-inline-end:24px} }
.tostip .rek{flex:1}
.tostip button{pointer-events:auto}
/* De melding staat op --inkt, ook in het lichte thema. Dennengroen daarop haalt
   1,1 en de lichte mos uit het donkere thema haalt op de omgekeerde melding
   1,9: in beide thema's onleesbaar. Vandaar één token dat per thema de goede
   kant kiest, 9,3 in licht en 12,5 in donker. Dat maakt de aparte donkerregel
   die hier stond overbodig. */
.tostip button{
  color:var(--merk-op-inkt);font-weight:630;white-space:nowrap;
  font-size:calc(13px * var(--schaal));padding:4px 2px;
}

/* Strook bovenaan, bv offline. */
.strook{
  display:flex;align-items:center;gap:9px;justify-content:center;
  padding:8px 14px;font-size:calc(12.5px * var(--schaal));font-weight:570;
  background:var(--vlak-2);color:var(--inkt-2);
  border-end-start-radius:var(--r-m);border-end-end-radius:var(--r-m);
}
.strook.waarschuw{background:var(--krap-was);color:var(--krap)}

/* De achterstandskaart op Vandaag. Ze staat tussen het oordeel en de dagstrook
   en heeft dus eigen lucht nodig aan beide kanten. .strook kon dat niet doen:
   die is gemaakt om vast te plakken aan de kaart erboven, en botste hier op de
   dagen eronder. */
.achterkaart{
  display:flex;align-items:center;gap:12px;
  margin-block:12px 16px;padding:12px 14px;
  background:var(--krap-was);color:var(--krap);
  border:1px solid color-mix(in srgb, var(--krap) 28%, transparent);
  border-radius:var(--r-l);
  font-size:calc(13px * var(--schaal));
}
.achterkaart .pict{display:inline-flex;flex:0 0 auto;align-items:center}
.achterkaart b{display:block;color:var(--inkt);font-weight:650;line-height:1.35}
.achterkaart .knop{flex:0 0 auto}

/* De startknop op Vandaag. Een gewone kaart met de kleur van het vak aan de
   beginkant, zodat ze bij het blok hoort dat ze start en niet als een melding
   leest. Ze staat tussen het oordeel en de dagstrook, net als de achterstand. */
.startkaart{margin-block:12px 16px;border-inline-start:4px solid var(--vak)}
.startkaart h2{margin:0}
.startkaart .sk-vak{margin-top:4px;color:var(--inkt);font-weight:600}
.startkaart .sk-hs{margin-top:2px;color:var(--inkt-2);overflow-wrap:anywhere}
.startkaart .sk-stap{margin-top:6px;color:var(--inkt-2);line-height:1.45;text-wrap:pretty}
.startkaart .sk-rij{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;margin-top:14px}

/* Na de eerste stap: doorgaan of stoppen, in de plaats van Pauzeren en Klaar. */
.timerlaag .opstapkeuze{display:flex;flex-direction:column;align-items:center;gap:12px}

/* Zoeklaag */
.zoeklaag .doos{max-width:620px;padding:14px}
.zoekrij{
  display:flex;align-items:center;gap:12px;width:100%;text-align:start;
  padding:11px 12px;border-radius:var(--r-m);min-height:52px;
}
.zoekrij:hover,.zoekrij.aan{background:var(--vlak-2)}
.zoekrij .pict{
  width:34px;height:34px;flex:0 0 34px;border-radius:12px;display:grid;place-items:center;
  background:var(--vlak-2);color:var(--inkt-3);
}
.zoekrij.aan .pict{background:var(--merk-was);color:var(--merk)}

/* ═══════════ Onboarding ════════════════════════════════════ */

/* Tijdens de onboarding hangt er geen tabbalk onder het scherm, dus de ruimte
   die main daarvoor vrijhoudt is enkel lege scrollhoogte onder de knop: de
   eerste stap scrolde 130 px zonder dat er iets stond. */
main:has(> .ob){padding-block:0}

.ob{
  min-height:100dvh;display:flex;flex-direction:column;
  max-width:640px;margin-inline:auto;width:100%;
  padding:0 18px calc(18px + env(safe-area-inset-bottom,0px));
}
.ob .obkop{
  display:flex;align-items:center;gap:12px;
  padding-block:calc(14px + env(safe-area-inset-top,0px)) 12px;
  position:sticky;top:0;background:var(--glas);backdrop-filter:blur(12px);z-index:5;
}
/* Op de eerste stap is er geen terug. De knop blijft staan (anders verspringt
   de voortgangsbalk op stap twee), maar onzichtbaar: zo valt hij ook uit de
   Tab-volgorde en uit wat een schermlezer voorleest. */
.ob .obkop .ico:disabled{visibility:hidden}
.ob .voortgang{flex:1;height:4px;border-radius:99px;background:var(--vlak-3);overflow:hidden;box-shadow:inset 0 0 0 1px var(--rand-veld)}
.ob .voortgang i{display:block;height:100%;background:var(--merk);border-radius:99px;transition:width var(--traag) var(--veer)}
.ob .inhoud{flex:1;padding-block:8px 18px}
/* De inhoud schuift alleen in beeld bij een ECHTE stapwissel. Binnen een stap
   wordt er ook hertekend (de teksten hangen aan de taal, de kaarten aan de
   keuze), en dan mag er niets bewegen: een scherm dat bij elke tik opnieuw
   opkomt, leest als een fout. Zie de uitleg bij teken() in app/onboarding.ts. */
.ob .inhoud.instapt{animation:instap var(--traag) var(--veer)}
.ob h1{
  font-size:clamp(25px,6.5vw,32px);margin-bottom:8px;
}
.ob .onder{color:var(--inkt-3);font-size:calc(14.5px * var(--schaal));margin-bottom:20px;max-width:44ch}
.ob .obpict{
  width:46px;height:46px;border-radius:17px;display:grid;place-items:center;
  background:var(--merk-was);color:var(--merk);margin-bottom:14px;
  box-shadow:inset 0 0 0 1px var(--merk-rand);
}
/* Het icoon voor een regel uitleg in de welkomkaart: even breed als een .ico,
   zodat de tekst op dezelfde plek begint, maar zo hoog als een regel .klein.
   Zo staat het midden op de eerste regel, ook als de tekst er twee telt, en
   blijft het bij hover wat het is: een beeld, geen knop. */
.ob .regelico{flex:0 0 38px;height:calc(13.5px * var(--schaal) * 1.6);display:grid;place-items:center;color:var(--merk)}
/* De taalstap draagt weinig: een vraag en twaalf knoppen. Onderaan vastgeplakt
   ziet dat er uit als een scherm dat nog moet inladen, dus die ene stap staat
   in het midden van wat er over is. Groeit de inhoud (grotere letters), dan
   groeit de kolom gewoon mee en centreert er niets meer weg. */
.ob .inhoud[data-stap="taal"]{display:flex;flex-direction:column;justify-content:center;padding-bottom:24px}
/* De kop van deze ene stap krijgt vaste ruimte voor twee regels.

   Gemeten over de twaalf talen op 390 px: "In welke taal wil je werken?" past in
   het Nederlands, Italiaans, Roemeens en Arabisch op een regel en in de acht
   andere niet. De inhoud staat hier verticaal gecentreerd, dus die ene regel
   verschil schoof de hele lijst 15,2 px op, precies de helft. Wie een taal
   aantikte, zag de knop onder zijn vinger wegspringen. Op 1440 px past de kop
   altijd op een regel en schoof er niets, dus dit gold alleen op een gsm. */
.ob .inhoud[data-stap="taal"] h1{min-height:2.4em;display:flex;align-items:center}
.ob .obvoet{
  position:sticky;bottom:0;padding-block:12px;
  background:linear-gradient(to top,var(--grond) 60%,transparent);
  display:flex;gap:10px;
}
.ob .obvoet .knop{flex:1}

/* Op een breed scherm plakt er niets vast. De kolom is daar al hoog genoeg om
   de hele stap te tonen, en een balk over de volle breedte die meeschuift ziet
   er dan uit als een gsm-app die te groot getrokken is. Het scheelt ook een
   echt euvel: een sticky element in een scrollende kolom is met de muis lastig
   te raken, want de pagina schuift onder de aanwijzer weg. */
@media (min-width:900px){
  /* Op een scherm hing de hele stap in de linkerbovenhoek met een halve pagina
     leegte eronder. margin-block:auto zet ze in het midden zolang er ruimte is,
     en laat gewoon scrollen zodra de stap hoger wordt dan het venster: met
     align-items:center zou de bovenkant dan buiten beeld vallen. */
  main:has(> .ob){display:flex}
  main > .ob{margin-block:auto}
  .ob{min-height:0;padding-bottom:40px}
  .ob .obkop{position:static;background:none;backdrop-filter:none}
  .ob .obvoet{position:static;background:none;padding-block:18px 0}
  .ob .obvoet .knop{flex:0 0 auto;min-width:200px}
}

/* HET ONTHAAL. De eerste kaart die iemand van HiSchool ziet. Het merkverloop
   blijft de drager, de foto ligt eronder met multiply zodat het groen niet
   verandert maar wel diepte krijgt.

   De foto staat hier en niet in de sectie Beeld hierboven, en dat is geen
   ordekwestie: deze regel gebruikt de SHORTHAND `background`, en die zet
   background-image terug op enkel het verloop. Stond de foto bovenaan, dan werd
   ze hier stil gewist en werd onthaal.webp wel gedeployd maar nooit opgevraagd.
   Precies dat gebeurde op 09-09-2026 een halve dag lang. */
.hero{
  border-radius:var(--r-xl);padding:26px 22px;margin-bottom:22px;
  background-image:
    linear-gradient(155deg,var(--merk) 0%,var(--merk-diep) 100%),
    var(--beeld-onthaal,url(beeld/onthaal.webp));
  background-size:cover;
  background-position:center;
  background-blend-mode:multiply,normal;
  color:var(--merk-op);position:relative;overflow:hidden;
  box-shadow:0 12px 32px -12px color-mix(in srgb,var(--merk) 60%,transparent);
}
@media (max-width:760px){ .hero{--beeld-onthaal:url(beeld/onthaal-s.webp)} }
body[data-beeld="uit"] .hero,
body[data-beeld="zacht"] .hero{
  background-image:linear-gradient(155deg,var(--merk) 0%,var(--merk-diep) 100%);
}
.hero::after{
  content:"";position:absolute;inset-block-start:-40%;inset-inline-end:-15%;
  width:260px;height:260px;border-radius:50%;
  background:radial-gradient(circle,rgba(255,255,255,.16),transparent 65%);
}
.hero h1{color:inherit;position:relative}
.hero p{color:color-mix(in srgb,var(--merk-op) 82%,transparent);position:relative;margin-top:8px}

/* Grote keuzekaarten, bv modeltraject tegenover eigen pakket. */
.keuzekaart{
  display:flex;align-items:flex-start;gap:14px;width:100%;text-align:start;
  padding:16px;border-radius:var(--r-l);border:1.5px solid var(--rand);
  background:var(--vlak);transition:all var(--snel) var(--veer);
}
.keuzekaart:hover{border-color:var(--rand-2);box-shadow:var(--op-1)}
.keuzekaart[aria-pressed="true"]{border-color:var(--merk);background:var(--merk-was)}
.keuzekaart .pict{
  width:42px;height:42px;flex:0 0 42px;border-radius:15px;display:grid;place-items:center;
  background:var(--vlak-2);color:var(--inkt-2);
}
.keuzekaart[aria-pressed="true"] .pict{background:var(--merk);color:var(--merk-op)}
.keuzekaart b{display:block;color:var(--inkt);font-size:calc(15px * var(--schaal));font-weight:600}
.keuzekaart span{display:block;color:var(--inkt-3);font-size:calc(13px * var(--schaal));margin-top:3px;line-height:1.55}
.keuzekaart + .keuzekaart{margin-top:10px}

/* Taalkiezer, op twee plaatsen: de eerste stap van de onboarding en het blad
   in Ik. Twaalf woorden in vijf schriften worden anders één grijze massa.

   De schijf draagt de tweeletterige code, en dat is geen versiering: wie de app
   per ongeluk in het Oekraïens zet, leest de lijst niet meer, maar NL en EN
   herkent hij wel. Gevuld in de merkkleur betekent gekozen, dus de staat hangt
   niet aan het vinkje alleen. Eronder staat de taal in de taal die nu aanstaat
   (Engels, Turks, Arabisch), want het eigen woord alleen helpt niet wie zoekt
   naar wat hij kent. Geen vlaggen: een vlag is een land en geen taal.

   Twee kolommen moeten op een gsm van 360 px passen en de naam mag daar niet
   in de puntjes eindigen, vandaar de smalle maten: elke pixel gaat naar het
   woord en niet naar de doos eromheen. */
.taallijst{display:grid;grid-template-columns:repeat(auto-fill,minmax(136px,1fr));gap:9px}
/* Op een scherm is er ruimte zat: daar drie brede kolommen in plaats van vier
   smalle, want auto-fill vult anders op met kolommen die net te krap zijn. */
@media (min-width:700px){ .taallijst{grid-template-columns:repeat(3,1fr)} }
.taalknop{
  display:flex;align-items:center;gap:9px;padding:10px;border-radius:var(--r-m);
  border:1px solid var(--rand);background:var(--vlak);text-align:start;min-height:58px;
  transition:border-color var(--snel),background var(--snel),box-shadow var(--snel),transform var(--snel) var(--veer);
}
.taalknop:hover{border-color:var(--rand-2);box-shadow:var(--op-1)}
.taalknop:active{transform:scale(.98)}
.taalknop .code{
  width:30px;height:30px;flex:0 0 30px;border-radius:11px;display:grid;place-items:center;
  background:var(--vlak-2);color:var(--inkt-3);
  font-size:calc(12px * var(--schaal));font-weight:630;letter-spacing:.04em;
  transition:background var(--snel),color var(--snel);
}
.taalknop .namen{min-width:0}
.taalknop b{
  display:block;color:var(--inkt);font-weight:570;font-size:calc(14px * var(--schaal));
  line-height:1.35;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.taalknop .erbij{
  display:block;color:var(--inkt-3);font-size:calc(12px * var(--schaal));
  line-height:1.4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.taalknop[aria-pressed="true"]{border-color:var(--merk);background:var(--merk-was);box-shadow:none}
.taalknop[aria-pressed="true"] .code{background:var(--merk);color:var(--merk-op)}

/* ═══════════ Skelet, terwijl er gerekend wordt ═════════════ */

.skelet{
  border-radius:var(--r-s);background:linear-gradient(
    100deg,var(--vlak-2) 30%,var(--vlak-3) 50%,var(--vlak-2) 70%);
  background-size:220% 100%;animation:glans 1.4s linear infinite;
}
@keyframes glans{ from{background-position:150% 0} to{background-position:-50% 0} }

/* ═══════════ Beweging ══════════════════════════════════════ */

@keyframes opkomen{ from{opacity:0;transform:translateY(8px) scale(.985)} to{opacity:1;transform:none} }
@keyframes omhoog{ from{transform:translateY(18px);opacity:.4} to{transform:none;opacity:1} }
@keyframes vervagen{ from{opacity:0} to{opacity:1} }
@keyframes instap{ from{opacity:0;transform:translateY(10px)} to{opacity:1;transform:none} }
@keyframes tik{ 0%{transform:scale(1)} 45%{transform:scale(1.14)} 100%{transform:scale(1)} }

.wisselt{animation:instap 240ms var(--veer)}
.tikt{animation:tik 320ms var(--veer)}

/* Wie minder beweging wil, krijgt geen halve app maar dezelfde zonder animatie. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important;scroll-behavior:auto !important;
  }
}
:root[data-beweging="uit"] *,
:root[data-beweging="uit"] *::before,
:root[data-beweging="uit"] *::after{
  animation-duration:.001ms !important;animation-iteration-count:1 !important;
  transition-duration:.001ms !important;
}

/* ═══════════ Afdrukken ═════════════════════════════════════
   Een weekplanning op papier boven het bureau is nog altijd het meest
   gebruikte hulpmiddel dat er bestaat. */

@media print{
  .tabbalk,.zijbalk,.kop .ico,.blokje .acties,.dagstrook{display:none !important}
  body{background:#fff;color:#000;font-size:11pt}
  .kaart,.oordeel,.weekrooster{box-shadow:none;border-color:#bbb;break-inside:avoid}
  main{padding:0;max-width:none}
  .weekrooster{min-width:0}
}
